summaryrefslogtreecommitdiffstats
path: root/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils.c')
-rw-r--r--utils.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/utils.c b/utils.c
index 164812e..80b95e7 100644
--- a/utils.c
+++ b/utils.c
@@ -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;