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

Sources/uqmi/uqmi/commands.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 <stdio.h>
 23 #include <string.h>
 24 #include <strings.h>
 25 #include <stdlib.h>
 26 #include <unistd.h>
 27 
 28 #include <libubox/blobmsg.h>
 29 #include <libubox/blobmsg_json.h>
 30 
 31 #include "uqmi.h"
 32 #include "utils.h"
 33 #include "commands.h"
 34 
 35 struct blob_buf status;
 36 bool single_line = false;
 37 
 38 static void no_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
 39 {
 40 }
 41 
 42 static void cmd_version_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
 43 {
 44         struct qmi_ctl_get_version_info_response res;
 45         void *c;
 46         char name_buf[16];
 47         int i;
 48 
 49         qmi_parse_ctl_get_version_info_response(msg, &res);
 50 
 51         c = blobmsg_open_table(&status, NULL);
 52         for (i = 0; i < res.data.service_list_n; i++) {
 53                 sprintf(name_buf, "service_%d", res.data.service_list[i].service);
 54                 blobmsg_printf(&status, name_buf, "%d,%d",
 55                         res.data.service_list[i].major_version,
 56                         res.data.service_list[i].minor_version);
 57         }
 58         blobmsg_close_table(&status, c);
 59 }
 60 
 61 static enum qmi_cmd_result
 62 cmd_version_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
 63 {
 64         qmi_set_ctl_get_version_info_request(msg);
 65         return QMI_CMD_REQUEST;
 66 }
 67 
 68 #define cmd_sync_cb no_cb
 69 static enum qmi_cmd_result
 70 cmd_sync_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
 71 {
 72         qmi_set_ctl_sync_request(msg);
 73         return QMI_CMD_REQUEST;
 74 }
 75 
 76 #define cmd_get_client_id_cb no_cb
 77 static enum qmi_cmd_result
 78 cmd_get_client_id_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
 79 {
 80         QmiService svc = qmi_service_get_by_name(arg);
 81 
 82         if (svc < 0) {
 83                 fprintf(stderr, "Invalid service name '%s'\n", arg);
 84                 return QMI_CMD_EXIT;
 85         }
 86 
 87         if (qmi_service_connect(qmi, svc, -1)) {
 88                 fprintf(stderr, "Failed to connect to service\n");
 89                 return QMI_CMD_EXIT;
 90         }
 91 
 92         printf("%d\n", qmi_service_get_client_id(qmi, svc));
 93         return QMI_CMD_DONE;
 94 }
 95 
 96 #define cmd_set_client_id_cb no_cb
 97 static enum qmi_cmd_result
 98 cmd_set_client_id_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
 99 {
100         QmiService svc;
101         int id;
102         char *s;
103 
104         s = strchr(arg, ',');
105         if (!s) {
106                 fprintf(stderr, "Invalid argument\n");
107                 return QMI_CMD_EXIT;
108         }
109         *s = 0;
110         s++;
111 
112         id = strtoul(s, &s, 0);
113         if (s && *s) {
114                 fprintf(stderr, "Invalid argument\n");
115                 return QMI_CMD_EXIT;
116         }
117 
118         svc = qmi_service_get_by_name(arg);
119         if (svc < 0) {
120                 fprintf(stderr, "Invalid service name '%s'\n", arg);
121                 return QMI_CMD_EXIT;
122         }
123 
124         if (qmi_service_connect(qmi, svc, id)) {
125                 fprintf(stderr, "Failed to connect to service\n");
126                 return QMI_CMD_EXIT;
127         }
128 
129         return QMI_CMD_DONE;
130 }
131 
132 static int
133 qmi_get_array_idx(const char **array, int size, const char *str)
134 {
135         int i;
136 
137         for (i = 0; i < size; i++) {
138                 if (!array[i])
139                         continue;
140 
141                 if (!strcmp(array[i], str))
142                         return i;
143         }
144 
145         return -1;
146 }
147 
148 #define cmd_ctl_set_data_format_cb no_cb
149 static enum qmi_cmd_result
150 cmd_ctl_set_data_format_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
151 {
152         struct qmi_ctl_set_data_format_request sreq = {};
153         const char *modes[] = {
154                 [QMI_CTL_DATA_LINK_PROTOCOL_802_3] = "802.3",
155                 [QMI_CTL_DATA_LINK_PROTOCOL_RAW_IP] = "raw-ip",
156         };
157         int mode = qmi_get_array_idx(modes, ARRAY_SIZE(modes), arg);
158 
159         if (mode < 0) {
160                 uqmi_add_error("Invalid mode (modes: 802.3, raw-ip)");
161                 return QMI_CMD_EXIT;
162         }
163 
164         qmi_set_ctl_set_data_format_request(msg, &sreq);
165         return QMI_CMD_DONE;
166 }
167 
168 #include "commands-wds.c"
169 #include "commands-dms.c"
170 #include "commands-nas.c"
171 #include "commands-wms.c"
172 #include "commands-wda.c"
173 #include "commands-uim.c"
174 
175 #define __uqmi_command(_name, _optname, _arg, _type) \
176         [__UQMI_COMMAND_##_name] = { \
177                 .name = #_optname, \
178                 .type = _type, \
179                 .prepare = cmd_##_name##_prepare, \
180                 .cb = cmd_##_name##_cb, \
181         }
182 
183 const struct uqmi_cmd_handler uqmi_cmd_handler[__UQMI_COMMAND_LAST] = {
184         __uqmi_commands
185 };
186 #undef __uqmi_command
187 
188 static struct uqmi_cmd *cmds;
189 static int n_cmds;
190 
191 void uqmi_add_command(char *arg, int cmd)
192 {
193         int idx = n_cmds++;
194 
195         cmds = realloc(cmds, n_cmds * sizeof(*cmds));
196         cmds[idx].handler = &uqmi_cmd_handler[cmd];
197         cmds[idx].arg = arg;
198 }
199 
200 static void uqmi_print_result(struct blob_attr *data)
201 {
202         char *str;
203 
204         if (!blob_len(data))
205                 return;
206 
207         str = blobmsg_format_json_indent(blob_data(data), false, single_line ? -1 : 0);
208         if (!str)
209                 return;
210 
211         printf("%s\n", str);
212         free(str);
213 }
214 
215 static bool __uqmi_run_commands(struct qmi_dev *qmi, bool option)
216 {
217         static struct qmi_request req;
218         char *buf = qmi->buf;
219         int i;
220 
221         for (i = 0; i < n_cmds; i++) {
222                 enum qmi_cmd_result res;
223                 bool cmd_option = cmds[i].handler->type == CMD_TYPE_OPTION;
224                 bool do_break = false;
225 
226                 if (cmd_option != option)
227                         continue;
228 
229                 blob_buf_init(&status, 0);
230                 if (cmds[i].handler->type > QMI_SERVICE_CTL &&
231                     qmi_service_connect(qmi, cmds[i].handler->type, -1)) {
232                         uqmi_add_error("Failed to connect to service");
233                         res = QMI_CMD_EXIT;
234                 } else {
235                         res = cmds[i].handler->prepare(qmi, &req, (void *) buf, cmds[i].arg);
236                 }
237 
238                 if (res == QMI_CMD_REQUEST) {
239                         qmi_request_start(qmi, &req, cmds[i].handler->cb);
240                         req.no_error_cb = true;
241                         if (qmi_request_wait(qmi, &req)) {
242                                 uqmi_add_error(qmi_get_error_str(req.ret));
243                                 do_break = true;
244                         }
245                 } else if (res == QMI_CMD_EXIT) {
246                         do_break = true;
247                 }
248 
249                 uqmi_print_result(status.head);
250                 if (do_break)
251                         return false;
252         }
253         return true;
254 }
255 
256 int uqmi_add_error(const char *msg)
257 {
258         blobmsg_add_string(&status, NULL, msg);
259         return QMI_CMD_EXIT;
260 }
261 
262 bool uqmi_run_commands(struct qmi_dev *qmi)
263 {
264         bool ret;
265 
266         ret = __uqmi_run_commands(qmi, true) &&
267               __uqmi_run_commands(qmi, false);
268 
269         free(cmds);
270         cmds = NULL;
271         n_cmds = 0;
272 
273         return ret;
274 }
275 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt