Add new Agent API : RequestPairingConsent.

This callback will be called for incoming pairing requests for 2.1
devices only when the remote IO capabilities are NoInputNoOutput
or DisplayOnly and the local IO capability is DisplayYesNo.
Currently, we were silently auto accepting.
diff --git a/doc/agent-api.txt b/doc/agent-api.txt
index d8d35c0..c927a55 100644
--- a/doc/agent-api.txt
+++ b/doc/agent-api.txt
@@ -68,6 +68,17 @@
 			Possible errors: org.bluez.Error.Rejected
 			                 org.bluez.Error.Canceled
 
+		void RequestPairingConsent(object device)
+
+			This method gets called when the service daemon
+			needs to confirm an incoming pairing request.
+
+			To accept it should return an empty reply
+			or an error to reject.
+
+			Possible errors: org.bluez.Error.Rejected
+			                 org.bluez.Error.Canceled
+
 		void Authorize(object device, string uuid)
 
 			This method gets called when the service daemon
diff --git a/src/agent.c b/src/agent.c
index c7fdbd4..3d4a448 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -55,7 +55,8 @@
 	AGENT_REQUEST_CONFIRMATION,
 	AGENT_REQUEST_PINCODE,
 	AGENT_REQUEST_AUTHORIZE,
-	AGENT_REQUEST_CONFIRM_MODE
+	AGENT_REQUEST_CONFIRM_MODE,
+	AGENT_REQUEST_PAIRING_CONSENT,
 } agent_request_type_t;
 
 struct agent {
@@ -695,6 +696,63 @@
 	return err;
 }
 
+static int pairing_consent_request_new(struct agent_request *req,
+						const char *device_path)
+{
+	struct agent *agent = req->agent;
+
+	req->msg = dbus_message_new_method_call(agent->name, agent->path,
+				"org.bluez.Agent", "RequestPairingConsent");
+	if (req->msg == NULL) {
+		error("Couldn't allocate D-Bus message");
+		return -ENOMEM;
+	}
+
+	dbus_message_append_args(req->msg,
+				DBUS_TYPE_OBJECT_PATH, &device_path,
+				DBUS_TYPE_INVALID);
+
+	if (dbus_connection_send_with_reply(connection, req->msg,
+				&req->call, REQUEST_TIMEOUT) == FALSE) {
+		error("D-Bus send failed");
+		return -EIO;
+	}
+
+	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
+
+	return 0;
+}
+
+int agent_request_pairing_consent(struct agent *agent, struct btd_device *device,
+				agent_cb cb, void *user_data,
+				GDestroyNotify destroy)
+{
+	struct agent_request *req;
+	const gchar *dev_path = device_get_path(device);
+	int err;
+
+	if (agent->request)
+		return -EBUSY;
+
+	debug("Calling Agent.RequestPairingConsent: name=%s, path=%s",
+			agent->name, agent->path);
+
+	req = agent_request_new(agent, AGENT_REQUEST_PAIRING_CONSENT, cb,
+				user_data, destroy);
+
+	err = pairing_consent_request_new(req, dev_path);
+	if (err < 0)
+		goto failed;
+
+	agent->request = req;
+
+	return 0;
+
+failed:
+	agent_request_free(req);
+	return err;
+}
+
 static int request_fallback(struct agent_request *req,
 				DBusPendingCallNotifyFunction function)
 {
diff --git a/src/dbus-hci.c b/src/dbus-hci.c
index b83506f..dcd121f 100644
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -287,6 +287,34 @@
 	hci_close_dev(dd);
 }
 
+static void pairing_consent_cb(struct agent *agent, DBusError *err,
+					void *user_data)
+{
+	struct btd_device *device = user_data;
+	struct btd_adapter *adapter = device_get_adapter(device);
+	user_confirm_reply_cp cp;
+	int dd;
+	uint16_t dev_id = adapter_get_dev_id(adapter);
+
+	dd = hci_open_dev(dev_id);
+	if (dd < 0) {
+		error("Unable to open hci%d", dev_id);
+		return;
+	}
+
+	memset(&cp, 0, sizeof(cp));
+	device_get_address(device, &cp.bdaddr);
+
+	if (err)
+		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY,
+					USER_CONFIRM_REPLY_CP_SIZE, &cp);
+	else
+		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_REPLY,
+					USER_CONFIRM_REPLY_CP_SIZE, &cp);
+
+	hci_close_dev(dd);
+}
+
 static int get_auth_requirements(bdaddr_t *local, bdaddr_t *remote,
 							uint8_t *auth)
 {
@@ -366,6 +394,20 @@
 		goto fail;
 	}
 
+	/* If local IO capabilities are DisplayYesNo and remote IO
+	 * capabiltiies are DisplayOnly or NoInputNoOutput;
+	 * call PairingConsent callback for incoming requests. */
+	struct agent *agent = NULL;
+	agent = device_get_agent(device);
+	if (!agent) {
+		agent = adapter_get_agent(adapter);
+		if ((agent_get_io_capability(agent) & 0x01) &&
+		            (remcap == 0x00 || remcap == 0x03))
+			return device_request_authentication(device,
+					AUTH_TYPE_PAIRING_CONSENT, 0,
+					pairing_consent_cb);
+	}
+
 	/* If no side requires MITM protection; auto-accept */
 	if ((loc_auth == 0xff || !(loc_auth & 0x01) || rem_cap == 0x03) &&
 				(!(rem_auth & 0x01) || loc_cap == 0x03)) {
diff --git a/src/device.c b/src/device.c
index fbb99d6..817c3a0 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2294,6 +2294,20 @@
 	device->authr->agent = NULL;
 }
 
+static void pairing_consent_cb(struct agent *agent, DBusError *err, void *data)
+{
+	struct authentication_req *auth = data;
+	struct btd_device *device = auth->device;
+
+	/* No need to reply anything if the authentication already failed */
+	if (!auth->cb)
+		return;
+
+	((agent_cb) auth->cb)(agent, err, device);
+
+	auth->cb = NULL;
+}
+
 int device_request_authentication(struct btd_device *device, auth_type_t type,
 						uint32_t passkey, void *cb)
 {
@@ -2335,6 +2349,10 @@
 	case AUTH_TYPE_AUTO:
 		err = 0;
 		break;
+	case AUTH_TYPE_PAIRING_CONSENT:
+		ret = agent_request_pairing_consent(agent, device,
+							pairing_consent_cb, auth, NULL);
+		break;
 	default:
 		err = -EINVAL;
 	}
@@ -2373,6 +2391,9 @@
 	case AUTH_TYPE_PASSKEY:
 		((agent_passkey_cb) auth->cb)(agent, &err, 0, device);
 		break;
+	case AUTH_TYPE_PAIRING_CONSENT:
+		((agent_cb) auth->cb) (agent, &err, device);
+		break;
 	case AUTH_TYPE_NOTIFY:
 	case AUTH_TYPE_AUTO:
 		/* User Notify/Auto doesn't require any reply */
diff --git a/src/device.h b/src/device.h
index 5f75e61..9288379 100644
--- a/src/device.h
+++ b/src/device.h
@@ -32,6 +32,7 @@
 	AUTH_TYPE_CONFIRM,
 	AUTH_TYPE_NOTIFY,
 	AUTH_TYPE_AUTO,
+	AUTH_TYPE_PAIRING_CONSENT,
 } auth_type_t;
 
 struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter,