project build/
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index 211a002..6ac4f76 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -171,7 +171,6 @@ $(full_target): $(full_src_files) $(droiddoc_templates) $(droiddoc) $(html_dir_f
\@$(PRIVATE_SRC_LIST_FILE) \
-J-Xmx1280m \
$(PRIVATE_PROFILING_OPTIONS) \
- -quiet \
-doclet com.google.doclava.Doclava \
-docletpath $(PRIVATE_DOCLETPATH) \
-templatedir $(PRIVATE_CUSTOM_TEMPLATE_DIR) \
diff --git a/target/product/core.mk b/target/product/core.mk
index cc6bd56..2d5c404 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -23,6 +23,10 @@ PRODUCT_PROPERTY_OVERRIDES := \
ro.config.alarm_alert=Scandium.ogg
PRODUCT_PACKAGES += \
+ SmartcardService \
+ org.simalliance.openmobileapi \
+ org.simalliance.openmobileapi.xml \
+ libassd \
ApplicationsProvider \
BackupRestoreConfirmation \
BasicDreams \
project cts/
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 2b61134..0505d27 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -37,6 +37,7 @@ cts_support_packages := \
CtsSomeAccessibilityServices \
CtsTestStubs \
SignatureTest \
+ CtsOpenMobileApiTestCases \
TestDeviceSetup \
CtsUiAutomatorApp \
$(cts_security_apps_list)
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index 8e23f13..15381a6 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -148,6 +148,10 @@ class CtsBuilder(object):
plan.Include('android\.nativemedia.*')
self.__WritePlan(plan, 'PDK')
+ plan = tools.TestPlan(packages)
+ plan.Include(r'android\.openmobile')
+ self.__WritePlan(plan, 'OpenMobile')
+
def LogGenerateDescription(name):
print 'Generating test description for package %s' % name
project device/samsung/i9300/
diff --git a/configs/nfcee_access.xml b/configs/nfcee_access.xml
index 02e12fd..20c3a86 100644
--- a/configs/nfcee_access.xml
+++ b/configs/nfcee_access.xml
@@ -5,6 +5,11 @@
See packages/apps/Nfc/etc/sample_nfcee_access.xml for full documentation.
-->
+
+
+
+
+
diff --git a/configs/nfcee_access_debug.xml b/configs/nfcee_access_debug.xml
index a96a2d1..b145f50 100644
--- a/configs/nfcee_access_debug.xml
+++ b/configs/nfcee_access_debug.xml
@@ -5,6 +5,11 @@
See packages/apps/Nfc/etc/sample_nfcee_access.xml for full documentation.
-->
+
+
+
+
+
project external/qemu/
diff --git a/Makefile.android b/Makefile.android
index c7d43af..06f692e 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -3,6 +3,11 @@ ifneq ($(filter true% %true,$(BUILD_EMULATOR)$(BUILD_STANDALONE_EMULATOR)),)
ifneq (,$(filter $(TARGET_ARCH),arm x86 mips))
LOCAL_PATH:= $(call my-dir)
+# ifneq ($(PCSC_INCPATH),)
+# $(shell touch $(LOCAL_PATH)/telephony/sim_card.c)
+# $(shell touch $(LOCAL_PATH)/android/cmdline-option.c)
+# endif
+
# determine the target cpu
ifeq ($(TARGET_ARCH),arm)
EMULATOR_TARGET_CPU := target-arm
@@ -78,6 +83,7 @@ ifeq ($(HOST_OS),darwin)
endif
+
# BUILD_STANDALONE_EMULATOR is only defined when building with
# the android-rebuild.sh script. The script will also provide
# adequate values for HOST_CC
@@ -275,10 +281,10 @@ LOCAL_STATIC_LIBRARIES := \
emulator-libui \
emulator-common \
-LOCAL_CFLAGS += -DCONFIG_STANDALONE_UI=1
+LOCAL_CFLAGS += -DCONFIG_STANDALONE_UI=1 -DENABLE_PCSC -I$(PCSC_INCPATH)
LOCAL_CFLAGS += $(EMULATOR_COMMON_CFLAGS) $(EMULATOR_LIBUI_CFLAGS)
-LOCAL_LDLIBS += $(EMULATOR_COMMON_LDLIBS) $(EMULATOR_LIBUI_LDLIBS)
+LOCAL_LDLIBS += $(EMULATOR_COMMON_LDLIBS) $(EMULATOR_LIBUI_LDLIBS) -L$(PCSC32_LIBPATH) -lpcsclite
LOCAL_SRC_FILES := \
android/cmdline-option.c \
diff --git a/Makefile.common b/Makefile.common
index 882d638..8d41a3e 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -138,6 +138,7 @@ LOCAL_SRC_FILES += $(common_LOCAL_SRC_FILES)
$(call gen-hw-config-defs)
$(call end-emulator-library)
+
## another for 64-bit
# NOTE: only linux and darwin in non-standalone mode is supported, because
# 1) For Windows: amd64-mingw32msvc-gcc doesn't work, see http://b/issue?id=5949152.
@@ -578,6 +579,7 @@ endif
common_LOCAL_CFLAGS += $(EMULATOR_LIBQEMU_CFLAGS)
+
## one for 32-bit
$(call start-emulator-library, emulator-libqemu)
# gdbstub-xml.c contains C-compilable arrays corresponding to the content
@@ -592,7 +594,7 @@ $(QEMU_GDBSTUB_XML_C): $(QEMU_TARGET_XML_SOURCES) $(LOCAL_PATH)/feature_to_c.sh
$(hide) rm -f $@
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(QEMU_GDBSTUB_XML_C)
-LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -I$(intermediates)
+LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -I$(intermediates) -DENABLE_PCSC -I$(PCSC_INCPATH)
LOCAL_SRC_FILES += $(common_LOCAL_SRC_FILES)
$(call gen-hw-config-defs)
$(call end-emulator-library)
@@ -614,7 +616,7 @@ ifneq ($(filter linux darwin,$(HOST_OS)),)
$(hide) rm -f $@
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(QEMU_GDBSTUB_XML_C)
- LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -I$(intermediates) -m64
+ LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -I$(intermediates) -DENABLE_PCSC -I$(PCSC_INCPATH) -m64
LOCAL_SRC_FILES += $(common_LOCAL_SRC_FILES)
$(call gen-hw-config-defs)
$(call end-emulator-library)
diff --git a/Makefile.target b/Makefile.target
index 3e45c61..5d608fa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -274,7 +274,7 @@ endif
## one for 32-bit
$(call start-emulator-library, emulator-target-$(EMULATOR_TARGET_CPU))
-LOCAL_CFLAGS += $(common_LOCAL_CFLAGS)
+LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -DENABLE_PCSC
LOCAL_SRC_FILES += $(common_LOCAL_SRC_FILES)
$(call gen-hw-config-defs)
$(call gen-hx-header,qemu-options.hx,qemu-options.def,os-posix.c os-win32.c)
@@ -284,7 +284,7 @@ $(call end-emulator-library)
ifneq ($(filter linux darwin,$(HOST_OS)),)
ifneq ($(BUILD_STANDALONE_EMULATOR),true)
$(call start-emulator-library, emulator64-target-$(EMULATOR_TARGET_CPU))
- LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -m64
+ LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -m64 -DENABLE_PCSC
LOCAL_SRC_FILES += $(common_LOCAL_SRC_FILES)
$(call gen-hw-config-defs)
$(call gen-hx-header,qemu-options.hx,qemu-options.def,os-posix.c os-win32.c)
@@ -374,6 +374,9 @@ LOCAL_CFLAGS += $(HW_OBJ_CFLAGS)
LOCAL_SRC_FILES += $(BLOCK_SOURCES)
LOCAL_CFLAGS += $(BLOCK_CFLAGS)
+LOCAL_LDLIBS += -L$(PCSC32_LIBPATH) -lpcsclite
+
+
$(call end-emulator-program)
##############################################################################
@@ -460,8 +463,8 @@ LOCAL_STATIC_LIBRARIES += \
emulator-libelff \
emulator-common \
$(SDL_STATIC_LIBRARIES)
-LOCAL_LDLIBS += $(common_LOCAL_LDLIBS)
-LOCAL_CFLAGS += $(common_LOCAL_CFLAGS)
+LOCAL_LDLIBS += $(common_LOCAL_LDLIBS) -L$(PCSC32_LIBPATH) -lpcsclite
+LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -DENABLE_PCSC -I$(PCSC_INCPATH)
LOCAL_SRC_FILES += $(common_LOCAL_SRC_FILES)
$(call gen-hx-header,qemu-monitor.hx,qemu-monitor.h,monitor.c)
$(call gen-hx-header,qemu-options.hx,qemu-options.def,vl-android.c qemu-options.h)
@@ -486,8 +489,8 @@ ifneq ($(filter linux darwin,$(HOST_OS)),)
emulator64-libelff \
emulator64-common \
$(SDL_STATIC_LIBRARIES_64)
- LOCAL_LDLIBS += $(common_LOCAL_LDLIBS) -m64
- LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -m64
+ LOCAL_LDLIBS += $(common_LOCAL_LDLIBS) -m64 -L$(PCSC64_LIBPATH) -lpcsclite
+ LOCAL_CFLAGS += $(common_LOCAL_CFLAGS) -m64 -DENABLE_PCSC -I$(PCSC_INCPATH)
LOCAL_SRC_FILES += $(common_LOCAL_SRC_FILES)
$(call gen-hx-header,qemu-monitor.hx,qemu-monitor.h,monitor.c)
$(call gen-hx-header,qemu-options.hx,qemu-options.def,vl-android.c qemu-options.h)
diff --git a/android/cmdline-option.c b/android/cmdline-option.c
index fb5aa23..60d9ed8 100644
--- a/android/cmdline-option.c
+++ b/android/cmdline-option.c
@@ -2,6 +2,7 @@
#include "android/utils/debug.h"
#include "android/utils/misc.h"
#include "android/utils/system.h"
+#include "telephony/sim_card.c"
#include
#include
#include
@@ -100,6 +101,20 @@ android_parse_options( int *pargc, char** *pargv, AndroidOptions* opt )
continue;
}
+#if defined(ENABLE_PCSC)
+extern void parse_pcsc_options( const char* options );
+
+ if (!strcmp(arg, "pcsc")) {
+ if ((nargs > 0) && (**aread != '-')) {
+ nargs--;
+ parse_pcsc_options(*aread++);
+ continue;
+ }
+ parse_pcsc_options(NULL);
+ continue;
+ }
+#endif
+
/* NOTE: variable tables map option names to values
* (e.g. field offsets into the AndroidOptions structure).
*
diff --git a/android/cmdline-options.h b/android/cmdline-options.h
index 5e8d59f..482734f 100644
--- a/android/cmdline-options.h
+++ b/android/cmdline-options.h
@@ -165,6 +165,8 @@ OPT_PARAM( screen, "", "set emulated screen mode" )
OPT_FLAG( force_32bit, "always use 32-bit emulator" )
+OPT_FLAG ( no_dns, "workaround no DNS" )
+
#undef CFG_FLAG
#undef CFG_PARAM
#undef OPT_FLAG
diff --git a/android/console.c b/android/console.c
index 07a59d2..fcb00dd 100644
--- a/android/console.c
+++ b/android/console.c
@@ -1564,6 +1564,29 @@ static const CommandDefRec gsm_commands[] =
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
+static int
+do_sim_apdu( ControlClient client, char* args )
+{
+ char temp[1024];
+
+ if (!args) {
+ control_write( client, "KO: missing argument, try 'sim apdu '\r\n" );
+ return -1;
+ }
+ sprintf( temp, "AT+CSIM=%d,\"%s\"", strlen(args), args );
+ amodem_send(android_modem, temp);
+ return 0;
+}
+
+
+static const CommandDefRec sim_commands[] =
+{
+ { "apdu", "Send APDU to SIM",
+ "'sim apdu' Send APDU to SIM\r\n", NULL,
+ do_sim_apdu, NULL },
+ { NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
/********************************************************************************************/
/********************************************************************************************/
/***** ******/
@@ -2983,6 +3006,10 @@ static const CommandDefRec main_commands[] =
"allows you to request the emulator sensors\r\n", NULL,
NULL, sensor_commands },
+ { "sim", "SIM related commands",
+ "allows you to send APDUs to the SIM\r\n", NULL,
+ NULL, sim_commands },
+
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
diff --git a/android/help.c b/android/help.c
index 1570160..1ce0d5b 100644
--- a/android/help.c
+++ b/android/help.c
@@ -1540,6 +1540,7 @@ help_force_32bit(stralloc_t* out)
#define help_version NULL
#define help_memory NULL
#define help_partition_size NULL
+#define help_no_dns NULL
typedef struct {
const char* name;
diff --git a/hw/goldfish_mmc.c b/hw/goldfish_mmc.c
index 3157bb3..b2b616c 100644
--- a/hw/goldfish_mmc.c
+++ b/hw/goldfish_mmc.c
@@ -14,6 +14,9 @@
#include "mmc.h"
#include "sd.h"
#include "block.h"
+#include
+#include "assd.h"
+
enum {
/* status register */
@@ -79,6 +82,10 @@ struct goldfish_mmc_state {
uint32_t block_count;
int is_SDHC;
+ int assd_fd;
+ uint8_t *assd_buffer;
+ int assd_state;
+
uint8_t* buf;
};
@@ -170,6 +177,21 @@ static const char* get_command_name(int command)
}
#endif
+ #define DEBUG_ASSD 1
+ #if DEBUG_ASSD
+ static void printStderrHexBuffer(uint8_t *buffer)
+ {
+ int i,n;
+ n = ((buffer[0]<<8) | buffer[1]);
+ if (n > 512) n = 512;
+ n -= 2;
+ if (n <= 0) return;
+ fprintf(stderr, "%02X", 0xff & buffer[2]);
+ for(i=1; ibuffer_address, buff0, sizeof buff0);
- new_status |= MMC_STAT_END_OF_DATA;
- }
+ {
+ uint8_t buff0[64];
+ uint32_t maskedArg;
+
+ maskedArg = 0x7fffffff & arg;
+
+ if (s->assd_fd == 0) {
+ // no ASSD available:
+ fprintf(stderr, "goldfish_mmc: no ASSD available\n");
+ if (maskedArg == 0x00FFFFF1) {
+ memset(buff0, 0, sizeof buff0);
+ buff0[13] = 2;
+ cpu_physical_memory_write(s->buffer_address, buff0, sizeof buff0);
+ new_status |= MMC_STAT_END_OF_DATA;
+ }
+ } else {
+ // ASSD available:
+ fprintf(stderr, "goldfish_mmc: ASSD available\n");
+ if (maskedArg == 0x00FFFFF1 || maskedArg==0x00FFFF1F) {
+ memset(buff0, 0, sizeof buff0);
+ buff0[11] = 2; // function=1 supported in function group 2
+ buff0[13] = 2;
+ buff0[16] = 0x10; // can switch to function 1 in function group 2
+ cpu_physical_memory_write(s->buffer_address, buff0, sizeof buff0);
+ new_status |= MMC_STAT_END_OF_DATA;
+ }
+ }
+
s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA | R1_APP_CMD; //2336
break;
+ }
case MMC_SET_BLOCKLEN:
s->block_length = arg;
@@ -403,7 +447,51 @@ static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd,
case MMC_SEND_STATUS:
s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
break;
- }
+
+ case MMC_ASSD_READ_SEC:
+ if (s->assd_fd==0) break;
+ cpu_physical_memory_write(s->buffer_address, s->assd_buffer, 512);
+ s->assd_state = 0;
+
+ new_status |= MMC_STAT_END_OF_DATA;
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
+ break;
+
+ case MMC_ASSD_WRITE_SEC:
+ if (s->assd_fd==0) break;
+ cpu_physical_memory_read(s->buffer_address, s->assd_buffer, 512);
+ #if DEBUG_ASSD
+ // { int i; fprintf(stderr, "goldfish_mmc: ASSD b:"); for (i=0; i<5; i++)fprintf(stderr, " %02X", 0xff & s->assd_buffer[i]); fprintf(stderr, "...\n"); }
+ fprintf(stderr, "goldfish_mmc: ASSD --> "); printStderrHexBuffer(s->assd_buffer); fprintf(stderr, "\n");
+ #endif
+ if (ioctl(s->assd_fd, ASSD_IOC_TRANSCEIVE, s->assd_buffer)) {
+ fprintf(stderr, "goldfish_mmc: Error: failed to transmit/receive ASSD command/response\n");
+ s->assd_buffer[0] = 0;
+ s->assd_buffer[1] = 0;
+ }
+ #if DEBUG_ASSD
+ fprintf(stderr, "goldfish_mmc: ASSD <-- "); printStderrHexBuffer(s->assd_buffer); fprintf(stderr, "\n");
+ #endif
+ s->assd_state = 2;
+
+ new_status |= MMC_STAT_END_OF_DATA;
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
+ break;
+
+ case MMC_ASSD_SEND_PSI:
+ memset(s->buf, 0, 512);
+ s->buf[0] = s->assd_state;
+ cpu_physical_memory_write(s->buffer_address, s->buf, 512);
+
+ new_status |= MMC_STAT_END_OF_DATA;
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
+ break;
+
+ case MMC_ASSD_CONTROL_ASSD_SYSTEM:
+ new_status |= MMC_STAT_END_OF_DATA;
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
+ break;
+ }
s->int_status |= new_status;
@@ -499,6 +587,32 @@ static CPUWriteMemoryFunc *goldfish_mmc_writefn[] = {
goldfish_mmc_write
};
+void goldfish_assd_init(struct goldfish_mmc_state *s)
+{
+ s->assd_fd = open("/dev/assd", O_RDWR);
+ if (s->assd_fd < 0) {
+ fprintf(stderr, "goldfish_mmc: Warning: failed to open /dev/assd\n");
+ s->assd_fd = 0;
+ return;
+ }
+ if (ioctl(s->assd_fd, ASSD_IOC_ENABLE)) {
+ fprintf(stderr, "goldfish_mmc: Info: failed to enable ASSD\n");
+ close(s->assd_fd);
+ s->assd_fd = 0;
+ return;
+ }
+ s->assd_buffer = (uint8_t*)malloc(512);
+ if (s->assd_buffer == NULL) {
+ fprintf(stderr, "goldfish_mmc: Error: failed to allocate ASSD buffer\n");
+ close(s->assd_fd);
+ s->assd_fd = 0;
+ return;
+ }
+ s->assd_state = 0;
+ fprintf(stderr, "goldfish_mmc: ASSD is ready\n");
+ return;
+ }
+
void goldfish_mmc_init(uint32_t base, int id, BlockDriverState* bs)
{
struct goldfish_mmc_state *s;
@@ -512,6 +626,7 @@ void goldfish_mmc_init(uint32_t base, int id, BlockDriverState* bs)
s->bs = bs;
s->buf = qemu_memalign(512,512);
+ goldfish_assd_init(s);
goldfish_device_add(&s->dev, goldfish_mmc_readfn, goldfish_mmc_writefn, s);
register_savevm( "goldfish_mmc", 0, GOLDFISH_MMC_SAVE_VERSION,
diff --git a/hw/mmc.h b/hw/mmc.h
index 3ae3ea9..5e33af3 100644
--- a/hw/mmc.h
+++ b/hw/mmc.h
@@ -78,6 +78,11 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
+#define MMC_ASSD_READ_SEC 34 /* ### */
+#define MMC_ASSD_WRITE_SEC 35 /* ### */
+#define MMC_ASSD_SEND_PSI 36 /* ### */
+#define MMC_ASSD_CONTROL_ASSD_SYSTEM 37 /* ### */
+
/*
* MMC_SWITCH argument format:
*
diff --git a/telephony/android_modem.c b/telephony/android_modem.c
index 52d5f9c..e55102f 100644
--- a/telephony/android_modem.c
+++ b/telephony/android_modem.c
@@ -1432,6 +1432,11 @@ handleSIM_IO( const char* cmd, AModem modem )
return asimcard_io( modem->sim, cmd );
}
+static const char*
+handleSIM_APDU( const char* cmd, AModem modem )
+{
+ return asimcard_cmd( modem->sim, cmd );
+}
static const char*
handleOperatorSelection( const char* cmd, AModem modem )
@@ -1825,7 +1830,7 @@ handleChangeOrEnterPIN( const char* cmd, AModem modem )
return "+CPIN: READY";
}
}
- break;
+ //break;
case A_SIM_STATUS_PIN: /* waiting for PIN */
if ( asimcard_check_pin( modem->sim, cmd ) )
@@ -2427,6 +2432,11 @@ static const struct {
/* see requestSIM_IO() */
{ "!+CRSM=", NULL, handleSIM_IO },
+ { "!+CSIM=", NULL, handleSIM_APDU },
+ { "!+CGLA=", NULL, handleSIM_APDU },
+ { "!+CCHO=", NULL, handleSIM_APDU },
+ { "!+CCHC=", NULL, handleSIM_APDU },
+
/* see onRequest() */
{ "+CHLD=0", NULL, handleHangup },
diff --git a/telephony/sim_card.c b/telephony/sim_card.c
index b172deb..736f317 100644
--- a/telephony/sim_card.c
+++ b/telephony/sim_card.c
@@ -13,6 +13,18 @@
#include
#include
#include
+#if defined(ENABLE_PCSC)
+#if ! defined(_WIN32)
+#include "pcsclite.h"
+#include "wintypes.h"
+#else
+#define WINSCARDDATA
+#define MAX_BUFFER_SIZE 264
+#endif
+#include "winscard.h"
+#include
+#include
+#endif
/* set ENABLE_DYNAMIC_RECORDS to 1 to enable dynamic records
* for now, this is an experimental feature that needs more testing
@@ -22,6 +34,9 @@
#define A_SIM_PIN_SIZE 4
#define A_SIM_PUK_SIZE 8
+#define MAX_N_CHANNELS 20
+#define H_CHANNEL_OFFSET 0x12345600
+
typedef struct ASimCardRec_ {
ASimStatus status;
char pin[ A_SIM_PIN_SIZE+1 ];
@@ -29,15 +44,20 @@ typedef struct ASimCardRec_ {
int pin_retries;
int port;
- char out_buff[ 256 ];
+ char out_buff[ 1024 ];
int out_size;
+#if defined(ENABLE_PCSC)
+ SCARDCONTEXT hContext;
+ SCARDHANDLE hCard;
+#endif
+
} ASimCardRec;
static ASimCardRec _s_card[1];
-ASimCard
-asimcard_create(int port)
+static ASimCard
+sw_asimcard_create(int port)
{
ASimCard card = _s_card;
card->status = A_SIM_STATUS_READY;
@@ -48,8 +68,8 @@ asimcard_create(int port)
return card;
}
-void
-asimcard_destroy( ASimCard card )
+static void
+sw_asimcard_destroy( ASimCard card )
{
/* nothing really */
card=card;
@@ -61,47 +81,47 @@ asimcard_ready( ASimCard card )
return card->status == A_SIM_STATUS_READY;
}
-ASimStatus
-asimcard_get_status( ASimCard sim )
+static ASimStatus
+sw_asimcard_get_status( ASimCard sim )
{
return sim->status;
}
-void
-asimcard_set_status( ASimCard sim, ASimStatus status )
+static void
+sw_asimcard_set_status( ASimCard sim, ASimStatus status )
{
sim->status = status;
}
-const char*
-asimcard_get_pin( ASimCard sim )
+static const char*
+sw_asimcard_get_pin( ASimCard sim )
{
return sim->pin;
}
-const char*
-asimcard_get_puk( ASimCard sim )
+static const char*
+sw_asimcard_get_puk( ASimCard sim )
{
return sim->puk;
}
-void
-asimcard_set_pin( ASimCard sim, const char* pin )
+static void
+sw_asimcard_set_pin( ASimCard sim, const char* pin )
{
strncpy( sim->pin, pin, A_SIM_PIN_SIZE );
sim->pin_retries = 0;
}
-void
-asimcard_set_puk( ASimCard sim, const char* puk )
+static void
+sw_asimcard_set_puk( ASimCard sim, const char* puk )
{
strncpy( sim->puk, puk, A_SIM_PUK_SIZE );
sim->pin_retries = 0;
}
-int
-asimcard_check_pin( ASimCard sim, const char* pin )
+static int
+sw_asimcard_check_pin( ASimCard sim, const char* pin )
{
if (sim->status != A_SIM_STATUS_PIN &&
sim->status != A_SIM_STATUS_READY )
@@ -121,8 +141,8 @@ asimcard_check_pin( ASimCard sim, const char* pin )
}
-int
-asimcard_check_puk( ASimCard sim, const char* puk, const char* pin )
+static int
+sw_asimcard_check_puk( ASimCard sim, const char* puk, const char* pin )
{
if (sim->status != A_SIM_STATUS_PUK)
return 0;
@@ -322,8 +342,8 @@ static SimFileEFDedicatedRec _const_files_dedicated[] =
};
#endif /* ENABLE_DYNAMIC_RECORDS */
-const char*
-asimcard_io( ASimCard sim, const char* cmd )
+static const char*
+sw_asimcard_io( ASimCard sim, const char* cmd )
{
int nn;
#if ENABLE_DYNAMIC_RECORDS
@@ -445,3 +465,693 @@ asimcard_io( ASimCard sim, const char* cmd )
return "ERROR: BAD COMMAND";
}
+#if defined(ENABLE_PCSC)
+#if defined(_WIN32)
+WINSCARDDATA const SCARD_IO_REQUEST g_rgSCardT0Pci = {SCARD_PROTOCOL_T0, 8};
+#endif
+
+static SCARD_IO_REQUEST pioSendPci;
+static unsigned char bRecvBuffer[MAX_BUFFER_SIZE], bSendBuffer[MAX_BUFFER_SIZE];
+
+static int pcsc_switch_enabled = 0;
+static char* pcsc_reader = NULL;
+
+void parse_pcsc_options( const char* options )
+{
+ long rv;
+ DWORD dwPref;
+ char *mszReaders;
+ ASimCard card = _s_card;
+
+ rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &card->hContext);
+ if(rv != SCARD_S_SUCCESS) {
+ printf("sim_card.c: pcscd not found\n");
+ return;
+ }
+
+#ifdef SCARD_AUTOALLOCATE
+ dwPref = SCARD_AUTOALLOCATE;
+ rv = SCardListReaders(card->hContext, NULL, (LPSTR)&mszReaders, &dwPref);
+#else
+ rv = SCardListReaders(card->hContext, NULL, NULL, &dwPref);
+ if(rv != SCARD_S_SUCCESS) {
+ printf("sim_card.c: no card reader found\n");
+ return;
+ }
+ mszReaders = calloc(dwPref, sizeof(char));
+ rv = SCardListReaders(card->hContext, NULL, mszReaders, &dwPref);
+#endif
+
+ if((rv != SCARD_S_SUCCESS) || (strlen(mszReaders) == 0)) {
+ rv = SCardReleaseContext(card->hContext);
+
+ printf("sim_card.c: no card reader found\n");
+ return;
+ }
+
+ if((options != NULL) && (strlen(options) > 0)) {
+ char* reader = mszReaders;
+ while(strlen(reader) > 0) {
+ if(!strncmp(options, reader, strlen(options))) {
+ pcsc_reader = reader;
+ break;
+ }
+ reader += strlen(reader) + 1;
+ }
+ }
+
+ // fallback to first card reader in list
+ if((pcsc_reader == NULL) || (strlen(pcsc_reader) == 0)) {
+ pcsc_reader = mszReaders;
+ while(strlen(mszReaders) > 0) {
+ printf("sim_card.c: %s\n", mszReaders);
+ mszReaders += strlen(mszReaders) + 1;
+ }
+ }
+ pcsc_switch_enabled = 1;
+ printf("sim_card.c: using card reader %s\n", pcsc_reader);
+}
+
+static ASimCard
+pcsc_asimcard_create( int port )
+{
+ long rv;
+ DWORD dwPref, len;
+ ASimCard card = _s_card;
+ card->status = A_SIM_STATUS_ABSENT;
+ card->pin_retries = 0;
+ card->port = port;
+
+
+ rv = SCardConnect(card->hContext, pcsc_reader, SCARD_SHARE_SHARED,
+ SCARD_PROTOCOL_T0, &card->hCard, &dwPref);
+ if((rv != SCARD_S_SUCCESS) || (dwPref != SCARD_PROTOCOL_T0)) {
+
+ printf("sim_card.c: failed to open card\n");
+ return card;
+ }
+
+ rv = SCardReconnect(card->hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0,
+ SCARD_RESET_CARD, &dwPref);
+ if((rv != SCARD_S_SUCCESS) || (dwPref != SCARD_PROTOCOL_T0)) {
+
+ printf("sim_card.c: failed to reset card\n");
+ return card;
+ }
+
+ pioSendPci = *SCARD_PCI_T0;
+
+ // check for DF Telecom
+ memcpy(bSendBuffer, "\xA0\xA4\x00\x00\x02\x7F\x10", 7);
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(card->hCard, &pioSendPci, bSendBuffer, 7, NULL,
+ bRecvBuffer, &len);
+ if((rv != SCARD_S_SUCCESS) || (len != 2) || (bRecvBuffer[0] != 0x9F)) {
+
+ printf("sim_card.c: sim application not found\n");
+ return card;
+ }
+
+ // identify current card status
+ memcpy(bSendBuffer, "\xA0\xA4\x00\x00\x02\x6F\x40", 7);
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(card->hCard, &pioSendPci, bSendBuffer, 7, NULL,
+ bRecvBuffer, &len);
+ if((rv != SCARD_S_SUCCESS) || (len != 2) || (bRecvBuffer[0] != 0x9F)) {
+
+ printf("sim_card.c: sim application not found\n");
+ return card;
+ }
+
+ memcpy(bSendBuffer, "\xA0\xB2\x01\x04\xFC", 5);
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(card->hCard, &pioSendPci, bSendBuffer, 5, NULL,
+ bRecvBuffer, &len);
+ if((rv != SCARD_S_SUCCESS) || (len != 2)) {
+
+ printf("sim_card.c: sim application not found\n");
+ return card;
+ }
+
+ if(bRecvBuffer[0] == 0x67)
+ card->status = A_SIM_STATUS_READY;
+
+ if((bRecvBuffer[0] == 0x98) && (bRecvBuffer[1] == 0x04))
+ card->status = A_SIM_STATUS_PIN;
+
+ // TODO: TERMINAL PROFILE, should be sent by RIL
+ memcpy(bSendBuffer, "\xA0\x10\x00\x00\x14\x3f\xfb\xff\xff\xff\x0f"
+ "\x00\x7f\x7f\x03\xfe\x1f\x23\x05\x14\x86\x07\x00\x00\x00", 25);
+ len = sizeof(bRecvBuffer);
+ SCardTransmit(card->hCard, &pioSendPci, bSendBuffer, 25, NULL,
+ bRecvBuffer, &len);
+
+ // TODO: TERMINAL CAPABILITY, should be sent by RIL
+ memcpy(bSendBuffer, "\x80\xAA\x00\x00\x04\xA9\x02\x81\x00", 9);
+
+ len = sizeof(bRecvBuffer);
+ SCardTransmit(card->hCard, &pioSendPci, bSendBuffer, 9, NULL,
+ bRecvBuffer, &len);
+
+ return card;
+}
+
+static void
+pcsc_asimcard_destroy( ASimCard card )
+{
+ long rv;
+
+ rv = SCardDisconnect(card->hCard, SCARD_UNPOWER_CARD);
+ rv = SCardReleaseContext(card->hContext);
+}
+
+static ASimStatus
+pcsc_asimcard_get_status( ASimCard sim )
+{
+ return sim->status;
+}
+
+static void
+pcsc_asimcard_set_pin( ASimCard sim, const char* pin )
+{
+ // TODO
+ sim->pin_retries = 0;
+}
+
+static int
+pcsc_asimcard_check_pin( ASimCard sim, const char* pin )
+{
+ long rv;
+ DWORD len;
+
+ if (sim->status != A_SIM_STATUS_PIN &&
+ sim->status != A_SIM_STATUS_READY )
+ return 0;
+
+ memcpy(bSendBuffer,
+ "\xA0\x20\x00\x01\x08\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 13);
+ memcpy(&bSendBuffer[5], pin, strlen(pin));
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 13, NULL,
+ bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len == 2)) {
+
+ if(((bRecvBuffer[0] == 0x90) && (bRecvBuffer[1] == 0x00)) || (bRecvBuffer[0] == 0x91)) {
+
+ sim->status = A_SIM_STATUS_READY;
+ sim->pin_retries = 0;
+ return 1;
+ }
+ }
+
+ if (sim->status != A_SIM_STATUS_READY) {
+ if (++sim->pin_retries == 3)
+ sim->status = A_SIM_STATUS_PUK;
+ }
+ return 0;
+}
+
+static int
+pcsc_asimcard_check_puk( ASimCard sim, const char* puk, const char* pin )
+{
+ if (sim->status != A_SIM_STATUS_PUK)
+ return 0;
+
+ // TODO
+
+ if ( ++sim->pin_retries == 6 ) {
+ sim->status = A_SIM_STATUS_ABSENT;
+ }
+ return 0;
+}
+
+static void
+asimcard_bytearray_to_str( char *s, unsigned char b[], int len )
+{
+ int i;
+
+ for(i = 0; i < len; i++)
+ sprintf(&s[i << 1], "%02x", b[i]);
+}
+
+static void
+asimcard_bytearray_to_crsm( char *s, unsigned char b[], int p3 )
+{
+ int i;
+
+ strcpy(s, "+CRSM: ");
+ sprintf(&s[strlen(s)], "%d", b[p3]);
+ strcat(s, ",");
+ sprintf(&s[strlen(s)], "%d", b[p3 + 1]);
+
+ if(p3 == 0)
+ return;
+
+ strcat(s, ",");
+ for(i = 0; i < p3; i++)
+ sprintf(&s[strlen(s)], "%02x", b[i]);
+}
+
+static void
+asimcard_str_to_bytearray( unsigned char b[], char *s )
+{
+ int i;
+
+ for(i = 0; i < (strlen(s) >> 1); i++) {
+ unsigned int bb;
+
+ sscanf(&s[i << 1], "%02x", &bb);
+ b[i] = bb;
+ }
+}
+
+static const char*
+pcsc_asimcard_cmd( ASimCard sim, const char* cmd )
+{
+ int clen, hChannel, iChannel;
+ char command[1024];
+
+ // transmit on basic channel:
+ if ( sscanf(cmd, "+CSIM=%d,\"%[0-9a-fA-F]", &clen, command) == 2 ) {
+ long rv;
+ DWORD len;
+
+ if ( (strlen(command) != clen) || (((clen >> 1) << 1) != clen) )
+ return "ERROR: BAD COMMAND";
+
+ asimcard_str_to_bytearray(bSendBuffer, command);
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, clen >> 1,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len >= 2)) {
+
+ if(len == 2) {
+ if((bRecvBuffer[0] == 0x61) || (bRecvBuffer[0] == 0x9f)) {
+ memcpy(&bSendBuffer[1], "\xc0\x00\x00", 3);
+ bSendBuffer[4] = bRecvBuffer[1];
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 5,
+ NULL, bRecvBuffer, &len);
+ } else
+ if(bRecvBuffer[0] == 0x6c) {
+ bSendBuffer[4] = bRecvBuffer[1];
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer,
+ clen >> 1, NULL, bRecvBuffer, &len);
+ }
+ }
+
+ if((rv == SCARD_S_SUCCESS) && (len >= 2)) {
+ sprintf(sim->out_buff, "+CSIM: %d,", (int)len << 1);
+ asimcard_bytearray_to_str(&sim->out_buff[strlen(sim->out_buff)],
+ bRecvBuffer, len);
+ return sim->out_buff;
+ }
+ }
+ return "+CME ERROR: SIM FAILURE";
+ }
+
+ // transmit on logical channel:
+ if ( sscanf(cmd, "+CGLA=%d,%d,\"%[0-9a-fA-F]", &hChannel, &clen, command)
+ == 3 ) {
+ long rv;
+ DWORD len;
+
+ iChannel = hChannel - H_CHANNEL_OFFSET;
+ if(iChannel <= 0 || iChannel >= MAX_N_CHANNELS)
+ return "+CME ERROR: INCORRECT PARAMETERS";
+
+ if ( (strlen(command) != clen) || (((clen >> 1) << 1) != clen) )
+ return "ERROR: BAD COMMAND";
+
+ asimcard_str_to_bytearray(bSendBuffer, command);
+
+ if (iChannel < 4) {
+ bSendBuffer[0] &= 0xfc;
+ bSendBuffer[0] |= iChannel;
+ }
+ else {
+ bSendBuffer[0] &= 0xf0;
+ bSendBuffer[0] |= 0x40 | (iChannel - 4);
+ }
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, clen >> 1,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len >= 2)) {
+
+ if(len == 2) {
+ if((bRecvBuffer[0] == 0x61) || (bRecvBuffer[0] == 0x9f)) {
+ memcpy(&bSendBuffer[1], "\xc0\x00\x00", 3);
+ bSendBuffer[4] = bRecvBuffer[1];
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 5,
+ NULL, bRecvBuffer, &len);
+ } else
+ if(bRecvBuffer[0] == 0x6c) {
+ bSendBuffer[4] = bRecvBuffer[1];
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer,
+ clen >> 1, NULL, bRecvBuffer, &len);
+ }
+ }
+
+ if((rv == SCARD_S_SUCCESS) && (len >= 2)) {
+ sprintf(sim->out_buff, "+CGLA: %d,", (int)len << 1);
+ asimcard_bytearray_to_str(&sim->out_buff[strlen(sim->out_buff)],
+ bRecvBuffer, len);
+ return sim->out_buff;
+ }
+ }
+ return "+CME ERROR: SIM FAILURE";
+ }
+
+ // open logical channel:
+ if ( sscanf(cmd, "+CCHO=\"%[0-9a-fA-F]", command) == 1 ) {
+ long rv;
+ DWORD len;
+
+ memcpy(bSendBuffer, "\x00\x70\x00\x00\x01", 5);
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 5,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len == 3) && (bRecvBuffer[0] > 0)) {
+ iChannel = bRecvBuffer[0];
+
+ bSendBuffer[0] = (iChannel < 4)? iChannel: 0x40 | (iChannel - 4);
+
+ memcpy(&bSendBuffer[1], "\xa4\x04\x00", 3);
+ bSendBuffer[4] = strlen(command) >> 1;
+ asimcard_str_to_bytearray(&bSendBuffer[5], command);
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer,
+ bSendBuffer[4] + 5, NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) &&
+ (((len == 2) && (bRecvBuffer[0] == 0x61)) ||
+ ((len >= 2) && (bRecvBuffer[len-2] == 0x90)))) {
+ sprintf(sim->out_buff, "+CCHO: %d", H_CHANNEL_OFFSET + iChannel);
+ return sim->out_buff;
+ }
+
+ memcpy(bSendBuffer, "\x00\x70\x80\x00\x00", 5);
+ bSendBuffer[3] = iChannel;
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 5,
+ NULL, bRecvBuffer, &len);
+
+ return "+CME ERROR: NOT FOUND";
+ }
+ return "+CME ERROR: MEMORY FULL";
+ }
+
+ // close logical channel:
+ if ( sscanf(cmd, "+CCHC=%d", &hChannel) == 1 ) {
+ long rv;
+ DWORD len;
+
+ iChannel = hChannel - H_CHANNEL_OFFSET;
+ if(iChannel <= 0 || iChannel >= MAX_N_CHANNELS)
+ return "+CME ERROR: INCORRECT PARAMETERS";
+
+ memcpy(bSendBuffer, "\x00\x70\x80\x00\x00", 5);
+ bSendBuffer[3] = iChannel;
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 5,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len == 2) &&
+ (bRecvBuffer[0] == 0x90) && (bRecvBuffer[1] == 0x00))
+ return NULL;
+
+ return "+CME ERROR: SIM FAILURE";
+ }
+
+ return "ERROR: BAD COMMAND";
+}
+
+static const char*
+pcsc_asimcard_io( ASimCard sim, const char* cmd )
+{
+ int command, id, p1, p2, p3;
+ char pathid[12];
+ long rv;
+ DWORD len;
+
+ assert( memcmp( cmd, "+CRSM=", 6 ) == 0 );
+ memset( pathid, 0, sizeof(pathid));
+
+ if ( sscanf(cmd, "+CRSM=%d,%d,%d,%d,%d", &command, &id, &p1, &p2, &p3)
+ == 5 ) {
+ // check for pathid.
+ int i = 6, j=0;
+ int delimitercount = 0;
+ unsigned int selects = 0;
+ for( ; i < strlen(cmd); i++ ) {
+ if( cmd[i] == ',' ){
+ delimitercount++;
+ continue;
+ }
+ if( delimitercount == 6 ) { // pathid comes after the 6th delimter
+ pathid[j++] = cmd[i];
+ }
+ }
+
+ unsigned int str_len = strlen(pathid);
+ if( (str_len % 4) != 0 ){
+ return "ERROR: Invalid path";
+ } else {
+ selects = str_len / 4;
+ }
+
+ unsigned int path[12];
+
+ for (i = 0; i < (str_len / 2); i++) {
+ sscanf(pathid + 2*i, "%02x", &path[i]);
+ }
+
+ // SELECT DF (optional)
+ if(id != 0) {
+ memcpy(bSendBuffer, "\xA0\xA4\x00\x00\x02\x7F\x20", 7);
+ if((id == 0x6F3A) || (id == 0x6F3B) || (id == 0x6F3C) ||
+ (id == 0x6F3D) || (id == 0x6F40) || (id == 0x6F42) ||
+ (id == 0x6F43) || (id == 0x6F44) || (id == 0x6F47) ||
+ (id == 0x6F49) || (id == 0x6F4A) || (id == 0x6F4B) ||
+ (id == 0x6F4C) || (id == 0x6F4D) || (id == 0x6F4E)) {
+
+ path[0] = 0x7F;
+ path[1] = 0x10;
+ selects = 1;
+ } else
+ if((id == 0x2FE2) || (id == 0x2F05) || (id == 0x2F00)) {
+
+ path[0] = 0x3F;
+ path[1] = 0x00;
+ selects = 1;
+ }
+
+ len = sizeof(bRecvBuffer);
+ for( i = 0; i < selects; i++ ) {
+ bSendBuffer[5] = path[2*i];
+ bSendBuffer[6] = path[2*i+1];
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 7,
+ NULL, bRecvBuffer, &len);
+ if((rv != SCARD_S_SUCCESS) || (len != 2) || (bRecvBuffer[0] != 0x9F))
+ return "ERROR: SELECT DF FAILED";
+ }
+ }
+
+ switch (command) {
+ case A_SIM_CMD_GET_RESPONSE:
+ {
+ memcpy(bSendBuffer, "\xA0\xA4\x00\x00\x02\xFF\xFF", 7);
+ bSendBuffer[5] = id >> 8;
+ bSendBuffer[6] = id & 0xff;
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 7,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len == 2) &&
+ (bRecvBuffer[0] == 0x9F)) {
+
+ memcpy(bSendBuffer, "\xA0\xC0\x00\x00\x0F", 5);
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 5,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len >= 2)) {
+
+ asimcard_bytearray_to_crsm(sim->out_buff, bRecvBuffer, len-2);
+ return sim->out_buff;
+ }
+ }
+
+ return "ERROR: INTERNAL SIM ERROR";
+ break;
+ }
+
+ case A_SIM_CMD_READ_BINARY:
+ {
+ // force EF(AD) content to match settings of MNO (len(MNC) = 3)
+ if((id == 0x6FAD) && (p3 == 4))
+ return "+CRSM: 144,0,00000003";
+
+ memcpy(bSendBuffer, "\xA0\xA4\x00\x00\x02\xFF\xFF", 7);
+ bSendBuffer[5] = id >> 8;
+ bSendBuffer[6] = id & 0xff;
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 7,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len == 2) &&
+ (bRecvBuffer[0] == 0x9F)) {
+
+ memcpy(bSendBuffer, "\xA0\xB0\x00\x00\xFF", 5);
+ bSendBuffer[3] = p2 & 0xff;
+ bSendBuffer[4] = p3 & 0xff;
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 5,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len >= 2)) {
+
+ asimcard_bytearray_to_crsm(sim->out_buff, bRecvBuffer, len-2);
+ return sim->out_buff;
+ }
+ }
+
+ return "ERROR: INTERNAL SIM ERROR";
+ break;
+ }
+
+ case A_SIM_CMD_READ_RECORD:
+ {
+ memcpy(bSendBuffer, "\xA0\xA4\x00\x00\x02\xFF\xFF", 7);
+ bSendBuffer[5] = id >> 8;
+ bSendBuffer[6] = id & 0xff;
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 7,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len == 2) &&
+ (bRecvBuffer[0] == 0x9F)) {
+
+ memcpy(bSendBuffer, "\xA0\xB2\xFF\xFF\xFF", 5);
+ bSendBuffer[2] = p1 & 0xff;
+ bSendBuffer[3] = p2 & 0xff;
+ bSendBuffer[4] = p3 & 0xff;
+
+ len = sizeof(bRecvBuffer);
+ rv = SCardTransmit(sim->hCard, &pioSendPci, bSendBuffer, 5,
+ NULL, bRecvBuffer, &len);
+ if((rv == SCARD_S_SUCCESS) && (len >= 2)) {
+
+ asimcard_bytearray_to_crsm(sim->out_buff, bRecvBuffer, len-2);
+ return sim->out_buff;
+ }
+ }
+
+ return "ERROR: INTERNAL SIM ERROR";
+ break;
+ }
+
+ default:
+ return "ERROR: UNSUPPORTED SIM COMMAND";
+ }
+ }
+ return "ERROR: BAD COMMAND";
+}
+
+#endif /* ENABLE_PCSC */
+
+/* wrapper functions */
+
+ASimCard
+asimcard_create( int port )
+{
+#if defined(ENABLE_PCSC)
+ if (pcsc_switch_enabled)
+ return pcsc_asimcard_create(port);
+#endif
+ return sw_asimcard_create(port);
+}
+
+void
+asimcard_destroy( ASimCard card )
+{
+#if defined(ENABLE_PCSC)
+ if (pcsc_switch_enabled)
+ return pcsc_asimcard_destroy(card);
+#endif
+ return sw_asimcard_destroy(card);
+}
+
+ASimStatus
+asimcard_get_status( ASimCard sim )
+{
+#if defined(ENABLE_PCSC)
+ if (pcsc_switch_enabled)
+ return pcsc_asimcard_get_status(sim);
+#endif
+ return sw_asimcard_get_status(sim);
+}
+
+void
+asimcard_set_pin( ASimCard sim, const char* pin )
+{
+#if defined(ENABLE_PCSC)
+ if (pcsc_switch_enabled)
+ return pcsc_asimcard_set_pin(sim, pin);
+#endif
+ return sw_asimcard_set_pin(sim, pin);
+}
+
+int
+asimcard_check_pin( ASimCard sim, const char* pin )
+{
+#if defined(ENABLE_PCSC)
+ if (pcsc_switch_enabled)
+ return pcsc_asimcard_check_pin(sim, pin);
+#endif
+ return sw_asimcard_check_pin(sim, pin);
+}
+
+int
+asimcard_check_puk( ASimCard sim, const char* puk, const char* pin )
+{
+#if defined(ENABLE_PCSC)
+ if (pcsc_switch_enabled)
+ return pcsc_asimcard_check_puk(sim, puk, pin);
+#endif
+ return sw_asimcard_check_puk(sim, puk, pin);
+}
+
+const char*
+asimcard_io( ASimCard sim, const char* cmd )
+{
+#if defined(ENABLE_PCSC)
+ if (pcsc_switch_enabled)
+ return pcsc_asimcard_io(sim, cmd);
+#endif
+ return sw_asimcard_io(sim, cmd);
+}
+
+const char*
+asimcard_cmd( ASimCard sim, const char* cmd )
+{
+#if defined(ENABLE_PCSC)
+ if (pcsc_switch_enabled)
+ return pcsc_asimcard_cmd(sim, cmd);
+#endif
+ return "ERROR: UNSUPPORTED COMMAND";
+}
+
diff --git a/telephony/sim_card.h b/telephony/sim_card.h
index 1bab1ba..69e033f 100644
--- a/telephony/sim_card.h
+++ b/telephony/sim_card.h
@@ -50,5 +50,6 @@ typedef enum {
} ASimCommand;
extern const char* asimcard_io( ASimCard sim, const char* cmd );
+extern const char* asimcard_cmd( ASimCard sim, const char* cmd );
#endif /* _android_sim_card_h */
project frameworks/base/
diff --git a/api/current.txt b/api/current.txt
index 0ff0fbc..e95bcb2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9804,7 +9804,6 @@ package android.hardware {
method public int getJpegQuality();
method public int getJpegThumbnailQuality();
method public android.hardware.Camera.Size getJpegThumbnailSize();
- method public java.lang.String getPowerMode();
method public int getMaxExposureCompensation();
method public int getMaxNumDetectedFaces();
method public int getMaxNumFocusAreas();
@@ -9814,6 +9813,7 @@ package android.hardware {
method public int getMinExposureCompensation();
method public int getPictureFormat();
method public android.hardware.Camera.Size getPictureSize();
+ method public java.lang.String getPowerMode();
method public android.hardware.Camera.Size getPreferredPreviewSizeForVideo();
method public int getPreviewFormat();
method public void getPreviewFpsRange(int[]);
@@ -16435,6 +16435,7 @@ package android.os {
field public static final int SIGNAL_KILL = 9; // 0x9
field public static final int SIGNAL_QUIT = 3; // 0x3
field public static final int SIGNAL_USR1 = 10; // 0xa
+ field public static final int SMARTCARD_UID = 1029; // 0x405
field public static final int SYSTEM_UID = 1000; // 0x3e8
field public static final int THREAD_PRIORITY_AUDIO = -16; // 0xfffffff0
field public static final int THREAD_PRIORITY_BACKGROUND = 10; // 0xa
@@ -41334,8 +41335,8 @@ package java.util.zip {
public class ZipFile {
ctor public ZipFile(java.io.File) throws java.io.IOException, java.util.zip.ZipException;
- ctor public ZipFile(java.lang.String) throws java.io.IOException;
ctor public ZipFile(java.io.File, int) throws java.io.IOException;
+ ctor public ZipFile(java.lang.String) throws java.io.IOException;
method public void close() throws java.io.IOException;
method public java.util.Enumeration extends java.util.zip.ZipEntry> entries();
method public java.util.zip.ZipEntry getEntry(java.lang.String);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 05099fb..bd6e188 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -104,6 +104,11 @@ public class Process {
public static final int SDCARD_RW_GID = 1015;
/**
+ * Defines the UID/GID for the SmartCard service process.
+ */
+ public static final int SMARTCARD_UID = 1029;
+
+ /**
* Defines the UID/GID for the group that controls VPN services.
* @hide
*/
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 126da58..c364161 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -188,6 +188,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final int LOG_UID = Process.LOG_UID;
private static final int NFC_UID = Process.NFC_UID;
private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
+ private static final int SMARTCARD_UID = Process.SMARTCARD_UID;
private static final boolean GET_CERTIFICATES = true;
@@ -977,6 +978,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);
+ mSettings.addSharedUserLPw("org.simalliance.uid.openmobileapi", SMARTCARD_UID, ApplicationInfo.FLAG_SYSTEM);
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 11e01b9..1396de6 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -286,5 +286,40 @@ interface ITelephony {
List getAllCellInfo();
int getLteOnGsmMode();
+
+ /**
+ * Returns the response APDU for a command APDU sent to a logical channel
+ */
+ String transmitIccLogicalChannel(int cla, int command, int channel,
+ int p1, int p2, int p3, String data);
+
+ /**
+ * Returns the response APDU for a command APDU sent to the basic channel
+ */
+ String transmitIccBasicChannel(int cla, int command,
+ int p1, int p2, int p3, String data);
+
+ /**
+ * Returns the channel id of the logical channel,
+ * Returns 0 on error.
+ */
+ int openIccLogicalChannel(String AID);
+
+ /**
+ * Return true if logical channel was closed successfully
+ */
+ boolean closeIccLogicalChannel(int channel);
+
+ /**
+ * Returns the error code of the last error occured.
+ * Currently only used for openIccLogicalChannel
+ */
+ int getLastError();
+
+ /**
+ * Returns the response APDU for a command APDU sent through SIM_IO
+ */
+ byte[] transmitIccSimIO(int fileID, int command,
+ int p1, int p2, int p3, String filePath);
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index d93da8f..1d22720 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -55,6 +55,10 @@ public interface RILConstants {
int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due
to wrong SIM/ME and no
retries needed */
+ int MISSING_RESOURCE = 29;//Old error code 16;
+ int NO_SUCH_ELEMENT = 30; //Old error code 17;
+ int INVALID_PARAMETER = 27; //Old error code 18;
+
/* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */
@@ -260,6 +264,11 @@ cat include/telephony/ril.h | \
int RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU = 106;
int RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS = 107;
int RIL_REQUEST_VOICE_RADIO_TECH = 108;
+ int RIL_REQUEST_SIM_TRANSMIT_BASIC = 10026;
+ int RIL_REQUEST_SIM_OPEN_CHANNEL = 10027;
+ int RIL_REQUEST_SIM_CLOSE_CHANNEL = 10028;
+ int RIL_REQUEST_SIM_TRANSMIT_CHANNEL = 10029;
+
int RIL_UNSOL_RESPONSE_BASE = 1000;
int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
project frameworks/opt/telephony/
diff --git a/src/java/com/android/internal/telephony/CommandException.java b/src/java/com/android/internal/telephony/CommandException.java
index 94c544e..e4c7e74 100644
--- a/src/java/com/android/internal/telephony/CommandException.java
+++ b/src/java/com/android/internal/telephony/CommandException.java
@@ -42,6 +42,9 @@ public class CommandException extends RuntimeException {
MODE_NOT_SUPPORTED,
FDN_CHECK_FAILURE,
ILLEGAL_SIM_OR_ME,
+ MISSING_RESOURCE,
+ NO_SUCH_ELEMENT,
+ INVALID_PARAMETER,
}
public CommandException(Error e) {
@@ -83,6 +86,12 @@ public class CommandException extends RuntimeException {
return new CommandException(Error.FDN_CHECK_FAILURE);
case RILConstants.ILLEGAL_SIM_OR_ME:
return new CommandException(Error.ILLEGAL_SIM_OR_ME);
+ case RILConstants.MISSING_RESOURCE:
+ return new CommandException(Error.MISSING_RESOURCE);
+ case RILConstants.NO_SUCH_ELEMENT:
+ return new CommandException(Error.NO_SUCH_ELEMENT);
+ case RILConstants.INVALID_PARAMETER:
+ return new CommandException(Error.INVALID_PARAMETER);
default:
Log.e("GSM", "Unrecognized RIL errno " + ril_errno);
return new CommandException(Error.INVALID_RESPONSE);
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index a88aded..4bb9cb8 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -1142,6 +1142,18 @@ public interface CommandsInterface {
void setNetworkSelectionModeManual(String operatorNumeric, Message response);
+
+ /**
+ * SmartCard API related exports
+ */
+ void iccExchangeAPDU(int cla, int command, int channel, int p1, int p2,
+ int p3, String data, Message response);
+
+ void iccOpenChannel(String AID, Message response);
+
+ void iccCloseChannel(int channel, Message response);
+
+
/**
* Queries whether the current network selection mode is automatic
* or manual
diff --git a/src/java/com/android/internal/telephony/IccCard.java b/src/java/com/android/internal/telephony/IccCard.java
index f1ac581..cf69082 100644
--- a/src/java/com/android/internal/telephony/IccCard.java
+++ b/src/java/com/android/internal/telephony/IccCard.java
@@ -211,4 +211,14 @@ public interface IccCard {
* @return true if a ICC card is present
*/
public boolean hasIccCard();
+
+ public void exchangeAPDU(int cla, int command, int channel, int p1, int p2,
+ int p3, String data, Message onComplete);
+
+ public void openLogicalChannel(String AID, Message onComplete);
+
+ public void closeLogicalChannel(int channel, Message onComplete);
+
+ public void exchangeSimIO(int fileID, int command,
+ int p1, int p2, int p3, String pathID, Message onComplete);
}
diff --git a/src/java/com/android/internal/telephony/IccCardProxy.java b/src/java/com/android/internal/telephony/IccCardProxy.java
index cdd2fea..b4624ac 100644
--- a/src/java/com/android/internal/telephony/IccCardProxy.java
+++ b/src/java/com/android/internal/telephony/IccCardProxy.java
@@ -693,4 +693,39 @@ public class IccCardProxy extends Handler implements IccCard {
private void loge(String msg) {
Log.e(LOG_TAG, msg);
}
+
+ public void exchangeAPDU(int cla, int command, int channel, int p1, int p2,
+ int p3, String data, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.exchangeAPDU(cla,command,channel,p1,p2,p3,data,onComplete);
+ }
+ }
+ }
+
+ public void openLogicalChannel(String AID, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ Log.d(LOG_TAG, "RIL opening logical channel to "+ AID);
+ mUiccApplication.openLogicalChannel(AID,onComplete);
+ }
+ }
+ }
+
+ public void closeLogicalChannel(int channel, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.closeLogicalChannel(channel,onComplete);
+ }
+ }
+ }
+
+ public void exchangeSimIO(int fileID, int command,
+ int p1, int p2, int p3, String pathID, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.exchangeSimIO(fileID,command,p1,p2,p3,pathID,onComplete);
+ }
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/IccProvider.java b/src/java/com/android/internal/telephony/IccProvider.java
index a66e19d..4d07ddc 100644
--- a/src/java/com/android/internal/telephony/IccProvider.java
+++ b/src/java/com/android/internal/telephony/IccProvider.java
@@ -39,7 +39,7 @@ import com.android.internal.telephony.IIccPhoneBook;
*/
public class IccProvider extends ContentProvider {
private static final String TAG = "IccProvider";
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final String[] ADDRESS_BOOK_COLUMN_NAMES = new String[] {
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 9d3314f..14e78e6 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -59,7 +59,9 @@ import com.android.internal.telephony.cdma.CdmaInformationRecords;
import com.android.internal.telephony.IccRefreshResponse;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
@@ -2165,7 +2167,7 @@ public class RIL extends BaseCommands implements CommandsInterface {
protected void
send(RILRequest rr) {
Message msg;
-
+
if (mSocket == null) {
rr.onError(RADIO_NOT_AVAILABLE, null);
rr.release();
@@ -2259,7 +2261,7 @@ public class RIL extends BaseCommands implements CommandsInterface {
}
Object ret = null;
-
+
if (error == 0 || p.dataAvail() > 0) {
// either command succeeds or command fails but with data payload
try {switch (rr.mRequest) {
@@ -2305,6 +2307,10 @@ public class RIL extends BaseCommands implements CommandsInterface {
case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret = responseSMS(p); break;
case RIL_REQUEST_SETUP_DATA_CALL: ret = responseSetupDataCall(p); break;
case RIL_REQUEST_SIM_IO: ret = responseICC_IO(p); break;
+ case RIL_REQUEST_SIM_TRANSMIT_BASIC: ret = responseICC_IO(p); break;
+ case RIL_REQUEST_SIM_OPEN_CHANNEL: ret = responseInts(p); break;
+ case RIL_REQUEST_SIM_CLOSE_CHANNEL: ret = responseVoid(p); break;
+ case RIL_REQUEST_SIM_TRANSMIT_CHANNEL: ret = responseICC_IO(p); break;
case RIL_REQUEST_SEND_USSD: ret = responseVoid(p); break;
case RIL_REQUEST_CANCEL_USSD: ret = responseVoid(p); break;
case RIL_REQUEST_GET_CLIR: ret = responseInts(p); break;
@@ -2523,7 +2529,7 @@ public class RIL extends BaseCommands implements CommandsInterface {
Object ret;
response = p.readInt();
-
+
try {switch(response) {
/*
cat libs/telephony/ril_unsol_commands.h \
@@ -3623,6 +3629,10 @@ public class RIL extends BaseCommands implements CommandsInterface {
case RIL_REQUEST_SEND_SMS_EXPECT_MORE: return "SEND_SMS_EXPECT_MORE";
case RIL_REQUEST_SETUP_DATA_CALL: return "SETUP_DATA_CALL";
case RIL_REQUEST_SIM_IO: return "SIM_IO";
+ case RIL_REQUEST_SIM_TRANSMIT_BASIC: return "SIM_TRANSMIT_BASIC";
+ case RIL_REQUEST_SIM_OPEN_CHANNEL: return "SIM_OPEN_CHANNEL";
+ case RIL_REQUEST_SIM_CLOSE_CHANNEL: return "SIM_CLOSE_CHANNEL";
+ case RIL_REQUEST_SIM_TRANSMIT_CHANNEL: return "SIM_TRANSMIT_CHANNEL";
case RIL_REQUEST_SEND_USSD: return "SEND_USSD";
case RIL_REQUEST_CANCEL_USSD: return "CANCEL_USSD";
case RIL_REQUEST_GET_CLIR: return "GET_CLIR";
@@ -3989,4 +3999,62 @@ public class RIL extends BaseCommands implements CommandsInterface {
pw.println(" mLastNITZTimeInfo=" + mLastNITZTimeInfo);
pw.println(" mTestingEmergencyCall=" + mTestingEmergencyCall.get());
}
+
+ public void
+ iccExchangeAPDU(int cla, int command, int channel, int p1, int p2, int p3,
+ String data, Message result) {
+ RILRequest rr;
+ if (channel == 0) {
+ rr = RILRequest.obtain(RIL_REQUEST_SIM_TRANSMIT_BASIC, result);
+ } else {
+ rr = RILRequest.obtain(RIL_REQUEST_SIM_TRANSMIT_CHANNEL, result);
+ }
+
+ rr.mp.writeInt(cla);
+ rr.mp.writeInt(command);
+ rr.mp.writeInt(channel);
+ rr.mp.writeString(null);
+ rr.mp.writeInt(p1);
+ rr.mp.writeInt(p2);
+ rr.mp.writeInt(p3);
+ rr.mp.writeString(data);
+ rr.mp.writeString(null);
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> iccExchangeAPDU: " + requestToString(rr.mRequest)
+ + "Channel 0x" + Integer.toHexString(channel) + ": "
+ + " 0x" + Integer.toHexString(cla)
+ + " 0x" + Integer.toHexString(command)
+ + " 0x" + Integer.toHexString(p1)
+ + " 0x" + Integer.toHexString(p2)
+ + " 0x" + Integer.toHexString(p3)
+ );
+
+ send(rr);
+ }
+
+ public void
+ iccOpenChannel(String AID, Message result) {
+ RILRequest rr
+ = RILRequest.obtain(RIL_REQUEST_SIM_OPEN_CHANNEL, result);
+
+ rr.mp.writeString(AID);
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> iccOpenChannel: " + requestToString(rr.mRequest)
+ + " " + AID);
+ send(rr);
+ }
+
+ public void
+ iccCloseChannel(int channel, Message result) {
+ RILRequest rr
+ = RILRequest.obtain(RIL_REQUEST_SIM_CLOSE_CHANNEL, result);
+
+ rr.mp.writeInt(1);
+ rr.mp.writeInt(channel);
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> iccCloseChannel: " + requestToString(rr.mRequest)
+ + " " + channel);
+
+ send(rr);
+ }
}
diff --git a/src/java/com/android/internal/telephony/SamsungExynos4RIL.java b/src/java/com/android/internal/telephony/SamsungExynos4RIL.java
index ce9667d..58ddc34 100644
--- a/src/java/com/android/internal/telephony/SamsungExynos4RIL.java
+++ b/src/java/com/android/internal/telephony/SamsungExynos4RIL.java
@@ -36,12 +36,14 @@ import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.NetworkInfo;
import android.os.AsyncResult;
+import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.PowerManager;
+import android.os.Process;
import android.os.SystemProperties;
import android.os.PowerManager.WakeLock;
import android.telephony.NeighboringCellInfo;
@@ -58,11 +60,14 @@ import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
import com.android.internal.telephony.cdma.CdmaInformationRecords;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.Runtime;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
@@ -152,11 +157,19 @@ public class SamsungExynos4RIL extends RIL implements CommandsInterface {
static final int RIL_UNSOL_UTS_GET_UNREAD_SMS_STATUS = 11031;
static final int RIL_UNSOL_MIP_CONNECT_STATUS = 11032;
+ //mh 052013 internal event check
+ private static final int EVENT_EXCHANGE_APDU_DONE = 1;
+ private static final int EVENT_OPEN_CHANNEL_DONE = 2;
+ private static final int EVENT_CLOSE_CHANNEL_DONE = 3;
+
protected HandlerThread mSamsungExynos4RILThread;
protected ConnectivityHandler mSamsungExynos4RILHandler;
private AudioManager audioManager;
private boolean mIsGBModem = SystemProperties.getBoolean("ro.ril.gbmodem", false);
-
+
+ //mh 052013 add response byte for open channel
+ private byte[] mOpenResponseBytes;
+
public SamsungExynos4RIL(Context context, int networkMode, int cdmaSubscription) {
super(context, networkMode, cdmaSubscription);
audioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
@@ -455,7 +468,7 @@ public class SamsungExynos4RIL extends RIL implements CommandsInterface {
case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: ret = responseInts(p); break;
case RIL_REQUEST_DATA_CALL_LIST: ret = responseDataCallList(p); break;
case RIL_REQUEST_RESET_RADIO: ret = responseVoid(p); break;
- case RIL_REQUEST_OEM_HOOK_RAW: ret = responseRaw(p); break;
+ case RIL_REQUEST_OEM_HOOK_RAW: ret = responseRawCheckRequest(p,rr.mResult); break;
case RIL_REQUEST_OEM_HOOK_STRINGS: ret = responseStrings(p); break;
case RIL_REQUEST_SCREEN_STATE: ret = responseVoid(p); break;
case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: ret = responseVoid(p); break;
@@ -955,4 +968,169 @@ public class SamsungExynos4RIL extends RIL implements CommandsInterface {
Log.d(LOG_TAG, "RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE blocked!!!");
//send(rr);
}
+
+
+
+ protected Object
+ responseRawCheckRequest(Parcel p, Message mResult) {
+ Object ret = null;
+ byte[] responseByteArray = p.createByteArray();
+
+ switch(mResult.arg1){
+ case EVENT_EXCHANGE_APDU_DONE:
+
+ if (responseByteArray != null) {
+ Log.d(LOG_TAG, "exchange APDU done received response byte array : " + IccUtils.bytesToHexString(responseByteArray));
+ if (responseByteArray.length >= 2) {
+ ret = new IccIoResult(
+ responseByteArray[responseByteArray.length - 2] & 0x0ff,
+ responseByteArray[responseByteArray.length - 1] & 0x0ff,
+ Arrays.copyOf(responseByteArray, responseByteArray.length - 2));
+ }
+ }
+ break;
+ case EVENT_OPEN_CHANNEL_DONE:
+ int channel = 0;
+
+ if(responseByteArray != null && responseByteArray.length > 0){
+ Log.d(LOG_TAG, "open channel done received response byte array : " + IccUtils.bytesToHexString(responseByteArray));
+ int channelLength = responseByteArray[0] & 0x0ff;
+ if (responseByteArray.length > channelLength) {
+ for (int i = channelLength; i > 0; --i) {
+ channel <<= 8;
+ channel |= responseByteArray[i] & 0x0ff;
+ }
+
+ if (responseByteArray.length > (channelLength + 1)) {
+ int responseLength = responseByteArray[channelLength + 1];
+
+ if (responseByteArray.length > (channelLength + 1 + responseLength)) {
+ mOpenResponseBytes = Arrays.copyOfRange(responseByteArray, channelLength + 1, channelLength + 1 + responseLength + 1);
+ }
+ }
+ }
+ }
+ ret = new int[]{channel};
+ break;
+ case EVENT_CLOSE_CHANNEL_DONE:
+ default:
+ return responseRaw(p);
+ }
+ return ret;
+ }
+
+ @Override
+ public void
+ iccExchangeAPDU(int cla, int command, int channel, int p1, int p2, int p3,
+ String data, Message result) {
+ ByteArrayOutputStream commandByteStream = new ByteArrayOutputStream();
+ DataOutputStream commandOutputStream = new DataOutputStream(commandByteStream);
+ try {
+ commandOutputStream.writeByte(21);
+
+ int commandLength = 12;
+ if (p3 == -1) {
+ commandOutputStream.writeByte(12);
+ } else {
+ commandOutputStream.writeByte(11);
+ ++commandLength;
+ }
+
+ byte[] dataBytes = null;
+ if (data != null) {
+ commandLength += data.length() / 2;
+
+ dataBytes = new byte[data.length() / 2];
+ for (int i = 0; i < dataBytes.length; ++i) {
+ dataBytes[i] = (byte) Integer.parseInt(data.substring(2 * i, 2 + 2 * i), 16);
+ }
+ }
+
+ commandOutputStream.writeShort(commandLength);
+ commandOutputStream.writeByte(cla);
+ commandOutputStream.writeByte(command);
+ commandOutputStream.writeByte(p1);
+ commandOutputStream.writeByte(p2);
+ if (p3 != -1) {
+ commandOutputStream.writeByte(p3);
+ }
+ commandOutputStream.writeInt(channel);
+ if (dataBytes != null) {
+ commandOutputStream.write(dataBytes);
+ }
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "CMD_ECHANGE_APDU: send failed - ", e);
+ }
+
+ Log.e(LOG_TAG, "sendRawRequest - iccExchangeAPDU: "
+ + "Channel 0x" + Integer.toHexString(channel) + ": "
+ + " 0x" + Integer.toHexString(cla)
+ + " 0x" + Integer.toHexString(command)
+ + " 0x" + Integer.toHexString(p1)
+ + " 0x" + Integer.toHexString(p2)
+ + " 0x" + Integer.toHexString(p3)
+ );
+
+ //inform response handler that this is a exchange APDU request
+ result.arg1 = EVENT_EXCHANGE_APDU_DONE;
+ invokeOemRilRequestRaw(commandByteStream.toByteArray(), result);
+ }
+
+ @Override
+ public void
+ iccOpenChannel(String AID, Message result) {
+ if(AID == null) {
+ AID = "";
+ }
+
+ final int aidLength = AID.length()/2;
+ byte[] aidBytes = new byte[aidLength];
+ for (int i = 0; i < aidLength; ++i) {
+ aidBytes[i] = (byte) Integer.parseInt(AID.substring(2 * i, 2 + 2 * i), 16);
+ }
+
+ ByteArrayOutputStream commandByteStream = new ByteArrayOutputStream();
+ DataOutputStream commandOutputStream = new DataOutputStream(commandByteStream);
+ try {
+ commandOutputStream.writeByte(21);
+ commandOutputStream.writeByte(9);
+ commandOutputStream.writeShort(4 + aidLength);
+ commandOutputStream.write(aidBytes);
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "CMD_OPEN_CHANNEL : open fail", e);
+ e.printStackTrace();
+ }
+
+ //inform response handler that this is a open channel request
+ result.arg1 = EVENT_OPEN_CHANNEL_DONE;
+
+ Log.d(LOG_TAG, "sendRawRequest - open channel: AID: "+ AID);
+ invokeOemRilRequestRaw(commandByteStream.toByteArray(), result);
+ }
+
+ @Override
+ public void
+ iccCloseChannel(int channel, Message result) {
+ ByteArrayOutputStream commandByteStream = new ByteArrayOutputStream();
+ DataOutputStream commandOutputStream = new DataOutputStream(commandByteStream);
+ try {
+ commandOutputStream.writeByte(21);
+ commandOutputStream.writeByte(10);
+ if (channel != 0) {
+ commandOutputStream.writeShort(8);
+ commandOutputStream.writeInt(channel);
+ } else {
+ commandOutputStream.writeShort(4);
+ }
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "CMD_CLOSE_CHANNEL : close fail", e);
+ }
+
+ //inform response handler that this is a close channel request
+ result.arg1 = EVENT_CLOSE_CHANNEL_DONE;
+
+ Log.d(LOG_TAG, "sendRawRequest - close channel "+ channel);
+ invokeOemRilRequestRaw(commandByteStream.toByteArray(), result);
+
+ }
}
diff --git a/src/java/com/android/internal/telephony/UiccCardApplication.java b/src/java/com/android/internal/telephony/UiccCardApplication.java
index 2718af6..f1b9d89 100644
--- a/src/java/com/android/internal/telephony/UiccCardApplication.java
+++ b/src/java/com/android/internal/telephony/UiccCardApplication.java
@@ -46,7 +46,11 @@ public class UiccCardApplication {
private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 2;
private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 3;
private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 4;
-
+ private static final int EVENT_EXCHANGE_APDU_DONE = 5;
+ private static final int EVENT_OPEN_CHANNEL_DONE = 6;
+ private static final int EVENT_CLOSE_CHANNEL_DONE = 7;
+ private static final int EVENT_SIM_IO_DONE = 8;
+
private final Object mLock = new Object();
private UiccCard mUiccCard; //parent
private AppState mAppState;
@@ -335,6 +339,18 @@ public class UiccCardApplication {
ar = (AsyncResult)msg.obj;
onChangeFacilityLock(ar);
break;
+ case EVENT_EXCHANGE_APDU_DONE:
+ case EVENT_OPEN_CHANNEL_DONE:
+ case EVENT_CLOSE_CHANNEL_DONE:
+ case EVENT_SIM_IO_DONE:
+ ar = (AsyncResult)msg.obj;
+ if(ar.exception != null) {
+ if (DBG) log("Error in SIM access with exception" + ar.exception);
+ }
+ AsyncResult.forMessage(((Message)ar.userObj),
+ ar.result, ar.exception);
+ ((Message)ar.userObj).sendToTarget();
+ break;
default:
loge("Unknown Event " + msg.what);
}
@@ -696,4 +712,26 @@ public class UiccCardApplication {
private void loge(String msg) {
Log.e(LOG_TAG, msg);
}
+
+ public void exchangeAPDU(int cla, int command, int channel, int p1, int p2,
+ int p3, String data, Message onComplete) {
+ mCi.iccExchangeAPDU(cla, command, channel, p1, p2, p3, data,
+ mHandler.obtainMessage(EVENT_EXCHANGE_APDU_DONE, onComplete));
+ }
+
+ public void openLogicalChannel(String AID, Message onComplete) {
+ mCi.iccOpenChannel(AID,
+ mHandler.obtainMessage(EVENT_OPEN_CHANNEL_DONE, onComplete));
+ }
+
+ public void closeLogicalChannel(int channel, Message onComplete) {
+ mCi.iccCloseChannel(channel,
+ mHandler.obtainMessage(EVENT_CLOSE_CHANNEL_DONE, onComplete));
+ }
+
+ public void exchangeSimIO(int fileID, int command,
+ int p1, int p2, int p3, String pathID, Message onComplete) {
+ mCi.iccIO(command,fileID,pathID,p1,p2,p3,null,null,
+ mHandler.obtainMessage(EVENT_SIM_IO_DONE, onComplete));
+ }
}
diff --git a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
index af12985..2c5be7d 100644
--- a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -422,5 +422,15 @@ class SipCommandInterface extends BaseCommands implements CommandsInterface {
public void getVoiceRadioTechnology(Message result) {
}
+ public void iccExchangeAPDU(int cla, int command, int channel, int p1,
+ int p2, int p3, String data, Message response) {
+ }
+
+ public void iccOpenChannel(String AID, Message response) {
+ }
+
+ public void iccCloseChannel(int channel, Message response) {
+ }
+
public boolean needsOldRilFeature(String feature) { return false; }
}
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
index 4903616..5c10d4a 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -1523,5 +1523,18 @@ public final class SimulatedCommands extends BaseCommands
unimplemented(response);
}
+ public void iccExchangeAPDU (int cla, int command, int channel, int p1,
+ int p2, int p3, String data, Message response) {
+ unimplemented(response);
+ }
+
+ public void iccOpenChannel(String AID, Message response) {
+ unimplemented(response);
+ }
+
+ public void iccCloseChannel(int channel, Message response) {
+ unimplemented(response);
+ }
+
public boolean needsOldRilFeature(String feature) { return false; }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
index ea6836d..d180712 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
@@ -621,4 +621,17 @@ class UsimDataDownloadCommands extends BaseCommands {
public void iccIOForApp(int command, int fileid, String path, int p1, int p2, int p3,
String data, String pin2, String aid, Message response) {
}
+
+ @Override
+ public void iccExchangeAPDU (int cla, int command, int channel, int p1,
+ int p2, int p3, String data, Message response) {
+ }
+
+ @Override
+ public void iccOpenChannel(String AID, Message response) {
+ }
+
+ @Override
+ public void iccCloseChannel(int channel, Message response) {
+ }
}
project hardware/ril/
diff --git a/include/telephony/ril.h b/include/telephony/ril.h
index 5e6d6c1..8e7609d 100644
--- a/include/telephony/ril.h
+++ b/include/telephony/ril.h
@@ -59,8 +59,12 @@ typedef enum {
location */
RIL_E_MODE_NOT_SUPPORTED = 13, /* HW does not support preferred network type */
RIL_E_FDN_CHECK_FAILURE = 14, /* command failed because recipient is not on FDN list */
- RIL_E_ILLEGAL_SIM_OR_ME = 15 /* network selection failed due to
+ RIL_E_ILLEGAL_SIM_OR_ME = 15, /* network selection failed due to
illegal SIM or ME */
+ RIL_E_MISSING_RESOURCE = 16,
+ RIL_E_NO_SUCH_ELEMENT = 17,
+ RIL_E_INVALID_PARAMETER = 18
+
} RIL_Errno;
typedef enum {
@@ -273,6 +277,7 @@ typedef struct {
} RIL_Dial;
typedef struct {
+ int cla;
int command; /* one of the commands listed for TS 27.007 +CRSM*/
int fileid; /* EF id */
char *path; /* "pathid" from TS 27.007 +CRSM command.
@@ -287,6 +292,7 @@ typedef struct {
} RIL_SIM_IO_v5;
typedef struct {
+ int cla;
int command; /* one of the commands listed for TS 27.007 +CRSM*/
int fileid; /* EF id */
char *path; /* "pathid" from TS 27.007 +CRSM command.
@@ -3320,6 +3326,22 @@ typedef struct {
#define RIL_REQUEST_VOICE_RADIO_TECH 108
+// "data" is a const RIL_SIM_IO *
+// "response" is a const RIL_SIM_IO_Response *
+#define RIL_REQUEST_SIM_TRANSMIT_BASIC 109
+
+// "data" is a const char * containing the AID of the applet
+// "response" is a int * containing the channel id
+#define RIL_REQUEST_SIM_OPEN_CHANNEL 110
+
+// "data" is a const int * containing the channel id
+// "response" is NULL
+#define RIL_REQUEST_SIM_CLOSE_CHANNEL 111
+
+// "data" is a const RIL_SIM_IO *
+// "response" is a const RIL_SIM_IO_Response *
+#define RIL_REQUEST_SIM_TRANSMIT_CHANNEL 112
+
/***********************************************************************/
diff --git a/libril/ril.cpp b/libril/ril.cpp
index f384148..8fbbb14 100644
--- a/libril/ril.cpp
+++ b/libril/ril.cpp
@@ -691,6 +693,7 @@ invalid:
/**
* Callee expects const RIL_SIM_IO *
* Payload is:
+ * int32_t cla
* int32_t command
* int32_t fileid
* String path
@@ -714,6 +717,12 @@ dispatchSIM_IO (Parcel &p, RequestInfo *pRI) {
// note we only check status at the end
+ simIO.v6.cla = 0;
+ if(pRI->pCI->requestNumber != RIL_REQUEST_SIM_IO) {
+ status = p.readInt32(&t);
+ simIO.v6.cla = (int)t;
+ }
+
status = p.readInt32(&t);
simIO.v6.command = (int)t;
@@ -740,6 +749,7 @@ dispatchSIM_IO (Parcel &p, RequestInfo *pRI) {
simIO.v6.command, simIO.v6.fileid, (char*)simIO.v6.path,
simIO.v6.p1, simIO.v6.p2, simIO.v6.p3,
(char*)simIO.v6.data, (char*)simIO.v6.pin2, simIO.v6.aidPtr);
+
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
@@ -3401,6 +3411,10 @@ requestToString(int request) {
case RIL_REQUEST_SEND_SMS_EXPECT_MORE: return "SEND_SMS_EXPECT_MORE";
case RIL_REQUEST_SETUP_DATA_CALL: return "SETUP_DATA_CALL";
case RIL_REQUEST_SIM_IO: return "SIM_IO";
+ case RIL_REQUEST_SIM_TRANSMIT_BASIC: return "SIM_TRANSMIT_BASIC";
+ case RIL_REQUEST_SIM_OPEN_CHANNEL: return "SIM_OPEN_CHANNEL";
+ case RIL_REQUEST_SIM_CLOSE_CHANNEL: return "SIM_CLOSE_CHANNEL";
+ case RIL_REQUEST_SIM_TRANSMIT_CHANNEL: return "SIM_TRANSMIT_CHANNEL";
case RIL_REQUEST_SEND_USSD: return "SEND_USSD";
case RIL_REQUEST_CANCEL_USSD: return "CANCEL_USSD";
case RIL_REQUEST_GET_CLIR: return "GET_CLIR";
diff --git a/libril/ril_commands.h b/libril/ril_commands.h
index 96f06ba..1d2b864 100644
--- a/libril/ril_commands.h
+++ b/libril/ril_commands.h
@@ -123,3 +123,7 @@
{RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU, dispatchStrings, responseVoid},
{RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, dispatchString, responseSIM_IO},
{RIL_REQUEST_VOICE_RADIO_TECH, dispatchVoiceRadioTech, responseInts},
+ {RIL_REQUEST_SIM_TRANSMIT_BASIC, dispatchSIM_IO, responseSIM_IO},
+ {RIL_REQUEST_SIM_OPEN_CHANNEL, dispatchString, responseInts},
+ {RIL_REQUEST_SIM_CLOSE_CHANNEL, dispatchInts, responseVoid},
+ {RIL_REQUEST_SIM_TRANSMIT_CHANNEL, dispatchSIM_IO, responseSIM_IO},
diff --git a/reference-ril/reference-ril.c b/reference-ril/reference-ril.c
index 2b991b1..ad20aa5 100644
--- a/reference-ril/reference-ril.c
+++ b/reference-ril/reference-ril.c
@@ -588,6 +588,9 @@ static void requestQueryNetworkSelectionMode(
ATResponse *p_response = NULL;
int response = 0;
char *line;
+ RIL_SIM_IO_Response sr;
+ char *cmd = NULL;
+ int len;
err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
@@ -831,6 +834,9 @@ static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
int count =0;
int numofElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
int response[numofElements];
+ RIL_SIM_IO_Response sr;
+ char *cmd = NULL;
+ int len;
err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
@@ -851,6 +857,57 @@ static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
+sim_status:
+ err = at_send_command_singleline("AT+CSIM=10,\"a0f2000002\"", "+CSIM:",
+ &p_response);
+
+ if (err < 0 || p_response->success == 0) {
+ goto sim_error;
+ }
+
+ line = p_response->p_intermediates->line;
+
+ err = at_tok_start(&line);
+ if (err < 0) goto sim_error;
+
+ err = at_tok_nextint(&line, &len);
+ if (err < 0) goto sim_error;
+
+ err = at_tok_nextstr(&line, &(sr.simResponse));
+ if (err < 0) goto sim_error;
+
+ sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
+ sr.simResponse[len - 4] = '\0';
+
+ if(sr.sw1 != 0x91)
+ goto sim_error;
+
+sim_fetch:
+ asprintf(&cmd, "AT+CSIM=10,\"a0120000%02x\"", sr.sw2);
+ err = at_send_command_singleline(cmd, "+CSIM:", &p_response);
+
+ if (err < 0 || p_response->success == 0) {
+ goto sim_error;
+ }
+
+ line = p_response->p_intermediates->line;
+
+ err = at_tok_start(&line);
+ if (err < 0) goto sim_error;
+
+ err = at_tok_nextint(&line, &len);
+ if (err < 0) goto sim_error;
+
+ err = at_tok_nextstr(&line, &(sr.simResponse));
+ if (err < 0) goto sim_error;
+
+ sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
+ sr.simResponse[len - 4] = '\0';
+
+ RIL_onUnsolicitedResponse(RIL_UNSOL_STK_PROACTIVE_COMMAND, sr.simResponse,
+ strlen(sr.simResponse));
+sim_error:
+ if (cmd != NULL) free(cmd);
at_response_free(p_response);
return;
@@ -1687,6 +1744,7 @@ static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
char *cmd = NULL;
RIL_SIM_IO_v6 *p_args;
char *line;
+ int len;
memset(&sr, 0, sizeof(sr));
@@ -1695,13 +1753,26 @@ static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
/* FIXME handle pin2 */
if (p_args->data == NULL) {
- asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
- p_args->command, p_args->fileid,
- p_args->p1, p_args->p2, p_args->p3);
+ if( p_args->path == NULL ) {
+ asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
+ p_args->command, p_args->fileid,
+ p_args->p1, p_args->p2, p_args->p3);
+ } else {
+ asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,,%s",
+ p_args->command, p_args->fileid,
+ p_args->p1, p_args->p2, p_args->p3,p_args->path);
+ }
} else {
- asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
- p_args->command, p_args->fileid,
- p_args->p1, p_args->p2, p_args->p3, p_args->data);
+ if( p_args->path == NULL ) {
+ asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
+ p_args->command, p_args->fileid,
+ p_args->p1, p_args->p2, p_args->p3, p_args->data);
+ } else {
+ asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s,%s",
+ p_args->command, p_args->fileid,
+ p_args->p1, p_args->p2, p_args->p3,p_args->data,p_args->path);
+ }
+
}
err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
@@ -1730,12 +1801,302 @@ static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
at_response_free(p_response);
free(cmd);
+ // return if no sim toolkit proactive command is ready
+ if(sr.sw1 != 0x91)
+ return;
+
+fetch:
+ asprintf(&cmd, "AT+CSIM=10,\"a0120000%02x\"", sr.sw2);
+ err = at_send_command_singleline(cmd, "+CSIM:", &p_response);
+
+ if (err < 0 || p_response->success == 0) {
+ goto fetch_error;
+ }
+
+ line = p_response->p_intermediates->line;
+
+ err = at_tok_start(&line);
+ if (err < 0) goto fetch_error;
+
+ err = at_tok_nextint(&line, &len);
+ if (err < 0) goto fetch_error;
+
+ err = at_tok_nextstr(&line, &(sr.simResponse));
+ if (err < 0) goto fetch_error;
+
+ sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
+ sr.simResponse[len - 4] = '\0';
+
+ RIL_onUnsolicitedResponse(RIL_UNSOL_STK_PROACTIVE_COMMAND, sr.simResponse, strlen(sr.simResponse));
+
+ goto fetch_error;
+
+error:
+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+fetch_error:
+ at_response_free(p_response);
+ free(cmd);
+
+}
+
+static void requestSIM_OpenChannel(void *data, size_t datalen, RIL_Token t)
+{
+ ATResponse *p_response = NULL;
+ int err;
+ char *cmd = NULL;
+ char *line;
+ int channel;
+
+ asprintf(&cmd, "AT+CCHO=\"%s\"", (char *)data);
+ err = at_send_command_singleline(cmd, "+CCHO:", &p_response);
+
+ if (err < 0 || p_response->success == 0) {
+ err = RIL_E_GENERIC_FAILURE;
+ if (!strcmp(p_response->finalResponse,
+ "+CME ERROR: MEMORY FULL"))
+ err = RIL_E_MISSING_RESOURCE;
+ if (!strcmp(p_response->finalResponse,
+ "+CME ERROR: NOT FOUND"))
+ err = RIL_E_NO_SUCH_ELEMENT;
+ goto error;
+ }
+
+ line = p_response->p_intermediates->line;
+
+ err = RIL_E_GENERIC_FAILURE;
+ if (at_tok_start(&line) < 0) goto error;
+ if (at_tok_nextint(&line, &channel) < 0) goto error;
+
+ RIL_onRequestComplete(t, RIL_E_SUCCESS, &channel, sizeof(int));
+ at_response_free(p_response);
+ free(cmd);
+
+ return;
+error:
+ RIL_onRequestComplete(t, err, NULL, 0);
+ at_response_free(p_response);
+ free(cmd);
+}
+
+static void requestSIM_CloseChannel(void *data, size_t datalen, RIL_Token t)
+{
+ ATResponse *p_response = NULL;
+ int err;
+ char *cmd = NULL;
+ char *line;
+ int channel;
+
+ asprintf(&cmd, "AT+CCHC=%d", *(int *)data);
+ err = at_send_command(cmd, &p_response);
+
+ if (err < 0 || p_response->success == 0) {
+ err = RIL_E_GENERIC_FAILURE;
+ if (!strcmp(p_response->finalResponse,
+ "+CME ERROR: INCORRECT PARAMETERS"))
+ err = RIL_E_INVALID_PARAMETER;
+ goto error;
+ }
+
+ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ at_response_free(p_response);
+ free(cmd);
+
return;
error:
+ RIL_onRequestComplete(t, err, NULL, 0);
+ at_response_free(p_response);
+ free(cmd);
+}
+
+static void requestSIM_TransmitBasic(void *data, size_t datalen, RIL_Token t)
+{
+ ATResponse *p_response = NULL;
+ RIL_SIM_IO_Response sr;
+ int err;
+ char *cmd = NULL;
+ RIL_SIM_IO_v6 *p_args;
+ char *line;
+ int len;
+
+ memset(&sr, 0, sizeof(sr));
+
+ p_args = (RIL_SIM_IO_v6 *)data;
+
+ if ((p_args->data == NULL) || (strlen(p_args->data) == 0)) {
+ if (p_args->p3 < 0) {
+ asprintf(&cmd, "AT+CSIM=%d,\"%02x%02x%02x%02x\"",
+ 8, p_args->cla, p_args->command,
+ p_args->p1, p_args->p2);
+ } else {
+ asprintf(&cmd, "AT+CSIM=%d,\"%02x%02x%02x%02x%02x\"",
+ 10, p_args->cla, p_args->command,
+ p_args->p1, p_args->p2, p_args->p3);
+ }
+ } else {
+ asprintf(&cmd, "AT+CSIM=%d,\"%02x%02x%02x%02x%02x%s\"",
+ 10 + strlen(p_args->data), p_args->cla, p_args->command,
+ p_args->p1, p_args->p2, p_args->p3,
+ p_args->data);
+ }
+ err = at_send_command_singleline(cmd, "+CSIM:", &p_response);
+
+ if (err < 0 || p_response->success == 0) {
+ goto error;
+ }
+
+ line = p_response->p_intermediates->line;
+
+ err = at_tok_start(&line);
+ if (err < 0) goto error;
+
+ err = at_tok_nextint(&line, &len);
+ if (err < 0) goto error;
+
+ err = at_tok_nextstr(&line, &(sr.simResponse));
+ if (err < 0) goto error;
+
+ sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
+ sr.simResponse[len - 4] = '\0';
+
+ RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
+ at_response_free(p_response);
+ free(cmd);
+
+ // end sim toolkit session if 90 00 on TERMINAL RESPONSE
+ if((p_args->command == 20) && (sr.sw1 == 0x90))
+ RIL_onUnsolicitedResponse(RIL_UNSOL_STK_SESSION_END, NULL, 0);
+
+ // return if no sim toolkit proactive command is ready
+ if(sr.sw1 != 0x91)
+ return;
+
+fetch:
+ asprintf(&cmd, "AT+CSIM=10,\"a0120000%02x\"", sr.sw2);
+ err = at_send_command_singleline(cmd, "+CSIM:", &p_response);
+
+ if (err < 0 || p_response->success == 0) {
+ goto fetch_error;
+ }
+
+ line = p_response->p_intermediates->line;
+
+ err = at_tok_start(&line);
+ if (err < 0) goto fetch_error;
+
+ err = at_tok_nextint(&line, &len);
+ if (err < 0) goto fetch_error;
+
+ err = at_tok_nextstr(&line, &(sr.simResponse));
+ if (err < 0) goto fetch_error;
+
+ sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
+ sr.simResponse[len - 4] = '\0';
+
+ RIL_onUnsolicitedResponse(RIL_UNSOL_STK_PROACTIVE_COMMAND, sr.simResponse, strlen(sr.simResponse));
+
+ goto fetch_error;
+error:
RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+fetch_error:
at_response_free(p_response);
free(cmd);
+}
+
+static void requestSIM_TransmitChannel(void *data, size_t datalen, RIL_Token t)
+{
+ ATResponse *p_response = NULL;
+ RIL_SIM_IO_Response sr;
+ int err;
+ char *cmd = NULL;
+ RIL_SIM_IO_v6 *p_args;
+ char *line;
+ int len;
+
+ memset(&sr, 0, sizeof(sr));
+
+ p_args = (RIL_SIM_IO_v6 *)data;
+
+ if ((p_args->data == NULL) || (strlen(p_args->data) == 0)) {
+ if (p_args->p3 < 0) {
+ asprintf(&cmd, "AT+CGLA=%d,%d,\"%02x%02x%02x%02x\"",
+ p_args->fileid,
+ 8, p_args->cla, p_args->command,
+ p_args->p1, p_args->p2);
+ } else {
+ asprintf(&cmd, "AT+CGLA=%d,%d,\"%02x%02x%02x%02x%02x\"",
+ p_args->fileid,
+ 10, p_args->cla, p_args->command,
+ p_args->p1, p_args->p2, p_args->p3);
+ }
+ } else {
+ asprintf(&cmd, "AT+CGLA=%d,%d,\"%02x%02x%02x%02x%02x%s\"",
+ p_args->fileid,
+ 10 + strlen(p_args->data), p_args->cla, p_args->command,
+ p_args->p1, p_args->p2, p_args->p3,
+ p_args->data);
+ }
+ err = at_send_command_singleline(cmd, "+CGLA:", &p_response);
+ if (err < 0 || p_response->success == 0) {
+ err = RIL_E_GENERIC_FAILURE;
+ if (!strcmp(p_response->finalResponse,
+ "+CME ERROR: INCORRECT PARAMETERS"))
+ err = RIL_E_INVALID_PARAMETER;
+ goto error;
+ }
+
+ line = p_response->p_intermediates->line;
+
+ err = RIL_E_GENERIC_FAILURE;
+ if (at_tok_start(&line) < 0) goto error;
+ if (at_tok_nextint(&line, &len) < 0) goto error;
+ if (at_tok_nextstr(&line, &(sr.simResponse)) < 0) goto error;
+
+ sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
+ sr.simResponse[len - 4] = '\0';
+
+ RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
+ at_response_free(p_response);
+ free(cmd);
+
+ // end sim toolkit session if 90 00 on TERMINAL RESPONSE
+ if((p_args->command == 20) && (sr.sw1 == 0x90))
+ RIL_onUnsolicitedResponse(RIL_UNSOL_STK_SESSION_END, NULL, 0);
+
+ // return if no sim toolkit proactive command is ready
+ if(sr.sw1 != 0x91)
+ return;
+
+fetch:
+ asprintf(&cmd, "AT+CSIM=10,\"a0120000%02x\"", sr.sw2);
+ err = at_send_command_singleline(cmd, "+CSIM:", &p_response);
+
+ if (err < 0 || p_response->success == 0) {
+ goto fetch_error;
+ }
+
+ line = p_response->p_intermediates->line;
+
+ err = at_tok_start(&line);
+ if (err < 0) goto fetch_error;
+
+ err = at_tok_nextint(&line, &len);
+ if (err < 0) goto fetch_error;
+
+ err = at_tok_nextstr(&line, &(sr.simResponse));
+ if (err < 0) goto fetch_error;
+
+ sscanf(&(sr.simResponse[len - 4]), "%02x%02x", &(sr.sw1), &(sr.sw2));
+ sr.simResponse[len - 4] = '\0';
+
+ RIL_onUnsolicitedResponse(RIL_UNSOL_STK_PROACTIVE_COMMAND, sr.simResponse, strlen(sr.simResponse));
+
+ goto fetch_error;
+error:
+ RIL_onRequestComplete(t, err, NULL, 0);
+fetch_error:
+ at_response_free(p_response);
+ free(cmd);
}
static void requestEnterSimPin(void* data, size_t datalen, RIL_Token t)
@@ -2030,10 +2391,62 @@ onRequest (int request, void *data, size_t datalen, RIL_Token t)
at_response_free(p_response);
break;
+ case RIL_REQUEST_STK_SET_PROFILE:
+ case RIL_REQUEST_STK_GET_PROFILE:
+ case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM:
+ RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
+ break;
+
+ case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND:
+ {
+ RIL_SIM_IO_v6 apdu;
+
+ apdu.cla = 0xa0;
+ apdu.command = 194;
+ apdu.p1 = 0;
+ apdu.p2 = 0;
+ apdu.p3 = strlen(data) >> 1;
+ apdu.data = data;
+
+ requestSIM_TransmitBasic(&apdu, 0, t);
+ }
+ break;
+
+ case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE:
+ {
+ RIL_SIM_IO_v6 apdu;
+
+ apdu.cla = 0xa0;
+ apdu.command = 20;
+ apdu.p1 = 0;
+ apdu.p2 = 0;
+ apdu.p3 = strlen(data) >> 1;
+ apdu.data = data;
+
+ requestSIM_TransmitBasic(&apdu, 0, t);
+ }
+ break;
+
case RIL_REQUEST_SIM_IO:
requestSIM_IO(data,datalen,t);
break;
+ case RIL_REQUEST_SIM_TRANSMIT_BASIC:
+ requestSIM_TransmitBasic(data, datalen, t);
+ break;
+
+ case RIL_REQUEST_SIM_OPEN_CHANNEL:
+ requestSIM_OpenChannel(data, datalen, t);
+ break;
+
+ case RIL_REQUEST_SIM_CLOSE_CHANNEL:
+ requestSIM_CloseChannel(data, datalen, t);
+ break;
+
+ case RIL_REQUEST_SIM_TRANSMIT_CHANNEL:
+ requestSIM_TransmitChannel(data, datalen, t);
+ break;
+
case RIL_REQUEST_SEND_USSD:
requestSendUSSD(data, datalen, t);
break;
project kernel/samsung/smdk4412/
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 6395019..bff1d29 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -3,7 +3,7 @@
#
obj-$(CONFIG_MMC) += mmc_core.o
-mmc_core-y := core.o bus.o host.o \
+mmc_core-y := core.o bus.o host.o assd.o \
mmc.o mmc_ops.o sd.o sd_ops.o \
sdio.o sdio_ops.o sdio_bus.o \
sdio_cis.o sdio_io.o sdio_irq.o \
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index eb7a4c8..3e18810 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -25,6 +25,8 @@
#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
+static struct mmc_driver *assd_drv;
+
static ssize_t mmc_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -107,7 +109,14 @@ static int mmc_bus_probe(struct device *dev)
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
- return drv->probe(card);
+ int ret = 0;
+
+ ret = drv->probe(card);
+
+ if (assd_drv != NULL)
+ assd_drv->probe(card);
+
+ return ret;
}
static int mmc_bus_remove(struct device *dev)
@@ -115,6 +124,13 @@ static int mmc_bus_remove(struct device *dev)
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
+ /*
+ * inform the assd module about the removal of a card.
+ * but only if the assd module is loaded.
+ */
+ if (assd_drv != NULL)
+ assd_drv->remove(card);
+
drv->remove(card);
return 0;
@@ -127,6 +143,9 @@ static int mmc_bus_pm_suspend(struct device *dev)
int ret = 0;
pm_message_t state = { PM_EVENT_SUSPEND };
+ if (assd_drv != NULL)
+ assd_drv->suspend(card,state);
+
if (dev->driver && drv->suspend)
ret = drv->suspend(card, state);
return ret;
@@ -140,6 +159,10 @@ static int mmc_bus_pm_resume(struct device *dev)
if (dev->driver && drv->resume)
ret = drv->resume(card);
+
+ if (assd_drv != NULL)
+ assd_drv->resume(card);
+
return ret;
}
@@ -195,6 +218,15 @@ void mmc_unregister_bus(void)
*/
int mmc_register_driver(struct mmc_driver *drv)
{
+ /*
+ * keep track whether or not the assd module is loaded.
+ */
+ if (!strcmp(drv->drv.name, "sd_assd")) {
+
+ assd_drv = drv;
+ return 0;
+ }
+
drv->drv.bus = &mmc_bus_type;
return driver_register(&drv->drv);
}
@@ -207,6 +239,15 @@ EXPORT_SYMBOL(mmc_register_driver);
*/
void mmc_unregister_driver(struct mmc_driver *drv)
{
+ /*
+ * keep track whether or not the assd module is loaded.
+ */
+ if (!strcmp(drv->drv.name, "sd_assd")) {
+
+ assd_drv = NULL;
+ return;
+ }
+
drv->drv.bus = &mmc_bus_type;
driver_unregister(&drv->drv);
}
project packages/apps/LegacyCamera/
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 7f0ca0a..75ebe3b 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -150,9 +150,9 @@
XGA
SVGA
WVGA
- VGA
+
CIF
- QVGA
+
QCIF
project packages/apps/Phone/
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 3ffed5d..6bbd526 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -17,12 +17,14 @@
package com.android.phone;
import android.app.ActivityManager;
+import android.app.IInstrumentationWatcher;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.AsyncResult;
+import android.os.Process;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -43,10 +45,18 @@ import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.CallManager;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.IccIoResult;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.CommandException;
+import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
/**
* Implementation of the ITelephony interface.
*/
@@ -62,7 +72,15 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
private static final int CMD_ANSWER_RINGING_CALL = 4;
private static final int CMD_END_CALL = 5; // not used yet
private static final int CMD_SILENCE_RINGER = 6;
- private static final int CMD_TOGGLE_LTE = 7; // not used yet
+ private static final int CMD_TOGGLE_LTE = 15; // not used yet
+ private static final int CMD_EXCHANGE_APDU = 7;
+ private static final int EVENT_EXCHANGE_APDU_DONE = 8;
+ private static final int CMD_OPEN_CHANNEL = 9;
+ private static final int EVENT_OPEN_CHANNEL_DONE = 10;
+ private static final int CMD_CLOSE_CHANNEL = 11;
+ private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
+ private static final int CMD_SIM_IO = 13;
+ private static final int EVENT_SIM_IO_DONE = 14;
/** The singleton instance. */
private static PhoneInterfaceManager sInstance;
@@ -72,6 +90,28 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
CallManager mCM;
MainThreadHandler mMainThreadHandler;
+ private int lastError;
+
+ //mh 052013 add response byte for open channel
+ private byte[] mOpenResponseBytes;
+
+ private static final class IccAPDUArgument {
+
+ public int channel, cla, command, p1, p2, p3;
+ public String data;
+
+ public IccAPDUArgument(int cla, int command, int channel,
+ int p1, int p2, int p3, String data) {
+ this.channel = channel;
+ this.cla = cla;
+ this.command = command;
+ this.p1 = p1;
+ this.p2 = p2;
+ this.p3 = p3;
+ this.data = data;
+ }
+ }
+
/**
* A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
* request after sending. The main thread will notify the request when it is complete.
@@ -86,7 +126,7 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
this.argument = argument;
}
}
-
+
/**
* A handler that processes messages on the main thread in the phone process. Since many
* of the Phone calls are not thread safe this is needed to shuttle the requests from the
@@ -169,6 +211,187 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
}
break;
+ case CMD_EXCHANGE_APDU:
+ request = (MainThreadRequest) msg.obj;
+ IccAPDUArgument argument =
+ (IccAPDUArgument) request.argument;
+ onCompleted = obtainMessage(EVENT_EXCHANGE_APDU_DONE,
+ request);
+ mPhone.getIccCard().exchangeAPDU(argument.cla,
+ argument.command,
+ argument.channel, argument.p1, argument.p2,
+ argument.p3, argument.data, onCompleted);
+ break;
+
+ case EVENT_EXCHANGE_APDU_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null && ar.result != null) {
+ request.result = new IccIoResult(0x6f, 0, (byte[])null);
+
+ if (ar.result != null && ar.result instanceof byte[]) {
+ Log.d(LOG_TAG, " received response byte array : " + IccUtils.bytesToHexString((byte[])ar.result));
+
+ byte[] resultBytes = (byte[])ar.result;
+ if (resultBytes.length >= 2) {
+ request.result = new IccIoResult(
+ resultBytes[resultBytes.length - 2] & 0x0ff,
+ resultBytes[resultBytes.length - 1] & 0x0ff,
+ Arrays.copyOf(resultBytes, resultBytes.length - 2));
+ }
+ }
+ lastError = 0;
+ } else {
+ request.result = new IccIoResult(0x6f, 0,
+ (byte[])null);
+ lastError = 1;
+ if ((ar.exception != null) &&
+ (ar.exception instanceof CommandException)) {
+ if (((CommandException)ar.exception)
+ .getCommandError() ==
+ CommandException.Error.INVALID_PARAMETER) {
+ lastError = 5;
+ }
+ }
+ }
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
+ case CMD_OPEN_CHANNEL:
+ Log.d(LOG_TAG, " start opening channel");
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE,
+ request);
+
+ Log.d(LOG_TAG, " Current Phone object: " + mPhone);
+ Log.d(LOG_TAG, " opening channel to card " + mPhone.getIccCard());
+
+ mPhone.getIccCard().openLogicalChannel(
+ (String)request.argument, onCompleted);
+
+ Log.d(LOG_TAG, " Card connection opened, now waiting for channel opening done");
+ break;
+
+ case EVENT_OPEN_CHANNEL_DONE:
+ Log.d(LOG_TAG, " channel open done");
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+
+ if (ar.result != null && ar.result instanceof byte[]) {
+ Log.d(LOG_TAG, " received response byte array : " + IccUtils.bytesToHexString((byte[])ar.result));
+ }
+
+ if (ar.exception == null && ar.result != null) {
+
+ //mh 052013 removed cast to integer
+ request.result = ar.result;
+ lastError = 0;
+ } else {
+ request.result = new byte[0];
+ lastError = 1;
+ //mh remove afterwards
+ if(ar.exception != null){
+ Log.d(LOG_TAG, " channel open exception ", ar.exception);
+ }else{
+ Log.d(LOG_TAG, " channel open exception is null");
+ }
+ Log.d(LOG_TAG, " asyncResult for open channel is " +ar.result );
+
+
+ if ((ar.exception != null) &&
+ (ar.exception instanceof CommandException)) {
+ if (((CommandException)ar.exception)
+ .getCommandError() ==
+ CommandException.Error.MISSING_RESOURCE) {
+ lastError = 2;
+ } else {
+ if (((CommandException)ar.exception)
+ .getCommandError() ==
+ CommandException.Error.NO_SUCH_ELEMENT) {
+ lastError = 3;
+ }
+ }
+ }
+ }
+ Log.d(LOG_TAG, " channel open and notify old thread");
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
+ case CMD_CLOSE_CHANNEL:
+ Log.d(LOG_TAG, " close channel");
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE,
+ request);
+ mPhone.getIccCard().closeLogicalChannel(
+ ((Integer)request.argument).intValue(),
+ onCompleted);
+ break;
+
+ case EVENT_CLOSE_CHANNEL_DONE:
+ Log.d(LOG_TAG, " close channel done");
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+
+ if (ar.result != null && ar.result instanceof byte[]) {
+ Log.d(LOG_TAG, " received response byte array : " + IccUtils.bytesToHexString((byte[])ar.result));
+ }
+
+ if (ar.exception == null) {
+ request.result = new Integer(0);
+ lastError = 0;
+ } else {
+ request.result = new Integer(-1);
+ lastError = 1;
+ if ((ar.exception != null) &&
+ (ar.exception instanceof CommandException)) {
+ if (((CommandException)ar.exception)
+ .getCommandError() ==
+ CommandException.Error.INVALID_PARAMETER) {
+ lastError = 5;
+ }
+ }
+ }
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
+ case CMD_SIM_IO:
+ Log.d(LOG_TAG, " SIM IO");
+ request = (MainThreadRequest) msg.obj;
+ IccAPDUArgument parameters =
+ (IccAPDUArgument) request.argument;
+ onCompleted = obtainMessage(EVENT_SIM_IO_DONE,request);
+ mPhone.getIccCard().exchangeSimIO( parameters.cla, /* fileID */
+ parameters.command,
+ parameters.p1, parameters.p2, parameters.p3,
+ parameters.data, onCompleted);
+ break;
+
+ case EVENT_SIM_IO_DONE:
+ Log.d(LOG_TAG, " SIM IO done");
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null && ar.result != null) {
+ request.result = ar.result;
+ lastError = 0;
+ } else {
+ request.result = new IccIoResult(0x6f, 0, (byte[])null);
+ lastError = 1;
+ if ((ar.exception != null) &&
+ (ar.exception instanceof CommandException)) {
+ if (((CommandException)ar.exception).getCommandError() ==
+ CommandException.Error.INVALID_PARAMETER) {
+ lastError = 5;
+ }}}
+ synchronized (request) { request.notifyAll(); }
+ break;
+
+
default:
Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
break;
@@ -186,17 +409,24 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
throw new RuntimeException("This method will deadlock if called from the main thread.");
}
+ Log.d(LOG_TAG, " start sending request");
MainThreadRequest request = new MainThreadRequest(argument);
Message msg = mMainThreadHandler.obtainMessage(command, request);
msg.sendToTarget();
+ Log.d(LOG_TAG, " Request sent, waiting for response");
// Wait for the request to complete
synchronized (request) {
+ Log.d(LOG_TAG, " successfully waited for the request "+request.result);
while (request.result == null) {
try {
+ Log.d(LOG_TAG, " now go to sleep");
request.wait();
+
+ Log.d(LOG_TAG, " request.result");
} catch (InterruptedException e) {
// Do nothing, go back and wait until the request is complete
+ Log.d(LOG_TAG, " interrupted, but still waiting");
}
}
}
@@ -871,4 +1101,111 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
public int getLteOnGsmMode() {
return mPhone.getLteOnGsmMode();
}
+
+ private String exchangeIccAPDU(int cla, int command,
+ int channel, int p1, int p2, int p3, String data) {
+ if (Binder.getCallingUid() != Process.SMARTCARD_UID)
+ throw new SecurityException("Only Smartcard API may access UICC");
+ Log.d(LOG_TAG, "> exchangeAPDU " + channel + " " + cla + " " +
+ command + " " + p1 + " " + p2 + " " + p3 + " " + data);
+ IccIoResult response =
+ (IccIoResult)sendRequest(CMD_EXCHANGE_APDU,
+ new IccAPDUArgument(cla, command, channel,
+ p1, p2, p3, data));
+ Log.d(LOG_TAG, "< exchangeAPDU " + response);
+ String s = Integer.toHexString(
+ (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
+ if (response.payload != null)
+ s = IccUtils.bytesToHexString(response.payload) + s;
+ return s;
+ }
+
+ public String transmitIccBasicChannel(int cla, int command,
+ int p1, int p2, int p3, String data) {
+ return exchangeIccAPDU(cla, command, 0, p1, p2, p3, data);
+ }
+
+ public String transmitIccLogicalChannel(int cla, int command,
+ int channel, int p1, int p2, int p3, String data) {
+ return exchangeIccAPDU(cla, command, channel, p1, p2, p3, data);
+ }
+
+ public int openIccLogicalChannel(String AID) {
+ if (Binder.getCallingUid() != Process.SMARTCARD_UID)
+ throw new SecurityException("Only Smartcard API may access UICC");
+
+ mOpenResponseBytes = null;
+
+ Log.d(LOG_TAG, "> openIccLogicalChannel " + AID);
+ Log.d(LOG_TAG, " sendRequestIcc");
+// mh 052013
+// Integer channel = (Integer)sendRequest(CMD_OPEN_CHANNEL, AID);
+
+ byte [] responseByteArray = (byte[])sendRequest(CMD_OPEN_CHANNEL, AID);
+ int channel = 0;
+
+ if(responseByteArray != null && responseByteArray.length > 0){
+ int channelLength = responseByteArray[0] & 0x0ff;
+ if (responseByteArray.length > channelLength) {
+ for (int i = channelLength; i > 0; --i) {
+ channel <<= 8;
+ channel |= responseByteArray[i] & 0x0ff;
+ }
+
+ if (responseByteArray.length > (channelLength + 1)) {
+ int responseLength = responseByteArray[channelLength + 1];
+
+ if (responseByteArray.length > (channelLength + 1 + responseLength)) {
+ mOpenResponseBytes = Arrays.copyOfRange(responseByteArray, channelLength + 1, channelLength + 1 + responseLength + 1);
+ }
+ }
+ }
+
+ Log.d(LOG_TAG, " received response byte array : " + IccUtils.bytesToHexString(responseByteArray));
+ }
+
+ Log.d(LOG_TAG, " Finished request");
+ Log.d(LOG_TAG, "< openIccLogicalChannel " + channel);
+ return channel;
+ }
+
+ public boolean closeIccLogicalChannel(int channel) {
+ if (Binder.getCallingUid() != Process.SMARTCARD_UID)
+ throw new SecurityException("Only Smartcard API may access UICC");
+ Log.d(LOG_TAG, "> closeIccLogicalChannel " + channel);
+ Integer err = (Integer)sendRequest(CMD_CLOSE_CHANNEL,
+ new Integer(channel));
+ Log.d(LOG_TAG, "< closeIccLogicalChannel " + err);
+ if(err.intValue() == 0)
+ return true;
+ return false;
+ }
+
+ public int getLastError() {
+ return lastError;
+ }
+
+ public byte[] transmitIccSimIO(int fileID, int command,
+ int p1, int p2, int p3, String filePath) {
+ if (Binder.getCallingUid() != Process.SMARTCARD_UID)
+ throw new SecurityException("Only Smartcard API may access UICC");
+ Log.d(LOG_TAG, "Exchange SIM_IO " + fileID + ":" + command + " " +
+ p1 + " " + p2 + " " + p3 + ":" + filePath);
+ IccIoResult response =
+ (IccIoResult)sendRequest(CMD_SIM_IO,
+ new IccAPDUArgument(fileID, command, -1,
+ p1, p2, p3, filePath));
+ Log.d(LOG_TAG, "Exchange SIM_IO [R]" + response);
+ byte[] result=null; int length=2;
+ if (response.payload != null) {
+ length=2+response.payload.length;
+ result=new byte[length];
+ System.arraycopy(response.payload,0,result,0,response.payload.length);
+ } else result=new byte[length];
+ Log.d(LOG_TAG,"Exchange SIM_IO [L] "+length);
+ result[length-1]=(byte)response.sw2;
+ result[length-2]=(byte)response.sw1;
+ return result;
+ }
+
}
project system/core/
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index a77f1d6..bb116d0 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -62,6 +62,7 @@
#define AID_DRMRPC 1026 /* group for drm rpc */
#define AID_NFC 1027 /* nfc subsystem */
#define AID_SDCARD_R 1028 /* external storage read access */
+#define AID_SMARTCARD 1029 /* smart card subsystem */
#define AID_SHELL 2000 /* adb and debug shell user */
#define AID_CACHE 2001 /* cache access */
@@ -147,7 +148,8 @@ static const struct android_id_info android_ids[] = {
{ "media_rw", AID_MEDIA_RW, },
{ "vpn", AID_VPN, },
{ "keystore", AID_KEYSTORE, },
- { "usb", AID_USB, },
+ { "smartcard", AID_SMARTCARD, },
+ { "usb", AID_USB, },
{ "mtp", AID_MTP, },
{ "gps", AID_GPS, },
{ "inet", AID_INET, },
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 8eec836..a1f9302 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -254,6 +254,9 @@ on post-fs-data
# Include extra init file
import /init.sn.rc
+ chmod 0660 /dev/assd
+ chown smartcard smartcard /dev/assd
+
on boot
# basic network init
ifup lo