• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/uqmi/commands-nas.c

  1 /*
  2  * uqmi -- tiny QMI support implementation
  3  *
  4  * Copyright (C) 2014-2015 Felix Fietkau <nbd@openwrt.org>
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the
 18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 19  * Boston, MA 02110-1301 USA.
 20  */
 21 
 22 #include "qmi-message.h"
 23 
 24 static struct qmi_nas_set_system_selection_preference_request sel_req;
 25 static struct   {
 26         bool mcc_is_set;
 27         bool mnc_is_set;
 28 } plmn_code_flag;
 29 
 30 #define cmd_nas_do_set_system_selection_cb no_cb
 31 static enum qmi_cmd_result
 32 cmd_nas_do_set_system_selection_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
 33 {
 34         qmi_set_nas_set_system_selection_preference_request(msg, &sel_req);
 35         return QMI_CMD_REQUEST;
 36 }
 37 
 38 static enum qmi_cmd_result
 39 do_sel_network(void)
 40 {
 41         static bool use_sel_req = false;
 42 
 43         if (!use_sel_req) {
 44                 use_sel_req = true;
 45                 uqmi_add_command(NULL, __UQMI_COMMAND_nas_do_set_system_selection);
 46         }
 47 
 48         return QMI_CMD_DONE;
 49 }
 50 
 51 #define cmd_nas_set_network_modes_cb no_cb
 52 static enum qmi_cmd_result
 53 cmd_nas_set_network_modes_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
 54 {
 55         static const struct {
 56                 const char *name;
 57                 QmiNasRatModePreference val;
 58         } modes[] = {
 59                 { "cdma", QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X | QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO },
 60                 { "td-scdma", QMI_NAS_RAT_MODE_PREFERENCE_TD_SCDMA },
 61                 { "gsm", QMI_NAS_RAT_MODE_PREFERENCE_GSM },
 62                 { "umts", QMI_NAS_RAT_MODE_PREFERENCE_UMTS },
 63                 { "lte", QMI_NAS_RAT_MODE_PREFERENCE_LTE },
 64         };
 65         QmiNasRatModePreference val = 0;
 66         char *word;
 67         int i;
 68 
 69         for (word = strtok(arg, ",");
 70              word;
 71              word = strtok(NULL, ",")) {
 72                 bool found = false;
 73 
 74                 for (i = 0; i < ARRAY_SIZE(modes); i++) {
 75                         if (strcmp(word, modes[i].name) != 0 &&
 76                                 strcmp(word, "all") != 0)
 77                                 continue;
 78 
 79                         val |= modes[i].val;
 80                         found = true;
 81                 }
 82 
 83                 if (!found) {
 84                         uqmi_add_error("Invalid network mode");
 85                         return QMI_CMD_EXIT;
 86                 }
 87         }
 88 
 89         qmi_set(&sel_req, mode_preference, val);
 90         return do_sel_network();
 91 }
 92 
 93 #define cmd_nas_set_network_preference_cb no_cb
 94 static enum qmi_cmd_result
 95 cmd_nas_set_network_preference_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
 96 {
 97         QmiNasGsmWcdmaAcquisitionOrderPreference pref = QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC;
 98 
 99         if (!strcmp(arg, "gsm"))
100                 pref = QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_GSM;
101         else if (!strcmp(arg, "wcdma"))
102                 pref = QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_WCDMA;
103 
104         qmi_set(&sel_req, gsm_wcdma_acquisition_order_preference, pref);
105         return do_sel_network();
106 }
107 
108 #define cmd_nas_set_roaming_cb no_cb
109 static enum qmi_cmd_result
110 cmd_nas_set_roaming_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
111 {
112         QmiNasRoamingPreference pref;
113 
114         if (!strcmp(arg, "any"))
115                 pref = QMI_NAS_ROAMING_PREFERENCE_ANY;
116         else if (!strcmp(arg, "only"))
117                 pref = QMI_NAS_ROAMING_PREFERENCE_NOT_OFF;
118         else if (!strcmp(arg, "off"))
119                 pref = QMI_NAS_ROAMING_PREFERENCE_OFF;
120         else
121                 return uqmi_add_error("Invalid argument");
122 
123         qmi_set(&sel_req, roaming_preference, pref);
124         return do_sel_network();
125 }
126 
127 #define cmd_nas_set_mcc_cb no_cb
128 static enum qmi_cmd_result
129 cmd_nas_set_mcc_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
130 {
131         char *err;
132         int value = strtoul(arg, &err, 10);
133         if (err && *err) {
134                 uqmi_add_error("Invalid MCC value");
135                 return QMI_CMD_EXIT;
136         }
137 
138         sel_req.data.network_selection_preference.mcc = value;
139         plmn_code_flag.mcc_is_set = true;
140         return QMI_CMD_DONE;
141 }
142 
143 #define cmd_nas_set_mnc_cb no_cb
144 static enum qmi_cmd_result
145 cmd_nas_set_mnc_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
146 {
147         char *err;
148         int value = strtoul(arg, &err, 10);
149         if (err && *err) {
150                 uqmi_add_error("Invalid MNC value");
151                 return QMI_CMD_EXIT;
152         }
153 
154         sel_req.data.network_selection_preference.mnc = value;
155         plmn_code_flag.mnc_is_set = true;
156         return QMI_CMD_DONE;
157 }
158 
159 #define cmd_nas_set_plmn_cb no_cb
160 static enum qmi_cmd_result
161 cmd_nas_set_plmn_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
162 {
163         sel_req.set.network_selection_preference = 1;
164         sel_req.data.network_selection_preference.mode = QMI_NAS_NETWORK_SELECTION_PREFERENCE_AUTOMATIC;
165 
166         if (!plmn_code_flag.mcc_is_set && plmn_code_flag.mnc_is_set) {
167                 uqmi_add_error("No MCC value");
168                 return QMI_CMD_EXIT;
169         }
170 
171         if (plmn_code_flag.mcc_is_set && sel_req.data.network_selection_preference.mcc) {
172                 if (!plmn_code_flag.mnc_is_set) {
173                         uqmi_add_error("No MNC value");
174                         return QMI_CMD_EXIT;
175                 } else {
176                         sel_req.data.network_selection_preference.mode = QMI_NAS_NETWORK_SELECTION_PREFERENCE_MANUAL;
177                 }
178         }
179 
180         return do_sel_network();
181 }
182 
183 #define cmd_nas_initiate_network_register_cb no_cb
184 static enum qmi_cmd_result
185 cmd_nas_initiate_network_register_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
186 {
187         static struct qmi_nas_initiate_network_register_request register_req = {
188                 QMI_INIT(action, QMI_NAS_NETWORK_REGISTER_TYPE_AUTOMATIC)
189         };
190 
191         qmi_set_nas_initiate_network_register_request(msg, &register_req);
192         return QMI_CMD_REQUEST;
193 }
194 
195 static void
196 cmd_nas_get_signal_info_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
197 {
198         struct qmi_nas_get_signal_info_response res;
199         void *c;
200 
201         qmi_parse_nas_get_signal_info_response(msg, &res);
202 
203         c = blobmsg_open_table(&status, NULL);
204         if (res.set.cdma_signal_strength) {
205                 blobmsg_add_string(&status, "type", "cdma");
206                 blobmsg_add_u32(&status, "rssi", (int32_t) res.data.cdma_signal_strength.rssi);
207                 blobmsg_add_u32(&status, "ecio", (int32_t) res.data.cdma_signal_strength.ecio);
208         }
209 
210         if (res.set.hdr_signal_strength) {
211                 blobmsg_add_string(&status, "type", "hdr");
212                 blobmsg_add_u32(&status, "rssi", (int32_t) res.data.hdr_signal_strength.rssi);
213                 blobmsg_add_u32(&status, "ecio", (int32_t) res.data.hdr_signal_strength.ecio);
214                 blobmsg_add_u32(&status, "io", res.data.hdr_signal_strength.io);
215         }
216 
217         if (res.set.gsm_signal_strength) {
218                 blobmsg_add_string(&status, "type", "gsm");
219                 blobmsg_add_u32(&status, "signal", (int32_t) res.data.gsm_signal_strength);
220         }
221 
222         if (res.set.wcdma_signal_strength) {
223                 blobmsg_add_string(&status, "type", "wcdma");
224                 blobmsg_add_u32(&status, "rssi", (int32_t) res.data.wcdma_signal_strength.rssi);
225                 blobmsg_add_u32(&status, "ecio", (int32_t) res.data.wcdma_signal_strength.ecio);
226         }
227 
228         if (res.set.lte_signal_strength) {
229                 blobmsg_add_string(&status, "type", "lte");
230                 blobmsg_add_u32(&status, "rssi", (int32_t) res.data.lte_signal_strength.rssi);
231                 blobmsg_add_u32(&status, "rsrq", (int32_t) res.data.lte_signal_strength.rsrq);
232                 blobmsg_add_u32(&status, "rsrp", (int32_t) res.data.lte_signal_strength.rsrp);
233                 blobmsg_add_u32(&status, "snr", (int32_t) res.data.lte_signal_strength.snr);
234         }
235 
236         if (res.set.tdma_signal_strength) {
237                 blobmsg_add_string(&status, "type", "tdma");
238                 blobmsg_add_u32(&status, "signal", (int32_t) res.data.tdma_signal_strength);
239         }
240 
241         blobmsg_close_table(&status, c);
242 }
243 
244 static enum qmi_cmd_result
245 cmd_nas_get_signal_info_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
246 {
247         qmi_set_nas_get_signal_info_request(msg);
248         return QMI_CMD_REQUEST;
249 }
250 
251 static void
252 cmd_nas_get_serving_system_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
253 {
254         struct qmi_nas_get_serving_system_response res;
255         static const char *reg_states[] = {
256                 [QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED] = "not_registered",
257                 [QMI_NAS_REGISTRATION_STATE_REGISTERED] = "registered",
258                 [QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING] = "searching",
259                 [QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED] = "registering_denied",
260                 [QMI_NAS_REGISTRATION_STATE_UNKNOWN] = "unknown",
261         };
262         void *c;
263 
264         qmi_parse_nas_get_serving_system_response(msg, &res);
265 
266         c = blobmsg_open_table(&status, NULL);
267         if (res.set.serving_system) {
268                 int state = res.data.serving_system.registration_state;
269 
270                 if (state > QMI_NAS_REGISTRATION_STATE_UNKNOWN)
271                         state = QMI_NAS_REGISTRATION_STATE_UNKNOWN;
272 
273                 blobmsg_add_string(&status, "registration", reg_states[state]);
274         }
275         if (res.set.current_plmn) {
276                 blobmsg_add_u32(&status, "plmn_mcc", res.data.current_plmn.mcc);
277                 blobmsg_add_u32(&status, "plmn_mnc", res.data.current_plmn.mnc);
278                 if (res.data.current_plmn.description)
279                         blobmsg_add_string(&status, "plmn_description", res.data.current_plmn.description);
280         }
281 
282         if (res.set.roaming_indicator)
283                 blobmsg_add_u8(&status, "roaming", !res.data.roaming_indicator);
284 
285         blobmsg_close_table(&status, c);
286 }
287 
288 static enum qmi_cmd_result
289 cmd_nas_get_serving_system_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
290 {
291         qmi_set_nas_get_serving_system_request(msg);
292         return QMI_CMD_REQUEST;
293 }
294 
295 static void
296 cmd_nas_network_scan_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
297 {
298         static struct qmi_nas_network_scan_response res;
299         const char *network_status[] = {
300                 "current_serving",
301                 "available",
302                 "home",
303                 "roaming",
304                 "forbidden",
305                 "not_forbidden",
306                 "preferred",
307                 "not_preferred",
308         };
309         const char *radio[] = {
310                 [QMI_NAS_RADIO_INTERFACE_NONE] = "none",
311                 [QMI_NAS_RADIO_INTERFACE_CDMA_1X] = "cdma-1x",
312                 [QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO] = "cdma-1x_evdo",
313                 [QMI_NAS_RADIO_INTERFACE_AMPS] = "amps",
314                 [QMI_NAS_RADIO_INTERFACE_GSM] = "gsm",
315                 [QMI_NAS_RADIO_INTERFACE_UMTS] = "umts",
316                 [QMI_NAS_RADIO_INTERFACE_LTE] = "lte",
317                 [QMI_NAS_RADIO_INTERFACE_TD_SCDMA] = "td-scdma",
318         };
319         void *t, *c, *info, *stat;
320         int i, j;
321 
322         qmi_parse_nas_network_scan_response(msg, &res);
323 
324         t = blobmsg_open_table(&status, NULL);
325 
326         c = blobmsg_open_array(&status, "network_info");
327         for (i = 0; i < res.data.network_information_n; i++) {
328                 info = blobmsg_open_table(&status, NULL);
329                 blobmsg_add_u32(&status, "mcc", res.data.network_information[i].mcc);
330                 blobmsg_add_u32(&status, "mnc", res.data.network_information[i].mnc);
331                 if (res.data.network_information[i].description)
332                         blobmsg_add_string(&status, "description", res.data.network_information[i].description);
333                 stat = blobmsg_open_array(&status, "status");
334                 for (j = 0; j < ARRAY_SIZE(network_status); j++) {
335                         if (!(res.data.network_information[i].network_status & (1 << j)))
336                                 continue;
337 
338                         blobmsg_add_string(&status, NULL, network_status[j]);
339                 }
340                 blobmsg_close_array(&status, stat);
341                 blobmsg_close_table(&status, info);
342         }
343         blobmsg_close_array(&status, c);
344 
345         c = blobmsg_open_array(&status, "radio_access_technology");
346         for (i = 0; i < res.data.radio_access_technology_n; i++) {
347                 const char *r = "unknown";
348                 int r_i = res.data.radio_access_technology[i].radio_interface;
349 
350                 info = blobmsg_open_table(&status, NULL);
351                 blobmsg_add_u32(&status, "mcc", res.data.radio_access_technology[i].mcc);
352                 blobmsg_add_u32(&status, "mnc", res.data.radio_access_technology[i].mnc);
353                 if (r_i >= 0 && r_i < ARRAY_SIZE(radio))
354                         r = radio[r_i];
355 
356                 blobmsg_add_string(&status, "radio", r);
357                 blobmsg_close_table(&status, info);
358         }
359         blobmsg_close_array(&status, c);
360 
361         blobmsg_close_table(&status, t);
362 }
363 
364 static enum qmi_cmd_result
365 cmd_nas_network_scan_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
366 {
367         struct qmi_nas_network_scan_request sreq = {
368                 QMI_INIT(network_type,
369                      QMI_NAS_NETWORK_SCAN_TYPE_GSM |
370                      QMI_NAS_NETWORK_SCAN_TYPE_UMTS |
371                      QMI_NAS_NETWORK_SCAN_TYPE_LTE |
372                      QMI_NAS_NETWORK_SCAN_TYPE_TD_SCDMA),
373         };
374 
375         qmi_set_nas_network_scan_request(msg, &sreq);
376         return QMI_CMD_REQUEST;
377 }
378 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt