host_file_io.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. // Copyright 2017 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. //
  14. // Hot It Works
  15. // ************
  16. //
  17. // This module implements host file I/O protocol on top of apptrace module.
  18. // The protocol is enough simple. It sends command with arguments to the host and receives response from it.
  19. // Responses contains return values of respective file I/O API. This value is returned to the caller.
  20. // Commands has the following format:
  21. // * Header. See esp_apptrace_fcmd_hdr_t.
  22. // * Operation arguments. See file operation helper structures below.
  23. #include <string.h>
  24. #include "esp_app_trace.h"
  25. #if CONFIG_ESP32_APPTRACE_ENABLE
  26. #define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
  27. #include "esp_log.h"
  28. const static char *TAG = "esp_host_file_io";
  29. #define ESP_APPTRACE_FILE_CMD_FOPEN 0x0
  30. #define ESP_APPTRACE_FILE_CMD_FCLOSE 0x1
  31. #define ESP_APPTRACE_FILE_CMD_FWRITE 0x2
  32. #define ESP_APPTRACE_FILE_CMD_FREAD 0x3
  33. #define ESP_APPTRACE_FILE_CMD_FSEEK 0x4
  34. #define ESP_APPTRACE_FILE_CMD_FTELL 0x5
  35. #define ESP_APPTRACE_FILE_CMD_STOP 0x6 // indicates that there is no files to transfer
  36. /** File operation header */
  37. typedef struct {
  38. uint8_t cmd; ///< Command ID
  39. } esp_apptrace_fcmd_hdr_t;
  40. /** Helper structure for fopen */
  41. typedef struct {
  42. const char *path;
  43. uint16_t path_len;
  44. const char *mode;
  45. uint16_t mode_len;
  46. } esp_apptrace_fopen_args_t;
  47. /** Helper structure for fclose */
  48. typedef struct {
  49. void *file;
  50. } esp_apptrace_fclose_args_t;
  51. /** Helper structure for fwrite */
  52. typedef struct {
  53. void * buf;
  54. size_t size;
  55. void * file;
  56. } esp_apptrace_fwrite_args_t;
  57. /** Helper structure for fread */
  58. typedef struct {
  59. size_t size;
  60. void * file;
  61. } esp_apptrace_fread_args_t;
  62. /** Helper structure for fseek */
  63. typedef struct {
  64. long offset;
  65. int whence;
  66. void * file;
  67. } esp_apptrace_fseek_args_t;
  68. /** Helper structure for ftell */
  69. typedef struct {
  70. void *file;
  71. } esp_apptrace_ftell_args_t;
  72. static esp_err_t esp_apptrace_file_cmd_send(esp_apptrace_dest_t dest, uint8_t cmd, void (*prep_args)(uint8_t *, void *), void *args, uint32_t args_len)
  73. {
  74. esp_err_t ret;
  75. esp_apptrace_fcmd_hdr_t *hdr;
  76. uint8_t *ptr = esp_apptrace_buffer_get(dest, sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
  77. if (ptr == NULL) {
  78. return ESP_ERR_NO_MEM;
  79. }
  80. hdr = (esp_apptrace_fcmd_hdr_t *)ptr;
  81. hdr->cmd = cmd;
  82. if (prep_args) {
  83. prep_args(ptr + sizeof(hdr->cmd), args);
  84. }
  85. // now indicate that this buffer is ready to be sent off to host
  86. ret = esp_apptrace_buffer_put(dest, ptr, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
  87. if (ret != ESP_OK) {
  88. ESP_LOGE(TAG, "Failed to put apptrace buffer (%d)!", ret);
  89. return ret;
  90. }
  91. ret = esp_apptrace_flush(dest, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
  92. if (ret != ESP_OK) {
  93. ESP_LOGE(TAG, "Failed to flush apptrace buffer (%d)!", ret);
  94. return ret;
  95. }
  96. return ESP_OK;
  97. }
  98. static esp_err_t esp_apptrace_file_rsp_recv(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t buf_len)
  99. {
  100. uint32_t tot_rd = 0;
  101. while (tot_rd < buf_len) {
  102. uint32_t rd_size = buf_len - tot_rd;
  103. esp_err_t ret = esp_apptrace_read(dest, buf, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
  104. if (ret != ESP_OK) {
  105. ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
  106. return ret;
  107. }
  108. tot_rd += rd_size;
  109. }
  110. return ESP_OK;
  111. }
  112. static void esp_apptrace_fopen_args_prepare(uint8_t *buf, void *priv)
  113. {
  114. esp_apptrace_fopen_args_t *args = priv;
  115. memcpy(buf, args->path, args->path_len);
  116. memcpy(buf + args->path_len, args->mode, args->mode_len);
  117. }
  118. void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode)
  119. {
  120. esp_apptrace_fopen_args_t cmd_args;
  121. cmd_args.path = path;
  122. cmd_args.path_len = strlen(path) + 1;
  123. cmd_args.mode = mode;
  124. cmd_args.mode_len = strlen(mode) + 1;
  125. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
  126. &cmd_args, cmd_args.path_len+cmd_args.mode_len);
  127. if (ret != ESP_OK) {
  128. ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  129. return NULL;
  130. }
  131. // now read the answer
  132. void *resp;
  133. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  134. if (ret != ESP_OK) {
  135. ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
  136. return NULL;
  137. }
  138. return resp;
  139. }
  140. static void esp_apptrace_fclose_args_prepare(uint8_t *buf, void *priv)
  141. {
  142. esp_apptrace_fclose_args_t *args = priv;
  143. memcpy(buf, &args->file, sizeof(args->file));
  144. }
  145. int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream)
  146. {
  147. esp_apptrace_fclose_args_t cmd_args;
  148. cmd_args.file = stream;
  149. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare,
  150. &cmd_args, sizeof(cmd_args));
  151. if (ret != ESP_OK) {
  152. ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  153. return EOF;
  154. }
  155. // now read the answer
  156. int resp;
  157. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  158. if (ret != ESP_OK) {
  159. ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
  160. return EOF;
  161. }
  162. return resp;
  163. }
  164. static void esp_apptrace_fwrite_args_prepare(uint8_t *buf, void *priv)
  165. {
  166. esp_apptrace_fwrite_args_t *args = priv;
  167. memcpy(buf, &args->file, sizeof(args->file));
  168. memcpy(buf + sizeof(args->file), args->buf, args->size);
  169. }
  170. size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream)
  171. {
  172. esp_apptrace_fwrite_args_t cmd_args;
  173. cmd_args.buf = (void *)ptr;
  174. cmd_args.size = size * nmemb;
  175. cmd_args.file = stream;
  176. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
  177. &cmd_args, sizeof(cmd_args.file)+cmd_args.size);
  178. if (ret != ESP_OK) {
  179. ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  180. return 0;
  181. }
  182. // now read the answer
  183. size_t resp;
  184. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  185. if (ret != ESP_OK) {
  186. ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
  187. return 0;
  188. }
  189. return resp;
  190. }
  191. static void esp_apptrace_fread_args_prepare(uint8_t *buf, void *priv)
  192. {
  193. esp_apptrace_fread_args_t *args = priv;
  194. memcpy(buf, &args->file, sizeof(args->file));
  195. memcpy(buf + sizeof(args->file), &args->size, sizeof(args->size));
  196. }
  197. size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream)
  198. {
  199. esp_apptrace_fread_args_t cmd_args;
  200. cmd_args.size = size * nmemb;
  201. cmd_args.file = stream;
  202. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
  203. &cmd_args, sizeof(cmd_args));
  204. if (ret != ESP_OK) {
  205. ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  206. return 0;
  207. }
  208. // now read the answer
  209. size_t resp;
  210. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  211. if (ret != ESP_OK) {
  212. ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
  213. return 0;
  214. }
  215. if (resp > 0) {
  216. ret = esp_apptrace_file_rsp_recv(dest, ptr, resp);
  217. if (ret != ESP_OK) {
  218. ESP_LOGE(TAG, "Failed to read file data (%d)!", ret);
  219. return 0;
  220. }
  221. }
  222. return resp;
  223. }
  224. static void esp_apptrace_fseek_args_prepare(uint8_t *buf, void *priv)
  225. {
  226. esp_apptrace_fseek_args_t *args = priv;
  227. memcpy(buf, &args->file, sizeof(args->file));
  228. }
  229. int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence)
  230. {
  231. esp_apptrace_fseek_args_t cmd_args;
  232. cmd_args.file = stream;
  233. cmd_args.offset = offset;
  234. cmd_args.whence = whence;
  235. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
  236. &cmd_args, sizeof(cmd_args));
  237. if (ret != ESP_OK) {
  238. ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  239. return -1;
  240. }
  241. // now read the answer
  242. int resp;
  243. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  244. if (ret != ESP_OK) {
  245. ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
  246. return -1;
  247. }
  248. return resp;
  249. }
  250. static void esp_apptrace_ftell_args_prepare(uint8_t *buf, void *priv)
  251. {
  252. esp_apptrace_ftell_args_t *args = priv;
  253. memcpy(buf, &args->file, sizeof(args->file));
  254. }
  255. int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream)
  256. {
  257. esp_apptrace_ftell_args_t cmd_args;
  258. cmd_args.file = stream;
  259. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare,
  260. &cmd_args, sizeof(cmd_args));
  261. if (ret != ESP_OK) {
  262. ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  263. return -1;
  264. }
  265. // now read the answer
  266. int resp;
  267. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  268. if (ret != ESP_OK) {
  269. ESP_LOGE(TAG, "Failed to read response (%d)!", ret);
  270. return -1;
  271. }
  272. return resp;
  273. }
  274. int esp_apptrace_fstop(esp_apptrace_dest_t dest)
  275. {
  276. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0);
  277. if (ret != ESP_OK) {
  278. ESP_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret);
  279. }
  280. return ret;
  281. }
  282. #endif