+#define SET_TON_NPI(dest, ton, npi) { \
+ dest = 0x80; \
+ dest |= (ton & 0x07) << 4; \
+ dest |= npi & 0x0F; \
+}
+
+static int __bt_ascii_to_upper(int ch)
+{
+ return (('a' <= (ch) && (ch) <= 'z') ? ((ch) - ('a'-'A')) : (ch));
+}
+
+static int __bt_sms_pack_gsm_code(gchar *p_out, const char *data, int in_len)
+{
+ DBG("+");
+ int i;
+ int pos;
+ int shift = 0;
+
+ for (pos = 0, i = 0; i < in_len; pos++, i++) {
+ /* pack the low bits */
+ p_out[pos] = data[i] >> shift;
+
+ if (i + 1 < in_len) {
+ /* pack the high bits using the low bits
+ of the next character */
+ p_out[pos] |= data[i+1] << (7 - shift);
+
+ shift++;
+
+ if (shift == 7) {
+ shift = 0;
+ i++;
+ }
+ }
+ }
+ DBG("-");
+ return pos;
+}
+
+static void __bt_sms_conv_digit_to_bcd(gchar *p_bcd, char *p_digits, int digit_len)
+{
+ int i;
+ int j;
+ int digit;
+ unsigned char higher;
+ unsigned char lower;
+
+ if (p_bcd == NULL || p_digits == NULL)
+ return;
+
+ /* 0123456789 -> 1032547698 */
+ for (i = 0, j = 0; i < digit_len; i = i + 2, j++) {
+ if (p_digits[i] == '*')
+ digit = 0x0A;
+ else if (p_digits[i] == '#')
+ digit = 0x0B;
+ else if (__bt_ascii_to_upper(p_digits[i]) == 'P')
+ digit = 0x0C;
+ else
+ digit = (int) (p_digits[i] - '0');
+
+ lower = digit & 0x0F;
+
+ if (digit_len != i + 1) {
+ if (p_digits[i+1] == '*')
+ digit = 0x0A;
+ else if (p_digits[i+1] == '#')
+ digit = 0x0B;
+ else if (__bt_ascii_to_upper(p_digits[i+1]) == 'P')
+ digit = 0x0C;
+ else
+ digit = (int) (p_digits[i+1] - '0');
+
+ higher = digit & 0x0F;
+ } else {
+ higher = 0xFF;
+ }
+
+ p_bcd[j] = (higher << 4) | lower;
+ }
+}
+
+static int __bt_sms_encode_addr(gchar *addr_field, char *dial_num,
+ int dial_num_len, int ton, int npi)
+{
+ DBG("+");
+ int index = 0;
+
+ if (dial_num == NULL || addr_field == NULL)
+ return -1;
+
+ if (dial_num[0] == '+') {
+ dial_num++;
+ dial_num_len--;
+ ton = SMS_TON_INTERNATIONAL;
+ }
+
+ if (ton != SMS_TON_ALPHA_NUMERIC) {
+ /* Origination address length address length */
+ addr_field[index++] = (unsigned char)dial_num_len;
+ } else {
+ addr_field[index] = (unsigned char)
+ (((dial_num_len * 7 + 7) / 8) * 2);
+
+ if (((dial_num_len * 7) % 8) <= 4)
+ addr_field[index]--;
+
+ index++;
+ }
+
+ SET_TON_NPI(addr_field[index], ton, npi);
+ index++; /* SET_TON_NPI */
+
+ if (ton != SMS_TON_ALPHA_NUMERIC) {
+ __bt_sms_conv_digit_to_bcd(&addr_field[index],
+ (char *)dial_num, dial_num_len);
+
+ if (dial_num_len % 2)
+ index += (dial_num_len / 2) + 1;
+ else
+ index += dial_num_len / 2;
+ } else {
+ index += __bt_sms_pack_gsm_code(&addr_field[index],
+ dial_num, (int)dial_num_len);
+ }
+
+ return index;
+}
+
+static int __bt_sms_encode_time(gchar *addr_field, time_t *tm)
+{
+ int index = 0;
+ struct tm ltime;
+ int year;
+ int month;
+
+ if (!localtime_r(tm, <ime))
+ return index;
+
+ year = ltime.tm_year + 1900; /* years since 1900 */
+ year = year % 100;
+ month = ltime.tm_mon + 1; /* months since January */
+
+ addr_field[index++] = ((year % 10) << 4) + (year / 10);
+ addr_field[index++] = ((month % 10) << 4) + (month / 10);
+ addr_field[index++] = ((ltime.tm_mday % 10) << 4) +
+ (ltime.tm_mday / 10);
+ addr_field[index++] = ((ltime.tm_hour % 10) << 4) +
+ (ltime.tm_hour / 10);
+ addr_field[index++] = ((ltime.tm_min % 10) << 4) + (ltime.tm_min / 10);
+ addr_field[index++] = ((ltime.tm_sec % 10) << 4) + (ltime.tm_sec / 10);
+ addr_field[index] = 0x00;
+
+ return index;
+}
+
+static gchar *__bt_get_sms_pdu_from_msg_data(gchar *number,
+ char *msg, time_t tm,
+ int *msg_pdu_len)
+{
+ DBG("+");
+ gchar packet[TAPI_NETTEXT_MSG_SIZE_MAX] = {0,};
+ int index = 0;
+
+ packet[index] = 0x00; /* Since SCA is unknown for stored messages */
+ index++;
+
+ /* TP-MTI : Type of message */
+ packet[index] = 0x00; /* SMS-DELIVER PDU */
+
+ /* TP-MMS bit is set to 1 as we support only SMS */
+ packet[index] |= 0x04;
+ index++;
+
+ /* TP-OA : Mobile originating address */
+ index += __bt_sms_encode_addr(packet+index,
+ number, strlen(number),
+ g_sca_info->Ton, g_sca_info->Npi);
+
+ /* TP-PID : Since we use only SMS so set to 0 */
+ packet[index++] = 0x00;
+
+ /* TP-DCS : Data Coding Scheme, default value set */
+ packet[index++] = 0x00;
+
+ /* TP-SCTS : Message timestamp */
+ index += __bt_sms_encode_time(packet+index, &tm);
+ index++;
+ /* TP-UDL : Message body length */
+ packet[index++] = strlen(msg);
+
+ /* TP-UD : Message body */
+ index += __bt_sms_pack_gsm_code(packet + index, msg, strlen(msg));
+
+ *msg_pdu_len = index;
+ DBG("-");
+
+ return g_memdup(packet, index);
+}
+
+static void __bt_get_sms_sca(TapiHandle *handle, int result, void *data,
+ void *user_data)
+{
+ TelSmsAddressInfo_t *scaInfo = data;
+ unsigned int i = 0;
+
+ DBG("__bt_get_sms_sca 0x%x", result);
+
+ if (data == NULL)
+ return;
+
+ g_sca_info = g_malloc0(sizeof(TelSmsAddressInfo_t));
+ g_sca_info->Ton = scaInfo->Ton;
+ g_sca_info->Npi = scaInfo->Npi;
+ g_sca_info->DialNumLen = scaInfo->DialNumLen;
+
+ DBG(" - TON = %d", scaInfo->Ton);
+ DBG(" - NPI = %d", scaInfo->Npi);
+ DBG(" - DialNumLen = %d", scaInfo->DialNumLen);
+ DBG(" - SCA Num");
+
+ for (i = 0; i < scaInfo->DialNumLen; i++) {
+ g_sca_info->szDiallingNum[i] = scaInfo->szDiallingNum[i];
+ DBG("[%02x]", g_sca_info->szDiallingNum[i]);
+ }
+}
+