summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAyush Garg <ayush.garg@samsung.com>2022-03-07 17:20:54 +0530
committerAnuj Jain <anuj01.jain@samsung.com>2023-09-27 14:50:58 +0530
commit1afb39a4bd5152ccf5f7d37b025fc220e24653cf (patch)
treedc98030d9b337b9dacd07cf3820944949ff3efc4
parent2c542bf2630350016971160e2095d6ebb35c8e12 (diff)
downloadbluetooth-1afb39a4bd5152ccf5f7d37b025fc220e24653cf.tar.gz
bluetooth-1afb39a4bd5152ccf5f7d37b025fc220e24653cf.tar.bz2
bluetooth-1afb39a4bd5152ccf5f7d37b025fc220e24653cf.zip
LE CoC: Implement CAPIs
This patch primarily handles following: - CAPIs to create and listen to L2CAP_LE socket - CAPIs to connect and disconnect to L2CAP_LE socket - CAPIs to get PSM of the listening L2CAP_LE socket - Event Handlers for connection, disconnection and authorization of L2CAP_LE socket To avoid build conflict please merge this patch after merging framework patch: (Change-Id: Icf4d8a51acc444765a9b61224a3a5d3fd26bfa65) Change-Id: I6ac0595799602db1402778da3f73109366a013c2 Signed-off-by: Ayush Garg <ayush.garg@samsung.com> Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
-rw-r--r--include/bluetooth_internal.h81
-rw-r--r--include/bluetooth_private.h274
-rw-r--r--include/bluetooth_type_internal.h34
-rw-r--r--src/bluetooth-common.c79
-rw-r--r--src/bluetooth-socket.c233
5 files changed, 700 insertions, 1 deletions
diff --git a/include/bluetooth_internal.h b/include/bluetooth_internal.h
index 236cf7e..8ffe88a 100644
--- a/include/bluetooth_internal.h
+++ b/include/bluetooth_internal.h
@@ -5475,6 +5475,87 @@ int bt_mesh_model_get_publication(bt_mesh_model_h model,
void *user_data);
/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Starts listening on passed L2CAP Connection-oriented Channel (CoC) socket.
+ * @since_tizen 7.0
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/bluetooth.admin
+ * @details bt_socket_l2cap_channel_connection_requested_cb() will be called when a L2CAP CoC connection is requested.
+ *
+ * @param[in] socket_fd The file descriptor socket on which start to listen
+ * @param[in] max_pending_connections The number of pending connections
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_NOT_ENABLED Not enabled
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_OPERATION_FAILED Operation failed
+ * @retval #BT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The socket must be created with bt_socket_create_l2cap_channel().
+ * @post This function invokes bt_socket_l2cap_channel_connection_state_changed_cb().
+ *
+ * @see bt_socket_create_l2cap_channel()
+ * @see bt_socket_set_l2cap_channel_connection_requested_cb()
+ * @see bt_socket_unset_l2cap_channel_connection_requested_cb()
+ * @see bt_socket_l2cap_channel_connection_requested_cb()
+ */
+int bt_socket_listen_l2cap_channel(int socket_fd, int max_pending_connections);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Accepts a connection request.
+ * @since_tizen 7.0
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/bluetooth.admin
+ * @param[in] requested_socket_fd The file descriptor of socket on which a connection is requested
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_NOT_ENABLED Not enabled
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_OPERATION_FAILED Operation failed
+ * @retval #BT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The connection is requested by bt_socket_l2cap_channel_connection_requested_cb().
+ * @see bt_socket_create_l2cap_channel()
+ * @see bt_socket_l2cap_channel_connection_requested_cb()
+ * @see bt_socket_listen_l2cap_channel()
+ * @see bt_socket_reject_l2cap_channel()
+*/
+int bt_socket_accept_l2cap_channel(int requested_socket_fd);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Rejects a connection request.
+ * @since_tizen 7.0
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/bluetooth.admin
+ * @param[in] socket_fd The file descriptor of socket on which a connection is requested
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_NOT_ENABLED Not enabled
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_OPERATION_FAILED Operation failed
+ * @retval #BT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The connection is requested by bt_socket_l2cap_channel_connection_requested_cb().
+ * @see bt_socket_create_l2cap_channel()
+ * @see bt_socket_l2cap_channel_connection_requested_cb()
+ * @see bt_socket_listen_l2cap_channel()
+ * @see bt_socket_accept_l2cap_channel()
+ */
+int bt_socket_reject_l2cap_channel(int socket_fd);
+
+/**
* @}
*/
diff --git a/include/bluetooth_private.h b/include/bluetooth_private.h
index da41913..8af0bdd 100644
--- a/include/bluetooth_private.h
+++ b/include/bluetooth_private.h
@@ -191,6 +191,8 @@ typedef enum {
BT_EVENT_MESH_NODE_MODEL_GROUP_VIR_SUB, /**< Mesh - Model Virtual Subscription - Add/Delete/overwrite/DeleteAll */
BT_EVENT_MESH_NODE_MODEL_PUBLICATION, /**< Mesh - Model Publication Status event index */
BT_EVENT_MESH_JOIN_NETWORK, /**< Mesh - Join Complete callback */
+ BT_EVENT_L2CAP_CHANNEL_CONNECTION_STATE_CHANGED, /**< L2CAP LE socket connection state is changed */
+ BT_EVENT_L2CAP_CHANNEL_CONNECTION_REQUESTED, /**< L2CAP LE socket connection is requested */
BT_EVENT_MAX
} bt_event_e;
@@ -1305,6 +1307,278 @@ extern tizen_profile_t profile;
#define TIZEN_FEATURE_ENABLE_LEGACY_GATT_CLIENT TIZEN_PROFILE_MOBILE
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Registers a L2CAP Connection-oriented Channel (CoC) server socket
+ * with a specific protocol/service multiplexer (PSM) value. If 0 is passed,
+ * the system will assign a dynamic psm value when bt_socket_listen_and_accept_l2cap_channel()
+ * is called. This psm value can be read from the bt_socket_get_l2cap_psm().
+ * @since_tizen 7.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/bluetooth
+ *
+ * @remarks A socket can be destroyed by bt_socket_destroy_l2cap_channel().
+ *
+ * @param[in] psm The dynamic psm value to start server
+ * @param[out] socket_fd The file descriptor of socket to listen
+ * @return 0 on success, otherwise a negative error value.
+ *
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_NOT_ENABLED Not enabled
+ * @retval #BT_ERROR_OPERATION_FAILED Operation failed
+ * @retval #BT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The state of local Bluetooth must be #BT_ADAPTER_ENABLED.
+ *
+ * @see bt_socket_listen_and_accept_l2cap_channel()
+ * @see bt_socket_destroy_l2cap_channel()
+ */
+int bt_socket_create_l2cap_channel(int psm, int *socket_fd);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Removes the L2CAP Connection-oriented Channel (CoC) server socket which was created using bt_socket_create_l2cap_channel().
+ * @since_tizen 7.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/bluetooth
+ * @remarks If callback function bt_socket_l2cap_channel_connection_state_changed_cb() is set and the remote Bluetooth device is connected, \n
+ * then bt_socket_l2cap_channel_connection_state_changed_cb() will be called when this function is finished successfully.
+ *
+ * @param[in] socket_fd The file descriptor of socket (which was created using bt_socket_create_l2cap_channel()) to destroy
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_NOT_ENABLED Not enabled
+ * @retval #BT_ERROR_OPERATION_FAILED Operation failed
+ * @retval #BT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The socket must be created with bt_socket_create_l2cap_channel().
+ * @post If callback function bt_socket_l2cap_channel_connection_state_changed_cb() is set and the remote Bluetooth device is connected,
+ * then bt_socket_l2cap_channel_connection_state_changed_cb() will be called.
+ * @see bt_socket_create_l2cap_channel()
+ * @see bt_socket_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_set_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_unset_l2cap_channel_connection_state_changed_cb()
+ */
+int bt_socket_destroy_l2cap_channel(int socket_fd);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Starts listening on passed L2CAP_LE socket and accepts connection requests.
+ * @details Pop-up is shown automatically when a L2CAP CoC connection is requested. \n
+ * bt_socket_l2cap_channel_connection_state_changed_cb() will be called with \n
+ * #BT_SOCKET_CONNECTED if you click "yes" and connection is finished successfully.
+ * @since_tizen 7.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/bluetooth
+ * @param[in] socket_fd The file descriptor of socket on which start to listen
+ * @param[in] max_pending_connections The maximum number of pending connections
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_NOT_ENABLED Not enabled
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_OPERATION_FAILED Operation failed
+ * @retval #BT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The socket must be created with bt_socket_create_l2cap_channel().
+ * @post If callback function bt_socket_l2cap_channel_connection_state_changed_cb() is set,
+ * then bt_socket_l2cap_channel_connection_state_changed_cb() will be called when the remote Bluetooth device is connected.
+ * @see bt_socket_create_l2cap_channel()
+ * @see bt_socket_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_set_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_unset_l2cap_channel_connection_state_changed_cb()
+ */
+int bt_socket_listen_and_accept_l2cap_channel(int socket_fd,
+ int max_pending_connections);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Get the assigned PSM for the listening L2CAP Connection-oriented Channel (CoC) server socket.
+ * @details It is used to get the system assigned PSM value especially when bt_socket_create_l2cap_channel()
+ * is called with psm value 0.
+ * @since_tizen 7.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/bluetooth
+ *
+ * @param[in] socket_fd The file descriptor of connected socket which was received using bt_socket_l2cap_channel_connection_state_changed_cb()
+ * @param[out] psm The assigned dynamic PSM value for the listening L2CAP CoC server socket
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre The bt_socket_listen_and_accept_l2cap_channel() must be called.
+ *
+ * @see bt_socket_create_l2cap_channel()
+ * @see bt_socket_listen_and_accept_l2cap_channel()
+ */
+int bt_socket_get_l2cap_psm(int socket_fd, int *psm);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Connects to a specific L2CAP CoC socket on a remote Bluetooth device PSM, asynchronously.
+ * @since_tizen 7.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/bluetooth
+ *
+ * @remarks A connection can be disconnected by bt_socket_disconnect_l2cap_channel().
+ *
+ * @param[in] remote_address The address of the remote Bluetooth device
+ * @param[in] psm The dynamic psm of a remote Bluetooth device
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_NOT_ENABLED Not enabled
+ * @retval #BT_ERROR_OPERATION_FAILED Operation failed
+ * @retval #BT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The state of local Bluetooth must be #BT_ADAPTER_ENABLED.
+ * @pre The remote device must be scannable with bt_adapter_le_start_scan().
+ * @post This function invokes bt_socket_l2cap_channel_connection_state_changed_cb().
+ *
+ * @see bt_adapter_le_start_scan()
+ * @see bt_socket_disconnect_l2cap_channel()
+ * @see bt_socket_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_set_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_unset_l2cap_channel_connection_state_changed_cb()
+ */
+int bt_socket_connect_l2cap_channel(const char *remote_address, int psm);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Disconnects the L2CAP CoC connection with the given file descriptor of connected socket.
+ * @since_tizen 7.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/bluetooth
+ * @param[in] socket_fd The file descriptor of socket to close which was received using bt_socket_l2cap_channel_connection_state_changed_cb().
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_NOT_ENABLED Not enabled
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The connection must be established.
+ *
+ * @see bt_socket_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_set_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_unset_l2cap_channel_connection_state_changed_cb()
+ */
+int bt_socket_disconnect_l2cap_channel(int socket_fd);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Sends data to the connected device.
+ * @since_tizen 7.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/bluetooth
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ *
+ * @param[in] socket_fd The file descriptor of connected socket which was received using bt_socket_l2cap_channel_connection_state_changed_cb()
+ * @param[in] data The data to be sent
+ * @param[in] length The length of data to be sent
+ *
+ * @return the number of bytes written (zero indicates nothing was written).
+ * @retval On error, -1 is returned, and errno is set appropriately. See write 2 man page.
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @exception BT_ERROR_PERMISSION_DENIED Permission denied
+ * @exception BT_ERROR_AGAIN Resource temporarily unavailable
+ *
+ * @pre The connection must be established.
+ *
+ * @see bt_socket_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_set_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_unset_l2cap_channel_connection_state_changed_cb()
+ */
+int bt_socket_send_data_l2cap_channel(int socket_fd, const char *data, int length);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Registers a callback function that will be invoked when a L2CAP CoC connection is requested.
+ * @since_tizen 7.0
+ * @param[in] callback The callback function to register
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The Bluetooth service must be initialized with bt_initialize().
+ * @post bt_socket_connection_requested_cb() will be invoked.
+ * @see bt_initialize()
+ * @see bt_socket_unset_l2cap_channel_connection_requested_cb()
+ */
+int bt_socket_set_l2cap_channel_connection_requested_cb(
+ bt_socket_connection_requested_cb callback, void *user_data);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Unregisters the callback function.
+ * @since_tizen 7.0
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The Bluetooth service must be initialized with bt_initialize().
+ * @see bt_initialize()
+ * @see bt_socket_set_l2cap_channel_connection_requested_cb()
+ * @see bt_socket_connection_requested_cb()
+ */
+int bt_socket_unset_l2cap_channel_connection_requested_cb(void);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Registers a callback function that will be invoked when the connection state changes.
+ * @since_tizen 7.0
+ * @param[in] callback The callback function to register
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The Bluetooth service must be initialized with bt_initialize().
+ * @post bt_socket_l2cap_channel_connection_state_changed_cb() will be invoked.
+ * @see bt_initialize()
+ * @see bt_socket_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_unset_l2cap_channel_connection_state_changed_cb()
+ */
+int bt_socket_set_l2cap_channel_connection_state_changed_cb(
+ bt_socket_l2cap_channel_connection_state_changed_cb callback, void *user_data);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Unregisters the callback function.
+ * @since_tizen 7.0
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #BT_ERROR_NONE Successful
+ * @retval #BT_ERROR_NOT_INITIALIZED Not initialized
+ * @retval #BT_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The Bluetooth service must be initialized with bt_initialize().
+ * @see bt_initialize()
+ * @see bt_socket_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_set_l2cap_channel_connection_state_changed_cb()
+ */
+int bt_socket_unset_l2cap_channel_connection_state_changed_cb(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/bluetooth_type_internal.h b/include/bluetooth_type_internal.h
index efae2a3..676a6e1 100644
--- a/include/bluetooth_type_internal.h
+++ b/include/bluetooth_type_internal.h
@@ -1700,6 +1700,40 @@ typedef bool (*bt_mesh_network_group_info_cb)
(int result, bt_mesh_network_h network, int total,
bt_mesh_group_h group, void *user_data);
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief L2CAP CoC connection data used for exchanging data between Bluetooth devices.
+ * @since_tizen 7.0
+ *
+ * @see bt_socket_l2cap_channel_connection_state_changed_cb()
+ */
+typedef struct {
+ int socket_fd; /**< The file descriptor of connected socket */
+ int server_fd; /**< The file descriptor of the server socket or -1 for client connection */
+ bt_socket_role_e local_role; /**< The local device role in this connection */
+ char *remote_address; /**< The remote device address */
+ int psm; /**< The psm of the connected socket */
+} bt_socket_l2cap_le_connection_s;
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_SOCKET_MODULE
+ * @brief Called when the l2cap channel socket connection state changes.
+ * @since_tizen 7.0
+ *
+ * @param[in] result The result of connection state changing
+ * @param[in] connection_state The connection state
+ * @param[in] connection The connection information which is established or disconnected
+ * @param[in] user_data The user data passed from the callback registration function
+ * @pre Either bt_socket_connect_l2cap_channel() will invoke this function.
+ * In addition, bt_socket_l2cap_channel_connection_state_changed_cb() will be invoked when the socket connection state is changed.
+ * @see bt_socket_listen_and_accept_l2cap_channel()
+ * @see bt_socket_connect_l2cap_channel()
+ * @see bt_socket_set_l2cap_channel_connection_state_changed_cb()
+ * @see bt_socket_unset_l2cap_channel_connection_state_changed_cb()
+ */
+typedef void (*bt_socket_l2cap_channel_connection_state_changed_cb)
+ (int result, bt_socket_connection_state_e connection_state, bt_socket_l2cap_le_connection_s *connection, void *user_data);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/src/bluetooth-common.c b/src/bluetooth-common.c
index 1cadb78..b58ba8b 100644
--- a/src/bluetooth-common.c
+++ b/src/bluetooth-common.c
@@ -301,6 +301,10 @@ static bt_event2index_table_t event2index[] = {
{ BLUETOOTH_EVENT_MESH_MODEL_VIRTUAL_SUBSCRIPTION_CONFGURED, BT_EVENT_MESH_NODE_MODEL_GROUP_VIR_SUB },
{ BLUETOOTH_EVENT_MESH_MODEL_PUBLICATION_STATUS, BT_EVENT_MESH_NODE_MODEL_PUBLICATION },
{ BLUETOOTH_EVENT_MESH_JOIN_COMPLETED, BT_EVENT_MESH_JOIN_NETWORK },
+ { BLUETOOTH_EVENT_L2CAP_LE_DATA_RECEIVED, BT_EVENT_DATA_RECEIVED},
+ { BLUETOOTH_EVENT_L2CAP_LE_CONNECTED, BT_EVENT_L2CAP_CHANNEL_CONNECTION_STATE_CHANGED},
+ { BLUETOOTH_EVENT_L2CAP_LE_DISCONNECTED, BT_EVENT_L2CAP_CHANNEL_CONNECTION_STATE_CHANGED},
+ { BLUETOOTH_EVENT_L2CAP_LE_AUTHORIZE, BT_EVENT_L2CAP_CHANNEL_CONNECTION_REQUESTED},
{ 0, -1 }
};
@@ -1554,6 +1558,10 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
bt_ipsp_connection_info_t *bt_ipsp_iface_info = NULL;
bt_pxp_property_changed_params_t *bt_pxp_property_info = NULL;
bluetooth_tds_activation_req_t *tds_act_req_info = NULL;
+ bluetooth_l2cap_le_connection_t *l2cap_le_connection_ind = NULL;
+ bluetooth_l2cap_le_disconnection_t *l2cap_le_disconnection_ind = NULL;
+ bluetooth_l2cap_le_connection_request_t *l2cap_le_request_ind = NULL;
+ bt_socket_l2cap_le_connection_s l2cap_le_connection;
#ifdef TIZEN_GATT_CLIENT
bt_gatt_char_property_t *char_prop = NULL;
@@ -4271,7 +4279,76 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
(_bt_get_error_code(param->result), (bt_mesh_node_h) info,
bt_event_slot_container[event_index].user_data);
break;
- }
+ } case BLUETOOTH_EVENT_L2CAP_LE_DATA_RECEIVED:
+ BT_INFO("L2CAP_LE: bt_socket_data_received_cb() will be * called");
+ ((bt_socket_data_received_cb)bt_event_slot_container[event_index].callback)
+ ((bt_socket_received_data_s *)(param->param_data), bt_event_slot_container[event_index].user_data);
+ break;
+ case BLUETOOTH_EVENT_L2CAP_LE_CONNECTED:
+ BT_INFO("L2CAP_LE: bt_socket_l2cap_channel_connection_state_changed_cb() will be called with BT_SOCKET_CONNECTED");
+ if (param->result == BLUETOOTH_ERROR_INVALID_PARAM)
+ error_code = BT_ERROR_OPERATION_FAILED;
+ else
+ error_code = _bt_get_error_code(param->result);
+
+ memset(&l2cap_le_connection, 0x00, sizeof(bt_socket_l2cap_le_connection_s));
+ l2cap_le_connection_ind = (bluetooth_l2cap_le_connection_t *)(param->param_data);
+
+ if (l2cap_le_connection_ind) {
+ l2cap_le_connection.socket_fd = l2cap_le_connection_ind->socket_fd;
+ l2cap_le_connection.local_role = l2cap_le_connection_ind->device_role;
+ l2cap_le_connection.server_fd = l2cap_le_connection_ind->server_id;
+ l2cap_le_connection.psm = l2cap_le_connection_ind->psm;
+
+ BT_INFO("L2CAP_LE PSM[%d] FD[%d] Role [%d] serverFD [%d]", l2cap_le_connection_ind->psm,
+ l2cap_le_connection_ind->socket_fd, (int)l2cap_le_connection_ind->device_role,
+ l2cap_le_connection_ind->server_id);
+
+ _bt_convert_address_to_string(&(l2cap_le_connection.remote_address),
+ &(l2cap_le_connection_ind->device_addr));
+ }
+
+ ((bt_socket_l2cap_channel_connection_state_changed_cb)bt_event_slot_container[event_index].callback)
+ (error_code, BT_SOCKET_CONNECTED, &l2cap_le_connection, bt_event_slot_container[event_index].user_data);
+
+ if (l2cap_le_connection.remote_address != NULL) {
+ free(l2cap_le_connection.remote_address);
+ l2cap_le_connection.remote_address = NULL;
+ }
+ break;
+ case BLUETOOTH_EVENT_L2CAP_LE_DISCONNECTED:
+ BT_INFO("L2CAP_LE: bt_socket_l2cap_channel_connection_state_changed_cb() will be called with BT_SOCKET_DISCONNECTED");
+
+ memset(&l2cap_le_connection, 0x00, sizeof(bt_socket_l2cap_le_connection_s));
+ l2cap_le_disconnection_ind = (bluetooth_l2cap_le_disconnection_t *)(param->param_data);
+
+ if (l2cap_le_disconnection_ind) {
+ l2cap_le_connection.socket_fd = l2cap_le_disconnection_ind->socket_fd;
+ l2cap_le_connection.local_role = l2cap_le_disconnection_ind->device_role;
+ l2cap_le_connection.psm = l2cap_le_disconnection_ind->psm;
+
+ _bt_convert_address_to_string(&(l2cap_le_connection.remote_address),
+ &(l2cap_le_disconnection_ind->device_addr));
+ }
+
+ ((bt_socket_l2cap_channel_connection_state_changed_cb)bt_event_slot_container[event_index].callback)
+ (_bt_get_error_code(param->result), BT_SOCKET_DISCONNECTED, &l2cap_le_connection, bt_event_slot_container[event_index].user_data);
+
+ if (l2cap_le_connection.remote_address != NULL) {
+ free(l2cap_le_connection.remote_address);
+ l2cap_le_connection.remote_address = NULL;
+ }
+ break;
+ case BLUETOOTH_EVENT_L2CAP_LE_AUTHORIZE:
+ BT_INFO("L2CAP_LE: Authorize bt_socket_connection_requested_cb() will be called");
+ l2cap_le_request_ind = (bluetooth_l2cap_le_connection_request_t *)(param->param_data);
+ _bt_convert_address_to_string(&device_addr, &(l2cap_le_request_ind->device_addr));
+ ((bt_socket_connection_requested_cb)bt_event_slot_container[event_index].callback)
+ (l2cap_le_request_ind->socket_fd, device_addr, bt_event_slot_container[event_index].user_data);
+
+ if (device_addr != NULL)
+ free(device_addr);
+ break;
default:
BT_INFO("Unknown function");
break;
diff --git a/src/bluetooth-socket.c b/src/bluetooth-socket.c
index 3973b7f..6e17538 100644
--- a/src/bluetooth-socket.c
+++ b/src/bluetooth-socket.c
@@ -312,3 +312,236 @@ int bt_socket_unset_connection_state_changed_cb(void)
return BT_ERROR_NONE;
}
+int bt_socket_create_l2cap_channel(int psm, int *socket_fd)
+{
+ int ret = 0;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(socket_fd);
+
+ ret = bluetooth_l2cap_le_create_socket(psm);
+ if (ret < 0) {
+ ret = _bt_get_error_code(ret); /* LCOV_EXCL_LINE */
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); /* LCOV_EXCL_LINE */
+ return ret; /* LCOV_EXCL_LINE */
+ } else {
+ *socket_fd = ret;
+ return BT_ERROR_NONE;
+ }
+}
+
+int bt_socket_destroy_l2cap_channel(int socket_fd)
+{
+ int error_code = BT_ERROR_NONE;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+ error_code = _bt_get_error_code(bluetooth_l2cap_le_remove_socket(socket_fd));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), /* LCOV_EXCL_LINE */
+ error_code);
+ }
+
+ return error_code;
+}
+
+/* LCOV_EXCL_START */
+int bt_socket_is_psm_used(int psm, bool *used)
+{
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(used);
+
+ *used = bluetooth_l2cap_le_is_server_psm_available(psm);
+
+ return BT_ERROR_NONE; /* LCOV_EXCL_STOP */
+}
+
+int bt_socket_listen_and_accept_l2cap_channel(int socket_fd,
+ int max_pending_connections)
+{
+ int error_code = BT_ERROR_NONE;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+ error_code = _bt_get_error_code(bluetooth_l2cap_le_listen_and_accept(socket_fd, max_pending_connections));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), /* LCOV_EXCL_LINE */
+ error_code);
+ }
+
+ return error_code;
+}
+
+/* LCOV_EXCL_START */
+int bt_socket_listen_l2cap_channel(int socket_fd, int max_pending_connections)
+{
+ int error_code = BT_ERROR_NONE;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+
+ error_code = _bt_get_error_code(bluetooth_l2cap_le_listen(socket_fd, max_pending_connections));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code),
+ error_code);
+ }
+
+ return error_code;
+}
+
+int bt_socket_accept_l2cap_channel(int socket_fd)
+{
+ int error_code = BT_ERROR_NONE;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+
+ error_code = _bt_get_error_code(bluetooth_l2cap_le_accept_connection(socket_fd));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code),
+ error_code);
+ }
+
+ return error_code;
+}
+
+int bt_socket_reject_l2cap_channel(int socket_fd)
+{
+ int error_code = BT_ERROR_NONE;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+
+ error_code = _bt_get_error_code(bluetooth_l2cap_le_reject_connection(socket_fd));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code),
+ error_code);
+ }
+
+ return error_code;
+}
+/* LCOV_EXCL_STOP */
+
+int bt_socket_connect_l2cap_channel(const char *remote_address, int psm)
+{
+ bluetooth_device_address_t addr_hex = { {0,} };
+ int error_code = BT_ERROR_NONE;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS(); /* LCOV_EXCL_START */
+ BT_CHECK_INPUT_PARAMETER(remote_address);
+
+ _bt_convert_address_to_hex(&addr_hex, remote_address);
+
+ error_code = _bt_get_error_code(bluetooth_l2cap_le_connect(&addr_hex, psm));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code),
+ error_code);
+ }
+
+ return error_code; /* LCOV_EXCL_STOP */
+}
+
+int bt_socket_disconnect_l2cap_channel(int socket_fd)
+{
+ int error_code = BT_ERROR_NONE;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS(); /* LCOV_EXCL_START */
+
+ error_code = _bt_get_error_code(bluetooth_l2cap_le_disconnect(socket_fd));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code),
+ error_code);
+ }
+
+ return error_code; /* LCOV_EXCL_STOP */
+}
+
+int bt_socket_send_data_l2cap_channel(int socket_fd, const char *data,
+ int length)
+{
+ int ret = 0;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS(); /* LCOV_EXCL_START */
+ BT_CHECK_INPUT_PARAMETER(data);
+
+ ret = bluetooth_l2cap_le_write(socket_fd, data, length);
+ if (ret <= 0) {
+ if (ret == -1) {
+ /* write fail case */
+ if (errno == EACCES || errno == EPERM) {
+ set_last_result(BT_ERROR_PERMISSION_DENIED);
+ BT_ERR("PERMISSION_DENIED, errno = %d", errno);
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ set_last_result(BT_ERROR_AGAIN);
+ BT_ERR("BT_ERROR_AGAIN, errno = %d", errno);
+ } else {
+ set_last_result(BT_ERROR_OPERATION_FAILED);
+ BT_ERR("BT_ERROR_OPERATION_FAILED, errno = %d", errno);
+ }
+ } else {
+ ret = _bt_get_error_code(ret);
+ set_last_result(ret);
+ BT_ERR("Write failed, ret = %d", ret);
+ }
+ }
+
+ return ret; /* LCOV_EXCL_STOP */
+}
+
+int bt_socket_get_l2cap_psm(int socket_fd, int *psm)
+{
+ int ret = 0;
+
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS(); /* LCOV_EXCL_START */
+
+ ret = bluetooth_l2cap_le_get_psm(socket_fd, psm);
+ if (ret < 0) {
+ ret = _bt_get_error_code(ret);
+ BT_ERR("Get PSM failed, ret = %d", ret);
+ }
+
+ return ret; /* LCOV_EXCL_STOP */
+}
+
+int bt_socket_set_l2cap_channel_connection_state_changed_cb(
+ bt_socket_l2cap_channel_connection_state_changed_cb callback, void *user_data)
+{
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(callback);
+ _bt_set_cb(BT_EVENT_L2CAP_CHANNEL_CONNECTION_STATE_CHANGED, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+int bt_socket_unset_l2cap_channel_connection_state_changed_cb(void)
+{
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+ _bt_unset_cb(BT_EVENT_L2CAP_CHANNEL_CONNECTION_STATE_CHANGED);
+ return BT_ERROR_NONE;
+}
+
+int bt_socket_set_l2cap_channel_connection_requested_cb(
+ bt_socket_connection_requested_cb callback, void *user_data)
+{
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(callback);
+ _bt_set_cb(BT_EVENT_L2CAP_CHANNEL_CONNECTION_REQUESTED, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+int bt_socket_unset_l2cap_channel_connection_requested_cb(void)
+{
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON);
+ BT_CHECK_INIT_STATUS();
+ _bt_unset_cb(BT_EVENT_L2CAP_CHANNEL_CONNECTION_REQUESTED);
+ return BT_ERROR_NONE;
+}
+