#ifndef __PDU_H #define __PDU_H #include #include #include #include extern char *strptime(const char *s, const char *format, struct tm *tm); #define PDU_BUFFER_SIZE 1024 #define PDU_ADDR_SIZE PHONEBOOK_ADDR_SIZE #define PDU_OCTETS_MAX 140 #define PDU_UD_8BIT_MAX PDU_OCTETS_MAX #define PDU_UD_7BIT_MAX (PDU_OCTETS_MAX * 8 / 7) #define PDU_UD_SIZE (PDU_UD_7BIT_MAX + 1) #define PDU_TIMESTAMP_LEN 14 #define PDU_CDMA_TIMESTAMP_LEN 12 #define PDU_TIMESTAMP_SIZE (PDU_TIMESTAMP_LEN + 1) #define GMT_OFFSET_LEN 2 #define GMT_OFFSET_IDX (PDU_TIMESTAMP_LEN - GMT_OFFSET_LEN) #define PDU_VPF_RELATIVE_2DAYS 0xA8 #define GSM_TABLE_SIZE 128 extern char strGSMTable[]; extern char strExtendedTable[]; struct pdu_addr { char addr[PDU_ADDR_SIZE]; uint8_t type; uint8_t len; }; enum { PDU_MTI_DELIVER = 0, PDU_MTI_SUBMIT = 1, PDU_MTI_REPORT = 2, PDU_MTI_RESERVED = 3, }; enum { PDU_VPF_NOT_PRESENT = 0, PDU_VPF_ENHANCED = 1, PDU_VPF_RELATIVE = 2, PDU_VPF_ABSOUTE = 3, }; //PDU data formats (how the data was represented before encoding) enum { PDU_ALPHABET_DEFAULT = 0, //GSM 7-bit, (supposedly CDMA 8-bit but haven't seen it) PDU_ALPHABET_DEFAULT2 = 1, //GSM 7-bit (used with some shortcodes) PDU_ALPHABET_CDMA_DEFAULT = 2, //no GSM, CDMA 7-bit PDU_ALPHABET_TE = 3, //TE specific PDU_ALPHABET_EIGHT = 4, //GSM 8-bit, CDMA 16-bit unicode PDU_ALPHABET_CDMA_EIGHT = 8, //GSM 16-bit, CDMA 8-bit (what CDMA radios are actually using) PDU_ALPHABET_DEFAULT_MULTI = 9,//no GSM, LVW2 7-bit, multi-part }; // CDMA Teleservice Identifiers (what type of message is received in CDMA network) // All such identifiers are described in 3GPP2 X.S0004-550-E, section 2.256 SMS_TeleserviceIdentifier enum { PDU_TELE_ID_UNUSED = 0, // Not used. // 1 - Reserved for maintenance. // 2 through 4095 - Reserved for assignment by MAP. // ... PDU_TELE_ID_CDMA_PAGE = 4097, // CDMA Cellular Paging Teleservice. PDU_TELE_ID_CDMA_MSG = 4098, // CDMA Cellular Messaging Teleservices. PDU_TELE_ID_CDMA_VOICE_MSG_NOTIF = 4099, // CDMA Voice Mail Notification // ... PDU_TELE_ID_CDMA_WEMT = 4101 // CDMA Wireless Enhanced Messaging Teleservice (WEMT). // ... }; struct pdu_info { int msg_len; struct pdu_addr smsc_addr; struct pdu_addr addr; union { uint8_t type; struct { uint8_t msg_type: 2; uint8_t reject_duplicates: 1; uint8_t validity_period_format: 2; uint8_t status_report: 1; uint8_t user_data_header: 1; uint8_t reply_path: 1; }; } type; uint8_t msg_reference; uint8_t protocol_id; uint16_t teleservice_id; // CDMA-specific, see 3GPP2 X.S0004-550-E for details union { uint8_t data_coding; struct { // uint8_t msg_class: 2; uint8_t alphabet: 4; uint8_t have_msg_class: 1; uint8_t compressed: 1; uint8_t unused: 2; } general; } data_coding; uint8_t validity_period; struct tm timestamp; uint8_t user_data_len; uint8_t user_data[PDU_UD_SIZE]; }; #define HEX_BYTE_LEN 2 int hex_nibble_scan(const char *buf, size_t len); int hex_byte_decode(const char *buf); int hex_byte_encode(char *buf, size_t len, int byte); int nibble_swap(char *buf, size_t len); int strunpad(char *str, unsigned char c); int strpad(char *str, size_t len, unsigned char c); int pdu_format_timestamp(struct pdu_info *pdu, char *str, size_t len, const char *fmt); int pdu_format_vp(struct pdu_info *pdu, char *str, size_t len); int pdu_addr_type_infer(const char *str); int pdu_addr_fill(struct pdu_addr *addr, const char *addr_str, int type); int pdu_user_data_read(int fd, struct pdu_info *pdu); #define shiftr(a, n) ((a) >> (n)) #define shiftl(a, n) ((a) << (n)) #define bit_mask(n, s) (((1 << (n)) - 1) << (s)) #define bit_maskr(n) bit_mask(n, 0) #define bit_maskl(n, b) bit_mask(n, (b) - (n)) #define cycleup(n, mod) ((n) % (mod)) #define cycledown(n, mod) ((mod - 1) - ((n) % (mod))) //Returns the number of octets the given septets (normal ascii) can be encoded to #define octets_from_septets(n) ((((n) * 7) + ((-(n) * 7) & 7)) / 8) //Returns the number of septets the given octets will decode to #define septets_from_octets(n) ((n) * 8 / 7) #define octet_idx(n) octets_from_septets(n) #define septet_idx(n) septets_from_octets(n) #define STRLEN_CHECK(str, len, ret) \ do { \ if (strnlen(str, len) < len) { \ log_error("buffer ends unexpectedly early"); \ return ret; \ } \ } while (0) #endif /* ~__PDU_H */