Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v5 1/4] Sim Access Profile connect/disconnect procedures
@ 2011-03-16 12:10 Waldemar Rymarkiewicz
  2011-03-16 12:10 ` [PATCH v5 2/4] Add support for SAP protocol Waldemar Rymarkiewicz
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Waldemar Rymarkiewicz @ 2011-03-16 12:10 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth, Waldemar Rymarkiewicz

Add support for SAP protocol features:
	* connect and disconnect requests
	* connect and disconnect responses
	* disconnect indication
	* timeouts for the valid connection
---
 sap/sap.h    |    2 +-
 sap/server.c |  433 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 424 insertions(+), 11 deletions(-)

diff --git a/sap/sap.h b/sap/sap.h
index bd0f06d..24240ca 100644
--- a/sap/sap.h
+++ b/sap/sap.h
@@ -143,7 +143,7 @@ enum sap_param_id {
 #define SAP_PARAM_ID_DISCONNECT_IND_LEN		0x01
 #define SAP_PARAM_ID_CARD_READER_STATUS_LEN	0x01
 #define SAP_PARAM_ID_STATUS_CHANGE_LEN		0x01
-#define SAP_PARAM_ID_TRANSPORT_PROTOCOL_LEN	0x01
+#define SAP_PARAM_ID_TRANSPORT_PROTO_LEN	0x01
 
 /* Transport Protocol - SAP v1.1 section 5.2.9 */
 enum sap_transport_protocol {
diff --git a/sap/server.c b/sap/server.c
index 1c62a3e..8337fe1 100644
--- a/sap/server.c
+++ b/sap/server.c
@@ -50,14 +50,28 @@
 #define SAP_SERVER_CHANNEL	8
 #define SAP_BUF_SIZE		512
 
+#define PADDING4(x) (4 - (x & 0x03))
+#define PARAMETER_SIZE(x) (sizeof(struct sap_parameter) + x + PADDING4(x))
+
+#define SAP_NO_REQ 0xFF
+
+#define SAP_TIMER_GRACEFUL_DISCONNECT 30
+#define SAP_TIMER_NO_ACTIVITY 30
+
 enum {
 	SAP_STATE_DISCONNECTED,
+	SAP_STATE_CONNECT_IN_PROGRESS,
 	SAP_STATE_CONNECTED,
+	SAP_STATE_GRACEFUL_DISCONNECT,
+	SAP_STATE_IMMEDIATE_DISCONNECT,
+	SAP_STATE_CLIENT_DISCONNECT
 };
 
 struct sap_connection {
 	GIOChannel *io;
 	uint32_t state;
+	uint8_t processing_req;
+	guint timer_id;
 };
 
 struct sap_server {
@@ -71,6 +85,72 @@ struct sap_server {
 static DBusConnection *connection;
 static struct sap_server *server;
 
+static void start_guard_timer(struct sap_connection *conn, guint interval);
+static void stop_guard_timer(struct sap_connection *conn);
+static gboolean guard_timeout(gpointer data);
+
+static int check_msg(struct sap_message *msg)
+{
+	if (!msg)
+		return -EINVAL;
+
+	switch (msg->id) {
+	case SAP_CONNECT_REQ:
+		if (msg->nparam != 0x01)
+			return -EBADMSG;
+
+		if (msg->param->id != SAP_PARAM_ID_MAX_MSG_SIZE)
+			return -EBADMSG;
+
+		if (ntohs(msg->param->len) != SAP_PARAM_ID_MAX_MSG_SIZE_LEN)
+			return -EBADMSG;
+
+		break;
+
+	case SAP_TRANSFER_APDU_REQ:
+		if (msg->nparam != 0x01)
+			return -EBADMSG;
+
+		if (msg->param->id != SAP_PARAM_ID_COMMAND_APDU)
+			if ( msg->param->id != SAP_PARAM_ID_COMMAND_APDU7816)
+				return -EBADMSG;
+
+		if (msg->param->len == 0x00)
+			return -EBADMSG;
+
+		break;
+
+	case SAP_SET_TRANSPORT_PROTOCOL_REQ:
+		if (msg->nparam != 0x01)
+			return -EBADMSG;
+
+		if (msg->param->id != SAP_PARAM_ID_TRANSPORT_PROTOCOL)
+			return -EBADMSG;
+
+		if (ntohs(msg->param->len) != SAP_PARAM_ID_TRANSPORT_PROTO_LEN)
+			return -EBADMSG;
+
+		if (*msg->param->val != SAP_TRANSPORT_PROTOCOL_T0)
+			if (*msg->param->val != SAP_TRANSPORT_PROTOCOL_T1)
+				return -EBADMSG;
+
+		break;
+
+	case SAP_DISCONNECT_REQ:
+	case SAP_TRANSFER_ATR_REQ:
+	case SAP_POWER_SIM_OFF_REQ:
+	case SAP_POWER_SIM_ON_REQ:
+	case SAP_RESET_SIM_REQ:
+	case SAP_TRANSFER_CARD_READER_STATUS_REQ:
+		if (msg->nparam != 0x00)
+			return -EBADMSG;
+
+		break;
+	}
+
+	return 0;
+}
+
 static sdp_record_t *create_sap_record(uint8_t channel)
 {
 	sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id;
@@ -126,16 +206,170 @@ static sdp_record_t *create_sap_record(uint8_t channel)
 	return record;
 }
 
+static int send_message(struct sap_connection *conn, void *buf, size_t size)
+{
+	size_t written = 0;
+	GError *gerr = NULL;
+	GIOStatus gstatus;
+
+	if (!conn || !buf)
+		return -EINVAL;
+
+	DBG("size %zu", size);
+
+	gstatus = g_io_channel_write_chars(conn->io, buf, size, &written,
+						&gerr);
+	if (gstatus != G_IO_STATUS_NORMAL) {
+		if (gerr)
+			g_error_free(gerr);
+
+		error("write error (0x%02x).", gstatus);
+		return -EINVAL;
+	}
+
+	if (written != size)
+		error("write error.(written %zu size %zu)", written, size);
+
+	return 0;
+}
+
+static int disconnect_ind(void *sap_device, uint8_t disc_type)
+{
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("data %p state %d disc_type 0x%02x", conn, conn->state, disc_type);
+
+	if (conn->state != SAP_STATE_GRACEFUL_DISCONNECT &&
+			conn->state != SAP_STATE_IMMEDIATE_DISCONNECT) {
+		error("Processing error (state %d pr 0x%02x)", conn->state,
+							conn->processing_req);
+		return -EPERM;
+	}
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_DISCONNECT_IND;
+	msg->nparam = 0x01;
+
+	/* Add disconnection type param. */
+	param->id  = SAP_PARAM_ID_DISCONNECT_IND;
+	param->len = htons(SAP_PARAM_ID_DISCONNECT_IND_LEN);
+	*param->val = disc_type;
+	size += PARAMETER_SIZE(SAP_PARAM_ID_DISCONNECT_IND_LEN);
+
+	return send_message(sap_device, buf, size);
+}
+
 static void connect_req(struct sap_connection *conn,
-					struct sap_parameter *param)
+				struct sap_parameter *param)
 {
-	DBG("SAP_CONNECT_REQUEST");
+	uint16_t maxmsgsize, *val;
+
+	DBG("conn %p state %d", conn, conn->state);
+
+	if (!param)
+		goto error_rsp;
+
+	if (conn->state != SAP_STATE_DISCONNECTED)
+		goto error_rsp;
+
+	stop_guard_timer(conn);
+
+	val = (uint16_t *) &param->val;
+	maxmsgsize = ntohs(*val);
+
+	DBG("Connect MaxMsgSize: 0x%04x", maxmsgsize);
+
+	conn->state = SAP_STATE_CONNECT_IN_PROGRESS;
+
+	if (maxmsgsize <= SAP_BUF_SIZE) {
+		conn->processing_req = SAP_CONNECT_REQ;
+		sap_connect_req(conn, maxmsgsize);
+	} else {
+		sap_connect_rsp(conn, SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED,
+								SAP_BUF_SIZE);
+	}
+
+	return;
+
+error_rsp:
+	error("Processing error (param %p state %d pr 0x%02x)", param,
+					conn->state, conn->processing_req);
+	sap_error_rsp(conn);
 }
 
 static int disconnect_req(struct sap_connection *conn, uint8_t disc_type)
 {
-	DBG("SAP_DISCONNECT_REQUEST");
-	return 0;
+	DBG("conn %p state %d disc_type 0x%02x", conn, conn->state, disc_type);
+
+	switch (disc_type) {
+	case SAP_DISCONNECTION_TYPE_GRACEFUL:
+		if (conn->state == SAP_STATE_DISCONNECTED)
+			goto error_req;
+
+		if (conn->state == SAP_STATE_CONNECT_IN_PROGRESS)
+			goto error_req;
+
+		if (conn->state == SAP_STATE_CONNECTED) {
+			conn->state = SAP_STATE_GRACEFUL_DISCONNECT;
+			conn->processing_req = SAP_NO_REQ;
+
+			disconnect_ind(conn, disc_type);
+			/* Timer will disconnect if client won't do.*/
+			start_guard_timer(conn, SAP_TIMER_GRACEFUL_DISCONNECT);
+		}
+
+		return 0;
+
+	case SAP_DISCONNECTION_TYPE_IMMEDIATE:
+		if (conn->state == SAP_STATE_DISCONNECTED)
+			goto error_req;
+
+		if (conn->state == SAP_STATE_CONNECT_IN_PROGRESS)
+			goto error_req;
+
+		if (conn->state == SAP_STATE_CONNECTED ||
+				conn->state == SAP_STATE_GRACEFUL_DISCONNECT) {
+			conn->state = SAP_STATE_IMMEDIATE_DISCONNECT;
+			conn->processing_req = SAP_NO_REQ;
+
+			stop_guard_timer(conn);
+			disconnect_ind(conn, disc_type);
+			sap_disconnect_req(conn, 0);
+		}
+
+		return 0;
+
+	case SAP_DISCONNECTION_TYPE_CLIENT:
+		if (conn->state != SAP_STATE_CONNECTED &&
+				conn->state != SAP_STATE_GRACEFUL_DISCONNECT)
+			goto error_rsp;
+
+		conn->state = SAP_STATE_CLIENT_DISCONNECT;
+		conn->processing_req = SAP_NO_REQ;
+
+		stop_guard_timer(conn);
+		sap_disconnect_req(conn, 0);
+
+		return 0;
+
+	default:
+		error("Unknown disconnection type (0x%02x).", disc_type);
+		return -EINVAL;
+	}
+
+error_rsp:
+	sap_error_rsp(conn);
+error_req:
+	error("Processing error (state %d pr 0x%02x)", conn->state,
+						conn->processing_req);
+	return -EPERM;
 }
 
 static void transfer_apdu_req(struct sap_connection *conn,
@@ -175,13 +409,163 @@ static void set_transport_protocol_req(struct sap_connection *conn,
 	DBG("SAP_SET_TRANSPORT_PROTOCOL_REQUEST");
 }
 
+static void start_guard_timer(struct sap_connection *conn, guint interval)
+{
+	if (!conn)
+		return;
+
+	if (!conn->timer_id)
+		conn->timer_id = g_timeout_add_seconds(interval, guard_timeout,
+									conn);
+	else
+		error("Timer is already active.");
+}
+
+static void stop_guard_timer(struct sap_connection *conn)
+{
+	if (conn  && conn->timer_id) {
+		g_source_remove(conn->timer_id);
+		conn->timer_id = 0;
+	}
+}
+
+static gboolean guard_timeout(gpointer data)
+{
+	struct sap_connection *conn = data;
+
+	if (!conn)
+		return FALSE;
+
+	DBG("conn %p state %d pr 0x%02x", conn, conn->state,
+						conn->processing_req);
+
+	conn->timer_id = 0;
+
+	switch (conn->state) {
+	case SAP_STATE_DISCONNECTED:
+		/* Client opened RFCOMM channel but didn't send CONNECT_REQ,
+		 * in fixed time or client disconnected SAP connection but
+		 * didn't closed RFCOMM channel in fixed time.*/
+		if (conn->io) {
+			g_io_channel_shutdown(conn->io, TRUE, NULL);
+			g_io_channel_unref(conn->io);
+		}
+		break;
+
+	case SAP_STATE_GRACEFUL_DISCONNECT:
+		/* Client didn't disconnect SAP connection in fixed time,
+		 * so close SAP connection immediately. */
+		disconnect_req(conn, SAP_DISCONNECTION_TYPE_IMMEDIATE);
+		break;
+
+	default:
+		error("Unexpected state (%d).", conn->state);
+		break;
+	}
+
+	return FALSE;
+}
+
 int sap_connect_rsp(void *sap_device, uint8_t status, uint16_t maxmsgsize)
 {
-	return 0;
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("state %d pr 0x%02x status 0x%02x", conn->state,
+						conn->processing_req, status);
+
+	if (conn->state != SAP_STATE_CONNECT_IN_PROGRESS)
+		return -EPERM;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_CONNECT_RESP;
+	msg->nparam = 0x01;
+
+	/* Add connection status */
+	param->id = SAP_PARAM_ID_CONN_STATUS;
+	param->len = htons(SAP_PARAM_ID_CONN_STATUS_LEN);
+	*param->val = status;
+	size += PARAMETER_SIZE(SAP_PARAM_ID_CONN_STATUS_LEN);
+
+	/* Add MaxMsgSize */
+	if (maxmsgsize && (status == SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED ||
+				status == SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL)) {
+		uint16_t *len;
+
+		msg->nparam++;
+		param = (struct sap_parameter *) &buf[size];
+		param->id = SAP_PARAM_ID_MAX_MSG_SIZE;
+		param->len = htons(SAP_PARAM_ID_MAX_MSG_SIZE_LEN);
+		len = (uint16_t *) &param->val;
+		*len = htons(maxmsgsize);
+		size += PARAMETER_SIZE(SAP_PARAM_ID_MAX_MSG_SIZE_LEN);
+	}
+
+	if (status == SAP_STATUS_OK) {
+		gboolean connected = TRUE;
+
+		emit_property_changed(connection, server->path,
+						SAP_SERVER_INTERFACE,
+			"Connected", DBUS_TYPE_BOOLEAN, &connected);
+
+		conn->state = SAP_STATE_CONNECTED;
+	} else {
+		conn->state = SAP_STATE_DISCONNECTED;
+
+		/* Timer will shutdown channel if client doesn't send
+		 * CONNECT_REQ or doesn't shutdown channel itself.*/
+		start_guard_timer(conn, SAP_TIMER_NO_ACTIVITY);
+	}
+
+	conn->processing_req = SAP_NO_REQ;
+
+	return send_message(sap_device, buf, size);
 }
 
 int sap_disconnect_rsp(void *sap_device)
 {
+	struct sap_connection *conn = sap_device;
+	struct sap_message msg;
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("state %d pr 0x%02x", conn->state, conn->processing_req);
+
+	switch (conn->state) {
+	case SAP_STATE_CLIENT_DISCONNECT:
+		memset(&msg, 0, sizeof(msg));
+		msg.id = SAP_DISCONNECT_RESP;
+
+		conn->state = SAP_STATE_DISCONNECTED;
+		conn->processing_req = SAP_NO_REQ;
+
+		/* Timer will close channel if client doesn't do it.*/
+		start_guard_timer(conn, SAP_TIMER_NO_ACTIVITY);
+
+		return send_message(sap_device, &msg, sizeof(msg));
+
+	case SAP_STATE_IMMEDIATE_DISCONNECT:
+		conn->state = SAP_STATE_DISCONNECTED;
+		conn->processing_req = SAP_NO_REQ;
+
+		if (conn->io) {
+			g_io_channel_shutdown(conn->io, TRUE, NULL);
+			g_io_channel_unref(conn->io);
+		}
+
+		return 0;
+
+	default:
+		break;
+	}
+
 	return 0;
 }
 
@@ -242,11 +626,14 @@ static int handle_cmd(void *data, void *buf, size_t size)
 		return -EINVAL;
 
 	if (size < sizeof(struct sap_message))
-		return -EINVAL;
+		goto error_rsp;
 
 	if (msg->nparam != 0 && size < (sizeof(struct sap_message) +
 					sizeof(struct sap_parameter) + 4))
-		return -EBADMSG;
+		goto error_rsp;
+
+	if (check_msg(msg) < 0)
+		goto error_rsp;
 
 	switch (msg->id) {
 	case SAP_CONNECT_REQ:
@@ -278,10 +665,13 @@ static int handle_cmd(void *data, void *buf, size_t size)
 		return 0;
 	default:
 		DBG("SAP unknown message.");
-		return -ENOMSG;
+		break;
 	}
 
-	return -1;
+error_rsp:
+	DBG("Bad request message format.");
+	sap_error_rsp(conn);
+	return -EBADMSG;
 }
 
 static void sap_conn_remove(struct sap_connection *conn)
@@ -347,6 +737,20 @@ static void sap_io_destroy(void *data)
 	DBG("conn %p", conn);
 
 	if (conn && conn->io) {
+		gboolean connected = FALSE;
+
+		stop_guard_timer(conn);
+
+		if (conn->state != SAP_STATE_CONNECT_IN_PROGRESS)
+			emit_property_changed(connection, server->path,
+					SAP_SERVER_INTERFACE, "Connected",
+					DBUS_TYPE_BOOLEAN, &connected);
+
+		if (conn->state == SAP_STATE_CONNECT_IN_PROGRESS ||
+				conn->state == SAP_STATE_CONNECTED ||
+				conn->state == SAP_STATE_GRACEFUL_DISCONNECT)
+			sap_disconnect_req(NULL, 1);
+
 		conn->io = NULL;
 		sap_conn_remove(conn);
 	}
@@ -361,6 +765,10 @@ static void sap_connect_cb(GIOChannel *io, GError *gerr, gpointer data)
 	if (!conn)
 		return;
 
+	/* Timer will shutdown the channel in case of lack of client
+	   activity */
+	start_guard_timer(conn, SAP_TIMER_NO_ACTIVITY);
+
 	g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
 			G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 			sap_io_cb, conn, sap_io_destroy);
@@ -468,6 +876,10 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
 	if (!server->conn)
 		return message_failed(msg, "Client already disconnected");
 
+	if (disconnect_req(server->conn, SAP_DISCONNECTION_TYPE_GRACEFUL) < 0)
+		return g_dbus_create_error(msg, ERROR_INTERFACE	".Failed",
+				"There is no active connection");
+
 	return dbus_message_new_method_return(msg);
 }
 
@@ -494,7 +906,8 @@ static DBusMessage *get_properties(DBusConnection *c,
 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
 
-	connected = (conn->state == SAP_STATE_CONNECTED);
+	connected = (conn->state == SAP_STATE_CONNECTED ||
+			conn->state == SAP_STATE_GRACEFUL_DISCONNECT);
 	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &connected);
 
 	dbus_message_iter_close_container(&iter, &dict);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v5 2/4] Add support for SAP protocol
  2011-03-16 12:10 [PATCH v5 1/4] Sim Access Profile connect/disconnect procedures Waldemar Rymarkiewicz
@ 2011-03-16 12:10 ` Waldemar Rymarkiewicz
  2011-03-16 22:06   ` ANGUS.H
  2011-03-16 12:10 ` [PATCH v5 3/4] Sim Access Profile dummy driver Waldemar Rymarkiewicz
  2011-03-16 12:10 ` [PATCH v5 4/4] Sim Access Profile test scripts Waldemar Rymarkiewicz
  2 siblings, 1 reply; 11+ messages in thread
From: Waldemar Rymarkiewicz @ 2011-03-16 12:10 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth, Waldemar Rymarkiewicz

Add new protocol features:
	* transfer APDu request/response
	* get ATR request/response
	* power sim of/on request/response
	* card reader status
	* set transport protocol
---
 sap/server.c |  415 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 399 insertions(+), 16 deletions(-)

diff --git a/sap/server.c b/sap/server.c
index 8337fe1..35abffb 100644
--- a/sap/server.c
+++ b/sap/server.c
@@ -89,6 +89,44 @@ static void start_guard_timer(struct sap_connection *conn, guint interval);
 static void stop_guard_timer(struct sap_connection *conn);
 static gboolean guard_timeout(gpointer data);
 
+static size_t add_result_parameter(uint8_t result,
+					struct sap_parameter *param)
+{
+	param->id = SAP_PARAM_ID_RESULT_CODE;
+	param->len = htons(SAP_PARAM_ID_RESULT_CODE_LEN);
+	*param->val = result;
+
+	return PARAMETER_SIZE(SAP_PARAM_ID_RESULT_CODE_LEN);
+}
+
+static int is_power_sim_off_req_allowed(uint8_t processing_req)
+{
+	switch (processing_req) {
+	case SAP_NO_REQ:
+	case SAP_TRANSFER_APDU_REQ:
+	case SAP_TRANSFER_ATR_REQ:
+	case SAP_POWER_SIM_ON_REQ:
+	case SAP_RESET_SIM_REQ:
+	case SAP_TRANSFER_CARD_READER_STATUS_REQ:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int is_reset_sim_req_allowed(uint8_t processing_req)
+{
+	switch (processing_req) {
+	case SAP_NO_REQ:
+	case SAP_TRANSFER_APDU_REQ:
+	case SAP_TRANSFER_ATR_REQ:
+	case SAP_TRANSFER_CARD_READER_STATUS_REQ:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
 static int check_msg(struct sap_message *msg)
 {
 	if (!msg)
@@ -375,38 +413,159 @@ error_req:
 static void transfer_apdu_req(struct sap_connection *conn,
 					struct sap_parameter *param)
 {
-	DBG("SAP_APDU_REQUEST");
+	DBG("conn %p state %d", conn, conn->state);
+
+	if (!param)
+		goto error_rsp;
+
+	param->len = ntohs(param->len);
+
+	if (conn->state != SAP_STATE_CONNECTED &&
+			conn->state != SAP_STATE_GRACEFUL_DISCONNECT)
+		goto error_rsp;
+
+	if (conn->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	conn->processing_req = SAP_TRANSFER_APDU_REQ;
+	sap_transfer_apdu_req(conn, param);
+
+	return;
+
+error_rsp:
+	error("Processing error (param %p state %d pr 0x%02x)", param,
+					conn->state, conn->processing_req);
+	sap_error_rsp(conn);
 }
 
 static void transfer_atr_req(struct sap_connection *conn)
 {
-	DBG("SAP_ATR_REQUEST");
+	DBG("conn %p state %d", conn, conn->state);
+
+	if (conn->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (conn->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	conn->processing_req = SAP_TRANSFER_ATR_REQ;
+	sap_transfer_atr_req(conn);
+
+	return;
+
+error_rsp:
+	error("Processing error (state %d pr 0x%02x)", conn->state,
+						conn->processing_req);
+	sap_error_rsp(conn);
 }
 
 static void power_sim_off_req(struct sap_connection *conn)
 {
-	DBG("SAP_SIM_OFF_REQUEST");
+	DBG("conn %p state %d", conn, conn->state);
+
+	if (conn->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (!is_power_sim_off_req_allowed(conn->processing_req))
+		goto error_rsp;
+
+	conn->processing_req = SAP_POWER_SIM_OFF_REQ;
+	sap_power_sim_off_req(conn);
+
+	return;
+
+error_rsp:
+	error("Processing error (state %d pr 0x%02x)", conn->state,
+						conn->processing_req);
+	sap_error_rsp(conn);
 }
 
 static void power_sim_on_req(struct sap_connection *conn)
 {
-	DBG("SAP_SIM_ON_REQUEST");
+	DBG("conn %p state %d", conn, conn->state);
+
+	if (conn->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (conn->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	conn->processing_req = SAP_POWER_SIM_ON_REQ;
+	sap_power_sim_on_req(conn);
+
+	return;
+
+error_rsp:
+	error("Processing error (state %d pr 0x%02x)", conn->state,
+						conn->processing_req);
+	sap_error_rsp(conn);
 }
 
 static void reset_sim_req(struct sap_connection *conn)
 {
-	DBG("SAP_RESET_SIM_REQUEST");
+	DBG("conn %p state %d", conn, conn->state);
+
+	if (conn->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (!is_reset_sim_req_allowed(conn->processing_req))
+		goto error_rsp;
+
+	conn->processing_req = SAP_RESET_SIM_REQ;
+	sap_reset_sim_req(conn);
+
+	return;
+
+error_rsp:
+	error("Processing error (state %d pr 0x%02x param)", conn->state,
+						conn->processing_req);
+	sap_error_rsp(conn);
 }
 
 static void transfer_card_reader_status_req(struct sap_connection *conn)
 {
-	DBG("SAP_TRANSFER_CARD_READER_STATUS_REQUEST");
+	DBG("conn %p state %d", conn, conn->state);
+
+	if (conn->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (conn->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	conn->processing_req = SAP_TRANSFER_CARD_READER_STATUS_REQ;
+	sap_transfer_card_reader_status_req(conn);
+
+	return;
+
+error_rsp:
+	error("Processing error (state %d pr 0x%02x)", conn->state,
+						conn->processing_req);
+	sap_error_rsp(conn);
 }
 
 static void set_transport_protocol_req(struct sap_connection *conn,
 					struct sap_parameter *param)
 {
-	DBG("SAP_SET_TRANSPORT_PROTOCOL_REQUEST");
+	if (!param)
+		goto error_rsp;
+
+	DBG("conn %p state %d param %p", conn, conn->state, param);
+
+	if (conn->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (conn->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	conn->processing_req = SAP_SET_TRANSPORT_PROTOCOL_REQ;
+	sap_set_transport_protocol_req(conn, param);
+
+	return;
+
+error_rsp:
+	error("Processing error (param %p state %d pr 0x%02x)", param,
+					conn->state, conn->processing_req);
+	sap_error_rsp(conn);
 }
 
 static void start_guard_timer(struct sap_connection *conn, guint interval)
@@ -572,49 +731,273 @@ int sap_disconnect_rsp(void *sap_device)
 int sap_transfer_apdu_rsp(void *sap_device, uint8_t result, uint8_t *apdu,
 					uint16_t length)
 {
-	return 0;
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("state %d pr 0x%02x", conn->state, conn->processing_req);
+
+	if (conn->processing_req != SAP_TRANSFER_APDU_REQ)
+		return 0;
+
+	if (result == SAP_RESULT_OK && (!apdu || (apdu && length == 0x00)))
+		return -EINVAL;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_TRANSFER_APDU_RESP;
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, param);
+
+	/* Add APDU response. */
+	if (result == SAP_RESULT_OK) {
+		msg->nparam++;
+		param = (struct sap_parameter *) &buf[size];
+		param->id = SAP_PARAM_ID_RESPONSE_APDU;
+		param->len = htons(length);
+
+		size += PARAMETER_SIZE(length);
+
+		if (size > SAP_BUF_SIZE)
+			return -EOVERFLOW;
+
+		memcpy(param->val, apdu, length);
+	}
+
+	conn->processing_req = SAP_NO_REQ;
+
+	return send_message(sap_device, buf, size);
 }
 
 int sap_transfer_atr_rsp(void *sap_device, uint8_t result, uint8_t *atr,
 					uint16_t length)
 {
-	return 0;
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("result 0x%02x state %d pr 0x%02x len %d", result, conn->state,
+			conn->processing_req, length);
+
+	if (conn->processing_req != SAP_TRANSFER_ATR_REQ)
+		return 0;
+
+	if (result == SAP_RESULT_OK && (!atr || (atr && length == 0x00)))
+		return -EINVAL;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_TRANSFER_ATR_RESP;
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, param);
+
+	/* Add ATR response */
+	if (result == SAP_RESULT_OK) {
+		msg->nparam++;
+		param = (struct sap_parameter *) &buf[size];
+		param->id = SAP_PARAM_ID_ATR;
+		param->len = htons(length);
+		size += PARAMETER_SIZE(length);
+
+		if (size > SAP_BUF_SIZE)
+			return -EOVERFLOW;
+
+		memcpy(param->val, atr, length);
+	}
+
+	conn->processing_req = SAP_NO_REQ;
+
+	return send_message(sap_device, buf, size);
 }
 
 int sap_power_sim_off_rsp(void *sap_device, uint8_t result)
 {
-	return 0;
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("state %d pr 0x%02x", conn->state, conn->processing_req);
+
+	if (conn->processing_req != SAP_POWER_SIM_OFF_REQ)
+		return 0;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_POWER_SIM_OFF_RESP;
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, msg->param);
+
+	conn->processing_req = SAP_NO_REQ;
+
+	return send_message(sap_device, buf, size);
 }
 
 int sap_power_sim_on_rsp(void *sap_device, uint8_t result)
 {
-	return 0;
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("state %d pr 0x%02x", conn->state, conn->processing_req);
+
+	if (conn->processing_req != SAP_POWER_SIM_ON_REQ)
+		return 0;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_POWER_SIM_ON_RESP;
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, msg->param);
+
+	conn->processing_req = SAP_NO_REQ;
+
+	return send_message(sap_device, buf, size);
 }
 
 int sap_reset_sim_rsp(void *sap_device, uint8_t result)
 {
-	return 0;
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("state %d pr 0x%02x result 0x%02x", conn->state,
+					conn->processing_req, result);
+
+	if (conn->processing_req != SAP_RESET_SIM_REQ)
+		return 0;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_RESET_SIM_RESP;
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, msg->param);
+
+	conn->processing_req = SAP_NO_REQ;
+
+	return send_message(sap_device, buf, size);
 }
 
 int sap_transfer_card_reader_status_rsp(void *sap_device, uint8_t result,
 						uint8_t status)
 {
-	return 0;
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("state %d pr 0x%02x result 0x%02x", conn->state,
+					conn->processing_req, result);
+
+	if (conn->processing_req != SAP_TRANSFER_CARD_READER_STATUS_REQ)
+		return 0;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_TRANSFER_CARD_READER_STATUS_RESP;
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, param);
+
+	/* Add card reader status. */
+	if (result == SAP_RESULT_OK) {
+		msg->nparam++;
+		param = (struct sap_parameter *) &buf[size];
+		param->id = SAP_PARAM_ID_CARD_READER_STATUS;
+		param->len = htons(SAP_PARAM_ID_CARD_READER_STATUS_LEN);
+		*param->val = status;
+		size += PARAMETER_SIZE(SAP_PARAM_ID_CARD_READER_STATUS_LEN);
+	}
+
+	conn->processing_req = SAP_NO_REQ;
+
+	return send_message(sap_device, buf, size);
 }
 
 int sap_transport_protocol_rsp(void *sap_device, uint8_t result)
 {
-	return 0;
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("state %d pr 0x%02x result 0x%02x", conn->state,
+					conn->processing_req, result);
+
+	if (conn->processing_req != SAP_SET_TRANSPORT_PROTOCOL_REQ)
+		return 0;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_SET_TRANSPORT_PROTOCOL_RESP;
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, msg->param);
+
+	conn->processing_req = SAP_NO_REQ;
+
+	return send_message(sap_device, buf, size);
 }
 
 int sap_error_rsp(void *sap_device)
 {
-	return 0;
+	struct sap_message msg;
+	struct sap_connection *conn = sap_device;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.id = SAP_ERROR_RESP;
+
+	return send_message(conn, &msg, sizeof(msg));
 }
 
 int sap_status_ind(void *sap_device, uint8_t status_change)
 {
-	return 0;
+	struct sap_connection *conn = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct sap_message);
+
+	if (!conn)
+		return -EINVAL;
+
+	DBG("state %d pr 0x%02x sc 0x%02x", conn->state, conn->processing_req,
+				status_change);
+
+	if (conn->state != SAP_STATE_CONNECTED &&
+			conn->state != SAP_STATE_GRACEFUL_DISCONNECT)
+		return 0;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_STATUS_IND;
+	msg->nparam = 0x01;
+
+	/* Add status change. */
+	param->id  = SAP_PARAM_ID_STATUS_CHANGE;
+	param->len = htons(SAP_PARAM_ID_STATUS_CHANGE_LEN);
+	*param->val = status_change;
+	size += PARAMETER_SIZE(SAP_PARAM_ID_STATUS_CHANGE_LEN);
+
+	return send_message(sap_device, buf, size);
 }
 
 static int handle_cmd(void *data, void *buf, size_t size)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v5 3/4] Sim Access Profile dummy driver
  2011-03-16 12:10 [PATCH v5 1/4] Sim Access Profile connect/disconnect procedures Waldemar Rymarkiewicz
  2011-03-16 12:10 ` [PATCH v5 2/4] Add support for SAP protocol Waldemar Rymarkiewicz
@ 2011-03-16 12:10 ` Waldemar Rymarkiewicz
  2011-03-23 13:00   ` Johan Hedberg
  2011-03-16 12:10 ` [PATCH v5 4/4] Sim Access Profile test scripts Waldemar Rymarkiewicz
  2 siblings, 1 reply; 11+ messages in thread
From: Waldemar Rymarkiewicz @ 2011-03-16 12:10 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth, Waldemar Rymarkiewicz

Add SAP dummy driver implementation and extend configure
with --with-sap=<driver>.
---
 .gitignore      |    1 +
 Makefile.am     |   13 +++-
 acinclude.m4    |    6 ++
 sap/sap-dummy.c |  269 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 275 insertions(+), 14 deletions(-)

diff --git a/.gitignore b/.gitignore
index 07e239f..3e36a59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@ lib/bluetooth
 src/builtin.h
 src/bluetoothd
 audio/telephony.c
+sap/sap.c
 scripts/bluetooth.rules
 scripts/97-bluetooth.rules
 scripts/97-bluetooth-hid2hci.rules
diff --git a/Makefile.am b/Makefile.am
index 7267200..2994bf9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -148,7 +148,13 @@ builtin_modules += sap
 builtin_sources += sap/main.c \
 			sap/manager.h sap/manager.c \
 			sap/server.h sap/server.c \
-			sap/sap.h sap/sap-dummy.c
+			sap/sap.h
+
+builtin_nodist += sap/sap.c
+
+noinst_LIBRARIES = sap/libsap.a
+
+sap_libsap_a_SOURCES = sap/sap.h sap/sap-dummy.c
 endif
 
 if INPUTPLUGIN
@@ -278,7 +284,7 @@ EXTRA_DIST += src/genbuiltin src/bluetooth.conf \
 			input/input.conf serial/serial.conf \
 			audio/audio.conf audio/telephony-dummy.c \
 			audio/telephony-maemo5.c audio/telephony-ofono.c \
-			audio/telephony-maemo6.c
+			audio/telephony-maemo6.c sap/sap-dummy.c
 
 
 if ALSA
@@ -403,6 +409,9 @@ src/builtin.h: src/genbuiltin $(builtin_sources)
 audio/telephony.c: audio/@TELEPHONY_DRIVER@
 	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
 
+sap/sap.c: sap/@SAP_DRIVER@
+	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+
 scripts/%.rules:
 	$(AM_V_GEN)cp $(subst 97-,,$@) $@
 
diff --git a/acinclude.m4 b/acinclude.m4
index d07418f..faa7f7c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -205,6 +205,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	configfiles_enable=yes
 	telephony_driver=dummy
 	maemo6_enable=no
+	sap_driver=dummy
 
 	AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable code optimization]), [
 		optimization_enable=${enableval}
@@ -226,6 +227,11 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		sap_enable=${enableval}
 	])
 
+	AC_ARG_WITH(sap, AC_HELP_STRING([--with-sap=DRIVER], [select SAP driver]), [
+		sap_driver=${withval}
+	])
+	AC_SUBST([SAP_DRIVER], [sap-${sap_driver}.c])
+
 	AC_ARG_ENABLE(serial, AC_HELP_STRING([--disable-serial], [disable serial plugin]), [
 		serial_enable=${enableval}
 	])
diff --git a/sap/sap-dummy.c b/sap/sap-dummy.c
index b433ba3..39e1fc9 100644
--- a/sap/sap-dummy.c
+++ b/sap/sap-dummy.c
@@ -2,6 +2,7 @@
  *  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
@@ -21,50 +22,185 @@
  *  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)
 {
-	sap_connect_rsp(sap_device, SAP_STATUS_OK, maxmsgsize);
-	sap_status_ind(sap_device, SAP_STATUS_CHANGE_CARD_RESET);
+	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)
 {
-	sap_transfer_apdu_rsp(sap_device, SAP_RESULT_OK, NULL, 0);
+	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)
 {
-	sap_transfer_atr_rsp(sap_device, SAP_RESULT_OK, NULL, 0);
+	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)
 {
-	sap_power_sim_off_rsp(sap_device, SAP_RESULT_OK);
+	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)
 {
-	sap_power_sim_on_rsp(sap_device, SAP_RESULT_OK);
+	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)
 {
-	sap_reset_sim_rsp(sap_device, SAP_RESULT_OK);
-	sap_status_ind(sap_device, SAP_STATUS_CHANGE_CARD_RESET);
+	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)
 {
-	sap_transfer_card_reader_status_rsp(sap_device, SAP_RESULT_OK,
-						ICC_READER_CARD_POWERED_ON);
+	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,
@@ -73,13 +209,122 @@ void sap_set_transport_protocol_req(void *sap_device,
 	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)
 {
-	DBG("SAP driver init.");
+	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)
 {
-	DBG("SAP driver exit.");
+	dbus_connection_unref(connection);
+	connection = NULL;
 }
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v5 4/4] Sim Access Profile test scripts
  2011-03-16 12:10 [PATCH v5 1/4] Sim Access Profile connect/disconnect procedures Waldemar Rymarkiewicz
  2011-03-16 12:10 ` [PATCH v5 2/4] Add support for SAP protocol Waldemar Rymarkiewicz
  2011-03-16 12:10 ` [PATCH v5 3/4] Sim Access Profile dummy driver Waldemar Rymarkiewicz
@ 2011-03-16 12:10 ` Waldemar Rymarkiewicz
  2011-03-23 13:02   ` Johan Hedberg
  2 siblings, 1 reply; 11+ messages in thread
From: Waldemar Rymarkiewicz @ 2011-03-16 12:10 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth, Waldemar Rymarkiewicz

Add simple SAP client python implementation and a test script.

To run test-sap.py you need Python 2.6 or newer (tested with 2.6 only)
and PyBluez package installed.
---
 test/sap.py      |  944 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/test-sap.py |  139 ++++++++
 2 files changed, 1083 insertions(+), 0 deletions(-)
 create mode 100644 test/sap.py
 create mode 100755 test/test-sap.py

diff --git a/test/sap.py b/test/sap.py
new file mode 100644
index 0000000..5a0c711
--- /dev/null
+++ b/test/sap.py
@@ -0,0 +1,944 @@
+""" Copyright (C) 2011 Tieto """
+
+""" Szymon Janc <szymon.janc@tieto.com> """
+""" Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> """
+
+""" 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 """
+
+from array import array
+from bluetooth import *
+import time
+import re
+
+class SAPParam:
+    """ SAP Parameter Class """
+
+    MaxMsgSize = 0x00
+    ConnectionStatus = 0x01
+    ResultCode = 0x02
+    DisconnectionType = 0x03
+    CommandAPDU = 0x04
+    ResponseAPDU = 0x05
+    ATR = 0x06
+    CardReaderStatus = 0x07
+    StatusChange = 0x08
+    TransportProtocol = 0x09
+    CommandAPDU7816 = 0x10
+
+    def __init__(self, name, id, value = None):
+        self.name = name
+        self.id = id
+        self.value = value
+
+    def _padding(self,  buf):
+        pad = array('B')
+        while ( (len(buf) + len(pad)) % 4 ) != 0:
+            pad.append(0)
+        return pad
+
+    def _basicCheck(self,  buf):
+        if len(buf) < 4 or (len(buf) % 4) != 0 or buf[1] != 0:
+                return (-1,  -1)
+        if buf[0] != self.id:
+            return (-1,  -1)
+        plen = buf[2] * 256 + buf[3] + 4
+        if plen > len(buf):
+            return (-1,  -1)
+        pad = plen
+        while (pad % 4) != 0:
+            if buf[pad] != 0:
+                return (-1,  -1)
+            pad+=1
+        return (plen,  pad)
+
+    def getID(self):
+        return self.id
+
+    def getValue(self):
+        return self.value
+
+    def getContent(self):
+        return "%s(id=0x%.2X), value=%s \n" %  (self.name,  self.id, self.value)
+
+    def serialize(self):
+        a = array('B', '\00\00\00\00')
+        a[0] = self.id
+        a[1] = 0	# reserved
+        a[2] = 0	# length
+        a[3] = 1	# length
+        a.append(self.value)
+        a.extend(self._padding(a))
+        return a
+
+    def deserialize(self,  buf):
+        p = self._basicCheck(buf)
+        if p[0] == -1:
+            return -1
+        self.id = buf[0]
+        self.value = buf[4]
+        return p[1]
+
+
+class SAPParam_MaxMsgSize(SAPParam):
+    """MaxMsgSize Param """
+
+    def __init__(self,  value = None):
+        SAPParam.__init__(self,"MaxMsgSize",  SAPParam.MaxMsgSize, value)
+        self.__validate()
+
+    def __validate(self):
+        if self.value > 0xFFFF:
+             self.value = 0xFFFF
+
+    def serialize(self):
+        a = array('B', '\00\00\00\00')
+        a[0] = self.id
+        a[3] = 2
+        a.append(self.value / 256)
+        a.append(self.value % 256)
+        a.extend(self._padding(a))
+        return a
+
+    def deserialize(self,  buf):
+        p = self._basicCheck(buf)
+        if p[0] == -1 :
+            return -1
+        self.value = buf[4] * 256 + buf[5]
+        return p[1]
+
+class SAPParam_CommandAPDU(SAPParam):
+    def __init__(self,  value = None):
+        if value is None:
+            SAPParam.__init__(self, "CommandAPDU",  SAPParam.CommandAPDU, array('B'))
+        else:
+            SAPParam.__init__(self, "CommandAPDU",  SAPParam.CommandAPDU, array('B', value))
+
+    def serialize(self):
+        a = array('B', '\00\00\00\00')
+        a[0] = self.id
+        plen = len(self.value)
+        a[2] = plen / 256
+        a[3] = plen % 256
+        a.extend(self.value)
+        a.extend(self._padding(a))
+        return a
+
+    def deserialize(self,  buf):
+        p = self._basicCheck(buf)
+        if p[0] == -1:
+            return -1
+        self.value = buf[4:p[0]]
+        return p[1]
+
+class SAPParam_ResponseAPDU(SAPParam_CommandAPDU):
+    """ResponseAPDU Param """
+
+    def __init__(self,  value = None):
+        if value is None:
+            SAPParam.__init__(self, "ResponseAPDU",  SAPParam.ResponseAPDU, array('B'))
+        else:
+            SAPParam.__init__(self, "ResponseAPDU",  SAPParam.ResponseAPDU, array('B', value))
+
+class SAPParam_ATR(SAPParam_CommandAPDU):
+    """ATR Param """
+
+    def __init__(self,  value = None):
+        if value is None:
+            SAPParam.__init__(self, "ATR",  SAPParam.ATR, array('B'))
+        else:
+            SAPParam.__init__(self, "ATR",  SAPParam.ATR, array('B', value))
+
+class SAPParam_CommandAPDU7816(SAPParam_CommandAPDU):
+    """Command APDU7816 Param."""
+
+    def __init__(self,  value = None):
+        if value is None:
+            SAPParam.__init__(self, "CommandAPDU7816",  SAPParam.CommandAPDU7816, array('B'))
+        else:
+            SAPParam.__init__(self, "CommandAPDU7816",  SAPParam.CommandAPDU7816, array('B', value))
+
+
+class SAPParam_ConnectionStatus(SAPParam):
+    """Connection status Param."""
+
+    def __init__(self,  value = None):
+        SAPParam.__init__(self,"ConnectionStatus",  SAPParam.ConnectionStatus, value)
+        self.__validate()
+
+    def __validate(self):
+        if self.value is not None and self.value not in (0x00,  0x01,  0x02,  0x03,  0x04):
+            print "Warning. ConnectionStatus value in reserved range (0x%x)" % self.value
+
+    def deserialize(self,  buf):
+        ret = SAPParam.deserialize(self, buf)
+        if ret == -1:
+            return -1
+        self.__validate()
+        return ret
+
+class SAPParam_ResultCode(SAPParam):
+    """ Result Code Param """
+
+    def __init__(self,  value = None):
+        SAPParam.__init__(self,"ResultCode",  SAPParam.ResultCode, value)
+        self.__validate()
+
+    def __validate(self):
+        if self.value is not None and self.value not in (0x00,  0x01,  0x02,  0x03,  0x04,  0x05,  0x06,  0x07):
+            print "Warning. ResultCode value in reserved range (0x%x)" % self.value
+
+    def deserialize(self,  buf):
+        ret = SAPParam.deserialize(self, buf)
+        if ret == -1:
+            return -1
+        self.__validate()
+        return ret
+
+class SAPParam_DisconnectionType(SAPParam):
+    """Disconnection Type Param."""
+
+    def __init__(self,  value = None):
+        SAPParam.__init__(self,"DisconnectionType",  SAPParam.DisconnectionType, value)
+        self.__validate()
+
+    def __validate(self):
+        if self.value is not None and self.value not in (0x00,  0x01):
+            print "Warning. DisconnectionType value in reserved range (0x%x)" % self.value
+
+    def deserialize(self,  buf):
+        ret = SAPParam.deserialize(self, buf)
+        if ret == -1:
+            return -1
+        self.__validate()
+        return ret
+
+class SAPParam_CardReaderStatus(SAPParam_CommandAPDU):
+    """Card reader Status Param."""
+
+    def __init__(self,  value = None):
+        if value is None:
+            SAPParam.__init__(self, "CardReaderStatus",  SAPParam.CardReaderStatus, array('B'))
+        else:
+            SAPParam.__init__(self, "CardReaderStatus",  SAPParam.CardReaderStatus, array('B', value))
+
+class SAPParam_StatusChange(SAPParam):
+    """Status Change Param """
+
+    def __init__(self,  value = None):
+        SAPParam.__init__(self,"StatusChange",  SAPParam.StatusChange, value)
+
+    def __validate(self):
+        if self.value is not None and self.value not in (0x00,  0x01,  0x02,  0x03,  0x04,  0x05):
+            print "Warning. StatusChange value in reserved range (0x%x)" % self.value
+
+    def deserialize(self,  buf):
+        ret = SAPParam.deserialize(self, buf)
+        if ret == -1:
+            return -1
+        self.__validate()
+        return ret
+
+class SAPParam_TransportProtocol(SAPParam):
+    """Transport Protocol Param """
+
+    def __init__(self,  value = None):
+        SAPParam.__init__(self,"TransportProtocol",  SAPParam.TransportProtocol, value)
+        self.__validate()
+
+    def __validate(self):
+        if self.value is not None and self.value not in (0x00,  0x01):
+            print "Warning. TransportProtoco value in reserved range (0x%x)" % self.value
+
+    def deserialize(self,  buf):
+        ret = SAPParam.deserialize(self, buf)
+        if ret == -1:
+            return -1
+        self.__validate()
+        return ret
+
+class SAPMessage:
+
+    CONNECT_REQ = 0x00
+    CONNECT_RESP = 0x01
+    DISCONNECT_REQ = 0x02
+    DISCONNECT_RESP =0x03
+    DISCONNECT_IND = 0x04
+    TRANSFER_APDU_REQ = 0x05
+    TRANSFER_APDU_RESP = 0x06
+    TRANSFER_ATR_REQ = 0x07
+    TRANSFER_ATR_RESP = 0x08
+    POWER_SIM_OFF_REQ = 0x09
+    POWER_SIM_OFF_RESP = 0x0A
+    POWER_SIM_ON_REQ = 0x0B
+    POWER_SIM_ON_RESP = 0x0C
+    RESET_SIM_REQ = 0x0D
+    RESET_SIM_RESP = 0x0E
+    TRANSFER_CARD_READER_STATUS_REQ = 0x0F
+    TRANSFER_CARD_READER_STATUS_RESP = 0x10
+    STATUS_IND = 0x11
+    ERROR_RESP = 0x12
+    SET_TRANSPORT_PROTOCOL_REQ = 0x13
+    SET_TRANSPORT_PROTOCOL_RESP = 0x14
+
+    def __init__(self,  name,  id):
+        self.name = name
+        self.id = id
+        self.params = []
+        self.buf = array('B')
+
+    def _basicCheck(self,  buf):
+        if len(buf) < 4 or (len(buf) % 4) != 0 :
+            return False
+
+        if buf[0] != self.id:
+            return False
+
+        return True
+
+    def getID(self):
+        return self.id
+
+    def getContent(self):
+        s = "%s(id=0x%.2X) " % (self.name,  self.id)
+        if len( self.buf): s = s + "[%s]" % re.sub("(.{2})", "0x\\1 " , self.buf.tostring().encode("hex").upper(), re.DOTALL)
+        s = s + "\n\t"
+        for p in self.params:
+            s = s + "\t" + p.getContent()
+        return s
+
+    def getParams(self):
+        return self.params
+
+    def addParam(self,  param):
+        self.params.append(param)
+
+    def serialize(self):
+        ret = array('B', '\00\00\00\00')
+        ret[0] = self.id
+        ret[1] = len(self.params)
+        ret[2] = 0	# reserved
+        ret[3] = 0	# reserved
+        for p in self.params:
+            ret.extend(p.serialize())
+
+        self.buf = ret
+        return ret
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        return len(buf) == 4 and buf[1] == 0 and self._basicCheck(buf)
+
+
+class SAPMessage_CONNECT_REQ(SAPMessage):
+    def __init__(self,  MaxMsgSize = None):
+        SAPMessage.__init__(self,"CONNECT_REQ",  SAPMessage.CONNECT_REQ)
+        if MaxMsgSize is not None:
+            self.addParam(SAPParam_MaxMsgSize(MaxMsgSize))
+
+    def _validate(self):
+        if len(self.params) == 1:
+            if self.params[0].getID() == SAPParam.MaxMsgSize:
+                return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+        if SAPMessage._basicCheck(self,  buf):
+            p = SAPParam_MaxMsgSize()
+            if p.deserialize(buf[4:]) == len(buf[4:]):
+                self.addParam(p)
+                return self._validate()
+
+        return False
+
+class SAPMessage_CONNECT_RESP(SAPMessage):
+    def __init__(self,  ConnectionStatus = None,  MaxMsgSize = None):
+        SAPMessage.__init__(self,"CONNECT_RESP",  SAPMessage.CONNECT_RESP)
+        if ConnectionStatus is not None:
+            self.addParam(SAPParam_ConnectionStatus(ConnectionStatus))
+            if MaxMsgSize is not None:
+                self.addParam(SAPParam_MaxMsgSize(MaxMsgSize))
+
+    def _validate(self):
+        if len(self.params) > 0:
+            if self.params[0] .getID() == SAPParam.ConnectionStatus:
+                if self.params[0].getValue() ==  0x02:
+                    if len(self.params) == 2:
+                        return True
+                else:
+                    if len(self.params) == 1:
+                        return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+
+        if SAPMessage._basicCheck(self,  buf):
+            p = SAPParam_ConnectionStatus()
+            r = p.deserialize(buf[4:])
+            if  r != -1:
+                self.addParam(p)
+                if buf[1] == 2:
+                    p = SAPParam_MaxMsgSize()
+                    r = p.deserialize(buf[4+r:])
+                    if r != -1:
+                        self.addParam(p)
+
+                return self._validate()
+
+        return False
+
+class SAPMessage_DISCONNECT_REQ(SAPMessage):
+    def __init__(self):
+        SAPMessage.__init__(self,"DISCONNECT_REQ",  SAPMessage.DISCONNECT_REQ)
+
+class SAPMessage_DISCONNECT_RESP(SAPMessage):
+    def __init__(self):
+        SAPMessage.__init__(self,"DISCONNECT_RESP",  SAPMessage.DISCONNECT_RESP)
+
+class SAPMessage_DISCONNECT_IND(SAPMessage):
+    def __init__(self,  Type = None):
+        SAPMessage.__init__(self,"DISCONNECT_IND",  SAPMessage.DISCONNECT_IND)
+        if Type is not None:
+            self.addParam(SAPParam_DisconnectionType(Type))
+
+    def _validate(self):
+        if len(self.params) == 1:
+            if self.params[0].getID() == SAPParam.DisconnectionType:
+                return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+        if SAPMessage._basicCheck(self,  buf):
+            p = SAPParam_DisconnectionType()
+            if p.deserialize(buf[4:]) == len(buf[4:]):
+                self.addParam(p)
+                return self._validate()
+
+        return False
+
+
+class SAPMessage_TRANSFER_APDU_REQ(SAPMessage):
+    def __init__(self,  APDU = None,  T = False):
+        SAPMessage.__init__(self,"TRANSFER_APDU_REQ",  SAPMessage.TRANSFER_APDU_REQ)
+        if APDU is not None:
+            if T :
+                self.addParam(SAPParam_CommandAPDU(APDU))
+            else:
+                self.addParam(SAPParam_CommandAPDU7816(APDU))
+
+    def _validate(self):
+        if len(self.params) == 1:
+            if self.params[0].getID() == SAPParam.CommandAPDU or self.params[0].getID() == SAPParam.CommandAPDU7816:
+                return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+        if SAPMessage._basicCheck(self,  buf):
+
+            p = SAPParam_CommandAPDU()
+            p2 = SAPParam_CommandAPDU7816()
+            if p.deserialize(buf[4:]) == len(buf[4:]):
+                self.addParam(p)
+                return self._validate()
+            elif p2.deserialize(buf[4:]) == len(buf[4:]):
+                self.addParam(p2)
+                return self._validate()
+
+        return False
+
+class SAPMessage_TRANSFER_APDU_RESP(SAPMessage):
+    def __init__(self,  ResultCode = None,  Response = None):
+        SAPMessage.__init__(self,"TRANSFER_APDU_RESP",  SAPMessage.TRANSFER_APDU_RESP)
+        if ResultCode is not None:
+            self.addParam(SAPParam_ResultCode(ResultCode))
+            if Response is not None:
+                self.addParam(SAPParam_ResponseAPDU(Response))
+
+    def _validate(self):
+        if len(self.params) > 0:
+            if self.params[0] .getID() == SAPParam.ResultCode:
+                if self.params[0].getValue() == 0x00:
+                    if len(self.params) == 2:
+                        return True
+                else:
+                    if len(self.params) == 1:
+                        return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+
+        if SAPMessage._basicCheck(self,  buf):
+            p = SAPParam_ResultCode()
+            r = p.deserialize(buf[4:])
+            if  r != -1:
+                self.addParam(p)
+                if buf[1] == 2:
+                    p = SAPParam_ResponseAPDU()
+                    r = p.deserialize(buf[4+r:])
+                    if r != -1:
+                        self.addParam(p)
+
+                return self._validate()
+
+        return False
+
+class SAPMessage_TRANSFER_ATR_REQ(SAPMessage):
+    def __init__(self):
+        SAPMessage.__init__(self,"TRANSFER_ATR_REQ",  SAPMessage.TRANSFER_ATR_REQ)
+
+class SAPMessage_TRANSFER_ATR_RESP(SAPMessage):
+    def __init__(self,  ResultCode = None,  ATR = None):
+        SAPMessage.__init__(self,"TRANSFER_ATR_RESP",  SAPMessage.TRANSFER_ATR_RESP)
+        if ResultCode is not None:
+            self.addParam(SAPParam_ResultCode(ResultCode))
+            if ATR is not None:
+                self.addParam(SAPParam_ATR(ATR))
+
+    def _validate(self):
+        if len(self.params) > 0:
+            if self.params[0] .getID() == SAPParam.ResultCode:
+                if self.params[0].getValue() == 0x00:
+                    if len(self.params) == 2:
+                        return True
+                else:
+                    if len(self.params) == 1:
+                        return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+
+        if SAPMessage._basicCheck(self,  buf):
+
+            p = SAPParam_ResultCode()
+            r = p.deserialize(buf[4:])
+
+            if  r != -1:
+
+                self.addParam(p)
+                if buf[1] == 2:
+
+                    p = SAPParam_ATR()
+                    r = p.deserialize(buf[4+r:])
+                    if r != -1:
+                        self.addParam(p)
+
+                return self._validate()
+
+        return False
+
+class SAPMessage_POWER_SIM_OFF_REQ(SAPMessage):
+    def __init__(self):
+        SAPMessage.__init__(self,"POWER_SIM_OFF_REQ",  SAPMessage.POWER_SIM_OFF_REQ)
+
+class SAPMessage_POWER_SIM_OFF_RESP(SAPMessage):
+    def __init__(self,  ResultCode = None):
+        SAPMessage.__init__(self,"POWER_SIM_OFF_RESP",  SAPMessage.POWER_SIM_OFF_RESP)
+        if ResultCode is not None:
+            self.addParam(SAPParam_ResultCode(ResultCode))
+
+    def _validate(self):
+        if len(self.params) == 1:
+            if self.params[0].getID() == SAPParam.ResultCode:
+                return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+        if SAPMessage._basicCheck(self,  buf):
+            p = SAPParam_ResultCode()
+            if p.deserialize(buf[4:]) == len(buf[4:]):
+                self.addParam(p)
+                return self._validate()
+
+        return False
+
+class SAPMessage_POWER_SIM_ON_REQ(SAPMessage):
+    def __init__(self):
+        SAPMessage.__init__(self,"POWER_SIM_ON_REQ",  SAPMessage.POWER_SIM_ON_REQ)
+
+class SAPMessage_POWER_SIM_ON_RESP(SAPMessage_POWER_SIM_OFF_RESP):
+    def __init__(self,  ResultCode = None):
+        SAPMessage.__init__(self,"POWER_SIM_ON_RESP",  SAPMessage.POWER_SIM_ON_RESP)
+        if ResultCode is not None:
+            self.addParam(SAPParam_ResultCode(ResultCode))
+
+class SAPMessage_RESET_SIM_REQ(SAPMessage):
+    def __init__(self):
+        SAPMessage.__init__(self,"RESET_SIM_REQ",  SAPMessage.RESET_SIM_REQ)
+
+class SAPMessage_RESET_SIM_RESP(SAPMessage_POWER_SIM_OFF_RESP):
+    def __init__(self,  ResultCode = None):
+        SAPMessage.__init__(self,"RESET_SIM_RESP",  SAPMessage.RESET_SIM_RESP)
+        if ResultCode is not None:
+            self.addParam(SAPParam_ResultCode(ResultCode))
+
+class SAPMessage_STATUS_IND(SAPMessage):
+    def __init__(self,  StatusChange = None):
+        SAPMessage.__init__(self,"STATUS_IND",  SAPMessage.STATUS_IND)
+        if StatusChange is not None:
+            self.addParam(SAPParam_StatusChange(StatusChange))
+
+    def _validate(self):
+        if len(self.params) == 1:
+            if self.params[0].getID() == SAPParam.StatusChange:
+                return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+        if SAPMessage._basicCheck(self,  buf):
+            p = SAPParam_StatusChange()
+            if p.deserialize(buf[4:]) == len(buf[4:]):
+                self.addParam(p)
+                return self._validate()
+
+        return False
+
+class SAPMessage_TRANSFER_CARD_READER_STATUS_REQ(SAPMessage):
+    def __init__(self):
+        SAPMessage.__init__(self,"TRANSFER_CARD_READER_STATUS_REQ",  SAPMessage.TRANSFER_CARD_READER_STATUS_REQ)
+
+class SAPMessage_TRANSFER_CARD_READER_STATUS_RESP(SAPMessage):
+    def __init__(self,  ResultCode = None,  Status = None):
+        SAPMessage.__init__(self,"TRANSFER_CARD_READER_STATUS_RESP",  SAPMessage.TRANSFER_CARD_READER_STATUS_RESP)
+        if ResultCode is not None:
+            self.addParam(SAPParam_ResultCode(ResultCode))
+            if Status is not None:
+                self.addParam(SAPParam_CardReaderStatus(Status))
+
+    def _validate(self):
+        if len(self.params) > 0:
+            if self.params[0] .getID() == SAPParam.ResultCode:
+                if self.params[0].getValue() == 0x00:
+                    if len(self.params) == 2:
+                        return True
+                else:
+                    if len(self.params) == 1:
+                        return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+
+        if SAPMessage._basicCheck(self,  buf):
+            p = SAPParam_ResultCode()
+            r = p.deserialize(buf[4:])
+            if  r != -1:
+                self.addParam(p)
+                if buf[1] == 2:
+                    p = SAPParam_CardReaderStatus()
+                    r = p.deserialize(buf[4+r:])
+                    if r != -1:
+                        self.addParam(p)
+
+                return self._validate()
+
+        return False
+
+class SAPMessage_ERROR_RESP(SAPMessage):
+    def __init__(self):
+        SAPMessage.__init__(self,"ERROR_RESP",  SAPMessage.ERROR_RESP)
+
+
+class SAPMessage_SET_TRANSPORT_PROTOCOL_REQ(SAPMessage):
+    def __init__(self,  protocol = None):
+        SAPMessage.__init__(self,"SET_TRANSPORT_PROTOCOL_REQ",  SAPMessage.SET_TRANSPORT_PROTOCOL_REQ)
+        if protocol is not None:
+            self.addParam(SAPParam_TransportProtocol(protocol))
+
+    def _validate(self):
+        if len(self.params) == 1:
+            if self.params[0].getID() == SAPParam.TransportProtocol:
+                return True
+        return False
+
+    def deserialize(self,  buf):
+        self.buf = buf
+        self.params[:] = []
+        if SAPMessage._basicCheck(self,  buf):
+            p = SAPParam_TransportProtocol()
+            if p.deserialize(buf[4:]) == len(buf[4:]):
+                self.addParam(p)
+                return self._validate()
+
+        return False
+
+class SAPMessage_SET_TRANSPORT_PROTOCOL_RESP(SAPMessage_POWER_SIM_OFF_RESP):
+    def __init__(self,  ResultCode = None):
+        SAPMessage.__init__(self,"SET_TRANSPORT_PROTOCOL_RESP",  SAPMessage.SET_TRANSPORT_PROTOCOL_RESP)
+        if ResultCode is not None:
+            self.addParam(SAPParam_ResultCode(ResultCode))
+
+
+class SAPClient:
+
+    CONNECTED = 1
+    DISCONNECTED = 0
+
+    uuid = "0000112D-0000-1000-8000-00805F9B34FB"
+    bufsize = 1024
+    timeout = 20
+    state = DISCONNECTED
+
+    def __init__(self,  host = None,  port = None):
+        self.sock = None
+
+        if host is None or is_valid_address(host):
+            self.host = host
+        else:
+            raise BluetoothError ("%s is not a valid BT address." % host)
+            self.host = None
+            return
+
+        if port is None:
+            self.__discover()
+        else:
+            self.port = port
+
+        self.__connectRFCOMM()
+
+    def __del__(self):
+        self.__disconnectRFCOMM()
+
+    def __disconnectRFCOMM(self):
+        if self.sock is not None:
+            self.sock.close()
+            self.state = self.DISCONNECTED
+
+    def __discover(self):
+        service_matches = find_service(self.uuid, self.host)
+
+        if len(service_matches) == 0:
+            raise BluetoothError ("No SAP service found")
+            return
+
+        first_match = service_matches[0]
+        self.port = first_match["port"]
+        self.host = first_match["host"]
+
+        print "SAP Service found on %s(%s)" % first_match["name"] % self.host
+
+    def __connectRFCOMM(self):
+        self.sock=BluetoothSocket( RFCOMM )
+        self.sock.connect((self.host, self.port))
+        self.sock.settimeout(self.timeout)
+        self.state = self.CONNECTED
+
+    def __sendMsg(self, msg):
+        if isinstance(msg,  SAPMessage):
+            s = msg.serialize()
+            print "\tTX: " + msg.getContent()
+            return self.sock.send(s.tostring())
+
+    def __rcvMsg(self,  msg):
+        if isinstance(msg,  SAPMessage):
+            print "\tRX Wait: %s(id = 0x%.2x)" % (msg.name, msg.id)
+            data = self.sock.recv(self.bufsize)
+            if data:
+                if msg.deserialize(array('B',data)):
+                    print "\tRX: len(%d) %s" % (len(data), msg.getContent())
+                    return msg
+                else:
+                    print "msg: %s" % array('B',data)
+                    raise BluetoothError ("Message deserialization failed.")
+            else:
+                raise BluetoothError ("Timeout. No data received.")
+
+    def connect(self):
+        self.__connectRFCOMM()
+
+    def disconnect(self):
+        self.__disconnectRFCOMM()
+
+    def isConnected(self):
+        return self.state
+
+    def proc_connect(self):
+        try:
+            self.__sendMsg(SAPMessage_CONNECT_REQ(self.bufsize))
+            params = self.__rcvMsg(SAPMessage_CONNECT_RESP()).getParams()
+
+            if params[0].getValue() in (0x00,  0x04):
+                pass
+            elif params[0].getValue() == 0x02:
+                self.bufsize = params[1].getValue()
+
+                self.__sendMsg(SAPMessage_CONNECT_REQ(self.bufsize))
+                params = self.__rcvMsg(SAPMessage_CONNECT_RESP()).getParams()
+
+                if params[0].getValue() not in (0x00,  0x04):
+                    return False
+            else:
+                return False
+
+            params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
+            if params[0].getValue() == 0x00:
+                return False
+            elif params[0].getValue() == 0x01:
+                """OK, Card reset"""
+                return self.proc_transferATR()
+            elif params[0].getValue() == 0x02:
+                """T0 not supported"""
+                if self.proc_transferATR():
+                    return self.proc_setTransportProtocol(1)
+                else:
+                    return False
+            else:
+                return False
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_disconnectByClient(self, timeout=0):
+        try:
+            self.__sendMsg(SAPMessage_DISCONNECT_REQ())
+            self.__rcvMsg(SAPMessage_DISCONNECT_RESP())
+            time.sleep(timeout) # let srv to close rfcomm
+            self.__disconnectRFCOMM()
+            return True
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_disconnectByServer(self, timeout=0):
+        try:
+            params = self.__rcvMsg(SAPMessage_DISCONNECT_IND()).getParams()
+
+            """gracefull"""
+            if params[0].getValue() == 0x00:
+                if not self.proc_transferAPDU():
+                    return False
+
+            return self.proc_disconnectByClient(timeout)
+
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_transferAPDU(self,  apdu = "Sample APDU command"):
+        try:
+            self.__sendMsg(SAPMessage_TRANSFER_APDU_REQ(apdu))
+            params = self.__rcvMsg(SAPMessage_TRANSFER_APDU_RESP()).getParams()
+            return True
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_transferATR(self):
+        try:
+            self.__sendMsg(SAPMessage_TRANSFER_ATR_REQ())
+            params = self.__rcvMsg(SAPMessage_TRANSFER_ATR_RESP()).getParams()
+            return True
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_powerSimOff(self):
+        try:
+            self.__sendMsg(SAPMessage_POWER_SIM_OFF_REQ())
+            params = self.__rcvMsg(SAPMessage_POWER_SIM_OFF_RESP()).getParams()
+            return True
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_powerSimOn(self):
+        try:
+            self.__sendMsg(SAPMessage_POWER_SIM_ON_REQ())
+            params = self.__rcvMsg(SAPMessage_POWER_SIM_ON_RESP()).getParams()
+            if params[0].getValue() == 0x00:
+                return self.proc_transferATR()
+
+            return True
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_resetSim(self):
+        try:
+            self.__sendMsg(SAPMessage_RESET_SIM_REQ())
+            params = self.__rcvMsg(SAPMessage_RESET_SIM_RESP()).getParams()
+            if params[0].getValue() == 0x00:
+                return self.proc_transferATR()
+
+            return True
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_reportStatus(self):
+        try:
+            params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_transferCardReaderStatus(self):
+        try:
+            self.__sendMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_REQ())
+            params = self.__rcvMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_RESP()).getParams()
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_errorResponse(self):
+        try:
+            """ send malformed message, no mandatory maxmsgsize parameter"""
+            self.__sendMsg(SAPMessage_CONNECT_REQ())
+
+            params = self.__rcvMsg(SAPMessage_ERROR_RESP()).getParams()
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+    def proc_setTransportProtocol(self,  protocol = 0):
+        try:
+            self.__sendMsg(SAPMessage_SET_TRANSPORT_PROTOCOL_REQ(protocol))
+            params = self.__rcvMsg(SAPMessage_SET_TRANSPORT_PROTOCOL_RESP()).getParams()
+
+            if params[0].getValue() == 0x00:
+                params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
+                if params[0].getValue() in (0x01,  0x02):
+                    return self.proc_transferATR()
+                else:
+                    return True
+                    """return False ???"""
+            elif params[0].getValue == 0x07:
+                """not supported"""
+                return True
+                """return False ???"""
+            else:
+                return False
+
+        except BluetoothError , e:
+            print "Error. " +str(e)
+            return False
+
+if __name__ == "__main__":
+    pass
diff --git a/test/test-sap.py b/test/test-sap.py
new file mode 100755
index 0000000..393f785
--- /dev/null
+++ b/test/test-sap.py
@@ -0,0 +1,139 @@
+""" Copyright (C) 2011 Tieto """
+""" Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> """
+
+from sap import *
+import time
+
+def connect_disconnect_by_client(sap):
+
+    print "[Test] Connect - Disconnect by client \n"
+
+    try:
+        if not sap.isConnected():
+           sap.connect()
+
+        if sap.proc_connect():
+            if sap.proc_disconnectByClient():
+                print "OK"
+                return 0
+
+        print "NOT OK"
+        return 1
+
+    except BluetoothError , e:
+        print "Error " + str(e)
+
+
+def connect_disconnect_by_server_gracefully(sap, timeout=0):
+
+    print "[Test] Connect - Disconnect by server with timer \n"
+
+    try:
+        if not sap.isConnected():
+           sap.connect()
+
+        if sap.proc_connect():
+            if sap.proc_disconnectByServer(timeout):
+                print "OK"
+                return 0
+
+        print "NOT OK"
+        return 1
+
+    except BluetoothError , e:
+        print "Error " + str(e)
+
+
+def connect_txAPDU_disconnect_by_client(sap):
+
+    print "[Test] Connect - TX APDU - Disconnect by client \n"
+
+    try:
+        if not sap.isConnected():
+           sap.connect()
+
+        if sap.proc_connect():
+            if not sap.proc_transferAPDU():
+                print "NOT OK 1"
+                return 1
+
+            if not sap.proc_transferAPDU():
+                print "NOT OK 2"
+                return 1
+
+            if not sap.proc_transferAPDU():
+                print "NOT OK 3"
+                return 1
+
+            if not sap.proc_transferAPDU():
+                print "NOT OK 4"
+                return 1
+
+            if sap.proc_disconnectByClient():
+                print "OK"
+                return 0
+
+        print "NOT OK"
+        return 1
+
+    except BluetoothError , e:
+        print "Error " + str(e)
+
+def connect_rfcomm_only_and_wait_for_close_by_server(sap):
+
+    print "[Test] Connect rfcomm only  - Disconnect by server timeout \n"
+
+    if not sap.isConnected():
+       sap.connect()
+
+    time.sleep(40)
+    print "OK"
+
+def power_sim_off_on(sap):
+
+    print "[Test] Powe sim off \n"
+
+    try:
+        if not sap.isConnected():
+           sap.connect()
+
+        if sap.proc_connect():
+            if not sap.proc_resetSim():
+                print "NOT OK"
+                return 1
+
+            if not sap.proc_powerSimOff():
+                print "NOT OK"
+                return 1
+
+            if not sap.proc_powerSimOn():
+                print "NOT OK"
+                return 1
+
+            if sap.proc_disconnectByClient():
+                print "OK"
+                return 0
+
+        print "NOT OK"
+        return 1
+
+    except BluetoothError , e:
+        print "Error " + str(e)
+
+
+if __name__ == "__main__":
+
+    host = "00:15:83:38:BF:18"
+    port = 8
+
+    try:
+        s = SAPClient(host, port)
+    except BluetoothError , e:
+        print "Error " +str(e)
+
+#    connect_disconnect_by_client(s)
+#    connect_disconnect_by_server_gracefully(s)
+#    connect_disconnect_by_server_gracefully(s, 40)  #  wait 40 sec for srv to close rfcomm sock
+#    connect_rfcomm_only_and_wait_for_close_by_server(s)
+    connect_txAPDU_disconnect_by_client(s)
+    power_sim_off_on(s)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v5 2/4] Add support for SAP protocol
  2011-03-16 12:10 ` [PATCH v5 2/4] Add support for SAP protocol Waldemar Rymarkiewicz
@ 2011-03-16 22:06   ` ANGUS.H
  2011-03-17  9:50     ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 11+ messages in thread
From: ANGUS.H @ 2011-03-16 22:06 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz; +Cc: Johan Hedberg, linux-bluetooth

2011/3/16 Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>:
> Add new protocol features:
>        * transfer APDu request/response
>        * get ATR request/response
>        * power sim of/on request/response
>        * card reader status
>        * set transport protocol
> ---
>  sap/server.c |  415 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 files changed, 399 insertions(+), 16 deletions(-)


Hi

A lot of code could be refactored.
Quite a few repeatable (logically) blocks in every
"...._req()" and "..._rsp()" handlers.

/A.H

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH v5 2/4] Add support for SAP protocol
  2011-03-16 22:06   ` ANGUS.H
@ 2011-03-17  9:50     ` Waldemar.Rymarkiewicz
  2011-03-19 14:57       ` ANGUS.H
  0 siblings, 1 reply; 11+ messages in thread
From: Waldemar.Rymarkiewicz @ 2011-03-17  9:50 UTC (permalink / raw)
  To: hombre71; +Cc: johan.hedberg, linux-bluetooth

Hi Angus.H,

>A lot of code could be refactored.
>Quite a few repeatable (logically) blocks in every 
>"...._req()" and "..._rsp()" handlers.
>

Indeed, but those blocks are not equal in all cases. Thus, I prefere to split it up into seperate functions instead of having one big function with switch-case statement.
It's not like we can replace those blocks with one generic function without switch-case.  I consider this as slightly more readable. However, I'm not strongly opposed to change it one function.

Waldek

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v5 2/4] Add support for SAP protocol
  2011-03-17  9:50     ` Waldemar.Rymarkiewicz
@ 2011-03-19 14:57       ` ANGUS.H
  0 siblings, 0 replies; 11+ messages in thread
From: ANGUS.H @ 2011-03-19 14:57 UTC (permalink / raw)
  To: Waldemar.Rymarkiewicz; +Cc: johan.hedberg, linux-bluetooth

On Thu, Mar 17, 2011 at 10:50 AM,  <Waldemar.Rymarkiewicz@tieto.com> wrote:
> Hi Angus.H,
>
>>A lot of code could be refactored.
>>Quite a few repeatable (logically) blocks in every
>>"...._req()" and "..._rsp()" handlers.
>>
>
> Indeed, but those blocks are not equal in all cases. Thus, I prefere to split it up into seperate functions instead of having one big function with switch-case statement.
> It's not like we can replace those blocks with one generic function without switch-case.  I consider this as slightly more readable. However, I'm not strongly opposed to change it one function.
>
> Waldek
>

Hi
I just wanted to say that refactoring of typical req() here could be
seen as 3 or 4 internal prcedure calls,
[ refactoring here == extracting common/repeatable code to new routine ]

typical req example:
static void power_sim_off_req(struct sap_connection *conn)
 {
-       DBG("SAP_SIM_OFF_REQUEST");
+       DBG("conn %p state %d", conn, conn->state);
+
+       if (conn->state != SAP_STATE_CONNECTED)
+               goto error_rsp;
+
+       if (!is_power_sim_off_req_allowed(conn->processing_req))
+               goto error_rsp;
+
+       conn->processing_req = SAP_POWER_SIM_OFF_REQ;
+       sap_power_sim_off_req(conn);
+
+       return;
+
+error_rsp:
+       error("Processing error (state %d pr 0x%02x)", conn->state,
+                                               conn->processing_req);
+       sap_error_rsp(conn);
 }

could be represented as:
{
validate_req(conn, VALIDATION_RULE)
assign_req(conn,REQ)
send_req(conn, handlers[REQ])  ( where handlers is an array of req/rsp
handlers to sap driver )
error_handling:
}


it's just an example, more readable/maintainable.
/AH

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v5 3/4] Sim Access Profile dummy driver
  2011-03-16 12:10 ` [PATCH v5 3/4] Sim Access Profile dummy driver Waldemar Rymarkiewicz
@ 2011-03-23 13:00   ` Johan Hedberg
  2011-03-24  9:32     ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 11+ messages in thread
From: Johan Hedberg @ 2011-03-23 13:00 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz; +Cc: linux-bluetooth

Hi Waldek,

On Wed, Mar 16, 2011, Waldemar Rymarkiewicz wrote:
> Add SAP dummy driver implementation and extend configure
> with --with-sap=<driver>.
> ---
>  .gitignore      |    1 +
>  Makefile.am     |   13 +++-
>  acinclude.m4    |    6 ++
>  sap/sap-dummy.c |  269 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  4 files changed, 275 insertions(+), 14 deletions(-)

The first three patches have been pushed upstream. Thanks. However, I
hope you do pay attention the refactoring suggestions that were made and
keep a look-out for possibilities for simplifying the code.

Johan

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v5 4/4] Sim Access Profile test scripts
  2011-03-16 12:10 ` [PATCH v5 4/4] Sim Access Profile test scripts Waldemar Rymarkiewicz
@ 2011-03-23 13:02   ` Johan Hedberg
  2011-03-24  9:40     ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 11+ messages in thread
From: Johan Hedberg @ 2011-03-23 13:02 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz; +Cc: linux-bluetooth

Hi Waldek,

On Wed, Mar 16, 2011, Waldemar Rymarkiewicz wrote:
> Add simple SAP client python implementation and a test script.
> 
> To run test-sap.py you need Python 2.6 or newer (tested with 2.6 only)
> and PyBluez package installed.
> ---
>  test/sap.py      |  944 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  test/test-sap.py |  139 ++++++++
>  2 files changed, 1083 insertions(+), 0 deletions(-)
>  create mode 100644 test/sap.py
>  create mode 100755 test/test-sap.py

We don't use the .py extension for any other python scripts in the tree
so please don't use it for your scripts either. You'll probably want to
name the scripts a little bit more descriptively than "sap" and
"test-sap". Also remember to mention them to Makefile.tools so they are
part of "make dist" (i.e. add them to EXTRA_DIST).

Johan

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH v5 3/4] Sim Access Profile dummy driver
  2011-03-23 13:00   ` Johan Hedberg
@ 2011-03-24  9:32     ` Waldemar.Rymarkiewicz
  0 siblings, 0 replies; 11+ messages in thread
From: Waldemar.Rymarkiewicz @ 2011-03-24  9:32 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth

Johan, 

>The first three patches have been pushed upstream. Thanks. 
>However, I hope you do pay attention the refactoring 
>suggestions that were made and keep a look-out for 
>possibilities for simplifying the code.
>

Thanks. 
Yes, I will see what I can refactor there.

Waldek

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH v5 4/4] Sim Access Profile test scripts
  2011-03-23 13:02   ` Johan Hedberg
@ 2011-03-24  9:40     ` Waldemar.Rymarkiewicz
  0 siblings, 0 replies; 11+ messages in thread
From: Waldemar.Rymarkiewicz @ 2011-03-24  9:40 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth

Hi Johan, 

>We don't use the .py extension for any other python scripts in 
>the tree so please don't use it for your scripts either. 
>You'll probably want to name the scripts a little bit more 
>descriptively than "sap" and "test-sap". Also remember to 
>mention them to Makefile.tools so they are part of "make dist" 
>(i.e. add them to EXTRA_DIST).
>

In fact, I missed EXTRA_DIST. Will fix this then.
I will remove .py extensions as well. I understand that the dbusdef.py is an exception?

I could propose test/sap-client and  test/test-sap or test/test-sap-server . It seems more saner I think. Doesn't it?

Waldek

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-03-24  9:40 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-16 12:10 [PATCH v5 1/4] Sim Access Profile connect/disconnect procedures Waldemar Rymarkiewicz
2011-03-16 12:10 ` [PATCH v5 2/4] Add support for SAP protocol Waldemar Rymarkiewicz
2011-03-16 22:06   ` ANGUS.H
2011-03-17  9:50     ` Waldemar.Rymarkiewicz
2011-03-19 14:57       ` ANGUS.H
2011-03-16 12:10 ` [PATCH v5 3/4] Sim Access Profile dummy driver Waldemar Rymarkiewicz
2011-03-23 13:00   ` Johan Hedberg
2011-03-24  9:32     ` Waldemar.Rymarkiewicz
2011-03-16 12:10 ` [PATCH v5 4/4] Sim Access Profile test scripts Waldemar Rymarkiewicz
2011-03-23 13:02   ` Johan Hedberg
2011-03-24  9:40     ` Waldemar.Rymarkiewicz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox