diff options
Diffstat (limited to 'sap/sap-dummy.c')
-rw-r--r-- | sap/sap-dummy.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/sap/sap-dummy.c b/sap/sap-dummy.c new file mode 100644 index 0000000..39e1fc9 --- /dev/null +++ b/sap/sap-dummy.c @@ -0,0 +1,330 @@ +/* + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2010 ST-Ericsson SA + * Copyright (C) 2011 Tieto Poland + * + * Author: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> + * for ST-Ericsson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <glib.h> +#include <gdbus.h> + +#include "log.h" +#include "sap.h" + +#define SAP_DUMMY_IFACE "org.bluez.SimAccessTest" +#define SAP_DUMMY_PATH "/org/bluez/test" + +enum { + SIM_DISCONNECTED= 0x00, + SIM_CONNECTED = 0x01, + SIM_POWERED_OFF = 0x02, + SIM_MISSING = 0x03 +}; + +static DBusConnection *connection = NULL; + +static int sim_card_conn_status = SIM_DISCONNECTED; +static void *sap_data = NULL; /* SAP server private data.*/ +static gboolean ongoing_call_status = FALSE; +static int max_msg_size_supported = 512; + +void sap_connect_req(void *sap_device, uint16_t maxmsgsize) +{ + DBG("status: %d", sim_card_conn_status); + + if (sim_card_conn_status != SIM_DISCONNECTED) { + sap_connect_rsp(sap_device, SAP_STATUS_CONNECTION_FAILED, + maxmsgsize); + return; + } else if (max_msg_size_supported > maxmsgsize) { + sap_connect_rsp(sap_device, SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL, + max_msg_size_supported); + return; + } else if (max_msg_size_supported < maxmsgsize) { + sap_connect_rsp(sap_device, + SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED, + max_msg_size_supported); + return; + } else if (ongoing_call_status) { + sap_connect_rsp(sap_device, SAP_STATUS_OK_ONGOING_CALL, + maxmsgsize); + return; + } else { + sim_card_conn_status = SIM_CONNECTED; + sap_data = sap_device; + + sap_connect_rsp(sap_device, SAP_STATUS_OK, maxmsgsize); + sap_status_ind(sap_device, SAP_STATUS_CHANGE_CARD_RESET); + } +} + +void sap_disconnect_req(void *sap_device, uint8_t linkloss) +{ + sim_card_conn_status = SIM_DISCONNECTED; + sap_data = NULL; + ongoing_call_status = FALSE; + + DBG("status: %d", sim_card_conn_status); + + if (linkloss) + return; + + sap_disconnect_rsp(sap_device); +} + +void sap_transfer_apdu_req(void *sap_device, struct sap_parameter *param) +{ + char apdu[] = "APDU response!"; + + DBG("status: %d", sim_card_conn_status); + + if (sim_card_conn_status == SIM_MISSING) + sap_transfer_apdu_rsp(sap_device, + SAP_RESULT_ERROR_CARD_REMOVED, NULL, 0); + else if (sim_card_conn_status == SIM_POWERED_OFF) + sap_transfer_apdu_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF, + NULL, 0); + else if (sim_card_conn_status != SIM_CONNECTED) + sap_transfer_apdu_rsp(sap_device, + SAP_RESULT_ERROR_NOT_ACCESSIBLE, NULL, 0); + else + sap_transfer_apdu_rsp(sap_device, SAP_RESULT_OK, + (uint8_t*)&apdu, sizeof(apdu)); +} + +void sap_transfer_atr_req(void *sap_device) +{ + char atr[] = "ATR response!"; + + DBG("status: %d", sim_card_conn_status); + + if (sim_card_conn_status == SIM_MISSING) + sap_transfer_atr_rsp(sap_device, SAP_RESULT_ERROR_CARD_REMOVED, + NULL, 0); + else if (sim_card_conn_status == SIM_POWERED_OFF) + sap_transfer_atr_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF, + NULL, 0); + else if (sim_card_conn_status != SIM_CONNECTED) + sap_transfer_atr_rsp(sap_device, SAP_RESULT_ERROR_NO_REASON, + NULL, 0); + else + sap_transfer_atr_rsp(sap_device, SAP_RESULT_OK, + (uint8_t*)&atr, sizeof(atr)); +} + +void sap_power_sim_off_req(void *sap_device) +{ + DBG("status: %d", sim_card_conn_status); + + if (sim_card_conn_status == SIM_MISSING) { + sap_power_sim_off_rsp(sap_device, + SAP_RESULT_ERROR_CARD_REMOVED); + } else if (sim_card_conn_status == SIM_POWERED_OFF) { + sap_power_sim_off_rsp(sap_device, + SAP_RESULT_ERROR_POWERED_OFF); + } else if (sim_card_conn_status != SIM_CONNECTED) { + sap_power_sim_off_rsp(sap_device, + SAP_RESULT_ERROR_NO_REASON); + } else { + sap_power_sim_off_rsp(sap_device, SAP_RESULT_OK); + sim_card_conn_status = SIM_POWERED_OFF; + } +} + +void sap_power_sim_on_req(void *sap_device) +{ + DBG("status: %d", sim_card_conn_status); + + if (sim_card_conn_status == SIM_MISSING) { + sap_power_sim_on_rsp(sap_device, + SAP_RESULT_ERROR_CARD_REMOVED); + } else if (sim_card_conn_status == SIM_POWERED_OFF) { + sap_power_sim_on_rsp(sap_device, SAP_RESULT_OK); + sim_card_conn_status = SIM_CONNECTED; + return; + } else if (sim_card_conn_status != SIM_CONNECTED) { + sap_power_sim_on_rsp(sap_device, + SAP_RESULT_ERROR_NOT_ACCESSIBLE); + } else { + sap_power_sim_on_rsp(sap_device, + SAP_RESULT_ERROR_NO_REASON); + } +} + +void sap_reset_sim_req(void *sap_device) +{ + DBG("status: %d", sim_card_conn_status); + + if (sim_card_conn_status == SIM_MISSING) { + sap_reset_sim_rsp(sap_device, SAP_RESULT_ERROR_CARD_REMOVED); + } else if (sim_card_conn_status == SIM_POWERED_OFF) { + sap_reset_sim_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF); + } else if (sim_card_conn_status != SIM_CONNECTED) { + sap_reset_sim_rsp(sap_device, SAP_RESULT_ERROR_NO_REASON); + } else { + sap_reset_sim_rsp(sap_device, SAP_RESULT_OK); + } +} + +void sap_transfer_card_reader_status_req(void *sap_device) +{ + DBG("status: %d", sim_card_conn_status); + + if (sim_card_conn_status != SIM_CONNECTED) { + sap_transfer_card_reader_status_rsp(sap_device, + SAP_RESULT_ERROR_NO_REASON, 0xF1); + return; + } + + sap_transfer_card_reader_status_rsp(sap_device, SAP_RESULT_OK, 0xF1); +} + +void sap_set_transport_protocol_req(void *sap_device, + struct sap_parameter *param) +{ + sap_transport_protocol_rsp(sap_device, SAP_RESULT_NOT_SUPPORTED); +} + +static inline DBusMessage *invalid_args(DBusMessage *msg) +{ + return g_dbus_create_error(msg, "org.bluez.Error.InvalidArguments", + "Invalid arguments in method call"); +} + +static DBusMessage *ongoing_call(DBusConnection *conn, DBusMessage *msg, + void *data) +{ + dbus_bool_t ongoing; + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &ongoing, + DBUS_TYPE_INVALID)) + return invalid_args(msg); + + if (ongoing_call_status && !ongoing) { + /* An ongoing call has finished. Continue connection.*/ + sap_connect_rsp(sap_data, SAP_STATUS_OK, + max_msg_size_supported); + sap_status_ind(sap_data, SAP_STATUS_CHANGE_CARD_RESET); + ongoing_call_status = ongoing; + } else if (!ongoing_call_status && ongoing) { + /* An ongoing call has started.*/ + ongoing_call_status = ongoing; + } + + DBG("OngoingCall status set to %d", ongoing_call_status); + + return dbus_message_new_method_return(msg); +} + +static DBusMessage *max_msg_size(DBusConnection *conn, DBusMessage *msg, + void *data) +{ + dbus_uint32_t size; + + if (sim_card_conn_status == SIM_CONNECTED) + return g_dbus_create_error(msg, "org.bluez.Error.Failed", + "Can't change msg size when connected."); + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &size, + DBUS_TYPE_INVALID)) + return invalid_args(msg); + + max_msg_size_supported = size; + + DBG("MaxMessageSize set to %d", max_msg_size_supported); + + return dbus_message_new_method_return(msg); +} + +static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg, + void *data) +{ + sim_card_conn_status = SIM_DISCONNECTED; + sap_status_ind(sap_data, SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE); + + return dbus_message_new_method_return(msg); +} + +static DBusMessage *card_status(DBusConnection *conn, DBusMessage *msg, + void *data) +{ + dbus_uint32_t status; + + DBG("status %d", sim_card_conn_status); + + if (sim_card_conn_status != SIM_CONNECTED) + return g_dbus_create_error(msg, "org.bluez.Error.Failed", + "Can't change msg size when not connected."); + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &status, + DBUS_TYPE_INVALID)) + return invalid_args(msg); + + if (status) { + if (sim_card_conn_status == SIM_MISSING) { + sim_card_conn_status = SIM_CONNECTED; + sap_status_ind(sap_data, + SAP_STATUS_CHANGE_CARD_INSERTED); + } + } else { + sim_card_conn_status = SIM_MISSING; + sap_status_ind(sap_data, SAP_STATUS_CHANGE_CARD_REMOVED); + } + + DBG("Card status changed to %d", status); + + return dbus_message_new_method_return(msg); +} + +static GDBusMethodTable dummy_methods[] = { + { "OngoingCall", "b", "", ongoing_call}, + { "MaxMessageSize", "u", "", max_msg_size}, + { "Disconnect", "", "", disconnect}, + { "CardStatus", "u", "", card_status}, + { } +}; + +int sap_init(void) +{ + connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + + if (g_dbus_register_interface(connection, SAP_DUMMY_PATH, + SAP_DUMMY_IFACE, dummy_methods, NULL, NULL, + NULL, NULL) == FALSE) { + error("sap-dummy interface %s init failed on path %s", + SAP_DUMMY_IFACE, SAP_DUMMY_PATH); + return -1; + } + + return 0; +} + +void sap_exit(void) +{ + dbus_connection_unref(connection); + connection = NULL; +} |