add an option for releasing client ids
[project/uqmi.git] / dev.c
diff --git a/dev.c b/dev.c
index ed9d60f..76a8f30 100644 (file)
--- a/dev.c
+++ b/dev.c
@@ -4,6 +4,10 @@
 #include <stdio.h>
 #include <string.h>
 #include "uqmi.h"
+#include "qmi-errors.h"
+#include "qmi-errors.c"
+
+bool cancel_all_requests = false;
 
 #define __qmi_service(_n) [__##_n] = _n
 static const uint8_t qmi_services[__QMI_SERVICE_LAST] = {
@@ -45,7 +49,6 @@ static void __qmi_request_complete(struct qmi_dev *qmi, struct qmi_request *req,
 {
        void *tlv_buf;
        int tlv_len;
-       int ret;
 
        if (!req->pending)
                return;
@@ -53,10 +56,14 @@ static void __qmi_request_complete(struct qmi_dev *qmi, struct qmi_request *req,
        req->pending = false;
        list_del(&req->list);
 
-       tlv_buf = qmi_msg_get_tlv_buf(msg, &tlv_len);
-       req->ret = qmi_check_message_status(tlv_buf, tlv_len);
-       if (req->ret)
-               msg = NULL;
+       if (msg) {
+               tlv_buf = qmi_msg_get_tlv_buf(msg, &tlv_len);
+               req->ret = qmi_check_message_status(tlv_buf, tlv_len);
+               if (req->ret)
+                       msg = NULL;
+       } else {
+               req->ret = QMI_ERROR_CANCELLED;
+       }
 
        if (req->cb && (msg || !req->no_error_cb))
                req->cb(qmi, req, msg);
@@ -95,7 +102,6 @@ static void qmi_notify_read(struct ustream *us, int bytes)
        struct qmi_msg *msg;
        char *buf;
        int len, msg_len;
-       int i;
 
        while (1) {
                buf = ustream_get_read_buf(us, &len);
@@ -120,8 +126,6 @@ int qmi_request_start(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_m
 {
        int len = qmi_complete_request_message(msg);
        uint16_t tid;
-       int ret;
-       int i;
 
        memset(req, 0, sizeof(*req));
        req->ret = -1;
@@ -172,6 +176,10 @@ int qmi_request_wait(struct qmi_dev *qmi, struct qmi_request *req)
                cancelled = uloop_cancelled;
                uloop_cancelled = false;
                uloop_run();
+
+               if (cancel_all_requests)
+                       qmi_request_cancel(qmi, req);
+
                uloop_cancelled = cancelled;
        }
 
@@ -253,6 +261,13 @@ static void __qmi_service_disconnect(struct qmi_dev *qmi, int idx)
        qmi_request_wait(qmi, &req);
 }
 
+int qmi_service_release_client_id(struct qmi_dev *qmi, QmiService svc)
+{
+       int idx = qmi_get_service_idx(svc);
+       qmi->service_keep_cid &= ~(1 << idx);
+       return 0;
+}
+
 static void qmi_close_all_services(struct qmi_dev *qmi)
 {
        uint32_t connected = qmi->service_connected;
@@ -302,7 +317,6 @@ int qmi_device_open(struct qmi_dev *qmi, const char *path)
 void qmi_device_close(struct qmi_dev *qmi)
 {
        struct qmi_request *req;
-       int idx;
 
        qmi_close_all_services(qmi);
        ustream_free(&qmi->sf.stream);
@@ -335,3 +349,15 @@ QmiService qmi_service_get_by_name(const char *str)
 
        return -1;
 }
+
+const char *qmi_get_error_str(int code)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(qmi_errors); i++) {
+               if (qmi_errors[i].code == code)
+                       return qmi_errors[i].text;
+       }
+
+       return "Unknown error";
+}