diff --git a/lib/include/btdevice.h b/lib/include/btdevice.h
index 83acdd89915ec66a28eaefceb4d9b85e086c3765..260ed867b70a24b6ba7ce49c33b9c25da9a12c64 100644
--- a/lib/include/btdevice.h
+++ b/lib/include/btdevice.h
@@ -20,6 +20,7 @@ class btdevice;
 namespace statemachine
 {
 	struct btdevice_sm;
+	struct disconnected;
 	struct idle;
 	struct pairing_connecting;
 	struct pairing_done;
@@ -108,6 +109,7 @@ public:
 	 * pairing_finished().
 	 */
 	friend struct statemachine::btdevice_sm;
+	friend struct statemachine::disconnected;
 	friend struct statemachine::idle;
 	friend struct statemachine::pairing_connecting;
 	friend struct statemachine::pairing_done;
@@ -322,7 +324,6 @@ private:
 		AUTH_FAILED,
 		LINK_KEY_REQUEST,
 		PIN_REQUEST,
-		DISCONNECT_COMPLETED,
 		IO_CAPABILITY_REQUEST_REPLY_SUCCEEDED,
 		IO_CAPABILITY_REQUEST_REPLY_FAILED,
 		USER_CONFIRMATION_REQUEST_REPLY_SUCCEEDED,
diff --git a/lib/src/btdevice.cpp b/lib/src/btdevice.cpp
index d1fd16039e66ed777189d1c6b9b98badcbedb5b3..8381f4e064a9e3a3b668a564a5000f71c7bfa46a 100644
--- a/lib/src/btdevice.cpp
+++ b/lib/src/btdevice.cpp
@@ -329,7 +329,7 @@ void btdevice::con_compl(bool success, uint16_t handle)
 void btdevice::discon_compl(bool success)
 {
 	if (success)
-		process_state(device_event::DISCONNECT_COMPLETED);
+		sm->process_event(sm::event_disconnected());
 
 	emit_event<&device_observer::device_event>(*this, NG_HCI_EVENT_DISCON_COMPL,
 	                                           success);
@@ -513,18 +513,6 @@ void btdevice::process_state(device_event event)
 		case device_event::PIN_REQUEST:
 			socket->send_pin_code_reply(this, addr, pin);
 			break;
-		case device_event::DISCONNECT_COMPLETED:
-			connected = false;
-			con_handle = INVALID_HANDLE;
-			if (current_state == device_state::PAIRING)
-			{
-				// If we disconnect during pairing, reset the state
-				// machine by overwriting it with a new one.
-				sm = std::make_unique<sm::btdevice_sm>(*this);
-				sm->initiate();
-				pairing_finished(false);
-			}
-			break;
 		case device_event::IO_CAPABILITY_REQUEST_REPLY_SUCCEEDED:
 			syslog(LOG_DEBUG, "%s: io_capability_request_reply succeeded",
 				   addr.str().c_str());
diff --git a/lib/src/btdevice_statemachine.h b/lib/src/btdevice_statemachine.h
index d5dba92d0ddeb9a04aee3538216b10d535853e87..d3fba4a3cc5dafa7dc5d362b451f2791e189156f 100644
--- a/lib/src/btdevice_statemachine.h
+++ b/lib/src/btdevice_statemachine.h
@@ -69,6 +69,7 @@ struct event_secure_simple_pairing_failed :
 struct event_pairing_done : sc::event<event_pairing_done> {};
 struct event_done : sc::event<event_done> {};
 struct event_auth_successful : sc::event<event_auth_successful> {};
+struct event_disconnected : sc::event<event_disconnected> {};
 
 /*
  * State machine definition
@@ -105,6 +106,10 @@ struct btdevice_sm : sc::state_machine<btdevice_sm, normal>
 		device.connected = false;
 	}
 
+	void pairing_cleanup(const event_disconnected &)
+	{
+		device.pairing_finished(false);
+	}
 
 private:
 	btdevice &device;
@@ -117,6 +122,7 @@ private:
 
 struct normal;
 struct pairing;
+struct disconnected;
 
 struct init;
 struct idle;
@@ -134,17 +140,34 @@ struct connecting;
 struct normal : sc::state<normal, btdevice_sm, idle>, state_logger
 {
 	typedef mpl::list<
-		sc::transition<event_start_pairing, pairing>> reactions;
+		sc::transition<event_start_pairing, pairing>,
+		sc::transition<event_disconnected, disconnected>> reactions;
 
 	normal(my_context ctx) : my_base(ctx), state_logger(ctx_device(), "normal")
 	{
 	}
 };
 
+struct disconnected : sc::state<disconnected, btdevice_sm>, state_logger
+{
+	typedef sc::transition<event_done, idle> reactions;
+
+	disconnected(my_context ctx) : my_base(ctx),
+		state_logger(ctx_device(), "disconnected")
+	{
+		ctx_device().connected = false;
+		ctx_device().con_handle = INVALID_HANDLE;
+
+		post_event(event_done());
+	}
+};
+
 struct pairing : sc::state<pairing, btdevice_sm, start_pairing>, state_logger
 {
 	typedef mpl::list<
-		sc::transition<event_pairing_done, normal>> reactions;
+		sc::transition<event_pairing_done, normal>,
+		sc::transition<event_disconnected, disconnected,
+		               btdevice_sm, &btdevice_sm::pairing_cleanup>> reactions;
 
 	pairing(my_context ctx) : my_base(ctx),
 		state_logger(ctx_device(), "pairing")