mbim-msg.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * umbim
  3. * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2
  7. * as published by the Free Software Foundation
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <alloca.h>
  17. #include <fcntl.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <unistd.h>
  22. #include <libubox/utils.h>
  23. #include <libubox/uloop.h>
  24. #include "mbim.h"
  25. #include "data/mbim-service-basic-connect.h"
  26. int transaction_id = 1;
  27. uint8_t basic_connect[16] = { 0xa2, 0x89, 0xcc, 0x33, 0xbc, 0xbb, 0x8b, 0x4f,
  28. 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6,0xdf };
  29. static int payload_offset, payload_free, payload_len;
  30. static uint8_t *payload_buffer;
  31. int
  32. mbim_add_payload(uint8_t len)
  33. {
  34. uint32_t offset = payload_offset;
  35. if (payload_free < len)
  36. return 0;
  37. payload_free -= len;
  38. payload_offset += len;
  39. payload_len += len;
  40. return offset;
  41. }
  42. int
  43. mbim_encode_string(struct mbim_string *str, char *in)
  44. {
  45. const int l = strlen(in);
  46. const int utf16_len = l * 2;
  47. const int pad_len = utf16_len % 4;
  48. const int s = mbim_add_payload(utf16_len + pad_len);
  49. uint8_t *p = &payload_buffer[s];
  50. int i;
  51. if (!s)
  52. return -1;
  53. str->offset = htole32(s);
  54. str->length = htole32(utf16_len);
  55. for (i = 0; i < l; i++)
  56. p[i * 2] = in[i];
  57. return 0;
  58. }
  59. char *
  60. mbim_get_string(struct mbim_string *str, char *in)
  61. {
  62. char *p = &in[le32toh(str->offset)];
  63. unsigned int i;
  64. if (!le32toh(str->offset))
  65. return NULL;
  66. if (le32toh(str->length)) {
  67. for (i = 0; i < le32toh(str->length) / 2; i++)
  68. p[i] = p[i * 2];
  69. p[i] = '\0';
  70. str->length = 0;
  71. }
  72. return p;
  73. }
  74. void
  75. mbim_get_ipv4(void *buffer, char *out, uint32_t offset)
  76. {
  77. uint8_t *b = buffer + offset;
  78. snprintf(out, 16, "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
  79. }
  80. void
  81. mbim_get_ipv6(void *buffer, char *out, uint32_t offset)
  82. {
  83. uint8_t *b = buffer + offset;
  84. snprintf(out, 40, "%x:%x:%x:%x:%x:%x:%x:%x", b[0] << 8 | b[1],
  85. b[2] << 8 | b[3], b[4] << 8 | b[5], b[6] << 8 | b[7],
  86. b[8] << 8 | b[9], b[10] << 8 | b[11], b[12] << 8 | b[13],
  87. b[14] << 8 | b[15]);
  88. }
  89. uint32_t
  90. mbim_get_int(void *buffer, uint32_t offset)
  91. {
  92. uint32_t *i = buffer + offset;
  93. return le32toh(*i);
  94. }
  95. const char*
  96. mbim_enum_string(struct mbim_enum *e, uint32_t key)
  97. {
  98. while (e->skey) {
  99. if (key == e->key)
  100. return e->val;
  101. e++;
  102. }
  103. return NULL;
  104. }
  105. void
  106. mbim_setup_header(struct mbim_message_header *hdr, MbimMessageType type, int length)
  107. {
  108. if (length < 16)
  109. length = 16;
  110. hdr->transaction_id = htole32(transaction_id++);
  111. hdr->type = htole32(type);
  112. hdr->length = htole32(length);
  113. }
  114. uint8_t*
  115. mbim_setup_command_msg(uint8_t *uuid, uint32_t type, uint32_t command_id, int len)
  116. {
  117. struct command_message *cmd = (struct command_message *) mbim_buffer;
  118. if (!mbim_buffer)
  119. return NULL;
  120. memset(mbim_buffer, 0, mbim_bufsize);
  121. cmd->fragment_header.total = htole32(1);
  122. cmd->fragment_header.current = htole32(0);
  123. memcpy(cmd->service_id, uuid, 16);
  124. cmd->command_id = htole32(command_id);
  125. cmd->command_type = htole32(type);
  126. cmd->buffer_length = htole32(len);
  127. payload_offset = len;
  128. payload_free = mbim_bufsize - (sizeof(*cmd) + len);
  129. payload_len = 0;
  130. payload_buffer = cmd->buffer;
  131. return cmd->buffer;
  132. }
  133. int
  134. mbim_send_command_msg(void)
  135. {
  136. struct command_message *cmd = (struct command_message *) mbim_buffer;
  137. if (!mbim_buffer)
  138. return 0;
  139. if (payload_len & 0x3) {
  140. payload_len &= ~0x3;
  141. payload_len += 4;
  142. }
  143. cmd->buffer_length = htole32(le32toh(cmd->buffer_length) + payload_len);
  144. mbim_setup_header(&cmd->header, MBIM_MESSAGE_TYPE_COMMAND, sizeof(*cmd) + le32toh(cmd->buffer_length));
  145. return mbim_send();
  146. }
  147. int
  148. mbim_send_open_msg(void)
  149. {
  150. struct mbim_open_message *msg = (struct mbim_open_message *) mbim_buffer;
  151. mbim_setup_header(&msg->header, MBIM_MESSAGE_TYPE_OPEN, sizeof(*msg));
  152. msg->max_control_transfer = htole32(mbim_bufsize);
  153. return mbim_send();
  154. }
  155. int
  156. mbim_send_close_msg(void)
  157. {
  158. struct mbim_message_header *hdr = (struct mbim_message_header *) mbim_buffer;
  159. if (no_close || !mbim_buffer) {
  160. mbim_end();
  161. return 0;
  162. }
  163. mbim_setup_header(hdr, MBIM_MESSAGE_TYPE_CLOSE, sizeof(*hdr));
  164. return mbim_send();
  165. }