host_file_io.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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_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. ESP_EARLY_LOGV(TAG, "%s %d", __func__, cmd);
  77. uint8_t *ptr = esp_apptrace_buffer_get(dest, sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
  78. if (ptr == NULL) {
  79. return ESP_ERR_NO_MEM;
  80. }
  81. hdr = (esp_apptrace_fcmd_hdr_t *)ptr;
  82. hdr->cmd = cmd;
  83. if (prep_args) {
  84. prep_args(ptr + sizeof(hdr->cmd), args);
  85. }
  86. // now indicate that this buffer is ready to be sent off to host
  87. ret = esp_apptrace_buffer_put(dest, ptr, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
  88. if (ret != ESP_OK) {
  89. ESP_EARLY_LOGE(TAG, "Failed to put apptrace buffer (%d)!", ret);
  90. return ret;
  91. }
  92. ret = esp_apptrace_flush(dest, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
  93. if (ret != ESP_OK) {
  94. ESP_EARLY_LOGE(TAG, "Failed to flush apptrace buffer (%d)!", ret);
  95. return ret;
  96. }
  97. return ESP_OK;
  98. }
  99. static esp_err_t esp_apptrace_file_rsp_recv(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t buf_len)
  100. {
  101. uint32_t tot_rd = 0;
  102. while (tot_rd < buf_len) {
  103. uint32_t rd_size = buf_len - tot_rd;
  104. esp_err_t ret = esp_apptrace_read(dest, buf + tot_rd, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
  105. if (ret != ESP_OK) {
  106. ESP_EARLY_LOGE(TAG, "Failed to read (%d)!", ret);
  107. return ret;
  108. }
  109. ESP_EARLY_LOGV(TAG, "%s read %d bytes", __FUNCTION__, rd_size);
  110. tot_rd += rd_size;
  111. }
  112. return ESP_OK;
  113. }
  114. static void esp_apptrace_fopen_args_prepare(uint8_t *buf, void *priv)
  115. {
  116. esp_apptrace_fopen_args_t *args = priv;
  117. memcpy(buf, args->path, args->path_len);
  118. memcpy(buf + args->path_len, args->mode, args->mode_len);
  119. }
  120. void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode)
  121. {
  122. esp_apptrace_fopen_args_t cmd_args;
  123. ESP_EARLY_LOGV(TAG, "esp_apptrace_fopen '%s' '%s'", path, mode);
  124. if (path == NULL || mode == NULL) {
  125. return 0;
  126. }
  127. cmd_args.path = path;
  128. cmd_args.path_len = strlen(path) + 1;
  129. cmd_args.mode = mode;
  130. cmd_args.mode_len = strlen(mode) + 1;
  131. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
  132. &cmd_args, cmd_args.path_len+cmd_args.mode_len);
  133. if (ret != ESP_OK) {
  134. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  135. return NULL;
  136. }
  137. // now read the answer
  138. void *resp;
  139. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  140. if (ret != ESP_OK) {
  141. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  142. return NULL;
  143. }
  144. return resp;
  145. }
  146. static void esp_apptrace_fclose_args_prepare(uint8_t *buf, void *priv)
  147. {
  148. esp_apptrace_fclose_args_t *args = priv;
  149. memcpy(buf, &args->file, sizeof(args->file));
  150. }
  151. int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream)
  152. {
  153. esp_apptrace_fclose_args_t cmd_args;
  154. cmd_args.file = stream;
  155. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare,
  156. &cmd_args, sizeof(cmd_args));
  157. if (ret != ESP_OK) {
  158. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  159. return EOF;
  160. }
  161. // now read the answer
  162. int resp;
  163. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  164. if (ret != ESP_OK) {
  165. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  166. return EOF;
  167. }
  168. return resp;
  169. }
  170. static void esp_apptrace_fwrite_args_prepare(uint8_t *buf, void *priv)
  171. {
  172. esp_apptrace_fwrite_args_t *args = priv;
  173. memcpy(buf, &args->file, sizeof(args->file));
  174. memcpy(buf + sizeof(args->file), args->buf, args->size);
  175. }
  176. size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream)
  177. {
  178. esp_apptrace_fwrite_args_t cmd_args;
  179. ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size*nmemb);
  180. if (ptr == NULL) {
  181. return 0;
  182. }
  183. cmd_args.buf = (void *)ptr;
  184. cmd_args.size = size * nmemb;
  185. cmd_args.file = stream;
  186. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
  187. &cmd_args, sizeof(cmd_args.file)+cmd_args.size);
  188. if (ret != ESP_OK) {
  189. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  190. return 0;
  191. }
  192. // now read the answer
  193. size_t resp;
  194. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  195. if (ret != ESP_OK) {
  196. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  197. return 0;
  198. }
  199. return resp;
  200. }
  201. static void esp_apptrace_fread_args_prepare(uint8_t *buf, void *priv)
  202. {
  203. esp_apptrace_fread_args_t *args = priv;
  204. memcpy(buf, &args->file, sizeof(args->file));
  205. memcpy(buf + sizeof(args->file), &args->size, sizeof(args->size));
  206. }
  207. size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream)
  208. {
  209. esp_apptrace_fread_args_t cmd_args;
  210. ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size*nmemb);
  211. if (ptr == NULL) {
  212. return 0;
  213. }
  214. cmd_args.size = size * nmemb;
  215. cmd_args.file = stream;
  216. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
  217. &cmd_args, sizeof(cmd_args));
  218. if (ret != ESP_OK) {
  219. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  220. return 0;
  221. }
  222. // now read the answer
  223. size_t resp;
  224. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  225. if (ret != ESP_OK) {
  226. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  227. return 0;
  228. }
  229. if (resp > 0) {
  230. ret = esp_apptrace_file_rsp_recv(dest, ptr, resp);
  231. if (ret != ESP_OK) {
  232. ESP_EARLY_LOGE(TAG, "Failed to read file data (%d)!", ret);
  233. return 0;
  234. }
  235. }
  236. return resp;
  237. }
  238. static void esp_apptrace_fseek_args_prepare(uint8_t *buf, void *priv)
  239. {
  240. esp_apptrace_fseek_args_t *args = priv;
  241. memcpy(buf, &args->file, sizeof(args->file));
  242. memcpy(buf + sizeof(args->file), &args->offset, sizeof(args->offset));
  243. memcpy(buf + sizeof(args->file) + sizeof(args->offset), &args->whence, sizeof(args->whence));
  244. }
  245. int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence)
  246. {
  247. esp_apptrace_fseek_args_t cmd_args;
  248. ESP_EARLY_LOGV(TAG, "esp_apptrace_fseek f %p o 0x%lx w %d", stream, offset, whence);
  249. cmd_args.file = stream;
  250. cmd_args.offset = offset;
  251. cmd_args.whence = whence;
  252. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
  253. &cmd_args, sizeof(cmd_args));
  254. if (ret != ESP_OK) {
  255. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  256. return -1;
  257. }
  258. // now read the answer
  259. int resp;
  260. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  261. if (ret != ESP_OK) {
  262. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  263. return -1;
  264. }
  265. return resp;
  266. }
  267. static void esp_apptrace_ftell_args_prepare(uint8_t *buf, void *priv)
  268. {
  269. esp_apptrace_ftell_args_t *args = priv;
  270. memcpy(buf, &args->file, sizeof(args->file));
  271. }
  272. int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream)
  273. {
  274. esp_apptrace_ftell_args_t cmd_args;
  275. cmd_args.file = stream;
  276. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare,
  277. &cmd_args, sizeof(cmd_args));
  278. if (ret != ESP_OK) {
  279. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  280. return -1;
  281. }
  282. // now read the answer
  283. int resp;
  284. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  285. if (ret != ESP_OK) {
  286. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  287. return -1;
  288. }
  289. return resp;
  290. }
  291. int esp_apptrace_fstop(esp_apptrace_dest_t dest)
  292. {
  293. ESP_EARLY_LOGV(TAG, "%s", __func__);
  294. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0);
  295. if (ret != ESP_OK) {
  296. ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret);
  297. }
  298. return ret;
  299. }
  300. #endif