ES-2024 reverter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
1.8KB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <stdint.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <fcntl.h>
  9. #include "context.h"
  10. #include "filedata.h"
  11. #include "logging.h"
  12. enum {
  13. XM_SOH = 0x01,
  14. XM_EOT = 0x04,
  15. XM_ACK = 0x06,
  16. XM_NACK = 0x15,
  17. XM_C = 0x43
  18. };
  19. struct xmodem_pkt {
  20. uint8_t header;
  21. uint8_t count;
  22. uint8_t ncount;
  23. uint8_t data[128];
  24. uint16_t crc;
  25. } __attribute__((packed));
  26. static void calc_crc(struct xmodem_pkt *pkt)
  27. {
  28. uint16_t crc = 0;
  29. uint8_t *ptr = pkt->data;
  30. int i, j;
  31. for (i = 0; i < sizeof(pkt->data); i++) {
  32. crc = crc ^ (*ptr++ << 8);
  33. for (j = 0; j < 8; j++)
  34. crc = (crc & 0x8000) ? (crc << 1 ^ 0x1021) : (crc << 1);
  35. }
  36. /* byteswap */
  37. pkt->crc = ((crc & 0xFF00) >> 8) | ((crc & 0xFF) << 8);
  38. }
  39. int xmodem_read(int fd, void *privdata)
  40. {
  41. struct context *ctx = (struct context *)privdata;
  42. struct xmodem_pkt pkt;
  43. int len = read(fd, &pkt, sizeof(pkt));
  44. if (len <= 0) {
  45. log_print(LOG_WARN, "xmodem_read(): read()");
  46. return -1;
  47. }
  48. int pktnum = 0;
  49. switch (pkt.header) {
  50. case XM_C: /* first packet */
  51. log_print(LOG_DEBUG, "%s: XMODEM started (%d bytes)", ctx->devname, ctx->file->size);
  52. pktnum = 0;
  53. break;
  54. case XM_ACK: /* next packet */
  55. if (ctx->lastpkt * 128 >= ctx->file->size)
  56. return -1;
  57. pktnum = ctx->lastpkt +1;
  58. break;
  59. case XM_NACK: /* resend last packet */
  60. pktnum = ctx->lastpkt;
  61. break;
  62. }
  63. if (pktnum * 128 < ctx->file->size) {
  64. pkt.header = XM_SOH;
  65. pkt.count = ((pktnum +1) & 0xFF);
  66. pkt.ncount = 0xFF - pkt.count;
  67. memcpy(pkt.data, (void *)(ctx->file->data) + pktnum * 128, 128);
  68. calc_crc(&pkt);
  69. write(fd, &pkt, sizeof(pkt));
  70. } else {
  71. log_print(LOG_DEBUG, "%s: XMODEM completed", ctx->devname);
  72. pkt.header = XM_EOT;
  73. write(fd, &pkt, 1);
  74. }
  75. ctx->lastpkt = pktnum;
  76. return 0;
  77. }