11#include "cJSON.h"
2+ #include "class/hid/hid_device.h"
23#include "driver/gpio.h"
34#include "esp_adc/adc_continuous.h"
45#include "esp_log.h"
@@ -205,7 +206,7 @@ static esp_err_t init_spiffs(void) {
205206 esp_vfs_spiffs_conf_t conf = {
206207 .base_path = "/spiffs" ,
207208 .partition_label = NULL ,
208- .max_files = 5 ,
209+ .max_files = 1 ,
209210 .format_if_mount_failed = true
210211 };
211212
@@ -249,6 +250,7 @@ esp_err_t save_json_to_file(const char *filename, cJSON *json) {
249250 free (json_string );
250251
251252 ESP_LOGI (TAG , "JSON saved to file: %s" , filepath );
253+ ESP_LOGI (TAG , "JSON: %s" , cJSON_Print (json ));
252254 return ESP_OK ;
253255}
254256
@@ -296,6 +298,13 @@ cJSON *load_json_from_file(const char *filename) {
296298 return json ;
297299}
298300
301+ #define CDC_ACCUM_BUF_SIZE (1024 * 1024) // 1MB buffer for large JSON payloads
302+ static char cdc_accum_buf [CDC_ACCUM_BUF_SIZE ];
303+ static size_t cdc_accum_len = 0 ;
304+
305+ #define MARKER "[EOF]"
306+ #define MARKER_LEN (sizeof(MARKER) - 1)
307+
299308/**
300309 * @brief CDC device RX callback
301310 *
@@ -307,77 +316,48 @@ cJSON *load_json_from_file(const char *filename) {
307316void tinyusb_cdc_rx_callback (int itf , cdcacm_event_t * event ) {
308317 size_t rx_size = 0 ;
309318 esp_err_t ret = tinyusb_cdcacm_read (itf , rx_buf , CONFIG_TINYUSB_CDC_RX_BUFSIZE , & rx_size );
310- if (ret == ESP_OK ) {
311- // Null terminate the received data
312- rx_buf [rx_size ] = '\0' ;
313-
314- // Try to parse as JSON
315- cJSON * json = cJSON_Parse ((char * )rx_buf );
316- if (json != NULL ) {
317- // Valid JSON received, save it
318- ESP_LOGI (TAG , "Valid JSON received, saving to config.json" );
319- esp_err_t save_ret = save_json_to_file (JSON_FILENAME , json );
320-
321- // Send response
322- const char * response ;
323- if (save_ret == ESP_OK ) {
324- response = "JSON saved successfully\r\n" ;
325- } else {
326- response = "Error saving JSON\r\n" ;
327- }
328- tinyusb_cdcacm_write_queue (itf , (uint8_t * )response , strlen (response ));
329- tinyusb_cdcacm_write_flush (itf , 0 );
330-
331- cJSON_Delete (json );
332- } else {
333- // Not valid JSON, echo back as normal
334- usb_message_t tx_msg = {
335- .buf_len = rx_size ,
336- .itf = itf ,
337- };
338- memcpy (tx_msg .buf , rx_buf , rx_size );
339- xQueueSend (usb_queue , & tx_msg , 0 );
340- }
341- } else {
342- ESP_LOGE (TAG , "Read Error" );
343- }
344- }
345-
346- /**
347- * @brief CDC device line change callback
348- *
349- * CDC device signals, that the DTR, RTS states changed
350- *
351- * @param[in] itf CDC device index
352- * @param[in] event CDC event type
353- */
354- void tinyusb_cdc_line_state_changed_callback (int itf , cdcacm_event_t * event ) {
355- int dtr = event -> line_state_changed_data .dtr ;
356- int rts = event -> line_state_changed_data .rts ;
357- ESP_LOGI (TAG , "Line state changed on channel %d: DTR:%d, RTS:%d" , itf , dtr , rts );
358-
359- // When DTR is set, terminal connection is opened
360- if (dtr ) {
361- // Send welcome message
362- const char * hello = "Hello! ESP32-S3 CDC device is ready!\r\n" ;
363- tinyusb_cdcacm_write_queue (itf , (uint8_t * )hello , strlen (hello ));
364- tinyusb_cdcacm_write_flush (itf , 0 );
365-
366- // Load and send current JSON content
367- cJSON * json = load_json_from_file (JSON_FILENAME );
368- if (json != NULL ) {
369- char * json_str = cJSON_PrintUnformatted (json );
370- if (json_str != NULL ) {
371- tinyusb_cdcacm_write_queue (itf , (uint8_t * )json_str , strlen (json_str ));
372- tinyusb_cdcacm_write_queue (itf , (uint8_t * )"\r\n" , 2 );
373- tinyusb_cdcacm_write_flush (itf , 0 );
374- free (json_str );
319+ ESP_LOGI (TAG , "CDC RX callback: ret=%d, rx_size=%d" , ret , rx_size );
320+ if (ret == ESP_OK && rx_size > 0 ) {
321+ ESP_LOGI (TAG , "Accumulating %d bytes to buffer (current len: %d)" , rx_size , cdc_accum_len );
322+ // Check for buffer overflow
323+ if (cdc_accum_len + rx_size < CDC_ACCUM_BUF_SIZE ) {
324+ memcpy (& cdc_accum_buf [cdc_accum_len ], rx_buf , rx_size );
325+ cdc_accum_len += rx_size ;
326+ ESP_LOGI (TAG , "Buffer after accumulation: len=%d" , cdc_accum_len );
327+ ESP_LOG_BUFFER_HEXDUMP (TAG , rx_buf , rx_size , ESP_LOG_INFO );
328+
329+ // Robustly search for marker anywhere in the buffer
330+ if (cdc_accum_len >= MARKER_LEN ) {
331+ for (size_t i = 0 ; i <= cdc_accum_len - MARKER_LEN ; ++ i ) {
332+ if (memcmp (& cdc_accum_buf [i ], MARKER , MARKER_LEN ) == 0 ) {
333+ ESP_LOGI (TAG , "Marker detected ([EOF]) at position %d. Attempting to parse JSON." , (int )i );
334+ cdc_accum_buf [i ] = '\0' ; // Null-terminate before marker
335+
336+ // Try to parse as JSON
337+ cJSON * json = cJSON_Parse (cdc_accum_buf );
338+ if (json != NULL ) {
339+ ESP_LOGI (TAG , "Valid JSON received, saving to config.json" );
340+ save_json_to_file (JSON_FILENAME , json );
341+ cJSON_Delete (json );
342+ } else {
343+ ESP_LOGE (TAG , "Invalid JSON received. Parse failed." );
344+ }
345+ // Move any data after the marker to the start of the buffer (for next message)
346+ size_t remaining = cdc_accum_len - (i + MARKER_LEN );
347+ if (remaining > 0 ) {
348+ memmove (cdc_accum_buf , & cdc_accum_buf [i + MARKER_LEN ], remaining );
349+ }
350+ cdc_accum_len = remaining ;
351+ ESP_LOGI (TAG , "Buffer reset for next message. Remaining bytes: %d" , (int )cdc_accum_len );
352+ ESP_LOGI (TAG , "Last 16 bytes: %.*s" , 16 , & cdc_accum_buf [cdc_accum_len > 16 ? cdc_accum_len - 16 : 0 ]);
353+ break ; // Only handle one message per callback
354+ }
355+ }
375356 }
376- cJSON_Delete (json );
377357 } else {
378- const char * no_json = "No JSON configuration found\r\n" ;
379- tinyusb_cdcacm_write_queue ( itf , ( uint8_t * ) no_json , strlen ( no_json ) );
380- tinyusb_cdcacm_write_flush ( itf , 0 ) ;
358+ // Buffer overflow, reset (no response)
359+ ESP_LOGE ( TAG , "CDC accumulation buffer overflow. Resetting buffer." );
360+ cdc_accum_len = 0 ;
381361 }
382362 }
383363}
@@ -393,12 +373,7 @@ void app_main(void) {
393373
394374 // Initialize TinyUSB
395375 ESP_LOGI (TAG , "USB initialization" );
396- const tinyusb_config_t tusb_cfg = {
397- .device_descriptor = NULL ,
398- .string_descriptor = NULL ,
399- .external_phy = false,
400- .configuration_descriptor = NULL ,
401- };
376+ extern const tinyusb_config_t tusb_cfg ;
402377 ESP_ERROR_CHECK (tinyusb_driver_install (& tusb_cfg ));
403378
404379 // Initialize CDC
@@ -407,28 +382,68 @@ void app_main(void) {
407382 .cdc_port = TINYUSB_CDC_ACM_0 ,
408383 .callback_rx = & tinyusb_cdc_rx_callback ,
409384 .callback_rx_wanted_char = NULL ,
410- .callback_line_state_changed = & tinyusb_cdc_line_state_changed_callback ,
411- .callback_line_coding_changed = NULL
385+ .callback_line_state_changed = NULL ,
386+ .callback_line_coding_changed = NULL ,
387+ .rx_unread_buf_sz = CONFIG_TINYUSB_CDC_RX_BUFSIZE
412388 };
413389 ESP_ERROR_CHECK (tusb_cdc_acm_init (& acm_cfg ));
414390
415391 ESP_LOGI (TAG , "USB initialization DONE" );
416392
393+ // test init json
394+ cJSON * json = load_json_from_file (JSON_FILENAME );
395+ ESP_LOGI (TAG , "JSON: %s" , cJSON_PrintUnformatted (json ));
396+ // const int size = cJSON_GetArraySize(json);
397+ // for (int i = 0; i < size; i++) {
398+ // cJSON *item = cJSON_GetArrayItem(json, i);
399+ // cJSON *id = cJSON_GetObjectItemCaseSensitive(item, "id");
400+ // cJSON *hardware = cJSON_GetObjectItemCaseSensitive(item, "hardware");
401+ // cJSON *adcChannel = cJSON_GetObjectItemCaseSensitive(hardware, "adcChannel");
402+ // cJSON *muxChannel = cJSON_GetObjectItemCaseSensitive(hardware, "muxChannel");
403+ // cJSON *magnetDirection = cJSON_GetObjectItemCaseSensitive(hardware, "magnetDirection");
404+ // ESP_LOGI(TAG, "id: %d", id->valueint);
405+ // ESP_LOGI(TAG, "adcChannel: %d", adcChannel->valueint);
406+ // ESP_LOGI(TAG, "muxChannel: %d", muxChannel->valueint);
407+ // ESP_LOGI(TAG, "magnetDirection: %d", magnetDirection->valueint);
408+ // }
409+ // cJSON_Delete(json);
410+
417411 // Main loop
418412 while (1 ) {
419- if (xQueueReceive (usb_queue , & msg , portMAX_DELAY )) {
420- if (msg .buf_len ) {
421- // Print received data
422- ESP_LOGI (TAG , "Data from channel %d:" , msg .itf );
423- ESP_LOG_BUFFER_HEXDUMP (TAG , msg .buf , msg .buf_len , ESP_LOG_INFO );
424-
425- // Echo back
426- tinyusb_cdcacm_write_queue (msg .itf , msg .buf , msg .buf_len );
427- esp_err_t err = tinyusb_cdcacm_write_flush (msg .itf , 0 );
428- if (err != ESP_OK ) {
429- ESP_LOGE (TAG , "CDC write error: %s" , esp_err_to_name (err ));
430- }
431- }
432- }
413+ vTaskDelay (pdMS_TO_TICKS (10 ));
414+ // if (xQueueReceive(usb_queue, &msg, portMAX_DELAY)) {
415+ // if (msg.buf_len) {
416+ // // Print received data
417+ // ESP_LOGI(TAG, "Data from channel %d with length %d", msg.itf, msg.buf_len);
418+ // ESP_LOG_BUFFER_HEXDUMP(TAG, msg.buf, msg.buf_len, ESP_LOG_INFO);
419+
420+ // // // Echo back
421+ // // tinyusb_cdcacm_write_queue(msg.itf, msg.buf, msg.buf_len);
422+ // // esp_err_t err = tinyusb_cdcacm_write_flush(msg.itf, 0);
423+ // // if (err != ESP_OK) {
424+ // // ESP_LOGE(TAG, "CDC write error: %s", esp_err_to_name(err));
425+ // // }
426+ // }
427+ // }
433428 }
434429}
430+
431+ /********* TinyUSB HID callbacks ***************/
432+
433+ // Invoked when received GET_REPORT control request
434+ // Application must fill buffer report's content and return its length.
435+ // Return zero will cause the stack to STALL request
436+ uint16_t tud_hid_get_report_cb (uint8_t instance , uint8_t report_id , hid_report_type_t report_type , uint8_t * buffer , uint16_t reqlen ) {
437+ (void )instance ;
438+ (void )report_id ;
439+ (void )report_type ;
440+ (void )buffer ;
441+ (void )reqlen ;
442+
443+ return 0 ;
444+ }
445+
446+ // Invoked when received SET_REPORT control request or
447+ // received data on OUT endpoint ( Report ID = 0, Type = 0 )
448+ void tud_hid_set_report_cb (uint8_t instance , uint8_t report_id , hid_report_type_t report_type , uint8_t const * buffer , uint16_t bufsize ) {
449+ }
0 commit comments