diff options
Diffstat (limited to 'utils.c')
-rw-r--r-- | utils.c | 155 |
1 files changed, 155 insertions, 0 deletions
@@ -61,6 +61,161 @@ void list_head_free(struct list_head *list) free(list); } +/* + * Converts GSM7 (8 bits) data to ASCII (7 bits) + */ +int gsm72ascii(unsigned char *data, char **data_dec, int length) +{ + int t, u, d, o = 0; + int i; + + int dec_length; + char *dec; + + dec_length = ((length * 8) - ((length * 8) % 7) ) / 7; + dec = malloc(dec_length); + + memset(dec, 0, dec_length); + + for (i = 0 ; i < length ; i++) + { + d = 7 - i % 7; + if (d == 7 && i != 0) + o++; + + t = (data[i] - (((data[i] >> d) & 0xff) << d)); + u = (data[i] >> d) & 0xff; + + dec[i+o]+=t << (i + o) % 8; + + if (u) + dec[i+1+o]+=u; + } + + *data_dec = dec; + + return dec_length; +} + +/* + * Converts ASCII (7 bits) data to GSM7 (8 bits) + */ +int ascii2gsm7_ussd(char *data, unsigned char **data_enc, int length) +{ + int d_off, d_pos, a_off, a_pos = 0; + int i; + + int enc_length; + unsigned char *enc; + + enc_length = ((length * 7) - (length * 7) % 8) / 8; + enc_length += (length * 7) % 8 > 0 ? 1 : 0; + + //FIXME: why does samsung does that? + enc_length++; + + enc = malloc(enc_length); + memset(enc, 0, enc_length); + + for (i = 0 ; i < length ; i++) + { + // offset from the right of data to keep + d_off = i % 8; + + // position of the data we keep + d_pos = ((i * 7) - (i * 7) % 8) / 8; + d_pos += (i * 7) % 8 > 0 ? 1 : 0; + + // adding the data with correct offset + enc[d_pos] |= data[i] >> d_off; + + // numbers of bits to omit to get data to add another place + a_off = 8 - d_off; + // position (on the encoded feed) of the data to add + a_pos = d_pos - 1; + + // adding the data to add at the correct position + enc[a_pos] |= data[i] << a_off; + } + + *data_enc = enc; + + //FIXME: what is going on here? + enc[enc_length - 2] |= 0x30; + enc[enc_length - 1] = 0x02; + + return enc_length; +} + +/* writes the utf8 character encoded in v + * to the buffer utf8 at the specified offset + */ +int utf8_write(char *utf8, int offset, int v) +{ + + int result; + + if (v < 0x80) { + result = 1; + if (utf8) + utf8[offset] = (char)v; + } else if (v < 0x800) { + result = 2; + if (utf8) { + utf8[offset + 0] = (char)(0xc0 | (v >> 6)); + utf8[offset + 1] = (char)(0x80 | (v & 0x3f)); + } + } else if (v < 0x10000) { + result = 3; + if (utf8) { + utf8[offset + 0] = (char)(0xe0 | (v >> 12)); + utf8[offset + 1] = (char)(0x80 | ((v >> 6) & 0x3f)); + utf8[offset + 2] = (char)(0x80 | (v & 0x3f)); + } + } else { + result = 4; + if (utf8) { + utf8[offset + 0] = (char)(0xf0 | ((v >> 18) & 0x7)); + utf8[offset + 1] = (char)(0x80 | ((v >> 12) & 0x3f)); + utf8[offset + 2] = (char)(0x80 | ((v >> 6) & 0x3f)); + utf8[offset + 3] = (char)(0x80 | (v & 0x3f)); + } + } + return result; +} + +sms_coding_scheme sms_get_coding_scheme(int data_encoding) +{ + switch (data_encoding >> 4) { + case 0x00: + case 0x02: + case 0x03: + return SMS_CODING_SCHEME_GSM7; + case 0x01: + if (data_encoding == 0x10) + return SMS_CODING_SCHEME_GSM7; + if (data_encoding == 0x11) + return SMS_CODING_SCHEME_UCS2; + break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + if (data_encoding & 0x20) + return SMS_CODING_SCHEME_UNKNOWN; + if (((data_encoding >> 2) & 3) == 0) + return SMS_CODING_SCHEME_GSM7; + if (((data_encoding >> 2) & 3) == 2) + return SMS_CODING_SCHEME_UCS2; + break; + case 0xF: + if (!(data_encoding & 4)) + return SMS_CODING_SCHEME_GSM7; + break; + } + return SMS_CODING_SCHEME_UNKNOWN; +} + int data_dump(const void *data, size_t size) { unsigned int cols = 8; |