#include #include #include #include "gsm.h" #define DIVC(x,y) ((x) / (y) + ((x) % (y) != 0)) uint8_t pdu_getc(char *pdu) { int ch; sscanf(pdu, "%2X", &ch); return ch; } void pdu_putc(uint8_t ch, char *pdu) { sprintf(pdu, "%.2X", ch); } void pdu_puts(uint8_t *s, int s_len, char *pdu) { int i; for (i=0; i> 8) & GSM_DCS_CLASS; } if (flags & GSM_FLAG_COMPRESS) *dcs |= GSM_DCS_COMPRESS_IND; if (flags & GSM_FLAG_DELETE) *dcs |= GSM_DCS_DELETE_IND; } int gsm_ts_enc(char *ts, char *pdu, int pdu_size) { uint8_t tz; int tz_hh, tz_mm; if (pdu_size < 14) return GSM_ERR; pdu[1] = ts[2]; // YY pdu[0] = ts[3]; pdu[3] = ts[5]; // MM pdu[2] = ts[6]; pdu[5] = ts[8]; // DD pdu[4] = ts[9]; pdu[7] = ts[11]; // hh pdu[6] = ts[12]; pdu[9] = ts[14]; // mm pdu[8] = ts[15]; pdu[11] = ts[17]; // ss pdu[10] = ts[18]; sscanf(ts + 20, "%2d:%2d", &tz_hh, &tz_mm); tz = tz_hh * 4 + tz_mm / 15; tz = (tz / 10) | ((tz % 10) << 4); if (ts[19] == '-') tz |= 0x08; pdu_putc(tz, pdu + 12); return 14; } int gsm_ts_dec(char *pdu, int pdu_len, char *ts) { uint8_t tz; if (pdu_len < 14) return GSM_ERR; ts[0] = '2'; ts[1] = '0'; ts[2] = pdu[1]; // YY ts[3] = pdu[0]; ts[4] = '-'; ts[5] = pdu[3]; // MM ts[6] = pdu[2]; ts[7] = '-'; ts[8] = pdu[5]; // DD ts[9] = pdu[4]; ts[10] = 'T'; ts[11] = pdu[7]; // hh ts[12] = pdu[6]; ts[13] = ':'; ts[14] = pdu[9]; // mm ts[15] = pdu[8]; ts[16] = ':'; ts[17] = pdu[11]; // ss ts[18] = pdu[10]; tz = pdu_getc(pdu + 12); if (tz & 0x08) { ts[19] = '-'; tz = tz & ~0x08; } else { ts[19] = '+'; } tz = (tz & 0x0f) * 10 + (tz >> 4); sprintf(ts + 20, "%.2d:%.2d", tz / 4, (tz % 4) * 15); return 14; } int gsm_7bit_enc(char *text, int text_len, char *pdu, int padb) { uint8_t carry = 0; int i = 0, pdu_len = 0, shc = 0; if (!text_len) return 0; if (padb) { shc = 7 - padb; } else { carry = *text; i++; } while (i < text_len) { pdu_putc(carry | (*(text + i) << (7 - shc)), pdu + pdu_len); pdu_len += 2; shc++; shc = shc % 7; if (!shc) { i++; if (i == text_len) return pdu_len; } carry = *(text + i) >> shc; i++; } pdu_putc(carry, pdu + pdu_len); pdu_len += 2; return pdu_len; } int gsm_7bit_dec(char *pdu, char *text, int text_len, int padb) { uint8_t ch; uint8_t carry = 0; int i = 0, pdu_len = 0, shc = 0; if (!text_len) return 0; if (padb) { ch = pdu_getc(pdu); pdu_len += 2; if (padb == 1) { *text = ch >> 1; i++; } else { carry = ch >> padb; shc = 8 - padb; } } while (i < text_len) { ch = pdu_getc(pdu + pdu_len); pdu_len += 2; *(text + i) = ((ch << shc) | carry) & 0x7f; carry = ch >> (7 - shc); i++; shc++; shc = shc % 7; if (!shc && (i < text_len)) { *(text + i) = carry; carry = 0; i++; } } return pdu_len; } int gsm_addr_enc(char *addr, int addr_len, uint8_t addr_type, char *pdu, int pdu_size) { int _pdu_len; addr_type |= GSM_EXT; if ((addr_type & GSM_TON) == GSM_TON_ALPHANUMERIC) { int _addr_len = DIVC(addr_len * 7, 4); _pdu_len = 4 + DIVC(_addr_len, 2) * 2; if (pdu_size < _pdu_len) return GSM_ERR; pdu_putc(_addr_len, pdu); pdu_putc(addr_type, pdu + 2); gsm_7bit_enc(addr, addr_len, pdu, 0); } else { int i; if (addr_type & GSM_TON_INTERNATIONAL) { if (addr[0] != '+') return GSM_ERR; addr++; addr_len--; } _pdu_len = 4 + DIVC(addr_len, 2) * 2; if (pdu_size < _pdu_len) return GSM_ERR; pdu_putc(addr_len, pdu); pdu_putc(addr_type, pdu + 2); for (i=0; i