diff options
author | Ayush Garg <ayush.garg@samsung.com> | 2022-03-07 17:20:54 +0530 |
---|---|---|
committer | Anuj Jain <anuj01.jain@samsung.com> | 2023-09-27 14:50:58 +0530 |
commit | 1afb39a4bd5152ccf5f7d37b025fc220e24653cf (patch) | |
tree | dc98030d9b337b9dacd07cf3820944949ff3efc4 | |
parent | 2c542bf2630350016971160e2095d6ebb35c8e12 (diff) | |
download | bluetooth-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.h | 81 | ||||
-rw-r--r-- | include/bluetooth_private.h | 274 | ||||
-rw-r--r-- | include/bluetooth_type_internal.h | 34 | ||||
-rw-r--r-- | src/bluetooth-common.c | 79 | ||||
-rw-r--r-- | src/bluetooth-socket.c | 233 |
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; +} + |