From 16e8f09a7e645df9077860a743851edf24759bdb Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Thu, 13 Jul 2017 09:51:52 +0100
Subject: [PATCH] Add avdtp_set_priority

---
 profiles/audio/a2dp.c  |  8 ++++++++
 profiles/audio/avdtp.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 profiles/audio/avdtp.h | 13 +++++++++++++
 3 files changed, 68 insertions(+)

--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -888,6 +888,10 @@
 
 	a2dp_sep->starting = FALSE;
 
+	avdtp_set_priority(session, CONN_PRIO_AVDTP,
+			   (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) ?
+			   CONN_DIR_SINK : CONN_DIR_SOURCE);
+
 	setup = find_setup_by_session(session);
 	if (!setup)
 		return;
@@ -964,6 +968,10 @@
 
 	a2dp_sep->suspending = FALSE;
 
+	avdtp_set_priority(session, CONN_PRIO_NORMAL,
+			   (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) ?
+			   CONN_DIR_SINK : CONN_DIR_SOURCE);
+
 	setup = find_setup_by_session(session);
 	if (!setup)
 		return;
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -37,6 +37,8 @@
 #include <glib.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"
@@ -3700,3 +3702,48 @@
 
 	return FALSE;
 }
+
+void avdtp_set_priority(struct avdtp *session, conn_prio_t prio, conn_dir_t dir)
+{
+	uint16_t handle;
+	GError *gerr = NULL;
+
+	if (bt_io_get(session->io, &gerr, BT_IO_OPT_HANDLE, &handle, BT_IO_OPT_INVALID)) {
+		struct write_connection_prio_rp {
+			uint16_t handle;
+			char prio;
+			char dir;
+		} rp;
+		struct hci_request rq;
+		struct hci_version ver;
+		int dd;
+		int hdev = 0; // XXX
+		int ret;
+
+		dd = hci_open_dev(hdev);
+		if (dd < 0) {
+		    error("Can't open device hci%d: %s (%d)\n",
+			  hdev, strerror(errno), errno);
+		    exit(1);
+		}
+
+		ret = hci_read_local_version(dd, &ver, 1000);
+		if (ret == 0 && ver.manufacturer == 15) { /* Broadcom */
+		    rp.handle = handle;
+		    rp.prio = prio;
+		    rp.dir = dir;
+
+		    memset(&rq, 0, sizeof(rq));
+		    rq.ogf    = OGF_VENDOR_CMD;
+		    rq.ocf    = 0x11a;
+		    rq.cparam = &rp;
+		    rq.clen   = sizeof(rp);
+
+		    ret = hci_send_req(dd, &rq, 1000);
+		}
+
+		hci_close_dev(dd);
+	} else {
+	    g_error_free(gerr);
+	}
+}
--- a/profiles/audio/avdtp.h
+++ b/profiles/audio/avdtp.h
@@ -28,6 +28,18 @@
 	AVDTP_SESSION_STATE_CONNECTED
 } avdtp_session_state_t;
 
+
+typedef enum {
+	CONN_PRIO_NORMAL = 0,
+	CONN_PRIO_AVDTP = 1,
+} conn_prio_t;
+
+
+typedef enum {
+	CONN_DIR_SOURCE = 0,
+	CONN_DIR_SINK = 1,
+} conn_dir_t;
+
 struct avdtp;
 struct avdtp_server;
 struct avdtp_stream;
@@ -300,3 +312,4 @@
 
 struct avdtp *avdtp_new(GIOChannel *chan, struct btd_device *device,
 							struct queue *lseps);
+void avdtp_set_priority(struct avdtp *session, conn_prio_t prio, conn_dir_t dir);
