|  | 
|  | 1 | +/***************************************************************************/ /** | 
|  | 2 | + * @file | 
|  | 3 | + * @brief sl_si91x_http_client_callback_framework.c | 
|  | 4 | + ******************************************************************************* | 
|  | 5 | + * # License | 
|  | 6 | + * <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b> | 
|  | 7 | + ******************************************************************************* | 
|  | 8 | + * | 
|  | 9 | + * SPDX-License-Identifier: Zlib | 
|  | 10 | + * | 
|  | 11 | + * The licensor of this software is Silicon Laboratories Inc. | 
|  | 12 | + * | 
|  | 13 | + * This software is provided 'as-is', without any express or implied | 
|  | 14 | + * warranty. In no event will the authors be held liable for any damages | 
|  | 15 | + * arising from the use of this software. | 
|  | 16 | + * | 
|  | 17 | + * Permission is granted to anyone to use this software for any purpose, | 
|  | 18 | + * including commercial applications, and to alter it and redistribute it | 
|  | 19 | + * freely, subject to the following restrictions: | 
|  | 20 | + * | 
|  | 21 | + * 1. The origin of this software must not be misrepresented; you must not | 
|  | 22 | + *    claim that you wrote the original software. If you use this software | 
|  | 23 | + *    in a product, an acknowledgment in the product documentation would be | 
|  | 24 | + *    appreciated but is not required. | 
|  | 25 | + * 2. Altered source versions must be plainly marked as such, and must not be | 
|  | 26 | + *    misrepresented as being the original software. | 
|  | 27 | + * 3. This notice may not be removed or altered from any source distribution. | 
|  | 28 | + * | 
|  | 29 | + ******************************************************************************/ | 
|  | 30 | + | 
|  | 31 | +#include "sl_si91x_http_client_callback_framework.h" | 
|  | 32 | +#include "sl_constants.h" | 
|  | 33 | +#include <string.h> | 
|  | 34 | + | 
|  | 35 | +/****************************************************** | 
|  | 36 | + *                    Constants | 
|  | 37 | + ******************************************************/ | 
|  | 38 | +//! HTTP OFFSET | 
|  | 39 | +#define SI91X_HTTP_OFFSET 12 | 
|  | 40 | + | 
|  | 41 | +//! HTTP PUT OFFSET | 
|  | 42 | +#define SI91X_HTTP_PUT_OFFSET 16 | 
|  | 43 | + | 
|  | 44 | +/****************************************************** | 
|  | 45 | + *                    Structures | 
|  | 46 | + ******************************************************/ | 
|  | 47 | +/** | 
|  | 48 | + * Callback entry structure for sl_http_client events | 
|  | 49 | + */ | 
|  | 50 | +typedef struct { | 
|  | 51 | +  sl_http_client_t client_handle;                   ///< HTTP client handle | 
|  | 52 | +  sl_http_client_event_handler_t callback_function; ///< User provided callback function pointer | 
|  | 53 | +} sl_http_client_callback_entry_t; | 
|  | 54 | + | 
|  | 55 | +/****************************************************** | 
|  | 56 | + *                 Global Variables | 
|  | 57 | + ******************************************************/ | 
|  | 58 | +static sl_http_client_callback_entry_t registered_callback[SL_HTTP_CLIENT_MAX_EVENT] = { 0 }; | 
|  | 59 | + | 
|  | 60 | +/****************************************************** | 
|  | 61 | + *               Function Declarations | 
|  | 62 | + ******************************************************/ | 
|  | 63 | +static sl_http_client_callback_entry_t *get_http_client_callback_entry(sl_http_client_event_t event); | 
|  | 64 | +static sl_status_t sl_si91x_http_client_put_delete(void); | 
|  | 65 | + | 
|  | 66 | +/****************************************************** | 
|  | 67 | + *               Function Definitions | 
|  | 68 | + ******************************************************/ | 
|  | 69 | +sl_status_t sl_http_client_register_callback(sl_http_client_event_t event, | 
|  | 70 | +                                             sl_http_client_t client_handle, | 
|  | 71 | +                                             sl_http_client_event_handler_t function) | 
|  | 72 | +{ | 
|  | 73 | +  // Get the callback entry associated with the specified event | 
|  | 74 | +  sl_http_client_callback_entry_t *entry = get_http_client_callback_entry(event); | 
|  | 75 | + | 
|  | 76 | +  // check if the entry is valid | 
|  | 77 | +  if (entry != NULL) { | 
|  | 78 | +    entry->client_handle     = client_handle; | 
|  | 79 | +    entry->callback_function = function; | 
|  | 80 | +    return SL_STATUS_OK; | 
|  | 81 | +  } | 
|  | 82 | +  return SL_STATUS_FAIL; | 
|  | 83 | +} | 
|  | 84 | + | 
|  | 85 | +static sl_status_t sl_si91x_http_client_put_delete(void) | 
|  | 86 | +{ | 
|  | 87 | +  sl_status_t status = SL_STATUS_OK; | 
|  | 88 | + | 
|  | 89 | +  sl_si91x_http_client_put_request_t *request = | 
|  | 90 | +    (sl_si91x_http_client_put_request_t *)malloc(sizeof(sl_si91x_http_client_put_request_t)); | 
|  | 91 | +  if (request == NULL) { | 
|  | 92 | +    return SL_STATUS_ALLOCATION_FAILED; | 
|  | 93 | +  } | 
|  | 94 | +  memset(request, 0, sizeof(sl_si91x_http_client_put_request_t)); | 
|  | 95 | +  request->command_type = SI91X_HTTP_CLIENT_PUT_DELETE; | 
|  | 96 | +  uint16_t packet_len   = sizeof(sl_si91x_http_client_put_request_t) - SI91X_HTTP_CLIENT_PUT_MAX_BUFFER_LENGTH; | 
|  | 97 | + | 
|  | 98 | +  status = sl_si91x_driver_send_command(RSI_WLAN_REQ_HTTP_CLIENT_PUT, | 
|  | 99 | +                                        SI91X_NETWORK_CMD, | 
|  | 100 | +                                        request, | 
|  | 101 | +                                        packet_len, | 
|  | 102 | +                                        SL_SI91X_WAIT_FOR_COMMAND_SUCCESS, | 
|  | 103 | +                                        NULL, | 
|  | 104 | +                                        NULL); | 
|  | 105 | +  // Free the memory allocated | 
|  | 106 | +  free(request); | 
|  | 107 | + | 
|  | 108 | +  // Verify the status | 
|  | 109 | +  VERIFY_STATUS_AND_RETURN(status); | 
|  | 110 | +  return status; | 
|  | 111 | +} | 
|  | 112 | + | 
|  | 113 | +static sl_http_client_callback_entry_t *get_http_client_callback_entry(sl_http_client_event_t event) | 
|  | 114 | +{ | 
|  | 115 | +  return ®istered_callback[event]; | 
|  | 116 | +} | 
|  | 117 | + | 
|  | 118 | +sl_status_t sl_http_client_default_event_handler(sl_http_client_event_t event, | 
|  | 119 | +                                                 sl_wifi_buffer_t *buffer, | 
|  | 120 | +                                                 void *sdk_context) | 
|  | 121 | +{ | 
|  | 122 | +  const sl_http_client_callback_entry_t *entry = get_http_client_callback_entry(event); | 
|  | 123 | + | 
|  | 124 | +  // Get the packet data from the buffer | 
|  | 125 | +  sl_si91x_packet_t *packet = (sl_si91x_packet_t *)sl_si91x_host_get_buffer_data(buffer, 0, NULL); | 
|  | 126 | + | 
|  | 127 | +  // Convert the firmware status to a library status | 
|  | 128 | +  sl_status_t status = convert_and_save_firmware_status(get_si91x_frame_status(packet)); | 
|  | 129 | + | 
|  | 130 | +  // Initialize an HTTP client response structure | 
|  | 131 | +  sl_http_client_response_t http_response = { 0 }; | 
|  | 132 | +  uint16_t end_of_data; | 
|  | 133 | +  uint16_t http_server_response; | 
|  | 134 | + | 
|  | 135 | +  http_response.status = status; | 
|  | 136 | + | 
|  | 137 | +  //! TBD | 
|  | 138 | +  http_response.response_headers = NULL; | 
|  | 139 | + | 
|  | 140 | +  if ((entry == NULL) && (entry->callback_function == NULL)) { | 
|  | 141 | +    return SL_STATUS_FAIL; | 
|  | 142 | +  } | 
|  | 143 | + | 
|  | 144 | +  SL_DEBUG_LOG("\r\n>>> %s : %x <<<\r\n", __func__, status); | 
|  | 145 | + | 
|  | 146 | +  // Handle different HTTP client response types based on the packet's command | 
|  | 147 | +  switch (packet->command) { | 
|  | 148 | +    case RSI_WLAN_RSP_HTTP_CLIENT_GET: | 
|  | 149 | +    case RSI_WLAN_RSP_HTTP_CLIENT_POST: | 
|  | 150 | +    case RSI_WLAN_RSP_HTTP_CLIENT_POST_DATA: { | 
|  | 151 | +      // Handle GET, POST, and POST_DATA responses | 
|  | 152 | +      if (status == SL_STATUS_OK) { | 
|  | 153 | +        // Extract http server response from packet | 
|  | 154 | +        memcpy(&http_server_response, packet->data + 2, sizeof(uint16_t)); | 
|  | 155 | + | 
|  | 156 | +        http_response.http_response_code = http_server_response; | 
|  | 157 | + | 
|  | 158 | +        // Check http server response and fill other callback response data | 
|  | 159 | +        // http server response - success codes 200 to 299, failure codes 300 to 499 | 
|  | 160 | +        // http_server_response will be zero, if FW returns error for any http client cmd | 
|  | 161 | +        if (http_server_response == 0 || (http_server_response >= 200 && http_server_response <= 499)) { | 
|  | 162 | +          // Extract end of data indication from packet | 
|  | 163 | +          memcpy(&end_of_data, packet->data, sizeof(uint16_t)); | 
|  | 164 | + | 
|  | 165 | +          http_response.end_of_data = end_of_data; | 
|  | 166 | +          http_response.data_buffer = &packet->data[SI91X_HTTP_OFFSET]; | 
|  | 167 | +          http_response.data_length = packet->length - SI91X_HTTP_OFFSET; | 
|  | 168 | +        } | 
|  | 169 | +      } else if (status == SL_STATUS_SI91X_HTTP_GET_CMD_IN_PROGRESS) { | 
|  | 170 | +        // Don't trigger the callback, If the HTTP GET execution is in progress | 
|  | 171 | +        return status; | 
|  | 172 | +      } | 
|  | 173 | +      break; | 
|  | 174 | +    } | 
|  | 175 | + | 
|  | 176 | +    case RSI_WLAN_RSP_HTTP_CLIENT_PUT: { | 
|  | 177 | +      // Handle PUT responses | 
|  | 178 | +      uint8_t http_cmd_type                                = *packet->data; | 
|  | 179 | +      const sl_si91x_http_client_put_pkt_rsp_t *response   = (sl_si91x_http_client_put_pkt_rsp_t *)&packet->data; | 
|  | 180 | +      const sl_si91x_http_put_pkt_server_rsp_t *server_rsp = (sl_si91x_http_put_pkt_server_rsp_t *)&packet->data; | 
|  | 181 | + | 
|  | 182 | +      // Delete HTTP PUT client if PUT request fails | 
|  | 183 | +      if (status != SL_STATUS_OK) { | 
|  | 184 | +        sl_si91x_http_client_put_delete(); | 
|  | 185 | +        break; | 
|  | 186 | +      } | 
|  | 187 | + | 
|  | 188 | +      // Check for HTTP_CLIENT_PUT_PKT command | 
|  | 189 | +      if (http_cmd_type == SI91X_HTTP_CLIENT_PUT_PKT) { | 
|  | 190 | +        http_response.data_length = 0; | 
|  | 191 | +        http_response.end_of_data = response->end_of_file; | 
|  | 192 | +      } | 
|  | 193 | +      // Check for HTTP Client PUT response from server | 
|  | 194 | +      else if (http_cmd_type == SI91X_HTTP_CLIENT_PUT_OFFSET_PKT) { | 
|  | 195 | +        http_response.data_length = (uint16_t)server_rsp->data_len; | 
|  | 196 | +        http_response.end_of_data = server_rsp->more; | 
|  | 197 | +      } | 
|  | 198 | + | 
|  | 199 | +      http_response.data_buffer = &packet->data[SI91X_HTTP_PUT_OFFSET]; | 
|  | 200 | + | 
|  | 201 | +      // 917 does not support HTTP Server response for SL_HTTP_PUT request | 
|  | 202 | +      http_response.http_response_code = 0; | 
|  | 203 | + | 
|  | 204 | +      // Delete HTTP PUT client if end of data is 1 | 
|  | 205 | +      if (http_response.end_of_data) { | 
|  | 206 | +        sl_si91x_http_client_put_delete(); | 
|  | 207 | +      } | 
|  | 208 | + | 
|  | 209 | +      break; | 
|  | 210 | +    } | 
|  | 211 | +    default: | 
|  | 212 | +      break; | 
|  | 213 | +  } | 
|  | 214 | +  return entry->callback_function(&entry->client_handle, event, &http_response, sdk_context); | 
|  | 215 | +} | 
0 commit comments