wmi_unified_coap_tlv.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /**
  17. * DOC: Implement API's specific to CoAP component.
  18. */
  19. #include <wmi_unified_priv.h>
  20. #include "wmi.h"
  21. #include "ol_defines.h"
  22. /*
  23. * send_coap_add_pattern_cmd_tlv() - Send wmi cmd for adding CoAP pattern
  24. * @wmi_handle: wmi handle
  25. * @param: parameter for CoAP add pattern
  26. *
  27. * Return: QDF_STATUS
  28. */
  29. static QDF_STATUS
  30. send_coap_add_pattern_cmd_tlv(wmi_unified_t wmi_handle,
  31. struct coap_offload_reply_param *param)
  32. {
  33. WMI_WOW_COAP_ADD_PATTERN_CMD_fixed_param *cmd;
  34. wmi_buf_t buf;
  35. QDF_STATUS status;
  36. uint8_t *buf_ptr;
  37. uint32_t len, coapmsg_len_align, verify_len_align;
  38. wmi_debug("vdev id %d pattern id %d timeout %d src ip 0x%x:%d coap msg len %d",
  39. param->vdev_id, param->pattern_id, param->cache_timeout,
  40. param->src_ip_v4, param->src_udp_port,
  41. param->coapmsg_len);
  42. wmi_debug("filter: dest ip 0x%x:%d is bc %d verify offset %d len %d",
  43. param->dest_ip_v4, param->dest_udp_port,
  44. param->dest_ip_v4_is_bc, param->verify_offset,
  45. param->verify_len);
  46. if (!param->verify || !param->verify_len ||
  47. !param->coapmsg || !param->coapmsg_len) {
  48. wmi_err("invalid param");
  49. return QDF_STATUS_E_INVAL;
  50. }
  51. coapmsg_len_align = qdf_align(param->coapmsg_len, 4);
  52. verify_len_align = qdf_align(param->verify_len, 4);
  53. len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + coapmsg_len_align +
  54. WMI_TLV_HDR_SIZE + verify_len_align;
  55. buf = wmi_buf_alloc(wmi_handle, len);
  56. if (!buf)
  57. return QDF_STATUS_E_NOMEM;
  58. buf_ptr = wmi_buf_data(buf);
  59. cmd = (WMI_WOW_COAP_ADD_PATTERN_CMD_fixed_param *)buf_ptr;
  60. WMITLV_SET_HDR(&cmd->tlv_header,
  61. WMITLV_TAG_STRUC_WMI_WOW_COAP_ADD_PATTERN_CMD_fixed_param,
  62. WMITLV_GET_STRUCT_TLVLEN(
  63. WMI_WOW_COAP_ADD_PATTERN_CMD_fixed_param));
  64. cmd->vdev_id = param->vdev_id;
  65. cmd->pattern_id = param->pattern_id;
  66. cmd->timeout = param->cache_timeout;
  67. WMI_COAP_IPV6_SET(cmd->pattern_type, 0);
  68. WMI_COAP_ADDR_TYPE_SET(cmd->pattern_type,
  69. param->dest_ip_v4_is_bc ? 1 : 0);
  70. qdf_mem_copy(cmd->match_udp_ip.ipv4_addr, &param->dest_ip_v4,
  71. sizeof(param->dest_ip_v4));
  72. cmd->match_udp_port = param->dest_udp_port;
  73. qdf_mem_copy(cmd->udp_local_ip.ipv4_addr, &param->src_ip_v4,
  74. sizeof(param->src_ip_v4));
  75. cmd->udp_local_port = param->src_udp_port;
  76. cmd->verify_offset = param->verify_offset;
  77. cmd->verify_len = param->verify_len;
  78. cmd->coapmsg_len = param->coapmsg_len;
  79. buf_ptr += sizeof(*cmd);
  80. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, verify_len_align);
  81. buf_ptr += WMI_TLV_HDR_SIZE;
  82. qdf_mem_copy(buf_ptr, param->verify, param->verify_len);
  83. buf_ptr += verify_len_align;
  84. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, coapmsg_len_align);
  85. buf_ptr += WMI_TLV_HDR_SIZE;
  86. qdf_mem_copy(buf_ptr, param->coapmsg, param->coapmsg_len);
  87. buf_ptr += coapmsg_len_align;
  88. wmi_mtrace(WMI_WOW_COAP_ADD_PATTERN_CMDID,
  89. cmd->vdev_id, cmd->pattern_id);
  90. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  91. WMI_WOW_COAP_ADD_PATTERN_CMDID);
  92. if (status != QDF_STATUS_SUCCESS) {
  93. wmi_err("Failed to send wow coap add pattern command %d",
  94. status);
  95. wmi_buf_free(buf);
  96. }
  97. return status;
  98. }
  99. /*
  100. * send_coap_del_pattern_cmd_tlv() - Send wmi cmd for deleting CoAP pattern
  101. * @wmi_handle: wmi handle
  102. * @vdev_id: vdev id
  103. * @pattern_id: pattern id
  104. *
  105. * Return: QDF_STATUS
  106. */
  107. static QDF_STATUS
  108. send_coap_del_pattern_cmd_tlv(wmi_unified_t wmi_handle,
  109. uint8_t vdev_id, uint32_t pattern_id)
  110. {
  111. WMI_WOW_COAP_DEL_PATTERN_CMD_fixed_param *cmd;
  112. wmi_buf_t buf;
  113. QDF_STATUS status;
  114. uint32_t len = sizeof(*cmd);
  115. wmi_debug("vdev id %d pattern id %d", vdev_id, pattern_id);
  116. buf = wmi_buf_alloc(wmi_handle, len);
  117. if (!buf)
  118. return QDF_STATUS_E_NOMEM;
  119. cmd = (WMI_WOW_COAP_DEL_PATTERN_CMD_fixed_param *)wmi_buf_data(buf);
  120. WMITLV_SET_HDR(&cmd->tlv_header,
  121. WMITLV_TAG_STRUC_WMI_WOW_COAP_DEL_PATTERN_CMD_fixed_param,
  122. WMITLV_GET_STRUCT_TLVLEN(
  123. WMI_WOW_COAP_DEL_PATTERN_CMD_fixed_param));
  124. cmd->vdev_id = vdev_id;
  125. cmd->pattern_id = pattern_id;
  126. wmi_mtrace(WMI_WOW_COAP_DEL_PATTERN_CMDID,
  127. cmd->vdev_id, cmd->pattern_id);
  128. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  129. WMI_WOW_COAP_DEL_PATTERN_CMDID);
  130. if (status != QDF_STATUS_SUCCESS) {
  131. wmi_err("Failed to send wow coap del pattern command %d",
  132. status);
  133. wmi_buf_free(buf);
  134. }
  135. return status;
  136. }
  137. /*
  138. * send_coap_add_pattern_cmd_tlv() - Send wmi cmd for adding CoAP keepalive
  139. * pattern
  140. * @wmi_handle: wmi handle
  141. * @param: parameter for CoAP add pattern
  142. *
  143. * Return: QDF_STATUS
  144. */
  145. static QDF_STATUS
  146. send_coap_add_keepalive_pattern_cmd_tlv(wmi_unified_t wmi_handle,
  147. struct coap_offload_periodic_tx_param *param)
  148. {
  149. WMI_WOW_COAP_ADD_KEEPALIVE_PATTERN_CMD_fixed_param *cmd;
  150. wmi_buf_t buf;
  151. QDF_STATUS status;
  152. uint8_t *buf_ptr;
  153. uint32_t len, coapmsg_len_align;
  154. wmi_debug("vdev id %d pattern id %d ip src 0x%x:%d dest 0x%x:%d bc %d timeout %d",
  155. param->vdev_id, param->pattern_id, param->src_ip_v4,
  156. param->src_udp_port, param->dest_ip_v4,
  157. param->dest_udp_port, param->dest_ip_v4_is_bc,
  158. param->timeout);
  159. if (!param->coapmsg || !param->coapmsg_len) {
  160. wmi_err("invalid CoAP message");
  161. return QDF_STATUS_E_INVAL;
  162. }
  163. coapmsg_len_align = qdf_align(param->coapmsg_len, 4);
  164. len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + coapmsg_len_align;
  165. buf = wmi_buf_alloc(wmi_handle, len);
  166. if (!buf)
  167. return QDF_STATUS_E_NOMEM;
  168. buf_ptr = wmi_buf_data(buf);
  169. cmd = (WMI_WOW_COAP_ADD_KEEPALIVE_PATTERN_CMD_fixed_param *)buf_ptr;
  170. WMITLV_SET_HDR(&cmd->tlv_header,
  171. WMITLV_TAG_STRUC_WMI_WOW_COAP_ADD_KEEPALIVE_PATTERN_CMD_fixed_param,
  172. WMITLV_GET_STRUCT_TLVLEN(
  173. WMI_WOW_COAP_ADD_KEEPALIVE_PATTERN_CMD_fixed_param));
  174. cmd->vdev_id = param->vdev_id;
  175. cmd->pattern_id = param->pattern_id;
  176. /* only support IPv4 in current stage */
  177. WMI_COAP_IPV6_SET(cmd->pattern_type, 0);
  178. WMI_COAP_ADDR_TYPE_SET(cmd->pattern_type,
  179. param->dest_ip_v4_is_bc ? 1 : 0);
  180. qdf_mem_copy(cmd->udp_remote_ip.ipv4_addr, &param->dest_ip_v4,
  181. sizeof(param->dest_ip_v4));
  182. cmd->udp_remote_port = param->dest_udp_port;
  183. qdf_mem_copy(cmd->udp_local_ip.ipv4_addr, &param->src_ip_v4,
  184. sizeof(param->src_ip_v4));
  185. cmd->udp_local_port = param->src_udp_port;
  186. cmd->timeout = param->timeout;
  187. cmd->coapmsg_len = param->coapmsg_len;
  188. buf_ptr += sizeof(*cmd);
  189. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, coapmsg_len_align);
  190. buf_ptr += WMI_TLV_HDR_SIZE;
  191. qdf_mem_copy(buf_ptr, param->coapmsg, param->coapmsg_len);
  192. buf_ptr += coapmsg_len_align;
  193. wmi_mtrace(WMI_WOW_COAP_ADD_KEEPALIVE_PATTERN_CMDID,
  194. cmd->vdev_id, cmd->pattern_id);
  195. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  196. WMI_WOW_COAP_ADD_KEEPALIVE_PATTERN_CMDID);
  197. if (status != QDF_STATUS_SUCCESS) {
  198. wmi_err("Failed to send wow coap add keepalive pattern command %d",
  199. status);
  200. wmi_buf_free(buf);
  201. }
  202. return status;
  203. }
  204. /*
  205. * send_coap_del_pattern_cmd_tlv() - Send wmi cmd for deleting CoAP
  206. * keepalive pattern
  207. * @wmi_handle: wmi handle
  208. * @vdev_id: vdev id
  209. * @pattern_id: pattern id
  210. *
  211. * Return: QDF_STATUS
  212. */
  213. static QDF_STATUS
  214. send_coap_del_keepalive_pattern_cmd_tlv(wmi_unified_t wmi_handle,
  215. uint8_t vdev_id, uint32_t pattern_id)
  216. {
  217. WMI_WOW_COAP_DEL_KEEPALIVE_PATTERN_CMD_fixed_param *cmd;
  218. wmi_buf_t buf;
  219. QDF_STATUS status;
  220. uint8_t *buf_ptr;
  221. uint32_t len = sizeof(*cmd);
  222. wmi_debug("vdev id %d pattern id %d", vdev_id, pattern_id);
  223. buf = wmi_buf_alloc(wmi_handle, len);
  224. if (!buf)
  225. return QDF_STATUS_E_NOMEM;
  226. buf_ptr = wmi_buf_data(buf);
  227. cmd = (WMI_WOW_COAP_DEL_KEEPALIVE_PATTERN_CMD_fixed_param *)buf_ptr;
  228. WMITLV_SET_HDR(&cmd->tlv_header,
  229. WMITLV_TAG_STRUC_WMI_WOW_COAP_DEL_KEEPALIVE_PATTERN_CMD_fixed_param,
  230. WMITLV_GET_STRUCT_TLVLEN(
  231. WMI_WOW_COAP_DEL_PATTERN_CMD_fixed_param));
  232. cmd->vdev_id = vdev_id;
  233. cmd->pattern_id = pattern_id;
  234. wmi_mtrace(WMI_WOW_COAP_DEL_KEEPALIVE_PATTERN_CMDID,
  235. cmd->vdev_id, cmd->pattern_id);
  236. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  237. WMI_WOW_COAP_DEL_KEEPALIVE_PATTERN_CMDID);
  238. if (status != QDF_STATUS_SUCCESS) {
  239. wmi_err("Failed to send wow coap del keepalive pattern command %d",
  240. status);
  241. wmi_buf_free(buf);
  242. }
  243. return status;
  244. }
  245. /*
  246. * send_coap_cache_get_cmd_tlv() - Send wmi cmd for getting cached CoAP
  247. * messages
  248. * @wmi_handle: wmi handle
  249. * @vdev_id: vdev id
  250. * @pattern_id: pattern id
  251. *
  252. * Return: QDF_STATUS
  253. */
  254. static QDF_STATUS
  255. send_coap_cache_get_cmd_tlv(wmi_unified_t wmi_handle,
  256. uint8_t vdev_id, uint32_t pattern_id)
  257. {
  258. WMI_WOW_COAP_GET_BUF_INFO_CMD_fixed_param *cmd;
  259. wmi_buf_t buf;
  260. QDF_STATUS status;
  261. uint32_t len = sizeof(*cmd);
  262. wmi_debug("vdev id %d pattern id %d", vdev_id, pattern_id);
  263. buf = wmi_buf_alloc(wmi_handle, len);
  264. if (!buf)
  265. return QDF_STATUS_E_NOMEM;
  266. cmd = (WMI_WOW_COAP_GET_BUF_INFO_CMD_fixed_param *)wmi_buf_data(buf);
  267. WMITLV_SET_HDR(&cmd->tlv_header,
  268. WMITLV_TAG_STRUC_WMI_WOW_COAP_GET_BUF_INFO_CMD_fixed_param,
  269. WMITLV_GET_STRUCT_TLVLEN(
  270. WMI_WOW_COAP_GET_BUF_INFO_CMD_fixed_param));
  271. cmd->vdev_id = vdev_id;
  272. cmd->pattern_id = pattern_id;
  273. wmi_mtrace(WMI_WOW_COAP_GET_BUF_INFO_CMDID,
  274. cmd->vdev_id, cmd->pattern_id);
  275. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  276. WMI_WOW_COAP_GET_BUF_INFO_CMDID);
  277. if (status != QDF_STATUS_SUCCESS) {
  278. wmi_err("Failed to send wow coap get buf info command %d",
  279. status);
  280. wmi_buf_free(buf);
  281. }
  282. return status;
  283. }
  284. /**
  285. * coap_extract_buf_info_tlv() - Extract CoAP buf info event
  286. * @wmi_handle: wmi handle
  287. * @evt_buf: Pointer to the event buffer
  288. * @info: pointer to CoAP buf info
  289. *
  290. * The caller needs to free any possible nodes in info->info_list
  291. * regardless of failure or success.
  292. *
  293. * Return: QDF_STATUS
  294. */
  295. static QDF_STATUS
  296. coap_extract_buf_info_tlv(wmi_unified_t wmi_handle, void *evt_buf,
  297. struct coap_buf_info *info)
  298. {
  299. WMI_WOW_COAP_BUF_INFO_EVENT_fixed_param *buf_info_ev;
  300. WMI_WOW_COAP_BUF_INFO_EVENTID_param_tlvs *param_buf = evt_buf;
  301. wmi_coap_tuple *tuple;
  302. uint8_t *payload;
  303. uint32_t num_tuple, num_payload;
  304. struct coap_buf_node *buf_node;
  305. int i, j;
  306. buf_info_ev = param_buf->fixed_param;
  307. if (!buf_info_ev) {
  308. wmi_debug("received null event data from target");
  309. return QDF_STATUS_E_INVAL;
  310. }
  311. if (buf_info_ev->vdev_id > WLAN_MAX_VDEVS) {
  312. wmi_debug("received invalid vdev_id %d",
  313. buf_info_ev->vdev_id);
  314. return QDF_STATUS_E_INVAL;
  315. }
  316. info->vdev_id = buf_info_ev->vdev_id;
  317. info->req_id = buf_info_ev->pattern_id;
  318. info->more_info = buf_info_ev->more_tuples;
  319. num_tuple = param_buf->num_coap_tuple;
  320. num_payload = param_buf->num_payloads;
  321. for (i = 0, j = 0; i < num_tuple && j < num_payload; i++) {
  322. tuple = &param_buf->coap_tuple[i];
  323. if (!tuple->payload_len) {
  324. wmi_err("idx %d: invalid payload len 0", i);
  325. continue;
  326. }
  327. payload = &param_buf->payloads[j];
  328. j += qdf_align(tuple->payload_len, 4);
  329. if (j > num_payload) {
  330. wmi_err("idx %d: payload len overflow, pos %d - total %d",
  331. i, j, num_payload);
  332. return QDF_STATUS_E_INVAL;
  333. }
  334. buf_node = qdf_mem_malloc(sizeof(*buf_node));
  335. if (!buf_node)
  336. return QDF_STATUS_E_NOMEM;
  337. buf_node->payload = qdf_mem_malloc(tuple->payload_len);
  338. if (!buf_node->payload) {
  339. qdf_mem_free(buf_node);
  340. return QDF_STATUS_E_NOMEM;
  341. }
  342. buf_node->tsf = tuple->tsf;
  343. qdf_mem_copy(&buf_node->src_ip, tuple->src_ip.ipv4_addr,
  344. sizeof(buf_node->src_ip));
  345. buf_node->len = tuple->payload_len;
  346. qdf_mem_copy(buf_node->payload, payload, buf_node->len);
  347. qdf_list_insert_back(&info->info_list, &buf_node->node);
  348. wmi_debug("idx %d: src ip 0x%x tsf 0x%llx payload len %d",
  349. i, buf_node->src_ip, buf_node->tsf, buf_node->len);
  350. }
  351. wmi_debug("vdev_id %d req_id %d num_tuple %d payload len %d more info %d",
  352. info->vdev_id, info->req_id, num_tuple,
  353. num_payload, info->more_info);
  354. return QDF_STATUS_SUCCESS;
  355. }
  356. /**
  357. * wmi_coap_attach_tlv() - attach CoAP tlv handlers
  358. * @wmi_handle: wmi handle
  359. *
  360. * Return: void
  361. */
  362. void wmi_coap_attach_tlv(wmi_unified_t wmi_handle)
  363. {
  364. struct wmi_ops *ops = wmi_handle->ops;
  365. ops->send_coap_add_pattern_cmd = send_coap_add_pattern_cmd_tlv;
  366. ops->send_coap_del_pattern_cmd = send_coap_del_pattern_cmd_tlv;
  367. ops->send_coap_add_keepalive_pattern_cmd =
  368. send_coap_add_keepalive_pattern_cmd_tlv;
  369. ops->send_coap_del_keepalive_pattern_cmd =
  370. send_coap_del_keepalive_pattern_cmd_tlv;
  371. ops->send_coap_cache_get_cmd = send_coap_cache_get_cmd_tlv;
  372. ops->extract_coap_buf_info = coap_extract_buf_info_tlv;
  373. }