From: Miao-chen Chou <mcchou@chromium.org>
To: Bluetooth Kernel Mailing List <linux-bluetooth@vger.kernel.org>
Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>,
Alain Michaud <alainm@chromium.org>,
Marcel Holtmann <marcel@holtmann.org>,
Howard Chung <howardchung@google.com>,
Miao-chen Chou <mcchou@chromium.org>
Subject: [BlueZ PATCH v2 1/3] error: BR/EDR and LE connection failure reasons
Date: Fri, 25 Jun 2021 22:21:51 -0700 [thread overview]
Message-ID: <20210625222111.BlueZ.v2.1.If79c3f0720cc893be1770c6853fe2fbe626f2caa@changeid> (raw)
In-Reply-To: <20210626052152.2543526-1-mcchou@chromium.org>
The source of Connect() failures can be divided into the following
three.
- bluetoothd's device interface state transition and profile state
transition
- Kernel's L2CAP layer state transition
- Potential HCI error codes returned by the remote device
This also added error-code.txt to describe these error codes.
Reviewed-by: Alain Michaud <alainm@chromium.org>
Reviewed-by: Howard Chung <howardchung@google.com>
---
Changes in v2:
- Add error-code.txt
- Remove BtdError from return string
doc/error-code.txt | 266 +++++++++++++++++++++++++++++++++++++++++++++
src/error.c | 111 +++++++++++++++++++
src/error.h | 52 +++++++++
3 files changed, 429 insertions(+)
create mode 100644 doc/error-code.txt
diff --git a/doc/error-code.txt b/doc/error-code.txt
new file mode 100644
index 000000000..e91324855
--- /dev/null
+++ b/doc/error-code.txt
@@ -0,0 +1,266 @@
+D-Bus Method Return Error Codes
+===============================
+
+The motivation of having detailed error codes 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
+===================================
+ code: 0x0001
+ errno: EALREADY, EISCONN
+
+Either the profile is already connected or ACL connection is in place.
+
+BR/EDR connection page timeout
+==============================
+ code: 0x0002
+ errno: EHOSTDOWN
+
+Failed due to page timeout.
+
+BR/EDR connection profile unavailable
+=====================================
+ code: 0x0003
+ errno: ENOPROTOOPT
+
+Failed to find connectable services or the target service.
+
+BR/EDR connection SDP search
+============================
+ code: 0x0004
+ errno: none
+
+Failed to complete the SDP search.
+
+BR/EDR connection create socket
+===============================
+ code: 0x0005
+ 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
+===================================
+ code: 0x0006
+ errno: EHOSTUNREACH
+
+Failed due to invalid arguments.
+
+BR/EDR connection not powered
+=============================
+ code: 0x0007
+ errno: EHOSTUNREACH
+
+Failed due to adapter not powered.
+
+BR/EDR connection not supported
+===============================
+ code: 0x0008
+ 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
+============================
+ code: 0x0009
+ errno: EBADFD
+
+Failed due to the socket is in bad state.
+
+BR/EDR connection memory allocation
+===================================
+ code: 0x000A
+ errno: EBADFD
+
+Failed to allocate memory in either host stack or controller.
+
+BR/EDR connection busy
+======================
+ code: 0x000B
+ 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
+=============================================
+ code: 0x000C
+ errno: EMLINK
+
+Failed due to reaching the concurrent connection limit to a device.
+
+BR/EDR connection timeout
+=========================
+ code: 0x000D
+ errno: ETIMEDOUT
+
+Failed due to connection timeout
+
+BR/EDR connection refused
+=========================
+ code: 0x000E
+ errno: ECONNREFUSED
+
+Refused by the remote device due to limited resource, security reason or
+unacceptable address type.
+
+BR/EDR connection aborted by remote
+===================================
+ code: 0x000F
+ errno: ECONNRESET
+
+Terminated by the remote device due to limited resource or power off.
+
+BR/EDR connection aborted by local
+==================================
+ code: 0x0010
+ errno: ECONNABORTED
+
+Aborted by the local host.
+
+BR/EDR connection protocol error
+================================
+ code: 0x0011
+ errno: EPROTO
+
+Failed due to LMP protocol error.
+
+BR/EDR connection canceled
+==========================
+ code: 0x0012
+ errno: none
+
+Failed due to cancellation caused by adapter drop, unexpected device drop, or
+incoming disconnection request before connection request is completed.
+
+BR/EDR connection unknown error
+===============================
+ code: 0x0013
+ errno: ENOSYS
+
+Failed due to unknown reason.
+
+LE connection invalid arguments
+===============================
+ code: 0x0101
+ errno: EINVAL
+
+Failed due to invalid arguments.
+
+LE connection not powered
+=========================
+ code: 0x0102
+ errno: EHOSTUNREACH
+
+Failed due to adapter not powered.
+
+LE connection not supported
+===========================
+ code: 0x0103
+ 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
+===============================
+ code: 0x0104
+ errno: EALREADY, EISCONN
+
+Either the BT IO is already connected or LE link connection in place.
+
+LE connection bad socket
+========================
+ code: 0x0105
+ errno: EBADFD
+
+Failed due to the socket is in bad state.
+
+LE connection memory allocation
+===============================
+ code: 0x0106
+ errno: ENOMEM
+
+Failed to allocate memory in either host stack or controller.
+
+LE connection busy
+==================
+ code: 0x0107
+ 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
+=====================
+ code: 0x0108
+ 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
+===========================
+ code: 0x0109
+ errno: EIO
+
+Failed to create or connect to BT IO socket. This can also indicate hardware
+failure in the controller.
+
+LE connection timeout
+=====================
+ code: 0x010A
+ errno: ETIMEDOUT
+
+Failed due to connection timeout
+
+LE connection concurrent connection limit
+=========================================
+ code: 0x010B
+ errno: EMLINK
+
+Failed due to reaching the synchronous connection limit to a device.
+
+LE connection abort by remote
+=============================
+ code: 0x010C
+ errno: ECONNRESET
+
+Aborted by the remote device due to limited resource or power off.
+
+LE connection abort by local
+============================
+ code: 0x010D
+ errno: ECONNABORTED
+
+Aborted by the local host.
+
+LE connection link layer protocol error
+=======================================
+ code: 0x010E
+ errno: EPROTO
+
+Failed due to link layer protocol error.
+
+LE connection GATT browsing
+===========================
+ code: 0x010F
+ errno: none
+
+Failed to complete the GATT browsing.
+
+LE connection unknown error
+===========================
+ code: 0x0110
+ errno: ENOSYS
+
+ Failed due to unknown reason.
diff --git a/src/error.c b/src/error.c
index 89517075e..73602c4bf 100644
--- a/src/error.c
+++ b/src/error.c
@@ -27,6 +27,7 @@
#include <config.h>
#endif
+#include <stdio.h>
#include "gdbus/gdbus.h"
#include "error.h"
@@ -43,6 +44,12 @@ DBusMessage *btd_error_invalid_args_str(DBusMessage *msg, const char *str)
"%s", str);
}
+DBusMessage *btd_error_invalid_args_err(DBusMessage *msg, uint16_t err)
+{
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments",
+ "0x%04X", err);
+}
+
DBusMessage *btd_error_busy(DBusMessage *msg)
{
return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",
@@ -79,12 +86,24 @@ DBusMessage *btd_error_in_progress(DBusMessage *msg)
"In Progress");
}
+DBusMessage *btd_error_in_progress_err(DBusMessage *msg, uint16_t err)
+{
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress", "0x%04X",
+ err);
+}
+
DBusMessage *btd_error_not_available(DBusMessage *msg)
{
return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAvailable",
"Operation currently not available");
}
+DBusMessage *btd_error_not_available_err(DBusMessage *msg, uint16_t err)
+{
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAvailable",
+ "0x%04X", err);
+}
+
DBusMessage *btd_error_does_not_exist(DBusMessage *msg)
{
return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist",
@@ -121,8 +140,100 @@ DBusMessage *btd_error_not_ready(DBusMessage *msg)
"Resource Not Ready");
}
+DBusMessage *btd_error_not_ready_err(DBusMessage *msg, uint16_t err)
+{
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".NotReady", "0x%04X",
+ err);
+}
+
DBusMessage *btd_error_failed(DBusMessage *msg, const char *str)
{
return g_dbus_create_error(msg, ERROR_INTERFACE
".Failed", "%s", str);
}
+
+DBusMessage *btd_error_failed_err(DBusMessage *msg, uint16_t err)
+{
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "0x%04X",
+ err);
+}
+
+uint16_t btd_error_bredr_conn_from_errno(int errno_code)
+{
+ switch (-errno_code) {
+ case EALREADY:
+ case EISCONN: // Fall through
+ return BTD_ERR_BREDR_CONN_ALREADY_CONNECTED;
+ case EHOSTDOWN:
+ return BTD_ERR_BREDR_CONN_PAGE_TIMEOUT;
+ case ENOPROTOOPT:
+ return BTD_ERR_BREDR_CONN_PROFILE_UNAVAILABLE;
+ case EIO:
+ return BTD_ERR_BREDR_CONN_CREATE_SOCKET;
+ case EINVAL:
+ return BTD_ERR_BREDR_CONN_INVALID_ARGUMENTS;
+ case EHOSTUNREACH:
+ return BTD_ERR_BREDR_CONN_ADAPTER_NOT_POWERED;
+ case EOPNOTSUPP:
+ case EPROTONOSUPPORT: // Fall through
+ return BTD_ERR_BREDR_CONN_NOT_SUPPORTED;
+ case EBADFD:
+ return BTD_ERR_BREDR_CONN_BAD_SOCKET;
+ case ENOMEM:
+ return BTD_ERR_BREDR_CONN_MEMORY_ALLOC;
+ case EBUSY:
+ return BTD_ERR_BREDR_CONN_BUSY;
+ case EMLINK:
+ return BTD_ERR_BREDR_CONN_CNCR_CONNECT_LIMIT;
+ case ETIMEDOUT:
+ return BTD_ERR_BREDR_CONN_TIMEOUT;
+ case ECONNREFUSED:
+ return BTD_ERR_BREDR_CONN_REFUSED;
+ case ECONNRESET:
+ return BTD_ERR_BREDR_CONN_ABORT_BY_REMOTE;
+ case ECONNABORTED:
+ return BTD_ERR_BREDR_CONN_ABORT_BY_LOCAL;
+ case EPROTO:
+ return BTD_ERR_BREDR_CONN_PROTO_ERROR;
+ default:
+ return BTD_ERR_BREDR_CONN_UNKNOWN;
+ }
+}
+
+uint16_t btd_error_le_conn_from_errno(int errno_code)
+{
+ switch (-errno_code) {
+ case EINVAL:
+ return BTD_ERR_LE_CONN_INVALID_ARGUMENTS;
+ case EHOSTUNREACH:
+ return BTD_ERR_LE_CONN_ADAPTER_NOT_POWERED;
+ case EOPNOTSUPP:
+ case EPROTONOSUPPORT: // Fall through
+ return BTD_ERR_LE_CONN_NOT_SUPPORTED;
+ case EALREADY:
+ case EISCONN: // Fall through
+ return BTD_ERR_LE_CONN_ALREADY_CONNECTED;
+ case EBADFD:
+ return BTD_ERR_LE_CONN_BAD_SOCKET;
+ case ENOMEM:
+ return BTD_ERR_LE_CONN_MEMORY_ALLOC;
+ case EBUSY:
+ return BTD_ERR_LE_CONN_BUSY;
+ case ECONNREFUSED:
+ return BTD_ERR_LE_CONN_REFUSED;
+ case EIO:
+ return BTD_ERR_LE_CONN_CREATE_SOCKET;
+ case ETIMEDOUT:
+ return BTD_ERR_LE_CONN_TIMEOUT;
+ case EMLINK:
+ return BTD_ERR_LE_CONN_SYNC_CONNECT_LIMIT;
+ case ECONNRESET:
+ return BTD_ERR_LE_CONN_ABORT_BY_REMOTE;
+ case ECONNABORTED:
+ return BTD_ERR_LE_CONN_ABORT_BY_LOCAL;
+ case EPROTO:
+ return BTD_ERR_LE_CONN_PROTO_ERROR;
+ default:
+ return BTD_ERR_LE_CONN_UNKNOWN;
+ }
+}
diff --git a/src/error.h b/src/error.h
index 7c8cad066..74d433aca 100644
--- a/src/error.h
+++ b/src/error.h
@@ -24,22 +24,74 @@
*/
#include <dbus/dbus.h>
+#include <stdint.h>
#define ERROR_INTERFACE "org.bluez.Error"
+/* BR/EDR connection failure reasons
+ * BT_ERR_* should be used as one of the parameters to btd_error_*_err().
+ */
+#define BTD_ERR_BREDR_CONN_ALREADY_CONNECTED 0x0001
+#define BTD_ERR_BREDR_CONN_PAGE_TIMEOUT 0x0002
+#define BTD_ERR_BREDR_CONN_PROFILE_UNAVAILABLE 0x0003
+#define BTD_ERR_BREDR_CONN_SDP_SEARCH 0x0004
+#define BTD_ERR_BREDR_CONN_CREATE_SOCKET 0x0005
+#define BTD_ERR_BREDR_CONN_INVALID_ARGUMENTS 0x0006
+#define BTD_ERR_BREDR_CONN_ADAPTER_NOT_POWERED 0x0007
+#define BTD_ERR_BREDR_CONN_NOT_SUPPORTED 0x0008
+#define BTD_ERR_BREDR_CONN_BAD_SOCKET 0x0009
+#define BTD_ERR_BREDR_CONN_MEMORY_ALLOC 0x000A
+#define BTD_ERR_BREDR_CONN_BUSY 0x000B
+#define BTD_ERR_BREDR_CONN_CNCR_CONNECT_LIMIT 0x000C
+#define BTD_ERR_BREDR_CONN_TIMEOUT 0x000D
+#define BTD_ERR_BREDR_CONN_REFUSED 0x000E
+#define BTD_ERR_BREDR_CONN_ABORT_BY_REMOTE 0x000F
+#define BTD_ERR_BREDR_CONN_ABORT_BY_LOCAL 0x0010
+#define BTD_ERR_BREDR_CONN_PROTO_ERROR 0x0011
+#define BTD_ERR_BREDR_CONN_CANCELED 0x0012
+#define BTD_ERR_BREDR_CONN_UNKNOWN 0x0013
+
+/* LE connection failure reasons
+ * BT_ERR_* should be used as one of the parameters to btd_error_*_err().
+ */
+#define BTD_ERR_LE_CONN_INVALID_ARGUMENTS 0x0101
+#define BTD_ERR_LE_CONN_ADAPTER_NOT_POWERED 0x0102
+#define BTD_ERR_LE_CONN_NOT_SUPPORTED 0x0103
+#define BTD_ERR_LE_CONN_ALREADY_CONNECTED 0x0104
+#define BTD_ERR_LE_CONN_BAD_SOCKET 0x0105
+#define BTD_ERR_LE_CONN_MEMORY_ALLOC 0x0106
+#define BTD_ERR_LE_CONN_BUSY 0x0107
+#define BTD_ERR_LE_CONN_REFUSED 0x0108
+#define BTD_ERR_LE_CONN_CREATE_SOCKET 0x0109
+#define BTD_ERR_LE_CONN_TIMEOUT 0x010A
+#define BTD_ERR_LE_CONN_SYNC_CONNECT_LIMIT 0x010B
+#define BTD_ERR_LE_CONN_ABORT_BY_REMOTE 0x010C
+#define BTD_ERR_LE_CONN_ABORT_BY_LOCAL 0x010D
+#define BTD_ERR_LE_CONN_PROTO_ERROR 0x010E
+#define BTD_ERR_LE_CONN_GATT_BROWSE 0x010F
+#define BTD_ERR_LE_CONN_UNKNOWN 0x0110
+
DBusMessage *btd_error_invalid_args(DBusMessage *msg);
DBusMessage *btd_error_invalid_args_str(DBusMessage *msg, const char *str);
+DBusMessage *btd_error_invalid_args_err(DBusMessage *msg, uint16_t err);
DBusMessage *btd_error_busy(DBusMessage *msg);
DBusMessage *btd_error_already_exists(DBusMessage *msg);
DBusMessage *btd_error_not_supported(DBusMessage *msg);
DBusMessage *btd_error_not_connected(DBusMessage *msg);
DBusMessage *btd_error_already_connected(DBusMessage *msg);
DBusMessage *btd_error_not_available(DBusMessage *msg);
+DBusMessage *btd_error_not_available_err(DBusMessage *msg, uint16_t err);
DBusMessage *btd_error_in_progress(DBusMessage *msg);
+DBusMessage *btd_error_in_progress_err(DBusMessage *msg, uint16_t err);
DBusMessage *btd_error_does_not_exist(DBusMessage *msg);
DBusMessage *btd_error_not_authorized(DBusMessage *msg);
DBusMessage *btd_error_not_permitted(DBusMessage *msg, const char *str);
DBusMessage *btd_error_no_such_adapter(DBusMessage *msg);
DBusMessage *btd_error_agent_not_available(DBusMessage *msg);
DBusMessage *btd_error_not_ready(DBusMessage *msg);
+DBusMessage *btd_error_not_ready_err(DBusMessage *msg, uint16_t err);
DBusMessage *btd_error_failed(DBusMessage *msg, const char *str);
+DBusMessage *btd_error_failed_err(DBusMessage *msg, uint16_t err);
+
+uint16_t btd_error_bredr_conn_from_errno(int errno_code);
+uint16_t btd_error_le_conn_from_errno(int errno_code);
--
2.32.0.93.g670b81a890-goog
next prev parent reply other threads:[~2021-06-26 5:22 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-26 5:21 [BlueZ PATCH v2 0/3] Detailed error code Miao-chen Chou
2021-06-26 5:21 ` Miao-chen Chou [this message]
2021-06-26 5:39 ` [BlueZ PATCH v2 1/3] error: BR/EDR and LE connection failure reasons Marcel Holtmann
2021-07-14 21:08 ` Miao-chen Chou
2021-07-14 22:06 ` Luiz Augusto von Dentz
2021-07-15 23:21 ` Miao-chen Chou
2021-07-16 17:51 ` Luiz Augusto von Dentz
2021-07-19 7:57 ` Marcel Holtmann
2021-07-20 20:57 ` Miao-chen Chou
2021-07-22 20:54 ` Alain Michaud
2021-07-23 7:38 ` Marcel Holtmann
2021-07-23 8:20 ` Szymon Janc
2021-07-23 13:20 ` Alain Michaud
2021-07-24 1:24 ` Miao-chen Chou
2021-06-26 5:52 ` Detailed error code bluez.test.bot
2021-06-26 5:21 ` [BlueZ PATCH v2 2/3] device: Include BtdError code in Connect() return Miao-chen Chou
2021-06-26 5:21 ` [BlueZ PATCH v2 3/3] client: Print error code for connect methods Miao-chen Chou
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210625222111.BlueZ.v2.1.If79c3f0720cc893be1770c6853fe2fbe626f2caa@changeid \
--to=mcchou@chromium.org \
--cc=alainm@chromium.org \
--cc=howardchung@google.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=luiz.von.dentz@intel.com \
--cc=marcel@holtmann.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).