Ymodem ESP32 1.0.0
Loading...
Searching...
No Matches
YmodemReceive.cpp
Go to the documentation of this file.
1
15#include "YmodemReceive.h"
16
17int processDataPacket(uint8_t* packet_data, int packet_length, fs::File& ffd, unsigned int file_size, unsigned int* errors)
18{
19 static unsigned int file_len = 0;
20
21 if (file_len < file_size) {
22 unsigned int write_len = packet_length;
23 file_len += packet_length;
24 if (file_len > file_size) {
25 write_len -= (file_len - file_size);
26 file_len = file_size;
27 }
28
29 int written_bytes = ffd.write(packet_data + PACKET_HEADER, write_len);
30 if (written_bytes != write_len) {
31 send_CA();
32 return -6;
33 }
34 LED_toggle();
35 }
36 send_ACK();
37 return 0;
38}
39
40void handleEOFPacket(unsigned int* file_done, unsigned int* errors)
41{
42 static int eof_cnt = 0;
43
44 eof_cnt++;
45 if (eof_cnt == 1) {
46 send_NAK();
47 }
48 else {
49 send_ACK();
50 *file_done = 1;
51 }
52}
53
54void extractFileInfo(uint8_t* packet_data, char* getname, int* size)
55{
56 char file_size[128];
57 unsigned int i = 0;
58 uint8_t* file_ptr = packet_data + PACKET_HEADER;
59
60 // Extraer el nombre del archivo
61 if (getname) {
62 while ((*file_ptr != 0) && (i < 64)) { // Máximo 64 caracteres para el nombre
63 *getname = *file_ptr++;
64 getname++;
65 i++;
66 }
67 *getname = '\0'; // Terminar la cadena
68 }
69
70 // Saltar el nombre del archivo y buscar el tamaño
71 while ((*file_ptr != 0) && (file_ptr < packet_data + PACKET_1K_SIZE)) {
72 file_ptr++;
73 }
74 file_ptr++; // Saltar el byte nulo después del nombre
75
76 // Extraer el tamaño del archivo
77 i = 0;
78 while ((*file_ptr != ' ') && (i < sizeof(file_size) - 1)) { // Leer hasta el espacio
79 file_size[i++] = *file_ptr++;
80 }
81 file_size[i] = '\0'; // Terminar la cadena
82
83 // Convertir el tamaño del archivo de texto a entero
84 if (strlen(file_size) > 0) {
85 *size = strtol(file_size, NULL, 10); // Base 10
86 }
87 else {
88 *size = 0; // Si no hay tamaño, se interpreta como 0
89 }
90}
91
92int processHeaderPacket(uint8_t* packet_data, int packet_length, unsigned int maxsize, char* getname, int* size, unsigned int* errors)
93{
94 if (packet_data[PACKET_HEADER] != 0) { // Paquete válido
95 extractFileInfo(packet_data, getname, size);
96 if (*size < 1 || *size > maxsize) {
97 send_CA();
98 return (*size > maxsize) ? -9 : -4;
99 }
101 return 0;
102 }
103 else { // Paquete de encabezado vacío
104 (*errors)++;
105 if (*errors > 5) {
106 send_CA();
107 return -5;
108 }
109 send_NAK();
110 return 0;
111 }
112}
113
114int processPacket(uint8_t* packet_data, int packet_length, fs::File& ffd, unsigned int maxsize, char* getname, unsigned int packets_received,
115 int* size, unsigned int* file_done, unsigned int* errors)
116{
117 if (packet_length == 0) { // Paquete EOF
118 handleEOFPacket(file_done, errors);
119 return 0;
120 }
121 else if (packet_length == -1) { // Abortado por transmisor
122 send_ACK();
123 return -1;
124 }
125 else if (packet_length == -2) { // Error de recepción
126 (*errors)++;
127 if (*errors > 5) {
128 send_CA();
129 return -2;
130 }
131 send_NAK();
132 return 0;
133 }
134
135 // Paquete normal
136 if (packets_received == 0) {
137 return processHeaderPacket(packet_data, packet_length, maxsize, getname, size, errors);
138 }
139 else {
140 return processDataPacket(packet_data, packet_length, ffd, *size, errors);
141 }
142}
143
144int handleFileSession(fs::File& ffd, unsigned int maxsize, char* getname, unsigned int* session_done, unsigned int* errors)
145{
146 unsigned int file_done = 0, packets_received = 0;
147 int size = 0;
148
149 while (!file_done) {
150 LED_toggle();
151 int packet_length = 0;
152 uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
153
154 int result = Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT);
155 if (result == 0) { // Paquete recibido correctamente
156 int process_result = processPacket(packet_data, packet_length, ffd, maxsize, getname, packets_received, &size, &file_done, errors);
157 if (process_result < 0) {
158 return process_result; // Error durante el procesamiento
159 }
160 packets_received++;
161 }
162 else if (result == -2) { // Usuario abortó
163 send_CA();
164 return -7;
165 }
166 else { // Timeout o error
167 (*errors)++;
168 if (*errors > MAX_ERRORS) {
169 send_CA();
170 return -8;
171 }
172 send_CRC16();
173 }
174 }
175
176 *session_done = 1;
177 return size;
178}
#define PACKET_HEADER
Definition YmodemDef.h:29
#define NAK_TIMEOUT
Definition YmodemDef.h:47
#define PACKET_1K_SIZE
Definition YmodemDef.h:33
#define PACKET_OVERHEAD
Definition YmodemDef.h:31
#define MAX_ERRORS
Definition YmodemDef.h:48
void handleEOFPacket(unsigned int *file_done, unsigned int *errors)
Handles the End Of File (EOF) packet in the Ymodem protocol.
int processHeaderPacket(uint8_t *packet_data, int packet_length, unsigned int maxsize, char *getname, int *size, unsigned int *errors)
Processes the header packet of a Ymodem transfer.
int processPacket(uint8_t *packet_data, int packet_length, fs::File &ffd, unsigned int maxsize, char *getname, unsigned int packets_received, int *size, unsigned int *file_done, unsigned int *errors)
Processes a received Ymodem packet.
int processDataPacket(uint8_t *packet_data, int packet_length, fs::File &ffd, unsigned int file_size, unsigned int *errors)
Processes a data packet received via Ymodem protocol.
int handleFileSession(fs::File &ffd, unsigned int maxsize, char *getname, unsigned int *session_done, unsigned int *errors)
Handles a file session for receiving data.
void extractFileInfo(uint8_t *packet_data, char *getname, int *size)
Extracts file information from a Ymodem packet.
Ymodem Packet reception functions.
void IRAM_ATTR LED_toggle()
Toggles the state of an LED.
void send_CRC16()
Sends the CRC16 checksum.
void send_ACKCRC16()
Sends an acknowledgment with CRC16.
int32_t Receive_Packet(uint8_t *data, int *length, uint32_t timeout)
Receives a packet of data.
void send_CA()
Sends the CA (Cancel) signal.
void send_ACK()
Sends an acknowledgment (ACK) signal.
void send_NAK()
Sends a Negative Acknowledgement (NAK) signal.