From 41a71a103c64fb62bcba8aa91d4f174947b3bd51 Mon Sep 17 00:00:00 2001 From: Abhijit RD Date: Fri, 22 Nov 2013 15:20:55 +0530 Subject: [PATCH] PHDC P2P Handling Added client and server side PHDC implementation for P2P mode Change-Id: Ieec9ccbf4d962bfdff4a2a42a1e421e9e195877e Signed-off-by: Abhijit R D --- client/include/net_nfc.h | 2 +- client/include/net_nfc_client_phdc.h | 75 +++ client/net_nfc_client.c | 4 + client/net_nfc_client_phdc.c | 388 +++++++++++++++ common/include/net_nfc_typedef.h | 13 +- common/net_nfc.xml | 61 +++ daemon/net_nfc_server.c | 9 +- daemon/net_nfc_server_phdc.c | 675 ++++++++++++++++++++++++++ daemon/net_nfc_server_phdc.h | 35 ++ daemon/net_nfc_server_process_phdc.c | 912 +++++++++++++++++++++++++++++++++++ daemon/net_nfc_server_process_phdc.h | 69 +++ 11 files changed, 2240 insertions(+), 3 deletions(-) create mode 100755 client/include/net_nfc_client_phdc.h create mode 100755 client/net_nfc_client_phdc.c create mode 100755 daemon/net_nfc_server_phdc.c create mode 100755 daemon/net_nfc_server_phdc.h create mode 100755 daemon/net_nfc_server_process_phdc.c create mode 100755 daemon/net_nfc_server_process_phdc.h diff --git a/client/include/net_nfc.h b/client/include/net_nfc.h index 51183ae..6dd4834 100644 --- a/client/include/net_nfc.h +++ b/client/include/net_nfc.h @@ -28,7 +28,7 @@ extern "C" { #include "net_nfc_ndef_record.h" #include "net_nfc_sign_record.h" #include "net_nfc_ndef_message_handover.h" - +#include "net_nfc_client_phdc.h" #include "net_nfc_client_context.h" #include "net_nfc_client_manager.h" #include "net_nfc_client_system_handler.h" diff --git a/client/include/net_nfc_client_phdc.h b/client/include/net_nfc_client_phdc.h new file mode 100755 index 0000000..d88ba2a --- /dev/null +++ b/client/include/net_nfc_client_phdc.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __NET_NFC_CLIENT_PHDC_H__ +#define __NET_NFC_CLIENT_PHDC_H__ + +#include "net_nfc_typedef.h" + +/* PHDC callbacks */ + +typedef void (*net_nfc_client_phdc_send_completed)(net_nfc_error_e result, + void *user_data); + +typedef void (*net_nfc_client_phdc_transport_connect_indication)( + net_nfc_phdc_handle_h handle_info,void *user_data); + +typedef void (*net_nfc_client_phdc_transport_disconnect_indication)(void *user_data); + +typedef void (*net_nfc_client_phdc_data_received)(data_s *phdc_data, + void *user_data); + +typedef void (*net_nfc_client_phdc_event_cb)( net_nfc_error_e result, + net_nfc_llcp_state_t event, void *user_data); + +/* PHDC client API's*/ +net_nfc_error_e net_nfc_client_phdc_send(net_nfc_phdc_handle_h handle, + data_s *data, net_nfc_client_phdc_send_completed callback, void *user_data); + +net_nfc_error_e net_nfc_client_phdc_send_sync(net_nfc_phdc_handle_h handle, + data_s *data); + +/* PHDC client API's - used for registering callbacks*/ +void net_nfc_client_phdc_set_transport_connect_indication( + net_nfc_client_phdc_transport_connect_indication callback, void *user_data); + +void net_nfc_client_phdc_set_transport_disconnect_indication( + net_nfc_client_phdc_transport_disconnect_indication callback, void *user_data); + +void net_nfc_client_phdc_set_data_received( + net_nfc_client_phdc_data_received callback, void *user_data); + +net_nfc_error_e net_nfc_client_phdc_register(net_nfc_phdc_role_e role, + const char *san,net_nfc_client_phdc_event_cb callback, void *user_data); + +net_nfc_error_e net_nfc_client_phdc_unregister( net_nfc_phdc_role_e role, + const char *san); + + +/* PHDC client API's - used for unregistering callbacks*/ +void net_nfc_client_phdc_unset_transport_connect_indication(void); + +void net_nfc_client_phdc_unset_transport_disconnect_indication(void); + +void net_nfc_client_phdc_unset_data_received(void); + +/* Init/Deint function calls*/ +net_nfc_error_e net_nfc_client_phdc_init(void); + +void net_nfc_client_phdc_deinit(void); + +#endif //__NET_NFC_CLIENT_PHDC_H__ + + diff --git a/client/net_nfc_client.c b/client/net_nfc_client.c index 64d5be7..6118ba0 100644 --- a/client/net_nfc_client.c +++ b/client/net_nfc_client.c @@ -31,6 +31,7 @@ #include "net_nfc_client_llcp.h" #include "net_nfc_client_snep.h" #include "net_nfc_client_p2p.h" +#include "net_nfc_client_phdc.h" #include "net_nfc_client_system_handler.h" #include "net_nfc_client_handover.h" @@ -97,6 +98,8 @@ void net_nfc_client_gdbus_init(void) return; if(net_nfc_client_handover_init() != NET_NFC_OK) return; + if(net_nfc_client_phdc_init() != NET_NFC_OK) + return; } void net_nfc_client_gdbus_deinit(void) @@ -110,6 +113,7 @@ void net_nfc_client_gdbus_deinit(void) net_nfc_client_transceive_deinit(); net_nfc_client_ndef_deinit(); net_nfc_client_tag_deinit(); + net_nfc_client_phdc_deinit(); net_nfc_client_manager_deinit(); #ifdef SECURITY_SERVER _deinit_smack(); diff --git a/client/net_nfc_client_phdc.c b/client/net_nfc_client_phdc.c new file mode 100755 index 0000000..09c50cb --- /dev/null +++ b/client/net_nfc_client_phdc.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "net_nfc_typedef_internal.h" +#include "net_nfc_debug_internal.h" +#include "net_nfc_util_internal.h" +#include "net_nfc_util_ndef_message.h" +#include "net_nfc_util_gdbus_internal.h" +#include "net_nfc_gdbus.h" +#include "net_nfc_client.h" +#include "net_nfc_client_manager.h" +#include "net_nfc_client_phdc.h" + +typedef struct _Phdc_SignalHandler PhdcSignalHandler; + +static NetNfcGDbusPhdc *phdc_proxy = NULL; +static PhdcSignalHandler phdc_signal_handler; + +struct _Phdc_SignalHandler +{ + net_nfc_client_phdc_transport_connect_indication phdc_transport_connect_indication_cb; + net_nfc_client_phdc_transport_disconnect_indication phdc_transport_disconnect_indication_cb; + net_nfc_client_phdc_data_received phdc_data_received_cb; + + gpointer phdc_transport_connect_indication_data; + gpointer phdc_transport_disconnect_indication_data; + gpointer phdc_data_received_data; +}; + + +static void _phdc_event_cb(NetNfcGDbusPhdc *object, gint arg_result, + guint arg_event,guint arg_user_data) +{ + GVariant *parameter = (GVariant *)GUINT_TO_POINTER(arg_user_data); + + NFC_DBG(" result [%d], event [%d], user_data [%p]", + arg_result, arg_event, parameter); + + if (parameter != NULL) + { + void *user_data; + net_nfc_client_phdc_event_cb callback; + + g_variant_get(parameter, "(uu)", + (guint *)&callback, + (guint *)&user_data); + + if (callback != NULL) + { + callback( arg_result, arg_event, user_data); + } + } + + if (arg_event == NET_NFC_LLCP_UNREGISTERED) + { + g_variant_unref(parameter); + } + +} + + +static void phdc_transport_disconnect_indication(GObject *source_object, gpointer user_data) +{ + NFC_INFO(">>> SIGNAL arrived"); + + RET_IF(NULL == phdc_signal_handler.phdc_transport_disconnect_indication_cb); + + phdc_signal_handler.phdc_transport_disconnect_indication_cb( + phdc_signal_handler.phdc_transport_disconnect_indication_data); +} + +static void phdc_transport_connect_indication(GObject *source_object, + guint arg_handle, gpointer user_data) +{ + net_nfc_phdc_handle_h handle_info = NULL; + + NFC_INFO(">>> SIGNAL arrived"); + + handle_info = GUINT_TO_POINTER(arg_handle); + + RET_IF(NULL == phdc_signal_handler.phdc_transport_connect_indication_cb); + + phdc_signal_handler.phdc_transport_connect_indication_cb(handle_info, + phdc_signal_handler.phdc_transport_connect_indication_data); +} + +static void phdc_call_send(GObject *source_object,GAsyncResult *res, gpointer user_data) +{ + gboolean ret; + GVariant *parameter = (GVariant *)user_data; + GError *error = NULL; + net_nfc_error_e out_result; + net_nfc_client_phdc_send_completed callback; + net_nfc_phdc_handle_h handle; + void *user_param; + + NFC_INFO(">>> phdc_call_send \n"); + + ret = net_nfc_gdbus_phdc_call_send_finish(NET_NFC_GDBUS_PHDC(source_object), + (gint *)&out_result, res, &error); + + if (FALSE == ret) + { + out_result = NET_NFC_IPC_FAIL; + + NFC_ERR("Can not finish phdc send: %s", error->message); + g_error_free(error); + } + + g_variant_get(parameter, "(uuu)", + (guint *)&callback, + (guint *)&user_param, + (guint *)&handle); + + NFC_INFO(">>> phdc_call_send %p\n", handle); + + if (callback != NULL) + { + callback( out_result, user_param); + } + + g_variant_unref(parameter); +} + +static void phdc_device_data_received(GObject *source_object,GVariant *arg_data, + gpointer user_data) +{ + data_s phdc_data = { NULL, }; + + NFC_INFO(">>> SIGNAL arrived"); + + RET_IF(NULL == phdc_signal_handler.phdc_data_received_cb); + + net_nfc_util_gdbus_variant_to_data_s(arg_data, &phdc_data); + phdc_signal_handler.phdc_data_received_cb(&phdc_data, + phdc_signal_handler.phdc_data_received_data); + + net_nfc_util_free_data(&phdc_data); +} + +API net_nfc_error_e net_nfc_client_phdc_send(net_nfc_phdc_handle_h handle, + data_s *data, net_nfc_client_phdc_send_completed callback, void *user_data) +{ + GVariant *arg_data; + GVariant *parameter; + + NFC_INFO(">>> net_nfc_client_phdc_send \n"); + + RETV_IF(NULL == phdc_proxy, NET_NFC_NOT_INITIALIZED); + + /* prevent executing daemon when nfc is off */ + RETV_IF(net_nfc_client_manager_is_activated() == false, NET_NFC_INVALID_STATE); + + parameter = g_variant_new("(uuu)", + GPOINTER_TO_UINT(callback), + GPOINTER_TO_UINT(user_data), + GPOINTER_TO_UINT(handle)); + + + arg_data = net_nfc_util_gdbus_data_to_variant(data); + + net_nfc_gdbus_phdc_call_send(phdc_proxy, + GPOINTER_TO_UINT(handle), + arg_data, + net_nfc_client_gdbus_get_privilege(), + NULL, + phdc_call_send, + parameter); + + return NET_NFC_OK; +} + + +API net_nfc_error_e net_nfc_client_phdc_send_sync(net_nfc_phdc_handle_h handle, + data_s *data) +{ + gboolean ret; + GVariant *arg_data; + GError *error = NULL; + + net_nfc_error_e out_result; + + RETV_IF(NULL == phdc_proxy, NET_NFC_NOT_INITIALIZED); + + /* prevent executing daemon when nfc is off */ + RETV_IF(net_nfc_client_manager_is_activated() == false, NET_NFC_INVALID_STATE); + + arg_data = net_nfc_util_gdbus_data_to_variant(data); + + ret = net_nfc_gdbus_phdc_call_send_sync(phdc_proxy, + GPOINTER_TO_UINT(handle), + arg_data, + net_nfc_client_gdbus_get_privilege(), + (gint *)&out_result, + NULL, + &error); + + if(FALSE == ret) + { + NFC_ERR("phdc send (sync call) failed: %s", error->message); + + g_error_free(error); + out_result = NET_NFC_IPC_FAIL; + } + + return out_result; +} + +API net_nfc_error_e net_nfc_client_phdc_register(net_nfc_phdc_role_e role, + const char *san,net_nfc_client_phdc_event_cb callback, void *user_data) +{ + GError *error = NULL; + GVariant *parameter; + net_nfc_error_e result = NET_NFC_OK; + + RETV_IF(NULL == phdc_proxy, NET_NFC_NOT_INITIALIZED); + + /* prevent executing daemon when nfc is off */ + RETV_IF(net_nfc_client_manager_is_activated() == false, NET_NFC_INVALID_STATE); + + parameter = g_variant_new("(uu)", + GPOINTER_TO_UINT(callback), + GPOINTER_TO_UINT(user_data)); + + if (net_nfc_gdbus_phdc_call_register_role_sync(phdc_proxy, + role, + san, + GPOINTER_TO_UINT(parameter), + net_nfc_client_gdbus_get_privilege(), + (gint *)&result, + NULL, + &error) == FALSE) + { + NFC_ERR("phdc register role(sync call) failed: %s", error->message); + g_error_free(error); + result = NET_NFC_IPC_FAIL; + g_variant_unref(parameter); + } + + return result; +} + +API net_nfc_error_e net_nfc_client_phdc_unregister( net_nfc_phdc_role_e role, + const char *san) +{ + GError *error = NULL; + net_nfc_error_e result = NET_NFC_OK; + + RETV_IF(NULL == phdc_proxy, NET_NFC_NOT_INITIALIZED); + + /* prevent executing daemon when nfc is off */ + RETV_IF(net_nfc_client_manager_is_activated() == false, NET_NFC_INVALID_STATE); + + if (net_nfc_gdbus_phdc_call_unregister_role_sync(phdc_proxy, + role, + san, + net_nfc_client_gdbus_get_privilege(), + (gint *)&result, + NULL, + &error) == FALSE) + { + NFC_ERR("phdc unregister role(sync call) failed: %s", error->message); + g_error_free(error); + + result = NET_NFC_IPC_FAIL; + } + + return result; +} + + +API void net_nfc_client_phdc_set_transport_connect_indication( + net_nfc_client_phdc_transport_connect_indication callback, void *user_data) +{ + RET_IF(NULL == callback); + + phdc_signal_handler.phdc_transport_connect_indication_cb = callback; + phdc_signal_handler.phdc_transport_connect_indication_data = user_data; +} + +API void net_nfc_client_phdc_set_transport_disconnect_indication( + net_nfc_client_phdc_transport_disconnect_indication callback, void *user_data) +{ + RET_IF(NULL == callback); + + phdc_signal_handler.phdc_transport_disconnect_indication_cb = callback; + phdc_signal_handler.phdc_transport_disconnect_indication_data = user_data; +} + +API void net_nfc_client_phdc_set_data_received( + net_nfc_client_phdc_data_received callback, void *user_data) +{ + RET_IF(NULL == callback); + + phdc_signal_handler.phdc_data_received_cb = callback; + phdc_signal_handler.phdc_data_received_data = user_data; +} + +API void net_nfc_client_phdc_unset_transport_connect_indication(void) +{ + phdc_signal_handler.phdc_transport_connect_indication_cb = NULL; + phdc_signal_handler.phdc_transport_connect_indication_data= NULL; +} + + +API void net_nfc_client_phdc_unset_transport_disconnect_indication(void) +{ + phdc_signal_handler.phdc_transport_disconnect_indication_cb = NULL; + phdc_signal_handler.phdc_transport_disconnect_indication_data = NULL; +} + +API void net_nfc_client_phdc_unset_data_received(void) +{ + phdc_signal_handler.phdc_data_received_cb = NULL; + phdc_signal_handler.phdc_data_received_data = NULL; +} + +net_nfc_error_e net_nfc_client_phdc_init(void) +{ + GError *error = NULL; + + if (phdc_proxy) + { + NFC_WARN("Already initialized"); + return NET_NFC_OK; + } + + phdc_proxy = net_nfc_gdbus_phdc_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.tizen.NetNfcService", + "/org/tizen/NetNfcService/Phdc", + NULL, + &error); + if (NULL == phdc_proxy) + { + NFC_ERR("Can not create proxy : %s", error->message); + g_error_free(error); + + return NET_NFC_UNKNOWN_ERROR; + } + + net_nfc_client_phdc_unset_transport_connect_indication(); + net_nfc_client_phdc_unset_transport_disconnect_indication(); + net_nfc_client_phdc_unset_data_received(); + + g_signal_connect(phdc_proxy, "phdc_connect", + G_CALLBACK(phdc_transport_connect_indication), NULL); + + g_signal_connect(phdc_proxy, "phdc_disconnect", + G_CALLBACK(phdc_transport_disconnect_indication), NULL); + + g_signal_connect(phdc_proxy, "phdc_received", + G_CALLBACK(phdc_device_data_received), NULL); + + g_signal_connect(phdc_proxy, "phdc-event", G_CALLBACK(_phdc_event_cb), NULL); + + + return NET_NFC_OK; +} + +void net_nfc_client_phdc_deinit(void) +{ + if (phdc_proxy) + { + g_object_unref(phdc_proxy); + phdc_proxy = NULL; + } + + net_nfc_client_phdc_unset_transport_connect_indication(); + net_nfc_client_phdc_unset_transport_disconnect_indication(); + net_nfc_client_phdc_unset_data_received(); + +} + diff --git a/common/include/net_nfc_typedef.h b/common/include/net_nfc_typedef.h index 1032360..f82fd62 100644 --- a/common/include/net_nfc_typedef.h +++ b/common/include/net_nfc_typedef.h @@ -390,9 +390,17 @@ typedef enum NET_NFC_CONN_HANDOVER_CARRIER_UNKNOWN, } net_nfc_conn_handover_carrier_type_e; +typedef enum +{ + NET_NFC_PHDC_UNKNOWN = 0x00, + NET_NFC_PHDC_MANAGER , + NET_NFC_PHDC_AGENT, +} net_nfc_phdc_role_e; + + /** This structure is just data, to express bytes array - */ + */ typedef struct { uint8_t *buffer; @@ -482,6 +490,9 @@ typedef uint32_t net_nfc_llcp_socket_t; typedef void *net_nfc_snep_handle_h; +typedef void *net_nfc_phdc_handle_h; + + // LLCP Callback typedef void (*net_nfc_llcp_socket_cb)(net_nfc_llcp_message_e message, net_nfc_error_e result, void *data, void *user_data, void *trans_data); diff --git a/common/net_nfc.xml b/common/net_nfc.xml index bd2d851..b913b6b 100644 --- a/common/net_nfc.xml +++ b/common/net_nfc.xml @@ -586,4 +586,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/daemon/net_nfc_server.c b/daemon/net_nfc_server.c index d5555c5..e6448fb 100644 --- a/daemon/net_nfc_server.c +++ b/daemon/net_nfc_server.c @@ -22,6 +22,7 @@ #include "net_nfc_gdbus.h" #include "net_nfc_server.h" #include "net_nfc_server_common.h" +#include "net_nfc_server_phdc.h" #include "net_nfc_server_vconf.h" #include "net_nfc_server_manager.h" #include "net_nfc_server_util.h" @@ -216,6 +217,12 @@ static void net_nfc_server_gdbus_init(void) return; } + if (net_nfc_server_phdc_init(connection) == FALSE) + { + NFC_ERR("Can not init phdc"); + return; + } + if (net_nfc_server_controller_thread_init() == FALSE) { NFC_ERR("Can not init controller thread"); @@ -238,7 +245,7 @@ static void net_nfc_server_gdbus_deinit(void) net_nfc_server_se_deinit(); net_nfc_server_snep_deinit(); net_nfc_server_system_handler_deinit(); - + net_nfc_server_phdc_deinit(); net_nfc_server_gdbus_deinit_client_context(); net_nfc_server_controller_thread_deinit(); diff --git a/daemon/net_nfc_server_phdc.c b/daemon/net_nfc_server_phdc.c new file mode 100755 index 0000000..91f33f2 --- /dev/null +++ b/daemon/net_nfc_server_phdc.c @@ -0,0 +1,675 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "net_nfc_debug_internal.h" +#include "net_nfc_util_internal.h" +#include "net_nfc_util_gdbus_internal.h" +#include "net_nfc_server_controller.h" +#include "net_nfc_gdbus.h" +#include "net_nfc_server_common.h" +#include "net_nfc_server_tag.h" +#include "net_nfc_server_context.h" +#include "net_nfc_server_process_phdc.h" +#include "net_nfc_server_phdc.h" +#include "net_nfc_server_llcp.h" + +typedef struct _PhdcSendData PhdcSendData; + +struct _PhdcSendData +{ + NetNfcGDbusPhdc *phdc; + GDBusMethodInvocation *invocation; + guint32 phdc_handle; + data_s data; +}; + +static NetNfcGDbusPhdc *phdc_skeleton = NULL; + + +static gboolean _phdc_send_request_cb_(net_nfc_phdc_handle_h handle, + net_nfc_error_e result, net_nfc_server_phdc_indication_type indication, + gpointer *user_data) +{ + + NFC_DBG("phdc_send_request_cb_result [%d]",result); + + GVariant *parameter = (GVariant *)user_data; + + g_assert(parameter != NULL); + + NetNfcGDbusPhdc *object; + GDBusMethodInvocation *invocation; + net_nfc_phdc_handle_h phdc_handle; + GVariant *phdc_data ; + + g_variant_get(parameter, + "(uuu@a(y))", + (guint *)&object, + (guint *)&invocation, + (guint *)&phdc_handle, + (guint *)&phdc_data); + + net_nfc_gdbus_phdc_complete_send(object, invocation, (gint)result); + + g_variant_unref(phdc_data); + g_object_unref(invocation); + g_object_unref(object); + g_variant_unref(parameter); + + result = NET_NFC_OK; + return result; + +} + +static void phdc_send_data_thread_func(gpointer user_data) +{ + NetNfcGDbusPhdc *object; + GDBusMethodInvocation *invocation; + net_nfc_error_e result; + net_nfc_phdc_handle_h handle = NULL; + GVariant *phdc_data; + data_s data = { NULL, }; + + if (NULL == user_data) + { + NFC_ERR("cannot get PHDC client data"); + return; + } + + NFC_DBG(">>> phdc_send_data_thread_func"); + + g_variant_get((GVariant *)user_data, + "(uuu@a(y))", + (guint *)&object, + (guint *)&invocation, + (guint *)&handle, + &phdc_data); + + g_assert(object != NULL); + g_assert(invocation != NULL); + + net_nfc_util_gdbus_variant_to_data_s(phdc_data, &data); + + result = net_nfc_server_phdc_agent_request(handle, &data, + _phdc_send_request_cb_, user_data); + + if (result != NET_NFC_OK) + { + net_nfc_gdbus_phdc_complete_send(object, invocation, (gint)result); + + g_object_unref(invocation); + g_object_unref(object); + g_variant_unref(user_data); + } + + g_variant_unref(phdc_data); +} + +static gboolean phdc_handle_send(NetNfcGDbusPhdc *phdc, + GDBusMethodInvocation *invocation, //object for handling remote calls,provides a way to asynly return data + guint handle, + GVariant* user_data, + GVariant *smack_privilege) +{ + bool ret; + gboolean result; + GVariant *parameter = NULL; + + NFC_INFO(">>> REQUEST from [%s]",g_dbus_method_invocation_get_sender(invocation)); + + /* check privilege and update client context */ + ret = net_nfc_server_gdbus_check_privilege(invocation, smack_privilege, + "nfc-manager::p2p", "w"); + + if(FALSE == ret) + { + NFC_ERR("permission denied, and finished request"); + result = NET_NFC_SECURITY_FAIL; + goto ERROR; + } + + parameter = g_variant_new("(uuu@a(y))", + GPOINTER_TO_UINT(g_object_ref(phdc)), + GPOINTER_TO_UINT(g_object_ref(invocation)), + handle, + user_data); + + if (NULL == parameter) + { + NFC_ERR("Memory allocation failed"); + result = NET_NFC_ALLOC_FAIL; + + goto ERROR; + } + + result = net_nfc_server_controller_async_queue_push(phdc_send_data_thread_func, parameter); + + if (FALSE == result) + { + /* return error if queue was blocked */ + NFC_ERR("controller is processing important message.."); + result = NET_NFC_BUSY; + + goto ERROR; + + } + + return TRUE; + + ERROR : + + if (parameter != NULL) + { + g_object_unref(invocation); + g_object_unref(phdc); + g_variant_unref(parameter); + } + + net_nfc_gdbus_phdc_complete_send(phdc, invocation, result); + return TRUE; +} + +void net_nfc_server_phdc_data_received_indication(data_s *arg_data) +{ + NFC_INFO("=net_nfc_server_phdc_transport_data_received_indication="); + + GVariant *data; + data = net_nfc_util_gdbus_data_to_variant(arg_data); + + if (NULL == phdc_skeleton) + { + NFC_ERR("phdc_skeleton is not initialized"); + return; + } + + net_nfc_gdbus_phdc_emit_phdc_received(phdc_skeleton, data); +} + +static void _emit_phdc_event_signal(GVariant *parameter, + net_nfc_phdc_handle_h handle, net_nfc_error_e result, uint32_t type) +{ + gboolean ret; + char *client_id = NULL; + void *user_data = NULL; + GError *error = NULL; + GDBusConnection *connection; + + g_variant_get(parameter, "(usu)", (guint *)&connection, &client_id, + (guint *)&user_data); + + ret = g_dbus_connection_emit_signal( + connection, + client_id, + "/org/tizen/NetNfcService/Phdc", + "org.tizen.NetNfcService.Phdc", + "PhdcEvent", + g_variant_new("(iuu)", (gint)result, type, + GPOINTER_TO_UINT(user_data)), &error); + + if (FALSE == ret) + { + if (error != NULL && error->message != NULL) + NFC_ERR("g_dbus_connection_emit_signal failed : %s", error->message); + else + NFC_ERR("g_dbus_connection_emit_signal failed"); + } + + g_free(client_id); +} + +static void _server_phdc_agent_cb_(net_nfc_phdc_handle_h handle, + net_nfc_error_e result, net_nfc_server_phdc_indication_type indication, data_s *data) +{ + if(NET_NFC_OK != result) + { + net_nfc_server_phdc_transport_disconnect_indication(); + return; + } + + RET_IF(NULL == handle); + + NFC_DBG(" handle [%p], result[%d]", handle, result); + + if( NET_NFC_PHDC_TARGET_CONNECTED == indication) + net_nfc_server_phdc_transport_connect_indication(handle); + else if(NET_NFC_PHDC_DATA_RECEIVED == indication) + net_nfc_server_phdc_data_received_indication(data); + + return; +} + + +static void _phdc_agent_activate_cb(int event, net_nfc_target_handle_s *handle, + uint32_t sap, const char *san, void *user_param) +{ + net_nfc_error_e result = NET_NFC_OK; + GVariant *parameter = (GVariant *)user_param; + char *client_id = NULL; + void *user_data = NULL; + GVariant *param = NULL; + GDBusConnection *connection = NULL; + + NFC_DBG("event [%d], handle [%p], sap [%d], san [%s]", event, handle, sap, san); + + if (NET_NFC_LLCP_START == event) + { + g_variant_get(parameter, "(usu)", (guint *)&connection, &client_id, (guint *)&user_data); + + param = g_variant_new("(usu)", GPOINTER_TO_UINT(g_object_ref(connection)),client_id, + GPOINTER_TO_UINT(user_data)); + + g_free(client_id); + + /* start phdc agent service*/ + result = net_nfc_server_phdc_agent_start(handle, (char *)san, sap, + _server_phdc_agent_cb_, param); + + if (NET_NFC_OK == result) + { + _emit_phdc_event_signal(parameter, handle, result, event); + } + else + { + NFC_ERR("net_nfc_server_phdc_manager_start failed, [%d]", result); + g_variant_unref(param); + } + } + else + { + _emit_phdc_event_signal(parameter, handle, result, NET_NFC_LLCP_UNREGISTERED); + /* unregister server */ + g_variant_unref(parameter); + } + +} + +static void _server_phdc_manager_cb_(net_nfc_phdc_handle_h handle, + net_nfc_error_e result, net_nfc_server_phdc_indication_type indication, data_s *data) +{ + + if(NET_NFC_OK != result) + { + net_nfc_server_phdc_transport_disconnect_indication(); + return; + } + + RET_IF(NULL == handle); + + NFC_DBG("result [%d], data [%p]", result, data); + + if( NET_NFC_PHDC_TARGET_CONNECTED == indication) + net_nfc_server_phdc_transport_connect_indication(handle); + else if(NET_NFC_PHDC_DATA_RECEIVED == indication) + net_nfc_server_phdc_data_received_indication(data); + + return ; +} + + +static void _phdc_manager_activate_cb(int event, net_nfc_target_handle_s *handle, + uint32_t sap, const char *san, void *user_param) +{ + net_nfc_error_e result = NET_NFC_OK; + GVariant *parameter = (GVariant *)user_param; + char *client_id = NULL; + void *user_data = NULL; + GVariant *param = NULL; + GDBusConnection *connection = NULL; + + NFC_DBG("event [%d], handle [%p], sap [%d], san [%s]", event, handle, sap, san); + + if (NET_NFC_LLCP_START == event) + { + g_variant_get(parameter, "(usu)", (guint *)&connection, &client_id, (guint *)&user_data); + + param = g_variant_new("(usu)", GPOINTER_TO_UINT(g_object_ref(connection)),client_id, + GPOINTER_TO_UINT(user_data)); + + g_free(client_id); + + /* start phdc manager service*/ + result = net_nfc_server_phdc_manager_start(handle, (char *)san, sap, + _server_phdc_manager_cb_, param); + + if (NET_NFC_OK == result) + { + _emit_phdc_event_signal(parameter, handle, result, event); + } + else + { + NFC_ERR("net_nfc_server_phdc_manager_start failed, [%d]", result); + g_variant_unref(param); + } + } + else + { + _emit_phdc_event_signal(parameter, handle, result, NET_NFC_LLCP_UNREGISTERED); + /* unregister server */ + g_variant_unref(parameter); + } + +} + +static void phdc_register_server_thread_func(gpointer user_data) +{ + gchar *arg_san = NULL; + guint arg_role; + guint arg_sap; + guint arg_user_data; + net_nfc_error_e result = NET_NFC_OK; + NetNfcGDbusPhdc *object = NULL; + g_assert(user_data != NULL); + GVariant *parameter = NULL; + GDBusConnection *connection = NULL; + GDBusMethodInvocation *invocation = NULL; + + g_variant_get((GVariant *)user_data, "(uuusu)", (guint *)&object, (guint *)&invocation, + &arg_role, &arg_san, &arg_user_data); + + g_assert(object != NULL); + g_assert(invocation != NULL); + + connection = g_dbus_method_invocation_get_connection(invocation); + + parameter = g_variant_new("(usu)", GPOINTER_TO_UINT(g_object_ref(connection)), + g_dbus_method_invocation_get_sender(invocation), arg_user_data); + + if (parameter != NULL) + { + if(!strcmp(arg_san,PHDC_SAN)) + { + arg_san = PHDC_SAN; + arg_sap = PHDC_SAP; + } + else if (!strcmp(arg_san,PHDS_SAN)) + { + arg_san = PHDS_SAN; + arg_sap = PHDS_SAP; + } + else + { + // anything else, as of now,defaulting to PHDC default server + arg_san = PHDC_SAN; + arg_sap = PHDC_SAP; + } + + if(NET_NFC_PHDC_MANAGER == arg_role) + { + result = net_nfc_server_llcp_register_service( + g_dbus_method_invocation_get_sender(invocation), arg_sap, + arg_san, _phdc_manager_activate_cb, parameter); + } + else if(NET_NFC_PHDC_AGENT == arg_role) + { + result = net_nfc_server_llcp_register_service( + g_dbus_method_invocation_get_sender(invocation), arg_sap, + arg_san, _phdc_agent_activate_cb, parameter); + } + + if (result != NET_NFC_OK) + { + NFC_ERR("net_nfc_service_llcp_register_service failed, [%d]", result); + g_object_unref(connection); + g_variant_unref(parameter); + } + } + else + { + result = NET_NFC_ALLOC_FAIL; + g_object_unref(connection); + } + + net_nfc_gdbus_phdc_complete_register_role(object, invocation, result); + + + g_variant_unref(user_data); + + +} + +static gboolean phdc_handle_register( + NetNfcGDbusPhdc *object, + GDBusMethodInvocation *invocation, + guint arg_role, + const gchar *arg_san, + guint arg_user_data, + GVariant *arg_privilege) +{ + bool ret; + gboolean result; + GVariant *parameter = NULL; + + NFC_INFO(">>> REQUEST from [%s]", g_dbus_method_invocation_get_sender(invocation)); + + /* check privilege and update client context */ + ret = net_nfc_server_gdbus_check_privilege(invocation, arg_privilege, + "nfc-manager::p2p", "rw"); + if (FALSE == ret) + { + NFC_ERR("permission denied, and finished request"); + result = NET_NFC_SECURITY_FAIL; + goto ERROR; + } + + parameter = g_variant_new("(uuusu)", GPOINTER_TO_UINT(g_object_ref(object)), + GPOINTER_TO_UINT(g_object_ref(invocation)), arg_role, arg_san, arg_user_data); + + if (parameter == NULL) + { + NFC_ERR("Memory allocation failed"); + result = NET_NFC_ALLOC_FAIL; + goto ERROR; + } + if(net_nfc_server_controller_async_queue_push( + phdc_register_server_thread_func, parameter) == FALSE) + { + NFC_ERR("controller is processing important message."); + result = NET_NFC_ALLOC_FAIL; + goto ERROR; + } + + return TRUE; + + ERROR : + if (parameter != NULL) + { + g_object_unref(invocation); + g_object_unref(object); + g_variant_unref(parameter); + } + + net_nfc_gdbus_phdc_complete_register_role(object, + invocation, + result); + + return TRUE; +} + +static void phdc_unregister_server_thread_func(gpointer user_data) +{ + guint arg_role; + guint arg_sap; + gchar *arg_san = NULL; + net_nfc_error_e result; + NetNfcGDbusSnep *object = NULL; + GDBusMethodInvocation *invocation = NULL; + + g_assert(user_data != NULL); + + g_variant_get((GVariant *)user_data, "(uuus)", (guint *)&object, (guint *)&invocation, + &arg_role, &arg_san); + + g_assert(object != NULL); + g_assert(invocation != NULL); + + if(!strcmp(arg_san,PHDS_SAN)) + arg_sap = PHDS_SAP; + else + arg_sap = PHDC_SAP; + + result = net_nfc_server_llcp_unregister_service( + g_dbus_method_invocation_get_sender(invocation), arg_sap, arg_san); + + net_nfc_gdbus_snep_complete_server_unregister(object, invocation, result); + + g_free(arg_san); + + g_object_unref(invocation); + g_object_unref(object); + + g_variant_unref(user_data); +} + +static gboolean phdc_handle_unregister( + NetNfcGDbusPhdc *object, + GDBusMethodInvocation *invocation, + guint arg_role, + const gchar *arg_san, + GVariant *arg_privilege) +{ + bool ret; + gboolean result; + GVariant *parameter = NULL; + + NFC_INFO(">>> REQUEST from [%s]", g_dbus_method_invocation_get_sender(invocation)); + + /* check privilege and update client context */ + ret = net_nfc_server_gdbus_check_privilege(invocation, arg_privilege, + "nfc-manager::p2p", "rw"); + + if (FALSE == ret) + { + NFC_ERR("permission denied, and finished request"); + result = NET_NFC_SECURITY_FAIL; + goto ERROR; + } + + parameter = g_variant_new("(uuus)", GPOINTER_TO_UINT(g_object_ref(object)), + GPOINTER_TO_UINT(g_object_ref(invocation)), arg_role, arg_san); + + if (parameter == NULL) + { + NFC_ERR("Memory allocation failed"); + result = NET_NFC_ALLOC_FAIL; + goto ERROR; + } + if(net_nfc_server_controller_async_queue_push( + phdc_unregister_server_thread_func, parameter) == FALSE) + { + NFC_ERR("controller is processing important message."); + result = NET_NFC_ALLOC_FAIL; + goto ERROR; + } + + return TRUE; + + ERROR : + if (parameter != NULL) + { + g_object_unref(invocation); + g_object_unref(object); + + g_variant_unref(parameter); + } + + net_nfc_gdbus_phdc_complete_register_role(object, + invocation, + result); + + return TRUE; +} + + +gboolean net_nfc_server_phdc_init(GDBusConnection *connection) +{ + gboolean result; + GError *error = NULL; + + if (phdc_skeleton) + net_nfc_server_phdc_deinit(); + + phdc_skeleton = net_nfc_gdbus_phdc_skeleton_new(); + + g_signal_connect(phdc_skeleton,"handle-send", G_CALLBACK(phdc_handle_send), NULL); + + g_signal_connect(phdc_skeleton,"handle-register-role", G_CALLBACK(phdc_handle_register), NULL); + + g_signal_connect(phdc_skeleton,"handle-unregister-role", G_CALLBACK(phdc_handle_unregister), NULL); + + result = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(phdc_skeleton), + connection, "/org/tizen/NetNfcService/Phdc", &error); + + if (FALSE == result) + { + g_error_free(error); + net_nfc_server_phdc_deinit(); + } + + return result; +} + +void net_nfc_server_phdc_deinit(void) +{ + if (phdc_skeleton) + { + g_object_unref(phdc_skeleton); + phdc_skeleton = NULL; + } +} + +void net_nfc_server_phdc_transport_disconnect_indication(void) +{ + NFC_INFO("====== phdc target disconnected ======"); + + /* release target information */ + net_nfc_server_free_target_info(); + + if (phdc_skeleton != NULL) + net_nfc_gdbus_phdc_emit_phdc_disconnect(phdc_skeleton); +} + + +void net_nfc_server_phdc_transport_connect_indication(net_nfc_phdc_handle_h handle) +{ + NFC_INFO("====== phdc target connected ======"); + + if (NULL == phdc_skeleton) + { + NFC_ERR("phdc_skeleton is not initialized"); + return; + } + + net_nfc_gdbus_phdc_emit_phdc_connect(phdc_skeleton, GPOINTER_TO_UINT(handle)); +} + +void net_nfc_server_phdc_data_sent(net_nfc_error_e result, gpointer user_data) +{ + PhdcSendData *data = (PhdcSendData *)user_data; + + g_assert(data != NULL); + g_assert(data->phdc != NULL); + g_assert(data->invocation != NULL); + + net_nfc_gdbus_phdc_complete_send(data->phdc, data->invocation, (gint)result); + + net_nfc_util_free_data(&data->data); + + g_object_unref(data->invocation); + g_object_unref(data->phdc); + + g_free(data); +} + diff --git a/daemon/net_nfc_server_phdc.h b/daemon/net_nfc_server_phdc.h new file mode 100755 index 0000000..a772283 --- /dev/null +++ b/daemon/net_nfc_server_phdc.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __NET_NFC_SERVER_PHDC_H__ +#define __NET_NFC_SERVER_PHDC_H__ + +#include +#include "net_nfc_typedef_internal.h" + +gboolean net_nfc_server_phdc_init(GDBusConnection *connection); + +void net_nfc_server_phdc_deinit(void); + +/* server side */ +void net_nfc_server_phdc_transport_disconnect_indication(void); + +void net_nfc_server_phdc_transport_connect_indication(net_nfc_phdc_handle_h handle); + +void net_nfc_server_phdc_data_received_indication(data_s *arg_data); + +void net_nfc_server_phdc_data_sent(net_nfc_error_e result, gpointer user_data); + +#endif //__NET_NFC_SERVER_PHDC_H__ \ No newline at end of file diff --git a/daemon/net_nfc_server_process_phdc.c b/daemon/net_nfc_server_process_phdc.c new file mode 100755 index 0000000..2574d4b --- /dev/null +++ b/daemon/net_nfc_server_process_phdc.c @@ -0,0 +1,912 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "net_nfc_debug_internal.h" +#include "net_nfc_server_tag.h" +#include "net_nfc_util_defines.h" +#include "net_nfc_util_internal.h" +#include "net_nfc_util_gdbus_internal.h" +#include "net_nfc_server_llcp.h" +#include "net_nfc_server_util.h" +#include "net_nfc_server_process_phdc.h" +#include "net_nfc_server_controller.h" +#include "net_nfc_server_phdc.h" + + + +typedef struct _net_nfc_server_phdc_pdu_t +{ + uint8_t data[128]; +} +__attribute__ ((packed)) net_nfc_server_phdc_pdu_t; + +//callback for internal send/receive +typedef void (*_net_nfc_server_phdc_operation_cb)( + net_nfc_error_e result, + data_s *data, + void *user_param); + +static void _net_nfc_server_phdc_agent_connected_cb(net_nfc_error_e result, + net_nfc_target_handle_s *handle, + net_nfc_llcp_socket_t socket, + data_s *data, + void *user_param); + +typedef struct _net_nfc_server_phdc_op_context_t +{ + net_nfc_target_handle_s *handle; + net_nfc_error_e result; + int socket; + uint32_t state; + uint32_t current; + uint16_t miu; + data_s data; + _net_nfc_server_phdc_operation_cb cb; + void *user_param; +}net_nfc_server_phdc_op_context_t; + + +typedef struct _net_nfc_server_phdc_job_t +{ + net_nfc_server_phdc_context_t *context; + net_nfc_target_handle_s *handle; + net_nfc_error_e result; + net_nfc_llcp_socket_t socket; + uint32_t state; + data_s data; + net_nfc_server_phdc_send_cb cb; + void *user_param; +}net_nfc_server_phdc_job_t; + +static void _net_nfc_server_phdc_agent_process( + net_nfc_server_phdc_job_t *job); + +static void _net_nfc_server_phdc_destory_context( + net_nfc_server_phdc_op_context_t *context); + +static void _net_nfc_server_phdc_clear_queue( + gpointer data, + gpointer user_data); + +static void _net_nfc_server_phdc_socket_error_cb(net_nfc_error_e result, + net_nfc_target_handle_s *handle, + net_nfc_llcp_socket_t socket, + data_s *data, + void *user_param); + +static void _net_nfc_server_phdc_recv_cb( + net_nfc_llcp_socket_t socket, + net_nfc_error_e result, + data_s *data, + void *extra, + void *user_param); + +static void _net_nfc_server_phdc_recv( + net_nfc_server_phdc_op_context_t *context); + +static net_nfc_server_phdc_op_context_t* _net_nfc_server_phdc_create_recv_context( + net_nfc_target_handle_s *handle, + net_nfc_llcp_socket_t socket, + void *cb, + void *user_param); + +static void _net_nfc_server_phdc_manager_op_cb( + net_nfc_error_e result, + data_s *data, + void *user_param); + + +static net_nfc_error_e net_nfc_server_phdc_recv( + net_nfc_target_handle_s *handle, + net_nfc_llcp_socket_t socket, + _net_nfc_server_phdc_operation_cb cb, + void *user_param); + +static void _net_nfc_server_phdc_manager_process( + net_nfc_server_phdc_context_t *context); + +static void _net_nfc_server_phdc_incoming_cb(net_nfc_error_e result, + net_nfc_target_handle_s *handle, + net_nfc_llcp_socket_t socket, + data_s *data, + void *user_param); + + +static void _net_nfc_server_phdc_destory_context(net_nfc_server_phdc_op_context_t *context) +{ + if (context != NULL) + { + if (context->data.buffer != NULL) + net_nfc_util_free_data(&context->data); + + _net_nfc_util_free_mem(context); + } +} + +static void _net_nfc_server_phdc_clear_queue(gpointer data,gpointer user_data) +{ + net_nfc_server_phdc_job_t *job = (net_nfc_server_phdc_job_t *)data; + + if (job != NULL) + { + if (job->cb != NULL) + { + job->cb((net_nfc_phdc_handle_h)job->context,NET_NFC_OPERATION_FAIL, + NET_NFC_PHDC_OPERATION_FAILED, job->user_param); + } + + if (job->data.buffer != NULL) + net_nfc_util_free_data(&job->data); + + _net_nfc_util_free_mem(job); + } +} + +static void _net_nfc_server_phdc_socket_error_cb(net_nfc_error_e result, + net_nfc_target_handle_s *handle, net_nfc_llcp_socket_t socket, data_s *data, + void *user_param) +{ + net_nfc_server_phdc_context_t *context = (net_nfc_server_phdc_context_t *)user_param; + + NFC_DBG("_net_nfc_server_phdc_socket_error_cb socket [%x], result [%d]", + socket, result); + + RET_IF(NULL == context); + + if (context->data.buffer != NULL) + net_nfc_util_free_data(&context->data); + + g_queue_foreach(&context->queue, _net_nfc_server_phdc_clear_queue, NULL); + + _net_nfc_util_free_mem(context); +} + + +static void _net_nfc_server_phdc_recv_cb(net_nfc_llcp_socket_t socket, + net_nfc_error_e result, data_s *data, void *extra, void *user_param) +{ + net_nfc_server_phdc_op_context_t *context = + (net_nfc_server_phdc_op_context_t *)user_param; + + uint8_t *buffer = NULL; + uint16_t pdu_length = 0; + + NFC_DBG("_net_nfc_server_phdc_recv_cb, socket[%x], result[%d]", socket, result); + + RET_IF(NULL == context); + + context->result = result; + + if (result != NET_NFC_OK) + { + NFC_ERR("error [%d]", result); + context->state = NET_NFC_STATE_ERROR; + goto END; + } + + if (NULL == data || NULL == data->buffer || 0 == data->length) + { + NFC_ERR("invalid response"); + context->state = NET_NFC_STATE_ERROR; + goto END; + } + + //first 2 bytes is phdc header length + memcpy(&pdu_length,data->buffer,PHDC_HEADER_LEN); + + pdu_length = ntohs(pdu_length); + NFC_INFO("pdu_legth [%d]", pdu_length); + + if(pdu_length > 0) + { + /* buffer create */ + net_nfc_util_alloc_data(&context->data,pdu_length); + if (NULL == context->data.buffer) + { + NFC_ERR("net_nfc_util_alloc_data failed"); + context->result = NET_NFC_ALLOC_FAIL; + goto END; + } + buffer =data->buffer; + context->data.length = data->length - PHDC_HEADER_LEN; + + /* copy data */ + if(context->data.length > 0) + { + memcpy(context->data.buffer ,buffer, context->data.length); + NFC_DBG("receive progress... [%d", context->data.length); + } + } +END: + context->cb(context->result, &context->data, context->user_param); +} + + +static void _net_nfc_server_phdc_recv(net_nfc_server_phdc_op_context_t *context) +{ + RET_IF(NULL == context); + + bool ret; + net_nfc_error_e result; + + NFC_DBG("socket [%x] waiting data.....", context->socket); + + ret = net_nfc_controller_llcp_recv(context->handle, context->socket, context->miu, + &result, _net_nfc_server_phdc_recv_cb, context); + + if(false == ret) + { + NFC_ERR("net_nfc_controller_llcp_recv failed, [%d]", result); + + context->result = result; + context->cb(context->result, &context->data, context->user_param); + + _net_nfc_server_phdc_destory_context(context); + } + +} + + +static net_nfc_server_phdc_op_context_t* _net_nfc_server_phdc_create_recv_context( + net_nfc_target_handle_s *handle, net_nfc_llcp_socket_t socket, void *cb, + void *user_param) +{ + + bool ret; + net_nfc_error_e result; + net_nfc_server_phdc_op_context_t *context = NULL; + net_nfc_llcp_config_info_s config; + + ret = net_nfc_controller_llcp_get_remote_config(handle, &config, &result); + + if(false == ret) + { + NFC_ERR("net_nfc_controller_llcp_get_remote_config failed, [%d]", result); + return NULL; + } + + _net_nfc_util_alloc_mem(context, sizeof(*context)); + + RETV_IF(NULL == context, NULL); + + context->handle = handle; + context->state = NET_NFC_LLCP_STEP_01; + context->socket = socket; + context->cb = cb; + context->user_param = user_param; + context->miu = MIN(config.miu, net_nfc_server_llcp_get_miu()); + + return context; +} + + +static net_nfc_error_e net_nfc_server_phdc_recv(net_nfc_target_handle_s *handle, + net_nfc_llcp_socket_t socket, _net_nfc_server_phdc_operation_cb cb, + void *user_param) +{ + net_nfc_error_e result; + net_nfc_server_phdc_op_context_t *context = NULL; + + /* create context */ + context = _net_nfc_server_phdc_create_recv_context(handle, socket, cb, user_param); + + if (context != NULL) + { + _net_nfc_server_phdc_recv(context); + result = NET_NFC_OK; + } + else + { + result = NET_NFC_ALLOC_FAIL; + + if (cb != NULL) + cb(result, NULL, user_param); + } + + return result; +} + + +static void _net_nfc_server_phdc_agent_connected_cb(net_nfc_error_e result, + net_nfc_target_handle_s *handle, net_nfc_llcp_socket_t socket, data_s *data, + void *user_param) +{ + net_nfc_server_phdc_context_t *context = + (net_nfc_server_phdc_context_t *)user_param; + + RET_IF(NULL == context); + + context->socket = socket; + + if (NET_NFC_OK == result) + NFC_DBG("socket [%x] connected. send message", socket); + else + NFC_ERR("connect socket failed, [%d]", result); + + net_nfc_server_phdc_recv(handle, socket, + _net_nfc_server_phdc_manager_op_cb, + context); + + if (context->cb != NULL) + context->cb((net_nfc_phdc_handle_h)context, result, + NET_NFC_PHDC_TARGET_CONNECTED, NULL); + +} + +net_nfc_error_e net_nfc_server_phdc_agent_connect(net_nfc_target_handle_s *handle, + const char *san, sap_t sap, net_nfc_server_phdc_cb cb, void *user_param) +{ + bool ret; + net_nfc_error_e result; + net_nfc_server_phdc_context_t *context = NULL; + + RETV_IF(NULL == handle, NET_NFC_NULL_PARAMETER); + + ret = net_nfc_server_target_connected(handle); + + if(FALSE == ret) + return NET_NFC_NOT_CONNECTED; + + _net_nfc_util_alloc_mem(context, sizeof(*context)); + + if (NULL == context) + { + NFC_ERR("_net_nfc_util_alloc_mem failed"); + result = NET_NFC_ALLOC_FAIL; + goto ERROR; + } + + context->handle = handle; + context->cb = cb; + context->user_param = user_param; + + result = net_nfc_server_llcp_simple_client(handle, san, sap, + _net_nfc_server_phdc_agent_connected_cb, + _net_nfc_server_phdc_socket_error_cb, + context); + + if (result != NET_NFC_OK) + { + NFC_ERR("net_nfc_server_llcp_simple_client failed, [%d]", result); + goto ERROR; + } + + if (san != NULL) + NFC_DBG("start phdc agent san [%s]", san); + else + NFC_DBG("start phdc agent, sap [%d]", sap); + + return result; + +ERROR : + if (context != NULL) + { + if (context->data.buffer != NULL) + { + net_nfc_util_free_data(&context->data); + } + _net_nfc_util_free_mem(context); + } + + return result; +} + + +static void _net_nfc_server_phdc_agent_do_job( + net_nfc_server_phdc_context_t *context) +{ + if (context->state == NET_NFC_LLCP_IDLE && g_queue_is_empty(&context->queue) == false) + { + net_nfc_server_phdc_job_t *job; + + job = g_queue_pop_head(&context->queue); + if (job != NULL) + { + context->state = NET_NFC_LLCP_STEP_01; + job->state = NET_NFC_LLCP_STEP_01; + _net_nfc_server_phdc_agent_process(job); + } + } +} + +static net_nfc_server_phdc_op_context_t* _net_nfc_server_phdc_create_send_context( + net_nfc_target_handle_s *handle, net_nfc_llcp_socket_t socket, data_s *data, + void *cb, void *user_param) +{ + bool ret; + uint32_t data_len = 0; + uint16_t length; + uint8_t *buffer = NULL; + net_nfc_server_phdc_op_context_t *context = NULL; + net_nfc_llcp_config_info_s config; + net_nfc_error_e result; + + ret = net_nfc_controller_llcp_get_remote_config(handle, + &config, &result); + + if(FALSE == ret) + { + NFC_ERR("net_nfc_controller_llcp_get_remote_config failed, [%d]", result); + return NULL; + } + + _net_nfc_util_alloc_mem(context, sizeof(*context)); + RETV_IF(NULL == context, NULL); + + if (data != NULL) + data_len =data->length; + + if (data_len > 0) + { + net_nfc_util_alloc_data(&context->data,data_len+PHDC_HEADER_LEN); + if (NULL == context->data.buffer) + { + _net_nfc_util_free_mem(context); + return NULL; + } + + length = (uint16_t)data->length; + length +=PHDC_HEADER_LEN; + buffer = context->data.buffer; + + if(data->buffer != NULL) + { + uint16_t network_length = htons(length); + memcpy(buffer,&network_length,PHDC_HEADER_LEN); + buffer+=PHDC_HEADER_LEN; + memcpy(buffer,data->buffer,data->length); + context->data.length = length; + } + } + + context->handle = handle; + context->socket = socket; + context->cb = cb; + context->user_param = user_param; + context->miu = MIN(config.miu, net_nfc_server_llcp_get_miu()); + + return context; +} + +static void _net_nfc_server_phdc_send_cb(net_nfc_llcp_socket_t socket, + net_nfc_error_e result, data_s *data, void *extra, void *user_param) +{ + net_nfc_server_phdc_op_context_t *context = + (net_nfc_server_phdc_op_context_t *)user_param; + + NFC_DBG("_net_nfc_server_phdc_send_cb, socket[%x], result[%d]", socket, result); + + RET_IF(NULL == context); + + context->result = result; + + /* complete and invoke callback */ + context->cb(context->result, NULL, context->user_param); + + _net_nfc_server_phdc_destory_context(context); +} + + +static void _net_nfc_server_phdc_send(net_nfc_server_phdc_op_context_t *context) +{ + bool ret; + data_s req_msg; + net_nfc_error_e result; + + RET_IF(NULL == context); + + req_msg.length = context->data.length; + req_msg.buffer = context->data.buffer; + + NFC_DBG("try to send data, socket [%x]",context->socket); + + ret= net_nfc_controller_llcp_send(context->handle, context->socket, + &req_msg, &result, _net_nfc_server_phdc_send_cb, context); + + if(FALSE == ret) + { + NFC_ERR("net_nfc_controller_llcp_send failed, [%d]",result); + context->result = result; + + context->cb(context->result, NULL, context->user_param); + _net_nfc_server_phdc_destory_context(context); + } +} + +static void _net_nfc_server_phdc_agent_send_cb(net_nfc_error_e result,data_s *data, + void *user_param) +{ + net_nfc_server_phdc_job_t*job = (net_nfc_server_phdc_job_t *)user_param; + + RET_IF(NULL == job); + + job->result = result; + + if (NET_NFC_OK ==result) + { + job->state = NET_NFC_LLCP_STEP_RETURN; + net_nfc_util_free_data(&job->data); + } + else + { + NFC_ERR("net_nfc_server_phdc_send failed, [%d]", result); + job->state = NET_NFC_STATE_ERROR; + } + + _net_nfc_server_phdc_agent_process(job); +} + + +net_nfc_error_e net_nfc_server_phdc_send(net_nfc_target_handle_s *handle, + net_nfc_llcp_socket_t socket, data_s *data, _net_nfc_server_phdc_operation_cb cb, + void *user_param) +{ + net_nfc_error_e result; + net_nfc_server_phdc_op_context_t *context = NULL; + + /* create context */ + context = _net_nfc_server_phdc_create_send_context(handle, socket,data, + cb, user_param); + + if (context != NULL) + { + /* send data */ + _net_nfc_server_phdc_send(context); + result = NET_NFC_OK; + } + else + { + NFC_ERR("_net_nfc_server_phdc_create_send_context failed"); + result = NET_NFC_ALLOC_FAIL; + + if (cb != NULL) + cb(result, NULL, user_param); + } + + return result; +} + +static void _net_nfc_server_phdc_agent_process(net_nfc_server_phdc_job_t *job) +{ + bool finish = false; + + RET_IF(NULL == job); + + switch (job->state) + { + case NET_NFC_LLCP_STEP_01 : + NFC_DBG("NET_NFC_LLCP_STEP_01"); + + /* send request */ + net_nfc_server_phdc_send(job->handle, job->socket, &job->data, + _net_nfc_server_phdc_agent_send_cb, job); + break; + + case NET_NFC_LLCP_STEP_RETURN : + NFC_DBG("NET_NFC_LLCP_STEP_RETURN"); + + /* complete and invoke callback */ + if (job->cb != NULL) + { + job->cb((net_nfc_phdc_handle_h)job->context, NET_NFC_OK, + NET_NFC_PHDC_DATA_RECEIVED, job->user_param); + } + /* finish job */ + finish = true; + break; + + case NET_NFC_STATE_ERROR : + default : + NFC_ERR("NET_NFC_STATE_ERROR"); + + /* error, invoke callback */ + NFC_ERR("phdc_agent_send failed, [%d]", job->result); + if (job->cb != NULL) + { + job->cb((net_nfc_phdc_handle_h)job->context, job->result, + NET_NFC_PHDC_OPERATION_FAILED, job->user_param); + } + /* finish job */ + finish = TRUE; + break; + } + + if (TRUE == finish) + { + net_nfc_server_phdc_context_t *context = job->context; + + if (job->data.buffer != NULL) + net_nfc_util_free_data(&job->data); + + _net_nfc_util_free_mem(job); + context->state = NET_NFC_LLCP_IDLE; + _net_nfc_server_phdc_agent_do_job(context); + } +} + + +net_nfc_error_e net_nfc_server_phdc_agent_request(net_nfc_phdc_handle_h handle, + data_s *data, net_nfc_server_phdc_send_cb cb, void *user_param) +{ + bool ret; + net_nfc_error_e result = NET_NFC_OK; + net_nfc_server_phdc_job_t *job = NULL; + net_nfc_server_phdc_context_t *context = (net_nfc_server_phdc_context_t *)handle; + + RETV_IF(NULL == handle, NET_NFC_NULL_PARAMETER); + RETV_IF(NULL == data, NET_NFC_NULL_PARAMETER); + RETV_IF(NULL == data->buffer, NET_NFC_NULL_PARAMETER); + + ret =net_nfc_server_target_connected(context->handle); + + if(FALSE == ret) + return NET_NFC_NOT_CONNECTED; + + /* check type */ + _net_nfc_util_alloc_mem(job, sizeof(*job)); + if (job != NULL) + { + net_nfc_util_alloc_data(&job->data, data->length); + if (job->data.buffer != NULL) + memcpy(job->data.buffer, data->buffer, data->length); + + job->cb = cb; + job->user_param = user_param; + job->context = context; + job->handle = context->handle; + job->socket = context->socket; + g_queue_push_tail(&context->queue, job); + } + else + return NET_NFC_ALLOC_FAIL; + + NFC_INFO("enqueued jobs [%d]", g_queue_get_length(&context->queue)); + + /* if agent is idle, starts sending request */ + if (context->state == NET_NFC_LLCP_IDLE) + _net_nfc_server_phdc_agent_do_job(context); + else + NFC_INFO("agent is working. this job will be enqueued"); + + return result; +} + + +net_nfc_error_e net_nfc_server_phdc_agent_start(net_nfc_target_handle_s *handle, + const char *san, sap_t sap, net_nfc_server_phdc_cb cb, void *user_param) +{ + net_nfc_error_e result; + + RETV_IF(NULL == handle, NET_NFC_NULL_PARAMETER); + RETV_IF(NULL == san, NET_NFC_NULL_PARAMETER); + + /* start PHDC Agent, register your callback */ + result = net_nfc_server_phdc_agent_connect(handle, san, sap, + cb, user_param); + + if (result != NET_NFC_OK) + { + NFC_ERR("net_nfc_server_phdc_agent_connect failed, [%d]",result); + } + return result; +} + +static void _net_nfc_server_phdc_manager_op_cb( net_nfc_error_e result, data_s *data, + void *user_param) +{ + net_nfc_server_phdc_context_t *context = + (net_nfc_server_phdc_context_t *)user_param; + + NFC_DBG("_net_nfc_server_phdc_manager_op_cb result [%d]", result); + + RET_IF(NULL == context); + + context->result = result; + if (NET_NFC_OK == result && data != NULL && data->buffer != NULL) + { + NFC_DBG("received message, length [%d]", data->length); + + net_nfc_util_alloc_data(&context->data, data->length); + if (context->data.buffer != NULL) + { + memcpy(context->data.buffer,data->buffer, data->length); + context->state = NET_NFC_LLCP_STEP_02; + } + else + { + NFC_ERR("net_nfc_util_alloc_data failed"); + context->state = NET_NFC_STATE_ERROR; + context->result = NET_NFC_ALLOC_FAIL; + } + } + else + { + NFC_ERR("net_nfc_server_phdc_recv failed, [%d]", result); + context->state = NET_NFC_STATE_ERROR; + } + + _net_nfc_server_phdc_manager_process(context); + +} + + +static void _net_nfc_server_phdc_manager_process( + net_nfc_server_phdc_context_t *context) +{ + bool finish = false; + RET_IF(NULL == context); + + switch (context->state) + { + case NET_NFC_LLCP_STEP_01 : + NFC_INFO("NET_NFC_LLCP_STEP_01 "); + /*receive the Agent data*/ + net_nfc_server_phdc_recv( context->handle,context->socket, + _net_nfc_server_phdc_manager_op_cb, context); + break; + case NET_NFC_LLCP_STEP_02 : + NFC_INFO("NET_NFC_LLCP_STEP_02"); + if (context->cb != NULL) + { + /* complete operation and invoke the callback*/ + context->cb((net_nfc_phdc_handle_h)context,NET_NFC_OK, + NET_NFC_PHDC_DATA_RECEIVED, &context->data); + } + finish = true; + break; + case NET_NFC_STATE_ERROR : + NFC_INFO("NET_NFC_STATE_ERROR"); + default : + if (context->cb != NULL) + { + context->cb((net_nfc_phdc_handle_h)context,context->result, + NET_NFC_PHDC_OPERATION_FAILED,&context->data); + } + return; + break; + } + + if(true == finish) + { + context->state = NET_NFC_LLCP_IDLE; + + net_nfc_server_phdc_recv(context->handle, + context->socket, + _net_nfc_server_phdc_manager_op_cb, + context); + + } +} + + +static void _net_nfc_server_phdc_incoming_cb(net_nfc_error_e result, + net_nfc_target_handle_s *handle, net_nfc_llcp_socket_t socket, data_s *data, + void *user_param) +{ + net_nfc_server_phdc_context_t *context = + (net_nfc_server_phdc_context_t *)user_param; + + net_nfc_server_phdc_context_t *accept_context = NULL; + + RET_IF(NULL == context); + + NFC_DBG("phdc incoming socket [%x], result [%d]", socket, result); + + if (result != NET_NFC_OK) + { + NFC_ERR("listen socket failed, [%d]", result); + goto ERROR; + } + + _net_nfc_util_alloc_mem(accept_context, sizeof(*accept_context)); + + if (NULL == accept_context) + { + NFC_ERR("_net_nfc_util_alloc_mem failed"); + result = NET_NFC_ALLOC_FAIL; + goto ERROR; + } + + accept_context->handle = context->handle; + accept_context->socket = socket; + accept_context->cb = context->cb; + accept_context->user_param = context->user_param; + accept_context->state = NET_NFC_LLCP_STEP_01; + + result = net_nfc_server_llcp_simple_accept(handle, socket, + _net_nfc_server_phdc_socket_error_cb, accept_context); + + if (result != NET_NFC_OK) + { + NFC_ERR("net_nfc_server_llcp_simple_accept failed, [%d]",result); + goto ERROR; + } + + NFC_DBG("socket [%x] accepted.. waiting for request message", socket); + + accept_context->cb((net_nfc_phdc_handle_h)accept_context, result, + NET_NFC_PHDC_TARGET_CONNECTED, data); + + _net_nfc_server_phdc_manager_process(accept_context); + + return; +ERROR : + if (accept_context != NULL) + { + _net_nfc_util_free_mem(accept_context); + } +} + +net_nfc_error_e net_nfc_server_phdc_manager_start(net_nfc_target_handle_s *handle, + const char *san, sap_t sap, net_nfc_server_phdc_cb cb, void *user_param) +{ + bool ret; + net_nfc_error_e result; + net_nfc_server_phdc_context_t *context = NULL; + + RETV_IF(NULL == handle, NET_NFC_NULL_PARAMETER); + RETV_IF(NULL == san, NET_NFC_NULL_PARAMETER); + + ret = net_nfc_server_target_connected(handle); + + if(FALSE == ret) + return NET_NFC_NOT_CONNECTED; + + _net_nfc_util_alloc_mem(context, sizeof(*context)); + if(NULL == context) + { + NFC_ERR("_create_phdc_context failed"); + result = NET_NFC_ALLOC_FAIL; + goto ERROR; + } + + context->handle = handle; + context->cb = cb; + context->user_param = user_param; + context->state = NET_NFC_LLCP_STEP_01; + + if(!strcmp(san,PHDC_SAN)) + { + /*Handle the default PHDC SAN*/ + result = net_nfc_server_llcp_simple_server(handle, san,sap, + _net_nfc_server_phdc_incoming_cb,_net_nfc_server_phdc_socket_error_cb, + context); + } + else + { + /*Handle other SAN, Implement as and when needed.*/ + result = NET_NFC_NOT_SUPPORTED; + } + + if (result != NET_NFC_OK) + { + NFC_ERR("net_nfc_server_llcp_simple_server failed, [%d]",result); + goto ERROR; + } + + NFC_DBG("start phdc manager, san [%s], sap [%d]", san, sap); + return result; + +ERROR : + if (context != NULL) + _net_nfc_util_free_mem(context); + + return result; +} + +/////////////////////////////////////////////////////////////////// + diff --git a/daemon/net_nfc_server_process_phdc.h b/daemon/net_nfc_server_process_phdc.h new file mode 100755 index 0000000..7e34d9d --- /dev/null +++ b/daemon/net_nfc_server_process_phdc.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __NET_NFC_SERVER_PROCESS_PHDC_H__ +#define __NET_NFC_SERVER_PROCESS_PHDC_H__ + +#include "net_nfc_gdbus.h" +#include "net_nfc_typedef_internal.h" + +#define PHDC_SAP 0x16 +#define PHDS_SAP 0x17 +#define PHDC_SAN "urn:nfc:sn:phdc" +#define PHDS_SAN "urn:nfc:sn:phds" +#define PHDC_HEADER_LEN 2 + +typedef enum +{ + NET_NFC_PHDC_OPERATION_FAILED = 0, + NET_NFC_PHDC_TARGET_CONNECTED , + NET_NFC_PHDC_DATA_RECEIVED +}net_nfc_server_phdc_indication_type; + + +//callback for manager connection accept / agent connect +typedef void (*net_nfc_server_phdc_cb)(net_nfc_phdc_handle_h handle, + net_nfc_error_e result, net_nfc_server_phdc_indication_type indication, data_s *data); + +//callback for data send +typedef gboolean (*net_nfc_server_phdc_send_cb)(net_nfc_phdc_handle_h handle, + net_nfc_error_e result, net_nfc_server_phdc_indication_type indication, gpointer *user_data); + +typedef struct _net_nfc_server_phdc_context_t net_nfc_server_phdc_context_t; + +struct _net_nfc_server_phdc_context_t +{ + net_nfc_target_handle_s *handle; + net_nfc_error_e result; + net_nfc_llcp_socket_t socket; + uint32_t state; + data_s data; + net_nfc_server_phdc_cb cb; + void *user_param; + GQueue queue; +}; + +net_nfc_error_e net_nfc_server_phdc_manager_start(net_nfc_target_handle_s *handle, + const char *san, sap_t sap, net_nfc_server_phdc_cb cb, void *user_param); + +net_nfc_error_e net_nfc_server_phdc_agent_start(net_nfc_target_handle_s *handle, + const char *san, sap_t sap, net_nfc_server_phdc_cb cb, void *user_param); + +net_nfc_error_e net_nfc_server_phdc_agent_request(net_nfc_phdc_handle_h handle, + data_s *data, net_nfc_server_phdc_send_cb cb, void *user_param); + + +#endif//__NET_NFC_SERVER_PROCESS_PHDC_H__ + -- 2.7.4