3155dcf1d1f705556c8d6b31e487e21820ff314c
[project/uqmi.git] / commands-wms.c
1 #include "qmi-message.h"
2
3 static void cmd_wms_list_messages_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
4 {
5         struct qmi_wms_list_messages_response res;
6         int i, len = 0;
7
8         qmi_parse_wms_list_messages_response(msg, &res);
9         blobmsg_alloc_string_buffer(&status, "messages", 1);
10         for (i = 0; i < res.data.message_list_n; i++) {
11                 len += sprintf(blobmsg_realloc_string_buffer(&status, len + 12) + len,
12                                " %d" + (len ? 0 : 1),
13                                            res.data.message_list[i].memory_index);
14         }
15         blobmsg_add_string_buffer(&status);
16 }
17
18 static enum qmi_cmd_result
19 cmd_wms_list_messages_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
20 {
21         static struct qmi_wms_list_messages_request mreq = {
22                 QMI_INIT(storage_type, QMI_WMS_STORAGE_TYPE_UIM),
23                 QMI_INIT(message_tag, QMI_WMS_MESSAGE_TAG_TYPE_MT_NOT_READ),
24         };
25
26         qmi_set_wms_list_messages_request(msg, &mreq);
27
28         return QMI_CMD_REQUEST;
29 }
30
31 static int
32 pdu_decode_7bit_str(char *dest, const unsigned char *data, int data_len, int bit_offset)
33 {
34         char *orig_dest = dest;
35         int i;
36
37         for (i = 0; i < data_len; i++) {
38                 int pos = (i + bit_offset) % 7;
39
40                 if (pos == 0) {
41                         *(dest++) = data[i] & 0x7f;
42                 } else {
43                         if (i)
44                                 *(dest++) = (data[i - 1] >> (7 + 1 - pos)) |
45                                             ((data[i] << pos) & 0x7f);
46
47                         if (pos == 6)
48                                 *(dest++) = (data[i] >> 1) & 0x7f;
49                 }
50         }
51         *dest = 0;
52         return dest - orig_dest;
53 }
54
55 static void decode_7bit_field(char *name, const unsigned char *data, int data_len)
56 {
57         bool multipart = false;
58         char *dest;
59         int part = 0, n_parts = 0;
60         int len, pos_offset = 0;
61         int i;
62
63         if (data[0] == 5 && data[1] == 0 && data[2] == 3) {
64                 multipart = true;
65                 n_parts = data[4];
66                 part = data[5];
67         } else if (data[0] == 6 && data[1] == 8 && data[2] == 4) {
68                 multipart = true;
69                 n_parts = data[5];
70                 part = data[6];
71         }
72
73         if (multipart) {
74                 len = data[0] + 1;
75                 data += len;
76                 data_len -= len;
77                 pos_offset = 6;
78         }
79
80         dest = blobmsg_alloc_string_buffer(&status, name, data_len * 8 / 7 + 2);
81         pdu_decode_7bit_str(dest, data, data_len, pos_offset);
82         blobmsg_add_string_buffer(&status);
83
84         if (multipart) {
85                 blobmsg_add_u32(&status, "part", part + 1);
86                 blobmsg_add_u32(&status, "parts", n_parts);
87         }
88 }
89
90 static char *pdu_add_semioctet(char *str, char val)
91 {
92         *str = '0' + (val & 0xf);
93         if (*str <= '9')
94                 str++;
95
96         *str = '0' + ((val >> 4) & 0xf);
97         if (*str <= '9')
98                 str++;
99
100         return str;
101 }
102
103 static void
104 pdu_decode_address(char *str, unsigned char *data, int len)
105 {
106         unsigned char toa;
107
108         toa = *(data++);
109         switch (toa & 0x70) {
110         case 0x50:
111                 pdu_decode_7bit_str(str, data, len, 0);
112                 return;
113         case 0x10:
114                 *(str++) = '+';
115                 /* fall through */
116         default:
117                 while (len--) {
118                         str = pdu_add_semioctet(str, *data);
119                         data++;
120                 }
121         }
122
123         *str = 0;
124 }
125
126 static void wms_decode_address(char *str, char *name, unsigned char *data, int len)
127 {
128         str = blobmsg_alloc_string_buffer(&status, name, len * 2 + 2);
129         pdu_decode_address(str, data, len);
130         blobmsg_add_string_buffer(&status);
131 }
132
133 static void cmd_wms_get_message_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
134 {
135         struct qmi_wms_raw_read_response res;
136         unsigned char *data, *end;
137         char *str;
138         int i, cur_len;
139         bool sent;
140
141         qmi_parse_wms_raw_read_response(msg, &res);
142         data = (unsigned char *) res.data.raw_message_data.raw_data;
143         end = data + res.data.raw_message_data.raw_data_n;
144
145         cur_len = *(data++);
146         if (data + cur_len >= end)
147                 return;
148
149         if (cur_len) {
150                 wms_decode_address(str, "smsc", data, cur_len - 1);
151                 data += cur_len;
152         }
153
154         if (data + 3 >= end)
155                 return;
156
157         sent = (*data & 0x3) == 1;
158         data++;
159         if (sent)
160                 data++;
161
162         cur_len = *(data++);
163         if (data + cur_len >= end)
164                 return;
165
166         if (cur_len) {
167                 cur_len = (cur_len + 1) / 2;
168                 wms_decode_address(str, sent ? "receiver" : "sender", data, cur_len);
169                 data += cur_len + 1;
170         }
171
172         if (data + 3 >= end)
173                 return;
174
175         /* Protocol ID */
176         if (*(data++) != 0)
177                 return;
178
179         /* Data Encoding */
180         if (*(data++) != 0)
181                 return;
182
183         if (sent) {
184                 /* Message validity */
185                 data++;
186         } else {
187                 if (data + 6 >= end)
188                         return;
189
190                 str = blobmsg_alloc_string_buffer(&status, "timestamp", 32);
191
192                 /* year */
193                 *(str++) = '2';
194                 *(str++) = '0';
195                 str = pdu_add_semioctet(str, data[0]);
196                 /* month */
197                 *(str++) = '-';
198                 str = pdu_add_semioctet(str, data[1]);
199                 /* day */
200                 *(str++) = '-';
201                 str = pdu_add_semioctet(str, data[2]);
202
203                 /* hour */
204                 *(str++) = ' ';
205                 str = pdu_add_semioctet(str, data[3]);
206                 /* minute */
207                 *(str++) = ':';
208                 str = pdu_add_semioctet(str, data[4]);
209                 /* second */
210                 *(str++) = ':';
211                 str = pdu_add_semioctet(str, data[5]);
212                 *str = 0;
213
214                 blobmsg_add_string_buffer(&status);
215
216                 data += 7;
217         }
218
219         cur_len = *(data++);
220         decode_7bit_field("text", data, end - data);
221 }
222
223 static enum qmi_cmd_result
224 cmd_wms_get_message_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
225 {
226         static struct qmi_wms_raw_read_request mreq = {
227                 QMI_INIT_SEQUENCE(message_memory_storage_id,
228                         .storage_type = QMI_WMS_STORAGE_TYPE_UIM,
229                 ),
230                 QMI_INIT(message_mode, QMI_WMS_MESSAGE_MODE_GSM_WCDMA),
231         };
232         char *err;
233         int id;
234
235         id = strtoul(arg, &err, 10);
236         if (err && *err) {
237                 blobmsg_add_string(&status, "error", "Invalid message ID");
238                 return QMI_CMD_EXIT;
239         }
240
241         mreq.data.message_memory_storage_id.memory_index = id;
242         qmi_set_wms_raw_read_request(msg, &mreq);
243
244         return QMI_CMD_REQUEST;
245 }
246
247
248 static void cmd_wms_get_raw_message_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
249 {
250         struct qmi_wms_raw_read_response res;
251         unsigned char *data;
252         int i, len = 0;
253         char *str;
254
255         qmi_parse_wms_raw_read_response(msg, &res);
256         data = (unsigned char *) res.data.raw_message_data.raw_data;
257         str = blobmsg_alloc_string_buffer(&status, "data", res.data.raw_message_data.raw_data_n * 3);
258         for (i = 0; i < res.data.raw_message_data.raw_data_n; i++) {
259                 str += sprintf(str, " %02x" + (i ? 0 : 1), data[i]);
260         }
261         blobmsg_add_string_buffer(&status);
262 }
263
264 #define cmd_wms_get_raw_message_prepare cmd_wms_get_message_prepare