Implement start_discovery hciops callback
diff --git a/plugins/hciops.c b/plugins/hciops.c
index 965e9de..23e8915 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -56,11 +56,26 @@
 #define DISCOV_INQ 1
 #define DISCOV_SCAN 2
 
+#define TIMEOUT_BR_LE_SCAN 5120 /* TGAP(100)/2 */
+#define TIMEOUT_LE_SCAN 10240 /* TGAP(gen_disc_scan_min) */
+
+#define LENGTH_BR_INQ 0x08
+#define LENGTH_BR_LE_INQ 0x04
+
+static int hciops_start_scanning(int index, int timeout);
+
 static int child_pipe[2] = { -1, -1 };
 
 static guint child_io_id = 0;
 static guint ctl_io_id = 0;
 
+enum adapter_type {
+	BR_EDR,
+	LE_ONLY,
+	BR_EDR_LE,
+	UNKNOWN,
+};
+
 /* Commands sent by kernel on starting an adapter */
 enum {
 	PENDING_BDADDR,
@@ -151,27 +166,74 @@
 	return dev->discov_state;
 }
 
+static inline gboolean is_resolvname_enabled(void)
+{
+	return main_opts.name_resolv ? TRUE : FALSE;
+}
+
 static void set_state(int index, int state)
 {
+	struct btd_adapter *adapter;
 	struct dev_info *dev = &devs[index];
 
 	if (dev->discov_state == state)
 		return;
 
+	adapter = manager_find_adapter_by_id(index);
+	if (!adapter) {
+		error("No matching adapter found");
+		return;
+	}
+
 	dev->discov_state = state;
 
 	DBG("hci%d: new state %d", index, dev->discov_state);
 
 	switch (dev->discov_state) {
 	case DISCOV_HALTED:
+		if (adapter_get_state(adapter) == STATE_SUSPENDED)
+			return;
+
+		if (is_resolvname_enabled() &&
+					adapter_has_discov_sessions(adapter))
+			adapter_set_state(adapter, STATE_RESOLVNAME);
+		else
+			adapter_set_state(adapter, STATE_IDLE);
 		break;
 	case DISCOV_INQ:
-		break;
 	case DISCOV_SCAN:
+		adapter_set_state(adapter, STATE_DISCOV);
 		break;
 	}
 }
 
+static inline gboolean is_le_capable(int index)
+{
+	struct dev_info *dev = &devs[index];
+
+	return (main_opts.le && dev->features[4] & LMP_LE &&
+			dev->extfeatures[0] & LMP_HOST_LE) ? TRUE : FALSE;
+}
+
+static inline gboolean is_bredr_capable(int index)
+{
+	struct dev_info *dev = &devs[index];
+
+	return (dev->features[4] & LMP_NO_BREDR) == 0 ? TRUE : FALSE;
+}
+
+static int get_adapter_type(int index)
+{
+	if (is_le_capable(index) && is_bredr_capable(index))
+		return BR_EDR_LE;
+	else if (is_le_capable(index))
+		return LE_ONLY;
+	else if (is_bredr_capable(index))
+		return BR_EDR;
+
+	return UNKNOWN;
+}
+
 static int ignore_device(struct hci_dev_info *di)
 {
 	return hci_test_bit(HCI_RAW, &di->flags) || di->type >> 4 != HCI_BREDR;
@@ -1831,12 +1893,30 @@
 
 static inline void inquiry_complete_evt(int index, uint8_t status)
 {
+	int adapter_type;
+	struct btd_adapter *adapter;
+
 	if (status) {
 		error("Inquiry Failed with status 0x%02x", status);
 		return;
 	}
 
-	set_state(index, DISCOV_HALTED);
+	adapter = manager_find_adapter_by_id(index);
+	if (!adapter) {
+		error("No matching adapter found");
+		return;
+	}
+
+	adapter_type = get_adapter_type(index);
+
+	if (adapter_type == BR_EDR_LE &&
+					adapter_has_discov_sessions(adapter)) {
+		int err = hciops_start_scanning(index, TIMEOUT_BR_LE_SCAN);
+		if (err < 0)
+			set_state(index, DISCOV_HALTED);
+	} else {
+		set_state(index, DISCOV_HALTED);
+	}
 }
 
 static inline void cc_inquiry_cancel(int index, uint8_t status)
@@ -3159,8 +3239,18 @@
 
 static int hciops_start_discovery(int index)
 {
-	DBG("index %d", index);
-	return -ENOSYS;
+	int adapter_type = get_adapter_type(index);
+
+	switch (adapter_type) {
+	case BR_EDR_LE:
+		return hciops_start_inquiry(index, LENGTH_BR_LE_INQ, FALSE);
+	case BR_EDR:
+		return hciops_start_inquiry(index, LENGTH_BR_INQ, FALSE);
+	case LE_ONLY:
+		return hciops_start_scanning(index, TIMEOUT_LE_SCAN);
+	default:
+		return -EINVAL;
+	}
 }
 
 static int hciops_stop_discovery(int index)