From 2b715f504dac85451c71ca6d88d4b4b91b26d55a Mon Sep 17 00:00:00 2001 From: mweirauch Date: Sun, 1 May 2011 11:58:20 +0200 Subject: [PATCH] Revert "Merge commit 'refs/merge-requests/1' of git://gitorious.org/xdandroid/hardware_xdandroid-ril" This reverts commit a16cfbd3c3417755b896621c37bdb23013889b74, reversing changes made to c1a182b1dbd91bac47fdd2b8552339760a351aba. --- Android.mk | 54 - MODULE_LICENSE_APACHE2 | 0 NOTICE | 190 -- at_tok.c | 190 -- at_tok.h | 30 - atchannel.c | 1029 ----------- atchannel.h | 124 -- gsm.c | 1165 ------------ gsm.h | 177 -- htcgeneric-ril.c | 4759 ------------------------------------------------ misc.c | 29 - misc.h | 19 - sms.c | 276 --- sms_gsm.c | 1112 ----------- sms_gsm.h | 85 - 15 files changed, 9239 deletions(-) delete mode 100644 Android.mk delete mode 100644 MODULE_LICENSE_APACHE2 delete mode 100644 NOTICE delete mode 100644 at_tok.c delete mode 100644 at_tok.h delete mode 100644 atchannel.c delete mode 100644 atchannel.h delete mode 100644 gsm.c delete mode 100644 gsm.h delete mode 100644 htcgeneric-ril.c delete mode 100644 misc.c delete mode 100644 misc.h delete mode 100644 sms.c delete mode 100644 sms_gsm.c delete mode 100644 sms_gsm.h diff --git a/Android.mk b/Android.mk deleted file mode 100644 index ede01e9..0000000 --- a/Android.mk +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2006 The Android Open Source Project - -# XXX using libutils for simulator build only... -# -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - htcgeneric-ril.c \ - atchannel.c \ - misc.c \ - at_tok.c \ - sms.c \ - sms_gsm.c \ - gsm.c - -LOCAL_SHARED_LIBRARIES := \ - libcutils libutils libril - - # for asprinf -LOCAL_CFLAGS := -D_GNU_SOURCE - -LOCAL_C_INCLUDES := $(KERNEL_HEADERS) - -ifeq ($(TARGET_PRODUCT),sooner) - LOCAL_CFLAGS += -DOMAP_CSMI_POWER_CONTROL -DUSE_TI_COMMANDS -endif - -ifeq ($(TARGET_PRODUCT),surf) - LOCAL_CFLAGS += -DPOLL_CALL_STATE -DUSE_QMI -endif - -ifeq ($(TARGET_PRODUCT),dream) - LOCAL_CFLAGS += -DPOLL_CALL_STATE -DUSE_QMI -endif - -LOCAL_MODULE_TAGS := optional - -ifeq (foo,foo) - #build shared library - LOCAL_SHARED_LIBRARIES += \ - libcutils libutils - LOCAL_LDLIBS += -lpthread - LOCAL_CFLAGS += -DRIL_SHLIB - LOCAL_MODULE:= libhtcgeneric-ril - LOCAL_PRELINK_MODULE := false - include $(BUILD_SHARED_LIBRARY) -else - #build executable - LOCAL_SHARED_LIBRARIES += \ - libril - LOCAL_MODULE:= htcgeneric-ril - include $(BUILD_EXECUTABLE) -endif diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 diff --git a/NOTICE b/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/at_tok.c b/at_tok.c deleted file mode 100644 index 11e0cba..0000000 --- a/at_tok.c +++ /dev/null @@ -1,190 +0,0 @@ -/* //device/system/reference-ril/at_tok.c -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "at_tok.h" -#include -#include -#include - -/** - * Starts tokenizing an AT response string - * returns -1 if this is not a valid response string, 0 on success. - * updates *p_cur with current position - */ -int at_tok_start(char **p_cur) -{ - if (*p_cur == NULL) { - return -1; - } - - // skip prefix - // consume "^[^:]:" - - *p_cur = strchr(*p_cur, ':'); - - if (*p_cur == NULL) { - return -1; - } - - (*p_cur)++; - - return 0; -} - -static void skipWhiteSpace(char **p_cur) -{ - if (*p_cur == NULL) return; - - while (**p_cur != '\0' && isspace(**p_cur)) { - (*p_cur)++; - } -} - -static void skipNextComma(char **p_cur) -{ - if (*p_cur == NULL) return; - - while (**p_cur != '\0' && **p_cur != ',') { - (*p_cur)++; - } - - if (**p_cur == ',') { - (*p_cur)++; - } -} - -static char * nextTok(char **p_cur) -{ - char *ret = NULL; - - skipWhiteSpace(p_cur); - - if (*p_cur == NULL) { - ret = NULL; - } else if (**p_cur == '"') { - (*p_cur)++; - ret = strsep(p_cur, "\""); - skipNextComma(p_cur); - } else { - ret = strsep(p_cur, ","); - } - - return ret; -} - - -/** - * Parses the next integer in the AT response line and places it in *p_out - * returns 0 on success and -1 on fail - * updates *p_cur - * "base" is the same as the base param in strtol - */ - -static int at_tok_nextint_base(char **p_cur, int *p_out, int base, int uns) -{ - char *ret; - - if (*p_cur == NULL) { - return -1; - } - - ret = nextTok(p_cur); - - if (ret == NULL) { - return -1; - } else { - long l; - char *end; - - if (uns) - l = strtoul(ret, &end, base); - else - l = strtol(ret, &end, base); - - *p_out = (int)l; - - if (end == ret) { - return -1; - } - } - - return 0; -} - -/** - * Parses the next base 10 integer in the AT response line - * and places it in *p_out - * returns 0 on success and -1 on fail - * updates *p_cur - */ -int at_tok_nextint(char **p_cur, int *p_out) -{ - return at_tok_nextint_base(p_cur, p_out, 10, 0); -} - -/** - * Parses the next base 16 integer in the AT response line - * and places it in *p_out - * returns 0 on success and -1 on fail - * updates *p_cur - */ -int at_tok_nexthexint(char **p_cur, int *p_out) -{ - return at_tok_nextint_base(p_cur, p_out, 16, 1); -} - -int at_tok_nextbool(char **p_cur, char *p_out) -{ - int ret; - int result; - - ret = at_tok_nextint(p_cur, &result); - - if (ret < 0) { - return -1; - } - - // booleans should be 0 or 1 - if (!(result == 0 || result == 1)) { - return -1; - } - - if (p_out != NULL) { - *p_out = (char)result; - } - - return ret; -} - -int at_tok_nextstr(char **p_cur, char **p_out) -{ - if (*p_cur == NULL) { - return -1; - } - - *p_out = nextTok(p_cur); - - return 0; -} - -/** returns 1 on "has more tokens" and 0 if no */ -int at_tok_hasmore(char **p_cur) -{ - return ! (*p_cur == NULL || **p_cur == '\0'); -} - - diff --git a/at_tok.h b/at_tok.h deleted file mode 100644 index 42bb4c9..0000000 --- a/at_tok.h +++ /dev/null @@ -1,30 +0,0 @@ -/* //device/system/reference-ril/at_tok.h -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef AT_TOK_H -#define AT_TOK_H 1 - -int at_tok_start(char **p_cur); -int at_tok_nextint(char **p_cur, int *p_out); -int at_tok_nexthexint(char **p_cur, int *p_out); - -int at_tok_nextbool(char **p_cur, char *p_out); -int at_tok_nextstr(char **p_cur, char **out); - -int at_tok_hasmore(char **p_cur); - -#endif /*AT_TOK_H */ diff --git a/atchannel.c b/atchannel.c deleted file mode 100644 index cdb92a0..0000000 --- a/atchannel.c +++ /dev/null @@ -1,1029 +0,0 @@ -/* //device/system/reference-ril/atchannel.c -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "atchannel.h" -#include "at_tok.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LOG_NDEBUG 0 -#define LOG_TAG "AT" -#include - -#ifdef HAVE_ANDROID_OS -/* for IOCTL's */ -#include -#endif /*HAVE_ANDROID_OS*/ - -#include "misc.h" - -#ifdef HAVE_ANDROID_OS -#define USE_NP 1 -#endif /* HAVE_ANDROID_OS */ - - -#define NUM_ELEMS(x) (sizeof(x)/sizeof(x[0])) - -#define MAX_AT_RESPONSE (8 * 1024) -#define HANDSHAKE_RETRY_COUNT 8 -#define HANDSHAKE_TIMEOUT_MSEC 250 - -static pthread_t s_tid_reader; -static int s_fd = -1; /* fd of the AT channel */ -static ATUnsolHandler s_unsolHandler; - -/* for input buffering */ - -static char s_ATBuffer[MAX_AT_RESPONSE+1]; -static char *s_ATBufferCur = s_ATBuffer; - -static int s_ackPowerIoctl; /* true if TTY has android byte-count - handshake for low power*/ -static int s_readCount = 0; - -#if AT_DEBUG -void AT_DUMP(const char* prefix, const char* buff, int len) -{ - if (len < 0) - len = strlen(buff); - LOGD("%.*s", len, buff); -} -#endif - -/* - * for current pending command - * these are protected by s_commandmutex - */ - -static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER; - -static ATCommandType s_type; -static const char *s_responsePrefix = NULL; -static const char *s_smsPDU = NULL; -static ATResponse *sp_response = NULL; - -static void (*s_onTimeout)(void) = NULL; -static void (*s_onReaderClosed)(void) = NULL; -static int s_readerClosed; - -static void onReaderClosed(); -static int writeCtrlZ (const char *s); -static int writeline (const char *s); - -#ifndef USE_NP -static void setTimespecRelative(struct timespec *p_ts, long long msec) -{ - struct timeval tv; - - gettimeofday(&tv, (struct timezone *) NULL); - - /* what's really funny about this is that I know - pthread_cond_timedwait just turns around and makes this - a relative time again */ - p_ts->tv_sec = tv.tv_sec + (msec / 1000); - p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L; -} -#endif /*USE_NP*/ - -static void sleepMsec(long long msec) -{ - struct timespec ts; - int err; - - ts.tv_sec = (msec / 1000); - ts.tv_nsec = (msec % 1000) * 1000 * 1000; - - do { - err = nanosleep (&ts, &ts); - } while (err < 0 && errno == EINTR); -} - - - -/** add an intermediate response to sp_response*/ -static void addIntermediate(const char *line) -{ - ATLine *p_new; - - p_new = (ATLine *) malloc(sizeof(ATLine)); - - p_new->line = strdup(line); - - /* note: this adds to the head of the list, so the list - will be in reverse order of lines received. the order is flipped - again before passing on to the command issuer */ - p_new->p_next = sp_response->p_intermediates; - sp_response->p_intermediates = p_new; -} - - -/** - * returns 1 if line is a final response indicating error - * See 27.007 annex B - * WARNING: NO CARRIER and others are sometimes unsolicited - */ -static const char * s_finalResponsesError[] = { - "ERROR", - "+CMS ERROR:", - "+CME ERROR:", - "NO CARRIER", /* sometimes! */ - "NO ANSWER", - "NO DIALTONE", -}; -static int isFinalResponseError(const char *line) -{ - size_t i; - - for (i = 0 ; i < NUM_ELEMS(s_finalResponsesError) ; i++) { - if (strStartsWith(line, s_finalResponsesError[i])) { - return 1; - } - } - - return 0; -} - -/** - * returns 1 if line is a final response indicating success - * See 27.007 annex B - * WARNING: NO CARRIER and others are sometimes unsolicited - */ -static const char * s_finalResponsesSuccess[] = { - "OK", - "CONNECT" /* some stacks start up data on another channel */ -}; -static int isFinalResponseSuccess(const char *line) -{ - size_t i; - - for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) { - if (strStartsWith(line, s_finalResponsesSuccess[i])) { - return 1; - } - } - - return 0; -} - -/** - * returns 1 if line is a final response, either error or success - * See 27.007 annex B - * WARNING: NO CARRIER and others are sometimes unsolicited - */ -static int isFinalResponse(const char *line) -{ - return isFinalResponseSuccess(line) || isFinalResponseError(line); -} - - -/** - * returns 1 if line is the first line in (what will be) a two-line - * SMS unsolicited response - */ -static const char * s_smsUnsoliciteds[] = { - "+CMT:", - "+CDS:", - "+CBM:" -}; -static int isSMSUnsolicited(const char *line) -{ - size_t i; - - for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) { - if (strStartsWith(line, s_smsUnsoliciteds[i])) { - return 1; - } - } - - return 0; -} - - -/** assumes s_commandmutex is held */ -static void handleFinalResponse(const char *line) -{ - sp_response->finalResponse = strdup(line); - - pthread_cond_signal(&s_commandcond); -} - -static void handleUnsolicited(const char *line) -{ - if (s_unsolHandler != NULL) { - s_unsolHandler(line, NULL); - } -} - -static void processLine(const char *line) -{ - pthread_mutex_lock(&s_commandmutex); - - if (sp_response == NULL) { - /* no command pending */ - handleUnsolicited(line); - } else if (isFinalResponseSuccess(line)) { - sp_response->success = 1; - handleFinalResponse(line); - } else if (isFinalResponseError(line)) { - sp_response->success = 0; - handleFinalResponse(line); - } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) { - // See eg. TS 27.005 4.3 - // Commands like AT+CMGS have a "> " prompt - writeCtrlZ(s_smsPDU); - s_smsPDU = NULL; - } else switch (s_type) { - case NO_RESULT: - handleUnsolicited(line); - break; - case NUMERIC: - if (sp_response->p_intermediates == NULL - && isdigit(line[0]) - ) { - addIntermediate(line); - } else { - /* either we already have an intermediate response or - the line doesn't begin with a digit */ - handleUnsolicited(line); - } - break; - case SINGLELINE: - if (sp_response->p_intermediates == NULL - && strStartsWith (line, s_responsePrefix) - ) { - addIntermediate(line); - } else { - /* we already have an intermediate response */ - handleUnsolicited(line); - } - break; - case MULTILINE: - if (strStartsWith (line, s_responsePrefix)) { - addIntermediate(line); - } else { - handleUnsolicited(line); - } - break; - - default: /* this should never be reached */ - LOGE("Unsupported AT command type %d\n", s_type); - handleUnsolicited(line); - break; - } - - pthread_mutex_unlock(&s_commandmutex); -} - - -/** - * Returns a pointer to the end of the next line - * special-cases the "> " SMS prompt - * - * returns NULL if there is no complete line - */ -static char * findNextEOL(char *cur) -{ - if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') { - /* SMS prompt character...not \r terminated */ - return cur+2; - } - - // Find next newline - while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++; - - return *cur == '\0' ? NULL : cur; -} - - -/** - * Reads a line from the AT channel, returns NULL on timeout. - * Assumes it has exclusive read access to the FD - * - * This line is valid only until the next call to readline - * - * This function exists because as of writing, android libc does not - * have buffered stdio. - */ - -static const char *readline() -{ - ssize_t count; - - char *p_read = NULL; - char *p_eol = NULL; - char *ret; - - /* this is a little odd. I use *s_ATBufferCur == 0 to - * mean "buffer consumed completely". If it points to a character, than - * the buffer continues until a \0 - */ - if (*s_ATBufferCur == '\0') { - /* empty buffer */ - s_ATBufferCur = s_ATBuffer; - *s_ATBufferCur = '\0'; - p_read = s_ATBuffer; - } else { /* *s_ATBufferCur != '\0' */ - /* there's data in the buffer from the last read */ - - // skip over leading newlines - while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') - s_ATBufferCur++; - - p_eol = findNextEOL(s_ATBufferCur); - - if (p_eol == NULL) { - /* a partial line. move it up and prepare to read more */ - size_t len; - - len = strlen(s_ATBufferCur); - - memmove(s_ATBuffer, s_ATBufferCur, len + 1); - p_read = s_ATBuffer + len; - s_ATBufferCur = s_ATBuffer; - } - /* Otherwise, (p_eol !- NULL) there is a complete line */ - /* that will be returned the while () loop below */ - } - - while (p_eol == NULL) { - if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) { - LOGE("ERROR: Input line exceeded buffer\n"); - /* ditch buffer and start over again */ - s_ATBufferCur = s_ATBuffer; - *s_ATBufferCur = '\0'; - p_read = s_ATBuffer; - } - - do { - count = read(s_fd, p_read, - MAX_AT_RESPONSE - (p_read - s_ATBuffer)); - } while (count < 0 && errno == EINTR); - - if (count > 0) { - AT_DUMP( "<< ", p_read, count ); - s_readCount += count; - - p_read[count] = '\0'; - - // skip over leading newlines - while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') - s_ATBufferCur++; - - p_eol = findNextEOL(s_ATBufferCur); - p_read += count; - } else if (count <= 0) { - /* read error encountered or EOF reached */ - if(count == 0) { - LOGD("atchannel: EOF reached"); - } else { - LOGD("atchannel: read error %s", strerror(errno)); - } - return NULL; - } - } - - /* a full line in the buffer. Place a \0 over the \r and return */ - - ret = s_ATBufferCur; - *p_eol = '\0'; - s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */ - /* and there will be a \0 at *p_read */ - - LOGD("AT< %s\n", ret); - return ret; -} - - -static void onReaderClosed() -{ - if (s_onReaderClosed != NULL && s_readerClosed == 0) { - - pthread_mutex_lock(&s_commandmutex); - - s_readerClosed = 1; - - pthread_cond_signal(&s_commandcond); - - pthread_mutex_unlock(&s_commandmutex); - - s_onReaderClosed(); - } -} - - -static void *readerLoop(void *arg) -{ - for (;;) { - const char * line; - - line = readline(); - - if (line == NULL) { - break; - } - - if(isSMSUnsolicited(line)) { - char *line1; - const char *line2; - - // The scope of string returned by 'readline()' is valid only - // till next call to 'readline()' hence making a copy of line - // before calling readline again. - line1 = strdup(line); - line2 = readline(); - - if (line2 == NULL) { - break; - } - - if (s_unsolHandler != NULL) { - s_unsolHandler (line1, line2); - } - free(line1); - } else { - processLine(line); - } - -#ifdef HAVE_ANDROID_OS - if (s_ackPowerIoctl > 0) { - /* acknowledge that bytes have been read and processed */ - ioctl(s_fd, OMAP_CSMI_TTY_ACK, &s_readCount); - s_readCount = 0; - } -#endif /*HAVE_ANDROID_OS*/ - } - - onReaderClosed(); - - return NULL; -} - -/** - * Sends string s to the radio with a \r appended. - * Returns AT_ERROR_* on error, 0 on success - * - * This function exists because as of writing, android libc does not - * have buffered stdio. - */ -static int writeline (const char *s) -{ - size_t cur = 0; - size_t len = strlen(s); - ssize_t written; - - if (s_fd < 0 || s_readerClosed > 0) { - return AT_ERROR_CHANNEL_CLOSED; - } - - LOGD("AT> %s\n", s); - - AT_DUMP( ">> ", s, strlen(s) ); - - /* the main string */ - while (cur < len) { - do { - written = write (s_fd, s + cur, len - cur); - } while (written < 0 && errno == EINTR); - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - cur += written; - } - - /* the \r */ - - do { - written = write (s_fd, "\r" , 1); - } while ((written < 0 && errno == EINTR) || (written == 0)); - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - return 0; -} -static int writeCtrlZ (const char *s) -{ - size_t cur = 0; - size_t len = strlen(s); - ssize_t written; - - if (s_fd < 0 || s_readerClosed > 0) { - return AT_ERROR_CHANNEL_CLOSED; - } - - LOGD("AT> %s^Z\n", s); - - AT_DUMP( ">* ", s, strlen(s) ); - - /* the main string */ - while (cur < len) { - do { - written = write (s_fd, s + cur, len - cur); - } while (written < 0 && errno == EINTR); - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - cur += written; - } - - /* the ^Z */ - - do { - written = write (s_fd, "\032" , 1); - } while ((written < 0 && errno == EINTR) || (written == 0)); - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - return 0; -} - -static void clearPendingCommand() -{ - if (sp_response != NULL) { - at_response_free(sp_response); - } - - sp_response = NULL; - s_responsePrefix = NULL; - s_smsPDU = NULL; -} - - -/** - * Starts AT handler on stream "fd' - * returns 0 on success, -1 on error - */ -int at_open(int fd, ATUnsolHandler h) -{ - int ret; - pthread_t tid; - pthread_attr_t attr; - - s_fd = fd; - s_unsolHandler = h; - s_readerClosed = 0; - - s_responsePrefix = NULL; - s_smsPDU = NULL; - sp_response = NULL; - - /* Android power control ioctl */ -#ifdef HAVE_ANDROID_OS -#ifdef OMAP_CSMI_POWER_CONTROL - ret = ioctl(fd, OMAP_CSMI_TTY_ENABLE_ACK); - if(ret == 0) { - int ack_count; - int read_count; - int old_flags; - char sync_buf[256]; - old_flags = fcntl(fd, F_GETFL, 0); - fcntl(fd, F_SETFL, old_flags | O_NONBLOCK); - do { - ioctl(fd, OMAP_CSMI_TTY_READ_UNACKED, &ack_count); - read_count = 0; - do { - ret = read(fd, sync_buf, sizeof(sync_buf)); - if(ret > 0) - read_count += ret; - } while(ret > 0 || (ret < 0 && errno == EINTR)); - ioctl(fd, OMAP_CSMI_TTY_ACK, &ack_count); - } while(ack_count > 0 || read_count > 0); - fcntl(fd, F_SETFL, old_flags); - s_readCount = 0; - s_ackPowerIoctl = 1; - } - else - s_ackPowerIoctl = 0; - -#else // OMAP_CSMI_POWER_CONTROL - s_ackPowerIoctl = 0; - -#endif // OMAP_CSMI_POWER_CONTROL -#endif /*HAVE_ANDROID_OS*/ - - pthread_attr_init (&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr); - - if (ret < 0) { - perror ("pthread_create"); - return -1; - } - - - return 0; -} - -/* FIXME is it ok to call this from the reader and the command thread? */ -void at_close() -{ - if (s_fd >= 0) { - close(s_fd); - } - s_fd = -1; - - pthread_mutex_lock(&s_commandmutex); - - s_readerClosed = 1; - - pthread_cond_signal(&s_commandcond); - - pthread_mutex_unlock(&s_commandmutex); - - /* the reader thread should eventually die */ -} - -static ATResponse * at_response_new() -{ - return (ATResponse *) calloc(1, sizeof(ATResponse)); -} - -void at_response_free(ATResponse *p_response) -{ - ATLine *p_line; - - if (p_response == NULL) return; - - p_line = p_response->p_intermediates; - - while (p_line != NULL) { - ATLine *p_toFree; - - p_toFree = p_line; - p_line = p_line->p_next; - - free(p_toFree->line); - free(p_toFree); - } - - free (p_response->finalResponse); - free (p_response); -} - -/** - * The line reader places the intermediate responses in reverse order - * here we flip them back - */ -static void reverseIntermediates(ATResponse *p_response) -{ - ATLine *pcur,*pnext; - - pcur = p_response->p_intermediates; - p_response->p_intermediates = NULL; - - while (pcur != NULL) { - pnext = pcur->p_next; - pcur->p_next = p_response->p_intermediates; - p_response->p_intermediates = pcur; - pcur = pnext; - } -} - -/** - * Internal send_command implementation - * Doesn't lock or call the timeout callback - * - * timeoutMsec == 0 means infinite timeout - */ - -static int at_send_command_full_nolock (const char *command, ATCommandType type, - const char *responsePrefix, const char *smspdu, - long long timeoutMsec, ATResponse **pp_outResponse) -{ - int err = 0; -#ifndef USE_NP - struct timespec ts; -#endif /*USE_NP*/ - - if(sp_response != NULL) { - err = AT_ERROR_COMMAND_PENDING; - goto error; - } - - err = writeline (command); - - if (err < 0) { - goto error; - } - - s_type = type; - s_responsePrefix = responsePrefix; - s_smsPDU = smspdu; - sp_response = at_response_new(); - -#ifndef USE_NP - if (timeoutMsec != 0) { - setTimespecRelative(&ts, timeoutMsec); - } -#endif /*USE_NP*/ - - while (sp_response->finalResponse == NULL && s_readerClosed == 0) { - if (timeoutMsec != 0) { -#ifdef USE_NP - err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec); -#else - err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts); -#endif /*USE_NP*/ - } else { - err = pthread_cond_wait(&s_commandcond, &s_commandmutex); - } - - if (err == ETIMEDOUT) { - err = AT_ERROR_TIMEOUT; - goto error; - } - } - - if (pp_outResponse == NULL) { - at_response_free(sp_response); - } else { - /* line reader stores intermediate responses in reverse order */ - reverseIntermediates(sp_response); - *pp_outResponse = sp_response; - } - - sp_response = NULL; - - if(s_readerClosed > 0) { - err = AT_ERROR_CHANNEL_CLOSED; - goto error; - } - - err = 0; -error: - clearPendingCommand(); - - return err; -} - -/** - * Internal send_command implementation - * - * timeoutMsec == 0 means infinite timeout - */ -static int at_send_command_full (const char *command, ATCommandType type, - const char *responsePrefix, const char *smspdu, - long long timeoutMsec, ATResponse **pp_outResponse) -{ - int err; - - if (0 != pthread_equal(s_tid_reader, pthread_self())) { - /* cannot be called from reader thread */ - return AT_ERROR_INVALID_THREAD; - } - - pthread_mutex_lock(&s_commandmutex); - - err = at_send_command_full_nolock(command, type, - responsePrefix, smspdu, - timeoutMsec, pp_outResponse); - - pthread_mutex_unlock(&s_commandmutex); - - if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) { - s_onTimeout(); - } - - return err; -} - - -/** - * Issue a single normal AT command with no intermediate response expected - * - * "command" should not include \r - * pp_outResponse can be NULL - * - * if non-NULL, the resulting ATResponse * must be eventually freed with - * at_response_free - */ -int at_send_command (const char *command, ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, NO_RESULT, NULL, - NULL, 0, pp_outResponse); - - return err; -} - - -int at_send_command_timeout (const char *command, long long timeout, ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, NO_RESULT, NULL, - NULL, timeout, pp_outResponse); - - return err; -} - - -int at_send_command_singleline (const char *command, - const char *responsePrefix, - ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, SINGLELINE, responsePrefix, - NULL, 0, pp_outResponse); - - if (err == 0 && pp_outResponse != NULL - && (*pp_outResponse)->success > 0 - && (*pp_outResponse)->p_intermediates == NULL - ) { - /* successful command must have an intermediate response */ - at_response_free(*pp_outResponse); - *pp_outResponse = NULL; - return AT_ERROR_INVALID_RESPONSE; - } - - return err; -} - - -int at_send_command_numeric (const char *command, - ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, NUMERIC, NULL, - NULL, 0, pp_outResponse); - - if (err == 0 && pp_outResponse != NULL - && (*pp_outResponse)->success > 0 - && (*pp_outResponse)->p_intermediates == NULL - ) { - /* successful command must have an intermediate response */ - at_response_free(*pp_outResponse); - *pp_outResponse = NULL; - return AT_ERROR_INVALID_RESPONSE; - } - - return err; -} - - -int at_send_command_sms (const char *command, - const char *pdu, - const char *responsePrefix, - ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, SINGLELINE, responsePrefix, - pdu, 0, pp_outResponse); - - if (err == 0 && pp_outResponse != NULL - && (*pp_outResponse)->success > 0 - && (*pp_outResponse)->p_intermediates == NULL - ) { - /* successful command must have an intermediate response */ - at_response_free(*pp_outResponse); - *pp_outResponse = NULL; - return AT_ERROR_INVALID_RESPONSE; - } - - return err; -} - - -int at_send_command_multiline (const char *command, - const char *responsePrefix, - ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, MULTILINE, responsePrefix, - NULL, 0, pp_outResponse); - - return err; -} - - -/** This callback is invoked on the command thread */ -void at_set_on_timeout(void (*onTimeout)(void)) -{ - s_onTimeout = onTimeout; -} - -/** - * This callback is invoked on the reader thread (like ATUnsolHandler) - * when the input stream closes before you call at_close - * (not when you call at_close()) - * You should still call at_close() - */ - -void at_set_on_reader_closed(void (*onClose)(void)) -{ - s_onReaderClosed = onClose; -} - - -/** - * Periodically issue an AT command and wait for a response. - * Used to ensure channel has start up and is active - */ - -int at_handshake() -{ - int i; - int err = 0; - - if (0 != pthread_equal(s_tid_reader, pthread_self())) { - /* cannot be called from reader thread */ - return AT_ERROR_INVALID_THREAD; - } - - pthread_mutex_lock(&s_commandmutex); - - for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) { - /* some stacks start with verbose off */ - err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT, - NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL); - - if (err == 0) { - break; - } - } - - if (err == 0) { - /* pause for a bit to let the input buffer drain any unmatched OK's - (they will appear as extraneous unsolicited responses) */ - - sleepMsec(HANDSHAKE_TIMEOUT_MSEC); - } - - pthread_mutex_unlock(&s_commandmutex); - - return err; -} - -/** - * Returns error code from response - * Assumes AT+CMEE=1 (numeric) mode - */ -AT_CME_Error at_get_cme_error(const ATResponse *p_response) -{ - int ret; - int err; - char *p_cur; - - if (p_response->success > 0) { - return CME_SUCCESS; - } - - if (p_response->finalResponse == NULL - || !strStartsWith(p_response->finalResponse, "+CME ERROR:") - ) { - return CME_ERROR_NON_CME; - } - - p_cur = p_response->finalResponse; - err = at_tok_start(&p_cur); - - if (err < 0) { - return CME_ERROR_NON_CME; - } - - err = at_tok_nextint(&p_cur, &ret); - - if (err < 0) { - return CME_ERROR_NON_CME; - } - - return (AT_CME_Error) ret; -} - diff --git a/atchannel.h b/atchannel.h deleted file mode 100644 index cfd49d5..0000000 --- a/atchannel.h +++ /dev/null @@ -1,124 +0,0 @@ -/* //device/system/reference-ril/atchannel.h -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef ATCHANNEL_H -#define ATCHANNEL_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* define AT_DEBUG to send AT traffic to /tmp/radio-at.log" */ -#define AT_DEBUG 0 - -#if AT_DEBUG -extern void AT_DUMP(const char* prefix, const char* buff, int len); -#else -#define AT_DUMP(prefix,buff,len) do{}while(0) -#endif - -#define AT_ERROR_GENERIC -1 -#define AT_ERROR_COMMAND_PENDING -2 -#define AT_ERROR_CHANNEL_CLOSED -3 -#define AT_ERROR_TIMEOUT -4 -#define AT_ERROR_INVALID_THREAD -5 /* AT commands may not be issued from - reader thread (or unsolicited response - callback */ -#define AT_ERROR_INVALID_RESPONSE -6 /* eg an at_send_command_singleline that - did not get back an intermediate - response */ - - -typedef enum { - NO_RESULT, /* no intermediate response expected */ - NUMERIC, /* a single intermediate response starting with a 0-9 */ - SINGLELINE, /* a single intermediate response starting with a prefix */ - MULTILINE /* multiple line intermediate response - starting with a prefix */ -} ATCommandType; - -/** a singly-lined list of intermediate responses */ -typedef struct ATLine { - struct ATLine *p_next; - char *line; -} ATLine; - -/** Free this with at_response_free() */ -typedef struct { - int success; /* true if final response indicates - success (eg "OK") */ - char *finalResponse; /* eg OK, ERROR */ - ATLine *p_intermediates; /* any intermediate responses */ -} ATResponse; - -/** - * a user-provided unsolicited response handler function - * this will be called from the reader thread, so do not block - * "s" is the line, and "sms_pdu" is either NULL or the PDU response - * for multi-line TS 27.005 SMS PDU responses (eg +CMT:) - */ -typedef void (*ATUnsolHandler)(const char *s, const char *sms_pdu); - -int at_open(int fd, ATUnsolHandler h); -void at_close(); - -/* This callback is invoked on the command thread. - You should reset or handshake here to avoid getting out of sync */ -void at_set_on_timeout(void (*onTimeout)(void)); -/* This callback is invoked on the reader thread (like ATUnsolHandler) - when the input stream closes before you call at_close - (not when you call at_close()) - You should still call at_close() - It may also be invoked immediately from the current thread if the read - channel is already closed */ -void at_set_on_reader_closed(void (*onClose)(void)); - -int at_send_command_singleline (const char *command, - const char *responsePrefix, - ATResponse **pp_outResponse); - -int at_send_command_numeric (const char *command, - ATResponse **pp_outResponse); - -int at_send_command_multiline (const char *command, - const char *responsePrefix, - ATResponse **pp_outResponse); - - -int at_handshake(); - -int at_send_command (const char *command, ATResponse **pp_outResponse); - -int at_send_command_sms (const char *command, const char *pdu, - const char *responsePrefix, - ATResponse **pp_outResponse); - -void at_response_free(ATResponse *p_response); - -typedef enum { - CME_ERROR_NON_CME = -1, - CME_SUCCESS = 0, - CME_SIM_NOT_INSERTED = 10 -} AT_CME_Error; - -AT_CME_Error at_get_cme_error(const ATResponse *p_response); - -#ifdef __cplusplus -} -#endif - -#endif /*ATCHANNEL_H*/ diff --git a/gsm.c b/gsm.c deleted file mode 100644 index 754f009..0000000 --- a/gsm.c +++ /dev/null @@ -1,1165 +0,0 @@ -#include "gsm.h" -#include - -/** UTILITIES - **/ -byte_t -gsm_int_to_bcdi( int value ) -{ - return (byte_t)((value / 10) | ((value % 10) << 4)); -} - -int -gsm_int_from_bcdi( byte_t val ) -{ - int ret = 0; - - if ((val & 0xf0) <= 0x90) - ret = (val >> 4); - - if ((val & 0x0f) <= 0x90) - ret |= (val % 0xf)*10; - - return ret; -} - - -static int -gsm_bcdi_to_ascii( cbytes_t bcd, int bcdlen, bytes_t dst ) -{ - static byte_t bcdichars[14] = "0123456789*#,N"; - - int result = 0; - int shift = 0; - - while (bcdlen > 0) { - int c = (bcd[0] >> shift) & 0xf; - - if (c == 0xf && bcdlen == 1) - break; - - if (c < 14) { - if (dst) dst[result] = bcdichars[c]; - result += 1; - } - bcdlen --; - shift += 4; - if (shift == 8) { - bcd++; - shift = 0; - } - } - return result; -} - - -static int -gsm_bcdi_from_ascii( cbytes_t ascii, int asciilen, bytes_t dst ) -{ - cbytes_t end = ascii + asciilen; - int result = 0; - int phase = 0x01; - - while (ascii < end) { - int c = *ascii++; - int d; - - if (c == '*') - c = 11; - else if (c == '#') - c = 12; - else if (c == ',') - c = 13; - else if (c == 'N') - c = 14; - else { - c -= '0'; - if ((unsigned)c >= 10) - break; - } - phase = (phase << 4) | c; - if (phase & 0x100) { - if (dst) dst[result] = (byte_t) phase; - result += 1; - phase = 0x01; - } - } - if (phase != 0x01) { - if (dst) dst[result] = (byte_t)( phase | 0xf0 ); - result += 1; - } - return result; -} - - -int -gsm_hexchar_to_int( char c ) -{ - if ((unsigned)(c - '0') < 10) - return c - '0'; - if ((unsigned)(c - 'a') < 6) - return 10 + (c - 'a'); - if ((unsigned)(c - 'A') < 6) - return 10 + (c - 'A'); - return -1; -} - -int -gsm_hexchar_to_int0( char c ) -{ - int ret = gsm_hexchar_to_int(c); - - return (ret < 0) ? 0 : ret; -} - -int -gsm_hex2_to_byte( const char* hex ) -{ - int hi = gsm_hexchar_to_int(hex[0]); - int lo = gsm_hexchar_to_int(hex[1]); - - if (hi < 0 || lo < 0) - return -1; - - return ( (hi << 4) | lo ); -} - -int -gsm_hex4_to_short( const char* hex ) -{ - int hi = gsm_hex2_to_byte(hex); - int lo = gsm_hex2_to_byte(hex+2); - - if (hi < 0 || lo < 0) - return -1; - - return ((hi << 8) | lo); -} - -int -gsm_hex2_to_byte0( const char* hex ) -{ - int hi = gsm_hexchar_to_int0(hex[0]); - int lo = gsm_hexchar_to_int0(hex[1]); - - return (byte_t)( (hi << 4) | lo ); -} - -void -gsm_hex_from_byte( char* hex, int val ) -{ - static const char hexdigits[] = "0123456789ABCDEF"; - - hex[0] = hexdigits[(val >> 4) & 15]; - hex[1] = hexdigits[val & 15]; -} - -void -gsm_hex_from_short( char* hex, int val ) -{ - gsm_hex_from_byte( hex, (val >> 8) ); - gsm_hex_from_byte( hex+2, val ); -} - - - -/** HEX - **/ -void -gsm_hex_to_bytes( cbytes_t hex, int hexlen, bytes_t dst ) -{ - int nn; - - for (nn = 0; nn < hexlen/2; nn++ ) { - dst[nn] = (byte_t) gsm_hex2_to_byte0( hex+2*nn ); - } - if (hexlen & 1) { - dst[nn] = gsm_hexchar_to_int0( hex[2*nn] ) << 4; - } -} - -void -gsm_hex_from_bytes( char* hex, cbytes_t src, int srclen ) -{ - int nn; - - for (nn = 0; nn < srclen; nn++) { - gsm_hex_from_byte( hex + 2*nn, src[nn] ); - } -} - -/** ROPES - **/ - -void -gsm_rope_init( GsmRope rope ) -{ - rope->data = NULL; - rope->pos = 0; - rope->max = 0; - rope->error = 0; -} - -void -gsm_rope_init_alloc( GsmRope rope, int count ) -{ - rope->data = rope->data0; - rope->pos = 0; - rope->max = sizeof(rope->data0); - rope->error = 0; - - if (count > 0) { - rope->data = calloc( count, 1 ); - rope->max = count; - - if (rope->data == NULL) { - rope->error = 1; - rope->max = 0; - } - } -} - -int -gsm_rope_done( GsmRope rope ) -{ - int result = rope->error; - - if (rope->data && rope->data != rope->data0) - free(rope->data); - - rope->data = NULL; - rope->pos = 0; - rope->max = 0; - rope->error = 0; - - return result; -} - - -bytes_t -gsm_rope_done_acquire( GsmRope rope, int *psize ) -{ - bytes_t result = rope->data; - - *psize = rope->pos; - if (result == rope->data0) { - result = malloc( rope->pos ); - if (result != NULL) - memcpy( result, rope->data, rope->pos ); - } - return result; -} - - -int -gsm_rope_ensure( GsmRope rope, int new_count ) -{ - if (rope->data != NULL) { - int old_max = rope->max; - bytes_t old_data = rope->data == rope->data0 ? NULL : rope->data; - int new_max = old_max; - bytes_t new_data; - - while (new_max < new_count) { - new_max += (new_max >> 1) + 4; - } - new_data = realloc( old_data, new_max ); - if (new_data == NULL) { - rope->error = 1; - return -1; - } - rope->data = new_data; - rope->max = new_max; - } else { - rope->max = new_count; - } - return 0; -} - -static int -gsm_rope_can_grow( GsmRope rope, int count ) -{ - if (!rope->data || rope->error) - return 0; - - if (rope->pos + count > rope->max) - { - if (rope->data == NULL) - rope->max = rope->pos + count; - - else if (rope->error || - gsm_rope_ensure( rope, rope->pos + count ) < 0) - return 0; - } - return 1; -} - -void -gsm_rope_add_c( GsmRope rope, char c ) -{ - if (gsm_rope_can_grow(rope, 1)) { - rope->data[ rope->pos ] = (byte_t) c; - } - rope->pos += 1; -} - -void -gsm_rope_add( GsmRope rope, const void* buf, int buflen ) -{ - if (gsm_rope_can_grow(rope, buflen)) { - memcpy( rope->data + rope->pos, (const char*)buf, buflen ); - } - rope->pos += buflen; -} - -void* -gsm_rope_reserve( GsmRope rope, int count ) -{ - void* result = NULL; - - if (gsm_rope_can_grow(rope, count)) - { - if (rope->data != NULL) - result = rope->data + rope->pos; - } - rope->pos += count; - - return result; -} - -/* skip a given number of Unicode characters in a utf-8 byte string */ -cbytes_t -utf8_skip( cbytes_t utf8, - cbytes_t utf8end, - int count) -{ - cbytes_t p = utf8; - cbytes_t end = utf8end; - - for ( ; count > 0; count-- ) { - int c; - - if (p > end) - break; - - c = *p++; - if (c > 128) { - while (p < end && (p[0] & 0xc0) == 0x80) - p++; - } - } - return p; -} - -static __inline__ int -utf8_next( cbytes_t *pp, cbytes_t end ) -{ - cbytes_t p = *pp; - int result = -1; - - if (p < end) { - int c= *p++; - if (c >= 128) { - if ((c & 0xe0) == 0xc0) - c &= 0x1f; - else if ((c & 0xf0) == 0xe0) - c &= 0x0f; - else - c &= 0x07; - - while (p < end && (p[0] & 0xc0) == 0x80) { - c = (c << 6) | (p[0] & 0x3f); - } - } - result = c; - *pp = p; - } -Exit: - return result; -} - - -__inline__ int -utf8_write( bytes_t utf8, int offset, int v ) -{ - int result; - - if (v < 128) { - result = 1; - if (utf8) - utf8[offset] = (byte_t) v; - } else if (v < 0x800) { - result = 2; - if (utf8) { - utf8[offset+0] = (byte_t)( 0xc0 | (v >> 6) ); - utf8[offset+1] = (byte_t)( 0x80 | (v & 0x3f) ); - } - } else if (v < 0x10000) { - result = 3; - if (utf8) { - utf8[offset+0] = (byte_t)( 0xe0 | (v >> 12) ); - utf8[offset+1] = (byte_t)( 0x80 | ((v >> 6) & 0x3f) ); - utf8[offset+2] = (byte_t)( 0x80 | (v & 0x3f) ); - } - } else { - result = 4; - if (utf8) { - utf8[offset+0] = (byte_t)( 0xf0 | ((v >> 18) & 0x7) ); - utf8[offset+1] = (byte_t)( 0x80 | ((v >> 12) & 0x3f) ); - utf8[offset+2] = (byte_t)( 0x80 | ((v >> 6) & 0x3f) ); - utf8[offset+3] = (byte_t)( 0x80 | (v & 0x3f) ); - } - } - return result; -} - -static __inline__ int -ucs2_write( bytes_t ucs2, int offset, int v ) -{ - if (ucs2) { - ucs2[offset+0] = (byte_t) (v >> 8); - ucs2[offset+1] = (byte_t) (v); - } - return 2; -} - -int -utf8_check( cbytes_t p, int utf8len ) -{ - cbytes_t end = p + utf8len; - int result = 0; - - if (p) { - while (p < end) { - int c = *p++; - if (c >= 128) { - int len; - if ((c & 0xe0) == 0xc0) { - len = 1; - } - else if ((c & 0xf0) == 0xe0) { - len = 2; - } - else if ((c & 0xf8) == 0xf0) { - len = 3; - } - else - goto Exit; /* malformed utf-8 */ - - if (p+len > end) /* string too short */ - goto Exit; - - for ( ; len > 0; len--, p++ ) { - if ((p[0] & 0xc0) != 0x80) - goto Exit; - } - } - } - result = 1; - } -Exit: - return result; -} - -/** UCS2 to UTF8 - **/ - -/* convert a UCS2 string into a UTF8 byte string, assumes 'buf' is correctly sized */ -int -ucs2_to_utf8( cbytes_t ucs2, - int ucs2len, - bytes_t buf ) -{ - int nn; - int result = 0; - - for (nn = 0; nn < ucs2len; ucs2 += 2, nn++) { - int c= (ucs2[0] << 8) | ucs2[1]; - result += utf8_write(buf, result, c); - } - return result; -} - -/* count the number of UCS2 chars contained in a utf8 byte string */ -int -utf8_to_ucs2( cbytes_t utf8, - int utf8len, - bytes_t ucs2 ) -{ - cbytes_t p = utf8; - cbytes_t end = p + utf8len; - int result = 0; - - while (p < end) { - int c = utf8_next(&p, end); - - if (c < 0) - break; - - result += ucs2_write(ucs2, result, c); - } - return result/2; -} - - - -/** GSM ALPHABET - **/ - -#define GSM_7BITS_ESCAPE 0x1b -#define GSM_7BITS_UNKNOWN 0 - -static const unsigned short gsm7bits_to_unicode[128] = { - '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec, 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5, -0x394, '_',0x3a6,0x393,0x39b,0x3a9,0x3a0,0x3a8,0x3a3,0x398,0x39e, 0, 0xc6, 0xe6, 0xdf, 0xc9, - ' ', '!', '"', '#', 0xa4, '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', - 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0xc4, 0xd6,0x147, 0xdc, 0xa7, - 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0, -}; - -static const unsigned short gsm7bits_extend_to_unicode[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\f', 0, 0, 0, 0, 0, - 0, 0, 0, 0, '^', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, '{', '}', 0, 0, 0, 0, 0,'\\', - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '[', '~', ']', 0, - '|', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,0x20ac, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - - -static int -unichar_to_gsm7( int unicode ) -{ - int nn; - for (nn = 0; nn < 128; nn++) { - if (gsm7bits_to_unicode[nn] == unicode) { - return nn; - } - } - return -1; -} - -static int -unichar_to_gsm7_extend( int unichar ) -{ - int nn; - for (nn = 0; nn < 128; nn++) { - if (gsm7bits_extend_to_unicode[nn] == unichar) { - return nn; - } - } - return -1; -} - - -/* return the number of septets needed to encode a unicode charcode */ -static int -unichar_to_gsm7_count( int unicode ) -{ - int nn; - - nn = unichar_to_gsm7(unicode); - if (nn >= 0) - return 1; - - nn = unichar_to_gsm7_extend(unicode); - if (nn >= 0) - return 2; - - return 0; -} - - -int -utf8_check_gsm7( cbytes_t utf8, - int utf8len ) -{ - cbytes_t utf8end = utf8 + utf8len; - - while (utf8 < utf8end) { - int c = utf8_next( &utf8, utf8end ); - if (unichar_to_gsm7_count(c) == 0) - return 0; - } - return 1; -} - - -int -utf8_from_gsm7( cbytes_t src, - int septet_offset, - int septet_count, - bytes_t utf8 ) -{ - int shift = (septet_offset & 7); - int escaped = 0; - int result = 0; - - src += (septet_offset >> 3); - for ( ; septet_count > 0; septet_count-- ) - { - int c = (src[0] >> shift) & 0x7f; - int v; - - if (shift > 1) { - c = ((src[1] << (8-shift)) | c) & 0x7f; - } - - if (escaped) { - v = gsm7bits_extend_to_unicode[c]; - } else if (c == GSM_7BITS_ESCAPE) { - escaped = 1; - goto NextSeptet; - } else { - v = gsm7bits_to_unicode[c]; - } - - result += utf8_write( utf8, result, v ); - - NextSeptet: - shift += 7; - if (shift >= 8) { - shift -= 8; - src += 1; - } - } - return result; -} - - -int -utf8_from_gsm8( cbytes_t src, int count, bytes_t utf8 ) -{ - int result = 0; - int escaped = 0; - - - for ( ; count > 0; count-- ) - { - int c = *src++; - int v; - - if (c == 0xff) - break; - - if (c == GSM_7BITS_ESCAPE) { - if (escaped) { /* two escape characters => one space */ - c = 0x20; - escaped = 0; - } else { - escaped = 1; - continue; - } - } - else - { - if (c >= 0x80) { - c = 0x20; - escaped = 0; - } else if (escaped) { - c = gsm7bits_extend_to_unicode[c]; - } else - c = gsm7bits_to_unicode[c]; - } - - result += utf8_write( utf8, result, c ); - } - return result; -} - -/* convert a GSM 7-bit message into a unicode character array - * the 'dst' array must contain at least 160 chars. the function - * returns the number of characters decoded - * - * assumes the 'dst' array has at least septet_count items, returns the - * number of unichars really written - */ -int -ucs2_from_gsm7( bytes_t ucs2, - cbytes_t src, - int septet_offset, - int septet_count ) -{ - const unsigned char* p = src + (septet_offset >> 3); - int shift = (septet_offset & 7); - int escaped = 0; - int result = 0; - - for ( ; septet_count > 0; septet_count-- ) - { - unsigned val = (p[0] >> shift) & 0x7f; - - if (shift > 1) - val = (val | (p[1] << (8-shift))) & 0x7f; - - if (escaped) { - int c = gsm7bits_to_unicode[val]; - - result += ucs2_write(ucs2, result, c); - escaped = 0; - } - else if (val == GSM_7BITS_ESCAPE) { - escaped = 1; - } - else { - val = gsm7bits_extend_to_unicode[val]; - if (val == 0) - val = 0x20; - - result += ucs2_write( ucs2, result, val ); - } - } - return result/2; -} - - -/* count the number of septets required to write a utf8 string */ -static int -utf8_to_gsm7_count( cbytes_t utf8, int utf8len ) -{ - cbytes_t utf8end = utf8 + utf8len; - int result = 0; - - while ( utf8 < utf8end ) { - int len; - int c = utf8_next( &utf8, utf8end ); - - if (c < 0) - break; - - len = unichar_to_gsm7_count(c); - if (len == 0) /* replace non-representables with space */ - len = 1; - - result += len; - } - return result; -} - -typedef struct { - bytes_t dst; - unsigned pad; - int bits; - int offset; -} BWriterRec, *BWriter; - -static void -bwriter_init( BWriter writer, bytes_t dst, int start ) -{ - int shift = start & 7; - - writer->dst = dst + (start >> 3); - writer->pad = 0; - writer->bits = shift; - writer->offset = start; - - if (shift > 0) { - writer->pad = writer->dst[0] & ~(0xFF << shift); - } -} - -static void -bwriter_add7( BWriter writer, unsigned value ) -{ - writer->pad |= (unsigned)(value << writer->bits); - writer->bits += 7; - if (writer->bits >= 8) { - writer->dst[0] = (byte_t)writer->pad; - writer->bits -= 8; - writer->pad >>= 8; - writer->dst += 1; - } - writer->offset += 7; -} - -static int -bwriter_done( BWriter writer ) -{ - if (writer->bits > 0) { - writer->dst[0] = (byte_t)writer->pad; - writer->pad = 0; - writer->bits = 0; - writer->dst += 1; - } - return writer->offset; -} - -/* convert a utf8 string to a gsm7 byte string - return the number of septets written */ -int -utf8_to_gsm7( cbytes_t utf8, int utf8len, bytes_t dst, int offset ) -{ - const unsigned char* utf8end = utf8 + utf8len; - BWriterRec writer[1]; - - if (dst == NULL) - return utf8_to_gsm7_count(utf8, utf8len); - - bwriter_init( writer, dst, offset ); - while ( utf8 < utf8end ) { - int c = utf8_next( &utf8, utf8end ); - int nn; - - if (c < 0) - break; - - nn = unichar_to_gsm7(c); - if (nn >= 0) { - bwriter_add7( writer, nn ); - continue; - } - - nn = unichar_to_gsm7_extend(c); - if (nn >= 0) { - bwriter_add7( writer, GSM_7BITS_ESCAPE ); - bwriter_add7( writer, nn ); - continue; - } - - /* unknown => replaced by space */ - bwriter_add7( writer, 0x20 ); - } - return bwriter_done( writer ); -} - - -int -utf8_to_gsm8( cbytes_t utf8, int utf8len, bytes_t dst ) -{ - const unsigned char* utf8end = utf8 + utf8len; - int result = 0; - - while ( utf8 < utf8end ) { - int c = utf8_next( &utf8, utf8end ); - int nn; - - if (c < 0) - break; - - nn = unichar_to_gsm7(c); - if (nn >= 0) { - if (dst) - dst[result] = (byte_t)nn; - result += 1; - continue; - } - - nn = unichar_to_gsm7_extend(c); - if (nn >= 0) { - if (dst) { - dst[result+0] = (byte_t) GSM_7BITS_ESCAPE; - dst[result+1] = (byte_t) nn; - } - result += 2; - continue; - } - - /* unknown => space */ - if (dst) - dst[result] = 0x20; - result += 1; - } - return result; -} - - -int -ucs2_to_gsm7( cbytes_t ucs2, int ucs2len, bytes_t dst, int offset ) -{ - const unsigned char* ucs2end = ucs2 + ucs2len*2; - BWriterRec writer[1]; - - bwriter_init( writer, dst, offset ); - while ( ucs2 < ucs2end ) { - int c = *ucs2++; - int nn; - - for (nn = 0; nn < 128; nn++) { - if ( gsm7bits_to_unicode[nn] == c ) { - bwriter_add7( writer, nn ); - goto NextUnicode; - } - } - for (nn = 0; nn < 128; nn++) { - if ( gsm7bits_extend_to_unicode[nn] == c ) { - bwriter_add7( writer, GSM_7BITS_ESCAPE ); - bwriter_add7( writer, nn ); - goto NextUnicode; - } - } - - /* unknown */ - bwriter_add7( writer, 0x20 ); - - NextUnicode: - ; - } - return bwriter_done( writer ); -} - - -int -ucs2_to_gsm8( cbytes_t ucs2, int ucs2len, bytes_t dst ) -{ - const unsigned char* ucs2end = ucs2 + ucs2len*2; - bytes_t dst0 = dst; - - while ( ucs2 < ucs2end ) { - int c = *ucs2++; - int nn; - - for (nn = 0; nn < 128; nn++) { - if ( gsm7bits_to_unicode[nn] == c ) { - *dst++ = (byte_t)nn; - goto NextUnicode; - } - } - for (nn = 0; nn < 128; nn++) { - if ( gsm7bits_extend_to_unicode[nn] == c ) { - dst[0] = (byte_t) GSM_7BITS_ESCAPE; - dst[1] = (byte_t) nn; - dst += 2; - goto NextUnicode; - } - } - - /* unknown */ - *dst++ = 0x20; - - NextUnicode: - ; - } - return (dst - dst0); -} - -int -gsm_bcdnum_to_ascii( cbytes_t bcd, int count, bytes_t dst ) -{ - int result = 0; - int shift = 0; - - while (count > 0) { - int c = (bcd[0] >> shift) & 0xf; - - if (c == 15 && count == 1) /* ignore trailing 0xf */ - break; - - if (c >= 14) - c = 0; - - if (dst) dst[result] = "0123456789*#,N"[c]; - result += 1; - - shift += 4; - if (shift == 8) { - shift = 0; - bcd += 1; - } - } - return result; -} - - -int -gsm_bcdnum_from_ascii( cbytes_t ascii, int asciilen, bytes_t dst ) -{ - cbytes_t end = ascii + asciilen; - int result = 0; - int phase = 0x01; - - while (ascii < end) { - int c = *ascii++; - - if (c == '*') - c = 10; - else if (c == '#') - c = 11; - else if (c == ',') - c = 12; - else if (c == 'N') - c = 13; - else { - c -= '0'; - if ((unsigned)c >= 10U) - return -1; - } - phase = (phase << 4) | c; - result += 1; - if (phase & 0x100) { - if (dst) dst[result/2] = (byte_t) phase; - phase = 0x01; - } - } - - if (result & 1) { - if (dst) dst[result/2] = (byte_t)(phase | 0xf0); - } - return result; -} - -/** ADN: Abbreviated Dialing Number - **/ - -#define ADN_FOOTER_SIZE 14 -#define ADN_OFFSET_NUMBER_LENGTH 0 -#define ADN_OFFSET_TON_NPI 1 -#define ADN_OFFSET_NUMBER_START 2 -#define ADN_OFFSET_NUMBER_END 11 -#define ADN_OFFSET_CAPABILITY_ID 12 -#define ADN_OFFSET_EXTENSION_ID 13 - -/* see 10.5.1 of 3GPP 51.011 */ -static int -sim_adn_alpha_to_utf8( cbytes_t alpha, cbytes_t end, bytes_t dst ) -{ - int result = 0; - int c, is_ucs2 = 0; - - /* ignore trailing 0xff */ - while (alpha < end && end[-1] == 0xff) - end--; - - if (alpha >= end) - return 0; - - if (alpha[0] == 0x80) { /* UCS/2 source encoding */ - int count, len; - - alpha += 1; - result = ucs2_to_utf8( alpha, (end-alpha)/2, dst ); - } - else - { - int is_ucs2 = 0; - int len = 0, base = 0; - - if (alpha+3 <= end && alpha[0] == 0x81) { - is_ucs2 = 1; - len = alpha[1]; - base = alpha[2] << 7; - alpha += 3; - if (len > end-alpha) - len = end-alpha; - } else if (alpha+4 <= end && alpha[0] == 0x82) { - is_ucs2 = 1; - len = alpha[1]; - base = (alpha[2] << 8) | alpha[3]; - alpha += 4; - if (len > end-alpha) - len = end-alpha; - } - - if (is_ucs2) { - end = alpha + len; - while (alpha < end) { - int c = alpha[0]; - if (c >= 0x80) { - result += utf8_write(dst, result, base + (c & 0x7f)); - alpha += 1; - } else { - /* GSM character set */ - int count; - for (count = 0; alpha+count < end && alpha[count] < 128; count++) - ; - result += utf8_from_gsm8(alpha, count, (dst ? dst+result : NULL)); - alpha += count; - } - } - } - else { - result = utf8_from_gsm8(alpha, end-alpha, dst); - } - } - return result; -} - -static int -sim_adn_alpha_from_utf8( cbytes_t utf8, int utf8len, bytes_t dst ) -{ - int result = 0; - - if (utf8_check_gsm7(utf8, utf8len)) { - /* GSM 7-bit compatible, encode directly as 8-bit string */ - result = utf8_to_gsm8(utf8, utf8len, dst); - } else { - /* otherwise, simply try UCS-2 encoding, nothing more serious at the moment */ - if (dst) { - dst[0] = 0x80; - } - result = 1 + utf8_to_ucs2(utf8, utf8len, dst ? (dst+1) : NULL)*2; - } - return result; -} - -int -sim_adn_record_from_bytes( SimAdnRecord rec, cbytes_t data, int len ) -{ - cbytes_t end = data + len; - cbytes_t footer = end - ADN_FOOTER_SIZE; - int num_len; - - rec->adn.alpha[0] = 0; - rec->adn.number[0] = 0; - rec->ext_record = 0xff; - - if (len < ADN_FOOTER_SIZE) - return -1; - - /* alpha is optional */ - if (len > ADN_FOOTER_SIZE) { - cbytes_t dataend = data + len - ADN_FOOTER_SIZE; - int count = sim_adn_alpha_to_utf8(data, dataend, NULL); - - if (count > sizeof(rec->adn.alpha)-1) /* too long */ - return -1; - - sim_adn_alpha_to_utf8(data, dataend, rec->adn.alpha); - rec->adn.alpha[count] = 0; - } - - num_len = footer[ADN_OFFSET_NUMBER_LENGTH]; - if (num_len > 11) - return -1; - - /* decode TON and number to ASCII, NOTE: this is lossy !! */ - { - int ton = footer[ADN_OFFSET_TON_NPI]; - bytes_t number = rec->adn.number; - int len = sizeof(rec->adn.number)-1; - int count; - - if (ton != 0x81 && ton != 0x91) - return -1; - - if (ton == 0x91) { - *number++ = '+'; - len -= 1; - } - - count = gsm_bcdnum_to_ascii( footer + ADN_OFFSET_NUMBER_START, - num_len*2, number ); - number[count] = 0; - } - return 0; -} - -int -sim_adn_record_to_bytes( SimAdnRecord rec, bytes_t data, int datalen ) -{ - bytes_t end = data + datalen; - bytes_t footer = end - ADN_FOOTER_SIZE; - int ton = 0x81; - cbytes_t number = rec->adn.number; - int len; - - if (number[0] == '+') { - ton = 0x91; - number += 1; - } - footer[0] = (strlen(number)+1)/2 + 1; - return 0; -} diff --git a/gsm.h b/gsm.h deleted file mode 100644 index 4076308..0000000 --- a/gsm.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef _android_gsm_h -#define _android_gsm_h - -/** USEFUL TYPES - **/ - -typedef unsigned char byte_t; -typedef byte_t* bytes_t; -typedef const byte_t* cbytes_t; - -/** BCD - **/ - -/* convert a 8-bit value into the corresponding nibble-bcd byte */ -extern byte_t gsm_int_to_bcdi( int value ); - -/* convert a nibble-bcd byte into an int, invalid nibbles are silently converted to 0 */ -extern int gsm_int_from_bcdi( byte_t value ); - -/** HEX - **/ - -/* convert a hex string into a byte string, assumes 'dst' is properly sized, and hexlen is even */ -extern void gsm_hex_to_bytes ( cbytes_t hex, int hexlen, bytes_t dst ); - -/* convert a byte string into a hex string, assumes 'hex' is properly sized */ -extern void gsm_hex_from_bytes( char* hex, cbytes_t src, int srclen ); - -/* convert a hexchar to an int, returns -1 on error */ -extern int gsm_hexchar_to_int( char c ); - -/* convert a hexchar to an int, returns 0 on error */ -extern int gsm_hexchar_to_int0( char c ); - -/* convert a 2-char hex value into an int, returns -1 on error */ -extern int gsm_hex2_to_byte( const char* hex ); - -/* convert a 2-char hex value into an int, returns 0 on error */ -extern int gsm_hex2_to_byte0( const char* hex ); - -/* convert a 4-char hex value into an int, returns -1 on error */ -extern int gsm_hex4_to_short( const char* hex ); - -/* convert a 4-char hex value into an int, returns 0 on error */ -extern int gsm_hex4_to_short0( const char* hex ); - -/* write a byte to a 2-byte hex string */ -extern void gsm_hex_from_byte( char* hex, int val ); - -extern void gsm_hex_from_short( char* hex, int val ); - -/** UTF-8 and GSM Alphabet - **/ - -/* check that a given utf8 string is well-formed, returns 1 on success, 0 otherwise */ -extern int utf8_check( cbytes_t utf8, int utf8len ); - -/* check that all characters in a given utf8 string can be encoded into the GSM alphabet. - returns 1 if TRUE, 0 otherwise */ -extern int utf8_check_gsm7( cbytes_t utf8, int utf8len ); - -/* convert a utf-8 string into a GSM septet string, assumes 'dst' is NULL or is properly sized, - and that all characters are representable. 'offset' is the starting bit offset in 'dst'. - non-representable characters are replaced by spaces. - returns the number of septets, */ -extern int utf8_to_gsm7( cbytes_t utf8, int utf8len, bytes_t dst, int offset ); - -/* convert a utf8 string into an array of 8-bit unpacked GSM septets, - * assumes 'dst' is NULL or is properly sized, returns the number of GSM bytes */ -extern int utf8_to_gsm8( cbytes_t utf8, int utf8len, bytes_t dst ); - -/* convert a GSM septets string into a utf-8 byte string. assumes that 'utf8' is NULL or properly - sized. 'offset' is the starting bit offset in 'src', 'count' is the number of input septets. - return the number of utf8 bytes. */ -extern int utf8_from_gsm7( cbytes_t src, int offset, int count, bytes_t utf8 ); - -/* convert an unpacked 8-bit GSM septets string into a utf-8 byte string. assumes that 'utf8' - is NULL or properly sized. 'count' is the number of input bytes. - returns the number of utf8 bytes */ -extern int utf8_from_gsm8( cbytes_t src, int count, bytes_t utf8 ); - - -/** UCS-2 and GSM Alphabet - ** - ** Note that here, 'ucs2' really refers to non-aligned UCS2-BE, as used by the GSM standard - **/ - -/* check that all characters in a given ucs2 string can be encoded into the GSM alphabet. - returns 1 if TRUE, 0 otherwise */ -extern int ucs2_check_gsm7( cbytes_t ucs2, int ucs2len ); - -/* convert a ucs2 string into a GSM septet string, assumes 'dst' is NULL or properly sized, - 'offset' is the starting bit offset in 'dst'. non-representable characters are replaced - by spaces. returns the number of septets */ -extern int ucs2_to_gsm7( cbytes_t ucs2, int ucs2len, bytes_t dst, int offset ); - -/* convert a ucs2 string into a GSM septet string, assumes 'dst' is NULL or properly sized, - non-representable characters are replaced by spaces. returns the number of bytes */ -extern int ucs2_to_gsm8( cbytes_t ucs2, int ucs2len, bytes_t dst ); - -/* convert a GSM septets string into a ucs2 string. assumes that 'ucs2' is NULL or - properly sized. 'offset' is the starting bit offset in 'src', 'count' is the number - of input septets. return the number of ucs2 characters (not bytes) */ -extern int ucs2_from_gsm7( bytes_t ucs2, cbytes_t src, int offset, int count ); - -/* convert an 8-bit unpacked GSM septets string into a ucs2 string. assumes that 'ucs2' - is NULL or properly sized. 'count' is the number of input septets. return the number - of ucs2 characters (not bytes) */ -extern int ucs2_from_gsm8( bytes_t ucs2, cbytes_t src, int count ); - - -/** UCS2 to/from UTF8 - **/ - -/* convert a ucs2 string into a utf8 byte string, assumes 'utf8' NULL or properly sized. - returns the number of utf8 bytes*/ -extern int ucs2_to_utf8( cbytes_t ucs2, int ucs2len, bytes_t utf8 ); - -/* convert a utf8 byte string into a ucs2 string, assumes 'ucs2' NULL or properly sized. - returns the number of ucs2 chars */ -extern int utf8_to_ucs2( cbytes_t utf8, int utf8len, bytes_t ucs2 ); - -/* try to skip a given number of characters in a utf-8 byte string, return new position */ -extern cbytes_t utf8_skip( cbytes_t utf8, cbytes_t utf8end, int count); - -/** Dial Numbers: TON byte + 'count' bcd numbers - **/ - -/* convert a bcd-coded GSM dial number into an ASCII string (not zero-terminated) - assumes 'dst' is NULL or properly sized, returns 0 in case of success, -1 in case of error. - 'num_digits' is the number of digits, not input bytes. a trailing 0xf0 is ignored automatically - return the number of ASCII chars */ -extern int gsm_bcdnum_to_ascii ( cbytes_t bcd, int num_digits, bytes_t dst ); - -/* convert an ASCII dial-number into a bcd-coded string, returns the number of 4-bit nibbles written, */ -extern int gsm_bcdnum_from_ascii( cbytes_t ascii, int asciilen, bytes_t dst ); - -/** ADN: Abbreviated Dialing Numbers - **/ -#define SIM_ADN_MAX_ALPHA 20 /* maximum number of characters in ADN alpha tag */ -#define SIM_ADN_MAX_NUMBER 20 /* maximum digits in ADN number */ - -typedef struct { - byte_t alpha [ SIM_ADN_MAX_ALPHA*3+1 ]; /* alpha tag in zero-terminated utf-8 */ - char number[ SIM_ADN_MAX_NUMBER+1 ]; /* dialing number in zero-terminated ASCII */ -} -SimAdnRec, *SimAdn; - -typedef struct { - SimAdnRec adn; - byte_t ext_record; /* 0 or 0xFF means no extension */ -} -SimAdnRecordRec, *SimAdnRecord; - -extern int sim_adn_record_from_bytes( SimAdnRecord rec, cbytes_t data, int datalen ); -extern int sim_adn_record_to_bytes ( SimAdnRecord rec, bytes_t data, int datalen ); - -/** ROPES - **/ - -typedef struct { - bytes_t data; - int max; - int pos; - int error; - unsigned char data0[16]; -} GsmRopeRec, *GsmRope; - -extern void gsm_rope_init( GsmRope rope ); -extern void gsm_rope_init_alloc( GsmRope rope, int alloc ); -extern int gsm_rope_done( GsmRope rope ); -extern bytes_t gsm_rope_done_acquire( GsmRope rope, int *psize ); -extern void gsm_rope_add_c( GsmRope rope, char c ); -extern void gsm_rope_add( GsmRope rope, const void* str, int len ); -extern void* gsm_rope_reserve( GsmRope rope, int len ); - -#endif /* _android_gsm_h */ diff --git a/htcgeneric-ril.c b/htcgeneric-ril.c deleted file mode 100644 index 628428d..0000000 --- a/htcgeneric-ril.c +++ /dev/null @@ -1,4759 +0,0 @@ -/* //device/system/htcgeneric-ril/htcgeneric-ril.c - ** - ** Copyright 2006, The Android Open Source Project - ** - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "atchannel.h" -#include "at_tok.h" -#include "misc.h" -#include "gsm.h" -#include -#include -#include -#include - -#define LOG_NDEBUG 0 -#define LOG_TAG "RIL" -#include - -#define MAX_AT_RESPONSE 0x1000 - -#define RIL_REQUEST_SEND_SMS_EXTENDED 512 - -/* pathname returned from RIL_REQUEST_SETUP_DATA_CALL / RIL_REQUEST_SETUP_DEFAULT_PDP */ -#define PPP_TTY_PATH "ppp0" - -#ifdef USE_TI_COMMANDS - -// Enable workaround for bug in (TI-based) HTC stack -// 1) Make incoming call, do not answer -// 2) Hangup remote end -// Expected: call should disappear from CLCC line -// Actual: Call shows as "ACTIVE" before disappearing -#define WORKAROUND_ERRONEOUS_ANSWER 1 - -// Some varients of the TI stack do not support the +CGEV unsolicited -// response. However, they seem to send an unsolicited +CME ERROR: 150 -#define WORKAROUND_FAKE_CGEV 1 -#endif - -typedef enum { - SIM_ABSENT = 0, - SIM_NOT_READY = 1, - SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */ - SIM_PIN = 3, - SIM_PUK = 4, - SIM_NETWORK_PERSONALIZATION = 5 -} SIM_Status; - -static void onRequest (int request, void *data, size_t datalen, RIL_Token t); -static RIL_RadioState currentState(); -static int onSupports (int requestCode); -static void onCancel (RIL_Token t); -static const char *getVersion(); -static int isRadioOn(); -static SIM_Status getSIMStatus(); -static int getCardStatus(RIL_CardStatus **pp_card_status); -static void freeCardStatus(RIL_CardStatus *p_card_status); -static void onDataCallListChanged(void *param); -static int killConn(char * cid); - - -extern const char * requestToString(int request); - -/*** Static Variables ***/ -static const RIL_RadioFunctions s_callbacks = { - RIL_VERSION, - onRequest, - currentState, - onSupports, - onCancel, - getVersion -}; - -#ifdef RIL_SHLIB -static const struct RIL_Env *s_rilenv; - -#define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen) -#define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c) -#define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c) -#endif - -static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE; - -static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER; - -static int slow_sim=0; -static int s_port = -1; -static int cdma_north_american_dialing = 0; -static const char * s_device_path = NULL; -static int s_device_socket = 0; - -/* trigger change to this with s_state_cond */ -static int s_closed = 0; - -static int sFD; /* file desc of AT channel */ -static char sATBuffer[MAX_AT_RESPONSE+1]; -static char *sATBufferCur = NULL; - /* Higher layers expect a NITZ string in this format: - * 08/10/28,19:08:37-20,1 (yy/mm/dd,hh:mm:ss(+/-)tz,dst) - */ -static char sNITZtime[sizeof("08/10/28,19:08:37-20,1")+4]; - -static const struct timeval TIMEVAL_SIMPOLL = {1,0}; -static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000}; -static const struct timeval TIMEVAL_0 = {0,0}; - -#ifdef WORKAROUND_ERRONEOUS_ANSWER -// Max number of times we'll try to repoll when we think -// we have a AT+CLCC race condition -#define REPOLL_CALLS_COUNT_MAX 4 - -// Line index that was incoming or waiting at last poll, or -1 for none -static int s_incomingOrWaitingLine = -1; -// Number of times we've asked for a repoll of AT+CLCC -static int s_repollCallsCount = 0; -// Should we expect a call to be answered in the next CLCC? -static int s_expectAnswer = 0; -#endif /* WORKAROUND_ERRONEOUS_ANSWER */ - -static void pollSIMState (void *param); -static void setRadioState(RIL_RadioState newState); - -static int isgsm=0; -static int is_world_cdma=0; /* Will be set to 1 for world phones operating in CDMA mode (i.e. RhodiumW/RHOD400/RHOD500) */ -static char erisystem[50]; -static char *callwaiting_num; -static int countValidCalls=0; -static int signalStrength[2]; - -static void handle_cdma_ccwa (const char *s) -{ - int err; - char *line, *tmp; - - if (callwaiting_num) - { - free(callwaiting_num); - callwaiting_num = NULL; - } - line = tmp = strdup(s); - err = at_tok_start(&tmp); - if (err) - goto out; - err = at_tok_nextstr(&tmp, &callwaiting_num); - if (err) - goto out; - callwaiting_num = strdup(callwaiting_num); - LOGE("successfully set callwaiting_numn"); -out: - free(line); -} - -extern char** cdma_to_gsmpdu(const char *); -extern char* gsm_to_cdmapdu(const char *); -extern int hex2int(const char); - -static void HexStr_to_DecInt(char *strings, unsigned int *ints) -{ - int i = 0; - int j = strlen(strings); - int k = 0; - for(i = 0, k = 0; i < j; i += 2, k++) - { - printf("%d, %d\n", i, k); - if(strings[i] <= 57){ - *(ints + k) += (unsigned int)((strings[i] - 48) * 16); - } - else{ - *(ints+k) += (unsigned int)(((strings[i] - 97) + 10) * 16); - } - - if(strings[i+1] <= 57){ - *(ints+k) += (unsigned int)(strings[i+1] - 48); - } - else{ - *(ints+k) += (unsigned int)((strings[i+1] - 97) + 10); - } - } -} - -static int clccStateToRILState(int state, RIL_CallState *p_state) - -{ - switch(state) { - case 0: *p_state = RIL_CALL_ACTIVE; return 0; - case 1: *p_state = RIL_CALL_HOLDING; return 0; - case 2: *p_state = RIL_CALL_DIALING; return 0; - case 3: *p_state = RIL_CALL_ALERTING; return 0; - case 4: *p_state = RIL_CALL_INCOMING; return 0; - case 5: *p_state = RIL_CALL_WAITING; return 0; - default: return -1; - } -} - -static const char* networkStatusToRilString(int state) -{ - switch(state){ - case 0: return("unknown"); break; - case 1: return("available"); break; - case 2: return("current"); break; - case 3: return("forbidden"); break; - default: return NULL; - } -} - -// some phone functions are controlled by msm_proc_comm through /sys -void writesys(char *name, char *val) { - FILE *fout; - char filename[256]; - strcpy(filename,"/sys/class/vogue_hw/"); - strcat(filename,name); - fout=fopen(filename,"w"); - if(!fout) return; - fprintf(fout, "%s", val); - fclose(fout); -} -/** - * Note: directly modified line and has *p_call point directly into - * modified line - */ -static int callFromCLCCLine(char *line, RIL_Call *p_call) -{ - //+CLCC: 1,0,2,0,0,\"+18005551212\",145 - // index,isMT,state,mode,isMpty(,number,TOA)? - - int err; - int state; - int mode; - - err = at_tok_start(&line); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &(p_call->index)); - if (err < 0) goto error; - - err = at_tok_nextbool(&line, &(p_call->isMT)); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &state); - if (err < 0) goto error; - - err = clccStateToRILState(state, &(p_call->state)); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &mode); - if (err < 0) goto error; - - p_call->isVoice = (mode == 0); - - err = at_tok_nextbool(&line, &(p_call->isMpty)); - if (err < 0) goto error; - - if (at_tok_hasmore(&line)) { - err = at_tok_nextstr(&line, &(p_call->number)); - - /* tolerate null here */ - if (err < 0) return 0; - - // Some lame implementations return strings - // like "NOT AVAILABLE" in the CLCC line - if (p_call->number != NULL - && 0 == strspn(p_call->number, "+0123456789") - ) { - p_call->number = NULL; - } - - err = at_tok_nextint(&line, &p_call->toa); - if (err < 0) goto error; - } - - return 0; - -error: - LOGE("invalid CLCC line\n"); - return -1; -} - -//returns the call number of the active data call, or -1 if no active call -static int dataCallNum() -{ - int err; - ATResponse *p_response; - ATLine *p_cur; - int countCalls; - RIL_Call *p_call; - int i; - int callNumber = -1; - - if(currentState() != RADIO_STATE_SIM_READY){ - return -1; - } - - err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response); - - if (err != 0 || p_response->success == 0) { - return -1; - } - - /* count the calls */ - for (countCalls = 0, p_cur = p_response->p_intermediates - ; p_cur != NULL - ; p_cur = p_cur->p_next - ) { - countCalls++; - } - - p_call = (RIL_Call *)alloca(sizeof(RIL_Call)); - memset (p_call, 0, sizeof(RIL_Call)); - - for (i = 0, p_cur = p_response->p_intermediates - ; p_cur != NULL - ; p_cur = p_cur->p_next - ) { - err = callFromCLCCLine(p_cur->line, p_call); - - if (err != 0) { - continue; - } - - if(p_call[0].isVoice == 0) // only count data calls - { - callNumber = i; - } - } - return callNumber; -} - - -/** do post-AT+CFUN=1 initialization */ -static void onRadioPowerOn() -{ -#ifdef USE_TI_COMMANDS - /* Must be after CFUN=1 */ - /* TI specific -- notifications for CPHS things such */ - /* as CPHS message waiting indicator */ - - at_send_command("AT%CPHS=1", NULL); - - /* TI specific -- enable NITZ unsol notifs */ - at_send_command("AT%CTZV=1", NULL); -#endif - if(isgsm) - { - at_send_command("ATE0", NULL); - at_send_command("AT+CLIP=1", NULL); - at_send_command("AT+CLIR=0", NULL); - at_send_command("AT+CPPP=2", NULL); - at_send_command("AT+HTCNV=1,12,6", NULL); - - /*enable ENS mode, okay to fail */ -// at_send_command("AT+HTCENS=1", NULL); -// at_send_command("AT+HSDPA=1", NULL); - at_send_command("AT+HTCAGPS=5", NULL); - at_send_command("AT", NULL); - at_send_command("AT+ODEN=112", NULL); - at_send_command("AT+ODEN=911", NULL); -// at_send_command("AT+ALS=4294967295", NULL); - } - pollSIMState(NULL); -} - -/** do post- SIM ready initialization */ -static void onSIMReady() -{ - /* Common initialization commands */ - - /* Network registration */ - at_send_command("AT+COPS=0", NULL); - - if(isgsm) { - /* Preferred RAT - UMTS Dualmode */ -// at_send_command("AT+XRAT=1,2", NULL); - - //debug what type of sim is it? - at_send_command("AT+SIMTYPE", NULL); - - /* - * Always send SMS messages directly to the TE - * - * mode = 1 // discard when link is reserved (link should never be - * reserved) - * mt = 2 // most messages routed to TE - * bm = 2 // new cell BM's routed to TE - * ds = 1 // Status reports routed to TE - * bfr = 1 // flush buffer - */ - at_send_command("AT+CNMI=1,2,2,1,1", NULL); - - at_send_command("AT+CSCB=1", NULL); - - /* Enable +CGEV GPRS event notifications, but don't buffer */ -// at_send_command("AT+CGEREP=1,0", NULL); - - /* Enable NITZ reporting */ -// at_send_command("AT+CTZU=1", NULL); -// at_send_command("AT+CTZR=1", NULL); - at_send_command("AT+HTCCTZR=1", NULL); - - /* Enable unsolizited RSSI reporting */ - at_send_command("AT@HTCCSQ=1", NULL); - - at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL); - - - } else { - - at_send_command("AT+HTC_GPSONE=4", NULL); - at_send_command("AT+CLVL=102", NULL); - at_send_command("AT+CLVL=51", NULL); - } -} - -static void requestRadioPower(void *data, size_t datalen, RIL_Token t) -{ - int onOff; - - int err; - ATResponse *p_response = NULL; - - assert (datalen >= sizeof(int *)); - onOff = ((int *)data)[0]; - - if (onOff == 0 && sState != RADIO_STATE_OFF) { - if(isgsm || is_world_cdma) - err = at_send_command("AT+CFUN=0", &p_response); - else - err = at_send_command("AT+CFUN=66", &p_response); - if (err < 0 || p_response->success == 0) goto error; - setRadioState(RADIO_STATE_OFF); - } else if (onOff > 0 && sState == RADIO_STATE_OFF) { - err = at_send_command("AT+CFUN=1", &p_response); - if (err < 0|| p_response->success == 0) { - // Some stacks return an error when there is no SIM, - // but they really turn the RF portion on - // So, if we get an error, let's check to see if it - // turned on anyway - - if (isRadioOn() != 1) { - goto error; - } - } - setRadioState(RADIO_STATE_SIM_NOT_READY); - } - - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -error: - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestOrSendDataCallList(RIL_Token *t); - -static void onDataCallListChanged(void *param) -{ - requestOrSendDataCallList(NULL); -} - -static void requestDataCallList(void *data, size_t datalen, RIL_Token t) -{ - requestOrSendDataCallList(&t); -} - -static void requestOrSendDataCallList(RIL_Token *t) -{ - ATResponse *p_response; - ATLine *p_cur; - RIL_Data_Call_Response *responses; - int err; - char status[1]; - int fd; - int n = 0; - char *out; - - if (isgsm) { - err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response); - if (err != 0 || p_response->success == 0) { - if (t != NULL) - RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0); - else - RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, - NULL, 0); - return; - } - - for (p_cur = p_response->p_intermediates; p_cur != NULL; - p_cur = p_cur->p_next) - n++; - - responses = alloca(n * sizeof(RIL_Data_Call_Response)); - - int i; - for (i = 0; i < n; i++) { - responses[i].cid = -1; - responses[i].active = -1; - responses[i].type = ""; - responses[i].apn = ""; - responses[i].address = ""; - } - - RIL_Data_Call_Response *response = responses; - for (p_cur = p_response->p_intermediates; p_cur != NULL; - p_cur = p_cur->p_next) { - char *line = p_cur->line; - - err = at_tok_start(&line); - if (err < 0) - goto error; - - err = at_tok_nextint(&line, &response->cid); - if (err < 0) - goto error; - - err = at_tok_nextint(&line, &response->active); - if (err < 0) - goto error; - - response++; - } - - at_response_free(p_response); - - err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response); - if (err != 0 || p_response->success == 0) { - if (t != NULL) - RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0); - else - RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, - NULL, 0); - return; - } - - for (p_cur = p_response->p_intermediates; p_cur != NULL; - p_cur = p_cur->p_next) { - char *line = p_cur->line; - int cid; - char *type; - char *apn; - char *address; - - - err = at_tok_start(&line); - if (err < 0) - goto error; - - err = at_tok_nextint(&line, &cid); - if (err < 0) - goto error; - - for (i = 0; i < n; i++) { - if (responses[i].cid == cid) - break; - } - - if (i >= n) { - /* details for a context we didn't hear about in the last request */ - continue; - } - - err = at_tok_nextstr(&line, &out); - if (err < 0) - goto error; - - responses[i].type = alloca(strlen(out) + 1); - strcpy(responses[i].type, out); - - err = at_tok_nextstr(&line, &out); - if (err < 0) - goto error; - - responses[i].apn = alloca(strlen(out) + 1); - strcpy(responses[i].apn, out); - - err = at_tok_nextstr(&line, &out); - if (err < 0) - goto error; - - responses[i].address = alloca(strlen(out) + 1); - strcpy(responses[i].address, out); - } - - at_response_free(p_response); - - } else { - //CDMA - n = 1; - responses = alloca(sizeof(RIL_Data_Call_Response)); - - responses[0].cid = 1; - if (dataCallNum() >= 0) - responses[0].active = 1; - else - responses[0].active = 0; - responses[0].type = ""; - responses[0].apn = "internet"; - responses[0].address = ""; - } - - // make sure pppd is still running, invalidate datacall if it isn't - if ((fd = open("/etc/ppp/ppp-gprs.pid",O_RDONLY)) > 0) - { - close(fd); - } - else - { - responses[0].active = 0; - } - - if (t != NULL) - RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses, - n * sizeof(RIL_Data_Call_Response)); - else - RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, - responses, - n * sizeof(RIL_Data_Call_Response)); - - return; - -error: - if (t != NULL) - RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0); - else - RIL_onUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, - NULL, 0); - - at_response_free(p_response); -} - -static void requestBasebandVersion(void *data, size_t datalen, RIL_Token t) -{ - int err; - ATResponse *p_response = NULL; - char * response = NULL; - char* line = NULL; - - if (isgsm) { - err = at_send_command_singleline("AT+CGMM", "", &p_response); - if (err != 0) goto error; - - line = p_response->p_intermediates->line; - - response = (char *)alloca(sizeof(char *)); - - err = at_tok_nextstr(&line, &response); - if (err < 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(char *)); - at_response_free(p_response); - } else { - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - } - return; - -error: - at_response_free(p_response); - LOGE("ERROR: requestBasebandVersion failed\n"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - - -static void requestQueryNetworkSelectionMode( - void *data, size_t datalen, RIL_Token t) -{ - int err; - ATResponse *p_response = NULL; - int response = 0; - char *line; - - if(isgsm) { //this command conflicts with the network status command - err = at_send_command_singleline("AT+COPS?", "+COPS:", &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, &response); - - if (err < 0) { - goto error; - } - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int)); - at_response_free(p_response); - return; - -error: - at_response_free(p_response); - LOGE("requestQueryNetworkSelectionMode must never return error when radio is on"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestQueryAvailableNetworks(void *data, size_t datalen, RIL_Token t) -{ - /* We expect an answer on the following form: - +COPS: (2,"AT&T","AT&T","310410",0),(1,"T-Mobile ","TMO","310260",0) - */ - - int err, operators, i, skip, status; - ATResponse *p_response = NULL; - char * c_skip, *line, *p = NULL; - char ** response = NULL; - - err = at_send_command_singleline("AT+COPS=?", "+COPS:", &p_response); - - if (err != 0) goto error; - - line = p_response->p_intermediates->line; - - err = at_tok_start(&line); - if (err < 0) goto error; - - /* Count number of '(' in the +COPS response to get number of operators*/ - operators = 0; - for (p = line ; *p != '\0' ;p++) { - if (*p == '(') operators++; - } - - response = (char **)alloca(operators * 4 * sizeof(char *)); - - for (i = 0 ; i < operators ; i++ ) - { - err = at_tok_nextstr(&line, &c_skip); - if (err < 0) goto error; - if (strcmp(c_skip,"") == 0) - { - operators = i; - continue; - } - status = atoi(&c_skip[1]); - response[i*4+3] = (char*)networkStatusToRilString(status); - - err = at_tok_nextstr(&line, &(response[i*4+0])); - if (err < 0) goto error; - - err = at_tok_nextstr(&line, &(response[i*4+1])); - if (err < 0) goto error; - - err = at_tok_nextstr(&line, &(response[i*4+2])); - if (err < 0) goto error; - - err = at_tok_nextstr(&line, &c_skip); - - if (err < 0) goto error; - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, response, (operators * 4 * sizeof(char *))); - at_response_free(p_response); - return; - -error: - at_response_free(p_response); - LOGE("ERROR - requestQueryAvailableNetworks() failed"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestGetPreferredNetworkType(void *data, size_t datalen, RIL_Token t) -{ - int err; - ATResponse *p_response = NULL; - int response = 0; - char *line; - - if(isgsm) - { - err = at_send_command_singleline("AT+CGAATT?", "+CGAATT:", &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; - } - - // Get third int in response - err = at_tok_nextint(&line, &response); - if (err < 0) { - goto error; - } - err = at_tok_nextint(&line, &response); - if (err < 0) { - goto error; - } - err = at_tok_nextint(&line, &response); - if (err < 0) { - goto error; - } - RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int)); - at_response_free(p_response); - return; - } - LOGE("ERROR: requestGetPreferredNetworkType() failed - modem does not support command\n"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - return; -error: - at_response_free(p_response); - LOGE("ERROR: requestGetPreferredNetworkType() failed\n"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestSetPreferredNetworkType(void *data, size_t datalen, RIL_Token t) -{ - int err, rat; - ATResponse *p_response = NULL; - char * cmd = NULL; - const char *at_rat = NULL; - - if(isgsm) - { - assert (datalen >= sizeof(int *)); - rat = ((int *)data)[0]; - -#ifdef USE_IDCC_MODEM - switch (rat) - { - case 0: at_rat = "1,2"; break;/* Dual Mode - WCDMA preferred*/ - case 1: at_rat = "0"; break; /* GSM only */ - case 2: at_rat = "2"; break; /* WCDMA only */ - } - - /* Need to unregister from NW before changing preferred RAT */ - err = at_send_command("AT+COPS=2", NULL); - if (err < 0) goto error; - - asprintf(&cmd, "AT+XRAT=%s", at_rat); -#else - LOGD("In requestSetPreferredNetworkType RAPH"); - switch (rat) { - case 0: at_rat = "2,1,0"; break;/* Dual Mode - WCDMA preferred*/ - case 1: at_rat = "2,1,1"; break; /* GSM only */ - case 2: at_rat = "2,1,2"; break; /* WCDMA only */ - } - - /* For some reason, without the bandset command, the CGAATT - one fails. [mdrobnak] */ - err = at_send_command("AT+BANDSET=0", NULL); - if (err < 0) goto error; - - asprintf(&cmd, "AT+CGAATT=%s", at_rat); - -#endif /* USE_IDCC_MODEM */ - err = at_send_command(cmd, &p_response); - free(cmd); - - if (err < 0|| p_response->success == 0) { - goto error; - } - - /* Register on the NW again */ - err = at_send_command("AT+COPS=0", NULL); - if (err < 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, sizeof(int)); - at_response_free(p_response); - return; - } - LOGE("ERROR: requestSetPreferredNetworkType() failed - command not supported by modem\n"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - return; -error: - at_response_free(p_response); - LOGE("ERROR: requestSetPreferredNetworkType() failed\n"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - - -static void requestQueryFacilityLock(void *data, size_t datalen, RIL_Token t) -{ - int err, rat, response; - ATResponse *p_response = NULL; - char * cmd = NULL; - char * line = NULL; - char * facility_string = NULL; - char * facility_password = NULL; - char * facility_class = NULL; - - LOGD("FACILITY"); - assert (datalen >= (3 * sizeof(char **))); - - facility_string = ((char **)data)[0]; - facility_password = ((char **)data)[1]; - facility_class = ((char **)data)[2]; - - - asprintf(&cmd, "AT+CLCK=\"%s\",2,\"%s\",%s", facility_string, facility_password, facility_class); - err = at_send_command_singleline(cmd,"+CLCK:", &p_response); - free(cmd); - 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, &response); - - if (err < 0) { - goto error; - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int)); - at_response_free(p_response); - return; - -error: - at_response_free(p_response); - LOGE("ERROR: requestQueryFacilityLock() failed\n"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void sendCallStateChanged(void *param) -{ - RIL_onUnsolicitedResponse ( - RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, - NULL, 0); -} - -static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t) -{ - int err,fd; - ATResponse *p_response; - ATLine *p_cur; - int countCalls; - RIL_Call *p_calls; - RIL_Call **pp_calls; - int i; - char status[1]; - int needRepoll = 0; - char *l_callwaiting_num=NULL; - -#ifdef WORKAROUND_ERRONEOUS_ANSWER - int prevIncomingOrWaitingLine; - - prevIncomingOrWaitingLine = s_incomingOrWaitingLine; - s_incomingOrWaitingLine = -1; -#endif /*WORKAROUND_ERRONEOUS_ANSWER*/ - - if(currentState() != RADIO_STATE_SIM_READY){ - /* Might be waiting for SIM PIN */ - RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0); - } - - err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response); - - if (err != 0 || p_response->success == 0) { - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - return; - } - - /* count the calls */ - for (countCalls = 0, p_cur = p_response->p_intermediates - ; p_cur != NULL - ; p_cur = p_cur->p_next - ) { - countCalls++; - } - - if (callwaiting_num) { - /* This is not thread-safe. Boo. */ - l_callwaiting_num = callwaiting_num; - callwaiting_num = NULL; - countCalls++; - } - - /* yes, there's an array of pointers and then an array of structures */ - - pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *)); - p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call)); - memset (p_calls, 0, countCalls * sizeof(RIL_Call)); - - /* init the pointer array */ - for(i = 0; i < countCalls ; i++) { - pp_calls[i] = &(p_calls[i]); - } - - for (countValidCalls = 0, p_cur = p_response->p_intermediates - ; p_cur != NULL - ; p_cur = p_cur->p_next - ) { - err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls); - - if (err != 0) { - continue; - } - -#ifdef WORKAROUND_ERRONEOUS_ANSWER - if (p_calls[countValidCalls].state == RIL_CALL_INCOMING - || p_calls[countValidCalls].state == RIL_CALL_WAITING - ) { - s_incomingOrWaitingLine = p_calls[countValidCalls].index; - } -#endif /*WORKAROUND_ERRONEOUS_ANSWER*/ - - if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE - && p_calls[countValidCalls].state != RIL_CALL_HOLDING - ) { - needRepoll = 1; - } - if(p_calls[countValidCalls].isVoice) // only count voice calls - countValidCalls++; - } - - if (l_callwaiting_num) { - char fake_clcc[64]; - int index = p_calls[countValidCalls-1].index+1; - - /* Try not to use an index greater than 9 */ - if (index > 9) { - int i; - - for (i=countValidCalls-2; i >= 0; i++) { - if (p_calls[i].index < 9) { - index = p_calls[i].index+1; - break; - } - } - } - - snprintf(fake_clcc, 64, "+CLCC: %d,0,5,0,0,\"%s\",129", - index, l_callwaiting_num); - free(l_callwaiting_num); - err = callFromCLCCLine(fake_clcc, p_calls + countValidCalls); - if (err == 0) { - countValidCalls++; - } - } - -#ifdef WORKAROUND_ERRONEOUS_ANSWER - // Basically: - // A call was incoming or waiting - // Now it's marked as active - // But we never answered it - // - // This is probably a bug, and the call will probably - // disappear from the call list in the next poll - if (prevIncomingOrWaitingLine >= 0 - && s_incomingOrWaitingLine < 0 - && s_expectAnswer == 0 - ) { - for (i = 0; i < countValidCalls ; i++) { - - if (p_calls[i].index == prevIncomingOrWaitingLine - && p_calls[i].state == RIL_CALL_ACTIVE - && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX - ) { - LOGI( - "Hit WORKAROUND_ERRONOUS_ANSWER case." - " Repoll count: %d\n", s_repollCallsCount); - s_repollCallsCount++; - goto error; - } - } - } - - s_expectAnswer = 0; - s_repollCallsCount = 0; -#endif /*WORKAROUND_ERRONEOUS_ANSWER*/ - LOGI("Calls=%d,Valid=%d\n",countCalls,countValidCalls); - if(countValidCalls==0) { // close audio if no voice calls. - LOGI("Audio Close\n"); - writesys("audio","5"); - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls, - countValidCalls * sizeof (RIL_Call *)); - - at_response_free(p_response); - -#ifdef POLL_CALL_STATE - if (countValidCalls) // We don't seem to get a "NO CARRIER" message from - // smd, so we're forced to poll until the call ends. -#else - if (needRepoll) -#endif - { - RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL); - } - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); -} - -static void requestDial(void *data, size_t datalen, RIL_Token t) -{ - RIL_Dial *p_dial; - char *cmd; - const char *clir; - int ret; - - p_dial = (RIL_Dial *)data; - - switch (p_dial->clir) { - case 1: clir = "I"; break; /*invocation*/ - case 2: clir = "i"; break; /*suppression*/ - default: - case 0: clir = ""; break; /*subscription default*/ - } - writesys("audio","2"); - if(cdma_north_american_dialing && strncmp(p_dial->address, "+1", 2)==0) - asprintf(&cmd, "ATD%s%s;", p_dial->address+1, clir); - else - asprintf(&cmd, "ATD%s%s;", p_dial->address, clir); - - ret = at_send_command(cmd, NULL); - - free(cmd); - - /* success or failure is ignored by the upper layer here. - it will call GET_CURRENT_CALLS and determine success that way */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t) -{ - RIL_SMS_WriteArgs *p_args; - char *cmd; - int length; - int err; - ATResponse *p_response = NULL; - - if(isgsm) { - - p_args = (RIL_SMS_WriteArgs *)data; - - length = strlen(p_args->pdu)/2; - asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status); - - err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response); - - free(cmd); - - if (err != 0 || p_response->success == 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - at_response_free(p_response); - } else { - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - } - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); -} - -static void requestHangup(void *data, size_t datalen, RIL_Token t) -{ - int *p_line; - - int ret; - char *cmd; - - p_line = (int *)data; - - // 3GPP 22.030 6.5.5 - // "Releases a specific active call X" - asprintf(&cmd, "AT+CHLD=1%d", p_line[0]); - - ret = at_send_command(cmd, NULL); - - free(cmd); - // writesys("audio","5"); - - /* success or failure is ignored by the upper layer here. - it will call GET_CURRENT_CALLS and determine success that way */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestSignalStrength(void *data, size_t datalen, RIL_Token t) -{ - ATResponse *p_response = NULL; - int err; - int response[2]; - char *line; - -#if 0 /* Just rely on unsolicited reports */ - if(signalStrength[0] == 0 && signalStrength[1] == 0) { - if(isgsm) - err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response); - else - err = at_send_command_singleline("AT+HTC_CSQ", "+HTC_CSQ:", &p_response); - - if (err < 0 || p_response->success == 0) { - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - goto error; - } - - line = p_response->p_intermediates->line; - - err = at_tok_start(&line); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &(response[0])); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &(response[1])); - if (err < 0) goto error; - if(!isgsm) { - response[0]*=2; - response[1]=99; - } - signalStrength[0] = response[0]; - signalStrength[1] = response[1]; - at_response_free(p_response); - - } else { - LOGD("Sending stored CSQ values to RIL"); - response[0] = signalStrength[0]; - response[1] = signalStrength[1]; - } -#endif - response[0] = signalStrength[0]; - response[1] = signalStrength[1]; - RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); - return; - -error: - LOGE("requestSignalStrength must never return an error when radio is on"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); -} - -static void requestDtmfStart(void *data, size_t datalen, RIL_Token t) -{ - int err; - char *cmd; - char c; - - assert (datalen >= sizeof(char *)); - - c = ((char *)data)[0]; - at_send_command("AT+CMUT=1", NULL); - asprintf(&cmd, "AT+VTS=%c", (int)c); - if(c=='*') - at_send_command("AT+WFSH", NULL); //FIXME: what is this for??? send flash? doesn't make sense - - err = at_send_command(cmd, NULL); - free(cmd); - - if (err != 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -error: - LOGE("ERROR: requestDtmfStart failed"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - -} - -static void requestDtmfStop(void *data, size_t datalen, RIL_Token t) -{ - int err; - - /* Send a command to cancel the DTMF tone*/ - err = at_send_command("AT", NULL); - if (err != 0) goto error; - err = at_send_command("AT+CMUT=0", NULL); - if (err != 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -error: - LOGE("ERROR: requestDtmfStop failed"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - -} - -static void requestSetMute(void *data, size_t datalen, RIL_Token t) -{ - int err; - char *cmd; - - assert (datalen >= sizeof(int *)); - - asprintf(&cmd, "AT+CMUT=%d", ((int*)data)[0]); - - err = at_send_command(cmd, NULL); - free(cmd); - - if (err != 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -error: - LOGE("ERROR: requestSetMute failed"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - -} - -static void requestGetMute(void *data, size_t datalen, RIL_Token t) -{ - int err; - ATResponse *p_response = NULL; - int response[1]; - char *line; - - if(!isgsm) { - err = at_send_command_singleline("AT+CMUT?", "+CMUT:", &p_response); - } else { - err = at_send_command_singleline("AT+MUT", "+CMUT:", &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, &response[0]); - if (err < 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(char*)); - at_response_free(p_response); - - return; - -error: - LOGE("ERROR: requestGetMute failed"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); -} - -static void requestScreenState(void *data, size_t datalen, RIL_Token t) -{ - int err, screenState; - - assert (datalen >= sizeof(int *)); - screenState = ((int*)data)[0]; - - if(screenState == 1) - { - if (isgsm) { - /* - if (ppt) - "AT+ENCSQ=1;\r" - else - "AT+ENCSQ=1;+CREG=2\r" - - requestRegistrationState - - "AT+HTCCTZR=1\r" - "AT@HTCPDPFD=0\r" - */ - /* Screen is on - be sure to enable all unsolicited notifications again */ -/* err = at_send_command("AT+CREG=2", NULL); - if (err < 0) goto error; - err = at_send_command("AT+CGREG=2", NULL); - if (err < 0) goto error; - err = at_send_command("AT+CGEREP=1,0", NULL); - if (err < 0) goto error; - err = at_send_command("AT@HTCPDPFD=0", NULL); - if (err < 0) goto error; - err = at_send_command("AT+ENCSQ=1",NULL); - if (err < 0) goto error; - err = at_send_command("AT@HTCCSQ=1", NULL); - if (err < 0) goto error;*/ - - err = at_send_command("AT+ENCSQ=1;+CREG=2", NULL); - if (err < 0) goto error; - err = at_send_command("AT+HTCCTZR=1", NULL); - if (err < 0) goto error; - err = at_send_command("AT@HTCPDPFD=0", NULL); - if (err < 0) goto error; - } else { - - } - } else if (screenState == 0) { - if (isgsm) { - /* - "AT+HTCPDPIDLE\r" - if (ppt) - "AT+ENCSQ=0;\r" - else - "AT+ENCSQ=0;+CREG=1\r" - "AT+HTCCTZR=2\r" - "AT@HTCPDPFD=1" - */ - /* Screen is off - disable all unsolicited notifications */ - /*err = at_send_command("AT+CREG=0", NULL); - if (err < 0) goto error; - err = at_send_command("AT+CGREG=0", NULL); - if (err < 0) goto error; - err = at_send_command("AT+CGEREP=0,0", NULL); - if (err < 0) goto error; - err = at_send_command("AT@HTCPDPFD=1", NULL); - if (err < 0) goto error; - err = at_send_command("AT+ENCSQ=0",NULL); - if (err < 0) goto error; - err = at_send_command("AT@HTCCSQ=0", NULL); - if (err < 0) goto error;*/ - - err = at_send_command("AT+HTCPDPIDLE", NULL); - if (err < 0) goto error; - err = at_send_command("AT+ENCSQ=0;+CREG=1", NULL); - if (err < 0) goto error; - err = at_send_command("AT+HTCCTZR=2", NULL); - if (err < 0) goto error; - err = at_send_command("AT@HTCPDPFD=1", NULL); - if (err < 0) goto error; - } else { - - } - } else { - /* Not a defined value - error */ - goto error; - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -error: - LOGE("ERROR: requestScreenState failed"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestRegistrationState(int request, void *data, - size_t datalen, RIL_Token t) -{ - int err; - int response[4]; - char * responseStr[4]; - ATResponse *p_response = NULL; - const char *cmd; - const char *prefix; - char *line, *p; - int commas; - int skip; - int i; - int count = 4; - int fd; - int dataCall = 0; - char status[1]; - - response[0]=1; - response[1]=-1; - response[2]=-1; - response[3]=1; - - if(isgsm) { - if (request == RIL_REQUEST_REGISTRATION_STATE) { - cmd = "AT+CREG?"; - prefix = "+CREG:"; - } else if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) { - cmd = "AT+CGREG?"; - prefix = "+CGREG:"; - } else { - assert(0); - goto error; - } - } else { - /* "Regular" CDMA (like Diam/Raph) uses AT+COPS, world phone CDMA uses AT+HTC_SRV_STATUS */ - if (is_world_cdma) - cmd = "AT+HTC_SRV_STATUS?"; - else - cmd = "AT+COPS?"; - - prefix= "$HTC_SYSTYPE"; - } - err = 1; - for (i=0;i<4 && err != 0;i++) - err = at_send_command_singleline(cmd, prefix, &p_response); - - if (err != 0) goto error; - - line = p_response->p_intermediates->line; - - err = at_tok_start(&line); - if (err < 0) goto error; - if (isgsm) { - /* Ok you have to be careful here - * The solicited version of the CREG response is - * +CREG: n, stat, [lac, cid] - * and the unsolicited version is - * +CREG: stat, [lac, cid] - * The parameter is basically "is unsolicited creg on?" - * which it should always be - * - * Now we should normally get the solicited version here, - * but the unsolicited version could have snuck in - * so we have to handle both - * - * Also since the LAC and CID are only reported when registered, - * we can have 1, 2, 3, or 4 arguments here - * - * finally, a +CGREG: answer may have a fifth value that corresponds - * to the network type, as in; - * - * +CGREG: n, stat [,lac, cid [,networkType]] - */ - - /* count number of commas */ - commas = 0; - for (p = line ; *p != '\0' ;p++) { - if (*p == ',') commas++; - } - - switch (commas) { - case 0: /* +CREG: */ - err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; - response[1] = -1; - response[2] = -1; - break; - - case 1: /* +CREG: , */ - err = at_tok_nextint(&line, &skip); - if (err < 0) goto error; - err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; - response[1] = -1; - response[2] = -1; - if (err < 0) goto error; - break; - - case 2: /* +CREG: , , */ - err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[1]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[2]); - if (err < 0) goto error; - break; - case 3: /* +CREG: , , , */ - err = at_tok_nextint(&line, &skip); - if (err < 0) goto error; - err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[1]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[2]); - if (err < 0) goto error; - - /* Hack for broken +CGREG responses which don't return the network type */ - if(request == RIL_REQUEST_GPRS_REGISTRATION_STATE) { - ATResponse *p_response_op = NULL; - err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response_op); - /* We need to get the 4th return param */ - int commas_op; - commas_op = 0; - char *p_op, *line_op; - line_op = p_response_op->p_intermediates->line; - - for (p_op = line_op ; *p_op != '\0' ;p_op++) { - if (*p_op == ',') commas_op++; - } - - if (commas_op == 3) { - err = at_tok_start(&line_op); - err = at_tok_nextint(&line_op, &skip); - if (err < 0) goto error; - err = at_tok_nextint(&line_op, &skip); - if (err < 0) goto error; - err = at_tok_nextint(&line_op, &skip); - if (err < 0) goto error; - err = at_tok_nextint(&line_op, &response[3]); - if (err < 0) goto error; - /* Now translate to 'Broken Android Speak' - can't follow the GSM spec */ - switch(response[3]) { - /* GSM/GSM Compact - aka GRPS */ - case 0: - case 1: - response[3] = 1; - break; - /* EGPRS - aka EDGE */ - case 3: - response[3] = 2; - break; - /* UTRAN - UMTS aka 3G */ - case 2: - case 7: - response[3] = 3; - break; - /* UTRAN with HSDPA and/or HSUPA aka Turbo-3G */ - case 4: - case 5: - case 6: - response[3] = 9; - break; - } - } - - at_response_free(p_response_op); - } - break; - /* special case for CGREG, there is a fourth parameter - * that is the network type (unknown/gprs/edge/umts) - */ - case 4: /* +CGREG: , , , , */ - err = at_tok_nextint(&line, &skip); - if (err < 0) goto error; - err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[1]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[2]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[3]); - if (err < 0) goto error; - break; - default: - goto error; - } - } else { //CDMA - if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) { - err = at_tok_nextint(&line, &response[3]); - if (response[3] < 1) - response[3] = 1; - if (response[3] > 3) - response[3] = 3; - } - } - asprintf(&responseStr[0], "%d", response[0]); - asprintf(&responseStr[1], "%x", response[1]); - asprintf(&responseStr[2], "%x", response[2]); - asprintf(&responseStr[3], "%d", response[3]); - - RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*)); - at_response_free(p_response); - - return; -error: - LOGE("requestRegistrationState must never return an error when radio is on"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); -} - -static void requestOperator(void *data, size_t datalen, RIL_Token t) -{ - int err; - int i; - int skip; - ATLine *p_cur; - char *response[4]; - - memset(response, 0, sizeof(response)); - - ATResponse *p_response = NULL; - if(isgsm) { - err = at_send_command_multiline( - "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?", - "+COPS:", &p_response); - - /* we expect 3 lines here: - * +COPS: 0,0,"T - Mobile" - * +COPS: 0,1,"TMO" - * +COPS: 0,2,"310170" - */ - - if (err != 0) goto error; - - for (i = 0, p_cur = p_response->p_intermediates - ; p_cur != NULL - ; p_cur = p_cur->p_next, i++ - ) { - char *line = p_cur->line; - - err = at_tok_start(&line); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &skip); - if (err < 0) goto error; - - // If we're unregistered, we may just get - // a "+COPS: 0" response - if (!at_tok_hasmore(&line)) { - response[i] = NULL; - continue; - } - - err = at_tok_nextint(&line, &skip); - if (err < 0) goto error; - - // a "+COPS: 0, n" response is also possible - if (!at_tok_hasmore(&line)) { - response[i] = NULL; - continue; - } - - err = at_tok_nextstr(&line, &(response[i])); - if (err < 0) goto error; - } - - if (i < 3) { - goto error; - } - if (i == 3) { - response[3] = '\0'; - } - } - else { - response[0]=erisystem; - response[1]="Android"; - response[2]="310260"; - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); - at_response_free(p_response); - return; - -error: - LOGE("requestOperator must not return error when radio is on"); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); -} - -static void requestSendSMS(void *data, size_t datalen, RIL_Token t, int request) -{ - int err; - char smsc[30]; - const char *pdu; - const char *testSmsc; - int tpLayerLength,length,i,plus = 0; - char *cmd1, *cmd2, *line, *temp; -// bytes_t first; - int tosca,curChar=0; - RIL_SMS_Response response; - ATResponse *p_response = NULL; - ATResponse *p2_response = NULL; - char * cdma=0; - char sendstr[512]; - struct { - RIL_SMS_Response resp; - int result; - } extendedResponse; - - testSmsc = ((char **)data)[0]; - pdu = ((const char **)data)[1]; - - tpLayerLength = strlen(pdu)/2; - LOGI("SMSC=%s PDU=%s",testSmsc,pdu); - // "NULL for default SMSC" - if (testSmsc == NULL) { - if(isgsm){ - err = at_send_command_singleline("AT+CSCA?", "+CSCA:", &p2_response); - - if (err < 0 || p2_response->success == 0) { - goto error; - } - - line = p2_response->p_intermediates->line; - - err = at_tok_start(&line); - if (err < 0) goto error; - - err = at_tok_nextstr(&line, &temp); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &tosca); - if (err < 0) goto error; - - if(temp[0]=='+') { - ++temp; - //plus = 1; - } - - length = strlen(temp) - plus; - sprintf(smsc,"%.2x%.2x",(length + 1) / 2 + 1, tosca); - - for (i = 0; curChar < length - 1; i+=2 ) { - smsc[5+i] = temp[plus+curChar++]; - smsc[4+i] = temp[plus+curChar++]; - } - - if ( length % 2) {//One extra number - smsc[4+length] = temp[curChar]; - smsc[3+length]='F'; - smsc[5+length]='\0'; - } else { - smsc[4+length] = '\0'; - } - //first = malloc(30*sizeof(byte_t)); - //length = 2 + (gsm_bcdnum_from_ascii(temp,strlen(temp),&first)) / 2; - //sprintf(smsc,"%.2x%.2x%s",length,tosca,first); - //free(first); - } - } - else - strcpy(smsc,testSmsc); - LOGI("SMSC=%s PDU=%s",smsc,pdu); - - if(!isgsm) { - strcpy(sendstr,"00"); - strcat(sendstr,pdu); - LOGI("GSM PDU=%s",pdu); - cdma=gsm_to_cdmapdu(sendstr); - tpLayerLength = strlen(cdma)/2; - } - asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength); - if(isgsm) - asprintf(&cmd2, "%s%s", smsc, pdu); - else - asprintf(&cmd2, "%s", cdma); - - err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response); - - free(cmd1); - free(cmd2); -// free(smsc); - - if (err != 0 || p_response->success == 0) goto error; - - memset(&response, 0, sizeof(response)); - - /* FIXME fill in messageRef and ackPDU */ - line = p_response->p_intermediates->line; - err = at_tok_start(&line); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &response.messageRef); - if (err < 0) goto error; - - response.ackPDU = NULL; - - if (request == RIL_REQUEST_SEND_SMS_EXTENDED) - { - extendedResponse.resp = response; - extendedResponse.result = 1; - RIL_onRequestComplete(t, RIL_E_SUCCESS, &extendedResponse, sizeof(extendedResponse)); - } - else - { - RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response)); - } - at_response_free(p_response); - at_response_free(p2_response); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); - at_response_free(p2_response); -} - -static void requestSetupDataCall(char **data, size_t datalen, RIL_Token t) -{ - const char *apn; - char *user = NULL; - char *pass = NULL; - char *cmd; - char *userpass; - int err; - ATResponse *p_response = NULL; - int fd, pppstatus,i,fd2; - FILE *pppconfig; - size_t cur = 0; - ssize_t written, rlen; - char status[32] = {0}; - char *buffer; - long buffSize, len; - int retry = 10; - char *response[3] = { "1", PPP_TTY_PATH, "255.255.255.255" }; - int mypppstatus; - - apn = ((const char **)data)[2]; - user = ((char **)data)[3]; - if(user != NULL) - { - if (strlen(user)<2) - user = "dummy"; - } else - user = "dummy"; - - pass = ((char **)data)[4]; - if(pass != NULL) - { - if (strlen(pass)<2) - pass = "dummy"; - } else - pass = "dummy"; - - LOGD("requesting data connection to APN '%s'\n", apn); - - //Make sure there is no existing connection or pppd instance running - if(killConn(response[0]) < 0) - goto error; - - if(isgsm) - { - if (*data[0]=='0') - LOGE("Android want us to connect as CDMA while we are a GSM phone !"); - } else - { - if(*data[0]=='1') - LOGE("Android want us to connect as GSM while we are a CDMA phone !"); - } - if(isgsm) { - asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn); - //FIXME check for error here - err = at_send_command(cmd, NULL); - free(cmd); - // Set required QoS params to default - err = at_send_command("AT+CGQREQ=1", NULL); - // Set minimum QoS params to default - err = at_send_command("AT+CGQMIN=1", NULL); - // packet-domain event reporting - err = at_send_command("AT+CGEREP=1,0", NULL); - // Hangup anything that's happening there now - err = at_send_command("AT+CGACT=0,1", NULL); - // Start data on PDP context 1 - err = at_send_command("ATD*99***1#", &p_response); - if (err < 0 || p_response->success == 0) { - at_response_free(p_response); - goto error; - } - at_response_free(p_response); - } else { - //CDMA - err = at_send_command("AT+CFUN=1", NULL); - err = at_send_command("AT+HTC_DUN=0", NULL); - err = at_send_command("ATH", NULL); - err = at_send_command("ATDT#777", &p_response); - if (err < 0 || p_response->success == 0) { - at_response_free(p_response); - goto error; - } - at_response_free(p_response); - } - - asprintf(&userpass, "%s * %s\n", user, pass); - len = strlen(userpass); - fd = open("/etc/ppp/pap-secrets",O_WRONLY); - if(fd < 0) - goto error; - write(fd, userpass, len); - close(fd); - fd = open("/etc/ppp/chap-secrets",O_WRONLY); - if(fd < 0) - goto error; - write(fd, userpass, len); - close(fd); - free(userpass); - - pppconfig = fopen("/etc/ppp/options.smd","r"); - if(!pppconfig) - goto error; - - //filesize - fseek(pppconfig, 0, SEEK_END); - buffSize = ftell(pppconfig); - rewind(pppconfig); - - //allocate memory - buffer = (char *) malloc (sizeof(char)*buffSize); - if (buffer == NULL) - goto error; - - //read in the original file - len = fread (buffer,1,buffSize,pppconfig); - if (len != buffSize) - goto error; - fclose(pppconfig); - - pppconfig = fopen("/etc/ppp/options.smd1","w"); - fwrite(buffer,1,buffSize,pppconfig); - fprintf(pppconfig,"user %s\n",user); - fclose(pppconfig); - free(buffer); - - // The modem replies immediately even if it's not connected! - // so wait a short time. - sleep(2); - mypppstatus = system("/bin/pppd /dev/smd1");//Or smd7 ? - if (mypppstatus < 0) - goto error; - sleep(5); // allow time for ip-up to run - /* - * We are supposed to return IP address in response[2], but this is not used by android currently - */ - /* - inaddr_t addr,mask; - unsigned int flags; - ifc_init(); - ifc_get_info(PPP_TTY_PATH, &addr, &mask, &flags); - ifc_close(); - */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - -} - -static int killConn(char *cid) -{ - int err; - char * cmd; - int fd,i=0; - ATResponse *p_response = NULL; - - while((fd = open("/etc/ppp/ppp-gprs.pid",O_RDONLY)) > 0) { - if(i%5 == 0) { - system("killall pppd"); - } - close(fd); - if(i>25) - goto error; - i++; - sleep(1); - } - if (isgsm) { - asprintf(&cmd, "AT+CGACT=0,%s", cid); - - err = at_send_command(cmd, &p_response); - free(cmd); - - if (err < 0 || p_response->success == 0) { - at_response_free(p_response); - goto error; - } - at_response_free(p_response); - } else { - //CDMA - if (dataCallNum() >= 0) { - err = at_send_command("ATH", &p_response); - - if (err < 0 || p_response->success == 0) { - at_response_free(p_response); - goto error; - } - at_response_free(p_response); - } - } - return 0; - -error: - return -1; -} - -static void requestDeactivateDataCall(void *data, size_t datalen, RIL_Token t) -{ - char *cid; - - cid = ((char **)data)[0]; - if (killConn(cid) < 0) - goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t) -{ - int ackSuccess; - int err; - - ackSuccess = ((int *)data)[0]; - - if (ackSuccess == 1) { - err = at_send_command("AT+CNMA=1", NULL); - } else if (ackSuccess == 0) { - err = at_send_command("AT+CNMA=2", NULL); - } else { - LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGE\n"); - goto error; - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - -} - -static void requestSIM_IO(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 *p_args; - char *line; - - memset(&sr, 0, sizeof(sr)); - - p_args = (RIL_SIM_IO *)data; - if(slow_sim) - usleep(slow_sim); - - /* 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); - } 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(isgsm){ - err = at_send_command_singleline(cmd, "+CRSM:", &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, &(sr.sw1)); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &(sr.sw2)); - if (err < 0) goto error; - - if (at_tok_hasmore(&line)) { - err = at_tok_nextstr(&line, &(sr.simResponse)); - if (err < 0) goto error; - } - } else { - //CDMA - if(p_args->fileid != 0x6f40) { - LOGE("SIM IO Request: %s\n", cmd); - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - at_response_free(p_response); - free(cmd); - return; - } else { //Asking for the MSISDN or phone number. 1+ bytes alpha id (leave null), 1 byte length of bcd number (set to 11), 1 byte TON/NPI (set to FF), 10 byte phone num, 1 byte capability id, 1 byte extension id - sr.sw1=144; - sr.sw2=0; - - if(p_args->command == 192) - asprintf(&sr.simResponse,"000000806f40040011a0aa01020120"); - else { - char * msid; - char * response; - int plus = 0; - int length; - int i; - int curChar=0; - - err = at_send_command_singleline("AT+CNUM", "+CNUM:", &p_response); - - if (err < 0 || p_response->success == 0) - goto error; - line = p_response->p_intermediates->line; - - at_tok_start(&line); - err = at_tok_nextstr(&line, &response); - if (err < 0) - goto error; - err = at_tok_nextstr(&line, &response); - if (err < 0) - goto error; - - if(response[0]=='+') - plus = 1; - - length = strlen(response) - plus; - asprintf(&msid,"%.2x%.2dFFFFFFFFFFFFFFFFFFFF",(length + 1) / 2 + 1, 81 + plus * 10); - - for (i = 0; curChar < length - 1; i+=2 ) { - msid[5+i] = response[plus+curChar++]; - msid[4+i] = response[plus+curChar++]; - } - - if ( length % 2) //One extra number - msid[4+length] = response[curChar]; - - asprintf(&sr.simResponse,"ffffffffffffffffffffffffffffffffffff%sffff",msid); - free(msid); - } - } - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr)); - at_response_free(p_response); - free(cmd); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); - free(cmd); - -} - -static void requestEnterSimPin(void* data, size_t datalen, RIL_Token t) -{ - ATResponse *p_response = NULL; - int err; - char* cmd = NULL; - const char** strings = (const char**)data;; - - if(isgsm) { - if ( datalen == sizeof(char*) ) { - asprintf(&cmd, "AT+CPIN=\"%s\"", strings[0]); - } else if ( datalen == 2*sizeof(char*) ) { - asprintf(&cmd, "AT+CPIN=\"%s\",\"%s\"", strings[0], strings[1]); - } else - goto error; - - err = at_send_command_singleline(cmd, "+CREG:", &p_response); - free(cmd); - - if (err < 0 || p_response->success == 0) { -error: - RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0); - } else { - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - - /* Notify that SIM is ready */ - setRadioState(RADIO_STATE_SIM_READY); - } - - at_response_free(p_response); - } else { - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - setRadioState(RADIO_STATE_SIM_READY); - } -} - -static void requestChangeSimPin(void* data, size_t datalen, RIL_Token t) -{ - ATResponse *p_response = NULL; - int err; - char* cmd = NULL; - const char** strings = (const char**)data;; - - if(isgsm) { - if ( datalen == 2*sizeof(char*) ) - asprintf(&cmd, "AT+CPWD=\"SC\",\"%s\",\"%s\"", strings[0], strings[1]); - else - goto error; - - err = at_send_command(cmd, &p_response); - free(cmd); - - if (err < 0 || p_response->success == 0) { -error: - RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0); - } - else - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - - at_response_free(p_response); - } else { - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - } -} - - -static void unsolicitedNitzTime(const char * s) -{ - int err; - char * response = NULL; - char * line, *origline; - char * p = NULL; - char * tz = NULL; /* Timezone */ - origline = line = strdup(s); - - /* Higher layers expect a NITZ string in this format: - * 08/10/28,19:08:37-20,1 (yy/mm/dd,hh:mm:ss(+/-)tz,dst) - */ - - if(strStartsWith(s,"+CTZV:")){ - - /* Get Time and Timezone data and store in static variable. - * Wait until DST is received to send response to upper layers - */ - at_tok_start(&line); - - err = at_tok_nextstr(&line, &tz); - if (err < 0) goto error; - - err = at_tok_nextstr(&line, &response); - if (err < 0) goto error; - - snprintf(sNITZtime, sizeof(sNITZtime), "%s%s", response, tz); - - } - else if(strStartsWith(s,"+CTZDST:")){ - - /* We got DST, now assemble the response and send to upper layers */ - at_tok_start(&line); - - err = at_tok_nextstr(&line, &tz); - if (err < 0) goto error; - - asprintf(&response, "%s,%s", sNITZtime, tz); - - RIL_onUnsolicitedResponse(RIL_UNSOL_NITZ_TIME_RECEIVED, response, strlen(response)); - free(response); - - } - else if(strStartsWith(s, "+HTCCTZV:")){ - at_tok_start(&line); - - err = at_tok_nextstr(&line, &response); - if (err < 0) goto error; - RIL_onUnsolicitedResponse(RIL_UNSOL_NITZ_TIME_RECEIVED, response, strlen(response)); - - } - free(origline); - return; - -error: - LOGE("Invalid NITZ line %s\n", s); -} - -static void unsolicitedRSSI(const char * s) -{ - int err; - int response[2]; - char * line = NULL, *origline; - const unsigned char asu_table[6]={0,2,6,12,25,31}; - - origline = strdup(s); - line = origline; - - err = at_tok_start(&line); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &(response[0])); - if (err < 0) goto error; - - response[0]=asu_table[response[0]%6]; - response[1]=99; - - signalStrength[0]=response[0]; - signalStrength[1]=response[1]; - free(origline); - - RIL_onUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH, response, sizeof(response)); - return; - -error: - /* The notification was for a battery event - do not send a msg to upper layers */ - return; -} - -static void requestNotSupported(RIL_Token t, int request) -{ - LOGD("Request %d is unsupported", request); - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - return; -} - -static void requestOEMHookRaw(void *data, size_t datalen, RIL_Token t) -{ - RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen); - return; -} - -static void requestQueryCallWaiting(void *data, size_t datalen, RIL_Token t) -{ - ATResponse *p_response = NULL; - int err; - char *cmd = NULL; - char *line; - int class; - int response[2]; - - class = ((int *)data)[0]; - - asprintf(&cmd, "AT+CCWA=1,2,%d",class); - - err = at_send_command_singleline(cmd, "+CCWA:", &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, &(response[0])); - if (err < 0) goto error; - - if (at_tok_hasmore(&line)) { - err = at_tok_nextint(&line, &(response[1])); - if (err < 0) goto error; - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); - at_response_free(p_response); - free(cmd); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); - free(cmd); -} - -static void requestSetCallWaiting(void *data, size_t datalen, RIL_Token t) -{ - ATResponse *p_response = NULL; - int err; - char *cmd = NULL; - int enabled, class; - - if((datalen<2)||(data==NULL)) goto error; - - enabled = ((int *)data)[0]; - class = ((int *)data)[1]; - - asprintf(&cmd, "AT+CCWA=0,%d,%d",enabled,class); - - err = at_send_command(cmd, NULL); - - if (err < 0 ) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - at_response_free(p_response); - free(cmd); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); - free(cmd); -} - -static void requestQueryCallForwardStatus(RIL_Token t) -{ - int err = 0; - int i = 0; - int n = 0; - int tmp = 0; - ATResponse *p_response = NULL; - ATLine *p_cur; - RIL_CallForwardInfo **responses = NULL; - char *cmd; - - err = at_send_command_multiline("AT+CCFC=0,2", "+CCFC:", &p_response); - - if(err != 0 || p_response->success == 0) - goto error; - - for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) - n++; - - responses = alloca(n * sizeof(RIL_CallForwardInfo *)); - - for(i = 0; i < n; i++) { - responses[i] = alloca(sizeof(RIL_CallForwardInfo)); - responses[i]->status = 0; - responses[i]->reason = 0; - responses[i]->serviceClass = 0; - responses[i]->toa = 0; - responses[i]->number = ""; - responses[i]->timeSeconds = 0; - } - - for (i = 0,p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next, i++) { - char *line = p_cur->line; - - err = at_tok_start(&line); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &(responses[i]->status)); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &(responses[i]->serviceClass)); - if (err < 0) goto error; - - if(!at_tok_hasmore(&line)) continue; - - err = at_tok_nextstr(&line, &(responses[i]->number)); - if (err < 0) goto error; - - if(!at_tok_hasmore(&line)) continue; - - err = at_tok_nextint(&line, &(responses[i]->toa)); - if (err < 0) goto error; - - if(!at_tok_hasmore(&line)) continue; - at_tok_nextint(&line,&tmp); - - if(!at_tok_hasmore(&line)) continue; - at_tok_nextint(&line,&tmp); - - if(!at_tok_hasmore(&line)) continue; - err = at_tok_nextint(&line, &(responses[i]->timeSeconds)); - if (err < 0) goto error; - - } - - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_SUCCESS, responses, sizeof(RIL_CallForwardInfo **)); - return; - -error: - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestSetCallForward(void *data, RIL_Token t) -{ - int err = 0; - char *cmd = NULL; - RIL_CallForwardInfo *info = NULL; - - info = ((RIL_CallForwardInfo *) data); - - if(data == NULL) goto error; - - asprintf(&cmd, "AT+CCFC = %d, %d, \"%s\"", - info->reason, info->status, - info->number); - - err = at_send_command(cmd, NULL); - - if (err < 0 ) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - free(cmd); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - free(cmd); -} - -static void requestGetCLIR(void *data, size_t datalen, RIL_Token t) -{ - /* Even though data and datalen must be NULL and 0 respectively this - * condition is not verified - */ - ATResponse *p_response = NULL; - int response[2]; - char *line = NULL; - int err = 0; - - err = at_send_command_singleline("AT+CLIR?", "+CLIR:", &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, &(response[0])); - if (err < 0) goto error; - - err = at_tok_nextint(&line, &(response[1])); - if (err < 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response)); - at_response_free(p_response); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); -} - -static void requestSetCLIR(void *data, size_t datalen, RIL_Token t) -{ - char *cmd = NULL; - int err = 0; - - asprintf(&cmd, "AT+CLIR=%d", ((int *)data)[0]); - - err = at_send_command(cmd, NULL); - free(cmd); - - if (err < 0) - RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0); - else - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestSendSMSExpectMore(void *data, size_t datalen, RIL_Token t) -{ - char *cmd = NULL; - asprintf(&cmd, "AT+CMMS=1"); - at_send_command(cmd, NULL); - free(cmd); - requestSendSMS(data, datalen, t, 0); -} - -static void requestSendUSSD(void *data, size_t datalen, RIL_Token t) -{ - ATResponse *p_response = NULL; - int err = 0; - int len; - cbytes_t ussdRequest; - char *cmd; - bytes_t temp; - char *newUSSDRequest; - if(isgsm) { - ussdRequest = (cbytes_t)(data); - temp = malloc(strlen((char *)ussdRequest)*sizeof(char)+1); - len = utf8_to_gsm8(ussdRequest,strlen((char *)ussdRequest),temp); - newUSSDRequest = malloc(2*len*sizeof(char)+1); - gsm_hex_from_bytes(newUSSDRequest,temp, len); - newUSSDRequest[2*len]='\0'; - asprintf(&cmd, "AT+CUSD=1,\"%s\",15", newUSSDRequest); - free(newUSSDRequest); - free(temp); - err = at_send_command(cmd, &p_response); - free(cmd); - if (err < 0 || p_response->success == 0) { - goto error; - } else { - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - } - at_response_free(p_response); - } else { - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - } - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void unsolicitedUSSD(const char *s) -{ - char *line, *linestart; - int typeCode, count, err, len; - char *message; - char *outputmessage; - char *responseStr[2]; - - LOGD("unsolicitedUSSD %s\n",s); - - linestart=line=strdup(s); - err = at_tok_start(&line); - if(err < 0) goto error; - - err = at_tok_nextint(&line, &typeCode); - if(err < 0) goto error; - - if(at_tok_hasmore(&line)) { - err = at_tok_nextstr(&line, &message); - if(err < 0) goto error; - outputmessage = malloc(strlen(message)*2+1); - gsm_hex_to_bytes((cbytes_t)message,strlen(message),(bytes_t)outputmessage); - responseStr[1] = malloc(strlen(outputmessage)*2+1); - len = utf8_from_gsm8((cbytes_t)outputmessage,strlen(outputmessage),(bytes_t)responseStr[1]); - responseStr[1][strlen(message)/2]='\0'; - free(outputmessage); - count = 2; - } else { - responseStr[1]=NULL; - count = 1; - } - free(linestart); - asprintf(&responseStr[0], "%d", typeCode); - - RIL_onUnsolicitedResponse (RIL_UNSOL_ON_USSD, responseStr, count*sizeof(char*)); - return; - -error: - free(linestart); - LOGE("unexpectedUSSD error\n"); -} - -static void unsolicitedERI(const char *s) { - char *line, *origline; - int temp; - char *newEri; - - origline = strdup(s); - line = origline; - at_tok_start(&line); - - at_tok_nextint(&line, &temp); - at_tok_nextint(&line, &temp); - at_tok_nextint(&line, &temp); - at_tok_nextint(&line, &temp); - at_tok_nextint(&line, &temp); - at_tok_nextint(&line, &temp); - at_tok_nextint(&line, &temp); - at_tok_nextstr(&line, &newEri); - - if(strlen(newEri)<50) - strcpy(erisystem,newEri); - - free(origline); -} - -static void requestSetFacilityLock(void *data, size_t datalen, RIL_Token t) -{ - /* It must be tested if the Lock for a particular class can be set without - * modifing the values of the other class. If not, first must call - * requestQueryFacilityLock to obtain the previus value - */ - int err = 0; - char *cmd = NULL; - char *code = NULL; - char *lock = NULL; - char *password = NULL; - char *class = NULL; - - assert (datalen >= (4 * sizeof(char **))); - - code = ((char **)data)[0]; - lock = ((char **)data)[1]; - password = ((char **)data)[2]; - class = ((char **)data)[3]; - - asprintf(&cmd, "AT+CLCK=\"%s\",%s,\"%s\",%s", code, lock, password, class); - err = at_send_command(cmd, NULL); - if (err < 0) goto error; - - free(cmd); - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestChangeBarringPassword(void *data, size_t datalen, RIL_Token t) -{ - int err = 0; - char *cmd = NULL; - char *string = NULL; - char *old_password = NULL; - char *new_password = NULL; - - assert (datalen >= (3 * sizeof(char **))); - - string = ((char **)data)[0]; - old_password = ((char **)data)[1]; - new_password = ((char **)data)[2]; - - asprintf(&cmd, "AT+CPWD=\"%s\",\"%s\",\"%s\"", string, old_password, new_password); - err = at_send_command(cmd, NULL); - - free(cmd); - - if (err < 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestSetNetworkSelectionManual(void *data, size_t datalen, RIL_Token t) -{ - char *operator = NULL; - char *cmd = NULL; - int err = 0; - ATResponse *p_response = NULL; - - operator = (char *)data; - asprintf(&cmd, "AT+COPS=1,2,\"%s\"", operator); - err = at_send_command(cmd, &p_response); - if (err < 0 || p_response->success == 0){ - err = at_send_command("AT+COPS=0", NULL); - if(err < 0) goto error; - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - at_response_free(p_response); - free(cmd); - return; - -error: - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestQueryCLIP(void *data, size_t datalen, RIL_Token t) -{ - ATResponse *p_response = NULL; - int err; - char *line; - int response; - - err = at_send_command_singleline("AT+CLIP?","+CLIP:",&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; - - /* The first number is discarded */ - err = at_tok_nextint(&line, &response); - if(err < 0) goto error; - - err = at_tok_nextint(&line, &response); - if(err < 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int)); - at_response_free(p_response); - return; - -error: - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestResetRadio(RIL_Token t) -{ - int err = 0; - - err = at_send_command("AT+CFUN=16", NULL); - if(err < 0) - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - else - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - - return; -} - -static void requestSetSuppSVCNotification(void *data, size_t datalen, RIL_Token t) -{ - int err = 0; - int enabled = 0; - char *cmd = NULL; - enabled = ((int *)data)[0]; - - asprintf(&cmd, "AT+CSSN=%d,%d", enabled, enabled); - err = at_send_command(cmd,NULL); - free(cmd); - if(err < 0) - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - else - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestExplicitCallTransfer(RIL_Token t) -{ - int err = 0; - err = at_send_command("AT+CHLD=4",NULL); - if(err < 0) - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - else - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestSetLocationUpdates(void *data, size_t datalen, RIL_Token t) -{ - int err = 0; - int updates = 0; - char *cmd = NULL; - ATResponse *p_response = NULL; - updates = ((int *)data)[0] == 1? 2 : 2; - - asprintf(&cmd, "AT+CREG=%d", updates); - - err = at_send_command_singleline(cmd,"+CLIP:",&p_response); - //if(err < 0 || p_response->success == 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - at_response_free(p_response); - return; - -error: - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestSTKGetprofile(RIL_Token t) -{ - int err = 0; - int responselen = 0; - ATResponse *p_response = NULL; - char *response = NULL; - char *line = NULL; - - err = at_send_command_singleline("AT+STKPROF?", "+STKPROF:", &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, &responselen); - if(err < 0) goto error; - - err = at_tok_nextstr(&line, &response); - if(err < 0) goto error; - - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_SUCCESS, response, responselen * sizeof(char)); - return; - -error: - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - return; -} - -static void requestSTKSetProfile(void * data, size_t datalen, RIL_Token t) -{ - int err = 0; - int length = 0; - char *profile = NULL; - char *cmd = NULL; - - profile = (char *)data; - length = strlen(profile); - asprintf(&cmd, "AT+STKPROF=%d,\"%s\"", length, profile); - - err = at_send_command(cmd, NULL); - free(cmd); - if(err < 0) - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - else - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; -} - -static void requestLastFailCause(RIL_Token t) -{ - ATResponse *p_response = NULL; - int err = 0; - int response = 0; - char *tmp = NULL; - char *line = NULL; - - err = at_send_command_singleline("AT+CEER", "+CEER:", &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_nextstr(&line, &tmp); - if(err < 0) goto error; - - err = at_tok_nextint(&line, &response); - if(err < 0) goto error; - - RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int)); - at_response_free(p_response); - return; - -error: - at_response_free(p_response); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestHangupWaitingOrBackground(RIL_Token t) -{ - // 3GPP 22.030 6.5.5 - // "Releases all held calls or sets User Determined User Busy - // (UDUB) for a waiting call." - at_send_command("AT+CHLD=0", NULL); - - /* success or failure is ignored by the upper layer here. - it will call GET_CURRENT_CALLS and determine success that way */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestHangupForegroundResumeBackground(RIL_Token t) -{ - // 3GPP 22.030 6.5.5 - // "Releases all active calls (if any exist) and accepts - // the other (held or waiting) call." - at_send_command("AT+CHLD=1", NULL); - // writesys("audio","5"); - - /* success or failure is ignored by the upper layer here. - it will call GET_CURRENT_CALLS and determine success that way */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestSwitchWaitingOrHoldingAndActive(RIL_Token t) -{ - // 3GPP 22.030 6.5.5 - // "Places all active calls (if any exist) on hold and accepts - // the other (held or waiting) call." - if (isgsm) - at_send_command("AT+CHLD=2", NULL); - else - at_send_command("AT+HTC_SENDFLASH", NULL); - -#ifdef WORKAROUND_ERRONEOUS_ANSWER - s_expectAnswer = 1; -#endif /* WORKAROUND_ERRONEOUS_ANSWER */ - - /* success or failure is ignored by the upper layer here. - it will call GET_CURRENT_CALLS and determine success that way */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestAnswer(RIL_Token t) -{ - at_send_command("ATA", NULL); - writesys("audio","2"); - -#ifdef WORKAROUND_ERRONEOUS_ANSWER - s_expectAnswer = 1; -#endif /* WORKAROUND_ERRONEOUS_ANSWER */ - - /* success or failure is ignored by the upper layer here. - it will call GET_CURRENT_CALLS and determine success that way */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestConference(RIL_Token t) -{ - // 3GPP 22.030 6.5.5 - // "Adds a held call to the conversation" - at_send_command("AT+CHLD=3", NULL); - - /* success or failure is ignored by the upper layer here. - it will call GET_CURRENT_CALLS and determine success that way */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); -} - -static void requestUDUB(RIL_Token t) -{ - /* user determined user busy */ - /* sometimes used: ATH */ - at_send_command("ATH", NULL); - - /* success or failure is ignored by the upper layer here. - it will call GET_CURRENT_CALLS and determine success that way */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - -} - -static void requestSeparateConnection(void * data, size_t datalen, RIL_Token t) -{ - char cmd[12]; - int party = ((int*)data)[0]; - - // Make sure that party is in a valid range. - // (Note: The Telephony middle layer imposes a range of 1 to 7. - // It's sufficient for us to just make sure it's single digit.) - if (party > 0 && party < 10){ - sprintf(cmd, "AT+CHLD=2%d", party); - at_send_command(cmd, NULL); - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - } - else{ - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - } -} - -static void requestDTMF(void * data, size_t datalen, RIL_Token t) -{ - int err = 0; - char c = ((char *)data)[0]; - char *cmd; - - asprintf(&cmd, "AT+VTS=%c", (int)c); - - err = at_send_command(cmd, NULL); - if(err < 0){ - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - } - else{ - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - } - - free(cmd); - return; -} - -static void requestGetIMSI(RIL_Token t) -{ - ATResponse *p_response = NULL; - char *imsi; - char *line; - char *response; - char *part; - int err; - - if(isgsm) { - int loop = 0; - int success = 0; - /* We are looping here because the command fails on the first try. - What needs to be done, is to trap the "+CME ERROR: 14" which means - SIM BUSY and retry that. As a workaround for now, simply try, wait - 1 second, and try again, until a valid result is obtained. Usually only - takes 2 tries. - */ - while ( loop < 10) { - err = at_send_command_numeric("AT+CIMI", &p_response); - if (err < 0 || p_response->success == 0) { - sleep(1); - loop++; - } - else { - loop=10; - success=1; - } - } - -/* if (err < 0 || p_response->success == 0 ) */ - if (success == 0) - goto error; - imsi = strdup(p_response->p_intermediates->line); - } else { - /* Disable this until CDMA uses the real IMSI */ -#if 0 - err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response); - - if (err < 0 || p_response->success == 0) - goto error; - line = p_response->p_intermediates->line; - - at_tok_start(&line); - err = at_tok_nextstr(&line, &response); - if (err < 0) - goto error; - err = at_tok_nextstr(&line, &response); - if (err < 0) - goto error; - err = at_tok_nextstr(&line, &response); - if (err < 0) - goto error; - - part = strdup(response); - - at_response_free(p_response); - free (part); - - err = at_send_command_singleline("AT+CNUM", "+CNUM:", &p_response); - - if (err < 0 || p_response->success == 0) - goto error; - line = p_response->p_intermediates->line; - - at_tok_start(&line); - err = at_tok_nextstr(&line, &response); - if (err < 0) - goto error; - err = at_tok_nextstr(&line, &response); - if (err < 0) - goto error; -#endif - //FIXME make it work with the real IMSI: asprintf(&imsi, "%s%s", part, response); //Real opID - asprintf(&imsi, "310260000000000"); //Fake opID - - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, imsi, sizeof(char *)); - free (imsi); - at_response_free(p_response); - return; -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); -} - -static void requestGetIMEISV(RIL_Token t) -{ - int err = 0; - ATResponse *p_response = NULL; - if(isgsm) { - err = at_send_command_numeric("AT+CGSN", &p_response); - if (err < 0 || p_response->success == 0) { - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - } else { - RIL_onRequestComplete(t, RIL_E_SUCCESS, - p_response->p_intermediates->line, sizeof(char *)); - } - } else { - /* On world phone, AT+GSN returns the IMEI in decimal. This can be returned directly. - * On regular CDMA, AT+GSN returns the ESN in hex. This has to be converted to decimal. - */ - - err = at_send_command_numeric("AT+GSN", &p_response); - if (err < 0 || p_response->success == 0) { - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - } else { - char * line = p_response->p_intermediates->line; - if (line[1] == 'x') { - /* Hex ESN: regular CDMA */ - unsigned long int imei; - char * imeiString; - imei = (unsigned long)hex2int(line[9]) + (unsigned long)16*hex2int(line[8]) - + (unsigned long)256*hex2int(line[7]) + (unsigned long)4096*hex2int(line[6]) - + (unsigned long)65536*hex2int(line[5]) + (unsigned long)1048576*hex2int(line[4]) - + (unsigned long)16777216*hex2int(line[3]) + (unsigned long)268435456*hex2int(line[2]); - asprintf(&imeiString,"%015lu",imei); - RIL_onRequestComplete(t, RIL_E_SUCCESS,imeiString, sizeof(char *)); - free(imeiString); - } else { - /* Decimal IMEI: world phone in CDMA mode */ - RIL_onRequestComplete(t, RIL_E_SUCCESS, - p_response->p_intermediates->line, sizeof(char *)); - } - } - - } - at_response_free(p_response); - return; -} - -static void requestCancelUSSD(RIL_Token t) -{ - int err = 0; - ATResponse *p_response = NULL; - - err = at_send_command_numeric("AT+CUSD=2", &p_response); - - if (err < 0 || p_response->success == 0){ - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - } - else{ - RIL_onRequestComplete(t, RIL_E_SUCCESS, - p_response->p_intermediates->line, sizeof(char *)); - } - - at_response_free(p_response); - return; -} - -static void requestSetNetworkSelectionAutomatic(RIL_Token t) -{ - int err = 0; - - err = at_send_command("AT+COPS=0", NULL); - if(err < 0) - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - else - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - - return; -} - -static void requestOEMHookStrings(void * data, size_t datalen, RIL_Token t) -{ - int i; - const char ** cur=(const char **)data; - char *send=NULL; - char *startswith=NULL; - int err=0; - ATResponse *p_response = NULL; - - if(datalen==sizeof (char *)) { - send=(char *)*cur++; - startswith=(char *)*cur; - err = at_send_command_singleline(send, startswith, &p_response); - if(err<0 || p_response->success == 0) - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - else - RIL_onRequestComplete(t, RIL_E_SUCCESS, p_response->p_intermediates->line, sizeof (char *)); - at_response_free(p_response); - return; - } -/* - if(isgsm) { - LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen); - - for (i = (datalen / sizeof (char *)), cur = (const char **)data; i > 0; cur++, i --){ - LOGD("> '%s'", *cur); - } - - // echo back strings - RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen); - } else { - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - } -*/ - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - return; -} - -static void requestDeleteSMSOnSIM(void * data, size_t datalen, RIL_Token t) -{ - int err = 0; - char * cmd; - ATResponse *p_response = NULL; - - if (isgsm) { - asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]); - - err = at_send_command(cmd, &p_response); - if (err < 0 || p_response->success == 0){ - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - } else { - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - } - - free(cmd); - at_response_free(p_response); - } else { - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - } - return; -} - -static void requestSTKSendEnvelopeCommand(void * data, size_t datalen, RIL_Token t) { - int err = 0; - int len = 0; - int envcmd = 0; - int itemid = 0; - int helpreq = 0; - int eventlst = 0; - int lang_cause = 0; - char *hexdata = (char *)data; - char *cmd = NULL; - unsigned int *intdata = NULL; - - len = strlen(data); - - intdata = (unsigned int*)(alloca((len / 2) * sizeof(unsigned int))); - - HexStr_to_DecInt(data, intdata); - - envcmd = intdata[0]; - if(envcmd == 211){ - itemid = intdata[8]; - helpreq = intdata[9]; - asprintf(&cmd, "AT+STKENV=%d, %d, %d", envcmd, itemid, helpreq); - err = at_send_command(cmd, NULL); - if(err < 0) - goto error; - } - else if(envcmd == 214){ - len = intdata[1]; - eventlst = intdata[4]; - if(len > 7) lang_cause = intdata[9]; - asprintf(&cmd, "AT+STKENV=%d, %d, %d", envcmd, eventlst, lang_cause); - err = at_send_command(cmd, NULL); - if(err < 0) - goto error; - - } - else{ - goto notsupported; - } - - free(cmd); - free(intdata); - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -notsupported: - free(cmd); - free(intdata); - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - return; - -error: - free(cmd); - free(intdata); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - return; -} - -static void requestSTKSendTerminalResponse(void * data, size_t datalen, RIL_Token t) { - int err = 0; - int len = 0; - int command = 0; - int result = 0; - int additionalInfo = 0; - int dcs = 0; - int offset = 0; - int optInfoLen = 0; - char *optInfo = NULL; - int i = 0; - char *hexdata = (char *)data; - char *cmd = NULL; - unsigned int *intdata = NULL; - - len = strlen(data); - intdata = (unsigned int*)(alloca((len / 2) * sizeof(unsigned int))); - HexStr_to_DecInt(data, intdata); - command = intdata[2]; - - switch(command){ - case 21: - command = 33; - break; - case 20: - command = 32; - break; - case 15: - command = 21; - break; - case 22: - command = 34; - break; - case 23: - command = 35; - break; - case 24: - command = 36; - break; - default: - goto notsupported; - break; - } - - switch(command){ - case 32: - case 33:{ - result = intdata[11]; - if(intdata[10] > 1) - additionalInfo = intdata[12]; - asprintf(&cmd, "AT+STKTR=%d, %d, %d", command, result, additionalInfo); - err = at_send_command(cmd, NULL); - if(err < 0) - goto error; - break; - } - case 21:{ - result = intdata[11]; - asprintf(&cmd, "AT+STKTR=%d, %d", command, result); - err = at_send_command(cmd, NULL); - if(err < 0) - goto error; - break; - } - case 34: - case 35: - case 36:{ - result = intdata[11]; - if(intdata[10] > 1){ - additionalInfo = intdata[12]; - offset = 1; - } - optInfoLen = (intdata[13] + offset) * 2; - optInfo = alloca(optInfoLen * sizeof(char)); - for(i = 0; i < optInfoLen; i++) - optInfo[i] = hexdata[15 + offset + i]; - - asprintf(&cmd, "AT+STKTR=%d, %d, %d, 0, %d,\"%s\"", command, result, additionalInfo, intdata[14+offset], optInfo); - - err = at_send_command(cmd, NULL); - if(err < 0) - goto error; - - break; - } - } - - free(cmd); - free(intdata); - free(optInfo); - RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); - return; - -notsupported: - free(cmd); - free(intdata); - free(optInfo); - RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); - return; - -error: - free(cmd); - free(intdata); - free(optInfo); - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -} - -static void requestNeighboringCellIds(void * data, size_t datalen, RIL_Token t) { - int err=1; - int response[4]; - char * responseStr[4]; - ATResponse *p_response = NULL; - char *line, *p; - int commas; - int skip; - int i; - int count = 3; - int cur_cid; - - RIL_NeighboringCell **pp_cellIds; - RIL_NeighboringCell *p_cellIds; - - pp_cellIds = (RIL_NeighboringCell **)alloca(sizeof(RIL_NeighboringCell *)); - p_cellIds = (RIL_NeighboringCell *)alloca(sizeof(RIL_NeighboringCell)); - pp_cellIds[0]=p_cellIds; - - for (i=0;i<4 && err != 0;i++) { - err = at_send_command_singleline("AT+CREG?", "+CREG:", &p_response); - } - - if (err != 0) goto error; - - line = p_response->p_intermediates->line; - - err = at_tok_start(&line); - if (err < 0) goto error; - /* Ok you have to be careful here - * The solicited version of the CREG response is - * +CREG: n, stat, [lac, cid] - * and the unsolicited version is - * +CREG: stat, [lac, cid] - * The parameter is basically "is unsolicited creg on?" - * which it should always be - * - * Now we should normally get the solicited version here, - * but the unsolicited version could have snuck in - * so we have to handle both - * - * Also since the LAC and CID are only reported when registered, - * we can have 1, 2, 3, or 4 arguments here - * - * finally, a +CGREG: answer may have a fifth value that corresponds - * to the network type, as in; - * - * +CGREG: n, stat [,lac, cid [,networkType]] - */ - - /* count number of commas */ - commas = 0; - for (p = line ; *p != '\0' ;p++) { - if (*p == ',') commas++; - } - switch (commas) { - case 0: /* +CREG: */ - case 1: /* +CREG: , */ - goto error; - break; - - case 2: /* +CREG: , , */ - err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[1]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &cur_cid); - asprintf(&(p_cellIds[0].cid), "%x", cur_cid); - if (err < 0) goto error; - break; - case 3: /* +CREG: , , , */ - err = at_tok_nextint(&line, &skip); - if (err < 0) goto error; - err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[1]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &cur_cid); - asprintf(&(p_cellIds[0].cid), "%x", cur_cid); - p_cellIds[0].rssi=2; - if (err < 0) goto error; - break; - case 4: /* +CGREG: , , , , */ - err = at_tok_nextint(&line, &skip); - if (err < 0) goto error; - err = at_tok_nextint(&line, &response[0]); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[1]); - if (err < 0) goto error; - err = at_tok_nextstr(&line, &p_cellIds[0].cid); - if (err < 0) goto error; - err = at_tok_nexthexint(&line, &response[3]); - if (err < 0) goto error; - count = 4; - break; - default: - goto error; - } - - RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_cellIds, sizeof(*pp_cellIds)); - at_response_free(p_response); - return; - -error: - RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - at_response_free(p_response); -} - - -/*** Callback methods from the RIL library to us ***/ - -/** - * Call from RIL to us to make a RIL_REQUEST - * - * Must be completed with a call to RIL_onRequestComplete() - * - * RIL_onRequestComplete() may be called from any thread, before or after - * this function returns. - * - * Will always be called from the same thread, so returning here implies - * that the radio is ready to process another command (whether or not - * the previous command has completed). - */ - static void -onRequest (int request, void *data, size_t datalen, RIL_Token t) -{ - ATResponse *p_response; - int err; - - LOGD("onRequest: %s (%d)", requestToString(request), request); - - /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS - * when RADIO_STATE_UNAVAILABLE. - */ - if (sState == RADIO_STATE_UNAVAILABLE - && request != RIL_REQUEST_GET_SIM_STATUS - ) { - RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0); - return; - } - - /* Ignore all non-power requests when RADIO_STATE_OFF - * (except RIL_REQUEST_GET_SIM_STATUS) - */ - if (sState == RADIO_STATE_OFF - && !(request == RIL_REQUEST_RADIO_POWER - || request == RIL_REQUEST_GET_SIM_STATUS) - ) { - RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0); - return; - } - - switch (request) { - case RIL_REQUEST_GET_SIM_STATUS: { - RIL_CardStatus *p_card_status; - char *p_buffer; - int buffer_size; - - int result = getCardStatus(&p_card_status); - if (result == RIL_E_SUCCESS) { - p_buffer = (char *)p_card_status; - buffer_size = sizeof(*p_card_status); - } else { - p_buffer = NULL; - buffer_size = 0; - } - RIL_onRequestComplete(t, result, p_buffer, buffer_size); - freeCardStatus(p_card_status); - break; - } - - case RIL_REQUEST_GET_CURRENT_CALLS: - requestGetCurrentCalls(data, datalen, t); - break; - - case RIL_REQUEST_DIAL: - requestDial(data, datalen, t); - break; - - case RIL_REQUEST_HANGUP: - requestHangup(data, datalen, t); - break; - - case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: - requestHangupWaitingOrBackground(t); - break; - - case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: - requestHangupForegroundResumeBackground(t); - break; - - case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: - requestSwitchWaitingOrHoldingAndActive(t); - break; - - case RIL_REQUEST_ANSWER: - requestAnswer(t); - break; - - case RIL_REQUEST_CONFERENCE: - requestConference(t); - break; - - case RIL_REQUEST_UDUB: - requestUDUB(t); - break; - - case RIL_REQUEST_SEPARATE_CONNECTION: - requestSeparateConnection(data, datalen, t); - break; - - case RIL_REQUEST_SIGNAL_STRENGTH: - requestSignalStrength(data, datalen, t); - break; - - case RIL_REQUEST_REGISTRATION_STATE: - case RIL_REQUEST_GPRS_REGISTRATION_STATE: - requestRegistrationState(request, data, datalen, t); - break; - - case RIL_REQUEST_SET_MUTE: - requestSetMute(data, datalen, t); - break; - - case RIL_REQUEST_GET_MUTE: - requestGetMute(data, datalen, t); - break; - - case RIL_REQUEST_SCREEN_STATE: - requestScreenState(data, datalen, t); - break; - - case RIL_REQUEST_OPERATOR: - requestOperator(data, datalen, t); - break; - - case RIL_REQUEST_RADIO_POWER: - requestRadioPower(data, datalen, t); - break; - - case RIL_REQUEST_QUERY_FACILITY_LOCK: - requestQueryFacilityLock(data, datalen, t); - break; - - case RIL_REQUEST_DTMF: - requestDTMF(data, datalen, t); - break; - - case RIL_REQUEST_DTMF_STOP: - requestDtmfStop(data, datalen, t); - break; - - case RIL_REQUEST_DTMF_START: - requestDtmfStart(data, datalen, t); - break; - - case RIL_REQUEST_SEND_SMS_EXTENDED: - case RIL_REQUEST_SEND_SMS: - requestSendSMS(data, datalen, t, request); - break; - - case RIL_REQUEST_SETUP_DATA_CALL: - requestSetupDataCall(data, datalen, t); - break; - - case RIL_REQUEST_DEACTIVATE_DATA_CALL: - requestDeactivateDataCall(data, datalen, t); - break; - - case RIL_REQUEST_SMS_ACKNOWLEDGE: - requestSMSAcknowledge(data, datalen, t); - break; - - case RIL_REQUEST_GET_IMSI: - requestGetIMSI(t); - break; - - case RIL_REQUEST_BASEBAND_VERSION: - requestBasebandVersion(data, datalen, t); - break; - - case RIL_REQUEST_GET_IMEI: - case RIL_REQUEST_GET_IMEISV: - requestGetIMEISV(t); - break; - - case RIL_REQUEST_SIM_IO: - requestSIM_IO(data,datalen,t); - break; - - case RIL_REQUEST_CANCEL_USSD: - requestCancelUSSD(t); - break; - - case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: - requestSetNetworkSelectionAutomatic(t); - break; - - case RIL_REQUEST_DATA_CALL_LIST: - requestDataCallList(data, datalen, t); - break; - - case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: - requestQueryNetworkSelectionMode(data, datalen, t); - break; - - case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: - requestQueryAvailableNetworks(data, datalen, t); - break; - - case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: - requestGetPreferredNetworkType(data, datalen, t); - break; - - case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: - requestSetPreferredNetworkType(data, datalen, t); - break; - - case RIL_REQUEST_OEM_HOOK_RAW: - // echo back data - requestOEMHookRaw(data, datalen, t); - break; - - case RIL_REQUEST_OEM_HOOK_STRINGS: - requestOEMHookStrings(data, datalen, t); - break; - - case RIL_REQUEST_WRITE_SMS_TO_SIM: - requestWriteSmsToSim(data, datalen, t); - break; - - case RIL_REQUEST_DELETE_SMS_ON_SIM: - requestDeleteSMSOnSIM(data, datalen, t); - break; - - case RIL_REQUEST_ENTER_SIM_PIN: - requestEnterSimPin(data, datalen, t); - break; - case RIL_REQUEST_CHANGE_SIM_PIN: - requestChangeSimPin(data, datalen, t); - break; - case RIL_REQUEST_ENTER_SIM_PUK: - case RIL_REQUEST_ENTER_SIM_PIN2: - case RIL_REQUEST_ENTER_SIM_PUK2: - case RIL_REQUEST_CHANGE_SIM_PIN2: - requestNotSupported(t, request); - break; - - case RIL_REQUEST_QUERY_CALL_WAITING: - requestQueryCallWaiting(data, datalen, t); - break; - - case RIL_REQUEST_SET_CALL_WAITING: - requestSetCallWaiting(data, datalen, t); - break; - - case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS: - requestQueryCallForwardStatus(t); - break; - - case RIL_REQUEST_SET_CALL_FORWARD: - requestSetCallForward(data, t); - break; - - case RIL_REQUEST_GET_CLIR: - requestGetCLIR(data, datalen, t); - break; - - case RIL_REQUEST_SET_CLIR: - requestSetCLIR(data, datalen, t); - break; - - case RIL_REQUEST_SEND_SMS_EXPECT_MORE: - requestSendSMSExpectMore(data, datalen, t); - break; - - case RIL_REQUEST_SEND_USSD: - requestSendUSSD(data, datalen, t); - break; - - case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: - // NOTE: There isn't an AT command with this capability - requestNotSupported(t, request); - break; - - case RIL_REQUEST_SET_FACILITY_LOCK: - requestSetFacilityLock(data, datalen, t); - break; - - case RIL_REQUEST_CHANGE_BARRING_PASSWORD: - requestChangeBarringPassword(data, datalen, t); - break; - - case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: - requestSetNetworkSelectionManual(data, datalen, t); - break; - - case RIL_REQUEST_QUERY_CLIP: - requestQueryCLIP(data, datalen, t); - break; - - case RIL_REQUEST_RESET_RADIO: - requestResetRadio(t); - break; - - case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: - requestSetSuppSVCNotification(data, datalen, t); - break; - - case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: - requestExplicitCallTransfer(t); - break; - - case RIL_REQUEST_SET_LOCATION_UPDATES: - requestSetLocationUpdates(data, datalen, t); - break; - - case RIL_REQUEST_STK_GET_PROFILE: - requestSTKGetprofile(t); - break; - - case RIL_REQUEST_STK_SET_PROFILE: - requestSTKSetProfile(data, datalen, t); - break; - - case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: - case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: - requestLastFailCause(t); - break; - - case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: - requestSTKSendEnvelopeCommand(data, datalen, t); - break; - - case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: - requestSTKSendTerminalResponse(data, datalen, t); - break; - - case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: - requestNeighboringCellIds(data, datalen, t); - break; - - case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: - requestNotSupported(t, request); - break; - - case RIL_REQUEST_SET_BAND_MODE: - requestNotSupported(t, request); - break; - - case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: - requestNotSupported(t, request); - break; - - case RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG: - requestNotSupported(t, request); - break; - - case RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG: - requestNotSupported(t, request); - break; - - case RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION: - requestNotSupported(t, request); - break; - - case RIL_REQUEST_DEVICE_IDENTITY: - requestNotSupported(t, request); - break; - - default: - requestNotSupported(t, request); - break; - } -} - -/** - * Synchronous call from the RIL to us to return current radio state. - * RADIO_STATE_UNAVAILABLE should be the initial state. - */ - static RIL_RadioState -currentState() -{ - return sState; -} -/** - * Call from RIL to us to find out whether a specific request code - * is supported by this implementation. - * - * Return 1 for "supported" and 0 for "unsupported" - */ - - static int -onSupports (int requestCode) -{ - //@@@ todo - - return 1; -} - -static void onCancel (RIL_Token t) -{ - //@@@todo - -} - -static const char * getVersion(void) -{ - return "HTC Vogue Community RIL 1.6.0 [xda]"; -} - - static void -setRadioState(RIL_RadioState newState) -{ - RIL_RadioState oldState; - - pthread_mutex_lock(&s_state_mutex); - - oldState = sState; - - if (s_closed > 0) { - // If we're closed, the only reasonable state is - // RADIO_STATE_UNAVAILABLE - // This is here because things on the main thread - // may attempt to change the radio state after the closed - // event happened in another thread - newState = RADIO_STATE_UNAVAILABLE; - } - - if (sState != newState || s_closed > 0) { - sState = newState; - - pthread_cond_broadcast (&s_state_cond); - } - - pthread_mutex_unlock(&s_state_mutex); - - /* do these outside of the mutex */ - if (sState != oldState) { - RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, - NULL, 0); - - /* FIXME onSimReady() and onRadioPowerOn() cannot be called - * from the AT reader thread - * Currently, this doesn't happen, but if that changes then these - * will need to be dispatched on the request thread - */ - if (sState == RADIO_STATE_SIM_READY) { - onSIMReady(); - } else if (sState == RADIO_STATE_SIM_NOT_READY) { - onRadioPowerOn(); - } - } -} - -/** returns one of RIM_SIM_*. Returns RIL_SIM_NOT_READY on error */ - static SIM_Status -getSIMStatus() -{ - ATResponse *p_response = NULL; - int err; - int ret; - char *cpinLine; - char *cpinResult; - - if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) { - ret = SIM_NOT_READY; - goto done; - } - - if (isgsm) - { - err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response); - - if (err != 0) { - ret = SIM_NOT_READY; - goto done; - } - - switch (at_get_cme_error(p_response)) { - case CME_SUCCESS: - break; - - case CME_SIM_NOT_INSERTED: - ret = SIM_ABSENT; - goto done; - - default: - ret = SIM_NOT_READY; - goto done; - } - - /* CPIN? has succeeded, now look at the result */ - - cpinLine = p_response->p_intermediates->line; - err = at_tok_start (&cpinLine); - - if (err < 0) { - ret = SIM_NOT_READY; - goto done; - } - - err = at_tok_nextstr(&cpinLine, &cpinResult); - - if (err < 0) { - ret = SIM_NOT_READY; - goto done; - } - - if (0 == strcmp (cpinResult, "SIM PIN")) { - ret = SIM_PIN; - goto done; - } else if (0 == strcmp (cpinResult, "SIM PUK")) { - ret = SIM_PUK; - goto done; - } else if (0 == strcmp (cpinResult, "PH-NET PIN")) { - return SIM_NETWORK_PERSONALIZATION; - } else if (0 != strcmp (cpinResult, "READY")) { - /* we're treating unsupported lock types as "sim absent" */ - ret = SIM_ABSENT; - goto done; - } - - at_response_free(p_response); - p_response = NULL; - cpinResult = NULL; - - } else { - //CDMA - } - //fall through if everything else succeeded - ret = SIM_READY; - -done: - at_response_free(p_response); - return ret; -} - -/** - * Get the current card status. - * - * This must be freed using freeCardStatus. - * @return: On success returns RIL_E_SUCCESS - */ -static int getCardStatus(RIL_CardStatus **pp_card_status) { - static RIL_AppStatus app_status_array[] = { - // SIM_ABSENT = 0 - { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN, - NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }, - // SIM_NOT_READY = 1 - { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN, - NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }, - // SIM_READY = 2 - { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY, - NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }, - // SIM_PIN = 3 - { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN, - NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN }, - // SIM_PUK = 4 - { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN, - NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN }, - // SIM_NETWORK_PERSONALIZATION = 5 - { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK, - NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN } - }; - RIL_CardState card_state; - int num_apps; - - int sim_status = getSIMStatus(); - if (sim_status == SIM_ABSENT) { - card_state = RIL_CARDSTATE_ABSENT; - num_apps = 0; - } else { - card_state = RIL_CARDSTATE_PRESENT; - num_apps = 1; - } - - // Allocate and initialize base card status. - RIL_CardStatus *p_card_status = malloc(sizeof(RIL_CardStatus)); - p_card_status->card_state = card_state; - p_card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN; - p_card_status->gsm_umts_subscription_app_index = RIL_CARD_MAX_APPS; - p_card_status->cdma_subscription_app_index = RIL_CARD_MAX_APPS; - p_card_status->num_applications = num_apps; - - // Initialize application status - int i; - for (i = 0; i < RIL_CARD_MAX_APPS; i++) { - p_card_status->applications[i] = app_status_array[SIM_ABSENT]; - } - - // Pickup the appropriate application status - // that reflects sim_status for gsm. - if (num_apps != 0) { - // Only support one app, gsm - p_card_status->num_applications = 1; - p_card_status->gsm_umts_subscription_app_index = 0; - - // Get the correct app status - p_card_status->applications[0] = app_status_array[sim_status]; - } - - *pp_card_status = p_card_status; - return RIL_E_SUCCESS; -} - -/** - * Free the card status returned by getCardStatus - */ -static void freeCardStatus(RIL_CardStatus *p_card_status) { - free(p_card_status); -} - -/** - * SIM ready means any commands that access the SIM will work, including: - * AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM - * (all SMS-related commands) - */ - -static void pollSIMState (void *param) -{ - ATResponse *p_response; - int ret; - - if (sState != RADIO_STATE_SIM_NOT_READY) { - // no longer valid to poll - return; - } - if(!isgsm) { - setRadioState(RADIO_STATE_SIM_READY); - return; - } - - switch(getSIMStatus()) { - case SIM_ABSENT: - case SIM_PIN: - case SIM_PUK: - case SIM_NETWORK_PERSONALIZATION: - default: - setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT); - return; - - case SIM_NOT_READY: - RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL); - return; - - case SIM_READY: - setRadioState(RADIO_STATE_SIM_READY); - return; - } -} - -/** returns 1 if on, 0 if off, and -1 on error */ -static int isRadioOn() -{ - ATResponse *p_response = NULL; - int err; - char *line; - char ret; - - err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response); - - if (err < 0 || p_response->success == 0) { - // assume radio is off - goto error; - } - - line = p_response->p_intermediates->line; - - err = at_tok_start(&line); - if (err < 0) goto error; - - err = at_tok_nextbool(&line, &ret); - if (err < 0) goto error; - - at_response_free(p_response); - - return (int)ret; - -error: - - at_response_free(p_response); - return -1; -} - -/** - * Initialize everything that can be configured while we're still in - * AT+CFUN=0 - */ -static void initializeCallback(void *param) -{ - ATResponse *p_response = NULL; - int err; - - at_handshake(); - - /* make sure the radio is off */ - if(isgsm) - at_send_command("AT+CFUN=0", NULL); - else { - /* Sending 'AT+CFUN=0' to a CDMA diam/raph eventually causes a "FATAL_ERROR: SM_TM (oncrpc_cb.c:00596)" - * Send 'CFUN=66' first, if that errors then we know this is a world phone */ - at_send_command("AT+CFUN=66", &p_response); - if (p_response->success == 0) - { - is_world_cdma = 1; - LOGD("Running on a world phone in CDMA mode\n"); - at_send_command("AT+CFUN=0", NULL); - } - at_response_free(p_response); - } - - - setRadioState (RADIO_STATE_OFF); - - - strcpy(erisystem,"Android"); - - /* note: we don't check errors here. Everything important will - be handled in onATTimeout and onATReaderClosed */ - - /* Common initialization strings */ - - /* atchannel is tolerant of echo but it must */ - /* reset and have verbose result codes */ - at_send_command("ATZV1", NULL); - - /* echo off */ - at_send_command("ATE0", NULL); - - /* No auto-answer */ - at_send_command("ATS0=0", NULL); - - /* send results */ - at_send_command("ATQ0", NULL); - - /* check for busy, don't check for dialone */ - at_send_command("ATX3", NULL); - - /* set DCD depending on service */ - at_send_command("AT&C1", NULL); - - /* set DTR according to service */ - at_send_command("AT&D1", NULL); - - /* Extended errors */ - at_send_command("AT+CMEE=1", NULL); - - /* Alternating voice/data off */ - at_send_command("AT+CMOD=0", NULL); - - /* Not muted */ - at_send_command("AT+CMUT=0", NULL); - - /* detailed rings, unknown */ - at_send_command("AT+CRC=1;+CR=1", NULL); - - /* caller id = yes */ - at_send_command("AT+CLIP=1", NULL); - - /* don't hide outgoing callerID */ - at_send_command("AT+CLIR=0", NULL); - - /* bring up the device, also resets the stack. Don't do this! Handled elsewhere */ -// at_send_command("AT+CFUN=1", NULL); - - if(isgsm) { - /* Call Waiting notifications */ - at_send_command("AT+CCWA=1", NULL); - - /* No connected line identification */ - at_send_command("AT+COLP=0", NULL); - - /* USSD unsolicited */ - at_send_command("AT+CUSD=1", NULL); - - /* SMS PDU mode */ - at_send_command("AT+CMGF=0", NULL); - - at_send_command("AT+GTKC=2", NULL); - - /* +CSSU unsolicited supp service notifications */ - at_send_command("AT+CSSN=0,1", NULL); - - /* HEX character set */ - at_send_command("AT+CSCS=\"HEX\"", NULL); - - /* Extra stuff */ - at_send_command("AT+FCLASS=0", NULL); - - at_send_command("AT+CNMI=1,2,2,2,0", NULL); - at_send_command("AT+CPPP=1", NULL); - - - /* Network registration events */ - err = at_send_command("AT+CREG=2", &p_response); - - /* some handsets -- in tethered mode -- don't support CREG=2 */ - if (err < 0 || p_response->success == 0) - at_send_command("AT+CREG=1", NULL); - - at_response_free(p_response); - - /* GPRS registration events */ - at_send_command("AT+CGREG=2", NULL); - - /* Disable RSSI Indicators for Now */ - at_send_command("AT@HTCCSQ=0", NULL); - at_send_command("AT+ENCSQ=1", NULL); - at_send_command("AT@HTCDIS=1;@HTCSAP=1", NULL); - at_send_command("AT+HTCmaskW1=262143,162161", NULL); - at_send_command("AT+CGEQREQ=1,4,0,0,0,0,2,0,\"0E0\",\"0E0\",3,0,0", NULL); - at_send_command("AT+HTCNV=1,12,6", NULL); -// at_send_command("AT+HSDPA=1", NULL); - at_send_command("AT+HTCCNIV=0", NULL); -// at_send_command("AT@HTCDORMANCYSET=3", NULL); - at_send_command("AT@HTCPDPFD=0", NULL); - at_send_command("AT+HTCAGPS=5", NULL); - at_send_command("AT@AGPSADDRESS=193,253,42,109,7275", NULL); - at_send_command("AT",NULL); - /* auto connect/disconnect settings */ -// at_send_command("AT+CGAATT=2,1,0", NULL); -// at_send_command("AT+BANDSET=0", NULL); - at_send_command("AT+GTKC=2", NULL); - - - } else { - if (is_world_cdma) - at_send_command("AT+CGAATT=2,1,6", NULL); /* '6'=CDMA-only mode, '3'=GSM-only, '0'=world mode */ - } - /* assume radio is off on error */ - if (isRadioOn() > 0) { - setRadioState (RADIO_STATE_SIM_NOT_READY); - } -} - -static void waitForClose() -{ - pthread_mutex_lock(&s_state_mutex); - - while (s_closed == 0) { - pthread_cond_wait(&s_state_cond, &s_state_mutex); - } - - pthread_mutex_unlock(&s_state_mutex); -} - -/** - * Called by atchannel when an unsolicited line appears - * This is called on atchannel's reader thread. AT commands may - * not be issued here - */ -static void onUnsolicited (const char *s, const char *sms_pdu) -{ - char *line = NULL; - int err; - - /* Ignore unsolicited responses until we're initialized. - * This is OK because the RIL library will poll for initial state - */ - if (sState == RADIO_STATE_UNAVAILABLE) { - return; - } - - if (strStartsWith(s, "%CTZV:") - || strStartsWith(s,"+CTZV:") - || strStartsWith(s,"+CTZDST:") - || strStartsWith(s,"+HTCCTZV:")) { - unsolicitedNitzTime(s); - } else if (strStartsWith(s,"+CRING:") - || strStartsWith(s,"RING") - || strStartsWith(s,"NO CARRIER") - || strStartsWith(s,"+CCWA") - ) { - if (strStartsWith(s,"+CCWA") && !isgsm) { - /* Handle CCWA specially */ - handle_cdma_ccwa(s); - } - RIL_onUnsolicitedResponse ( - RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, - NULL, 0); - RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); - } else if (strStartsWith(s,"+XCIEV:") - || strStartsWith(s,"$HTC_CSQ:") - || strStartsWith(s,"@HTCCSQ:")) { - unsolicitedRSSI(s); - } else if (strStartsWith(s,"+CREG:") - || strStartsWith(s,"+CGREG:")) - /* || strStartsWith(s,"$HTC_SYSTYPE:")) */{ - RIL_onUnsolicitedResponse ( - RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, - NULL, 0); - RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); - } else if (strStartsWith(s, "+CMT:")) { - LOGD("GSM_PDU=%s\n",sms_pdu); - if(!isgsm) { - char **pdu; - pdu=cdma_to_gsmpdu(sms_pdu); - while(*pdu) { - // dbg(3,"RIL","SMS GSM_PDU=%s\n",*pdu); - RIL_onUnsolicitedResponse ( - RIL_UNSOL_RESPONSE_NEW_SMS,*pdu,strlen(*pdu)); - pdu++; - } - } else - RIL_onUnsolicitedResponse ( - RIL_UNSOL_RESPONSE_NEW_SMS, - sms_pdu, strlen(sms_pdu)); - } else if (strStartsWith(s, "+CDS:")) { - RIL_onUnsolicitedResponse ( - RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, - sms_pdu, strlen(sms_pdu)); - } else if (strStartsWith(s, "+CGEV:")) { - /* Really, we can ignore NW CLASS and ME CLASS events here, - * but right now we don't since extranous - * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated - */ - /* can't issue AT commands here -- call on main thread */ - RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); -#ifdef WORKAROUND_FAKE_CGEV - } else if (strStartsWith(s, "+CME ERROR: 150")) { - RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); -#endif /* WORKAROUND_FAKE_CGEV */ - } else if (strStartsWith(s, "$HTC_ERIIND:")) { - unsolicitedERI(s); - } else if (strStartsWith(s, "+CUSD:")) { - unsolicitedUSSD(s); - } -} - -/* Called on command or reader thread */ -static void onATReaderClosed() -{ - LOGI("AT channel closed\n"); - at_close(); - s_closed = 1; - - setRadioState (RADIO_STATE_UNAVAILABLE); -} - -/* Called on command thread */ -static void onATTimeout() -{ - LOGI("AT channel timeout; closing\n"); - at_close(); - - s_closed = 1; - - /* FIXME cause a radio reset here */ - - setRadioState (RADIO_STATE_UNAVAILABLE); -} - -static void usage(char *s) -{ -#ifdef RIL_SHLIB - fprintf(stderr, "htcgeneric-ril requires: -p or -d /dev/tty_device\n"); -#else - fprintf(stderr, "usage: %s [-p ] [-d /dev/tty_device]\n", s); - exit(-1); -#endif -} - - static void * -mainLoop(void *param) -{ - int fd; - int ret; - - AT_DUMP("== ", "entering mainLoop()", -1 ); - at_set_on_reader_closed(onATReaderClosed); - at_set_on_timeout(onATTimeout); - - for (;;) { - fd = -1; - while (fd < 0) { - if (s_port > 0) { - fd = socket_loopback_client(s_port, SOCK_STREAM); - } else if (s_device_socket) { - fd = socket_local_client( s_device_path, - ANDROID_SOCKET_NAMESPACE_FILESYSTEM, - SOCK_STREAM ); - } else if (s_device_path != NULL) { - fd = open (s_device_path, O_RDWR); - if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) { - - /* disable echo on serial ports */ - struct termios ios; - tcgetattr( fd, &ios ); - ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ - tcsetattr( fd, TCSANOW, &ios ); - } - } - - if (fd < 0) { - perror ("opening AT interface. retrying..."); - sleep(10); - /* never returns */ - } - } - - s_closed = 0; - ret = at_open(fd, onUnsolicited); - - if (ret < 0) { - LOGE ("AT error %d on at_open\n", ret); - return 0; - } - - RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0); - - // Give initializeCallback a chance to dispatched, since - // we don't presently have a cancellation mechanism - sleep(1); - - waitForClose(); - LOGI("Re-opening after close"); - } -} - -#ifdef RIL_SHLIB - -pthread_t s_tid_mainloop; -void parse_cmdline() { - int fd=open("/proc/cmdline", O_RDONLY); - char buf[1024]; - char *ptr,*ptr2; - int i; - buf[1023]=0; - if(fd<0) - return; - if(read(fd, buf, 1023)<0) { - close(fd); - return; - } - ptr=strstr(buf, "force_cdma="); - if(ptr && (ptr==buf || ptr[-1]==' ')) { - ptr+=strlen("force_cdma="); - if(atoi(ptr)) - isgsm=0; - else - isgsm=1; - } - ptr=strstr(buf, "slow_sim="); - if(ptr && (ptr==buf || ptr[-1]==' ')) { - ptr+=strlen("slow_sim="); - slow_sim=atoi(ptr); - } - ptr=strstr(buf, "north_am_dialing="); - if(ptr && (ptr==buf || ptr[-1]==' ')) { - ptr+=strlen("north_am_dialing="); - cdma_north_american_dialing=atoi(ptr); - } -} - -const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv) -{ - int ret; - int fd = -1; - int opt; - pthread_attr_t attr; - char buffer[32]; - - s_rilenv = env; - - fd=open("/sys/class/htc_hw/radio", O_RDONLY); - read(fd, buffer, 32); - isgsm=0; - if(strncmp(buffer, "GSM",3)==0) - isgsm=1; - close(fd); - parse_cmdline(); - - while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) { - switch (opt) { - case 'p': - s_port = atoi(optarg); - if (s_port == 0) { - usage(argv[0]); - return NULL; - } - LOGI("Opening loopback port %d\n", s_port); - break; - - case 'd': - s_device_path = "/dev/smd0"; - LOGI("Opening tty device %s\n", s_device_path); - break; - - case 's': - s_device_path = optarg; - s_device_socket = 1; - LOGI("Opening socket %s\n", s_device_path); - break; - - default: - usage(argv[0]); - return NULL; - } - } - - if (s_port < 0 && s_device_path == NULL) { - usage(argv[0]); - return NULL; - } - - pthread_attr_init (&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL); - - return &s_callbacks; -} -#else /* RIL_SHLIB */ -int main (int argc, char **argv) -{ - int ret; - int fd = -1; - int opt; - - while ( -1 != (opt = getopt(argc, argv, "p:d:"))) { - switch (opt) { - case 'p': - s_port = atoi(optarg); - if (s_port == 0) { - usage(argv[0]); - } - LOGI("Opening loopback port %d\n", s_port); - break; - - case 'd': - s_device_path = "/dev/smd0"; - LOGI("Opening tty device %s\n", s_device_path); - break; - - case 's': - s_device_path = optarg; - s_device_socket = 1; - LOGI("Opening socket %s\n", s_device_path); - break; - - default: - usage(argv[0]); - } - } - - if (s_port < 0 && s_device_path == NULL) { - usage(argv[0]); - } - - RIL_register(&s_callbacks); - - mainLoop(NULL); - - return 0; -} - -#endif /* RIL_SHLIB */ diff --git a/misc.c b/misc.c deleted file mode 100644 index 7945e75..0000000 --- a/misc.c +++ /dev/null @@ -1,29 +0,0 @@ -/* //device/system/reference-ril/misc.c -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -/** returns 1 if line starts with prefix, 0 if it does not */ -int strStartsWith(const char *line, const char *prefix) -{ - for ( ; *line != '\0' && *prefix != '\0' ; line++, prefix++) { - if (*line != *prefix) { - return 0; - } - } - - return *prefix == '\0'; -} - diff --git a/misc.h b/misc.h deleted file mode 100644 index bafe7df..0000000 --- a/misc.h +++ /dev/null @@ -1,19 +0,0 @@ -/* //device/system/reference-ril/misc.h -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -/** returns 1 if line starts with prefix, 0 if it does not */ -int strStartsWith(const char *line, const char *prefix); diff --git a/sms.c b/sms.c deleted file mode 100644 index 460c470..0000000 --- a/sms.c +++ /dev/null @@ -1,276 +0,0 @@ -// -// Convert CDMA SMS to GSM and vice versa. -// By Martin Johnson -// GPL -// -#include -#include -#include "sms_gsm.h" - -#ifndef nodroid -#define LOG_TAG "SMS_RIL" -#include -#else -#define LOGD printf -#define LOGE printf -#define LOGI printf -#endif - -int hex2int(char c) { - if(c>'9') return c-'A'+10; - return c-'0'; -} - -int getbit(char *s,int b) { - int byte=b/4; - int bit=b%4; - - int data=hex2int(s[byte]); - if(data&(1<<(3-bit))) return 1; - else return 0; -} - -const char hextable[17]="0123456789ABCDEF"; - -void setbit(char *s,int b, int val) { - int byte=b/4; - int bit=b%4; - - s[byte]=hextable[hex2int(s[byte]) | (val<<(3-bit))] ; -} - -int getbits(char *s,int startbit,int nbits) { - int val=0; - int i; - - for(i=0;i>(nbits-i-1))&1); -} - -const char decode_table[17]=".1234567890*#..."; - -void decode_number(char *msg, int length, char *no) { - - int ndigits=getbits(msg,2,8); - int j,digit; - - for(j=0;j160) LOGE("Error: Message String too long"); - for(i=0;i<512;i++) - pdu[i]='0'; - setbits(pdu,0,16,0); - setbits(pdu,16,24,0x021002); - pdu=pdu+10; - setbits(pdu,0,8,0x04); - length=encode_number(pdu+4, to); - setbits(pdu,8,8,length); - pdu=pdu+length*2+4; - setbits(pdu,0,24,0x060100); - pdu=pdu+6; - setbits(pdu,0,8,0x08); - length=encode_bearer_data(pdu+4, message); - if(length>255) LOGE("Error: Message Hex too long"); - setbits(pdu,8,8,length); - pdu=pdu+length*2+4; - *pdu=0; -} - -char **cdma_to_gsmpdu(char *msg) { - char from[256]; - char message[256]; - static char hexpdu[1024]; - static char *hexpdus[16]; - int i=0; - int is_vm=0; - decode_cdma_sms(msg,from,message,&is_vm); -// if(strlen(message)>=160) message[159]=0; - LOGD("CDMA Message:%s From:%s\n",message,from); - SmsAddressRec smsaddr; - SmsTimeStampRec smstime; - if (is_vm) { - /* voicemail notifications must have a 4 byte address */ - if (is_vm & 0x10) { - /* set message waiting indicator */ - strcpy(from, "1100"); - } else { - /* clear message waiting indicator */ - strcpy(from, "0100"); - } - } - sms_address_from_str(&smsaddr,from,strlen(from)); - if (is_vm) { - /* voicemail notifications have a clear bottom nibble in toa - * and an alphanumeric address type */ - smsaddr.toa = 0xd0; - } - sms_timestamp_now(&smstime); - SmsPDU *pdu=smspdu_create_deliver_utf8((const unsigned char *)message,strlen(message),&smsaddr,&smstime); - //hexpdu=malloc(512); - char *s=hexpdu; - while(*pdu) { - smspdu_to_hex(*pdu, s,512); - hexpdus[i]=s; - s=s+strlen(s)+2; - smspdu_free(*pdu); - i++; - pdu++; - } - hexpdus[i]=0; - return hexpdus; -} - -char *gsm_to_cdmapdu(char *msg) { - char to[256]; - char message[256]; - static char hexpdu[512]; - SmsAddressRec smsaddr; - sms_address_from_str(&smsaddr,"000000",6); - - SmsPDU pdu=smspdu_create_from_hex( msg, strlen(msg) ); - if(smspdu_get_receiver_address(pdu,&smsaddr)<0) { - LOGE("Error: no receiver address"); - smspdu_get_sender_address(pdu,&smsaddr); - } - sms_address_to_str(&smsaddr,to,256); - if(to[0]=='+') { // convert + to 00 otherwise international sms doesn't work - memmove(to+1,to,255); - to[0]='0'; - to[1]='0'; - } - int length=smspdu_get_text_message(pdu, message, 256); - message[length]=0; - smspdu_free(pdu); - LOGD("GSM Message:%s To:%s\n",message,to); - encode_cdma_sms(hexpdu,to,message); - return hexpdu; -} - diff --git a/sms_gsm.c b/sms_gsm.c deleted file mode 100644 index 6535bdc..0000000 --- a/sms_gsm.c +++ /dev/null @@ -1,1112 +0,0 @@ -#include "sms_gsm.h" -#include "gsm.h" -#include -#include -//#include - -/* maximum number of data bytes in a SMS data message */ -#define MAX_USER_DATA_BYTES 140 - -/* maximum number of 7-bit septets in a SMS text message */ -#define MAX_USER_DATA_SEPTETS 160 - -/* size of the user data header in bytes */ -#define USER_DATA_HEADER_SIZE 6 - -/** MESSAGE TEXT - **/ -int -sms_utf8_from_message_str( const char* str, int strlen, unsigned char* utf8, int utf8len ) -{ - const char* p = str; - const char* end = p + strlen; - int count = 0; - int escaped = 0; - - while (p < end) - { - int c = p[0]; - - /* read the value from the string */ - p += 1; - if (c >= 128) { - if ((c & 0xe0) == 0xc0) - c &= 0x1f; - else if ((c & 0xf0) == 0xe0) - c &= 0x0f; - else - c &= 0x07; - p++; - while (p < end && (p[0] & 0xc0) == 0x80) { - c = (c << 6) | (p[0] & 0x3f); - p++; - } - } - if (escaped) { - switch (c) { - case '\\': - break; - case 'n': /* \n is line feed */ - c = 10; - break; - - case 'x': /* \xNN, where NN is a 2-digit hexadecimal value */ - if (p+2 > end) - return -1; - c = gsm_hex2_to_byte( p ); - if (c < 0) - return -1; - break; - - case 'u': /* \uNNNN where NNNN is a 4-digiti hexadecimal value */ - if (p + 4 > end) - return -1; - c = gsm_hex4_to_short( p ); - if (c < 0) - return -1; - break; - - default: /* invalid escape, return -1 */ - return -1; - } - escaped = 0; - } - else if (c == '\\') - { - escaped = 1; - continue; - } - - /* now, try to write it to the destination */ - if (c < 128) { - if (count < utf8len) - utf8[count] = (byte_t) c; - count += 1; - } - else if (c < 0x800) { - if (count < utf8len) - utf8[count] = (byte_t)(0xc0 | ((c >> 6) & 0x1f)); - if (count+1 < utf8len) - utf8[count+1] = (byte_t)(0x80 | (c & 0x3f)); - count += 2; - } - else { - if (count < utf8len) - utf8[count] = (byte_t)(0xc0 | ((c >> 12) & 0xf)); - if (count+1 < utf8len) - utf8[count+1] = (byte_t)(0x80 | ((c >> 6) & 0x3f)); - if (count+2 < utf8len) - utf8[count+2] = (byte_t)(0x80 | (c & 0x3f)); - count += 3; - } - } - - if (escaped) /* bad final escape */ - return -1; - - return count; -} - -/** TIMESTAMPS - **/ -void -sms_timestamp_now( SmsTimeStamp stamp ) -{ - time_t now_time = time(NULL); - struct tm gm = *(gmtime(&now_time)); - struct tm local = *(localtime(&now_time)); - int tzdiff = 0; - - stamp->data[0] = gsm_int_to_bcdi( local.tm_year % 100 ); - stamp->data[1] = gsm_int_to_bcdi( local.tm_mon+1 ); - stamp->data[2] = gsm_int_to_bcdi( local.tm_mday ); - stamp->data[3] = gsm_int_to_bcdi( local.tm_hour ); - stamp->data[4] = gsm_int_to_bcdi( local.tm_min ); - stamp->data[5] = gsm_int_to_bcdi( local.tm_sec ); - - tzdiff = (local.tm_hour*4 + local.tm_min/15) - (gm.tm_hour*4 + gm.tm_min/15); - if (local.tm_yday > gm.tm_yday) - tzdiff += 24*4; - else if (local.tm_yday < gm.tm_yday) - tzdiff -= 24*4; - - stamp->data[6] = gsm_int_to_bcdi( tzdiff >= 0 ? tzdiff : -tzdiff ); - if (tzdiff < 0) - stamp->data[6] |= 0x08; -} - -int -sms_timestamp_to_tm( SmsTimeStamp stamp, struct tm* tm ) -{ - int tzdiff; - - tm->tm_year = gsm_int_from_bcdi( stamp->data[0] ); - if (tm->tm_year < 50) - tm->tm_year += 100; - tm->tm_mon = gsm_int_from_bcdi( stamp->data[1] ) -1; - tm->tm_mday = gsm_int_from_bcdi( stamp->data[2] ); - tm->tm_hour = gsm_int_from_bcdi( stamp->data[3] ); - tm->tm_min = gsm_int_from_bcdi( stamp->data[4] ); - tm->tm_sec = gsm_int_from_bcdi( stamp->data[5] ); - - tm->tm_isdst = -1; - - tzdiff = gsm_int_from_bcdi( stamp->data[6] & 0xf7 ); - if (stamp->data[6] & 0x8) - tzdiff = -tzdiff; - - return tzdiff; -} - -static void -gsm_rope_add_timestamp( GsmRope rope, const SmsTimeStampRec* ts ) -{ - gsm_rope_add( rope, ts->data, 7 ); -} - - -/** SMS ADDRESSES - **/ -int -sms_address_to_str( SmsAddress address, char* str, int strlen ) -{ - bytes_t data = address->data; - if(address->toa == 0x91) - *str++='+'; - int i; - char c; - for(i=0;ilen;i++) { - c=data[i/2]; - if(i&1) c=c>>4; - *str++='0'+(c&15); - } - *str=0; - return 1; -} - - -int -sms_address_from_str( SmsAddress address, const char* src, int srclen ) -{ - const char* end = src + srclen; - int shift = 0, len = 0; - bytes_t data = address->data; - - address->len = 0; - address->toa = 0x81; - - if (src >= end) - return -1; - - if ( src[0] == '+' ) { - address->toa = 0x91; - if (++src == end) - goto Fail; - } - - memset( address->data, 0, sizeof(address->data) ); - - shift = 0; - - while (src < end) { - int c = *src++ - '0'; - - if ( (unsigned)c >= 10 || - data >= address->data + sizeof(address->data) ) - goto Fail; - - data[0] |= c << shift; - len += 1; - shift += 4; - if (shift == 8) { - shift = 0; - data += 1; - } - } - if (shift != 0) - data[0] |= 0xf0; - - address->len = len; - return 0; - -Fail: - return -1; -} - -int -sms_address_from_bytes( SmsAddress address, const unsigned char* buf, int buflen ) -{ - int len = sizeof(address->data), num_digits; - - if (buflen < 2) - return -1; - - address->len = num_digits = buf[0]; - address->toa = buf[1]; - - len = (num_digits+1)/2; - if ( len > sizeof(address->data) ) - return -1; - - memcpy( address->data, buf+2, len ); - return 0; -} - -int -sms_address_to_bytes( SmsAddress address, unsigned char* buf, int bufsize ) -{ - int len = (address->len + 1)/2 + 2; - - if (buf == NULL) - bufsize = 0; - - if (bufsize < 1) goto Exit; - buf[0] = address->len; - - if (bufsize < 2) goto Exit; - buf[1] = address->toa; - - buf += 2; - bufsize -= 2; - if (bufsize > len-2) - bufsize = len - 2; - - memcpy( buf, address->data, bufsize ); -Exit: - return len; -} - -int -sms_address_from_hex ( SmsAddress address, const char* hex, int hexlen ) -{ - const char* hexend = hex + hexlen; - int nn, len, num_digits; - - if (hexlen < 4) - return -1; - - address->len = num_digits = gsm_hex2_to_byte( hex ); - address->toa = gsm_hex2_to_byte( hex+2 ); - hex += 4; - - len = (num_digits + 1)/2; - if (hex + len*2 > hexend) - return -1; - - for ( nn = 0; nn < len; nn++ ) - address->data[nn] = gsm_hex2_to_byte( hex + nn*2 ); - - return 0; -} - -int -sms_address_to_hex ( SmsAddress address, char* hex, int hexlen ) -{ - int len = (address->len + 1)/2 + 2; - int nn; - - if (hex == NULL) - hexlen = 0; - - if (hexlen < 2) goto Exit; - gsm_hex_from_byte( hex, address->len ); - if (hexlen < 4) goto Exit; - gsm_hex_from_byte( hex+2, address->toa ); - hex += 4; - hexlen -= 4; - if ( hexlen > 2*(len - 2) ) - hexlen = (len - 2)/2; - - for ( nn = 0; nn < hexlen; nn += 2 ) - gsm_hex_from_byte( hex+nn, address->data[nn/2] ); - -Exit: - return len*2; -} - -static void -gsm_rope_add_address( GsmRope rope, const SmsAddressRec* addr ) -{ - gsm_rope_add_c( rope, addr->len ); - gsm_rope_add_c( rope, addr->toa ); - gsm_rope_add( rope, addr->data, (addr->len+1)/2 ); - if (addr->len & 1) { - if (!rope->error && rope->data != NULL) - rope->data[ rope->pos-1 ] |= 0xf0; - } -} - - -/** SMS PARSER - **/ -static int -sms_get_byte( cbytes_t *pcur, cbytes_t end ) -{ - cbytes_t cur = *pcur; - int result = -1; - - if (cur < end) { - result = cur[0]; - *pcur = cur + 1; - } - return result; -} - -/* parse a service center address, returns -1 in case of error */ -static int -sms_get_sc_address( cbytes_t *pcur, - cbytes_t end, - SmsAddress address ) -{ - cbytes_t cur = *pcur; - int result = -1; - - if (cur < end) { - int len = cur[0]; - int dlen, adjust = 0; - - cur += 1; - - if (len == 0) { /* empty address */ - address->len = 0; - address->toa = 0x00; - result = 0; - goto Exit; - } - - if (cur + len > end) { - goto Exit; - } - - address->toa = *cur++; - len -= 1; - result = 0; - - for (dlen = 0; dlen < len; dlen+=1) - { - int c = cur[dlen]; - int v; - - adjust = 0; - if (dlen >= sizeof(address->data)) { - result = -1; - break; - } - - v = (c & 0xf); - if (v >= 0xe) - break; - - adjust = 1; - address->data[dlen] = (byte_t) c; - - v = (c >> 4) & 0xf; - if (v >= 0xe) { - break; - } - } - address->len = 2*dlen + adjust; - } -Exit: - if (!result) - *pcur = cur; - - return result; -} - -static int -sms_skip_sc_address( cbytes_t *pcur, - cbytes_t end ) -{ - cbytes_t cur = *pcur; - int result = -1; - int len; - - if (cur >= end) - goto Exit; - - len = cur[0]; - cur += 1 + len; - if (cur > end) - goto Exit; - - *pcur = cur; - result = 0; -Exit: - return result; -} - -/* parse a sender/receiver address, returns -1 in case of error */ -static int -sms_get_address( cbytes_t *pcur, - cbytes_t end, - SmsAddress address ) -{ - cbytes_t cur = *pcur; - int result = -1; - int len, dlen; - - if (cur >= end) - goto Exit; - - dlen = *cur++; - - if (dlen == 0) { - address->len = 0; - address->toa = 0; - result = 0; - goto Exit; - } - - if (cur + 1 + (dlen+1)/2 > end) - goto Exit; - - address->len = dlen; - address->toa = *cur++; - - len = (dlen + 1)/2; - if (len > sizeof(address->data)) - goto Exit; - - memcpy( address->data, cur, len ); - cur += len; - result = 0; - -Exit: - if (!result) - *pcur = cur; - - return result; -} - -static int -sms_skip_address( cbytes_t *pcur, - cbytes_t end ) -{ - cbytes_t cur = *pcur; - int result = -1; - int dlen; - - if (cur + 2 > end) - goto Exit; - - dlen = cur[0]; - cur += 2 + (dlen + 1)/2; - if (cur > end) - goto Exit; - - result = 0; -Exit: - return result; -} - -/* parse a service center timestamp */ -static int -sms_get_timestamp( cbytes_t *pcur, - cbytes_t end, - SmsTimeStamp ts ) -{ - cbytes_t cur = *pcur; - - if (cur + 7 > end) - return -1; - - memcpy( ts->data, cur, 7 ); - *pcur = cur + 7; - return 0; -} - -static int -sms_skip_timestamp( cbytes_t *pcur, - cbytes_t end ) -{ - cbytes_t cur = *pcur; - - if (cur + 7 > end) - return -1; - - *pcur = cur + 7; - return 0; -} - - -/** SMS PDU - **/ - -typedef struct SmsPDURec { - bytes_t base; - bytes_t end; - bytes_t tpdu; -} SmsPDURec; - -void -smspdu_free( SmsPDU pdu ) -{ - if (pdu) { - free( pdu->base ); - pdu->base = NULL; - pdu->end = NULL; - pdu->tpdu = NULL; - } -} - -SmsPduType -smspdu_get_type( SmsPDU pdu ) -{ - cbytes_t data = pdu->tpdu; - cbytes_t end = pdu->end; - int mtiByte = sms_get_byte(&data, end); - - switch (mtiByte & 3) { - case 0: return SMS_PDU_DELIVER; - case 1: return SMS_PDU_SUBMIT; - case 2: return SMS_PDU_STATUS_REPORT; - default: return SMS_PDU_INVALID; - } -} - -int -smspdu_get_sender_address( SmsPDU pdu, SmsAddress address ) -{ - cbytes_t data = pdu->tpdu; - cbytes_t end = pdu->end; - int mtiByte = sms_get_byte(&data, end); - - switch (mtiByte & 3) { - case 0: /* SMS_PDU_DELIVER; */ - return sms_get_sc_address( &data, end, address ); - - default: return -1; - } -} - -int -smspdu_get_sc_timestamp( SmsPDU pdu, SmsTimeStamp ts ) -{ - cbytes_t data = pdu->tpdu; - cbytes_t end = pdu->end; - int mtiByte = sms_get_byte( &data, end ); - - switch (mtiByte & 3) { - case 0: /* SMS_PDU_DELIVER */ - { - SmsAddressRec address; - - if ( sms_get_sc_address( &data, end, &address ) < 0 ) - return -1; - - data += 2; /* skip protocol identifer + coding scheme */ - - return sms_get_timestamp( &data, end, ts ); - } - - default: return -1; - } -} - -int -smspdu_get_receiver_address( SmsPDU pdu, SmsAddress address ) -{ - cbytes_t data = pdu->tpdu; - cbytes_t end = pdu->end; - int mtiByte = sms_get_byte( &data, end ); - - switch (mtiByte & 3) { - case 1: /* SMS_PDU_SUBMIT */ - { - data += 1; /* skip message reference */ - return sms_get_address( &data, end, address ); - } - - default: return -1; - } -} - -typedef enum { - SMS_CODING_SCHEME_UNKNOWN = 0, - SMS_CODING_SCHEME_GSM7, - SMS_CODING_SCHEME_UCS2 - -} SmsCodingScheme; - -/* see TS 23.038 Section 5 for details */ -static SmsCodingScheme -sms_get_coding_scheme( cbytes_t *pcur, - cbytes_t end ) -{ - cbytes_t cur = *pcur; - int dataCoding; - - if (cur >= end) - return SMS_CODING_SCHEME_UNKNOWN; - - dataCoding = *cur++; - *pcur = cur; - - switch (dataCoding >> 4) { - case 0x00: - case 0x02: - case 0x03: - return SMS_CODING_SCHEME_GSM7; - - case 0x01: - if (dataCoding == 0x10) return SMS_CODING_SCHEME_GSM7; - if (dataCoding == 0x11) return SMS_CODING_SCHEME_UCS2; - break; - - case 0x04: case 0x05: case 0x06: case 0x07: - if (dataCoding & 0x20) return SMS_CODING_SCHEME_UNKNOWN; /* compressed 7-bits */ - if (((dataCoding >> 2) & 3) == 0) return SMS_CODING_SCHEME_GSM7; - if (((dataCoding >> 2) & 3) == 2) return SMS_CODING_SCHEME_UCS2; - break; - - case 0xF: - if (!(dataCoding & 4)) return SMS_CODING_SCHEME_GSM7; - break; - } - return SMS_CODING_SCHEME_UNKNOWN; -} - - -/* see TS 23.040 section 9.2.3.24 for details */ -static int -sms_get_text_utf8( cbytes_t *pcur, - cbytes_t end, - int hasUDH, - SmsCodingScheme coding, - GsmRope rope ) -{ - cbytes_t cur = *pcur; - int result = -1; - int len; - -#ifdef nodroid - printf("sms_get_text_utf8 %d %d\n",hasUDH,coding); -#endif - if (cur >= end) - goto Exit; - - len = *cur++; - - /* skip user data header if any */ - if ( hasUDH ) - { - int hlen; - - if (cur >= end) - goto Exit; - - hlen = *cur++; - if (cur + hlen > end) - goto Exit; - - cur += hlen; - - if (coding == SMS_CODING_SCHEME_GSM7) - len -= (hlen*2-2); - else - len -= hlen+1; - - if (len < 0) - goto Exit; - } - - /* switch the user data header if any */ - if (coding == SMS_CODING_SCHEME_GSM7) - { - int count = utf8_from_gsm7( cur, 0, len, NULL ); - - if (rope != NULL) - { - bytes_t dst = gsm_rope_reserve( rope, count ); - if(hasUDH && dst) - *dst++=(*cur++)>>1; - if (dst != NULL) - utf8_from_gsm7( cur, 0, len, dst ); - } - cur += (len+1)/2; - } - else if (coding == SMS_CODING_SCHEME_UCS2) - { - int count = ucs2_to_utf8( cur, len/2, NULL ); - - if (rope != NULL) - { - bytes_t dst = gsm_rope_reserve( rope, count ); - if (dst != NULL) - ucs2_to_utf8( cur, len/2, dst ); - } - cur += len; - } - result = 0; - -Exit: - if (!result) - *pcur = cur; - - return result; -} - -/* get the message embedded in a SMS PDU as a utf8 byte array, returns the length of the message in bytes */ -/* or -1 in case of error */ -int -smspdu_get_text_message( SmsPDU pdu, unsigned char* utf8, int utf8len ) -{ - cbytes_t data = pdu->tpdu; - cbytes_t end = pdu->end; - int mtiByte = sms_get_byte( &data, end ); - - switch (mtiByte & 3) { - case 0: /* SMS_PDU_DELIVER */ - { - SmsAddressRec address; - SmsTimeStampRec timestamp; - SmsCodingScheme coding; - GsmRopeRec rope[1]; - int result; - - if ( sms_get_sc_address( &data, end, &address ) < 0 ) - goto Fail; - - data += 1; /* skip protocol identifier */ - coding = sms_get_coding_scheme( &data, end ); - if (coding == SMS_CODING_SCHEME_UNKNOWN) - goto Fail; - - if ( sms_get_timestamp( &data, end, ×tamp ) < 0 ) - goto Fail; - - gsm_rope_init_alloc( rope, 0 ); - if ( sms_get_text_utf8( &data, end, (mtiByte & 0x40), coding, rope ) < 0 ) - goto Fail; - - result = rope->pos; - if (utf8len > result) - utf8len = result; - - if (utf8len > 0) - memcpy( utf8, rope->data, utf8len ); - - gsm_rope_done( rope ); - return result; - } - - case 1: /* SMS_PDU_SUBMIT */ - { - SmsAddressRec address; - SmsCodingScheme coding; - GsmRopeRec rope[1]; - int result; - - data += 1; /* message reference */ - - if ( sms_get_address( &data, end, &address ) < 0 ) - goto Fail; - - data += 1; /* skip protocol identifier */ - coding = sms_get_coding_scheme( &data, end ); - if (coding == SMS_CODING_SCHEME_UNKNOWN) - goto Fail; - - gsm_rope_init_alloc( rope, 0 ); - if ( sms_get_text_utf8( &data, end, (mtiByte & 0x40), coding, rope ) < 0 ) { - gsm_rope_done( rope ); - goto Fail; - } - - result = rope->pos; - if (utf8len > result) - utf8len = result; - - if (utf8len > 0) - memcpy( utf8, rope->data, utf8len ); - - gsm_rope_done( rope ); - return result; - } - } -Fail: - return -1; -} - - -static void -gsm_rope_add_sms_user_header( GsmRope rope, - int ref_number, - int pdu_count, - int pdu_index ) -{ - gsm_rope_add_c( rope, 0x05 ); /* total header length == 5 bytes */ - gsm_rope_add_c( rope, 0x00 ); /* element id: concatenated message reference number */ - gsm_rope_add_c( rope, 0x03 ); /* element len: 3 bytes */ - gsm_rope_add_c( rope, (byte_t)ref_number ); /* reference number */ - gsm_rope_add_c( rope, (byte_t)pdu_count ); /* max pdu index */ - gsm_rope_add_c( rope, (byte_t)pdu_index+1 ); /* current pdu index */ -} - -/* write a SMS-DELIVER PDU into a rope */ -static void -gsm_rope_add_sms_deliver_pdu( GsmRope rope, - cbytes_t utf8, - int utf8len, - int use_gsm7, - const SmsAddressRec* sender_address, - const SmsTimeStampRec* timestamp, - int ref_num, - int pdu_count, - int pdu_index) -{ - int count; - int coding; - int mtiByte = 0x20; /* message type - SMS DELIVER */ - - if (pdu_count > 1) - mtiByte |= 0x40; /* user data header indicator */ - - gsm_rope_add_c( rope, 0 ); /* no SC Address */ - gsm_rope_add_c( rope, mtiByte ); /* message type - SMS-DELIVER */ - gsm_rope_add_address( rope, sender_address ); - gsm_rope_add_c( rope, 0 ); /* protocol identifier */ - - /* data coding scheme - GSM 7 bits / no class - or - 16-bit UCS2 / class 1 */ - coding = (use_gsm7 ? 0x00 : 0x09); - - gsm_rope_add_c( rope, coding ); /* data coding scheme */ - gsm_rope_add_timestamp( rope, timestamp ); /* service center timestamp */ - - if (use_gsm7) { - bytes_t dst; - int count = utf8_to_gsm7( utf8, utf8len, NULL, 0 ); - int pad = 0; - - //assert( count <= MAX_USER_DATA_SEPTETS - USER_DATA_HEADER_SIZE ); - - if (pdu_count > 1) - { - int headerBits = 6*8; /* 6 is size of header in bytes */ - int headerSeptets = headerBits / 7; - if (headerBits % 7 > 0) - headerSeptets += 1; - - pad = headerSeptets*7 - headerBits; - - gsm_rope_add_c( rope, count + headerSeptets ); - gsm_rope_add_sms_user_header(rope, ref_num, pdu_count, pdu_index); - } - else - gsm_rope_add_c( rope, count ); - - count = (count*7+pad+7)/8; /* convert to byte count */ - - dst = gsm_rope_reserve( rope, count ); - if (dst != NULL) { - utf8_to_gsm7( utf8, utf8len, dst, pad ); - } - } else { - bytes_t dst; - int count = utf8_to_ucs2( utf8, utf8len, NULL ); - - //assert( count*2 <= MAX_USER_DATA_BYTES - USER_DATA_HEADER_SIZE ); - - if (pdu_count > 1) - { - gsm_rope_add_c( rope, count*2 + 6 ); - gsm_rope_add_sms_user_header( rope, ref_num, pdu_count, pdu_index ); - } - else - gsm_rope_add_c( rope, count*2 ); - - gsm_rope_add_c( rope, count*2 ); - dst = gsm_rope_reserve( rope, count*2 ); - if (dst != NULL) { - utf8_to_ucs2( utf8, utf8len, dst ); - } - } -} - - -static SmsPDU -smspdu_create_deliver( cbytes_t utf8, - int utf8len, - int use_gsm7, - const SmsAddressRec* sender_address, - const SmsTimeStampRec* timestamp, - int ref_num, - int pdu_count, - int pdu_index ) -{ - SmsPDU p; - GsmRopeRec rope[1]; - int size; - - p = calloc( sizeof(*p), 1 ); - if (!p) goto Exit; - - gsm_rope_init( rope ); - gsm_rope_add_sms_deliver_pdu( rope, utf8, utf8len, use_gsm7, - sender_address, timestamp, - ref_num, pdu_count, pdu_index); - if (rope->error) - goto Fail; - - gsm_rope_init_alloc( rope, rope->pos ); - - gsm_rope_add_sms_deliver_pdu( rope, utf8, utf8len, use_gsm7, - sender_address, timestamp, - ref_num, pdu_count, pdu_index ); - - p->base = gsm_rope_done_acquire( rope, &size ); - if (p->base == NULL) - goto Fail; - - p->end = p->base + size; - p->tpdu = p->base + 1; -Exit: - return p; - -Fail: - free(p); - return NULL; -} - - -void -smspdu_free_list( SmsPDU* pdus ) -{ - if (pdus) { - int nn; - for (nn = 0; pdus[nn] != NULL; nn++) - smspdu_free( pdus[nn] ); - - free( pdus ); - } -} - - - -SmsPDU* -smspdu_create_deliver_utf8( const unsigned char* utf8, - int utf8len, - const SmsAddressRec* sender_address, - const SmsTimeStampRec* timestamp ) -{ - SmsTimeStampRec ts0; - int use_gsm7; - int count, block; - int num_pdus = 0; - int leftover = 0; - SmsPDU* list = NULL; - - static unsigned char ref_num = 0; - - if (timestamp == NULL) { - sms_timestamp_now( &ts0 ); - timestamp = &ts0; - } - - /* can we encode the message with the GSM 7-bit alphabet ? */ - use_gsm7 = utf8_check_gsm7( utf8, utf8len ); - - /* count the number of SMS PDUs we'll need */ - block = MAX_USER_DATA_SEPTETS - USER_DATA_HEADER_SIZE; - - if (use_gsm7) { - count = utf8_to_gsm7( utf8, utf8len, NULL, 0 ); - } else { - count = utf8_to_ucs2( utf8, utf8len, NULL ); - block = MAX_USER_DATA_BYTES - USER_DATA_HEADER_SIZE; - } - - num_pdus = count / block; - leftover = count - num_pdus*block; - if (leftover > 0) - num_pdus += 1; - - list = calloc( sizeof(SmsPDU*), count + 1 ); - if (list == NULL) - return NULL; - - /* now create each SMS PDU */ - { - cbytes_t src = utf8; - cbytes_t src_end = utf8 + utf8len; - int nn; - - for (nn = 0; nn < num_pdus; nn++) - { - int skip = block; - cbytes_t src_next; - - if (leftover > 0 && nn == num_pdus-1) - skip = leftover; - - src_next = utf8_skip( src, src_end, skip ); - list[nn] = smspdu_create_deliver( src, src_next - src, use_gsm7, sender_address, timestamp, - ref_num, num_pdus, nn ); - if (list[nn] == NULL) - goto Fail; - - src = src_next; - } - } - - ref_num++; - -Exit: - return list; - -Fail: - smspdu_free_list(list); - return NULL; -} - - -SmsPDU -smspdu_create_from_hex( const char* hex, int hexlen ) -{ - SmsPDU p; - cbytes_t data; - - p = calloc( sizeof(*p), 1 ); - if (!p) goto Exit; - - p->base = malloc( (hexlen+1)/2 ); - if (p->base == NULL) { - free(p); - p = NULL; - goto Exit; - } - - gsm_hex_to_bytes( hex, hexlen, p->base ); - p->end = p->base + (hexlen+1)/2; - - data = p->base; - if ( sms_skip_sc_address( &data, p->end ) < 0 ) - goto Fail; - - p->tpdu = (bytes_t) data; - -Exit: - return p; - -Fail: - free(p->base); - free(p); - return NULL; -} - -int -smspdu_to_hex( SmsPDU pdu, char* hex, int hexlen ) -{ - int result = (pdu->end - pdu->base)*2; - int nn; - - if (hexlen > result) - hexlen = result; - - for (nn = 0; nn*2 < hexlen; nn++) { - gsm_hex_from_byte( &hex[nn*2], pdu->base[nn] ); - } - return result; -} - diff --git a/sms_gsm.h b/sms_gsm.h deleted file mode 100644 index e521803..0000000 --- a/sms_gsm.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef _android_sms_h -#define _android_sms_h - -#include - -/** MESSAGE TEXT - **/ -/* convert a quoted message text into a utf8 string. Note: you can use 'str' as the destination buffer - * with the current implementation. always return the number of utf8 bytes corresponding to the original - * message string, even if utf8 is NULL and utf8len is 0 - */ -extern int sms_utf8_from_message_str( const char* str, int strlen, unsigned char* utf8, int utf8len ); - -/** TIMESTAMPS - **/ - -/* An SMS timestamp structure */ -typedef struct { - unsigned char data[7]; -} SmsTimeStampRec, *SmsTimeStamp; - -extern void sms_timestamp_now( SmsTimeStamp stamp ); -extern int sms_timestamp_to_tm( SmsTimeStamp stamp, struct tm* tm ); - -/** SMS ADDRESSES - **/ - -#define SMS_ADDRESS_MAX_SIZE 16 - -typedef struct { - unsigned char len; - unsigned char toa; - unsigned char data[ SMS_ADDRESS_MAX_SIZE ]; -} SmsAddressRec, *SmsAddress; - -extern int sms_address_from_str( SmsAddress address, const char* src, int srclen ); -extern int sms_address_to_str( SmsAddress address, char* src, int srclen ); - -extern int sms_address_from_bytes( SmsAddress address, const unsigned char* buf, int buflen ); -extern int sms_address_to_bytes ( SmsAddress address, unsigned char* buf, int bufsize ); -extern int sms_address_from_hex ( SmsAddress address, const char* hex, int hexlen ); -extern int sms_address_to_hex ( SmsAddress address, char* hex, int hexsize ); - -/** SMS PROTOCOL DATA UNITS - **/ - -typedef struct SmsPDURec* SmsPDU; - -extern SmsPDU* smspdu_create_deliver_utf8( const unsigned char* utf8, - int utf8len, - const SmsAddressRec* sender_address, - const SmsTimeStampRec* timestamp ); - -extern void smspdu_free_list( SmsPDU* pdus ); - -extern SmsPDU smspdu_create_from_hex( const char* hex, int hexlen ); - -extern int smspdu_to_hex( SmsPDU pdu, char* hex, int hexsize ); - -/* free a given SMS PDU */ -extern void smspdu_free( SmsPDU pdu ); - -typedef enum { - SMS_PDU_INVALID = 0, - SMS_PDU_DELIVER, - SMS_PDU_SUBMIT, - SMS_PDU_STATUS_REPORT -} SmsPduType; - -extern SmsPduType smspdu_get_type( SmsPDU pdu ); - -/* retrieve the sender address of a SMS-DELIVER pdu, returns -1 otherwise */ -extern int smspdu_get_sender_address( SmsPDU pdu, SmsAddress address ); - -/* retrieve the service center timestamp of a SMS-DELIVER pdu, return -1 otherwise */ -extern int smspdu_get_sc_timestamp( SmsPDU pdu, SmsTimeStamp timestamp ); - -/* retrieve the receiver address of a SMS-SUBMIT pdu, return -1 otherwise */ -extern int smspdu_get_receiver_address( SmsPDU pdu, SmsAddress address ); - -/* get the message embedded in a SMS PDU as a utf8 byte array, returns the length of the message in bytes */ -/* or -1 in case of error */ -extern int smspdu_get_text_message( SmsPDU pdu, unsigned char* utf8, int utf8len ); - -#endif /* _android_sms_h */ -- 2.1.4