diff options
Diffstat (limited to 'telephony/sim_card.c')
-rw-r--r-- | telephony/sim_card.c | 439 |
1 files changed, 0 insertions, 439 deletions
diff --git a/telephony/sim_card.c b/telephony/sim_card.c deleted file mode 100644 index a5a3249..0000000 --- a/telephony/sim_card.c +++ /dev/null @@ -1,439 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -*/ -#include "sim_card.h" -#include <string.h> -#include <assert.h> - -/* set ENABLE_DYNAMIC_RECORDS to 1 to enable dynamic records - * for now, this is an experimental feature that needs more testing - */ -#define ENABLE_DYNAMIC_RECORDS 0 - -#define A_SIM_PIN_SIZE 4 -#define A_SIM_PUK_SIZE 8 - -typedef struct ASimCardRec_ { - ASimStatus status; - char pin[ A_SIM_PIN_SIZE+1 ]; - char puk[ A_SIM_PUK_SIZE+1 ]; - int pin_retries; - - char out_buff[ 256 ]; - int out_size; - -} ASimCardRec; - -static ASimCardRec _s_card[1]; - -ASimCard -asimcard_create( void ) -{ - ASimCard card = _s_card; - card->status = A_SIM_STATUS_READY; - card->pin_retries = 0; - strncpy( card->pin, "0000", sizeof(card->pin) ); - strncpy( card->puk, "12345678", sizeof(card->puk) ); - return card; -} - -void -asimcard_destroy( ASimCard card ) -{ - /* nothing really */ - card=card; -} - -static __inline__ int -asimcard_ready( ASimCard card ) -{ - return card->status == A_SIM_STATUS_READY; -} - -ASimStatus -asimcard_get_status( ASimCard sim ) -{ - return sim->status; -} - -void -asimcard_set_status( ASimCard sim, ASimStatus status ) -{ - sim->status = status; -} - -const char* -asimcard_get_pin( ASimCard sim ) -{ - return sim->pin; -} - -const char* -asimcard_get_puk( ASimCard sim ) -{ - return sim->puk; -} - -void -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 ) -{ - strncpy( sim->puk, puk, A_SIM_PUK_SIZE ); - sim->pin_retries = 0; -} - - -int -asimcard_check_pin( ASimCard sim, const char* pin ) -{ - if (sim->status != A_SIM_STATUS_PIN && - sim->status != A_SIM_STATUS_READY ) - return 0; - - if ( !strcmp( sim->pin, pin ) ) { - 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; -} - - -int -asimcard_check_puk( ASimCard sim, const char* puk, const char* pin ) -{ - if (sim->status != A_SIM_STATUS_PUK) - return 0; - - if ( !strcmp( sim->puk, puk ) ) { - strncpy( sim->puk, puk, A_SIM_PUK_SIZE ); - strncpy( sim->pin, pin, A_SIM_PIN_SIZE ); - sim->status = A_SIM_STATUS_READY; - sim->pin_retries = 0; - return 1; - } - - if ( ++sim->pin_retries == 6 ) { - sim->status = A_SIM_STATUS_ABSENT; - } - return 0; -} - -typedef enum { - SIM_FILE_DM = 0, - SIM_FILE_DF, - SIM_FILE_EF_DEDICATED, - SIM_FILE_EF_LINEAR, - SIM_FILE_EF_CYCLIC -} SimFileType; - -typedef enum { - SIM_FILE_READ_ONLY = (1 << 0), - SIM_FILE_NEED_PIN = (1 << 1), -} SimFileFlags; - -/* descriptor for a known SIM File */ -#define SIM_FILE_HEAD \ - SimFileType type; \ - unsigned short id; \ - unsigned short flags; - -typedef struct { - SIM_FILE_HEAD -} SimFileAnyRec, *SimFileAny; - -typedef struct { - SIM_FILE_HEAD - cbytes_t data; - int length; -} SimFileEFDedicatedRec, *SimFileEFDedicated; - -typedef struct { - SIM_FILE_HEAD - byte_t rec_count; - byte_t rec_len; - cbytes_t records; -} SimFileEFLinearRec, *SimFileEFLinear; - -typedef SimFileEFLinearRec SimFileEFCyclicRec; -typedef SimFileEFCyclicRec* SimFileEFCyclic; - -typedef union { - SimFileAnyRec any; - SimFileEFDedicatedRec dedicated; - SimFileEFLinearRec linear; - SimFileEFCyclicRec cyclic; -} SimFileRec, *SimFile; - - -#if ENABLE_DYNAMIC_RECORDS -/* convert a SIM File descriptor into an ASCII string, - assumes 'dst' is NULL or properly sized. - return the number of chars, or -1 on error */ -static int -sim_file_to_hex( SimFile file, bytes_t dst ) -{ - SimFileType type = file->any.type; - int result = 0; - - /* see 9.2.1 in TS 51.011 */ - switch (type) { - case SIM_FILE_EF_DEDICATED: - case SIM_FILE_EF_LINEAR: - case SIM_FILE_EF_CYCLIC: - { - if (dst) { - int file_size, perm; - - memcpy(dst, "0000", 4); /* bytes 1-2 are RFU */ - dst += 4; - - /* bytes 3-4 are the file size */ - if (type == SIM_FILE_EF_DEDICATED) - file_size = file->dedicated.length; - else - file_size = file->linear.rec_count * file->linear.rec_len; - - gsm_hex_from_short( dst, file_size ); - dst += 4; - - /* bytes 5-6 are the file id */ - gsm_hex_from_short( dst, file->any.id ); - dst += 4; - - /* byte 7 is the file type - always EF, i.e. 0x04 */ - dst[0] = '0'; - dst[1] = '4'; - dst += 2; - - /* byte 8 is RFU, except bit 7 for cyclic files, which indicates - that INCREASE is allowed. Since we don't support this yet... */ - dst[0] = '0'; - dst[1] = '0'; - dst += 2; - - /* byte 9-11 are access conditions */ - if (file->any.flags & SIM_FILE_READ_ONLY) { - if (file->any.flags & SIM_FILE_NEED_PIN) - perm = 0x1a; - else - perm = 0x0a; - } else { - if (file->any.flags & SIM_FILE_NEED_PIN) - perm = 0x11; - else - perm = 0x00; - } - gsm_hex_from_byte(dst, perm); - memcpy( dst+2, "a0aa", 4 ); - dst += 6; - - /* byte 12 is file status, we don't support invalidation */ - dst[0] = '0'; - dst[1] = '0'; - dst += 2; - - /* byte 13 is length of the following data, always 2 */ - dst[0] = '0'; - dst[1] = '2'; - dst += 2; - - /* byte 14 is struct of EF */ - dst[0] = '0'; - if (type == SIM_FILE_EF_DEDICATED) - dst[1] = '0'; - else if (type == SIM_FILE_EF_LINEAR) - dst[1] = '1'; - else - dst[1] = '3'; - - /* byte 15 is lenght of record, or 0 */ - if (type == SIM_FILE_EF_DEDICATED) { - dst[0] = '0'; - dst[1] = '0'; - } else - gsm_hex_from_byte( dst, file->linear.rec_len ); - } - result = 30; - } - break; - - default: - result = -1; - } - return result; -} - - -static const byte_t _const_spn_cphs[20] = { - 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - -static const byte_t _const_voicemail_cphs[1] = { - 0x55 -}; - -static const byte_t _const_iccid[10] = { - 0x98, 0x10, 0x14, 0x30, 0x12, 0x11, 0x81, 0x15, 0x70, 0x02 -}; - -static const byte_t _const_cff_cphs[1] = { - 0x55 -}; - -static SimFileEFDedicatedRec _const_files_dedicated[] = -{ - { SIM_FILE_EF_DEDICATED, 0x6f14, SIM_FILE_READ_ONLY | SIM_FILE_NEED_PIN, - _const_spn_cphs, sizeof(_const_spn_cphs) }, - - { SIM_FILE_EF_DEDICATED, 0x6f11, SIM_FILE_NEED_PIN, - _const_voicemail_cphs, sizeof(_const_voicemail_cphs) }, - - { SIM_FILE_EF_DEDICATED, 0x2fe2, SIM_FILE_READ_ONLY, - _const_iccid, sizeof(_const_iccid) }, - - { SIM_FILE_EF_DEDICATED, 0x6f13, SIM_FILE_NEED_PIN, - _const_cff_cphs, sizeof(_const_cff_cphs) }, - - { 0, 0, 0, NULL, 0 } /* end of list */ -}; -#endif /* ENABLE_DYNAMIC_RECORDS */ - -const char* -asimcard_io( ASimCard sim, const char* cmd ) -{ - int nn; -#if ENABLE_DYNAMIC_RECORDS - int command, id, p1, p2, p3; -#endif - static const struct { const char* cmd; const char* answer; } answers[] = - { - { "+CRSM=192,28436,0,0,15", "+CRSM: 144,0,000000146f1404001aa0aa01020000" }, - { "+CRSM=176,28436,0,0,20", "+CRSM: 144,0,416e64726f6964ffffffffffffffffffffffffff" }, - - { "+CRSM=192,28433,0,0,15", "+CRSM: 144,0,000000016f11040011a0aa01020000" }, - { "+CRSM=176,28433,0,0,1", "+CRSM: 144,0,55" }, - - { "+CRSM=192,12258,0,0,15", "+CRSM: 144,0,0000000a2fe204000fa0aa01020000" }, - { "+CRSM=176,12258,0,0,10", "+CRSM: 144,0,98101430121181157002" }, - - { "+CRSM=192,28435,0,0,15", "+CRSM: 144,0,000000016f13040011a0aa01020000" }, - { "+CRSM=176,28435,0,0,1", "+CRSM: 144,0,55" }, - - { "+CRSM=192,28472,0,0,15", "+CRSM: 144,0,0000000f6f3804001aa0aa01020000" }, - { "+CRSM=176,28472,0,0,15", "+CRSM: 144,0,ff30ffff3c003c03000c0000f03f00" }, - - { "+CRSM=192,28617,0,0,15", "+CRSM: 144,0,000000086fc9040011a0aa01020104" }, - { "+CRSM=178,28617,1,4,4", "+CRSM: 144,0,01000000" }, - - { "+CRSM=192,28618,0,0,15", "+CRSM: 144,0,0000000a6fca040011a0aa01020105" }, - { "+CRSM=178,28618,1,4,5", "+CRSM: 144,0,0000000000" }, - - { "+CRSM=192,28589,0,0,15", "+CRSM: 144,0,000000046fad04000aa0aa01020000" }, - { "+CRSM=176,28589,0,0,4", "+CRSM: 144,0,00000003" }, - - { "+CRSM=192,28438,0,0,15", "+CRSM: 144,0,000000026f1604001aa0aa01020000" }, - { "+CRSM=176,28438,0,0,2", "+CRSM: 144,0,0233" }, - - { "+CRSM=192,28486,0,0,15", "+CRSM: 148,4" }, - { "+CRSM=192,28621,0,0,15", "+CRSM: 148,4" }, - - { "+CRSM=192,28613,0,0,15", "+CRSM: 144,0,000000f06fc504000aa0aa01020118" }, - { "+CRSM=178,28613,1,4,24", "+CRSM: 144,0,43058441aa890affffffffffffffffffffffffffffffffff" }, - - { "+CRSM=192,28480,0,0,15", "+CRSM: 144,0,000000806f40040011a0aa01020120" }, - { "+CRSM=178,28480,1,4,32", "+CRSM: 144,0,ffffffffffffffffffffffffffffffffffff07815155258131f5ffffffffffff" }, - - { "+CRSM=192,28615,0,0,15", "+CRSM: 144,0,000000406fc7040011a0aa01020120" }, - { "+CRSM=178,28615,1,4,32", "+CRSM: 144,0,566f6963656d61696cffffffffffffffffff07915155125740f9ffffffffffff" }, - - { NULL, NULL } - }; - - assert( memcmp( cmd, "+CRSM=", 6 ) == 0 ); - -#if ENABLE_DYNAMIC_RECORDS - if ( sscanf(cmd, "+CRSM=%d,%d,%d,%d,%d", &command, &id, &p1, &p2, &p3) == 5 ) { - switch (command) { - case A_SIM_CMD_GET_RESPONSE: - { - const SimFileEFDedicatedRec* file = _const_files_dedicated; - - assert(p1 == 0 && p2 == 0 && p3 == 15); - - for ( ; file->id != 0; file++ ) { - if (file->id == id) { - int count; - char* out = sim->out_buff; - strcpy( out, "+CRSM: 144,0," ); - out += strlen(out); - count = sim_file_to_hex( (SimFile) file, out ); - if (count < 0) - return "ERROR: INTERNAL SIM ERROR"; - out[count] = 0; - return sim->out_buff; - } - } - break; - } - - case A_SIM_CMD_READ_BINARY: - { - const SimFileEFDedicatedRec* file = _const_files_dedicated; - - assert(p1 == 0 && p2 == 0); - - for ( ; file->id != 0; file++ ) { - if (file->id == id) { - char* out = sim->out_buff; - - if (p3 > file->length) - return "ERROR: BINARY LENGTH IS TOO LONG"; - - strcpy( out, "+CRSM: 144,0," ); - out += strlen(out); - gsm_hex_from_bytes( out, file->data, p3 ); - out[p3*2] = 0; - return sim->out_buff; - } - } - break; - } - - case A_SIM_CMD_READ_RECORD: - break; - - default: - return "ERROR: UNSUPPORTED SIM COMMAND"; - } - } -#endif - - for (nn = 0; answers[nn].cmd != NULL; nn++) { - if ( !strcmp( answers[nn].cmd, cmd ) ) { - return answers[nn].answer; - } - } - return "ERROR: BAD COMMAND"; -} - |