diff --git a/src/btstack_defines.h b/src/btstack_defines.h
index 27d82699d..568183956 100644
--- a/src/btstack_defines.h
+++ b/src/btstack_defines.h
@@ -118,6 +118,8 @@ typedef uint8_t sm_key_t[16];
 
 #define L2CAP_SERVICE_ALREADY_REGISTERED                   0x69
 #define L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU                  0x6A
+#define L2CAP_SERVICE_NOT_FOUND                            0x6B
+#define L2CAP_LOCAL_CID_INVALID                            0x6C
     
 #define RFCOMM_MULTIPLEXER_STOPPED                         0x70
 #define RFCOMM_CHANNEL_ALREADY_REGISTERED                  0x71
diff --git a/src/l2cap.c b/src/l2cap.c
index 3d677c119..a2cc9bfca 100644
--- a/src/l2cap.c
+++ b/src/l2cap.c
@@ -772,6 +772,38 @@ static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * ch
     channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
 }
 
+static l2cap_channel_t * l2cap_create_channel_entry(btstack_packet_handler_t packet_handler, bd_addr_t address, bd_addr_type_t address_type, 
+    uint16_t psm, uint16_t local_mtu, gap_security_level_t security_level){
+
+    l2cap_channel_t * channel = btstack_memory_l2cap_channel_get();
+    if (!channel) {
+        return NULL;
+    }
+
+     // Init memory (make valgrind happy)
+    memset(channel, 0, sizeof(l2cap_channel_t));
+        
+    // fill in 
+    channel->packet_handler = packet_handler;
+    bd_addr_copy(channel->address, address);
+    channel->address_type = address_type;
+    channel->psm = psm;
+    channel->local_mtu  = local_mtu;
+    channel->remote_mtu = L2CAP_MINIMAL_MTU;
+    channel->required_security_level = security_level;
+
+    // 
+    channel->local_cid = l2cap_next_local_cid();
+    channel->con_handle = 0;
+
+    // set initial state
+    channel->state = L2CAP_STATE_WILL_SEND_CREATE_CONNECTION;
+    channel->state_var = L2CAP_CHANNEL_STATE_VAR_NONE;
+    channel->remote_sig_id = L2CAP_SIG_ID_INVALID;
+    channel->local_sig_id = L2CAP_SIG_ID_INVALID;
+    return channel;
+}
+
 /** 
  * @brief Creates L2CAP channel to the PSM of a remote device with baseband address. A new baseband connection will be initiated if necessary.
  * @param packet_handler
@@ -780,38 +812,19 @@ static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * ch
  * @param mtu
  * @param local_cid
  */
-uint8_t l2cap_create_channel(btstack_packet_handler_t channel_packet_handler, bd_addr_t address, uint16_t psm, uint16_t mtu, uint16_t * out_local_cid){
-    log_info("L2CAP_CREATE_CHANNEL addr %s psm 0x%x mtu %u", bd_addr_to_str(address), psm, mtu);
+
+uint8_t l2cap_create_channel(btstack_packet_handler_t channel_packet_handler, bd_addr_t address, uint16_t psm, uint16_t local_mtu, uint16_t * out_local_cid){
+    log_info("L2CAP_CREATE_CHANNEL addr %s psm 0x%x mtu %u", bd_addr_to_str(address), psm, local_mtu);
     
-    // alloc structure
-    l2cap_channel_t * channel = btstack_memory_l2cap_channel_get();
+    if (local_mtu > l2cap_max_mtu()) {
+        local_mtu = l2cap_max_mtu();
+    }
+
+    l2cap_channel_t * channel = l2cap_create_channel_entry(channel_packet_handler, address, BD_ADDR_TYPE_CLASSIC, psm, local_mtu, LEVEL_0);
     if (!channel) {
         return BTSTACK_MEMORY_ALLOC_FAILED;
     }
 
-     // Init memory (make valgrind happy)
-    memset(channel, 0, sizeof(l2cap_channel_t));
-    // limit local mtu to max acl packet length - l2cap header
-    if (mtu > l2cap_max_mtu()) {
-        mtu = l2cap_max_mtu();
-    }
-        
-    // fill in 
-    bd_addr_copy(channel->address, address);
-    channel->psm = psm;
-    channel->con_handle = 0;
-    channel->packet_handler = channel_packet_handler;
-    channel->remote_mtu = L2CAP_MINIMAL_MTU;
-    channel->local_mtu = mtu;
-    channel->local_cid = l2cap_next_local_cid();
-
-    // set initial state
-    channel->state = L2CAP_STATE_WILL_SEND_CREATE_CONNECTION;
-    channel->state_var = L2CAP_CHANNEL_STATE_VAR_NONE;
-    channel->remote_sig_id = L2CAP_SIG_ID_INVALID;
-    channel->local_sig_id = L2CAP_SIG_ID_INVALID;
-    channel->required_security_level = LEVEL_0;
-
     // add to connections list
     btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) channel);
 
@@ -1081,25 +1094,17 @@ static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig
 
     // alloc structure
     // log_info("l2cap_handle_connection_request register channel");
-    l2cap_channel_t * channel = btstack_memory_l2cap_channel_get();
+    l2cap_channel_t * channel = l2cap_create_channel_entry(service->packet_handler, hci_connection->address, BD_ADDR_TYPE_CLASSIC, 
+    psm, service->mtu, service->required_security_level);
     if (!channel){
         // 0x0004 No resources available
         l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, 0x0004);
         return;
     }
-    // Init memory (make valgrind happy)
-    memset(channel, 0, sizeof(l2cap_channel_t));
-    // fill in 
-    bd_addr_copy(channel->address, hci_connection->address);
-    channel->psm = psm;
+
     channel->con_handle = handle;
-    channel->packet_handler = service->packet_handler;
-    channel->local_cid  = l2cap_next_local_cid();
     channel->remote_cid = source_cid;
-    channel->local_mtu  = service->mtu;
-    channel->remote_mtu = L2CAP_DEFAULT_MTU;
     channel->remote_sig_id = sig_id; 
-    channel->required_security_level = service->required_security_level;
 
     // limit local mtu to max acl packet length - l2cap header
     if (channel->local_mtu > l2cap_max_mtu()) {
@@ -1530,7 +1535,6 @@ uint8_t l2cap_register_service(btstack_packet_handler_t service_packet_handler,
     log_info("L2CAP_REGISTER_SERVICE psm 0x%x mtu %u", psm, mtu);
     
     // check for alread registered psm 
-    // TODO: emit error event
     l2cap_service_t *service = l2cap_get_service(psm);
     if (service) {
         log_error("l2cap_register_service: PSM %u already registered", psm);
@@ -1538,7 +1542,6 @@ uint8_t l2cap_register_service(btstack_packet_handler_t service_packet_handler,
     }
     
     // alloc structure
-    // TODO: emit error event
     service = btstack_memory_l2cap_service_get();
     if (!service) {
         log_error("l2cap_register_service: no memory for l2cap_service_t");
@@ -1583,8 +1586,6 @@ void l2cap_register_fixed_channel(btstack_packet_handler_t the_packet_handler, u
 
 #ifdef ENABLE_BLE
 
-
-#if 0
 static inline l2cap_service_t * l2cap_le_get_service(uint16_t psm){
     return l2cap_get_service_internal(&l2cap_le_services, psm);
 }
@@ -1592,33 +1593,26 @@ static inline l2cap_service_t * l2cap_le_get_service(uint16_t psm){
  * @brief Regster L2CAP LE Credit Based Flow Control Mode service
  * @param
  */
-void l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint16_t psm,
-    uint16_t mtu, uint16_t mps, uint16_t initial_credits, gap_security_level_t security_level){
+uint8_t l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, gap_security_level_t security_level){
     
-    log_info("L2CAP_LE_REGISTER_SERVICE psm 0x%x mtu %u connection %p", psm, mtu, connection);
+    log_info("L2CAP_LE_REGISTER_SERVICE psm 0x%x", psm);
     
     // check for alread registered psm 
-    // TODO: emit error event
     l2cap_service_t *service = l2cap_le_get_service(psm);
     if (service) {
-        log_error("l2cap_le_register_service_internal: PSM %u already registered", psm);
-        l2cap_emit_service_registered(connection, L2CAP_SERVICE_ALREADY_REGISTERED, psm);
-        return;
+        return L2CAP_SERVICE_ALREADY_REGISTERED;
     }
     
     // alloc structure
-    // TODO: emit error event
     service = btstack_memory_l2cap_service_get();
     if (!service) {
         log_error("l2cap_register_service_internal: no memory for l2cap_service_t");
-        l2cap_emit_service_registered(connection, BTSTACK_MEMORY_ALLOC_FAILED, psm);
-        return;
+        return BTSTACK_MEMORY_ALLOC_FAILED;
     }
     
     // fill in 
     service->psm = psm;
-    service->mtu = mtu;
-    service->mps = mps;
+    service->mtu = 0;
     service->packet_handler = packet_handler;
     service->required_security_level = security_level;
 
@@ -1626,17 +1620,132 @@ void l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint16_t
     btstack_linked_list_add(&l2cap_le_services, (btstack_linked_item_t *) service);
     
     // done
-    l2cap_emit_service_registered(connection, 0, psm);
+    return 0;
 }
 
-void l2cap_le_unregister_service(uint16_t psm) {
-
+uint8_t l2cap_le_unregister_service(uint16_t psm) {
     log_info("L2CAP_LE_UNREGISTER_SERVICE psm 0x%x", psm);
-
     l2cap_service_t *service = l2cap_le_get_service(psm);
-    if (!service) return;
+    if (!service) return L2CAP_SERVICE_NOT_FOUND;
+
     btstack_linked_list_remove(&l2cap_le_services, (btstack_linked_item_t *) service);
     btstack_memory_l2cap_service_free(service);
+    return 0;
 }
-#endif
+
+/*
+ * @brief Accept incoming LE Data Channel connection
+ * @param local_cid             L2CAP LE Data Channel Identifier
+ * @param receive_buffer        buffer used for reassembly of L2CAP LE Information Frames into service data unit (SDU) with given MTU
+ * @param receive_buffer_size   buffer size equals MTU
+ * @param initial_credits       Number of initial credits provided to peer
+ */
+
+uint8_t l2cap_le_accept_connection(uint16_t local_cid, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits){
+    return 0;
+}
+
+/** 
+ * @brief Deny incoming LE Data Channel connection due to resource constraints
+ * @param local_cid             L2CAP LE Data Channel Identifier
+ */
+
+uint8_t l2cap_le_decline_connection(uint16_t local_cid){
+    return 0;
+}
+
+/**
+ * @brief Create LE Data Channel
+ * @param packet_handler        Packet handler for this connection
+ * @param address               Peer address
+ * @param address_type          Peer address type
+ * @param psm                   Service PSM to connect to
+ * @param receive_buffer        buffer used for reassembly of L2CAP LE Information Frames into service data unit (SDU) with given MTU
+ * @param receive_buffer_size   buffer size equals MTU
+ * @param initial_credits       Number of initial credits provided to peer
+ * @param security_level        Minimum required security level
+ * @param out_local_cid         L2CAP LE Channel Identifier is stored here
+ */
+uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, bd_addr_type_t address_type, 
+    uint16_t psm, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits, gap_security_level_t security_level,
+    uint16_t * out_local_cid)
+{
+    log_info("L2CAP_LE_CREATE_CHANNEL addr %s psm 0x%x mtu %u", bd_addr_to_str(address), psm, mtu);
+    
+    l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, address, BD_ADDR_TYPE_CLASSIC, psm, mtu, LEVEL_0);
+    if (!channel) {
+        return BTSTACK_MEMORY_ALLOC_FAILED;
+    }
+
+    // add to connections list
+    btstack_linked_list_add(&l2cap_le_channels, (btstack_linked_item_t *) channel);
+
+    // store local_cid
+    if (out_local_cid){
+       *out_local_cid = channel->local_cid;
+    }
+
+    // check if hci connection is already usable
+    hci_connection_t * conn = hci_connection_for_bd_addr_and_type(address, address_type);
+    if (conn){
+        log_info("l2cap_le_create_channel, hci connection already exists");
+        // l2cap_handle_connection_complete(conn->con_handle, channel);
+        // check if remote supported fearures are already received
+        // if (conn->bonding_flags & BONDING_RECEIVED_REMOTE_FEATURES) {
+        //     l2cap_handle_remote_supported_features_received(channel);
+        // }
+    }
+
+    l2cap_run();
+
+    return 0;
+}
+
+/**
+ * @brief Provide credtis for LE Data Channel
+ * @param local_cid             L2CAP LE Data Channel Identifier
+ * @param credits               Number additional credits for peer
+ */
+uint8_t l2cap_le_provide_credits(uint16_t cid, uint16_t credits){
+    return 0;
+}
+
+/**
+ * @brief Check if outgoing buffer is available and that there's space on the Bluetooth module
+ * @param local_cid             L2CAP LE Data Channel Identifier
+ */
+int l2cap_le_can_send_now(uint16_t cid){
+    return 0;
+}
+
+/**
+ * @brief Request emission of L2CAP_EVENT_CAN_SEND_NOW as soon as possible
+ * @note L2CAP_EVENT_CAN_SEND_NOW might be emitted during call to this function
+ *       so packet handler should be ready to handle it
+ * @param local_cid             L2CAP LE Data Channel Identifier
+ */
+uint8_t l2cap_le_request_can_send_now_event(uint16_t cid){
+    return 0;
+}
+
+/**
+ * @brief Send data via LE Data Channel
+ * @note Since data larger then the maximum PDU needs to be segmented into multiple PDUs, data needs to stay valid until ... event
+ * @param local_cid             L2CAP LE Data Channel Identifier
+ * @param data                  data to send
+ * @param size                  data size
+ */
+uint8_t l2cap_le_send_data(uint16_t cid, uint8_t * data, uint16_t size){
+    return 0;
+}
+
+/**
+ * @brief Disconnect from LE Data Channel
+ * @param local_cid             L2CAP LE Data Channel Identifier
+ */
+uint8_t l2cap_le_disconnect(uint16_t cid)
+{
+    return 0;
+}
+
 #endif
diff --git a/src/l2cap.h b/src/l2cap.h
index a79b10e85..abf570699 100644
--- a/src/l2cap.h
+++ b/src/l2cap.h
@@ -112,8 +112,10 @@ typedef struct {
     L2CAP_CHANNEL_STATE_VAR state_var;
 
     // info
-    bd_addr_t address;
     hci_con_handle_t con_handle;
+
+    bd_addr_t address;
+    bd_addr_type_t address_type;
     
     uint8_t   remote_sig_id;    // used by other side, needed for delayed response
     uint8_t   local_sig_id;     // own signaling identifier
@@ -123,6 +125,8 @@ typedef struct {
     
     uint16_t  local_mtu;
     uint16_t  remote_mtu;
+
+    uint16_t  mps;  // LE Data Channel
     
     uint16_t  flush_timeout;    // default 0xffff
 
@@ -132,7 +136,16 @@ typedef struct {
 
     uint8_t   reason; // used in decline internal
     uint8_t   waiting_for_can_send_now;
+
+    // credits for outgoing traffic
+    uint8_t credits_outgoing;
     
+    // number of packets remote will be granted
+    uint8_t new_credits_incoming;
+
+    // credits for incoming traffic
+    uint8_t credits_incoming;
+
 } l2cap_channel_t;
 
 // info regarding potential connections
@@ -145,15 +158,13 @@ typedef struct {
     
     // incoming MTU
     uint16_t mtu;
-
-    // incoming MPS
-    uint16_t mps;
     
     // internal connection
     btstack_packet_handler_t packet_handler;
 
     // required security level
-    gap_security_level_t required_security_level;    
+    gap_security_level_t required_security_level;
+
 } l2cap_service_t;
 
 
@@ -292,14 +303,14 @@ void l2cap_release_packet_buffer(void);
  * @param psm
  * @param security_level
  */
-void l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, gap_security_level_t security_level);
+uint8_t l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, gap_security_level_t security_level);
 
 /**
  * @brief Unregister L2CAP LE Data Channel service
  * @param psm
  */
 
-void l2cap_le_unregister_service(uint16_t psm);
+uint8_t l2cap_le_unregister_service(uint16_t psm);
 
 /*
  * @brief Accept incoming LE Data Channel connection
@@ -319,7 +330,7 @@ uint8_t l2cap_le_accept_connection(uint16_t local_cid, uint8_t * receive_sdu_buf
 uint8_t l2cap_le_decline_connection(uint16_t local_cid);
 
 /**
- * @brief Create LE Data Channel connection
+ * @brief Create LE Data Channel
  * @param packet_handler        Packet handler for this connection
  * @param address               Peer address
  * @param address_type          Peer address type
@@ -330,7 +341,7 @@ uint8_t l2cap_le_decline_connection(uint16_t local_cid);
  * @param security_level        Minimum required security level
  * @param out_local_cid         L2CAP LE Channel Identifier is stored here
  */
-uint8_t l2cap_le_create_connection(btstack_packet_handler_t packet_handler, bd_addr_t address, bd_addr_type_t address_type, 
+uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, bd_addr_type_t address_type, 
     uint16_t psm, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits, gap_security_level_t security_level,
     uint16_t * out_local_cid);