summaryrefslogtreecommitdiff
path: root/src/pdu.h
blob: 5b4eb155fddb9b31d5e4a0f687c82c4b8fdb429a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifndef __PDU_H
#define __PDU_H

#include <stdint.h>
#include <string.h>
#include <time.h>

#include <phonebook.h>

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
};

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;
	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 */