tofile.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include <rtthread.h>
  10. #include <ymodem.h>
  11. #include <dfs_file.h>
  12. #include <unistd.h>
  13. #include <stdio.h>
  14. #include <sys/stat.h>
  15. #include <sys/statfs.h>
  16. #include <stdlib.h>
  17. #include <board.h>
  18. struct custom_ctx
  19. {
  20. struct rym_ctx parent;
  21. int fd;
  22. int flen;
  23. char fpath[256];
  24. };
  25. static enum rym_code _rym_bg(
  26. struct rym_ctx *ctx,
  27. rt_uint8_t *buf,
  28. rt_size_t len)
  29. {
  30. struct custom_ctx *cctx = (struct custom_ctx*)ctx;
  31. cctx->fpath[0] = '/';
  32. /* the buf should be the file name */
  33. strcpy(&(cctx->fpath[1]), (const char*)buf);
  34. cctx->fd = open(cctx->fpath, O_CREAT | O_WRONLY | O_TRUNC, 0);
  35. if (cctx->fd < 0)
  36. {
  37. rt_err_t err = rt_get_errno();
  38. rt_kprintf("error creating file: %d\n", err);
  39. rt_kprintf("abort transmission\n");
  40. return RYM_CODE_CAN;
  41. }
  42. cctx->flen = atoi((const char*)buf+strlen((const char*)buf)+1);
  43. if (cctx->flen == 0)
  44. cctx->flen = -1;
  45. return RYM_CODE_ACK;
  46. }
  47. static enum rym_code _rym_tof(
  48. struct rym_ctx *ctx,
  49. rt_uint8_t *buf,
  50. rt_size_t len)
  51. {
  52. struct custom_ctx *cctx = (struct custom_ctx*)ctx;
  53. RT_ASSERT(cctx->fd >= 0);
  54. if (cctx->flen == -1)
  55. {
  56. write(cctx->fd, buf, len);
  57. }
  58. else
  59. {
  60. int wlen = len > cctx->flen ? cctx->flen : len;
  61. write(cctx->fd, buf, wlen);
  62. cctx->flen -= wlen;
  63. }
  64. return RYM_CODE_ACK;
  65. }
  66. static enum rym_code _rym_end(
  67. struct rym_ctx *ctx,
  68. rt_uint8_t *buf,
  69. rt_size_t len)
  70. {
  71. struct custom_ctx *cctx = (struct custom_ctx*)ctx;
  72. RT_ASSERT(cctx->fd >= 0);
  73. close(cctx->fd);
  74. cctx->fd = -1;
  75. return RYM_CODE_ACK;
  76. }
  77. rt_err_t rym_write_to_file(rt_device_t idev)
  78. {
  79. rt_err_t res;
  80. struct custom_ctx *ctx = rt_malloc(sizeof(*ctx));
  81. RT_ASSERT(idev);
  82. rt_kprintf("entering RYM mode\n");
  83. res = rym_recv_on_device(&ctx->parent, idev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
  84. _rym_bg, _rym_tof, _rym_end, 1000);
  85. /* there is no Ymodem traffic on the line so print out info. */
  86. rt_kprintf("leaving RYM mode with code %d\n", res);
  87. rt_kprintf("file %s has been created.\n", ctx->fpath);
  88. rt_free(ctx);
  89. return res;
  90. }
  91. #ifdef RT_USING_FINSH
  92. #include <finsh.h>
  93. rt_err_t ry(char *dname)
  94. {
  95. rt_err_t res;
  96. rt_device_t dev = rt_device_find(dname);
  97. if (!dev)
  98. {
  99. rt_kprintf("could not find device:%s\n", dname);
  100. return -RT_ERROR;
  101. }
  102. res = rym_write_to_file(dev);
  103. return res;
  104. }
  105. FINSH_FUNCTION_EXPORT(ry, receive files by ymodem protocol);
  106. #endif