host_file_io.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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. 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. cmd_args.path = path;
  125. cmd_args.path_len = strlen(path) + 1;
  126. cmd_args.mode = mode;
  127. cmd_args.mode_len = strlen(mode) + 1;
  128. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
  129. &cmd_args, cmd_args.path_len+cmd_args.mode_len);
  130. if (ret != ESP_OK) {
  131. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  132. return NULL;
  133. }
  134. // now read the answer
  135. void *resp;
  136. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  137. if (ret != ESP_OK) {
  138. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  139. return NULL;
  140. }
  141. return resp;
  142. }
  143. static void esp_apptrace_fclose_args_prepare(uint8_t *buf, void *priv)
  144. {
  145. esp_apptrace_fclose_args_t *args = priv;
  146. memcpy(buf, &args->file, sizeof(args->file));
  147. }
  148. int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream)
  149. {
  150. esp_apptrace_fclose_args_t cmd_args;
  151. cmd_args.file = stream;
  152. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare,
  153. &cmd_args, sizeof(cmd_args));
  154. if (ret != ESP_OK) {
  155. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  156. return EOF;
  157. }
  158. // now read the answer
  159. int resp;
  160. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  161. if (ret != ESP_OK) {
  162. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  163. return EOF;
  164. }
  165. return resp;
  166. }
  167. static void esp_apptrace_fwrite_args_prepare(uint8_t *buf, void *priv)
  168. {
  169. esp_apptrace_fwrite_args_t *args = priv;
  170. memcpy(buf, &args->file, sizeof(args->file));
  171. memcpy(buf + sizeof(args->file), args->buf, args->size);
  172. }
  173. size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream)
  174. {
  175. esp_apptrace_fwrite_args_t cmd_args;
  176. ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size*nmemb);
  177. cmd_args.buf = (void *)ptr;
  178. cmd_args.size = size * nmemb;
  179. cmd_args.file = stream;
  180. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
  181. &cmd_args, sizeof(cmd_args.file)+cmd_args.size);
  182. if (ret != ESP_OK) {
  183. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  184. return 0;
  185. }
  186. // now read the answer
  187. size_t resp;
  188. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  189. if (ret != ESP_OK) {
  190. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  191. return 0;
  192. }
  193. return resp;
  194. }
  195. static void esp_apptrace_fread_args_prepare(uint8_t *buf, void *priv)
  196. {
  197. esp_apptrace_fread_args_t *args = priv;
  198. memcpy(buf, &args->file, sizeof(args->file));
  199. memcpy(buf + sizeof(args->file), &args->size, sizeof(args->size));
  200. }
  201. size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream)
  202. {
  203. esp_apptrace_fread_args_t cmd_args;
  204. ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size*nmemb);
  205. cmd_args.size = size * nmemb;
  206. cmd_args.file = stream;
  207. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
  208. &cmd_args, sizeof(cmd_args));
  209. if (ret != ESP_OK) {
  210. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  211. return 0;
  212. }
  213. // now read the answer
  214. size_t resp;
  215. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  216. if (ret != ESP_OK) {
  217. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  218. return 0;
  219. }
  220. if (resp > 0) {
  221. ret = esp_apptrace_file_rsp_recv(dest, ptr, resp);
  222. if (ret != ESP_OK) {
  223. ESP_EARLY_LOGE(TAG, "Failed to read file data (%d)!", ret);
  224. return 0;
  225. }
  226. }
  227. return resp;
  228. }
  229. static void esp_apptrace_fseek_args_prepare(uint8_t *buf, void *priv)
  230. {
  231. esp_apptrace_fseek_args_t *args = priv;
  232. memcpy(buf, &args->file, sizeof(args->file));
  233. memcpy(buf + sizeof(args->file), &args->offset, sizeof(args->offset));
  234. memcpy(buf + sizeof(args->file) + sizeof(args->offset), &args->whence, sizeof(args->whence));
  235. }
  236. int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence)
  237. {
  238. esp_apptrace_fseek_args_t cmd_args;
  239. ESP_EARLY_LOGV(TAG, "esp_apptrace_fseek f %p o 0x%lx w %d", stream, offset, whence);
  240. cmd_args.file = stream;
  241. cmd_args.offset = offset;
  242. cmd_args.whence = whence;
  243. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
  244. &cmd_args, sizeof(cmd_args));
  245. if (ret != ESP_OK) {
  246. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  247. return -1;
  248. }
  249. // now read the answer
  250. int resp;
  251. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  252. if (ret != ESP_OK) {
  253. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  254. return -1;
  255. }
  256. return resp;
  257. }
  258. static void esp_apptrace_ftell_args_prepare(uint8_t *buf, void *priv)
  259. {
  260. esp_apptrace_ftell_args_t *args = priv;
  261. memcpy(buf, &args->file, sizeof(args->file));
  262. }
  263. int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream)
  264. {
  265. esp_apptrace_ftell_args_t cmd_args;
  266. cmd_args.file = stream;
  267. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare,
  268. &cmd_args, sizeof(cmd_args));
  269. if (ret != ESP_OK) {
  270. ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
  271. return -1;
  272. }
  273. // now read the answer
  274. int resp;
  275. ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
  276. if (ret != ESP_OK) {
  277. ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
  278. return -1;
  279. }
  280. return resp;
  281. }
  282. int esp_apptrace_fstop(esp_apptrace_dest_t dest)
  283. {
  284. ESP_EARLY_LOGV(TAG, "%s", __func__);
  285. esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0);
  286. if (ret != ESP_OK) {
  287. ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret);
  288. }
  289. return ret;
  290. }
  291. #endif