LE CoC: Implement CAPIs 65/272065/2
authorAyush Garg <ayush.garg@samsung.com>
Mon, 7 Mar 2022 11:50:54 +0000 (17:20 +0530)
committerAyush Garg <ayush.garg@samsung.com>
Tue, 8 Mar 2022 09:32:24 +0000 (15:02 +0530)
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

Change-Id: I6ac0595799602db1402778da3f73109366a013c2
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
include/bluetooth_internal.h
include/bluetooth_private.h
include/bluetooth_type_internal.h
src/bluetooth-common.c
src/bluetooth-socket.c

index cd3e8230cdf96bdd6a4ce1ea0262c6be452fb068..a2a18e0074fa837c0568c66a34a3cae1e75aa3cd 100644 (file)
@@ -5442,6 +5442,87 @@ int bt_mesh_model_get_publication(bt_mesh_model_h model,
                bt_mesh_model_publication_status_cb callback,
                        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);
+
 /**
  * @}
  */
index b925e02f5f90a6f9c607160252110548dba28833..840b3d78ae37fc530561c32228108459ab5fade4 100644 (file)
@@ -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;
 
@@ -1306,6 +1308,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
index d55a748848e64c59f049dfefd9cb1212d8ad3f5c..254bd0ff8f349f23bbd3bde57caaaf1f0dc6b3d7 100644 (file)
@@ -1687,6 +1687,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 */
index b3f328f8d482a038e13f8a25e51698124332d9ef..da623f9ab35811eeab49b61ca4863672c6accde5 100644 (file)
@@ -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;
@@ -4287,7 +4295,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;
index 3973b7f6e5ecacfa557f0b1d09b9cd591e0f8116..26bf4fd5982075a41afcf6d5429567446af716bf 100644 (file)
@@ -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;
+}
+