| /* |
| * |
| * BlueZ - Bluetooth protocol stack for Linux |
| * |
| * Copyright (C) 2012 Tieto Poland |
| * |
| * |
| * 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 <stdio.h> |
| #include <errno.h> |
| #include <unistd.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "parser.h" |
| |
| #define PADDING4(x) ((4 - ((x) & 0x03)) & 0x03) |
| |
| #define SAP_CONNECT_REQ 0x00 |
| #define SAP_CONNECT_RESP 0x01 |
| #define SAP_DISCONNECT_REQ 0x02 |
| #define SAP_DISCONNECT_RESP 0x03 |
| #define SAP_DISCONNECT_IND 0x04 |
| #define SAP_TRANSFER_APDU_REQ 0x05 |
| #define SAP_TRANSFER_APDU_RESP 0x06 |
| #define SAP_TRANSFER_ATR_REQ 0x07 |
| #define SAP_TRANSFER_ATR_RESP 0x08 |
| #define SAP_POWER_SIM_OFF_REQ 0x09 |
| #define SAP_POWER_SIM_OFF_RESP 0x0A |
| #define SAP_POWER_SIM_ON_REQ 0x0B |
| #define SAP_POWER_SIM_ON_RESP 0x0C |
| #define SAP_RESET_SIM_REQ 0x0D |
| #define SAP_RESET_SIM_RESP 0x0E |
| #define SAP_TRANSFER_CARD_READER_STATUS_REQ 0x0F |
| #define SAP_TRANSFER_CARD_READER_STATUS_RESP 0x10 |
| #define SAP_STATUS_IND 0x11 |
| #define SAP_ERROR_RESP 0x12 |
| #define SAP_SET_TRANSPORT_PROTOCOL_REQ 0x13 |
| #define SAP_SET_TRANSPORT_PROTOCOL_RESP 0x14 |
| |
| #define SAP_PARAM_ID_MAX_MSG_SIZE 0x00 |
| #define SAP_PARAM_ID_CONN_STATUS 0x01 |
| #define SAP_PARAM_ID_RESULT_CODE 0x02 |
| #define SAP_PARAM_ID_DISCONNECT_IND 0x03 |
| #define SAP_PARAM_ID_COMMAND_APDU 0x04 |
| #define SAP_PARAM_ID_COMMAND_APDU7816 0x10 |
| #define SAP_PARAM_ID_RESPONSE_APDU 0x05 |
| #define SAP_PARAM_ID_ATR 0x06 |
| #define SAP_PARAM_ID_CARD_READER_STATUS 0x07 |
| #define SAP_PARAM_ID_STATUS_CHANGE 0x08 |
| #define SAP_PARAM_ID_TRANSPORT_PROTOCOL 0x09 |
| |
| #define SAP_STATUS_OK 0x00 |
| #define SAP_STATUS_CONNECTION_FAILED 0x01 |
| #define SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED 0x02 |
| #define SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL 0x03 |
| #define SAP_STATUS_OK_ONGOING_CALL 0x04 |
| |
| #define SAP_DISCONNECTION_TYPE_GRACEFUL 0x00 |
| #define SAP_DISCONNECTION_TYPE_IMMEDIATE 0x01 |
| #define SAP_DISCONNECTION_TYPE_CLIENT 0xFF |
| |
| #define SAP_RESULT_OK 0x00 |
| #define SAP_RESULT_ERROR_NO_REASON 0x01 |
| #define SAP_RESULT_ERROR_NOT_ACCESSIBLE 0x02 |
| #define SAP_RESULT_ERROR_POWERED_OFF 0x03 |
| #define SAP_RESULT_ERROR_CARD_REMOVED 0x04 |
| #define SAP_RESULT_ERROR_POWERED_ON 0x05 |
| #define SAP_RESULT_ERROR_NO_DATA 0x06 |
| #define SAP_RESULT_NOT_SUPPORTED 0x07 |
| |
| #define SAP_STATUS_CHANGE_UNKNOWN_ERROR 0x00 |
| #define SAP_STATUS_CHANGE_CARD_RESET 0x01 |
| #define SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE 0x02 |
| #define SAP_STATUS_CHANGE_CARD_REMOVED 0x03 |
| #define SAP_STATUS_CHANGE_CARD_INSERTED 0x04 |
| #define SAP_STATUS_CHANGE_CARD_RECOVERED 0x05 |
| |
| #define SAP_TRANSPORT_PROTOCOL_T0 0x00 |
| #define SAP_TRANSPORT_PROTOCOL_T1 0x01 |
| |
| static const char *msg2str(uint8_t msg) |
| { |
| switch (msg) { |
| case SAP_CONNECT_REQ: |
| return "Connect Req"; |
| case SAP_CONNECT_RESP: |
| return "Connect Resp"; |
| case SAP_DISCONNECT_REQ: |
| return "Disconnect Req"; |
| case SAP_DISCONNECT_RESP: |
| return "Disconnect Resp"; |
| case SAP_DISCONNECT_IND: |
| return "Disconnect Ind"; |
| case SAP_TRANSFER_APDU_REQ: |
| return "Transfer APDU Req"; |
| case SAP_TRANSFER_APDU_RESP: |
| return "Transfer APDU Resp"; |
| case SAP_TRANSFER_ATR_REQ: |
| return "Transfer ATR Req"; |
| case SAP_TRANSFER_ATR_RESP: |
| return "Transfer ATR Resp"; |
| case SAP_POWER_SIM_OFF_REQ: |
| return "Power SIM Off Req"; |
| case SAP_POWER_SIM_OFF_RESP: |
| return "Power SIM Off Resp"; |
| case SAP_POWER_SIM_ON_REQ: |
| return "Power SIM On Req"; |
| case SAP_POWER_SIM_ON_RESP: |
| return "Power SIM On Resp"; |
| case SAP_RESET_SIM_REQ: |
| return "Reset SIM Req"; |
| case SAP_RESET_SIM_RESP: |
| return "Reset SIM Resp"; |
| case SAP_TRANSFER_CARD_READER_STATUS_REQ: |
| return "Transfer Card Reader Status Req"; |
| case SAP_TRANSFER_CARD_READER_STATUS_RESP: |
| return "Transfer Card Reader Status Resp"; |
| case SAP_STATUS_IND: |
| return "Status Ind"; |
| case SAP_ERROR_RESP: |
| return "Error Resp"; |
| case SAP_SET_TRANSPORT_PROTOCOL_REQ: |
| return "Set Transport Protocol Req"; |
| case SAP_SET_TRANSPORT_PROTOCOL_RESP: |
| return "Set Transport Protocol Resp"; |
| default: |
| return "Reserved"; |
| } |
| } |
| |
| static const char *param2str(uint8_t param) |
| { |
| switch (param) { |
| case SAP_PARAM_ID_MAX_MSG_SIZE: |
| return "MaxMsgSize"; |
| case SAP_PARAM_ID_CONN_STATUS: |
| return "ConnectionStatus"; |
| case SAP_PARAM_ID_RESULT_CODE: |
| return "ResultCode"; |
| case SAP_PARAM_ID_DISCONNECT_IND: |
| return "DisconnectionType"; |
| case SAP_PARAM_ID_COMMAND_APDU: |
| return "CommandAPDU"; |
| case SAP_PARAM_ID_COMMAND_APDU7816: |
| return "CommandAPDU7816"; |
| case SAP_PARAM_ID_RESPONSE_APDU: |
| return "ResponseAPDU"; |
| case SAP_PARAM_ID_ATR: |
| return "ATR"; |
| case SAP_PARAM_ID_CARD_READER_STATUS: |
| return "CardReaderStatus"; |
| case SAP_PARAM_ID_STATUS_CHANGE: |
| return "StatusChange"; |
| case SAP_PARAM_ID_TRANSPORT_PROTOCOL: |
| return "TransportProtocol"; |
| default: |
| return "Reserved"; |
| } |
| } |
| |
| static const char *status2str(uint8_t status) |
| { |
| switch (status) { |
| case SAP_STATUS_OK: |
| return "OK, Server can fulfill requirements"; |
| case SAP_STATUS_CONNECTION_FAILED: |
| return "Error, Server unable to establish connection"; |
| case SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED: |
| return "Error, Server does not support maximum message size"; |
| case SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL: |
| return "Error, maximum message size by Client is too small"; |
| case SAP_STATUS_OK_ONGOING_CALL: |
| return "OK, ongoing call"; |
| default: |
| return "Reserved"; |
| } |
| } |
| |
| static const char *disctype2str(uint8_t disctype) |
| { |
| switch (disctype) { |
| case SAP_DISCONNECTION_TYPE_GRACEFUL: |
| return "Graceful"; |
| case SAP_DISCONNECTION_TYPE_IMMEDIATE: |
| return "Immediate"; |
| default: |
| return "Reserved"; |
| } |
| } |
| |
| static const char *result2str(uint8_t result) |
| { |
| switch (result) { |
| case SAP_RESULT_OK: |
| return "OK, request processed correctly"; |
| case SAP_RESULT_ERROR_NO_REASON: |
| return "Error, no reason defined"; |
| case SAP_RESULT_ERROR_NOT_ACCESSIBLE: |
| return "Error, card not accessible"; |
| case SAP_RESULT_ERROR_POWERED_OFF: |
| return "Error, card (already) powered off"; |
| case SAP_RESULT_ERROR_CARD_REMOVED: |
| return "Error, card removed"; |
| case SAP_RESULT_ERROR_POWERED_ON: |
| return "Error, card already powered on"; |
| case SAP_RESULT_ERROR_NO_DATA: |
| return "Error, data not available"; |
| case SAP_RESULT_NOT_SUPPORTED: |
| return "Error, not supported"; |
| default: |
| return "Reserved"; |
| } |
| } |
| |
| static const char *statuschg2str(uint8_t statuschg) |
| { |
| switch (statuschg) { |
| case SAP_STATUS_CHANGE_UNKNOWN_ERROR: |
| return "Unknown Error"; |
| case SAP_STATUS_CHANGE_CARD_RESET: |
| return "Card reset"; |
| case SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE: |
| return "Card not accessible"; |
| case SAP_STATUS_CHANGE_CARD_REMOVED: |
| return "Card removed"; |
| case SAP_STATUS_CHANGE_CARD_INSERTED: |
| return "Card inserted"; |
| case SAP_STATUS_CHANGE_CARD_RECOVERED: |
| return "Card recovered"; |
| default: |
| return "Reserved"; |
| } |
| } |
| |
| static const char *prot2str(uint8_t prot) |
| { |
| switch (prot) { |
| case SAP_TRANSPORT_PROTOCOL_T0: |
| return "T=0"; |
| case SAP_TRANSPORT_PROTOCOL_T1: |
| return "T=1"; |
| default: |
| return "Reserved"; |
| } |
| } |
| |
| static void parse_parameters(int level, struct frame *frm) |
| { |
| uint8_t param; |
| uint16_t len; |
| uint8_t pv8; |
| |
| while (frm->len > 3) { |
| p_indent(level, frm); |
| |
| param = p_get_u8(frm); |
| p_get_u8(frm); |
| len = p_get_u16(frm); |
| |
| printf("%s (0x%02x) len %d = ", param2str(param), param, len); |
| |
| switch (param) { |
| case SAP_PARAM_ID_MAX_MSG_SIZE: |
| printf("%d\n", p_get_u16(frm)); |
| break; |
| case SAP_PARAM_ID_CONN_STATUS: |
| pv8 = p_get_u8(frm); |
| printf("0x%02x (%s)\n", pv8, status2str(pv8)); |
| break; |
| case SAP_PARAM_ID_RESULT_CODE: |
| case SAP_PARAM_ID_CARD_READER_STATUS: |
| pv8 = p_get_u8(frm); |
| printf("0x%02x (%s)\n", pv8, result2str(pv8)); |
| break; |
| case SAP_PARAM_ID_DISCONNECT_IND: |
| pv8 = p_get_u8(frm); |
| printf("0x%02x (%s)\n", pv8, disctype2str(pv8)); |
| break; |
| case SAP_PARAM_ID_STATUS_CHANGE: |
| pv8 = p_get_u8(frm); |
| printf("0x%02x (%s)\n", pv8, statuschg2str(pv8)); |
| break; |
| case SAP_PARAM_ID_TRANSPORT_PROTOCOL: |
| pv8 = p_get_u8(frm); |
| printf("0x%02x (%s)\n", pv8, prot2str(pv8)); |
| break; |
| default: |
| printf("\n"); |
| raw_ndump(level + 1, frm, len); |
| frm->ptr += len; |
| frm->len -= len; |
| } |
| |
| /* Skip padding */ |
| frm->ptr += PADDING4(len); |
| frm->len -= PADDING4(len); |
| } |
| } |
| |
| void sap_dump(int level, struct frame *frm) |
| { |
| uint8_t msg, params; |
| |
| msg = p_get_u8(frm); |
| params = p_get_u8(frm); |
| |
| /* Skip reserved field */ |
| p_get_u16(frm); |
| |
| p_indent(level, frm); |
| |
| printf("SAP: %s: params %d\n", msg2str(msg), params); |
| |
| parse_parameters(level, frm); |
| } |