From 8e6ba80c8adc38fdad92d626d2b1c005140497e8 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Tue, 20 Jul 2010 19:14:38 +0200 Subject: btsap: prototypical client, protocol definitions, parsing helpers, osmocon tool server. --- src/host/osmocon/osmocon.c | 11 ++- src/target/firmware/comm/Makefile | 2 +- src/target/firmware/comm/btsap.c | 67 ++++++++++++++ src/target/firmware/comm/sim_btsap.c | 131 ++++++++++++++++++++++++++ src/target/firmware/include/btsap.h | 144 +++++++++++++++++++++++++++++ src/target/firmware/include/comm/sercomm.h | 5 +- 6 files changed, 356 insertions(+), 4 deletions(-) create mode 100644 src/target/firmware/comm/btsap.c create mode 100644 src/target/firmware/comm/sim_btsap.c create mode 100644 src/target/firmware/include/btsap.h diff --git a/src/host/osmocon/osmocon.c b/src/host/osmocon/osmocon.c index d702d745..f0e52486 100644 --- a/src/host/osmocon/osmocon.c +++ b/src/host/osmocon/osmocon.c @@ -158,6 +158,7 @@ struct dnload { int echo_bytecount; struct tool_server layer2_server; + struct tool_server sap_server; struct tool_server loader_server; }; @@ -1448,12 +1449,13 @@ int main(int argc, char **argv) uint32_t tmp_load_address = ROMLOAD_ADDRESS; const char *serial_dev = "/dev/ttyUSB1"; const char *layer2_un_path = "/tmp/osmocom_l2"; + const char *sap_un_path = "/tmp/osmocom_sap"; const char *loader_un_path = "/tmp/osmocom_loader"; dnload.mode = MODE_C123; dnload.chainload_filename = NULL; - while ((opt = getopt(argc, argv, "d:hl:p:m:c:s:v")) != -1) { + while ((opt = getopt(argc, argv, "d:hl:p:m:c:s:a:v")) != -1) { switch (opt) { case 'p': serial_dev = optarg; @@ -1469,6 +1471,9 @@ int main(int argc, char **argv) case 'l': loader_un_path = optarg; break; + case 'a': + sap_un_path = optarg; + break; case 'v': version(argv[0]); break; @@ -1520,6 +1525,10 @@ int main(int argc, char **argv) SC_DLCI_L1A_L23) != 0) exit(1); + if (register_tool_server(&dnload.sap_server, sap_un_path, + SC_DLCI_SAP) != 0) + exit(1); + if (register_tool_server(&dnload.loader_server, loader_un_path, SC_DLCI_LOADER) != 0) exit(1); diff --git a/src/target/firmware/comm/Makefile b/src/target/firmware/comm/Makefile index 25fbb983..bdf951ee 100644 --- a/src/target/firmware/comm/Makefile +++ b/src/target/firmware/comm/Makefile @@ -1,5 +1,5 @@ LIBRARIES+=comm comm_DIR=comm -comm_SRCS=msgb.c sercomm.c sercomm_cons.c timer.c +comm_SRCS=msgb.c sercomm.c sercomm_cons.c timer.c btsap.c sim_btsap.c diff --git a/src/target/firmware/comm/btsap.c b/src/target/firmware/comm/btsap.c new file mode 100644 index 00000000..62d97de9 --- /dev/null +++ b/src/target/firmware/comm/btsap.c @@ -0,0 +1,67 @@ + +#include + +#include + +struct msgb *sap_alloc_msg(uint8_t id, uint8_t nparams) +{ + struct msgb *m = msgb_alloc(HACK_MAX_MSG, "btsap"); + + if(!m) { + return m; + } + + msgb_put_u8(m, id); + msgb_put_u8(m, nparams); + msgb_put_u16(m, 0); // reserved + + return m; +} + +void sap_parse_msg(struct msgb *m, uint8_t *id, uint8_t *nparams) +{ + *id = msgb_get_u8(m); + *nparams = msgb_get_u8(m); + msgb_get_u16(m); +} + +void sap_put_param(struct msgb *m, uint8_t id, uint16_t length, const uint8_t *value) +{ + /* write header */ + msgb_put_u8(m, id); + msgb_put_u8(m, 0); // reserved + msgb_put_u16(m, length); + + /* need to align payload to 4 bytes */ + size_t align = length % 4; + if(align) { + align = 4 - align; + } + + /* append value and pad */ + uint8_t *p = msgb_put(m, length + align); + memcpy(p, value, length); + memset(p + length, 0, align); +} + +void sap_get_param(struct msgb *m, uint8_t *id, uint16_t *length, const uint8_t **value) +{ + /* consume header */ + *id = msgb_get_u8(m); + msgb_get_u8(m); // reserved + *length = msgb_get_u16(m); + + /* need to align payload to 4 bytes */ + size_t align = *length % 4; + if(align) { + align = 4 - align; + } + + /* consume data and pad */ + *value = msgb_get(m, (*length) + align); +} + +void sap_send(struct msgb *m) +{ + sercomm_sendmsg(SC_DLCI_SAP, m); +} diff --git a/src/target/firmware/comm/sim_btsap.c b/src/target/firmware/comm/sim_btsap.c new file mode 100644 index 00000000..c7bd5b59 --- /dev/null +++ b/src/target/firmware/comm/sim_btsap.c @@ -0,0 +1,131 @@ +/* Client for Bluetooth SIM Access Profile */ + +/* (C) 2010 by Ingo Albrecht + * + * All Rights Reserved + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include + +/* XXX memdump_range */ +#include + +struct { + int state; +} btsap; + +static void handle_sap_response(uint8_t dlci, struct msgb *msg) +{ + puts("Received SAP response:"); + memdump_range(msg->data, msg->data_len); +} + +int sim_init(void) +{ + btsap.state = SAP_State_NOT_CONNECTED; + + sercomm_register_rx_cb(SC_DLCI_SAP, &handle_sap_response); + + return 0; +} + +int sim_connect(void) +{ + struct msgb *m; + + /* check state */ + if(btsap.state == SAP_State_NOT_CONNECTED) { + btsap.state = SAP_State_NEGOTIATING; + } else if (!btsap.state == SAP_State_NEGOTIATING) { + return -EINVAL; + } + + /* build and send connect request */ + m = sap_alloc_msg(SAP_CONNECT_REQ, 1); + + uint16_t maxmsgsize = htons(HACK_MAX_MSG); + sap_put_param(m, SAP_Parameter_MaxMsgSize, 2, &maxmsgsize); + + return sap_send(m); +} + +int sim_disconnect(void) +{ + struct msgb *m; + + if(btsap.state == SAP_State_NOT_CONNECTED + || btsap.state == SAP_State_NEGOTIATING) { + return -EINVAL; + } + + btsap.state = SAP_State_NOT_CONNECTED; + + m = sap_alloc_msg(SAP_DISCONNECT_REQ, 0); + return sap_send(m); +} + +int sim_power_on(void) +{ + struct msgb *m; + + if(btsap.state != SAP_State_IDLE) { + return -EINVAL; + } + + btsap.state = SAP_State_PROCESSING_SIM_ON_REQ; + + m = sap_alloc_msg(SAP_POWER_SIM_ON_REQ, 0); + sap_send(m); +} + +int sim_power_off(void) +{ + struct msgb *m; + + if(btsap.state == SAP_State_NOT_CONNECTED + || btsap.state == SAP_State_NEGOTIATING) { + return -EINVAL; + } + + btsap.state = SAP_State_PROCESSING_SIM_OFF_REQ; + + m = sap_alloc_msg(SAP_POWER_SIM_OFF_REQ, 0); + sap_send(m); +} + +int sim_reset(void) +{ + struct msgb *m; + + if(btsap.state == SAP_State_NOT_CONNECTED + || btsap.state == SAP_State_NEGOTIATING) { + return -EINVAL; + } + + btsap.state = SAP_State_PROCESSING_SIM_RESET_REQ; + + m = sap_alloc_msg(SAP_RESET_SIM_REQ, 0); + sap_send(m); +} + +int sim_transfer_atr(/* callback */); +int sim_transfer_apdu(/* callback, struct msgb *request */); diff --git a/src/target/firmware/include/btsap.h b/src/target/firmware/include/btsap.h new file mode 100644 index 00000000..0704a67b --- /dev/null +++ b/src/target/firmware/include/btsap.h @@ -0,0 +1,144 @@ +/* Protocol constants and helpers for Bluetooth SIM Access Profile */ + +/* (C) 2010 by Ingo Albrecht + * + * All Rights Reserved + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* This intends to cover SAP 1.1 */ + +#ifndef btsap_h +#define btsap_h + +#include + +/* XXX put this somewhere serious and clean up uses */ +#define HACK_MAX_MSG 128 + + +/* Message type ids */ +enum { + SAP_CONNECT_REQ = 0x00, + SAP_CONNECT_RESP = 0x01, + SAP_DISCONNECT_REQ = 0x02, + SAP_DISCONNECT_RESP = 0x03, + SAP_DISCONNECT_IND = 0x04, + SAP_TRANSFER_APDU_REQ = 0x05, + SAP_TRANSFER_APDU_RESP = 0x06, + SAP_TRANSFER_ATR_REQ = 0x07, + SAP_TRANSFER_ATR_RESP = 0x08, + SAP_POWER_SIM_OFF_REQ = 0x09, + SAP_POWER_SIM_OFF_RESP = 0x0a, + SAP_POWER_SIM_ON_REQ = 0x0b, + SAP_POWER_SIM_ON_RESP = 0x0c, + SAP_RESET_SIM_REQ = 0x0d, + SAP_RESET_SIM_RESP = 0x0e, + SAP_TRANSFER_CARD_READER_STATUS_REQ = 0x0f, + SAP_TRANSFER_CARD_READER_STATUS_RESP = 0x10, + SAP_STATUS_IND = 0x11, + SAP_ERROR_RESP = 0x12, + SAP_SET_TRANSPORT_PROTOCOL_REQ = 0x13, + SAP_SET_TRANSPORT_PROTOCOL_RESP = 0x14 +}; + +/* Parameter type ids */ +enum { + SAP_Parameter_MaxMsgSize = 0x00, + SAP_Parameter_ConnectionStatus = 0x01, + SAP_Parameter_ResultCode = 0x02, + SAP_Parameter_DisconnectionType = 0x03, + SAP_Parameter_CommandAPDU = 0x04, + SAP_Parameter_ResponseAPDU = 0x05, + SAP_Parameter_ATR = 0x06, + SAP_Parameter_CardReaderStatus = 0x07, + SAP_Parameter_StatusChange = 0x08, + SAP_Parameter_TransportProtocol = 0x09, + SAP_Parameter_CommandAPDU7816 = 0x10 +}; + +/* Parameter enums */ + +enum { + SAP_ConnectionStatus_OK = 0x00, + SAP_ConnectionStatus_SERVER_UNABLE_CONN = 0x01, + SAP_ConnectionStatus_SERVER_MSGSIZE_NOT_SUPP = 0x02, + SAP_ConnectionStatus_MSGSIZE_TOO_SMALL = 0x03, + SAP_ConnectionStatus_OK_ONGOING_CALL = 0x04 +}; + +enum { + SAP_ResultCode_OK = 0x00, + SAP_ResultCode_FAULT = 0x01, + SAP_ResultCode_CARD_NOT_ACCESSIBLE = 0x02, + SAP_ResultCode_CARD_POWERED_OFF = 0x03, + SAP_ResultCode_CARD_REMOVED = 0x04, + SAP_ResultCode_CARD_ALREADY_POWERED_ON = 0x05, + SAP_ResultCode_DATA_NOT_AVAILABLE = 0x06, + SAP_ResultCode_NOT_SUPPORTED = 0x07 +}; + +enum { + SAP_DisconnectionType_GRACEFUL = 0x00, + SAP_DisconnectionType_IMMEDIATE = 0x01 +}; + +/* XXX SAP_CardReaderStatus from GSM 11.14 and TS31.111 */ + +enum { + SAP_StatusChange_UNKNOWN_ERROR = 0x00, + SAP_StatusChange_CARD_RESET = 0x01, + SAP_StatusChange_CARD_NOT_ACCESSIBLE = 0x02, + SAP_StatusChange_CARD_REMOVED = 0x03, + SAP_StatusChange_CARD_INSERTED = 0x04, + SAP_StatusChange_CARD_RECOVERED = 0x05 +}; + +enum { + SAP_TransportProtocol_T0 = 0x00, + SAP_TransportProtocol_T1 = 0x01 +}; + + +/* client and server state machine */ + +/* The following enum is not from the spec + * but has been cobbled together from a simplified + * state chart found in the spec. + */ +enum { + SAP_State_NOT_CONNECTED, + SAP_State_NEGOTIATING, + SAP_State_IDLE, + SAP_State_PROCESSING_APDU_REQ, + SAP_State_PROCESSING_ATR_REQ, + SAP_State_PROCESSING_SIM_RESET_REQ, + SAP_State_PROCESSING_SIM_OFF_REQ, + SAP_State_PROCESSING_SIM_ON_REQ, + SAP_State_PROCESSING_CARD_READER_STATUS_REQ, + SAP_State_PROCESSING_SET_TRANSPORT_PROTOCOL_REQ, +}; + +/* parsing and formatting helpers */ + +struct msgb *sap_alloc_msg(uint8_t id, uint8_t nparams); +void sap_parse_msg(struct msgb *m, uint8_t *id, uint8_t *nparams); + +void sap_put_param(struct msgb *m, uint8_t id, uint16_t length, const uint8_t *value); +void sap_get_param(struct msgb *m, uint8_t *id, uint16_t *length, const uint8_t **value); + +#endif /* !btsap_h */ diff --git a/src/target/firmware/include/comm/sercomm.h b/src/target/firmware/include/comm/sercomm.h index 8fbbff97..c6dd3cb0 100644 --- a/src/target/firmware/include/comm/sercomm.h +++ b/src/target/firmware/include/comm/sercomm.h @@ -19,8 +19,9 @@ enum sercomm_dlci { SC_DLCI_HIGHEST = 0, SC_DLCI_DEBUG = 4, SC_DLCI_L1A_L23 = 5, - SC_DLCI_LOADER = 9, - SC_DLCI_CONSOLE = 10, + SC_DLCI_SAP = 6, + SC_DLCI_LOADER = 50, + SC_DLCI_CONSOLE = 60, SC_DLCI_ECHO = 128, _SC_DLCI_MAX }; -- cgit v1.2.3