/* * uqmi -- tiny QMI support implementation * * Copyright (C) 2014-2015 Felix Fietkau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include "uqmi.h" #include "commands.h" static const char *device; #define CMD_OPT(_arg) (-2 - _arg) #define __uqmi_command(_name, _optname, _arg, _option) { #_optname, _arg##_argument, NULL, CMD_OPT(__UQMI_COMMAND_##_name) } static const struct option uqmi_getopt[] = { __uqmi_commands, { "single", no_argument, NULL, 's' }, { "device", required_argument, NULL, 'd' }, { "keep-client-id", required_argument, NULL, 'k' }, { "release-client-id", required_argument, NULL, 'r' }, { "mbim", no_argument, NULL, 'm' }, { "timeout", required_argument, NULL, 't' }, { NULL, 0, NULL, 0 } }; #undef __uqmi_command static int usage(const char *progname) { fprintf(stderr, "Usage: %s \n" "Options:\n" " --single, -s: Print output as a single line (for scripts)\n" " --device=NAME, -d NAME: Set device name to NAME (required)\n" " --keep-client-id : Keep Client ID for service \n" " --release-client-id : Release Client ID after exiting\n" " --mbim, -m NAME is an MBIM device with EXT_QMUX support\n" " --timeout, -t response timeout in msecs\n" "\n" "Services: dms, nas, pds, wds, wms\n" "\n" "Actions:\n" " --get-versions: Get service versions\n" " --set-client-id ,: Set Client ID for service to \n" " (implies --keep-client-id)\n" " --get-client-id : Connect and get Client ID for service \n" " (implies --keep-client-id)\n" " --sync: Release all Client IDs\n" wds_helptext dms_helptext uim_helptext nas_helptext wms_helptext wda_helptext "\n", progname); return 1; } static void keep_client_id(struct qmi_dev *qmi, const char *optarg) { QmiService svc = qmi_service_get_by_name(optarg); if (svc < 0) { fprintf(stderr, "Invalid service %s\n", optarg); exit(1); } qmi_service_get_client_id(qmi, svc); } static void release_client_id(struct qmi_dev *qmi, const char *optarg) { QmiService svc = qmi_service_get_by_name(optarg); if (svc < 0) { fprintf(stderr, "Invalid service %s\n", optarg); exit(1); } qmi_service_release_client_id(qmi, svc); } static void handle_exit_signal(int signal) { cancel_all_requests = true; uloop_end(); } static void _request_timeout_handler(struct uloop_timeout *timeout) { fprintf(stderr, "Request timed out\n"); handle_exit_signal(0); } struct uloop_timeout request_timeout = { .cb = _request_timeout_handler, }; int main(int argc, char **argv) { static struct qmi_dev dev; int ch, ret; uloop_init(); signal(SIGINT, handle_exit_signal); signal(SIGTERM, handle_exit_signal); while ((ch = getopt_long(argc, argv, "d:k:smt:", uqmi_getopt, NULL)) != -1) { int cmd_opt = CMD_OPT(ch); if (ch < 0 && cmd_opt >= 0 && cmd_opt < __UQMI_COMMAND_LAST) { uqmi_add_command(optarg, cmd_opt); continue; } switch(ch) { case 'r': release_client_id(&dev, optarg); break; case 'k': keep_client_id(&dev, optarg); break; case 'd': device = optarg; break; case 's': single_line = true; break; case 'm': dev.is_mbim = true; break; case 't': uloop_timeout_set(&request_timeout, atol(optarg)); break; default: return usage(argv[0]); } } if (!device) { fprintf(stderr, "No device given\n"); return usage(argv[0]); } if (qmi_device_open(&dev, device)) { fprintf(stderr, "Failed to open device\n"); return 2; } ret = uqmi_run_commands(&dev) ? 0 : -1; qmi_device_close(&dev); return ret; }