msc_example_main.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <assert.h>
  10. #include "freertos/FreeRTOS.h"
  11. #include "freertos/task.h"
  12. #include "freertos/queue.h"
  13. #include "freertos/semphr.h"
  14. #include "esp_err.h"
  15. #include "esp_log.h"
  16. #include "usb/usb_host.h"
  17. #include "msc_host.h"
  18. #include "msc_host_vfs.h"
  19. #include "ffconf.h"
  20. #include "ff.h"
  21. #include "esp_vfs.h"
  22. #include "errno.h"
  23. #include "hal/usb_hal.h"
  24. static const char* TAG = "example";
  25. static QueueHandle_t app_queue;
  26. static SemaphoreHandle_t ready_to_uninstall_usb;
  27. static void msc_event_cb(const msc_host_event_t *event, void *arg)
  28. {
  29. if (event->event == MSC_DEVICE_CONNECTED) {
  30. ESP_LOGI(TAG, "MSC device connected");
  31. } else if (event->event == MSC_DEVICE_DISCONNECTED) {
  32. ESP_LOGI(TAG, "MSC device disconnected");
  33. }
  34. xQueueSend(app_queue, event, 10);
  35. }
  36. static void print_device_info(msc_host_device_info_t *info)
  37. {
  38. const size_t megabyte = 1024 * 1024;
  39. uint64_t capacity = ((uint64_t)info->sector_size * info->sector_count) / megabyte;
  40. printf("Device info:\n");
  41. printf("\t Capacity: %llu MB\n", capacity);
  42. printf("\t Sector size: %u\n", info->sector_size);
  43. printf("\t Sector count: %u\n", info->sector_count);
  44. printf("\t PID: 0x%4X \n", info->idProduct);
  45. printf("\t VID: 0x%4X \n", info->idVendor);
  46. wprintf(L"\t iProduct: %S \n", info->iProduct);
  47. wprintf(L"\t iManufacturer: %S \n", info->iManufacturer);
  48. wprintf(L"\t iSerialNumber: %S \n", info->iSerialNumber);
  49. }
  50. static void file_operations(void)
  51. {
  52. const char *directory = "/usb/esp";
  53. const char *file_path = "/usb/esp/test.txt";
  54. struct stat s = {0};
  55. bool directory_exists = stat(directory, &s) == 0;
  56. if (!directory_exists) {
  57. if (mkdir(directory, 0775) != 0) {
  58. ESP_LOGE(TAG, "mkdir failed with errno: %s\n", strerror(errno));
  59. }
  60. }
  61. ESP_LOGI(TAG, "Writing file");
  62. FILE *f = fopen(file_path, "w");
  63. if (f == NULL) {
  64. ESP_LOGE(TAG, "Failed to open file for writing");
  65. return;
  66. }
  67. fprintf(f, "Hello World!\n");
  68. fclose(f);
  69. ESP_LOGI(TAG, "Reading file");
  70. f = fopen(file_path, "r");
  71. if (f == NULL) {
  72. ESP_LOGE(TAG, "Failed to open file for reading");
  73. return;
  74. }
  75. char line[64];
  76. fgets(line, sizeof(line), f);
  77. fclose(f);
  78. // strip newline
  79. char *pos = strchr(line, '\n');
  80. if (pos) {
  81. *pos = '\0';
  82. }
  83. ESP_LOGI(TAG, "Read from file: '%s'", line);
  84. }
  85. // Handles common USB host library events
  86. static void handle_usb_events(void *args)
  87. {
  88. while (1) {
  89. uint32_t event_flags;
  90. usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
  91. // Release devices once all clients has deregistered
  92. if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
  93. usb_host_device_free_all();
  94. }
  95. // Give ready_to_uninstall_usb semaphore to indicate that USB Host library
  96. // can be deinitialized, and terminate this task.
  97. if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
  98. xSemaphoreGive(ready_to_uninstall_usb);
  99. break;
  100. }
  101. }
  102. vTaskDelete(NULL);
  103. }
  104. static uint8_t wait_for_msc_device(void)
  105. {
  106. msc_host_event_t app_event;
  107. ESP_LOGI(TAG, "Waiting for USB stick to be connected");
  108. xQueueReceive(app_queue, &app_event, portMAX_DELAY);
  109. assert( app_event.event == MSC_DEVICE_CONNECTED );
  110. return app_event.device.address;
  111. }
  112. void app_main(void)
  113. {
  114. msc_host_device_handle_t msc_device;
  115. BaseType_t task_created;
  116. ready_to_uninstall_usb = xSemaphoreCreateBinary();
  117. app_queue = xQueueCreate(3, sizeof(msc_host_event_t));
  118. assert(app_queue);
  119. const usb_host_config_t host_config = { .intr_flags = ESP_INTR_FLAG_LEVEL1 };
  120. ESP_ERROR_CHECK( usb_host_install(&host_config) );
  121. task_created = xTaskCreate(handle_usb_events, "usb_events", 2048, NULL, 2, NULL);
  122. assert(task_created);
  123. const msc_host_driver_config_t msc_config = {
  124. .create_backround_task = true,
  125. .task_priority = 5,
  126. .stack_size = 2048,
  127. .callback = msc_event_cb,
  128. };
  129. ESP_ERROR_CHECK( msc_host_install(&msc_config) );
  130. uint8_t device_address = wait_for_msc_device();
  131. ESP_ERROR_CHECK( msc_host_install_device(device_address, &msc_device) );
  132. msc_host_print_descriptors(msc_device);
  133. msc_host_device_info_t info;
  134. ESP_ERROR_CHECK( msc_host_get_device_info(msc_device, &info) );
  135. print_device_info(&info);
  136. msc_host_vfs_handle_t vfs_handle;
  137. const esp_vfs_fat_mount_config_t mount_config = {
  138. .format_if_mount_failed = false,
  139. .max_files = 3,
  140. .allocation_unit_size = 1024,
  141. };
  142. ESP_ERROR_CHECK( msc_host_vfs_register(msc_device, "/usb", &mount_config, &vfs_handle) );
  143. file_operations();
  144. ESP_ERROR_CHECK( msc_host_vfs_unregister(vfs_handle) );
  145. ESP_ERROR_CHECK( msc_host_uninstall_device(msc_device) );
  146. ESP_ERROR_CHECK( msc_host_uninstall() );
  147. xSemaphoreTake(ready_to_uninstall_usb, portMAX_DELAY);
  148. ESP_ERROR_CHECK( usb_host_uninstall() );
  149. ESP_LOGI(TAG, "Done");
  150. }