commands-uim.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * uqmi -- tiny QMI support implementation
  3. *
  4. * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
  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. static int uim_slot = 0;
  22. #define cmd_uim_verify_pin1_cb no_cb
  23. static enum qmi_cmd_result
  24. cmd_uim_verify_pin1_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  25. {
  26. struct qmi_uim_verify_pin_request data = {
  27. QMI_INIT_SEQUENCE(session,
  28. .session_type = QMI_UIM_SESSION_TYPE_CARD_SLOT_1,
  29. .application_identifier_n = 0
  30. ),
  31. QMI_INIT_SEQUENCE(info,
  32. .pin_id = QMI_UIM_PIN_ID_PIN1,
  33. .pin_value = arg
  34. )
  35. };
  36. qmi_set_uim_verify_pin_request(msg, &data);
  37. return QMI_CMD_REQUEST;
  38. }
  39. #define cmd_uim_verify_pin2_cb no_cb
  40. static enum qmi_cmd_result
  41. cmd_uim_verify_pin2_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  42. {
  43. struct qmi_uim_verify_pin_request data = {
  44. QMI_INIT_SEQUENCE(session,
  45. .session_type = QMI_UIM_SESSION_TYPE_CARD_SLOT_1,
  46. .application_identifier_n = 0
  47. ),
  48. QMI_INIT_SEQUENCE(info,
  49. .pin_id = QMI_UIM_PIN_ID_PIN2,
  50. .pin_value = arg
  51. )
  52. };
  53. qmi_set_uim_verify_pin_request(msg, &data);
  54. return QMI_CMD_REQUEST;
  55. }
  56. static void cmd_uim_get_sim_state_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
  57. {
  58. struct qmi_uim_get_card_status_response res;
  59. void * const card_table = blobmsg_open_table(&status, NULL);
  60. static const char *card_application_states[] = {
  61. [QMI_UIM_CARD_APPLICATION_STATE_UNKNOWN] = "unknown",
  62. [QMI_UIM_CARD_APPLICATION_STATE_DETECTED] = "detected",
  63. [QMI_UIM_CARD_APPLICATION_STATE_PIN1_OR_UPIN_PIN_REQUIRED] = "pin-required",
  64. [QMI_UIM_CARD_APPLICATION_STATE_PUK1_OR_UPIN_PUK_REQUIRED] = "puk-required",
  65. [QMI_UIM_CARD_APPLICATION_STATE_CHECK_PERSONALIZATION_STATE] = "check-personalization-state",
  66. [QMI_UIM_CARD_APPLICATION_STATE_PIN1_BLOCKED] = "pin1-blocked",
  67. [QMI_UIM_CARD_APPLICATION_STATE_ILLEGAL] = "illegal",
  68. [QMI_UIM_CARD_APPLICATION_STATE_READY] = "ready",
  69. };
  70. qmi_parse_uim_get_card_status_response(msg, &res);
  71. for (int i = 0; i < res.data.card_status.cards_n; ++i) {
  72. if (res.data.card_status.cards[i].card_state != QMI_UIM_CARD_STATE_PRESENT)
  73. continue;
  74. uint8_t card_application_state;
  75. uint8_t pin1_state = res.data.card_status.cards[i].upin_state;
  76. uint8_t pin1_retries = res.data.card_status.cards[i].upin_retries;
  77. uint8_t puk1_retries = res.data.card_status.cards[i].upuk_retries;
  78. uint8_t pin2_state;
  79. uint8_t pin2_retries;
  80. uint8_t puk2_retries;
  81. bool has_pin2 = false;
  82. for (int j = 0; j < res.data.card_status.cards[i].applications_n; ++j) {
  83. if (res.data.card_status.cards[i].applications[j].type == QMI_UIM_CARD_APPLICATION_TYPE_UNKNOWN)
  84. continue;
  85. card_application_state = pin1_state = res.data.card_status.cards[i].applications[j].state;
  86. if (!res.data.card_status.cards[i].applications[j].upin_replaces_pin1) {
  87. pin1_state = res.data.card_status.cards[i].applications[j].pin1_state;
  88. pin1_retries = res.data.card_status.cards[i].applications[j].pin1_retries;
  89. puk1_retries = res.data.card_status.cards[i].applications[j].puk1_retries;
  90. }
  91. pin2_state = res.data.card_status.cards[i].applications[j].pin2_state;
  92. pin2_retries = res.data.card_status.cards[i].applications[j].pin2_retries;
  93. puk2_retries = res.data.card_status.cards[i].applications[j].puk2_retries;
  94. has_pin2 = true;
  95. break; /* handle first application only for now */
  96. }
  97. if (card_application_state > QMI_UIM_CARD_APPLICATION_STATE_READY)
  98. card_application_state = QMI_UIM_CARD_APPLICATION_STATE_UNKNOWN;
  99. blobmsg_add_u32(&status, "card_slot", i + 1); /* Slot is idx + 1 */
  100. blobmsg_add_string(&status, "card_application_state", card_application_states[card_application_state]);
  101. blobmsg_add_string(&status, "pin1_status", get_pin_status(pin1_state));
  102. blobmsg_add_u32(&status, "pin1_verify_tries", pin1_retries);
  103. blobmsg_add_u32(&status, "pin1_unlock_tries", puk1_retries);
  104. if (has_pin2) {
  105. blobmsg_add_string(&status, "pin2_status", get_pin_status(pin2_state));
  106. blobmsg_add_u32(&status, "pin2_verify_tries", pin2_retries);
  107. blobmsg_add_u32(&status, "pin2_unlock_tries", puk2_retries);
  108. }
  109. break; /* handle only first preset SIM card for now */
  110. }
  111. blobmsg_close_table(&status, card_table);
  112. }
  113. static enum qmi_cmd_result
  114. cmd_uim_get_sim_state_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  115. {
  116. qmi_set_uim_get_card_status_request(msg);
  117. return QMI_CMD_REQUEST;
  118. }
  119. #define cmd_uim_slot_cb no_cb
  120. static enum qmi_cmd_result
  121. cmd_uim_slot_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  122. {
  123. char *err;
  124. int value = strtoul(arg, &err, 10);
  125. if ((err && *err) || value < 1 || value > 2) {
  126. uqmi_add_error("Invalid UIM-Slot value. Allowed: [1,2]");
  127. return QMI_CMD_EXIT;
  128. }
  129. uim_slot = value;
  130. return QMI_CMD_DONE;
  131. }
  132. #define cmd_uim_power_off_cb no_cb
  133. static enum qmi_cmd_result
  134. cmd_uim_power_off_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  135. {
  136. struct qmi_uim_power_off_sim_request data = {
  137. QMI_INIT(slot, uim_slot)
  138. };
  139. if (!uim_slot) {
  140. uqmi_add_error("UIM-Slot not set. Use --uim-slot <slot> to set it.");
  141. return QMI_CMD_EXIT;
  142. }
  143. qmi_set_uim_power_off_sim_request(msg, &data);
  144. return QMI_CMD_REQUEST;
  145. }
  146. #define cmd_uim_power_on_cb no_cb
  147. static enum qmi_cmd_result
  148. cmd_uim_power_on_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  149. {
  150. struct qmi_uim_power_on_sim_request data = {
  151. QMI_INIT(slot, uim_slot)
  152. };
  153. if (!uim_slot) {
  154. uqmi_add_error("UIM-Slot not set. Use --uim-slot <slot> to set it.");
  155. return QMI_CMD_EXIT;
  156. }
  157. qmi_set_uim_power_on_sim_request(msg, &data);
  158. return QMI_CMD_REQUEST;
  159. }