diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index cac8803c3..1e5c12efb 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -11,12 +11,10 @@ jobs: example: - "examples/arduino-ble5-advertising" - "examples/arduino-blink" - - "examples/arduino-briki-internal-libs" - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-wifiscan" - - "examples/espidf-aws-iot" - "examples/espidf-ble-eddystone" - "examples/espidf-coap-server" - "examples/espidf-exceptions" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a93ede2d1..446f8849c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: [3.7] + python-version: [3.9] example: - "examples/espidf-hello-world" runs-on: ${{ matrix.os }} diff --git a/boards/4d_systems_esp32s3_gen4_r8n16.json b/boards/4d_systems_esp32s3_gen4_r8n16.json new file mode 100644 index 000000000..4418be557 --- /dev/null +++ b/boards/4d_systems_esp32s3_gen4_r8n16.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_S3R8N16", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32_s3r8n16" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "4D Systems GEN4-ESP32 16MB (ESP32S3-R8N16)", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://4dsystems.com.au/products", + "vendor": "4D Systems" +} diff --git a/boards/adafruit_camera_esp32s3.json b/boards/adafruit_camera_esp32s3.json new file mode 100644 index 000000000..2693d8649 --- /dev/null +++ b/boards/adafruit_camera_esp32s3.json @@ -0,0 +1,66 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-4MB-1ota.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_CAMERA_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x0117" + ], + [ + "0x239A", + "0x8117" + ], + [ + "0x239A", + "0x8118" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_camera_esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit pyCamera S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_camera_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s2.json b/boards/adafruit_feather_esp32s2.json new file mode 100644 index 000000000..1594c06c2 --- /dev/null +++ b/boards/adafruit_feather_esp32s2.json @@ -0,0 +1,64 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80EB" + ], + [ + "0x239A", + "0x00EB" + ], + [ + "0x239A", + "0x80EC" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_feather_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5000", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3_reversetft.json b/boards/adafruit_feather_esp32s3_reversetft.json index de9a8e53f..c9209de57 100644 --- a/boards/adafruit_feather_esp32s3_reversetft.json +++ b/boards/adafruit_feather_esp32s3_reversetft.json @@ -10,7 +10,8 @@ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT", "-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/adafruit_metro_esp32s3.json b/boards/adafruit_metro_esp32s3.json new file mode 100644 index 000000000..7b5b77d2f --- /dev/null +++ b/boards/adafruit_metro_esp32s3.json @@ -0,0 +1,67 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "partitions-16MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_METRO_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8145" + ], + [ + "0x239A", + "0x0145" + ], + [ + "0x239A", + "0x8146" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_metro_esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Metro ESP32-S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_metro_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5500", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32s3_n4r2.json b/boards/adafruit_qtpy_esp32s3_n4r2.json new file mode 100644 index 000000000..ec2b7648a --- /dev/null +++ b/boards/adafruit_qtpy_esp32s3_n4r2.json @@ -0,0 +1,66 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8143" + ], + [ + "0x239A", + "0x0143" + ], + [ + "0x239A", + "0x8144" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_qtpy_esp32s3_n4r2" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S3 (4M Flash 2M PSRAM)", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_qtpy_esp32s3_n4r2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5700", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qualia_s3_rgb666.json b/boards/adafruit_qualia_s3_rgb666.json new file mode 100644 index 000000000..e1607a913 --- /dev/null +++ b/boards/adafruit_qualia_s3_rgb666.json @@ -0,0 +1,67 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "partitions-16MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_QUALIA_S3_RGB666", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8147" + ], + [ + "0x239A", + "0x0147" + ], + [ + "0x239A", + "0x8148" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_qualia_s3_rgb666" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Qualia ESP32-S3 RGB666", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_qualia_s3_rgb666/tinyuf2.bin" + ] + ] + }, + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5800", + "vendor": "Adafruit" +} diff --git a/boards/atd147_s3.json b/boards/atd147_s3.json new file mode 100644 index 000000000..8fb9d0e00 --- /dev/null +++ b/boards/atd147_s3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ATD143_S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "atd147_s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ArtronShop ATD1.47-S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/ArtronShop", + "vendor": "ArtronShop" +} diff --git a/boards/aventen_s3_sync.json b/boards/aventen_s3_sync.json new file mode 100644 index 000000000..83cda02d4 --- /dev/null +++ b/boards/aventen_s3_sync.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_AVENTEN_S3_SYNC", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "Aventen_S3_Sync" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Aventen S3 Sync", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.linkedin.com/company/aventen/", + "vendor": "Aventen" +} diff --git a/boards/bee_data_logger.json b/boards/bee_data_logger.json new file mode 100644 index 000000000..eb9e79d0b --- /dev/null +++ b/boards/bee_data_logger.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_BeeDataLogger", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x815C" + ] + ], + "mcu": "esp32s3", + "variant": "Bee_Data_Logger" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Smart Bee Data Logger", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/strid3r21/Bee-Data-Logger", + "vendor": "Smart Bee" +} diff --git a/boards/briki_abc_esp32.json b/boards/briki_abc_esp32.json deleted file mode 100644 index 429514895..000000000 --- a/boards/briki_abc_esp32.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "mbcwb", - "extra_flags": "-DBRIKI_MBC_WB_ESP -DBRIKI_ABC -w", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "briki_mbcwb_esp32", - "partitions": "8MB_ffat.csv" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino" - ], - "name": "Briki ABC (MBC-WB) - ESP32", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 3407872, - "protocol": "mbctool", - "protocols": [ - "mbctool" - ], - "require_upload_port": true, - "speed": 1500000 - }, - "url": "https://briki.org", - "vendor": "meteca" -} diff --git a/boards/briki_mbc-wb_esp32.json b/boards/briki_mbc-wb_esp32.json deleted file mode 100644 index df5c3756a..000000000 --- a/boards/briki_mbc-wb_esp32.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "mbcwb", - "extra_flags": "-DBRIKI_MBC_WB_ESP -DBRIKI_MBC_WB -w", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "briki_mbcwb_esp32", - "partitions": "8MB_ffat.csv" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino" - ], - "name": "Briki MBC-WB - ESP32", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 3407872, - "protocol": "mbctool", - "protocols": [ - "mbctool" - ], - "require_upload_port": true, - "speed": 1500000 - }, - "url": "https://briki.org", - "vendor": "meteca" -} diff --git a/boards/esp32-c6-devkitc-1.json b/boards/esp32-c6-devkitc-1.json index 6e90aee03..18a76dcc7 100644 --- a/boards/esp32-c6-devkitc-1.json +++ b/boards/esp32-c6-devkitc-1.json @@ -15,7 +15,7 @@ "name": "Espressif ESP32-C6-DevKitC-1", "upload": { "flash_size": "8MB", - "maximum_ram_size": 524288, + "maximum_ram_size": 327680, "maximum_size": 8388608, "require_upload_port": true, "speed": 460800 diff --git a/boards/esp32-pico-devkitm-2.json b/boards/esp32-pico-devkitm-2.json new file mode 100644 index 000000000..821128b09 --- /dev/null +++ b/boards/esp32-pico-devkitm-2.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_PICO_DEVKITM_2", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-PICO-DevKitM-2", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-pico-devkitm-2.html", + "vendor": "Espressif Systems" +} diff --git a/boards/esp32-s3-devkitm-1.json b/boards/esp32-s3-devkitm-1.json index a7a1d5e88..b4bcf5ccb 100644 --- a/boards/esp32-s3-devkitm-1.json +++ b/boards/esp32-s3-devkitm-1.json @@ -24,6 +24,7 @@ "variant": "esp32s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/esp32s3_powerfeather.json b/boards/esp32s3_powerfeather.json new file mode 100644 index 000000000..1076778cb --- /dev/null +++ b/boards/esp32s3_powerfeather.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_POWERFEATHER", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x81BB" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3_powerfeather" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESP32-S3 PowerFeather", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://powerfeather.dev/", + "vendor": "PowerFeather" +} + diff --git a/boards/esp32s3usbotg.json b/boards/esp32s3usbotg.json new file mode 100644 index 000000000..eaa427ae0 --- /dev/null +++ b/boards/esp32s3usbotg.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_S3_USB_OTG", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3usbotg" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-USB-OTG", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32s3/esp32-s3-usb-otg/user_guide.html", + "vendor": "Espressif" +} diff --git a/boards/freenove_esp32_s3_wroom.json b/boards/freenove_esp32_s3_wroom.json new file mode 100644 index 000000000..5089f14fc --- /dev/null +++ b/boards/freenove_esp32_s3_wroom.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_USB_CDC_ON_BOOT=0" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "psram_type": "opi", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Freenove ESP32-S3 WROOM N8R8 (8MB Flash / 8MB PSRAM)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board", + "vendor": "Freenove" +} diff --git a/boards/freenove_esp32_wrover.json b/boards/freenove_esp32_wrover.json new file mode 100644 index 000000000..a154f82de --- /dev/null +++ b/boards/freenove_esp32_wrover.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_DEV", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wrover-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Freenove ESP32-Wrover", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://store.freenove.com/products/fnk0060", + "vendor": "Freenove" +} diff --git a/boards/heltec_wifi_kit_32_V3.json b/boards/heltec_wifi_kit_32_V3.json index d10631917..62d730131 100644 --- a/boards/heltec_wifi_kit_32_V3.json +++ b/boards/heltec_wifi_kit_32_V3.json @@ -21,7 +21,7 @@ ] ], "mcu": "esp32s3", - "variant": "heltec_wifi_kit_32_v3" + "variant": "heltec_wifi_kit_32_V3" }, "connectivity": [ "wifi", diff --git a/boards/heltec_wireless_stick_lite.json b/boards/heltec_wireless_stick_lite.json index 6ffac9acf..7382ddec0 100644 --- a/boards/heltec_wireless_stick_lite.json +++ b/boards/heltec_wireless_stick_lite.json @@ -6,7 +6,7 @@ "core": "esp32", "extra_flags": "-DARDUINO_HELTEC_WIRELESS_STICK_LITE", "f_cpu": "240000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "dio", "mcu": "esp32", "variant": "heltec_wireless_stick_lite" diff --git a/boards/ioxesp32.json b/boards/ioxesp32.json new file mode 100644 index 000000000..e1575422e --- /dev/null +++ b/boards/ioxesp32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_IOXESP32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "ioxesp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ArtronShop IOXESP32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.ioxesp32.com/", + "vendor": "ArtronShop" +} diff --git a/boards/ioxesp32ps.json b/boards/ioxesp32ps.json new file mode 100644 index 000000000..ad66d9b7d --- /dev/null +++ b/boards/ioxesp32ps.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_IOXESP32PS" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "ioxesp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ArtronShop IOXESP32PS", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.ioxesp32.com/", + "vendor": "ArtronShop" +} diff --git a/boards/lilka_v2.json b/boards/lilka_v2.json new file mode 100644 index 000000000..c21432e74 --- /dev/null +++ b/boards/lilka_v2.json @@ -0,0 +1,60 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LILKA", + "-DLILKA_VERSION=2", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8145" + ], + [ + "0x239A", + "0x0145" + ], + [ + "0x239A", + "0x8146" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Lilka v2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/and3rson/lilka", + "vendor": "Anderson & friends" +} + diff --git a/boards/lilygo-t-display.json b/boards/lilygo-t-display.json new file mode 100644 index 000000000..c55bdb152 --- /dev/null +++ b/boards/lilygo-t-display.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LILYGO_T_DISPLAY", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x1A86", + "0x55D4" + ] + ], + "mcu": "esp32", + "variant": "lilygo_t_display" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LilyGo T-Display", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "hhttps://www.lilygo.cc/products/lilygo%C2%AE-ttgo-t-display-1-14-inch-lcd-esp32-control-board", + "vendor": "LilyGo" +} diff --git a/boards/lionbits3.json b/boards/lionbits3.json new file mode 100644 index 000000000..56bc5cdb2 --- /dev/null +++ b/boards/lionbits3.json @@ -0,0 +1,51 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LIONBITS3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "lionbits3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Lion:Bit S3 STEM Dev Board", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://lionbit.cc/shop/", + "vendor": "Lion:Bit" +} diff --git a/boards/lolin32_lite.json b/boards/lolin32_lite.json index 5e16bc85a..45632691d 100644 --- a/boards/lolin32_lite.json +++ b/boards/lolin32_lite.json @@ -17,6 +17,9 @@ "ethernet", "can" ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, "frameworks": [ "arduino", "espidf" diff --git a/boards/lolin_s2_mini.json b/boards/lolin_s2_mini.json index 59832f8cb..1282c1fa2 100644 --- a/boards/lolin_s2_mini.json +++ b/boards/lolin_s2_mini.json @@ -7,7 +7,8 @@ "extra_flags": [ "-DARDUINO_LOLIN_S2_MINI", "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MODE=0" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/lolin_s3.json b/boards/lolin_s3.json index 9daea1796..8124b938a 100644 --- a/boards/lolin_s3.json +++ b/boards/lolin_s3.json @@ -7,10 +7,12 @@ }, "core": "esp32", "extra_flags": [ - "-DBOARD_HAS_PSRAM", "-DARDUINO_LOLIN_S3", + "-DBOARD_HAS_PSRAM", "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", @@ -39,9 +41,7 @@ "upload": { "flash_size": "16MB", "maximum_ram_size": 327680, - "maximum_size": 16777216, - "use_1200bps_touch": true, - "wait_for_upload_port": true, + "maximum_size": 16777216, "require_upload_port": true, "speed": 460800 }, diff --git a/boards/lolin_s3_pro.json b/boards/lolin_s3_pro.json new file mode 100644 index 000000000..4340aacc6 --- /dev/null +++ b/boards/lolin_s3_pro.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_S3_PRO", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8161" + ] + ], + "mcu": "esp32s3", + "variant": "lolin_s3_pro" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S3 PRO", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/s3/s3_pro.html", + "vendor": "WEMOS" +} diff --git a/boards/m5stack-core-esp32-16M.json b/boards/m5stack-core-esp32-16M.json new file mode 100644 index 000000000..4c5502dc4 --- /dev/null +++ b/boards/m5stack-core-esp32-16M.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stack_Core_ESP32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "m5stack_core_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack Core ESP32 16M", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 532480, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-cores3.json b/boards/m5stack-cores3.json index 069097dcf..96bc6864e 100644 --- a/boards/m5stack-cores3.json +++ b/boards/m5stack-cores3.json @@ -7,7 +7,9 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_M5STACK_CORES3", + "-DBOARD_HAS_PSRAM", "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_RUNNING_CORE=1", "-DARDUINO_EVENT_RUNNING_CORE=1" ], diff --git a/boards/motorgo_mini_1.json b/boards/motorgo_mini_1.json new file mode 100644 index 000000000..536d7e4ba --- /dev/null +++ b/boards/motorgo_mini_1.json @@ -0,0 +1,43 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DARDUINO_MOTORGO_MINI_1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "motorgo_mini_1" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MotorGo Mini 1 (ESP32-S3)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://motorgo.net/shop/ols/products/motorgo-mini-v1-dot-2-starter-kit-plus-motors", + "vendor": "MotorGo" +} diff --git a/boards/namino_arancio.json b/boards/namino_arancio.json new file mode 100644 index 000000000..e0fcd340c --- /dev/null +++ b/boards/namino_arancio.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_NAMINO_ARANCIO", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "namino_arancio" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Namino Arancio", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://namino.cc/boards/namino-arancio", + "vendor": "MECT SRL" +} diff --git a/boards/namino_rosso.json b/boards/namino_rosso.json new file mode 100644 index 000000000..01545844e --- /dev/null +++ b/boards/namino_rosso.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_NAMINO_ROSSO", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "namino_rosso" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Namino Rosso", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://namino.cc/boards/namino-rosso", + "vendor": "MECT SRL" +} diff --git a/boards/sensebox_mcu_esp32s2.json b/boards/sensebox_mcu_esp32s2.json new file mode 100644 index 000000000..dc9e6db07 --- /dev/null +++ b/boards/sensebox_mcu_esp32s2.json @@ -0,0 +1,65 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_SENSEBOX_MCU_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MSC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x81B8" + ], + [ + "0x303A", + "0x81B9" + ], + [ + "0x303A", + "0x81BA" + ] + ], + "mcu": "esp32s2", + "variant": "sensebox_mcu_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "senseBox MCU-S2 ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/sensebox_mcu_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://sensebox.de/en/products-home", + "vendor": "senseBox" +} diff --git a/boards/um_nanos3.json b/boards/um_nanos3.json new file mode 100644 index 000000000..921a36e3f --- /dev/null +++ b/boards/um_nanos3.json @@ -0,0 +1,51 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_NANOS3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8179" + ] + ], + "mcu": "esp32s3", + "variant": "um_nanos3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker NanoS3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/nanoS3", + "vendor": "Unexpected Maker" +} diff --git a/boards/weactstudio_esp32c3coreboard.json b/boards/weactstudio_esp32c3coreboard.json new file mode 100644 index 000000000..507e66526 --- /dev/null +++ b/boards/weactstudio_esp32c3coreboard.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32C3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WeAct Studio ESP32C3CoreBoard", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 409600, + "maximum_size": 393216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/WeActStudio/WeActStudio.ESP32C3CoreBoard", + "vendor": "WeAct Studio" +} diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index eea32aa38..537f4b292 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -32,12 +32,7 @@ SConscript("_embed_files.py", exports="env") -if build_core == "mbcwb": - SConscript( - join(DefaultEnvironment().PioPlatform().get_package_dir( - "framework-arduino-mbcwb"), "tools", "platformio-esp-build.py")) - -elif "espidf" not in env.subst("$PIOFRAMEWORK"): +if "espidf" not in env.subst("$PIOFRAMEWORK"): SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 9fff3a8fc..2ece86765 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -26,7 +26,7 @@ import sys import shutil import os -import pkg_resources +import re import platform as sys_platform import click @@ -59,11 +59,23 @@ idf_variant = mcu.lower() # Required until Arduino switches to v5 -IDF5 = platform.get_package_version("framework-espidf").split(".")[1].startswith("5") +IDF5 = ( + platform.get_package_version("framework-espidf") + .split(".")[1] + .startswith("5") +) IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c3", "esp32c6") else ("xtensa-%s" % mcu)) + "toolchain-riscv32-esp" + if mcu in ("esp32c3", "esp32c6") + else ( + ( + "toolchain-xtensa-esp-elf" + if "arduino" not in env.subst("$PIOFRAMEWORK") + else "toolchain-xtensa-%s" % mcu + ) + ) ) @@ -97,8 +109,8 @@ PROJECT_SRC_DIR = env.subst("$PROJECT_SRC_DIR") CMAKE_API_REPLY_PATH = os.path.join(".cmake", "api", "v1", "reply") SDKCONFIG_PATH = os.path.expandvars(board.get( - "build.esp-idf.sdkconfig_path", - os.path.join(PROJECT_DIR, "sdkconfig.%s" % env.subst("$PIOENV")), + "build.esp-idf.sdkconfig_path", + os.path.join(PROJECT_DIR, "sdkconfig.%s" % env.subst("$PIOENV")), )) @@ -318,8 +330,9 @@ def _normalize_define(define_string): define_string = define_string.strip() if "=" in define_string: define, value = define_string.split("=", maxsplit=1) - if '"' in value and not value.startswith("\\"): - # Escape only raw values + if any(char in value for char in (' ', '<', '>')): + value = f'"{value}"' + elif '"' in value and not value.startswith("\\"): value = value.replace('"', '\\"') return (define, value) return define_string @@ -330,8 +343,11 @@ def _normalize_define(define_string): ] for f in compile_group.get("compileCommandFragments", []): - if f.get("fragment", "").startswith("-D"): - result.append(_normalize_define(f["fragment"][2:])) + fragment = f.get("fragment", "").strip() + if fragment.startswith('"'): + fragment = fragment.strip('"') + if fragment.startswith("-D"): + result.append(_normalize_define(fragment[2:])) return result @@ -417,8 +433,8 @@ def _extract_flags(config): for cg in config["compileGroups"]: flags[cg["language"]] = [] for ccfragment in cg["compileCommandFragments"]: - fragment = ccfragment.get("fragment", "") - if not fragment.strip() or fragment.startswith("-D"): + fragment = ccfragment.get("fragment", "").strip("\" ") + if not fragment or fragment.startswith("-D"): continue flags[cg["language"]].extend( click.parser.split_arg_string(fragment.strip()) @@ -431,7 +447,7 @@ def _extract_flags(config): # Flags are sorted because CMake randomly populates build flags in code model return { - "ASFLAGS": sorted(app_flags.get("ASM", default_flags.get("ASM"))), + "ASPPFLAGS": sorted(app_flags.get("ASM", default_flags.get("ASM"))), "CFLAGS": sorted(app_flags.get("C", default_flags.get("C"))), "CXXFLAGS": sorted(app_flags.get("CXX", default_flags.get("CXX"))), } @@ -483,7 +499,7 @@ def _scan_components_from_framework(): return components or _scan_components_from_framework() -def extract_linker_script_fragments(framework_components_dir, sdk_config): +def extract_linker_script_fragments_backup(framework_components_dir, sdk_config): # Hardware-specific components are excluded from search and added manually below project_components = load_component_paths( framework_components_dir, ignored_component_prefixes=("esp32", "riscv") @@ -531,6 +547,52 @@ def extract_linker_script_fragments(framework_components_dir, sdk_config): return result +def extract_linker_script_fragments( + ninja_buildfile, framework_components_dir, sdk_config +): + def _normalize_fragment_path(base_dir, fragment_path): + if not os.path.isabs(fragment_path): + fragment_path = os.path.abspath( + os.path.join(base_dir, fragment_path) + ) + if not os.path.isfile(fragment_path): + print("Warning! The `%s` fragment is not found!" % fragment_path) + + return fragment_path + + assert os.path.isfile( + ninja_buildfile + ), "Cannot extract linker fragments! Ninja build file is missing!" + + result = [] + with open(ninja_buildfile, encoding="utf8") as fp: + for line in fp.readlines(): + if "sections.ld: CUSTOM_COMMAND" not in line: + continue + for fragment_match in re.finditer(r"(\S+\.lf\b)+", line): + result.append(_normalize_fragment_path( + BUILD_DIR, fragment_match.group(0).replace("$:", ":") + )) + + break + + # Fall back option if the new algorithm didn't work + if not result: + result = extract_linker_script_fragments_backup( + framework_components_dir, sdk_config + ) + + if board.get("build.esp-idf.extra_lf_files", ""): + for fragment_path in board.get( + "build.esp-idf.extra_lf_files" + ).splitlines(): + if not fragment_path.strip(): + continue + result.append(_normalize_fragment_path(PROJECT_DIR, fragment_path)) + + return result + + def create_custom_libraries_list(ldgen_libraries_file, ignore_targets): if not os.path.isfile(ldgen_libraries_file): sys.stderr.write("Error: Couldn't find the list of framework libraries\n") @@ -559,11 +621,13 @@ def create_custom_libraries_list(ldgen_libraries_file, ignore_targets): def generate_project_ld_script(sdk_config, ignore_targets=None): ignore_targets = ignore_targets or [] linker_script_fragments = extract_linker_script_fragments( - os.path.join(FRAMEWORK_DIR, "components"), sdk_config + os.path.join(BUILD_DIR, "build.ninja"), + os.path.join(FRAMEWORK_DIR, "components"), + sdk_config ) - # Create a new file to avoid automatically generated library entry as files from - # this library are built internally by PlatformIO + # Create a new file to avoid automatically generated library entry as files + # from this library are built internally by PlatformIO libraries_list = create_custom_libraries_list( os.path.join(BUILD_DIR, "ldgen_libraries"), ignore_targets ) @@ -592,16 +656,31 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): '--objdump "{objdump}"' ).format(**args) + initial_ld_script = os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "sections.ld.in", + ) + + framework_version = [int(v) for v in get_framework_version().split(".")] + if framework_version[:2] > [5, 2]: + initial_ld_script = preprocess_linker_file( + initial_ld_script, + os.path.join( + BUILD_DIR, + "esp-idf", + "esp_system", + "ld", + "sections.ld.in", + ) + ) + return env.Command( os.path.join("$BUILD_DIR", "sections.ld"), - os.path.join( - FRAMEWORK_DIR, - "components", - "esp_system", - "ld", - idf_variant, - "sections.ld.in", - ), + initial_ld_script, env.VerboseAction(cmd, "Generating project linker script $TARGET"), ) @@ -640,7 +719,7 @@ def prepare_build_envs(config, default_env, debug_allowed=True): build_env = default_env.Clone() build_env.SetOption("implicit_cache", 1) for cc in compile_commands: - build_flags = cc.get("fragment") + build_flags = cc.get("fragment", "").strip("\" ") if not build_flags.startswith("-D"): if build_flags.startswith("-include") and ".." in build_flags: source_index = cg.get("sourceIndexes")[0] @@ -649,7 +728,7 @@ def prepare_build_envs(config, default_env, debug_allowed=True): parsed_flags = build_env.ParseFlags(build_flags) build_env.AppendUnique(**parsed_flags) if cg.get("language", "") == "ASM": - build_env.AppendUnique(ASFLAGS=parsed_flags.get("CCFLAGS", [])) + build_env.AppendUnique(ASPPFLAGS=parsed_flags.get("CCFLAGS", [])) build_env.AppendUnique(CPPDEFINES=defines, CPPPATH=includes) if sys_includes: build_env.Append(CCFLAGS=[("-isystem", inc) for inc in sys_includes]) @@ -681,7 +760,7 @@ def compile_source_files( src_path = os.path.join(project_src_dir, src_path) obj_path = os.path.join("$BUILD_DIR", prepend_dir or "") - if src_path.startswith(components_dir): + if src_path.lower().startswith(components_dir.lower()): obj_path = os.path.join( obj_path, os.path.relpath(src_path, components_dir) ) @@ -692,8 +771,8 @@ def compile_source_files( obj_path = os.path.join(obj_path, os.path.basename(src_path)) preserve_source_file_extension = board.get( - "build.esp-idf.preserve_source_file_extension", False - ) + "build.esp-idf.preserve_source_file_extension", "yes" + ) == "yes" objects.append( build_envs[compile_group_idx].StaticObject( @@ -800,6 +879,7 @@ def build_bootloader(sdk_config): "-DPYTHON=" + get_python_exe(), "-DIDF_PATH=" + FRAMEWORK_DIR, "-DSDKCONFIG=" + SDKCONFIG_PATH, + "-DPROJECT_SOURCE_DIR=" + PROJECT_DIR, "-DLEGACY_INCLUDE_COMMON_HEADERS=", "-DEXTRA_COMPONENT_DIRS=" + os.path.join(FRAMEWORK_DIR, "components", "bootloader"), @@ -939,12 +1019,38 @@ def find_default_component(target_configs): env.Exit(1) +def get_framework_version(): + def _extract_from_cmake_version_file(): + version_cmake_file = os.path.join( + FRAMEWORK_DIR, "tools", "cmake", "version.cmake" + ) + if not os.path.isfile(version_cmake_file): + return + + with open(version_cmake_file, encoding="utf8") as fp: + pattern = r"set\(IDF_VERSION_(MAJOR|MINOR|PATCH) (\d+)\)" + matches = re.findall(pattern, fp.read()) + if len(matches) != 3: + return + # If found all three parts of the version + return ".".join([match[1] for match in matches]) + + pkg = platform.get_package("framework-espidf") + version = get_original_version(str(pkg.metadata.version.truncate())) + if not version: + # Fallback value extracted directly from the cmake version file + version = _extract_from_cmake_version_file() + if not version: + version = "0.0.0" + + return version + + def create_version_file(): version_file = os.path.join(FRAMEWORK_DIR, "version.txt") if not os.path.isfile(version_file): with open(version_file, "w") as fp: - package_version = platform.get_package_version("framework-espidf") - fp.write(get_original_version(package_version) or package_version) + fp.write(get_framework_version()) def generate_empty_partition_image(binary_path, image_size): @@ -972,7 +1078,7 @@ def generate_empty_partition_image(binary_path, image_size): def get_partition_info(pt_path, pt_offset, pt_params): if not os.path.isfile(pt_path): sys.stderr.write( - "Missing partition table file `%s`\n" % os.path.basename(pt_path) + "Missing partition table file `%s`\n" % pt_path ) env.Exit(1) @@ -1025,6 +1131,46 @@ def get_app_partition_offset(pt_table, pt_offset): return app_params.get("offset", "0x10000") +def preprocess_linker_file(src_ld_script, target_ld_script): + return env.Command( + target_ld_script, + src_ld_script, + env.VerboseAction( + " ".join( + [ + os.path.join( + platform.get_package_dir("tool-cmake"), + "bin", + "cmake", + ), + "-DCC=%s" + % os.path.join( + TOOLCHAIN_DIR, + "bin", + "$CC", + ), + "-DSOURCE=$SOURCE", + "-DTARGET=$TARGET", + "-DCONFIG_DIR=%s" % os.path.join(BUILD_DIR, "config"), + "-DLD_DIR=%s" + % os.path.join( + FRAMEWORK_DIR, "components", "esp_system", "ld" + ), + "-P", + os.path.join( + "$BUILD_DIR", + "esp-idf", + "esp_system", + "ld", + "linker_script_generator.cmake", + ), + ] + ), + "Generating LD script $TARGET", + ), + ) + + def generate_mbedtls_bundle(sdk_config): bundle_path = os.path.join("$BUILD_DIR", "x509_crt_bundle") if os.path.isfile(env.subst(bundle_path)): @@ -1110,16 +1256,20 @@ def _get_installed_pip_packages(python_exe_path): return result + skip_python_packages = os.path.join(FRAMEWORK_DIR, ".pio_skip_pypackages") + if os.path.isfile(skip_python_packages): + return + deps = { # https://github.com/platformio/platformio-core/issues/4614 "urllib3": "<2", # https://github.com/platformio/platform-espressif32/issues/635 "cryptography": "~=41.0.1" if IDF5 else ">=2.1.4,<35.0.0", "future": ">=0.18.3", - "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", + "pyparsing": ">=3.1.0,<4" if IDF5 else ">=2.0.3,<2.4.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", - "idf-component-manager": "~=1.2.3" if IDF5 else "~=1.0", - "esp-idf-kconfig": "~=1.2.0" + "idf-component-manager": "~=1.5.2" if IDF5 else "~=1.0", + "esp-idf-kconfig": ">=1.4.2,<2.0.0" } if sys_platform.system() == "Darwin" and "arm" in sys_platform.machine().lower(): @@ -1157,9 +1307,7 @@ def _get_installed_pip_packages(python_exe_path): # A special "esp-windows-curses" python package is required on Windows # for Menuconfig on IDF <5 - if not IDF5 and "esp-windows-curses" not in { - pkg.key for pkg in pkg_resources.working_set - }: + if not IDF5 and "esp-windows-curses" not in installed_packages: env.Execute( env.VerboseAction( '"%s" -m pip install "file://%s/tools/kconfig_new/esp-windows-curses"' @@ -1168,16 +1316,18 @@ def _get_installed_pip_packages(python_exe_path): ) ) + def get_idf_venv_dir(): # The name of the IDF venv contains the IDF version to avoid possible conflicts and # unnecessary reinstallation of Python dependencies in cases when Arduino # as an IDF component requires a different version of the IDF package and # hence a different set of Python deps or their versions - idf_version = get_original_version(platform.get_package_version("framework-espidf")) + idf_version = get_framework_version() return os.path.join( env.subst("$PROJECT_CORE_DIR"), "penv", ".espidf-" + idf_version ) + def ensure_python_venv_available(): def _is_venv_outdated(venv_data_file): @@ -1212,7 +1362,7 @@ def _create_venv(venv_dir): env.Execute( env.VerboseAction( '"$PYTHONEXE" -m venv --clear "%s"' % venv_dir, - "Creating a new virtual environment for IDF Python dependencies", + "Creating a new virtual environment for IDF Python dependencies", ) ) @@ -1220,7 +1370,6 @@ def _create_venv(venv_dir): pip_path ), "Error: Failed to create a proper virtual environment. Missing the `pip` binary!" - venv_dir = get_idf_venv_dir() venv_data_file = os.path.join(venv_dir, "pio-idf-venv.json") if not os.path.isfile(venv_data_file) or _is_venv_outdated(venv_data_file): @@ -1267,19 +1416,31 @@ def get_python_exe(): # if not board.get("build.ldscript", ""): - linker_script = env.Command( - os.path.join("$BUILD_DIR", "memory.ld"), - board.get( - "build.esp-idf.ldscript", + initial_ld_script = board.get("build.esp-idf.ldscript", os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "memory.ld.in", + )) + + framework_version = [int(v) for v in get_framework_version().split(".")] + if framework_version[:2] > [5, 2]: + initial_ld_script = preprocess_linker_file( + initial_ld_script, os.path.join( - FRAMEWORK_DIR, - "components", + BUILD_DIR, + "esp-idf", "esp_system", "ld", - idf_variant, "memory.ld.in", - ), - ), + ) + ) + + linker_script = env.Command( + os.path.join("$BUILD_DIR", "memory.ld"), + initial_ld_script, env.VerboseAction( '$CC -I"$BUILD_DIR/config" -I"%s" -C -P -x c -E $SOURCE -o $TARGET' % os.path.join(FRAMEWORK_DIR, "components", "esp_system", "ld"), @@ -1441,7 +1602,9 @@ def get_python_exe(): # Extra flags which need to be explicitly specified in LINKFLAGS section because SCons # cannot merge them correctly -extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) +extra_flags = filter_args( + link_args["LINKFLAGS"], ["-T", "-u", "-Wl,--start-group", "-Wl,--end-group"] +) link_args["LINKFLAGS"] = sorted(list(set(link_args["LINKFLAGS"]) - set(extra_flags))) # remove the main linker script flags '-T memory.ld' @@ -1582,13 +1745,44 @@ def _skip_prj_source_files(node): if sdk_config.get("MBEDTLS_CERTIFICATE_BUNDLE", False): generate_mbedtls_bundle(sdk_config) +# +# Check if flash size is set correctly in the IDF configuration file +# + +board_flash_size = board.get("upload.flash_size", "4MB") +idf_flash_size = sdk_config.get("ESPTOOLPY_FLASHSIZE", "4MB") +if board_flash_size != idf_flash_size: + print( + "Warning! Flash memory size mismatch detected. Expected %s, found %s!" + % (board_flash_size, idf_flash_size) + ) + print( + "Please select a proper value in your `sdkconfig.defaults` " + "or via the `menuconfig` target!" + ) + # # To embed firmware checksum a special argument for esptool.py is required # +extra_elf2bin_flags = "--elf-sha256-offset 0xb0" +# https://github.com/espressif/esp-idf/blob/master/components/esptool_py/project_include.cmake#L58 +# For chips that support configurable MMU page size feature +# If page size is configured to values other than the default "64KB" in menuconfig, +mmu_page_size = "64KB" +if sdk_config.get("SOC_MMU_PAGE_SIZE_CONFIGURABLE", False): + if board_flash_size == "2MB": + mmu_page_size = "32KB" + elif board_flash_size == "1MB": + mmu_page_size = "16KB" + +if mmu_page_size != "64KB": + extra_elf2bin_flags += " --flash-mmu-page-size %s" % mmu_page_size + action = copy.deepcopy(env["BUILDERS"]["ElfToBin"].action) + action.cmd_list = env["BUILDERS"]["ElfToBin"].action.cmd_list.replace( - "-o", "--elf-sha256-offset 0xb0 -o" + "-o", extra_elf2bin_flags + " -o" ) env["BUILDERS"]["ElfToBin"].action = action diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 5af8f87d1..89aa42011 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -13,10 +13,11 @@ # limitations under the License. import os +import sys from platformio import fs from platformio.util import get_systype -from platformio.proc import where_is_program +from platformio.proc import where_is_program, exec_command from SCons.Script import Import @@ -34,11 +35,14 @@ def prepare_ulp_env_vars(env): ulp_env.PrependENVPath("IDF_PATH", FRAMEWORK_DIR) + toolchain_path = platform.get_package_dir( + "toolchain-xtensa-esp-elf" + if "arduino" not in env.subst("$PIOFRAMEWORK") + else "toolchain-xtensa-%s" % idf_variant + ) + additional_packages = [ - os.path.join( - platform.get_package_dir("toolchain-xtensa-%s" % idf_variant), - "bin", - ), + toolchain_path, os.path.join( platform.get_package_dir("toolchain-esp32ulp"), "bin", @@ -57,7 +61,7 @@ def prepare_ulp_env_vars(env): def collect_ulp_sources(): return [ - fs.to_unix_path(os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp", f)) + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp", f) for f in os.listdir(os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp")) if f.endswith((".c", ".S", ".s")) ] @@ -77,41 +81,53 @@ def get_component_includes(target_config): def generate_ulp_config(target_config): - riscv_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_RISCV", False) + def _generate_ulp_configuration_action(env, target, source): + riscv_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_RISCV", False) + + cmd = ( + os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), + "-DCMAKE_GENERATOR=Ninja", + "-DCMAKE_TOOLCHAIN_FILE=" + + os.path.join( + FRAMEWORK_DIR, + "components", + "ulp", + "cmake", + "toolchain-%sulp%s.cmake" + % ( + "" if riscv_ulp_enabled else idf_variant + "-", + "-riscv" if riscv_ulp_enabled else "", + ), + ), + "-DULP_S_SOURCES=%s" % ";".join([fs.to_unix_path(s.get_abspath()) for s in source]), + "-DULP_APP_NAME=ulp_main", + "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), + "-DCOMPONENT_INCLUDES=%s" % ";".join(get_component_includes(target_config)), + "-DIDF_TARGET=%s" % idf_variant, + "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), + "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), + "-DPYTHON=" + env.subst("$PYTHONEXE"), + "-DSDKCONFIG_CMAKE=" + os.path.join(BUILD_DIR, "config", "sdkconfig.cmake"), + "-GNinja", + "-B", + ULP_BUILD_DIR, + os.path.join(FRAMEWORK_DIR, "components", "ulp", "cmake"), + ) + + result = exec_command(cmd) + if result["returncode"] != 0: + sys.stderr.write(result["err"] + "\n") + env.Exit(1) ulp_sources = collect_ulp_sources() ulp_sources.sort() - cmd = ( - os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), - "-DCMAKE_GENERATOR=Ninja", - "-DCMAKE_TOOLCHAIN_FILE=" - + os.path.join( - FRAMEWORK_DIR, - "components", - "ulp", - "cmake", - "toolchain-%sulp%s.cmake" - % ("" if riscv_ulp_enabled else idf_variant + "-", "-riscv" if riscv_ulp_enabled else ""), - ), - '-DULP_S_SOURCES="%s"' % ";".join(ulp_sources), - "-DULP_APP_NAME=ulp_main", - "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), - '-DCOMPONENT_INCLUDES="%s"' % ";".join(get_component_includes(target_config)), - "-DIDF_TARGET=%s" % idf_variant, - "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), - "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), - "-DPYTHON=" + env.subst("$PYTHONEXE"), - "-DULP_COCPU_IS_RISCV=%s" % ("ON" if riscv_ulp_enabled else "OFF"), - "-GNinja", - "-B", - ULP_BUILD_DIR, - os.path.join(FRAMEWORK_DIR, "components", "ulp", "cmake"), - ) return ulp_env.Command( os.path.join(ULP_BUILD_DIR, "build.ninja"), ulp_sources, - ulp_env.VerboseAction(" ".join(cmd), "Generating ULP configuration"), + ulp_env.VerboseAction( + _generate_ulp_configuration_action, "Generating ULP configuration" + ), ) @@ -124,14 +140,19 @@ def compile_ulp_binary(): "build", ) - return ulp_env.Command( + # The `build.ninja` dependency is always generated with the same content + # so a cloned environment with a decider that depends on a timestamp is used + ulp_binary_env = ulp_env.Clone() + ulp_binary_env.Decider("timestamp-newer") + + return ulp_binary_env.Command( [ os.path.join(ULP_BUILD_DIR, "ulp_main.h"), os.path.join(ULP_BUILD_DIR, "ulp_main.ld"), os.path.join(ULP_BUILD_DIR, "ulp_main.bin"), ], None, - ulp_env.VerboseAction(" ".join(cmd), "Generating ULP project files $TARGETS"), + ulp_binary_env.VerboseAction(" ".join(cmd), "Generating ULP project files $TARGETS"), ) diff --git a/builder/main.py b/builder/main.py index 1f493503a..2cb21d1ab 100644 --- a/builder/main.py +++ b/builder/main.py @@ -59,12 +59,32 @@ def _get_board_memory_type(env): ) -def _get_board_f_flash(env): - frequency = env.subst("$BOARD_F_FLASH") +def _normalize_frequency(frequency): frequency = str(frequency).replace("L", "") return str(int(int(frequency) / 1000000)) + "m" +def _get_board_f_flash(env): + frequency = env.subst("$BOARD_F_FLASH") + return _normalize_frequency(frequency) + + +def _get_board_f_image(env): + board_config = env.BoardConfig() + if "build.f_image" in board_config: + return _normalize_frequency(board_config.get("build.f_image")) + + return _get_board_f_flash(env) + + +def _get_board_f_boot(env): + board_config = env.BoardConfig() + if "build.f_boot" in board_config: + return _normalize_frequency(board_config.get("build.f_boot")) + + return _get_board_f_flash(env) + + def _get_board_flash_mode(env): if ["arduino"] == env.get("PIOFRAMEWORK") and _get_board_memory_type(env) in ( "opi_opi", @@ -184,7 +204,7 @@ def _to_unix_slashes(path): def fetch_fs_size(env): fs = None for p in _parse_partitions(env): - if p["type"] == "data" and p["subtype"] in ("spiffs", "fat"): + if p["type"] == "data" and p["subtype"] in ("spiffs", "fat", "littlefs"): fs = p if not fs: sys.stderr.write( @@ -225,10 +245,12 @@ def __fetch_fs_size(target, source, env): env.Replace( __get_board_boot_mode=_get_board_boot_mode, __get_board_f_flash=_get_board_f_flash, + __get_board_f_image=_get_board_f_image, + __get_board_f_boot=_get_board_f_boot, __get_board_flash_mode=_get_board_flash_mode, __get_board_memory_type=_get_board_memory_type, - AR="%s-elf-ar" % toolchain_arch, + AR="%s-elf-gcc-ar" % toolchain_arch, AS="%s-elf-as" % toolchain_arch, CC="%s-elf-gcc" % toolchain_arch, CXX="%s-elf-g++" % toolchain_arch, @@ -244,7 +266,7 @@ def __fetch_fs_size(target, source, env): ) if env.get("PIOFRAMEWORK") == ["espidf"] else "%s-elf-gdb" % toolchain_arch, OBJCOPY=join( platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), - RANLIB="%s-elf-ranlib" % toolchain_arch, + RANLIB="%s-elf-gcc-ranlib" % toolchain_arch, SIZETOOL="%s-elf-size" % toolchain_arch, ARFLAGS=["rc"], @@ -296,7 +318,7 @@ def __fetch_fs_size(target, source, env): '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_freq", "${__get_board_f_image(__env__)}", "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" ]), "Building $TARGET"), @@ -432,7 +454,7 @@ def __fetch_fs_size(target, source, env): "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_freq", "${__get_board_f_image(__env__)}", "--flash_size", board.get("upload.flash_size", "detect") ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE' @@ -450,7 +472,7 @@ def __fetch_fs_size(target, source, env): "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_freq", "${__get_board_f_image(__env__)}", "--flash_size", board.get("upload.flash_size", "detect"), "$FS_START" ], @@ -463,32 +485,6 @@ def __fetch_fs_size(target, source, env): ] -elif upload_protocol == "mbctool": - env.Replace( - UPLOADER=join( - platform.get_package_dir("tool-mbctool") or "", "bin", "mbctool"), - UPLOADERFLAGS=[ - "--device", "esp", - "--speed", "$UPLOAD_SPEED", - "--port", '"$UPLOAD_PORT"', - "--upload", - "0x1000", join( - platform.get_package_dir("framework-arduino-mbcwb"), - "tools", "sdk", "bin", "bootloader_qio_80m.bin"), - "0x8000", join("$BUILD_DIR", "partitions.bin"), - "0xe000", join( - platform.get_package_dir("framework-arduino-mbcwb"), - "tools", "partitions", "boot_app0.bin"), - "0x10000", join("$BUILD_DIR", "${PROGNAME}.bin"), - ], - UPLOADCMD='"$UPLOADER" $UPLOADERFLAGS' - ) - upload_actions = [ - env.VerboseAction(env.AutodetectUploadPort, - "Looking for upload port..."), - env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") - ] - elif upload_protocol == "dfu": hwids = board.get("build.hwids", [["0x2341", "0x0070"]]) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 85e0fab00..fa67ab603 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -44,3 +44,8 @@ monitor_speed = 115200 platform = espressif32 framework = arduino board = arduino_nano_esp32 + +[env:adafruit_qtpy_esp32s3_n4r2] +platform = espressif32 +board = adafruit_qtpy_esp32s3_n4r2 +framework = arduino diff --git a/examples/arduino-briki-internal-libs/.gitignore b/examples/arduino-briki-internal-libs/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/arduino-briki-internal-libs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/arduino-briki-internal-libs/.travis.yml b/examples/arduino-briki-internal-libs/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/arduino-briki-internal-libs/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/arduino-briki-internal-libs/README.md b/examples/arduino-briki-internal-libs/README.md deleted file mode 100644 index 8dbe25a79..000000000 --- a/examples/arduino-briki-internal-libs/README.md +++ /dev/null @@ -1,27 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/arduino-briki-internal-libs - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Build specific environment -$ pio run -e briki_abc_esp32 - -# Upload firmware for the specific environment -$ pio run -e briki_abc_esp32 --target upload - -# Clean build files -$ pio run --target clean -``` \ No newline at end of file diff --git a/examples/arduino-briki-internal-libs/include/README b/examples/arduino-briki-internal-libs/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/arduino-briki-internal-libs/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/arduino-briki-internal-libs/lib/README b/examples/arduino-briki-internal-libs/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/arduino-briki-internal-libs/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/arduino-briki-internal-libs/platformio.ini b/examples/arduino-briki-internal-libs/platformio.ini deleted file mode 100644 index c4afadb19..000000000 --- a/examples/arduino-briki-internal-libs/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[env:briki_abc_esp32] -platform = espressif32 -board = briki_abc_esp32 -framework = arduino - -[env:briki_mbc-wb_esp32] -platform = espressif32 -board = briki_mbc-wb_esp32 -framework = arduino diff --git a/examples/arduino-briki-internal-libs/src/WiFiTelnetToSerial.ino b/examples/arduino-briki-internal-libs/src/WiFiTelnetToSerial.ino deleted file mode 100644 index 63bdf6c13..000000000 --- a/examples/arduino-briki-internal-libs/src/WiFiTelnetToSerial.ino +++ /dev/null @@ -1,129 +0,0 @@ -/* - WiFiTelnetToSerial - Example Transparent UART to Telnet Server for ESP32 - - Copyright (c) 2017 Hristo Gochkov. All rights reserved. - This file is part of the ESP32 WiFi library for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include -#include - -WiFiMulti wifiMulti; - -//how many clients should be able to telnet to this ESP32 -#define MAX_SRV_CLIENTS 1 -const char* ssid = "**********"; -const char* password = "**********"; - -WiFiServer server(23); -WiFiClient serverClients[MAX_SRV_CLIENTS]; - -void setup() { - Serial.begin(115200); - Serial.println("\nConnecting"); - - wifiMulti.addAP(ssid, password); - wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); - wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); - - Serial.println("Connecting Wifi "); - for (int loops = 10; loops > 0; loops--) { - if (wifiMulti.run() == WL_CONNECTED) { - Serial.println(""); - Serial.print("WiFi connected "); - Serial.print("IP address: "); - Serial.println(WiFi.localIP()); - break; - } - else { - Serial.println(loops); - delay(1000); - } - } - if (wifiMulti.run() != WL_CONNECTED) { - Serial.println("WiFi connect failed"); - delay(1000); - ESP.restart(); - } - - //start UART and the server - Serial2.begin(9600); - server.begin(); - server.setNoDelay(true); - - Serial.print("Ready! Use 'telnet "); - Serial.print(WiFi.localIP()); - Serial.println(" 23' to connect"); -} - -void loop() { - uint8_t i; - if (wifiMulti.run() == WL_CONNECTED) { - //check if there are any new clients - if (server.hasClient()){ - for(i = 0; i < MAX_SRV_CLIENTS; i++){ - //find free/disconnected spot - if (!serverClients[i] || !serverClients[i].connected()){ - if(serverClients[i]) serverClients[i].stop(); - serverClients[i] = server.available(); - if (!serverClients[i]) Serial.println("available broken"); - Serial.print("New client: "); - Serial.print(i); Serial.print(' '); - Serial.println(serverClients[i].remoteIP()); - break; - } - } - if (i >= MAX_SRV_CLIENTS) { - //no free/disconnected spot so reject - server.available().stop(); - } - } - //check clients for data - for(i = 0; i < MAX_SRV_CLIENTS; i++){ - if (serverClients[i] && serverClients[i].connected()){ - if(serverClients[i].available()){ - //get data from the telnet client and push it to the UART - while(serverClients[i].available()) Serial2.write(serverClients[i].read()); - } - } - else { - if (serverClients[i]) { - serverClients[i].stop(); - } - } - } - //check UART for data - if(Serial2.available()){ - size_t len = Serial2.available(); - uint8_t sbuf[len]; - Serial2.readBytes(sbuf, len); - //push UART data to all connected telnet clients - for(i = 0; i < MAX_SRV_CLIENTS; i++){ - if (serverClients[i] && serverClients[i].connected()){ - serverClients[i].write(sbuf, len); - delay(1); - } - } - } - } - else { - Serial.println("WiFi not connected!"); - for(i = 0; i < MAX_SRV_CLIENTS; i++) { - if (serverClients[i]) serverClients[i].stop(); - } - delay(1000); - } -} diff --git a/examples/arduino-briki-internal-libs/test/README b/examples/arduino-briki-internal-libs/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/arduino-briki-internal-libs/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/espidf-aws-iot/.gitignore b/examples/espidf-aws-iot/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/espidf-aws-iot/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/espidf-aws-iot/.travis.yml b/examples/espidf-aws-iot/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-aws-iot/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-aws-iot/CMakeLists.txt b/examples/espidf-aws-iot/CMakeLists.txt deleted file mode 100644 index 61f45be84..000000000 --- a/examples/espidf-aws-iot/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(subscribe_publish) diff --git a/examples/espidf-aws-iot/README.md b/examples/espidf-aws-iot/README.md deleted file mode 100644 index da21cb256..000000000 --- a/examples/espidf-aws-iot/README.md +++ /dev/null @@ -1,22 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell - -# Change directory to example -$ cd platform-espressif32/examples/espidf-aws-iot - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Clean build files -$ pio run --target clean -``` \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/.gitignore b/examples/espidf-aws-iot/components/esp-aws-iot/.gitignore deleted file mode 100644 index bf8e14f7e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.o - -# Example project files -examples/**/sdkconfig -examples/**/sdkconfig.old -examples/**/build - -# AWS IoT Examples require device-specific certs/keys -examples/*/main/certs/*.pem.* diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/.gitlab-ci.yml b/examples/espidf-aws-iot/components/esp-aws-iot/.gitlab-ci.yml deleted file mode 100644 index 5536211db..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/.gitlab-ci.yml +++ /dev/null @@ -1,42 +0,0 @@ -stages: - - build - -variables: - BATCH_BUILD: "1" - V: "0" - MAKEFLAGS: "-j5 --no-keep-going" - IDF_PATH: "$CI_PROJECT_DIR/esp-idf" - -build_demo: - stage: build - image: $CI_DOCKER_REGISTRY/esp32-ci-env - tags: - - build - script: - # add gitlab ssh key - - export PATH="$IDF_PATH/tools:$PATH" - - mkdir -p ~/.ssh - - chmod 700 ~/.ssh - - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64 - - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa - - chmod 600 ~/.ssh/id_rsa - - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config - - git --version - - git submodule update --init --recursive - - git clone --recursive --depth 1 $GITLAB_SSH_SERVER/idf/esp-idf.git - - export PATH="$IDF_PATH/tools:$PATH" - - cd esp-idf - - ./install.sh - - . export.sh - - cd .. - - cd examples/thing_shadow - - cat sdkconfig.ci >> sdkconfig.defaults - - make defconfig && make -j4 - - make clean && rm -rf build - - idf.py build - - cd ../.. - - cd examples/subscribe_publish - - cat sdkconfig.ci >> sdkconfig.defaults - - make defconfig && make -j4 - - make clean && rm -rf build - - idf.py build diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/.gitmodules b/examples/espidf-aws-iot/components/esp-aws-iot/.gitmodules deleted file mode 100644 index f75792f69..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "aws-iot-device-sdk-embedded-C"] - path = aws-iot-device-sdk-embedded-C - url = https://github.com/espressif/aws-iot-device-sdk-embedded-C.git diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/CMakeLists.txt deleted file mode 100644 index 653fd191b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -set(COMPONENT_ADD_INCLUDEDIRS "port/include aws-iot-device-sdk-embedded-C/include") -set(aws_sdk_dir aws-iot-device-sdk-embedded-C/src) -set(COMPONENT_SRCS "${aws_sdk_dir}/aws_iot_jobs_interface.c" - "${aws_sdk_dir}/aws_iot_jobs_json.c" - "${aws_sdk_dir}/aws_iot_jobs_topics.c" - "${aws_sdk_dir}/aws_iot_jobs_types.c" - "${aws_sdk_dir}/aws_iot_json_utils.c" - "${aws_sdk_dir}/aws_iot_mqtt_client.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_common_internal.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_connect.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_publish.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_subscribe.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_unsubscribe.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_yield.c" - "${aws_sdk_dir}/aws_iot_shadow.c" - "${aws_sdk_dir}/aws_iot_shadow_actions.c" - "${aws_sdk_dir}/aws_iot_shadow_json.c" - "${aws_sdk_dir}/aws_iot_shadow_records.c" - "port/network_mbedtls_wrapper.c" - "port/threads_freertos.c" - "port/timer.c") - -set(COMPONENT_REQUIRES "mbedtls") -set(COMPONENT_PRIV_REQUIRES "jsmn") - -register_component() diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/Kconfig b/examples/espidf-aws-iot/components/esp-aws-iot/Kconfig deleted file mode 100644 index 0e41d9689..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/Kconfig +++ /dev/null @@ -1,146 +0,0 @@ -menu "Amazon Web Services IoT Platform" - -config AWS_IOT_MQTT_HOST - string "AWS IoT Endpoint Hostname" - default "" - help - Default endpoint host name to connect to AWS IoT MQTT/S gateway - - This is the custom endpoint hostname and is specific to an AWS - IoT account. You can find it by logging into your AWS IoT - Console and clicking the Settings button. The endpoint hostname - is shown under the "Custom Endpoint" heading on this page. - - If you need per-device hostnames for different regions or - accounts, you can override the default hostname in your app. - -config AWS_IOT_MQTT_PORT - int "AWS IoT MQTT Port" - default 8883 - range 0 65535 - help - Default port number to connect to AWS IoT MQTT/S gateway - - If you need per-device port numbers for different regions, you can - override the default port number in your app. - - -config AWS_IOT_MQTT_TX_BUF_LEN - int "MQTT TX Buffer Length" - default 512 - range 32 131072 - help - Maximum MQTT transmit buffer size. This is the maximum MQTT - message length (including protocol overhead) which can be sent. - - Sending longer messages will fail. - -config AWS_IOT_MQTT_RX_BUF_LEN - int "MQTT RX Buffer Length" - default 512 - range 32 131072 - help - Maximum MQTT receive buffer size. This is the maximum MQTT - message length (including protocol overhead) which can be - received. - - Longer messages are dropped. - - - -config AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS - int "Maximum MQTT Topic Filters" - default 5 - range 1 100 - help - Maximum number of concurrent MQTT topic filters. - - -config AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - int "Auto reconnect initial interval (ms)" - default 1000 - range 10 3600000 - help - Initial delay before making first reconnect attempt, if the AWS IoT connection fails. - Client will perform exponential backoff, starting from this value. - -config AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - int "Auto reconnect maximum interval (ms)" - default 128000 - range 10 3600000 - help - Maximum delay between reconnection attempts. If the exponentially increased delay - interval reaches this value, the client will stop automatically attempting to reconnect. - -menu "Thing Shadow" - - config AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER - bool "Override Shadow RX buffer size" - default n - help - Allows setting a different Thing Shadow RX buffer - size. This is the maximum size of a Thing Shadow - message in bytes, plus one. - - If not overridden, the default value is the MQTT RX Buffer length plus one. If overriden, do not set - higher than the default value. - - config AWS_IOT_SHADOW_MAX_SIZE_OF_RX_BUFFER - int "Maximum RX Buffer (bytes)" - depends on AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER - default 513 - range 32 65536 - help - Allows setting a different Thing Shadow RX buffer size. - This is the maximum size of a Thing Shadow message in bytes, - plus one. - - - config AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES - int "Maximum unique client ID size (bytes)" - default 80 - range 4 1000 - help - Maximum size of the Unique Client Id. - - config AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS - int "Maximum simultaneous responses" - default 10 - range 1 100 - help - At any given time we will wait for this many responses. This will correlate to the rate at which the - shadow actions are requested - - config AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES - int "Maximum simultaneous Thing Name operations" - default 10 - range 1 100 - help - We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any - given time - - config AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED - int "Maximum expected JSON tokens" - default 120 - help - These are the max tokens that is expected to be in the Shadow JSON document. Includes the metadata which - is published - - config AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME - int "Maximum topic length (not including Thing Name)" - default 60 - range 10 1000 - help - All shadow actions have to be published or subscribed to a topic which is of the format - $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing - Name - - config AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME - int "Maximum Thing Name length" - default 20 - range 4 1000 - help - Maximum length of a Thing Name. - -endmenu # Thing Shadow -endmenu # AWS IoT diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/LICENSE b/examples/espidf-aws-iot/components/esp-aws-iot/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/README.md deleted file mode 100644 index 57b5b1619..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# ESP-AWS-IoT - -This framework enables AWS IoT cloud connectivity with ESP32 based platforms using [AWS IoT Device Embedded SDK](https://github.com/aws/aws-iot-device-sdk-embedded-C). - -## Getting Started - -- Please clone this repository using, - ``` - git clone --recursive https://github.com/espressif/esp-aws-iot - ``` -- Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html for setting ESP-IDF - - ESP-IDF can be downloaded from https://github.com/espressif/esp-idf/ - - ESP-IDF v3.1 and above is recommended version -- Please refer to [example README](examples/README.md) for more information on setting up examples diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.gitignore b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.gitignore deleted file mode 100644 index 32361d47b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -# Ignore executables -*.o -IotSdkC_tests -samples/linux/jobs_sample/jobs_sample -samples/linux/shadow_sample/shadow_sample -samples/linux/shadow_sample_console_echo/shadow_console_echo -samples/linux/subscribe_publish_library_sample/libAwsIotSdk.a -samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample -samples/linux/subscribe_publish_sample/subscribe_publish_sample -tests/integration/integration_tests_mbedtls -tests/integration/integration_tests_mbedtls_mt - -# Ignore test artifacts -objs/* -testLibs/* - -# Ignore CppUTest and mbed TLS -external_libs/CppUTest/* -external_libs/mbedTLS/* - -# Ignore credentials -certs/* diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.travis.yml b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.travis.yml deleted file mode 100644 index 509ccf78e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.travis.yml +++ /dev/null @@ -1,44 +0,0 @@ -language: c - -install: - # Remove placeholders. - - rm external_libs/CppUTest/* - - rm external_libs/mbedTLS/* - - # Get mbedtls. - - wget -qO- https://github.com/ARMmbed/mbedtls/archive/mbedtls-2.16.5.tar.gz | tar xvz -C external_libs/mbedTLS --strip-components=1 - - # Get CppUTest. - - wget -qO- https://github.com/cpputest/cpputest/archive/v3.6.tar.gz | tar xvz -C external_libs/CppUTest --strip-components=1 - -script: - # Verify that the samples build. - - cd samples/linux/jobs_sample - - make -j2 - - cd ../shadow_sample - - make -j2 - - cd ../shadow_sample_console_echo - - make -j2 - - cd ../subscribe_publish_library_sample - - make -j2 - - cd ../subscribe_publish_sample - - make -j2 - - # Build and run unit tests. - - cd ../../../ - - make build-cpputest -j2 - - make all_no_tests -j2 - - ./IotSdkC_tests -v - - # Set up integration tests if not a pull request. - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cd tests/integration; fi - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then sed -i 's/^.*#define AWS_IOT_MQTT_HOST.*$/#define AWS_IOT_MQTT_HOST "'"$AWS_IOT_ENDPOINT"'"/' include/aws_iot_config.h; fi - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then make app -j2; fi - - # Import credentials for integration tests. - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O ../../certs/rootCA.crt; fi - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then echo -e $AWS_IOT_CLIENT_CERT > ../../certs/cert.pem; fi - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then echo -e $AWS_IOT_PRIVATE_KEY > ../../certs/privkey.pem; fi - - # Run integration tests. - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then ./integration_tests_mbedtls; fi diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md deleted file mode 100644 index 497128753..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md +++ /dev/null @@ -1,233 +0,0 @@ -# Change Log - -## [3.0.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v3.0.1) (May 10, 2018) - -Bugfixes: - - - [#167](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/167), [#168](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/168) Fixed issues reported by Coverity Scan. - - [#177](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/177) Fixes a memory corruption bug and handling of timeouts. - -Other: - - - Add .travis.yml for Travis CI. - - Removed C++ sample. - - Removed includes of `inttypes.h`, which doesn't exist on some systems. - - [#175](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/175) Added comments on static allocation of MQTT topics. - -## [3.0.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v3.0.0) (Apr 17, 2018) - -Bugfixes: - - - [#152](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/152) Fixes potential buffer overflows in `parseStringValue` by requiring a size parameter in `jsonStruct_t`. - - [#155](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/155) Fixes other memory corruption bugs; also improves stability. - -The two bug fixes above are not backwards compatible with v2.3.0. Please see [README.md](README.md#migrating-from-2x-to-3x) for details on migrating to v3.0.0. - -## [2.3.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.3.0) (Mar 21, 2018) - -New Features: - - - Add [AWS IoT Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) support. - - Use AWS IoT Core support for MQTT over port 443. MQTT connection now defaults to port 443. - -Pull requests: - - - [#124](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/124) - Thing Shadow: Fix potential shadow buffer overflow - - [#135](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/135) - mbedtls_wrap: Fix unintialized variable usage - - Fix bugs in long-running integration tests. - -## [2.2.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.2.1) (Dec 26, 2017) - -Bugfixes: - - - [#115](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/115) - Issue with new client metrics - -Pull requests: - - - [#112](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/112) - Initialize msqParams.isRetained to 0 in publishToShadowAction() - - [#118](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/118) - mqttInitParams.mqttPacketTimeout_ms initialized - -## [2.2.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.2.0) (Nov 22, 2017) - -New Features: - - - Added SDK metrics string into connect packet - -Bugfixes: - - - [#49](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/49) - Add support for SHADOW_JSON_STRING as supported value - - [#57](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/57) - remove unistd.h - - [#58](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/58) - Fix return type of aws_iot_mqtt_internal_is_topic_matched - - [#59](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/95) - Fix extraneous assignment - - [#62](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/62) - Clearing SubscriptionList entries in shadowActionAcks after subscription failure - - [#63](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/63) - Stack overflow when IOT_DEBUG is enabled - - [#66](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/66) - Bug in send packet function - - [#69](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/69) - Fix for broken deleteActionHandler in shadow API - - [#71](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/71) - Prevent messages on /update/accepted from incrementing shadowJsonVersionNum in delta - - [#73](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/73) - wait for all messages to be received in subscribe publish sample - - [#96](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/96) - destroy TLS instance even if disconnect send fails - - Fix for aws_iot_mqtt_resubscribe not properly resubscribing to all topics - - Update MbedTLS Network layer Readme to remove specific version link - - Fix for not Passing througheError code on aws_iot_shadow_connect failure - - Allow sending of SHADOW_JSON_OBJECT to the shadow - - Ignore delta token callback for metadata - - Fix infinite publish exiting early in subscribe publish sample - -Improvements: - - - Updated jsmn to latest commit - - Change default keepalive interval to 600 seconds - -Pull requests: - - - [#29](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/29) - three small fixes - - [#59](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/59) - Fixed MQTT header constructing and parsing - - [#88](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/88) - Fix username and password are confused - - [#78](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/78) - Fixed compilation warnings - - [#102](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/102) - Corrected markdown headers - - [#105](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/105) - Fixed warnings when compiling - -## [2.1.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.1.1) (Sep 5, 2016) - -Bugfixes/Improvements: - - - Network layer interface improvements to address reported issues - - Incorporated GitHub pull request [#41](https://github.com/aws/aws-iot-device-sdk-embedded-c/pull/41) - - Bugfixes for issues [#36](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/36) and [#33](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/33) - -## [2.1.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.1.0) (Jun 15, 2016) - -New features: - - - Added unit tests, further details can be found in the testing readme [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/README.md/) - - Added sample to demonstrate building the SDK as library - - Added sample to demonstrate building the SDK in C++ - -Bugfixes/Improvements: - - - Increased default value of Maximum Reconnect Wait interval to 128 secs - - Increased default value of MQTT Command Timeout in Shadow Connect to 20 secs - - Shadow null/length checks - - Client Id Length not passed correctly in shadow connect - - Add extern C to headers and source files, added sample to demonstrate usage with C++ - - Delete/Accepted not being reported, callback added for delete/accepted - - Append IOT_ to all Debug macros (eg. DEBUG is now IOT_DEBUG) - - Fixed exit on error for subscribe_publish_sample - -## [2.0.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.0.0) (April 28, 2016) - -New features: - - - Refactored API to make it instance specific. This is a breaking change in the API from 1.x releases because a Client Instance parameter had to be added to all APIs - - Added Threading library porting layer wrapper - - Added support for multiple connections from one application - - Shadows and connections de-linked, connection needs to be set up separately, can be used independently of shadow - - Added integration tests for testing SDK functionality - -Bugfixes/Improvements: - - - Yield cannot be called again while waiting for application callback to return - - Fixed issue with TLS layer handles not being cleaned up properly on connection failure reported [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/16) - - Renamed timer_linux.h to timer_platform.h as requested [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/5) - - Adds support for disconnect handler to shadow. A similar pull request can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/9) - - New SDK folder structure, cleaned and simplified code structure - - Removed Paho Wrapper, Merge MQTT into SDK code, added specific error codes - - Refactored Network and Timer layer wrappers, added specific error codes - - Refactored samples and makefiles - -## [1.1.2](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.1.2) (April 22, 2016) - -Bugfixes/Improvements: - - - Signature mismatch in MQTT library file fixed - - Makefiles have a protective target on the top to prevent accidental execution - -## [1.1.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.1.1) (April 1, 2016) - -Bugfixes/Improvements: - - - Removing the Executable bit from all the files in the repository. Fixing [this](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/14) issue - - Refactoring MQTT client to remove declaration after statement warnings - - Fixing [this](https://forums.aws.amazon.com/thread.jspa?threadID=222467&tstart=0) bug - - -## [1.1.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.1.0) (February 10, 2016) -Features: - - - Auto Reconnect and Resubscribe - -Bugfixes/Improvements: - - - MQTT buffer handling incase of bigger message - - Large timeout values converted to seconds and milliseconds - - Dynamic loading of Shadow parameters. Client ID and Thing Name are not hard-coded - - MQTT Library refactored - - -## [1.0.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.0.1) (October 21, 2015) - -Bugfixes/Improvements: - - - Paho name changed to Eclipse Paho - - Renamed the Makefiles in the samples directory - - Device Shadow - Delete functionality macro fixed - - `subscribe_publish_sample` updated - -## [1.0.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.0.0) (October 8, 2015) - -Features: - - - Release to github - - SDK tarballs made available for public download - -Bugfixes/Improvements: - - Updated API documentation - -## 0.4.0 (October 5, 2015) - -Features: - - - Thing Shadow Actions - Update, Delete, Get for any Thing Name - - aws_iot_config.h file for easy configuration of parameters - - Sample app for talking with console's Interactive guide - - disconnect handler for the MQTT client library - -Bugfixes/Improvements: - - - mbedTLS read times out every 10 ms instead of hanging for ever - - mbedTLS handshake failure handled - -## 0.3.0 (September 14, 2015) - -Features: - - - Testing with mbedTLS, prepping for relase - -Bugfixes/Improvements: - - - Refactored to break out timer and network interfaces - -## 0.2.0 (September 2, 2015) - -Features: - - - Added initial Shadow implementation + example - - Added hostname verification to OpenSSL example - - Added iot_log interface - - Initial API Docs (Doxygen) - -Bugfixes/Improvements: - - - Fixed yield timeout - - Refactored APIs to pass by reference vs value - -## 0.1.0 (August 12, 2015) - -Features: - - - Initial beta release - - MQTT Publish and Subscribe - - TLS mutual auth on linux with OpenSSL - -Bugfixes/Improvements: - - N/A diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CODE_OF_CONDUCT.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CODE_OF_CONDUCT.md deleted file mode 100644 index 3b6446687..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,4 +0,0 @@ -## Code of Conduct -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). -For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact -opensource-codeofconduct@amazon.com with any additional questions or comments. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CONTRIBUTING.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CONTRIBUTING.md deleted file mode 100644 index eb63eaed2..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CONTRIBUTING.md +++ /dev/null @@ -1,61 +0,0 @@ -# Contributing Guidelines - -Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional -documentation, we greatly value feedback and contributions from our community. - -Please read through this document before submitting any issues or pull requests to ensure we have all the necessary -information to effectively respond to your bug report or contribution. - - -## Reporting Bugs/Feature Requests - -We welcome you to use the GitHub issue tracker to report bugs or suggest features. - -When filing an issue, please check [existing open](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues), or [recently closed](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already -reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: - -* A reproducible test case or series of steps -* The version of our code being used -* Any modifications you've made relevant to the bug -* Anything unusual about your environment or deployment - - -## Contributing via Pull Requests -Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: - -1. You are working against the latest source on the *master* branch. -2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. -3. You open an issue to discuss any significant work - we would hate for your time to be wasted. - -To send us a pull request, please: - -1. Fork the repository. -2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. -3. Ensure local tests pass. -4. Commit to your fork using clear commit messages. -5. Send us a pull request, answering any default questions in the pull request interface. -6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. - -GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and -[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). - - -## Finding contributions to work on -Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws/aws-iot-device-sdk-embedded-C/labels/help%20wanted) issues is a great place to start. - - -## Code of Conduct -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). -For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact -opensource-codeofconduct@amazon.com with any additional questions or comments. - - -## Security issue notifications -If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. - - -## Licensing - -See the [LICENSE](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. - -We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk deleted file mode 100644 index 9f3c3054f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk +++ /dev/null @@ -1,575 +0,0 @@ -#--------- -# -# MakefileWorker.mk -# -# Include this helper file in your makefile -# It makes -# A static library -# A test executable -# -# See this example for parameter settings -# examples/Makefile -# -#---------- -# Inputs - these variables describe what to build -# -# INCLUDE_DIRS - Directories used to search for include files. -# This generates a -I for each directory -# SRC_DIRS - Directories containing source file to built into the library -# SRC_FILES - Specific source files to build into library. Helpful when not all code -# in a directory can be built for test (hopefully a temporary situation) -# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner -# These do not go in a library. They are explicitly included in the test runner -# TEST_SRC_FILES - Specific source files to build into the unit test runner -# These do not go in a library. They are explicitly included in the test runner -# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner -# These do not go in a library. They are explicitly included in the test runner -#---------- -# You can adjust these variables to influence how to build the test target -# and where to put and name outputs -# See below to determine defaults -# COMPONENT_NAME - the name of the thing being built -# TEST_TARGET - name the test executable. By default it is -# $(COMPONENT_NAME)_tests -# Helpful if you want 1 > make files in the same directory with different -# executables as output. -# CPPUTEST_HOME - where CppUTest home dir found -# TARGET_PLATFORM - Influences how the outputs are generated by modifying the -# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the -# normal objs and lib directories. Also modifies where to search for the -# CPPUTEST_LIB to link against. -# CPPUTEST_OBJS_DIR - a directory where o and d files go -# CPPUTEST_LIB_DIR - a directory where libs go -# CPPUTEST_ENABLE_DEBUG - build for debug -# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete -# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out -# of the test harness -# CPPUTEST_USE_GCOV - Turn on coverage analysis -# Clean then build with this flag set to Y, then 'make gcov' -# CPPUTEST_MAPFILE - generate a map file -# CPPUTEST_WARNINGFLAGS - overly picky by default -# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make -# other targets. Like CSlim, which is part of fitnesse -# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user -# specification of source files and directories that aren't below -# the user's Makefile in the directory tree, like: -# SRC_DIRS += ../../lib/foo -# It defaults to N, and shouldn't be necessary except in the above case. -#---------- -# -# Other flags users can initialize to sneak in their settings -# CPPUTEST_CXXFLAGS - flags for the C++ compiler -# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor -# CPPUTEST_CFLAGS - flags for the C complier -# CPPUTEST_LDFLAGS - Linker flags -#---------- - -# Some behavior is weird on some platforms. Need to discover the platform. - -# Platforms -UNAME_OUTPUT = "$(shell uname -a)" -MACOSX_STR = Darwin -MINGW_STR = MINGW -CYGWIN_STR = CYGWIN -LINUX_STR = Linux -SUNOS_STR = SunOS -UNKNWOWN_OS_STR = Unknown - -# Compilers -CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)" -CLANG_STR = clang -SUNSTUDIO_CXX_STR = SunStudio - -UNAME_OS = $(UNKNWOWN_OS_STR) - -ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR)) - UNAME_OS = $(MINGW_STR) -endif - -ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR)) - UNAME_OS = $(CYGWIN_STR) -endif - -ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR)) - UNAME_OS = $(LINUX_STR) -endif - -ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR)) - UNAME_OS = $(MACOSX_STR) -#lion has a problem with the 'v' part of -a - UNAME_OUTPUT = "$(shell uname -pmnrs)" -endif - -ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR)) - UNAME_OS = $(SUNOS_STR) - - SUNSTUDIO_CXX_ERR_STR = CC -flags -ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR)) - CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)" - COMPILER_NAME = $(SUNSTUDIO_CXX_STR) -endif -endif - -ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR)) - COMPILER_NAME = $(CLANG_STR) -endif - -#Kludge for mingw, it does not have cc.exe, but gcc.exe will do -ifeq ($(UNAME_OS),$(MINGW_STR)) - CC := gcc -endif -# RHEL5 is always going to use GCC, CC is going for the old verison -CC := gcc -#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the -# Standard C++ library as a shared library. Unbelievable. -ifeq ($(UNAME_OS),$(MINGW_STR)) - CPPUTEST_LDFLAGS += -static -endif -ifeq ($(UNAME_OS),$(CYGWIN_STR)) - CPPUTEST_LDFLAGS += -static -endif - - -#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic -ifeq ($(UNAME_OS),$(MACOSX_STR)) -ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9) - CPPUTEST_PEDANTIC_ERRORS = N -endif -endif - -ifndef COMPONENT_NAME - COMPONENT_NAME = name_this_in_the_makefile -endif - -# Debug on by default -ifndef CPPUTEST_ENABLE_DEBUG - CPPUTEST_ENABLE_DEBUG = Y -endif - -# new and delete for memory leak detection on by default -ifndef CPPUTEST_USE_MEM_LEAK_DETECTION - CPPUTEST_USE_MEM_LEAK_DETECTION = Y -endif - -# Use the standard C library -ifndef CPPUTEST_USE_STD_C_LIB - CPPUTEST_USE_STD_C_LIB = Y -endif - -# Use the standard C++ library -ifndef CPPUTEST_USE_STD_CPP_LIB - CPPUTEST_USE_STD_CPP_LIB = Y -endif - -# Use gcov, off by default -ifndef CPPUTEST_USE_GCOV - CPPUTEST_USE_GCOV = N -endif - -ifndef CPPUTEST_PEDANTIC_ERRORS - CPPUTEST_PEDANTIC_ERRORS = Y -endif - -# Default warnings -ifndef CPPUTEST_WARNINGFLAGS - CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wswitch-default -Wswitch-enum -Wconversion -ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y) - CPPUTEST_WARNINGFLAGS += -pedantic-errors -endif -ifeq ($(UNAME_OS),$(LINUX_STR)) -# CPPUTEST_WARNINGFLAGS += -Wsign-conversion -endif - CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual - CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes -endif - -#Wonderful extra compiler warnings with clang -ifeq ($(COMPILER_NAME),$(CLANG_STR)) -# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that. -# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit) -# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor -# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled. - CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables - CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded -endif - -# Uhm. Maybe put some warning flags for SunStudio here? -ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR)) - CPPUTEST_CXX_WARNINGFLAGS = - CPPUTEST_C_WARNINGFLAGS = -endif - -# Default dir for temporary files (d, o) -ifndef CPPUTEST_OBJS_DIR -ifndef TARGET_PLATFORM - CPPUTEST_OBJS_DIR = objs -else - CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM) -endif -endif - -# Default dir for the output library -ifndef CPPUTEST_LIB_DIR -ifndef TARGET_PLATFORM - CPPUTEST_LIB_DIR = testLibs -else - CPPUTEST_LIB_DIR = testLibs/$(TARGET_PLATFORM) -endif -endif - -# No map by default -ifndef CPPUTEST_MAP_FILE - CPPUTEST_MAP_FILE = N -endif - -# No extentions is default -ifndef CPPUTEST_USE_EXTENSIONS - CPPUTEST_USE_EXTENSIONS = N -endif - -# No VPATH is default -ifndef CPPUTEST_USE_VPATH - CPPUTEST_USE_VPATH := N -endif -# Make empty, instead of 'N', for usage in $(if ) conditionals -ifneq ($(CPPUTEST_USE_VPATH), Y) - CPPUTEST_USE_VPATH := -endif - -ifndef TARGET_PLATFORM -CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_BUILD_LIB) -else -CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_BUILD_LIB)/$(TARGET_PLATFORM) -endif - -# -------------------------------------- -# derived flags in the following area -# -------------------------------------- - -# Without the C library, we'll need to disable the C++ library and ... -ifeq ($(CPPUTEST_USE_STD_C_LIB), N) - CPPUTEST_USE_STD_CPP_LIB = N - CPPUTEST_USE_MEM_LEAK_DETECTION = N - CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED - CPPUTEST_CPPFLAGS += -nostdinc -endif - -CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION - -ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) - CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED -else - ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE - CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_INCLUDE)/CppUTest/MemoryLeakDetectorNewMacros.h - endif - ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE - CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_INCLUDE)/CppUTest/MemoryLeakDetectorMallocMacros.h - endif -endif - -ifeq ($(CPPUTEST_ENABLE_DEBUG), Y) - CPPUTEST_CXXFLAGS += -g - CPPUTEST_CFLAGS += -g - CPPUTEST_LDFLAGS += -g -endif - -ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) - CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED -ifeq ($(CPPUTEST_USE_STD_C_LIB), Y) - CPPUTEST_CXXFLAGS += -nostdinc++ -endif -endif - -ifdef $(GMOCK_HOME) - GTEST_HOME = $(GMOCK_HOME)/gtest - CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include - GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a - LD_LIBRARIES += $(GMOCK_LIBRARY) - CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS - CPPUTEST_WARNINGFLAGS = - CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME) - GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a - LD_LIBRARIES += $(GTEST_LIBRARY) -endif - - -ifeq ($(CPPUTEST_USE_GCOV), Y) - CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage - CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage -endif - -CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS) -CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS) -CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE) -CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) -CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS) - -TARGET_MAP = $(COMPONENT_NAME).map.txt -ifeq ($(CPPUTEST_MAP_FILE), Y) - CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP) -endif - -# Link with CppUTest lib -CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a - -ifeq ($(CPPUTEST_USE_EXTENSIONS), Y) -CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a -endif - -ifdef CPPUTEST_STATIC_REALTIME - LD_LIBRARIES += -lrt -endif - -TARGET_LIB = \ - $(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a - -ifndef TEST_TARGET - ifndef TARGET_PLATFORM - TEST_TARGET = $(COMPONENT_NAME)_tests - else - TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests - endif -endif - -#Helper Functions -get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c) -get_dirs_from_dirspec = $(wildcard $1) -get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) -__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)))) -src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2)) -src_to_o = $(call src_to,.o,$1) -src_to_d = $(call src_to,.d,$1) -src_to_gcda = $(call src_to,.gcda,$1) -src_to_gcno = $(call src_to,.gcno,$1) -time = $(shell date +%s) -delta_t = $(eval minus, $1, $2) -debug_print_list = $(foreach word,$1,echo " $(word)";) echo; - -#Derived -STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) - -SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) -OBJ = $(call src_to_o,$(SRC)) - -STUFF_TO_CLEAN += $(OBJ) - -TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES) -TEST_OBJS = $(call src_to_o,$(TEST_SRC)) -STUFF_TO_CLEAN += $(TEST_OBJS) - - -MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) -MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) -STUFF_TO_CLEAN += $(MOCKS_OBJS) - -ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) - -# If we're using VPATH -ifeq ($(CPPUTEST_USE_VPATH), Y) -# gather all the source directories and add them - VPATH += $(sort $(dir $(ALL_SRC))) -# Add the component name to the objs dir path, to differentiate between same-name objects - CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR)) -endif - -#LCOV html generation -BUILD_OUTPUT_DIR=build_output -COVERAGE_DIR=$(BUILD_OUTPUT_DIR)/generated-coverage -LCOV_INFO_FILE=$(TEST_TARGET).info -LCOV_SUMMARY_FILE=$(TEST_TARGET)_summary.info - -#Test coverage with gcov -GCOV_OUTPUT = gcov_output.txt -GCOV_REPORT = gcov_report.txt -GCOV_ERROR = gcov_error.txt -GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) -GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) -TEST_OUTPUT = $(TEST_TARGET).txt -STUFF_TO_CLEAN += \ - $(GCOV_OUTPUT)\ - $(GCOV_REPORT)\ - $(GCOV_REPORT).html\ - $(GCOV_ERROR)\ - $(GCOV_GCDA_FILES)\ - $(GCOV_GCNO_FILES)\ - $(TEST_OUTPUT) - -#The gcda files for gcov need to be deleted before each run -#To avoid annoying messages. -GCOV_CLEAN = $(SILENCE)$(RM) -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) -RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) - -ifeq ($(CPPUTEST_USE_GCOV), Y) - - ifeq ($(COMPILER_NAME),$(CLANG_STR)) - LD_LIBRARIES += --coverage - else - LD_LIBRARIES += -lgcov - endif -endif - - -INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) -INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) -MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) -INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) - -CPPUTEST_CPPFLAGS += $(INCLUDES) - -DEP_FILES = $(call src_to_d, $(ALL_SRC)) -STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) -STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output - -# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags -CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS) -CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS) -CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS) -LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS) - -# Don't consider creating the archive a warning condition that does STDERR output -ARFLAGS := $(ARFLAGS)c - -DEP_FLAGS=-MMD -MP - -# Some macros for programs to be overridden. For some reason, these are not in Make defaults -RANLIB = ranlib - -# Targets - -ALL_TARGETS += cpputest_all -ALL_TARGETS_CLEAN += cpputest_clean -.PHONY: cpputest_all -cpputest_all: start $(TEST_TARGET) gcov - $(RUN_TEST_TARGET) - -.PHONY: start -start: $(TEST_TARGET) - $(SILENCE)START_TIME=$(call time) - -.PHONY: all_no_tests -all_no_tests: $(TEST_TARGET) - -.PHONY: flags -flags: - @echo - @echo "OS ${UNAME_OS}" - @echo "Compile C and C++ source with CPPFLAGS:" - @$(call debug_print_list,$(CPPFLAGS)) - @echo "Compile C++ source with CXXFLAGS:" - @$(call debug_print_list,$(CXXFLAGS)) - @echo "Compile C source with CFLAGS:" - @$(call debug_print_list,$(CFLAGS)) - @echo "Link with LDFLAGS:" - @$(call debug_print_list,$(LDFLAGS)) - @echo "Link with LD_LIBRARIES:" - @$(call debug_print_list,$(LD_LIBRARIES)) - @echo "Create libraries with ARFLAGS:" - @$(call debug_print_list,$(ARFLAGS)) - -TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START) -test-deps: $(TEST_DEPS) - -$(TEST_TARGET): $(TEST_DEPS) - @echo Linking $@ - $(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS) - -$(TARGET_LIB): $(OBJ) - @echo Building archive $@ - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(AR) $(ARFLAGS) $@ $^ - $(SILENCE)$(RANLIB) $@ - -test: $(TEST_TARGET) - $(RUN_TEST_TARGET) $(COMMAND_LINE_ARGUMENTS) | tee $(TEST_OUTPUT) -vtest: $(TEST_TARGET) - $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) - -$(CPPUTEST_OBJS_DIR)/%.o: %.cc - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -$(CPPUTEST_OBJS_DIR)/%.o: %.cpp - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -$(CPPUTEST_OBJS_DIR)/%.o: %.c - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -ifneq "$(MAKECMDGOALS)" "clean" --include $(DEP_FILES) -endif - -.PHONY: cpputest_clean -cpputest_clean: - @echo Making clean - $(SILENCE)$(RM) $(STUFF_TO_CLEAN) - $(SILENCE)$(RM) -rf gcov $(CPPUTEST_OBJS_DIR) - $(SILENCE)find . -name "*.gcno" | xargs $(RM) -f - $(SILENCE)find . -name "*.gcda" | xargs $(RM) -f - -#realclean gets rid of all gcov, o and d files in the directory tree -#not just the ones made by this makefile -.PHONY: realclean -realclean: clean - $(SILENCE)$(RM) -rf gcov - $(SILENCE)$(RM) -rf $(BUILD_OUTPUT_DIR) - $(SILENCE)find . -name "*.gdcno" | xargs $(RM) -f - $(SILENCE)find . -name "*.[do]" | xargs $(RM) -f - -gcov: test - $(SILENCE)mkdir -p $(BUILD_OUTPUT_DIR) -ifeq ($(CPPUTEST_USE_VPATH), Y) - $(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR) -else - $(SILENCE)for d in $(SRC_DIRS) ; do \ - FILES=`ls $$d/*.c $$d/*.cc $$d/*.cpp 2> /dev/null` ; \ - gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$FILES >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ - done - $(SILENCE)for f in $(SRC_FILES) ; do \ - gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ - done -endif - $(SILENCE)./filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) - $(SILENCE)mkdir -p gcov - $(SILENCE)mv *.gcov gcov - $(SILENCE)mv gcov_* gcov - $(SILENCE)mkdir -p $(COVERAGE_DIR) - $(SILENCE)lcov -d $(CPPUTEST_OBJS_DIR) -c -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) -q --rc lcov_branch_coverage=1 - $(SILENCE)lcov --remove $(COVERAGE_DIR)/$(LCOV_INFO_FILE) $(LCOV_EXCLUDE_PATTERN) -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) - $(SILENCE)lcov --remove $(COVERAGE_DIR)/$(LCOV_INFO_FILE) "*CppUTest*" -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) - $(SILENCE)lcov --summary ./$(COVERAGE_DIR)/$(LCOV_INFO_FILE) &> $(COVERAGE_DIR)/$(LCOV_SUMMARY_FILE) - $(SILENCE)echo ansic:line:`grep -E -o "([0-9]*\.[0-9]+|[0-9]+)" $(COVERAGE_DIR)/$(LCOV_SUMMARY_FILE) | head -1` >> $(COVERAGE_DIR)/coverage-data.txt - $(SILENCE)genhtml -o $(COVERAGE_DIR) $(COVERAGE_DIR)/$(LCOV_INFO_FILE) -q --rc lcov_branch_coverage=1 - @echo "See gcov directory for details" - -.PHONEY: format -format: - $(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR) - -.PHONEY: debug -debug: - @echo - @echo "Target Source files:" - @$(call debug_print_list,$(SRC)) - @echo "Target Object files:" - @$(call debug_print_list,$(OBJ)) - @echo "Test Source files:" - @$(call debug_print_list,$(TEST_SRC)) - @echo "Test Object files:" - @$(call debug_print_list,$(TEST_OBJS)) - @echo "Mock Source files:" - @$(call debug_print_list,$(MOCKS_SRC)) - @echo "Mock Object files:" - @$(call debug_print_list,$(MOCKS_OBJS)) - @echo "All Input Dependency files:" - @$(call debug_print_list,$(DEP_FILES)) - @echo Stuff to clean: - @$(call debug_print_list,$(STUFF_TO_CLEAN)) - @echo Includes: - @$(call debug_print_list,$(INCLUDES)) - --include $(OTHER_MAKEFILE_TO_INCLUDE) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/LICENSE.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/LICENSE.txt deleted file mode 100644 index 1b6cbea0c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/LICENSE.txt +++ /dev/null @@ -1,120 +0,0 @@ -############################################################################################################################# - - -Apache License -Version 2.0, January 2004 - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. -"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. -"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. -"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. -"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. -"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. -"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. -"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). -"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. -"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. -2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. -3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. -4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: - 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and - 2. You must cause any modified files to carry prominent notices stating that You changed the files; and - 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and - 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. -You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. -5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. -6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. -7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. -8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. -9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - - -############################################################################################################################# - - -Components are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - - -############################################################################################################################# - - -Copyright (C) 2012, iSEC Partners. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -############################################################################################################################# - - _ _ ____ _ - Project ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - -Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - -This software is licensed as described in the file COPYING, which -you should have received as part of this distribution. The terms -are also available at http://curl.haxx.se/docs/copyright.html. - -You may opt to use, copy, modify, merge, publish, distribute and/or sell -copies of the Software, and permit persons to whom the Software is -furnished to do so, under the terms of the COPYING file. - -This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -KIND, either express or implied. - - -############################################################################################################################# - - -Copyright (c) 2010 Serge A. Zaitsev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -############################################################################################################################# - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/Makefile deleted file mode 100644 index 4f37f9219..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/Makefile +++ /dev/null @@ -1,131 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -#Set this to @ to keep the makefile quiet -ifndef SILENCE - SILENCE = @ -endif - -CC = gcc -RM = rm - -DEBUG = - -#--- Inputs ----# -COMPONENT_NAME = IotSdkC - -ALL_TARGETS := build-cpputest -ALL_TARGETS_CLEAN := - -CPPUTEST_USE_EXTENSIONS = Y -CPP_PLATFORM = Gcc -CPPUTEST_CFLAGS += -std=gnu99 -CPPUTEST_LDFLAGS += -lpthread -CPPUTEST_CFLAGS += -D__USE_BSD -CPPUTEST_USE_GCOV = Y - -#IoT client directory -IOT_CLIENT_DIR = . - -APP_DIR = $(IOT_CLIENT_DIR)/tests/unit -APP_NAME = aws_iot_sdk_unit_tests -APP_SRC_FILES = $(shell find $(APP_DIR)/src -name '*.cpp') -APP_SRC_FILES += $(shell find $(APP_DIR)/src -name '*.c') -APP_INCLUDE_DIRS = -I $(APP_DIR)/include - -CPPUTEST_DIR = $(IOT_CLIENT_DIR)/external_libs/CppUTest - -# Provide paths for CppUTest to run Unit Tests otherwise build will fail -ifndef CPPUTEST_INCLUDE - CPPUTEST_INCLUDE = $(CPPUTEST_DIR)/include -endif - -ifndef CPPUTEST_BUILD_LIB - CPPUTEST_BUILD_LIB = $(CPPUTEST_DIR) -endif - -CPPUTEST_LDFLAGS += -ldl $(CPPUTEST_BUILD_LIB)/libCppUTest.a - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux - -#MbedTLS directory -TEMP_MBEDTLS_SRC_DIR = $(APP_DIR)/tls_mock -TLS_LIB_DIR = $(TEMP_MBEDTLS_SRC_DIR) -TLS_INCLUDE_DIR = -I $(TEMP_MBEDTLS_SRC_DIR) - -# Logging level control -#LOG_FLAGS += -DENABLE_IOT_DEBUG -#LOG_FLAGS += -DENABLE_IOT_TRACE -#LOG_FLAGS += -DENABLE_IOT_INFO -#LOG_FLAGS += -DENABLE_IOT_WARN -#LOG_FLAGS += -DENABLE_IOT_ERROR -COMPILER_FLAGS += $(LOG_FLAGS) - -EXTERNAL_LIBS += -L$(CPPUTEST_BUILD_LIB) - -#IoT client directory -PLATFORM_COMMON_DIR = $(PLATFORM_DIR)/common - -IOT_INCLUDE_DIRS = -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn - -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn/ -name '*.c') - -#Aggregate all include and src directories -INCLUDE_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_DIRS += $(APP_INCLUDE_DIRS) -INCLUDE_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_DIRS += $(CPPUTEST_INCLUDE) - -TEST_SRC_DIRS = $(APP_DIR)/src - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) -PRE_MAKE_CMDS = cd $(CPPUTEST_DIR) && -PRE_MAKE_CMDS += cmake CMakeLists.txt && -PRE_MAKE_CMDS += make && -PRE_MAKE_CMDS += cd - && -PRE_MAKE_CMDS += pwd && -PRE_MAKE_CMDS += cp -f $(CPPUTEST_DIR)/src/CppUTest/libCppUTest.a $(CPPUTEST_DIR)/libCppUTest.a && -PRE_MAKE_CMDS += cp -f $(CPPUTEST_DIR)/src/CppUTestExt/libCppUTestExt.a $(CPPUTEST_DIR)/libCppUTestExt.a - -# Using TLS Mock for running Unit Tests -MOCKS_SRC += $(APP_DIR)/tls_mock/aws_iot_tests_unit_mock_tls_params.c -MOCKS_SRC += $(APP_DIR)/tls_mock/aws_iot_tests_unit_mock_tls.c - -ISYSTEM_HEADERS += $(IOT_ISYSTEM_HEADERS) -CPPUTEST_CPPFLAGS += $(ISYSTEM_HEADERS) -CPPUTEST_CPPFLAGS += $(LOG_FLAGS) - -LCOV_EXCLUDE_PATTERN = "tests/unit/*" -LCOV_EXCLUDE_PATTERN += "tests/integration/*" -LCOV_EXCLUDE_PATTERN += "external_libs/*" - -#use this section for running a specific group of tests, comment this to run all -#ONLY FOR TESTING PURPOSE -#COMMAND_LINE_ARGUMENTS += -g CommonTests -#COMMAND_LINE_ARGUMENTS += -v - -build-cpputest: - $(PRE_MAKE_CMDS) - -include CppUTestMakefileWorker.mk - -.PHONY: run-unit-tests -run-unit-tests: $(ALL_TARGETS) - @echo $(ALL_TARGETS) - -.PHONY: clean -clean: - $(MAKE) -C $(CPPUTEST_DIR) clean - $(RM) -rf build_output - $(RM) -rf gcov - $(RM) -rf objs - $(RM) -rf testLibs diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/NOTICE.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/NOTICE.txt deleted file mode 100644 index c3f856f11..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/NOTICE.txt +++ /dev/null @@ -1,16 +0,0 @@ -AWS C SDK for Internet of Things Service -Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - -This product includes software developed by -Amazon Inc (http://www.amazon.com/). - -********************** -THIRD PARTY COMPONENTS -********************** -This software includes third party software subject to the following licensing: -- Embedded C MQTT Client - From the Eclipse Paho Project - EPL v1.0 -- mbedTLS (external library, included in tarball or downloaded separately) - Apache 2.0 -- jsmn (JSON Parsing) - MIT -- cURL (hostname verification) - MIT - -The licenses for these third party components are included in LICENSE.txt diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/PortingGuide.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/PortingGuide.md deleted file mode 100644 index 2ca5f8d8c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/PortingGuide.md +++ /dev/null @@ -1,145 +0,0 @@ -# Porting Guide - -## Scope -The scope of this document is to provide instructions to modify the provided source files and functions in this SDK to run in a variety of embedded C–based environments (e.g. real-time OS, embedded Linux) and to be adjusted to use a specific TLS implementation as available with specific hardware platforms. - -## Contents of the SDK - -The C-code files of this SDK are delivered via the following directory structure (see comment behind folder name for an explanation of its content). - -Current SDK Directory Layout (mbedTLS) - -|--`certs` (Private key, device certificate and Root CA)
-|--`docs` (Developer guide & API documentation)
-|--`external_libs` (external libraries - jsmn, mbedTLS)
-|--`include` (Header files of the AWS IoT device SDK)
-|--`src` (Source files of the AWS IoT device SDK)
-|--`platform` (Platform specific files)
-|--`samples` (Samples including makefiles for building on mbedTLS)
-|--`tests` (Tests for verifying SDK is functioning as expected)
- -All makefiles in this SDK were configured using the documented folder structure above, so moving or renaming folders will require modifications to makefiles. - -## Explanation of folders and their content - - * `certs` : This directory is initially empty and will need to contain the private key, the client certificate and the root CA. The client certificate and private key can be downloaded from the AWS IoT console or be created using the AWS CLI commands. The root CA can be downloaded from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem). - - * `docs` : SDK API and file documentation. - - * `external_libs` : The mbedTLS and jsmn source files. The jsmn source files are always present. The mbedTLS source files are only included when downloading the tarball version of the SDK. - - * `include` : This directory contains the header files that an application using the SDK needs to include. - - * `src` : This directory contains the SDK source code including the MQTT library, device shadow code and utilities. - - * `platform` : Platform specific files for timer, TLS and threading layers. Includes a reference implementation for the linux using mbedTLS and pthread. - - * `samples` : This directory contains sample applications as well as their makefiles. The samples include a simple MQTT example which publishes and subscribes to the AWS IoT service as well as a device shadow example that shows example usage of the device shadow functionality. - - * `tests` : Contains tests for verifying SDK functionality. For further details please check the readme file included with the tests [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/tests/README.md/). - -## Integrating the SDK into your environment - -This section explains the API calls that need to be implemented in order for the Device SDK to run on your platform. The SDK interfaces follow the driver model where only prototypes are defined by the Device SDK itself while the implementation is delegated to the user of the SDK to adjust it to the platform in use. The following sections list the needed functionality for the device SDK to run successfully on any given platform. - -### Timer Functions - -A timer implementation is necessary to handle request timeouts (sending MQTT connect, subscribe, etc. commands) as well as connection maintenance (MQTT keep-alive pings). Timers need millisecond resolution and are polled for expiration so these can be implemented using a "milliseconds since startup" free-running counter if desired. In the synchronous sample provided with this SDK only one command will be "in flight" at one point in time plus the client's ping timer. - -Define the `Timer` Struct as in `timer_platform.h` - -`void init_timer(Timer *);` -init_timer - A timer structure is initialized to a clean state. - -`bool has_timer_expired(Timer *);` -has_timer_expired - a polling function to determine if the timer has expired. - -`void countdown_ms(Timer *, uint32_t);` -countdown_ms - set the timer to expire in x milliseconds and start the timer. - -`void countdown_sec(Timer *, uint32_t);` -countdown_sec - set the timer to expire in x seconds and start the timer. - -`uint32_t left_ms(Timer *);` -left_ms - query time in milliseconds left on the timer. - -`void delay(unsigned milliseconds)` -delay - sleep for the specified number of milliseconds. - - -### Network Functions - -In order for the MQTT client stack to be able to communicate via the TCP/IP network protocol stack using a mutually authenticated TLS connection, the following API calls need to be implemented for your platform. - -For additional details about API parameters refer to the [API documentation](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html). - -Define the `TLSDataParams` Struct as in `network_platform.h` -This is used for data specific to the TLS library being used. - -`IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t DestinationPort, uint32_t timeout_ms, bool ServerVerificationFlag);` -Initialize the network client / structure. - -`IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *TLSParams);` -Create a TLS TCP socket to the configure address using the credentials provided via the NewNetwork API call. This will include setting up certificate locations / arrays. - - -`IoT_Error_t iot_tls_write(Network*, unsigned char*, size_t, Timer *, size_t *);` -Write to the TLS network buffer. - -`IoT_Error_t iot_tls_read(Network*, unsigned char*, size_t, Timer *, size_t *);` -Read from the TLS network buffer. - -`IoT_Error_t iot_tls_disconnect(Network *pNetwork);` -Disconnect API - -`IoT_Error_t iot_tls_destroy(Network *pNetwork);` -Clean up the connection - -`IoT_Error_t iot_tls_is_connected(Network *pNetwork);` -Check if the TLS layer is still connected - -The TLS library generally provides the API for the underlying TCP socket. - - -### Threading Functions - -The MQTT client uses a state machine to control operations in multi-threaded situations. However it requires a mutex implementation to guarantee thread safety. This is not required in situations where thread safety is not important and it is disabled by default. The _ENABLE_THREAD_SUPPORT_ macro needs to be defined in aws_iot_config.h to enable this layer. You will also need to add the -lpthread linker flag for the compiler if you are using the provided reference implementation. - -For additional details about API parameters refer to the [API documentation](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html). - -Define the `IoT_Mutex_t` Struct as in `threads_platform.h` -This is used for data specific to the TLS library being used. - -`IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *);` -Initialize the mutex provided as argument. - -`IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *);` -Lock the mutex provided as argument - -`IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *);` -Unlock the mutex provided as argument. - -`IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *);` -Destroy the mutex provided as argument. - -The threading layer provides the implementation of mutexes used for thread-safe operations. - -## Time source for certificate validation - -As part of the TLS handshake the device (client) needs to validate the server certificate which includes validation of the certificate lifetime requiring that the device is aware of the actual time. Devices should be equipped with a real time clock or should be able to obtain the current time via NTP. Bypassing validation of the lifetime of a certificate is not recommended as it exposes the device to a security vulnerability, as it will still accept server certificates even when they have already has_timer_expired. - -## Integration into operating system -### Single-Threaded implementation - -The single threaded implementation implies that the sample application code (SDK + MQTT client) is called periodically by the firmware application running on the main thread. This is done by calling the function `aws_iot_mqtt_yield` (in the simple pub-sub example) and by calling `aws_iot_shadow_yield()` (in the device shadow example). In both cases the keep-alive time is set to 10 seconds. This means that the yield functions need to be called at a minimum frequency of once every 10 seconds. Note however that the `iot_mqtt_yield()` function takes care of reading incoming MQTT messages from the IoT service as well and hence should be called more frequently depending on the timing requirements of an application. All incoming messages can only be processed at the frequency at which `yield` is called. - -### Multi-Threaded implementation - -In the simple multi-threaded case the `yield` function can be moved to a background thread. Ensure this task runs at the frequency described above. In this case, depending on the OS mechanism, a message queue or mailbox could be used to proxy incoming MQTT messages from the callback to the worker task responsible for responding to or dispatching messages. A similar mechanism could be employed to queue publish messages from threads into a publish queue that are processed by a publishing task. Ensure the threading layer is enabled as the library is not thread safe otherwise. -There is a validation test for the multi-threaded implementation that can be found with the integration tests. You can find further details in the Readme for the integration tests [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/tests/integration/README.md/). We have run the validation test with 10 threads sending 500 messages each and verified to be working fine. It can be used as a reference testing application to validate whether your use case will work with multi-threading enabled. - -## Sample applications - -The sample apps in this SDK provide a working implementation for mbedTLS. They use a reference implementation for linux provided with the SDK. Threading layer is enabled in the subscribe publish sample. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/README.md deleted file mode 100644 index 2686ad6a9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/README.md +++ /dev/null @@ -1,270 +0,0 @@ -# AWS IoT Device SDK for Embedded C - -This tag [3.1.5](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/v3.1.5) contains the v3 version of AWS IoT Device SDK for Embedded C. No new features will be added to this tag; instead, only bug fixes will be made and minimally tested. - - -## Overview - -The AWS IoT device SDK for embedded C is a collection of C source files which can be used in embedded applications to securely connect to the [AWS IoT platform](http://docs.aws.amazon.com/iot/latest/developerguide/what-is-aws-iot.html). It includes transport clients **MQTT**, **TLS** implementations and examples for their use. It also supports AWS IoT specific features such as **Thing Shadow**. It is distributed in source form and intended to be built into customer firmware along with application code, other libraries and RTOS. For additional information about porting the Device SDK for embedded C onto additional platforms please refer to the [PortingGuide](./PortingGuide.md). - -## Features -The Device SDK simplifies access to the Pub/Sub functionality of the AWS IoT broker via MQTT and provide APIs to interact with Thing Shadows. The SDK has been tested to work with the AWS IoT platform to ensure best interoperability of a device with the AWS IoT platform. - -### MQTT Connection -The Device SDK provides functionality to create and maintain a mutually authenticated TLS connection over which it runs MQTT. This connection is used for any further publish operations and allow for subscribing to MQTT topics which will call a configurable callback function when these topics are received. - -### Thing Shadow -The Device SDK implements the specific protocol for Thing Shadows to retrieve, update and delete Thing Shadows adhering to the protocol that is implemented to ensure correct versioning and support for client tokens. It abstracts the necessary MQTT topic subscriptions by automatically subscribing to and unsubscribing from the reserved topics as needed for each API call. Inbound state change requests are automatically signalled via a configurable callback. - -### Jobs -The Device SDK implements features to facilitate use of the AWS Jobs service. The Jobs service can be used for device management tasks such as updating program files, rotating device certificates, or running other maintenance tasks such are restoring device settings or restarting devices. - -## Design Goals of this SDK -The embedded C SDK was specifically designed for resource constrained devices (running on micro-controllers and RTOS). - -Primary aspects are: - * Flexibility in picking and choosing functionality (reduce memory footprint) - * Static memory only (no malloc’s) - * Configurable resource usage(JSON tokens, MQTT subscription handlers, etc…) - * Can be ported to a different RTOS, uses wrappers for OS specific functions - -For more information on the Architecture of the SDK refer [here](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html) - -## Collection of Metrics -Beginning with Release v2.2.0 of the SDK, AWS collects usage metrics indicating which language and version of the SDK is being used. This allows us to prioritize our resources towards addressing issues faster in SDKs that see the most and is an important data point. However, we do understand that not all customers would want to report this data by default. In that case, the sending of usage metrics can be easily disabled by the user by setting the `DISABLE_METRICS` flag to true in the -`aws_iot_config.h` for each application. - -## How to get started ? -Ensure you understand the AWS IoT platform and create the necessary certificates and policies. For more information on the AWS IoT platform please visit the [AWS IoT developer guide](http://docs.aws.amazon.com/iot/latest/developerguide/iot-security-identity.html). - -In order to quickly get started with the AWS IoT platform, we have ported the SDK for POSIX type Operating Systems like Ubuntu, OS X and RHEL. The SDK is configured for the mbedTLS library and can be built out of the box with *GCC* using *make utility*. You'll need to download mbedTLS from the official ARMmbed repository. We recommend that you pick the latest version of 2.16 LTS release in order to have up-to-date security fixes. - -## Installation -This section explains the individual steps to retrieve the necessary files and be able to build your first application using the AWS IoT device SDK for embedded C. - -Steps: - - * Create a directory to hold your application e.g. (/home/*user*/aws_iot/my_app) - * Change directory to this new directory - * Download the SDK to device and place in the newly created directory - * Expand the tarball (tar -xf ). This will create the below directories: - * `certs` - TLS certificates directory - * `docs` - SDK API and file documentation. This folder is not present on GitHub. You can access the documentation [here](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html) - * `external_libs` - The mbedTLS and jsmn source files - * `include` - The AWS IoT SDK header files - * `platform` - Platform specific files for timer, TLS and threading layers - * `samples` - The sample applications - * `src` - The AWS IoT SDK source files - * `tests` - Contains tests for verifying that the SDK is functioning as expected. More information can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/README.md/) - * View further information on how to use the SDK in the README file for samples that can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/samples/README.md/) - -Also, for a guided example on getting started with the Thing Shadow, visit the AWS IoT Console's [Interactive Guide](https://console.aws.amazon.com/iot). - -## Porting to different platforms -As Embedded devices run on different real-time operating systems and TCP/IP stacks, it is one of the important design goals for the Device SDK to keep it portable. Please refer to the [porting guide](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/PortingGuide.md/) to get more information on how to make this SDK run on your devices (i.e. microcontrollers). - -## Migrating from 1.x to 2.x -The 2.x branch makes several changes to the SDK. This section provides information on what changes will be required in the client application for migrating from v1.x to 2.x. - - * The first change is in the folder structure. Client applications using the SDK now need to keep only the certs, external_libs, include, src and platform folder in their application. The folder descriptions can be found above - * All the SDK headers are in the `include` folder. These need to be added to the makefile as include directories - * The source files are in the `src` folder. These need to be added to the makefile as one of the source directories - * Similar to 1.x, the platform folder contains the platform specific headers and source files. These need to be added to the makefile as well - * The `platform/threading` folder only needs to be added if multi-threading is required, and the `_ENABLE_THREAD_SUPPORT_` macro is defined in config - * The list below provides a mapping for migrating from the major APIs used in 1.x to the new APIs: - - | Description | 1.x | 2.x | - | :---------- | :-- | :-- | - | Initializing the client | ```void aws_iot_mqtt_init(MQTTClient_t *pClient);``` | ```IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *pInitParams);``` | - | Connect | ```IoT_Error_t aws_iot_mqtt_connect(MQTTConnectParams *pParams);``` | ```IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams);``` | - | Subscribe | ```IoT_Error_t aws_iot_mqtt_subscribe(MQTTSubscribeParams *pParams);``` | ```IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData);``` | - | Unsubscribe | ```IoT_Error_t aws_iot_mqtt_unsubscribe(char *pTopic);``` | ```IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen);``` | - | Yield | ```IoT_Error_t aws_iot_mqtt_yield(int timeout);``` | ```IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms);``` | - | Publish | ```IoT_Error_t aws_iot_mqtt_publish(MQTTPublishParams *pParams);``` | ```IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, IoT_Publish_Message_Params *pParams);``` | - | Disconnect | ```IoT_Error_t aws_iot_mqtt_disconnect(void);``` | ```IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient);``` | - -You can find more information on how to use the new APIs in the README file for samples that can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/samples/README.md/) - -## Migrating from 2.x to 3.x -AWS IoT Device SDK for Embedded C v3.0.0 fixes two bugs (see #152 and #155) that create a potential buffer overflows. This version is not backward compatible with previous versions, so users will need to recompile their applications with the new version. - -Users of AWS IoT Device Shadows or Json utility functions such as `extractClientToken`, `emptyJsonWithClientToken`, `isJsonValidAndParse` and `isReceivedJsonValid` are encouraged to upgrade to version v3.0.0. For users who cannot upgrade, review all parts of your solution where user input can be sent to the device, and ensure sufficient authorization of these operations is enforced. - -Details of the required changes to public functions and data structures are shown below: - -### Changes in the `jsonStruct` data structure: -The member `dataLength` has been added to struct `jsonStruct`, which is declared in [include/aws_iot_shadow_json_data.h](include/aws_iot_shadow_json_data.h#L60). - -```c -struct jsonStruct { - const char * pKey; - void * pData; - size_t dataLength; - JsonPrimitiveType type; - JsonStructCallback_t cb; -}; -``` - -The size of the buffer `pData` must now be specified by `dataLength`. **Failure to do so may result in undefined behavior**. Below are examples of the code changes required to use the new jsonStruct. - -With a primitive data type, such as `int32_t`: - -```c -… -jsonStruct_t exampleJsonStruct; -int32_t value = 0L; - -/* Set the members of exampleJsonStruct. */ -exampleJsonStruct.pKey = “exampleKey”; -exampleJsonStruct.pData = &value; -exampleJsonStruct.type = SHADOW_JSON_INT32; -exampleJsonStruct.cb = exampleCallback; - -/* Register a delta callback using example JsonStruct. */ -aws_iot_shadow_register_delta(&mqttClient, &exampleJsonStruct); -… -``` - -Version 3.0.0 will require the following code: - -```c -… -jsonStruct_t exampleJsonStruct; -int32_t value = 0L; - -/* Set the members of exampleJsonStruct. */ -exampleJsonStruct.pKey = “exampleKey”; -exampleJsonStruct.pData = &value; -exampleJsonStruct.dataLength = sizeof(int32_t); /* sizeof(value) also OK.*/ -exampleJsonStruct.type = SHADOW_JSON_INT32; -exampleJsonStruct.cb = exampleCallback; - -/* Register a delta callback using example JsonStruct. */ -aws_iot_shadow_register_delta(&mqttClient, &exampleJsonStruct); -… -``` - -With a string, versions up to v2.3.0 would require the following code: - -```c -… -jsonStruct_t exampleJsonStruct; -char stringBuffer[SIZE_OF_BUFFER]; -/* Set the members of exampleJsonStruct. */ -exampleJsonStruct.pKey = “exampleKey”; -exampleJsonStruct.pData = stringBuffer; -exampleJsonStruct.type = SHADOW_JSON_STRING; -exampleJsonStruct.cb = exampleCallback; -/* Register a delta callback using example JsonStruct. */ -aws_iot_shadow_register_delta(&mqttClient, &exampleJsonStruct); -… -``` - -Version 3.0.0 will require the following code: - -```c -… -jsonStruct_t exampleJsonStruct; -char stringBuffer[SIZE_OF_BUFFER]; -/* Set the members of exampleJsonStruct. */ -exampleJsonStruct.pKey = “exampleKey”; -exampleJsonStruct.pData = stringBuffer; -exampleJsonStruct.dataLength = SIZE_OF_BUFFER; -exampleJsonStruct.type = SHADOW_JSON_STRING; -exampleJsonStruct.cb = exampleCallback; -/* Register a delta callback using example JsonStruct. */ -aws_iot_shadow_register_delta(&mqttClient, &exampleJsonStruct); -… -``` - -### Changes in parseStringValue: -The function `parseStringValue`, declared in [include/aws_iot_json_utils.h](include/aws_iot_json_utils.h#L179) and implemented in [src/aws_iot_json_utils.c](src/aws_iot_json_utils.c#L184), now requires the inclusion of a buffer length. Its new function signature is: - -```c -IoT_Error_t parseStringValue(char *buf, size_t bufLen, const char *jsonString, jsmntok_t *token); -``` - -Below is an example of code changes required to use the new parseStringValue. - -With up to version v2.3.0: - -```c -… -char* jsonString = “…”; -jsmntok_t jsmnTokens[NUMBER_OF_JSMN_TOKENS]; -char stringBuffer[SIZE_OF_BUFFER]; -parseStringValue(stringBuffer, jsonString, jsmnTokens); -… -``` - -Version 3.0.0 will require the following code: - -```c -… -char* jsonString = “…”; -jsmntok_t jsmnTokens[NUMBER_OF_JSMN_TOKENS]; -char stringBuffer[SIZE_OF_BUFFER]; -parseStringValue(stringBuffer, SIZE_OF_BUFFER, jsonString, jsmnTokens); -… -``` - -### Changes to functions intended for internal usage: -Version 3.0.0 changes the signature of four functions intended for internal usage. The new signatures explicitly carry the information for the size of the buffer or JSON document passed as a parameter to the functions. Users of the SDK may need to change their code and recompile to ingest the changes. We report the old and new signatures below. - -#### Old signatures: - -```c -bool extractClientToken(const char *pJsonDocument, char *pExtractedClientToken); - -static void emptyJsonWithClientToken(char *pBuffer); - -bool isJsonValidAndParse(const char *pJsonDocument, void *pJsonHandler, int32_t *pTokenCount); - -bool isReceivedJsonValid(const char *pJsonDocument); -``` - -#### New signatures: - -```c -bool extractClientToken(const char *pJsonDocument, size_t jsonSize, char *pExtractedClientToken, size_t clientTokenSize); - -static void emptyJsonWithClientToken(char *pBuffer, size_t bufferSize); - -bool isJsonValidAndParse(const char *pJsonDocument, size_t jsonSize, void *pJsonHandler, int32_t *pTokenCount); - -bool isReceivedJsonValid(const char *pJsonDocument, size_t jsonSize); -``` - -## Resources -[API Documentation](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html) - -[MQTT 3.1.1 Spec](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/csprd02/mqtt-v3.1.1-csprd02.html) - -## Support -If you have any technical questions about AWS IoT Device SDK, use the [AWS IoT forum](https://forums.aws.amazon.com/forum.jspa?forumID=210). -For any other questions on AWS IoT, contact [AWS Support](https://aws.amazon.com/contact-us/). - -## Sample APIs -Connecting to the AWS IoT MQTT platform - -``` -AWS_IoT_Client client; -rc = aws_iot_mqtt_init(&client, &iotInitParams); -rc = aws_iot_mqtt_connect(&client, &iotConnectParams); -``` - - -Subscribe to a topic - -``` -AWS_IoT_Client client; -rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); -``` - - -Update Thing Shadow from a device - -``` -rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, pJsonDocumentBuffer, ShadowUpdateStatusCallback, - pCallbackContext, TIMEOUT_4SEC, persistenSubscription); -``` diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/certs/README.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/certs/README.txt deleted file mode 100644 index 8df3d0208..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/certs/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Copy certificates for running the samples and tests provided with the SDK into this directory -# Certificates can be created and downloaded from the AWS IoT Console -# The IoT Client takes the full path of the certificates as an input parameter while initializing -# This is the default folder for the certificates only for samples and tests. A different path can be specified if required. \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.png b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.png deleted file mode 100644 index d010a47e3..000000000 Binary files a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.png and /dev/null differ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.txt deleted file mode 100644 index 77218ea51..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.txt +++ /dev/null @@ -1,32 +0,0 @@ -/** -@page architecture SDK Architecture and Design -@brief This page documents the architecture and design goals of this SDK. - -The Embedded C SDK has a layered architecture. It is currently based on the MQTT protocol, but may support protocols like HTTP in the future. - -This SDK is primarily targeted for resource-constrained devices. - -@section architecture_considerations Considerations during design -- Low memory footprint (around 6k of code size without TLS library for the MQTT layer) -- Flexibility in picking and choosing functionality -- Static memory only (no malloc) -- Configurable resource usage (JSON tokens, MQTT subscription handlers, etc.) -- Portability across RTOSes - -@section architecture_diagram Layered architecture -@brief There are primarily 3 layers in the SDK as shown in the diagram below. - -@image html architecture.png - -@subsection architecture_tls TLS layer - -This SDK uses TLS sockets to talk to the server. We provide wrappers around mbed TLS (ARM) that allow the libraries to connect with AWS IoT Platform. - -@subsection architecture_mqtt AWS IoT MQTT client - -The MQTT library included in this SDK is a modification of the [Paho C MQTT client](https://www.eclipse.org/paho/clients/c/). MQTT is a standardized publish subscribe protocol popular on embedded devices. AWS IoT supports the MQTT protocol for communication with devices. This MQTT library can be used standalone or with other AWS IoT services such as Thing Shadows or Jobs. - -@subsection architecture_shadow Thing Shadow - -This SDK provides a client implementation for [AWS IoT Thing Shadows](https://docs.aws.amazon.com/iot/latest/developerguide/iot-device-shadows.html). A device's Shadow is a JSON document that is used to store and retrieve its current state information in the cloud regardless of whether it is connected to the Internet. -*/ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/common b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/common deleted file mode 100644 index 67181c419..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/common +++ /dev/null @@ -1,95 +0,0 @@ -# SDK version. -PROJECT_NUMBER = "3" - -# Doxygen layout file for libraries. -LAYOUT_FILE = doc/config/layout_library.xml - -# Documentation output directory. -OUTPUT_DIRECTORY = doc/output/ - -# Don't generate LaTeX documentation -GENERATE_LATEX = NO - -# Don't rearrange members in the input files. -SORT_MEMBER_DOCS = NO - -# Silence output (warnings only). -QUIET = YES - -# Configure Doxygen for C. -OPTIMIZE_OUTPUT_FOR_C = YES -TYPEDEF_HIDES_STRUCT = YES - -# Disable the tab bar and use treeview instead. -DISABLE_INDEX = YES -GENERATE_TREEVIEW = YES - -# All files should have unique names, so showing the full path is unnecessary. -FULL_PATH_NAMES = NO - -# Disable the default Doxygen diagrams. -HAVE_DOT = NO - -# Disable the default Doxygen search engine (for now). -SEARCHENGINE = NO - -# Use custom header file, footer file, and stylesheet. -HTML_HEADER = doc/config/html/header.html -HTML_FOOTER = doc/config/html/footer.html -HTML_EXTRA_STYLESHEET = doc/config/html/style.css - -# Don't show external pages or groups. -EXTERNAL_GROUPS = NO -EXTERNAL_PAGES = NO - -# Preprocessor defines. -PREDEFINED = _ENABLE_THREAD_SUPPORT_ - -# Alias for starting a dependencies section. -ALIASES += dependencies{2}="@section \1_dependencies Dependencies^^@brief Dependencies of the \2.^^^^" - -# Alias for starting a configuration settings page. -ALIASES += describeconfig="Configuration settings are C pre-processor constants. They can be set with a @c #`define` in the config file (`iot_config.h`) or by using a compiler option such as `-D` in gcc. If a configuration setting is not defined, the library will use a \"sensible\" default value (unless otherwise noted). Because they are compile-time constants, a library must be rebuilt if a configuration setting is changed." -ALIASES += configpage{2}="@page \1_config Configuration^^@brief Configuration settings of the \2.^^^^@describeconfig^^@par configpagemarker" -ALIASES += configpage{4}="@page \1_config \3 Configuration^^@brief Configuration settings of the \2.^^^^@describeconfig^^^^The settings on this page only affect the [\2](@ref \1). In addition to the settings on this page, them \2 will also be affected by [settings that affect all \4](@ref global_\4_config).^^@par configpagemarker" -ALIASES += globalconfigpage{3}="@page global_\1_config Global \2 Configuration^^^^@describeconfig^^@brief Configuration settings that affect all \3.^^@par configpagemarker" - -# Aliases for "Possible values", "Recommended values", and "Default values" -# used in configuration setting pages. -ALIASES += configpossible="Possible values: " -ALIASES += configrecommended="Recommended values: " -ALIASES += configdefault="Default value (if undefined): " - -# Alias for starting a constants page. -ALIASES += constantspage{2}="@page \1_constants Constants^^@brief Defined constants of the \2.^^^^Libraries may @c #`define` constants in their headers with special meanings. This page describes the meanings and uses of any constants defined by the \2. Related constants are shown in a single section on this page.^^" - -# Alias for starting a functions page. -ALIASES += functionspage{2}="@page \1_functions Functions^^@brief Functions of the \2.^^^^The \2 consists of the following functions." -ALIASES += functionspage{3}="@page \1_functions \3^^@brief Functions of the \2.^^^^The \2 consists of the following functions." - -# Alias for listing a single function on a functions page. -ALIASES += functionname{1}="@subpage \1
^^ @copybrief \1^^" - -# Alias for creating a page for a single function. -ALIASES += functionpage{3}="@page \2_function_\3 \1^^^^@snippet this declare_\2_\3^^@copydoc \1" - -# Alias for starting a handles group. -ALIASES += handles{2}="@defgroup \1_datatypes_handles Handles^^@brief Opaque handles of the \2." - -# Alias for starting an enum group. -ALIASES += enums{2}="@defgroup \1_datatypes_enums Enumerated types^^@brief Enumerated types of the \2." - -# Alias for starting a function pointers group. -ALIASES += functionpointers{2}="@defgroup \1_datatypes_functionpointers Function pointers types^^@brief Function pointers types of the \2." - -# Alias for starting a structs group. -ALIASES += structs{2}="@defgroup \1_datatypes_structs Structured types^^@brief Structured types of the \2." - -# Alias for starting a parameter structures group. -ALIASES += paramstructs{2}="@defgroup \1_datatypes_paramstructs Parameter structures^^@brief Structures passed as parameters to [\2 functions](@ref \1_functions)^^^^These structures are passed as parameters to library functions. Documentation for these structures will state the functions associated with each parameter structure and the purpose of each member." - -# Alias for "Parameter for". -ALIASES += paramfor="Parameter for: " - -# Alias for parameter structure initializers. -ALIASES += initializer{2}="All instances of #\1 should be initialized with #\2.^^" diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/footer.html b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/footer.html deleted file mode 100644 index 18c84eb78..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/footer.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/header.html b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/header.html deleted file mode 100644 index a60bb68d3..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/header.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - $projectname: $title - - - - - $title - - - - - - $search - $mathjax - - $extrastylesheet - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - -
-
- AWS IoT Device SDK C: - $projectname -
- -
- $projectbrief -
- -
-
- $projectbrief -
-
- $searchbox -
- Return to main page ↑ -
-
- -$treeview - - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/style.css b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/style.css deleted file mode 100644 index 433d4cd4b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/style.css +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Stylesheet for Doxygen HTML output. - * - * This file defines styles for custom elements in the header/footer and - * overrides some of the default Doxygen styles. - * - * Styles in this file do not affect the treeview sidebar. - */ - -/* Set the margins to place a small amount of whitespace on the left and right - * side of the page. */ -div.contents { - margin-left:4em; - margin-right:4em; -} - -/* Justify text in paragraphs. */ -p { - text-align: justify; -} - -/* Style of section headings. */ -h1 { - border-bottom: 1px solid #879ECB; - color: #354C7B; - font-size: 160%; - font-weight: normal; - padding-bottom: 4px; - padding-top: 8px; -} - -/* Style of subsection headings. */ -h2:not(.memtitle):not(.groupheader) { - font-size: 125%; - margin-bottom: 0px; - margin-top: 16px; - padding: 0px; -} - -/* Style of paragraphs immediately after subsection headings. */ -h2 + p { - margin: 0px; - padding: 0px; -} - -/* Style of subsubsection headings. */ -h3 { - font-size: 100%; - margin-bottom: 0px; -} - -/* Style of paragraphs immediately after subsubsection headings. */ -h3 + p { - margin-top: 0px; -} - -/* Style of the prefix "AWS IoT Device SDK C" that appears in the header. */ -#csdkprefix { - color: #757575; -} - -/* Style of the "Return to main page" link that appears in the header. */ -#returntomain { - padding: 0.5em; -} - -/* Style of the dividers on Configuration Settings pages. */ -div.configpagedivider { - margin-left: 0px !important; - margin-right: 0px !important; - margin-top: 20px !important; -} - -/* Style of configuration setting names. */ -dl.section.user ~ h1 { - border-bottom: none; - color: #000000; - font-family: monospace, fixed; - font-size: 16px; - margin-bottom: 0px; - margin-left: 2em; - margin-top: 1.5em; -} - -/* Style of paragraphs on a configuration settings page. */ -dl.section.user ~ * { - margin-bottom: 10px; - margin-left: 4em; - margin-right: 4em; - margin-top: 0px; -} - -/* Hide the configuration setting marker. */ -dl.section.user { - display: none; -} - -/* Overrides for code fragments and lines. */ -div.fragment { - background: #ffffff; - border: none; - padding: 5px; -} - -div.line { - color: #3a3a3a; -} - -/* Overrides for code syntax highlighting colors. */ -span.comment { - color: #008000; -} - -span.keyword, span.keywordtype, span.keywordflow { - color: #0000ff; -} - -span.preprocessor { - color: #50015a; -} - -span.stringliteral, span.charliteral { - color: #800c0c; -} - -a.code, a.code:visited, a.line, a.line:visited { - color: #496194; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_library.xml b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_library.xml deleted file mode 100644 index 7aebbfee9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_library.xml +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_main.xml b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_main.xml deleted file mode 100644 index 7d9fc5e16..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_main.xml +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/main b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/main deleted file mode 100644 index 8ef18d1ef..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/main +++ /dev/null @@ -1,30 +0,0 @@ -# Include common configuration options. -@INCLUDE_PATH = doc/config -@INCLUDE = common - -# Basic project information. -PROJECT_NAME = "Main" - -# Library documentation output directory. -HTML_OUTPUT = main - -# Generate Doxygen tag file for this library. -GENERATE_TAGFILE = doc/tag/main.tag - -# Files to show on the main page. -INPUT = README.md \ - CHANGELOG.md \ - PortingGuide.md \ - doc/architecture.txt - -# Path to architecture image. -IMAGE_PATH += doc/ - -# Use repository README as main page. -USE_MDFILE_AS_MAINPAGE = README.md - -# Don't automatically link to library symbols. -AUTOLINK_SUPPORT = NO - -# Use the Main page layout file -LAYOUT_FILE = doc/config/layout_main.xml diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/mqtt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/mqtt deleted file mode 100644 index 38da6f2f0..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/mqtt +++ /dev/null @@ -1,21 +0,0 @@ -# Include common configuration options. -@INCLUDE_PATH = doc/config -@INCLUDE = common - -# Basic project information. -PROJECT_NAME = "MQTT" -PROJECT_BRIEF = "MQTT v3.1.1 client library" - -# Library documentation output directory. -HTML_OUTPUT = mqtt - -# Generate Doxygen tag file for this library. -GENERATE_TAGFILE = doc/tag/mqtt.tag - -# Directories containing library source code. -INPUT = doc/lib \ - include/ \ - src/ - -# Library file names. -FILE_PATTERNS = *mqtt*.c *mqtt*.h *mqtt*.txt diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/lib/mqtt.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/lib/mqtt.txt deleted file mode 100644 index 03a77d30f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/lib/mqtt.txt +++ /dev/null @@ -1,61 +0,0 @@ -/** -@mainpage -@anchor mqtt -@brief MQTT v3.1.1 client library. - -MQTT is a standardized publish subscribe protocol popular on embedded devices. The MQTT library provided with this SDK implements a subset of the MQTT v3.1.1 protocol. The sample application for Linux `subscribe_publish_sample.c` is provided as a starting point for using this library. - -The interface for communication over MQTT is provided in the file `aws_iot_mqtt_interface.h`. -- MQTT client context management: @ref mqtt_function_init and @ref mqtt_function_free -- Connection management: @ref mqtt_function_connect and @ref mqtt_function_disconnect -- Publishing messages to the server: @ref mqtt_function_publish -- Managing subscriptions: @ref mqtt_function_subscribe and @ref mqtt_function_unsubscribe -- Process incoming messages, reconnections, and keep-alive: @ref mqtt_function_yield - -@note In a multithreaded environment, always ensure that calls to this library's functions are serialized, such as with a lock or a queue. This library is not thread safe. - -@note This library does not support QoS 2 or retained messages. - -@section mqtt_configuration Configuration -@brief The following configuration settings are associated with this MQTT library. -- `AWS_IOT_MQTT_TX_BUF_LEN`
-Size of buffer for outgoing messages. -- `AWS_IOT_MQTT_RX_BUF_LEN`
-Size of buffer for incoming messages. Messages longer than this will be dropped. -- `AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS`
-Number of subscriptions that may be registered simultaneously. -- `AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL`
-The initial wait time before the first reconnect attempt. See @ref mqtt_autoreconnect. -- `AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL`
-The maximum wait time between reconnect attempts. See @ref mqtt_autoreconnect. -*/ - -/** -@page mqtt_autoreconnect Auto-reconnect -@brief This page describes the auto-reconnect mechanism of the MQTT library. - -The auto-reconnect mechanism can be enabled through the following methods: -- Set #IoT_Client_Init_Params.enableAutoReconnect to `true` when calling @ref mqtt_function_init. -- Call @ref mqtt_function_autoreconnect_set_status with `newStatus` set to `true`. @ref mqtt_function_autoreconnect_set_status must only be called after @ref mqtt_function_connect. - -Once enabled, this feature will attempt to reconnect to the server if the library detects a disconnection. The reconnections are handled through @ref mqtt_function_yield. In addition to re-establishing the network connection and MQTT session, all the previous subscriptions will be re-established. This restores the client-side subscriptions for both clean and persistent MQTT sessions. - -The following events are considered disconnects: -- Fatal errors returned from the TLS layer. -- Failure to send a ping request. -- Failure to receive a timely ping response. - -On all disconnect events, the #iot_disconnect_handler for an MQTT client will be called. - -Reconnect attempts are made with an exponential backoff strategy. -- `AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL`
-The initial wait time before the first reconnect attempt. -- `AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL`
-The maximum wait time between reconnect attempts. - -If a reconnect attempt after `AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL` fails, @ref mqtt_function_yield will return `NETWORK_RECONNECT_TIMED_OUT`. There will be no more reconnect attempts. If an application still wants to re-connect, it should call @ref mqtt_function_attempt_reconnect. - -Calling @ref mqtt_function_attempt_reconnect performs a single reconnect and resubscribe attempt. It is equivalent to a manual reconnect attempt. - -@note Since reconnects are handled by @ref mqtt_function_yield and a new TLS handshake for reconnection may take a significant amount of time, calls to @ref mqtt_function_yield that handle reconnections may block for longer than usual. -*/ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt deleted file mode 100644 index 5b2e09255..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Copy source code for CppUTest into this directory -# The SDK was tested internally with CppUTest v3.6 which can be found here - https://github.com/cpputest/cpputest/releases/tag/v3.6 \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c deleted file mode 100644 index e920e8620..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2010 Serge A. Zaitsev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/** - * @file jsmn.c - * @brief Implementation of the JSMN (Jasmine) JSON parser. - * - * For more information on JSMN: - * @see http://zserge.com/jsmn.html - */ - -#include "jsmn.h" - -/** - * Allocates a fresh unused token from the token pull. - */ -static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, - jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *tok; - if (parser->toknext >= num_tokens) { - return NULL; - } - tok = &tokens[parser->toknext++]; - tok->start = tok->end = -1; - tok->size = 0; -#ifdef JSMN_PARENT_LINKS - tok->parent = -1; -#endif - return tok; -} - -/** - * Fills token type and boundaries. - */ -static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, - int start, int end) { - token->type = type; - token->start = start; - token->end = end; - token->size = 0; -} - -/** - * Fills next available token with JSON primitive. - */ -static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - int start; - - start = parser->pos; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - switch (js[parser->pos]) { -#ifndef JSMN_STRICT - /* In strict mode primitive must be followed by "," or "}" or "]" */ - case ':': -#endif - case '\t' : case '\r' : case '\n' : case ' ' : - case ',' : case ']' : case '}' : - goto found; - } - if (js[parser->pos] < 32 || js[parser->pos] >= 127) { - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } -#ifdef JSMN_STRICT - /* In strict mode primitive must be followed by a comma/object/array */ - parser->pos = start; - return JSMN_ERROR_PART; -#endif - -found: - if (tokens == NULL) { - parser->pos--; - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - parser->pos--; - return 0; -} - -/** - * Fills next token with JSON string. - */ -static int jsmn_parse_string(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - - int start = parser->pos; - - parser->pos++; - - /* Skip starting quote */ - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c = js[parser->pos]; - - /* Quote: end of string */ - if (c == '\"') { - if (tokens == NULL) { - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - return 0; - } - - /* Backslash: Quoted symbol expected */ - if (c == '\\' && parser->pos + 1 < len) { - int i; - parser->pos++; - switch (js[parser->pos]) { - /* Allowed escaped symbols */ - case '\"': case '/' : case '\\' : case 'b' : - case 'f' : case 'r' : case 'n' : case 't' : - break; - /* Allows escaped symbol \uXXXX */ - case 'u': - parser->pos++; - for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { - /* If it isn't a hex character we have an error */ - if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ - (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ - (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ - parser->pos = start; - return JSMN_ERROR_INVAL; - } - parser->pos++; - } - parser->pos--; - break; - /* Unexpected symbol */ - default: - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } - } - parser->pos = start; - return JSMN_ERROR_PART; -} - -/** - * Parse JSON string and fill tokens. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens) { - int r; - int i; - jsmntok_t *token; - int count = parser->toknext; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c; - jsmntype_t type; - - c = js[parser->pos]; - switch (c) { - case '{': case '[': - count++; - if (tokens == NULL) { - break; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) - return JSMN_ERROR_NOMEM; - if (parser->toksuper != -1) { - tokens[parser->toksuper].size++; -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - } - token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); - token->start = parser->pos; - parser->toksuper = parser->toknext - 1; - break; - case '}': case ']': - if (tokens == NULL) - break; - type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); -#ifdef JSMN_PARENT_LINKS - if (parser->toknext < 1) { - return JSMN_ERROR_INVAL; - } - token = &tokens[parser->toknext - 1]; - for (;;) { - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - token->end = parser->pos + 1; - parser->toksuper = token->parent; - break; - } - if (token->parent == -1) { - if(token->type != type || parser->toksuper == -1) { - return JSMN_ERROR_INVAL; - } - break; - } - token = &tokens[token->parent]; - } -#else - for (i = parser->toknext - 1; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - parser->toksuper = -1; - token->end = parser->pos + 1; - break; - } - } - /* Error if unmatched closing bracket */ - if (i == -1) return JSMN_ERROR_INVAL; - for (; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - parser->toksuper = i; - break; - } - } -#endif - break; - case '\"': - r = jsmn_parse_string(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - case '\t' : case '\r' : case '\n' : case ' ': - break; - case ':': - parser->toksuper = parser->toknext - 1; - break; - case ',': - if (tokens != NULL && parser->toksuper != -1 && - tokens[parser->toksuper].type != JSMN_ARRAY && - tokens[parser->toksuper].type != JSMN_OBJECT) { -#ifdef JSMN_PARENT_LINKS - parser->toksuper = tokens[parser->toksuper].parent; -#else - for (i = parser->toknext - 1; i >= 0; i--) { - if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { - if (tokens[i].start != -1 && tokens[i].end == -1) { - parser->toksuper = i; - break; - } - } - } -#endif - } - break; -#ifdef JSMN_STRICT - /* In strict mode primitives are: numbers and booleans */ - case '-': case '0': case '1' : case '2': case '3' : case '4': - case '5': case '6': case '7' : case '8': case '9': - case 't': case 'f': case 'n' : - /* And they must not be keys of the object */ - if (tokens != NULL && parser->toksuper != -1) { - jsmntok_t *t = &tokens[parser->toksuper]; - if (t->type == JSMN_OBJECT || - (t->type == JSMN_STRING && t->size != 0)) { - return JSMN_ERROR_INVAL; - } - } -#else - /* In non-strict mode every unquoted value is a primitive */ - default: -#endif - r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - -#ifdef JSMN_STRICT - /* Unexpected char in strict mode */ - default: - return JSMN_ERROR_INVAL; -#endif - } - } - - if (tokens != NULL) { - for (i = parser->toknext - 1; i >= 0; i--) { - /* Unmatched opened object or array */ - if (tokens[i].start != -1 && tokens[i].end == -1) { - return JSMN_ERROR_PART; - } - } - } - - return count; -} - -/** - * Creates a new parser based over a given buffer with an array of tokens - * available. - */ -void jsmn_init(jsmn_parser *parser) { - parser->pos = 0; - parser->toknext = 0; - parser->toksuper = -1; -} - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h deleted file mode 100644 index e0ffb1bc4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2010 Serge A. Zaitsev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/** - * @file jsmn.h - * @brief Definition of the JSMN (Jasmine) JSON parser. - * - * For more information on JSMN: - * @see http://zserge.com/jsmn.html - */ - -#ifndef __JSMN_H_ -#define __JSMN_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * JSON type identifier. Basic types are: - * o Object - * o Array - * o String - * o Other primitive: number, boolean (true/false) or null - */ -typedef enum { - JSMN_UNDEFINED = 0, - JSMN_OBJECT = 1, - JSMN_ARRAY = 2, - JSMN_STRING = 3, - JSMN_PRIMITIVE = 4 -} jsmntype_t; - -enum jsmnerr { - /* Not enough tokens were provided */ - JSMN_ERROR_NOMEM = -1, - /* Invalid character inside JSON string */ - JSMN_ERROR_INVAL = -2, - /* The string is not a full JSON packet, more bytes expected */ - JSMN_ERROR_PART = -3 -}; - -/** - * JSON token description. - * type type (object, array, string etc.) - * start start position in JSON data string - * end end position in JSON data string - */ -typedef struct { - jsmntype_t type; - int start; - int end; - int size; -#ifdef JSMN_PARENT_LINKS - int parent; -#endif -} jsmntok_t; - -/** - * JSON parser. Contains an array of token blocks available. Also stores - * the string being parsed now and current position in that string - */ -typedef struct { - unsigned int pos; /* offset in the JSON string */ - unsigned int toknext; /* next token to allocate */ - int toksuper; /* superior token node, e.g parent object or array */ -} jsmn_parser; - -/** - * Create JSON parser over an array of tokens - */ -void jsmn_init(jsmn_parser *parser); - -/** - * Run JSON parser. It parses a JSON data string into and array of tokens, each describing - * a single JSON object. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens); - -#ifdef __cplusplus -} -#endif - -#endif /* __JSMN_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt deleted file mode 100644 index b6b428d36..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Copy source code for mbedTLS into this directory -# -# You'll need to download mbedTLS from the official ARMmbed repository and -# place the files here. We recommend that you pick the latest version of 2.16 -# LTS release in order to have up-to-date security fixes. - -# Note that this SDK will not negotiate the TLS Maximum Fragment Length even if -# it is enabled in mbedTLS' configuration. Therefore, you should ensure content -# buffers used by mbedTLS are at least 16384 bytes in length to use the largest -# maximum record length supported by TLS. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/filterGcov.sh b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/filterGcov.sh deleted file mode 100755 index fee4a0327..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/filterGcov.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -INPUT_FILE=$1 -TEMP_FILE1=${INPUT_FILE}1.tmp -TEMP_FILE2=${INPUT_FILE}2.tmp -TEMP_FILE3=${INPUT_FILE}3.tmp -ERROR_FILE=$2 -OUTPUT_FILE=$3 -HTML_OUTPUT_FILE=$3.html -TEST_RESULTS=$4 - -flattenGcovOutput() { -while read line1 -do - read line2 - echo $line2 " " $line1 - read junk - read junk -done < ${INPUT_FILE} -} - -getRidOfCruft() { -sed '-e s/^Lines.*://g' \ - '-e s/^[0-9]\./ &/g' \ - '-e s/^[0-9][0-9]\./ &/g' \ - '-e s/of.*File/ /g' \ - "-e s/'//g" \ - '-e s/^.*\/usr\/.*$//g' \ - '-e s/^.*\.$//g' -} - -flattenPaths() { -sed \ - -e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \ - -e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \ - -e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \ - -e 's/\/[^/][^/]*\/\.\.\//\//g' -} - -getFileNameRootFromErrorFile() { -sed '-e s/gc..:cannot open .* file//g' ${ERROR_FILE} -} - -writeEachNoTestCoverageFile() { -while read line -do - echo " 0.00% " ${line} -done -} - -createHtmlOutput() { - echo "" - echo "" - sed "-e s/.*% /
CoverageFile
&<\/td>/" \ - "-e s/[a-zA-Z0-9_]*\.[ch][a-z]*/&<\/a><\/td><\/tr>/" - echo "
" - sed "-e s/.*/&
/g" < ${TEST_RESULTS} -} - -flattenGcovOutput | getRidOfCruft | flattenPaths > ${TEMP_FILE1} -getFileNameRootFromErrorFile | writeEachNoTestCoverageFile | flattenPaths > ${TEMP_FILE2} -cat ${TEMP_FILE1} ${TEMP_FILE2} | sort | uniq > ${OUTPUT_FILE} -createHtmlOutput < ${OUTPUT_FILE} > ${HTML_OUTPUT_FILE} -rm -f ${TEMP_FILE1} ${TEMP_FILE2} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h deleted file mode 100644 index f0ccc3963..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_error.h - * @brief Definition of error types for the SDK. - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_ERROR_H_ -#define AWS_IOT_SDK_SRC_IOT_ERROR_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Used to avoid warnings in case of unused parameters in function pointers */ -#define IOT_UNUSED(x) (void)(x) - -/*! \public - * @brief IoT Error enum - * - * Enumeration of return values from the IoT_* functions within the SDK. - * Values less than -1 are specific error codes - * Value of -1 is a generic failure response - * Value of 0 is a generic success response - * Values greater than 0 are specific non-error return codes - */ -typedef enum { - /** Returned when the Network physical layer is connected */ - NETWORK_PHYSICAL_LAYER_CONNECTED = 6, - /** Returned when the Network is manually disconnected */ - NETWORK_MANUALLY_DISCONNECTED = 5, - /** Returned when the Network is disconnected and the reconnect attempt is in progress */ - NETWORK_ATTEMPTING_RECONNECT = 4, - /** Return value of yield function to indicate auto-reconnect was successful */ - NETWORK_RECONNECTED = 3, - /** Returned when a read attempt is made on the TLS buffer and it is empty */ - MQTT_NOTHING_TO_READ = 2, - /** Returned when a connection request is successful and packet response is connection accepted */ - MQTT_CONNACK_CONNECTION_ACCEPTED = 1, - /** Success return value - no error occurred */ - SUCCESS = 0, - /** A generic error. Not enough information for a specific error code */ - FAILURE = -1, - /** A required parameter was passed as null */ - NULL_VALUE_ERROR = -2, - /** The TCP socket could not be established */ - TCP_CONNECTION_ERROR = -3, - /** The TLS handshake failed */ - SSL_CONNECTION_ERROR = -4, - /** Error associated with setting up the parameters of a Socket */ - TCP_SETUP_ERROR = -5, - /** A timeout occurred while waiting for the TLS handshake to complete. */ - NETWORK_SSL_CONNECT_TIMEOUT_ERROR = -6, - /** A Generic write error based on the platform used */ - NETWORK_SSL_WRITE_ERROR = -7, - /** SSL initialization error at the TLS layer */ - NETWORK_SSL_INIT_ERROR = -8, - /** An error occurred when loading the certificates. The certificates could not be located or are incorrectly formatted. */ - NETWORK_SSL_CERT_ERROR = -9, - /** SSL Write times out */ - NETWORK_SSL_WRITE_TIMEOUT_ERROR = -10, - /** SSL Read times out */ - NETWORK_SSL_READ_TIMEOUT_ERROR = -11, - /** A Generic error based on the platform used */ - NETWORK_SSL_READ_ERROR = -12, - /** Returned when the Network is disconnected and reconnect is either disabled or physical layer is disconnected */ - NETWORK_DISCONNECTED_ERROR = -13, - /** Returned when the Network is disconnected and the reconnect attempt has timed out */ - NETWORK_RECONNECT_TIMED_OUT_ERROR = -14, - /** Returned when the Network is already connected and a connection attempt is made */ - NETWORK_ALREADY_CONNECTED_ERROR = -15, - /** Network layer Error Codes */ - /** Network layer Random number generator seeding failed */ - NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED = -16, - /** A generic error code for Network layer errors */ - NETWORK_SSL_UNKNOWN_ERROR = -17, - /** Returned when the physical layer is disconnected */ - NETWORK_PHYSICAL_LAYER_DISCONNECTED = -18, - /** Returned when the root certificate is invalid */ - NETWORK_X509_ROOT_CRT_PARSE_ERROR = -19, - /** Returned when the device certificate is invalid */ - NETWORK_X509_DEVICE_CRT_PARSE_ERROR = -20, - /** Returned when the private key failed to parse */ - NETWORK_PK_PRIVATE_KEY_PARSE_ERROR = -21, - /** Returned when the network layer failed to open a socket */ - NETWORK_ERR_NET_SOCKET_FAILED = -22, - /** Returned when the server is unknown */ - NETWORK_ERR_NET_UNKNOWN_HOST = -23, - /** Returned when connect request failed */ - NETWORK_ERR_NET_CONNECT_FAILED = -24, - /** Returned when there is nothing to read in the TLS read buffer */ - NETWORK_SSL_NOTHING_TO_READ = -25, - /** A connection could not be established. */ - MQTT_CONNECTION_ERROR = -26, - /** A timeout occurred while waiting for the TLS handshake to complete */ - MQTT_CONNECT_TIMEOUT_ERROR = -27, - /** A timeout occurred while waiting for the TLS request complete */ - MQTT_REQUEST_TIMEOUT_ERROR = -28, - /** The current client state does not match the expected value */ - MQTT_UNEXPECTED_CLIENT_STATE_ERROR = -29, - /** The client state is not idle when request is being made */ - MQTT_CLIENT_NOT_IDLE_ERROR = -30, - /** The MQTT RX buffer received corrupt or unexpected message */ - MQTT_RX_MESSAGE_PACKET_TYPE_INVALID_ERROR = -31, - /** The MQTT RX buffer received a bigger message. The message will be dropped */ - MQTT_RX_BUFFER_TOO_SHORT_ERROR = -32, - /** The MQTT TX buffer is too short for the outgoing message. Request will fail */ - MQTT_TX_BUFFER_TOO_SHORT_ERROR = -33, - /** The client is subscribed to the maximum possible number of subscriptions */ - MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR = -34, - /** Failed to decode the remaining packet length on incoming packet */ - MQTT_DECODE_REMAINING_LENGTH_ERROR = -35, - /** Connect request failed with the server returning an unknown error */ - MQTT_CONNACK_UNKNOWN_ERROR = -36, - /** Connect request failed with the server returning an unacceptable protocol version error */ - MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = -37, - /** Connect request failed with the server returning an identifier rejected error */ - MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR = -38, - /** Connect request failed with the server returning an unavailable error */ - MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR = -39, - /** Connect request failed with the server returning a bad userdata error */ - MQTT_CONNACK_BAD_USERDATA_ERROR = -40, - /** Connect request failed with the server failing to authenticate the request */ - MQTT_CONNACK_NOT_AUTHORIZED_ERROR = -41, - /** An error occurred while parsing the JSON string. Usually malformed JSON. */ - JSON_PARSE_ERROR = -42, - /** Shadow: The response Ack table is currently full waiting for previously published updates */ - SHADOW_WAIT_FOR_PUBLISH = -43, - /** Any time an snprintf writes more than size value, this error will be returned */ - SHADOW_JSON_BUFFER_TRUNCATED = -44, - /** Any time an snprintf encounters an encoding error or not enough space in the given buffer */ - SHADOW_JSON_ERROR = -45, - /** Mutex initialization failed */ - MUTEX_INIT_ERROR = -46, - /** Mutex lock request failed */ - MUTEX_LOCK_ERROR = -47, - /** Mutex unlock request failed */ - MUTEX_UNLOCK_ERROR = -48, - /** Mutex destroy failed */ - MUTEX_DESTROY_ERROR = -49, - /** Input argument exceeded the allowed maximum size */ - MAX_SIZE_ERROR = -50, - /** Some limit has been exceeded, e.g. the maximum number of subscriptions has been reached */ - LIMIT_EXCEEDED_ERROR = -51, - /** Invalid input topic type */ - INVALID_TOPIC_TYPE_ERROR = -52 -} IoT_Error_t; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_SDK_SRC_IOT_ERROR_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_interface.h deleted file mode 100644 index 4f033d9d6..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_interface.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_jobs_interface.h - * @brief An interface for interacting with the AWS IoT Jobs system. - * - * This file defines utility functions for interacting with the AWS IoT jobs - * APIs over MQTT. It provides functions for managing subscriptions to job - * related topics and for sending queries and updates requests for jobs. - * Callers are responsible for managing the subscriptions and associating - * responses with the queries and update messages. - */ -#ifndef AWS_IOT_JOBS_INTERFACE_H_ -#define AWS_IOT_JOBS_INTERFACE_H_ - -#ifdef DISABLE_IOT_JOBS -#error "Jobs API is disabled" -#endif - -/** - * @file aws_iot_jobs_interface.h - * @brief Functions for interacting with the AWS IoT Jobs system. - */ -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_jobs_topics.h" -#include "aws_iot_jobs_types.h" -#include "aws_iot_error.h" -#include "aws_iot_json_utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Subscribe to jobs messages for the given thing and/or jobs. - * - * The function can be used to subscribe to all job related messages. To subscribe - * to messages not related to a job the jobId passed should be null. The jobId - * can also be "+" to subscribe to messages related to any job, or "$next" to - * indicate the next pending job. - * - * See also #aws_iot_jobs_subscribe_to_all_job_messages to subscribe to all possible - * messages in one operation. - * - * \note Subscribing with the same thing, job and topic type more than - * once is undefined. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the name of the thing to subscribe to - * \param jobId the job id to subscribe to. To subscribe to messages not related to - * a job the jobId passed should be null. The jobId can also be "+" to subscribe to - * messages related to any job, or "$next" to indicate the next pending job. - * \param topicType the topic type to subscribe to - * \param replyType the reply topic type to subscribe to - * \param pApplicationHandler the callback handler - * \param pApplicationHandlerData the callback context data. This must remain valid at least until - * aws_iot_jobs_unsubscribe_from_job_messages is called. - * \param topicBuffer. A buffer to use to hold the topic name for the subscription. This buffer - * must remain valid at least until aws_iot_jobs_unsubscribe_from_job_messages is called. - * \param topicBufferSize the size of the topic buffer. The function will fail - * with LIMIT_EXCEEDED_ERROR if this is too small. - * \return the result of subscribing to the topic (see aws_iot_mqtt_subscribe) - */ -IoT_Error_t aws_iot_jobs_subscribe_to_job_messages( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - AwsIotJobExecutionTopicType topicType, - AwsIotJobExecutionTopicReplyType replyType, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData, - char *topicBuffer, - uint16_t topicBufferSize); - -/** - * @brief Subscribe to all job messages. - * - * Subscribe to all job messages for the given thing. - * - * \note Subscribing with the same thing more than once is undefined. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the name of the thing to subscribe to - * \param pApplicationHandler the callback handler - * \param pApplicationHandlerData the callback context data. This must remain valid at least until - * aws_iot_jobs_unsubscribe_from_job_messages is called. - * \param topicBuffer. A buffer to use to hold the topic name for the subscription. This buffer - * must remain valid at least until aws_iot_jobs_unsubscribe_from_job_messages is called. - * \param topicBufferSize the size of the topic buffer. The function will fail - * with LIMIT_EXCEEDED_ERROR if this is too small. - * \return the result of subscribing to the topic (see aws_iot_mqtt_subscribe) - */ -IoT_Error_t aws_iot_jobs_subscribe_to_all_job_messages( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData, - char *topicBuffer, - uint16_t topicBufferSize); - -/** - * @brief Unsubscribe from a job subscription - * - * Remove the subscription created using #aws_iot_jobs_subscribe_to_job_messages or - * #aws_iot_jobs_subscribe_to_all_job_messages. - * - * \param pClient the client to use - * \param topicBuffer the topic buffer passed to #aws_iot_jobs_subscribe_to_job_messages or - * #aws_iot_jobs_subscribe_to_all_job_messages when the subscription was created. - * \return #SUCCESS or the first error encountered. - */ -IoT_Error_t aws_iot_jobs_unsubscribe_from_job_messages( - AWS_IoT_Client *pClient, - char *topicBuffer); - -/** - * @brief Send a query to one of the job query APIs. - * - * Send a query to one of the job query APIs. If jobId is null this - * requests a list of pending jobs for the thing. If jobId is - * not null then it sends a query for the details of that job. - * If jobId is $next then it sends a query for the details for - * the next pending job. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the thing name to query for - * \param jobId the id of the job to query for. If null a list - * of all pending jobs for the thing is requested. - * \param clientToken the client token to use for the query. - * If null no clientToken is sent resulting in an empty message. - * \param topicBuffer the topic buffer to use. This may be discarded - * as soon as this function returns - * \param topicBufferSize the size of topicBuffer - * \param messageBuffer the message buffer to use. May be NULL - * if clientToken is NULL - * \param messageBufferSize the size of messageBuffer - * \param topicType the topic type to publish query to - * \return LIMIT_EXCEEDED_ERROR if the topic buffer or - * message buffer is too small, NULL_VALUE_ERROR if the any of - * the required inputs are NULL, otherwise the result - * of the mqtt publish - */ -IoT_Error_t aws_iot_jobs_send_query( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const char *clientToken, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize, - AwsIotJobExecutionTopicType topicType); - -/** - * @brief Send a start next command to the job start-next API. - * - * Send a start next command to the job start-next API. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the thing name to query for - * \param startNextRequest the start-next request to send - * \param topicBuffer the topic buffer to use. This may be discarded - * as soon as this function returns - * \param topicBufferSize the size of topicBuffer - * \param messageBuffer the message buffer to use. May be NULL - * if clientToken is NULL - * \param messageBufferSize the size of messageBuffer - * \return LIMIT_EXCEEDED_ERROR if the topic buffer or - * message buffer is too small, NULL_VALUE_ERROR if the any of - * the required inputs are NULL, otherwise the result - * of the mqtt publish - */ -IoT_Error_t aws_iot_jobs_start_next( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const AwsIotStartNextPendingJobExecutionRequest *startNextRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize); - -/** - * @brief Send a describe job query to the job query API. - * - * Send a describe job query to the job query API. If jobId is null this - * requests a list of pending jobs for the thing. If jobId is - * not null then it sends a query for the details of that job. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the thing name to query for - * \param jobId the id of the job to query for. If null a list - * of all pending jobs for the thing is requested. - * \param describeRequest the describe request to send - * \param topicBuffer the topic buffer to use. This may be discarded - * as soon as this function returns - * \param topicBufferSize the size of topicBuffer - * \param messageBuffer the message buffer to use. May be NULL - * if clientToken is NULL - * \param messageBufferSize the size of messageBuffer - * \return LIMIT_EXCEEDED_ERROR if the topic buffer or - * message buffer is too small, NULL_VALUE_ERROR if the any of - * the required inputs are NULL, otherwise the result - * of the mqtt publish - */ -IoT_Error_t aws_iot_jobs_describe( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const AwsIotDescribeJobExecutionRequest *describeRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize); - -/** - * @brief Send an update about a job execution. - * - * Send an update about a job execution. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the thing name to send the update for - * \param jobId the id of the job to send the update for - * \param updateRequest the update request to send - * \param topicBuffer the topic buffer to use. This may be discarded - * as soon as this function returns - * \param topicBufferSize the size of topicBuffer - * \param messageBuffer the message buffer to use. - * \param messageBufferSize the size of messageBuffer - * \return LIMIT_EXCEEDED_ERROR if the topic buffer or - * message buffer is too small, NULL_VALUE_ERROR if the any of - * the required inputs are NULL, otherwise the result - * of the mqtt publish - */ -IoT_Error_t aws_iot_jobs_send_update( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const AwsIotJobExecutionUpdateRequest *updateRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize); - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_JOBS_INTERFACE_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_json.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_json.h deleted file mode 100644 index 55e45142b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_json.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_jobs_json.h - * @brief Functions for mapping between json and the AWS Iot Job data structures. - */ - -#ifdef DISABLE_IOT_JOBS -#error "Jobs API is disabled" -#endif - -#ifndef AWS_IOT_JOBS_JSON_H_ -#define AWS_IOT_JOBS_JSON_H_ - -#include -#include "jsmn.h" -#include "aws_iot_jobs_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Serialize a job execution update request into a json string. - * - * \param requestBuffer buffer to contain the serialized request. If null - * this function will return the size of the buffer required - * \param bufferSize the size of the buffer. If this is smaller than the required - * length the string will be truncated to fit. - * \request the request to serialize. - * \return The size of the json string to store the serialized request or -1 - * if the request is invalid. Note that the return value should be checked against - * the size of the buffer and if its larger handle the fact that the string has - * been truncated. - */ -int aws_iot_jobs_json_serialize_update_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotJobExecutionUpdateRequest *request); - -/** - * Serialize a job API request that contains only a client token. - * - * \param requestBuffer buffer to contain the serialized request. If null - * this function will return the size of the buffer required - * \param bufferSize the size of the buffer. If this is smaller than the required - * length the string will be truncated to fit. - * \param clientToken the client token to use for the request. - * \return The size of the json string to store the serialized request or -1 - * if the request is invalid. Note that the return value should be checked against - * the size of the buffer and if its larger handle the fact that the string has - * been truncated. - */ -int aws_iot_jobs_json_serialize_client_token_only_request( - char *requestBuffer, size_t bufferSize, - const char *clientToken); - -/** - * Serialize describe job execution request into json string. - * - * \param requestBuffer buffer to contain the serialized request. If null - * this function will return the size of the buffer required - * \param bufferSize the size of the buffer. If this is smaller than the required - * length the string will be truncated to fit. - * \param request the request to serialize. - * \return The size of the json string to store the serialized request or -1 - * if the request is invalid. Note that the return value should be checked against - * the size of the buffer and if its larger handle the fact that the string has - * been truncated. - */ -int aws_iot_jobs_json_serialize_describe_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotDescribeJobExecutionRequest *request); - -/** - * Serialize start next job execution request into json string. - * - * \param requestBuffer buffer to contain the serialized request. If null - * this function will return the size of the buffer required - * \param bufferSize the size of the buffer. If this is smaller than the required - * length the string will be truncated to fit. - * \param request the start-next request to serialize. - * \return The size of the json string to store the serialized request or -1 - * if the request is invalid. Note that the return value should be checked against - * the size of the buffer and if its larger handle the fact that the string has - * been truncated. - */ -int aws_iot_jobs_json_serialize_start_next_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotStartNextPendingJobExecutionRequest *request); - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_JOBS_JSON_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_topics.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_topics.h deleted file mode 100644 index 3e291878b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_topics.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_job_topics.h - * @brief Functions for parsing and creating MQTT topics used by the AWS IoT Jobs system. - */ - -#ifdef DISABLE_IOT_JOBS -#error "Jobs API is disabled" -#endif - -#ifndef AWS_IOT_JOBS_TOPICS_H_ -#define AWS_IOT_JOBS_TOPICS_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define JOB_ID_NEXT "$next" -#define JOB_ID_WILDCARD "+" - -/** - * The type of job topic. - */ -typedef enum { - JOB_UNRECOGNIZED_TOPIC = 0, - JOB_GET_PENDING_TOPIC, - JOB_START_NEXT_TOPIC, - JOB_DESCRIBE_TOPIC, - JOB_UPDATE_TOPIC, - JOB_NOTIFY_TOPIC, - JOB_NOTIFY_NEXT_TOPIC, - JOB_WILDCARD_TOPIC -} AwsIotJobExecutionTopicType; - -/** - * The type of reply topic, or #JOB_REQUEST_TYPE for - * topics that are not replies. - */ -typedef enum { - JOB_UNRECOGNIZED_TOPIC_TYPE = 0, - JOB_REQUEST_TYPE, - JOB_ACCEPTED_REPLY_TYPE, - JOB_REJECTED_REPLY_TYPE, - JOB_WILDCARD_REPLY_TYPE -} AwsIotJobExecutionTopicReplyType; - -/** - * @brief Get the topic matching the provided details and put into the provided buffer. - * - * If the buffer is not large enough to store the full topic the topic will be truncated - * to fit, with the last character always being a null terminator. - * - * \param buffer the buffer to put the results into - * \param bufferSize the size of the buffer - * \param topicType the type of the topic - * \param replyType the reply type of the topic - * \param thingName the name of the thing in the topic - * \param jobId the name of the job id in the topic - * \return the number of characters in the topic excluding the null terminator. A return - * value of bufferSize or more means that the topic string was truncated. - */ -int aws_iot_jobs_get_api_topic(char *buffer, size_t bufferSize, - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType, - const char* thingName, const char* jobId); - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_JOBS_TOPICS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_types.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_types.h deleted file mode 100644 index b96ac02b7..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_types.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_jobs_types.h - * @brief Structures defining the interface with the AWS IoT Jobs system - * - * This file defines the structures returned by and sent to the AWS IoT Jobs system. - * - */ - -#ifdef DISABLE_IOT_JOBS -#error "Jobs API is disabled" -#endif - -#ifndef AWS_IOT_JOBS_TYPES_H_ -#define AWS_IOT_JOBS_TYPES_H_ - -#include -#include -#include "jsmn.h" -#include "timer_interface.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - JOB_EXECUTION_STATUS_NOT_SET = 0, - JOB_EXECUTION_QUEUED, - JOB_EXECUTION_IN_PROGRESS, - JOB_EXECUTION_FAILED, - JOB_EXECUTION_SUCCEEDED, - JOB_EXECUTION_CANCELED, - JOB_EXECUTION_REJECTED, - /*** - * Used for any status not in the supported list of statuses - */ - JOB_EXECUTION_UNKNOWN_STATUS = 99 -} JobExecutionStatus; - -extern const char *JOB_EXECUTION_QUEUED_STR; -extern const char *JOB_EXECUTION_IN_PROGRESS_STR; -extern const char *JOB_EXECUTION_FAILED_STR; -extern const char *JOB_EXECUTION_SUCCEEDED_STR; -extern const char *JOB_EXECUTION_CANCELED_STR; -extern const char *JOB_EXECUTION_REJECTED_STR; - -/** - * Convert a string to its matching status. - * - * \return the matching status, or JOB_EXECUTION_UNKNOWN_STATUS if the string was not recognized. - */ -JobExecutionStatus aws_iot_jobs_map_string_to_job_status(const char *str); - -/** - * Convert a status to its string. - * - * \return a string representing the status, or null if the status is not recognized. - */ -const char *aws_iot_jobs_map_status_to_string(JobExecutionStatus status); - -/** - * A request to update the status of a job execution. - */ -typedef struct { - int64_t expectedVersion; // set to 0 to ignore - int64_t executionNumber; // set to 0 to ignore - JobExecutionStatus status; - const char *statusDetails; - bool includeJobExecutionState; - bool includeJobDocument; - const char *clientToken; -} AwsIotJobExecutionUpdateRequest; - -/** - * A request to get the status of a job execution. - */ -typedef struct { - int64_t executionNumber; // set to 0 to ignore - bool includeJobDocument; - const char *clientToken; -} AwsIotDescribeJobExecutionRequest; - -/** - * A request to get and start the next pending (not in a terminal state) job execution for a Thing. - */ -typedef struct { - const char *statusDetails; - const char *clientToken; -} AwsIotStartNextPendingJobExecutionRequest; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_JOBS_TYPES_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h deleted file mode 100644 index af762d8a9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_json_utils.h - * @brief Utilities for manipulating JSON - * - * json_utils provides JSON parsing utilities for use with the IoT SDK. - * Underlying JSON parsing relies on the Jasmine JSON parser. - * - */ - -#ifndef AWS_IOT_SDK_SRC_JSON_UTILS_H_ -#define AWS_IOT_SDK_SRC_JSON_UTILS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "aws_iot_error.h" -#include "jsmn.h" - -// utility functions -/** - * @brief JSON Equality Check - * - * Given a token pointing to a particular JSON node and an - * input string, check to see if the key is equal to the string. - * - * @param json json string - * @param tok json token - pointer to key to test for equality - * @param s input string for key to test equality - * - * @return 0 if equal, 1 otherwise - */ -int8_t jsoneq(const char *json, jsmntok_t *tok, const char *s); - -/** - * @brief Parse a signed 32-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of int32_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a signed 16-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of int16_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseInteger16Value(int16_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a signed 8-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of int8_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse an unsigned 32-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of uint32_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseUnsignedInteger32Value(uint32_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse an unsigned 16-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of uint16_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse an unsigned 8-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of uint8_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a float value from a JSON node. - * - * Given a JSON node parse the float value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param f address of float to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a double value from a JSON node. - * - * Given a JSON node parse the double value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param d address of double to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a boolean value from a JSON node. - * - * Given a JSON node parse the boolean value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param b address of boolean to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a string value from a JSON node. - * - * Given a JSON node parse the string value from the value. - * - * @param buf address of string to be updated - * @param bufLen length of buf in bytes - * @param jsonString json string - * @param token json token - pointer to JSON node - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseStringValue(char *buf, size_t bufLen, const char *jsonString, jsmntok_t *token); - -/** - * @brief Find the JSON node associated with the given key in the given object. - * - * Given a JSON node parse the string value from the value. - * - * @param key json key - * @param token json token - pointer to JSON node - * @param jsonString json string - * - * @return pointer to found property value - * @return NULL - not found - */ -jsmntok_t *findToken(const char *key, const char *jsonString, jsmntok_t *token); - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_SDK_SRC_JSON_UTILS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h deleted file mode 100644 index 2eeac5954..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_log.h - * @brief Logging macros for the SDK. - * This file defines common logging macros with log levels to be used within the SDK. - * These macros can also be used in the IoT application code as a common way to output - * logs. The log levels can be tuned by modifying the makefile. Removing (commenting - * out) the IOT_* statement in the makefile disables that log level. - * - * It is expected that the macros below will be modified or replaced when porting to - * specific hardware platforms as printf may not be the desired behavior. - */ - -#ifndef _IOT_LOG_H -#define _IOT_LOG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** - * @brief Debug level logging macro. - * - * Macro to expose function, line number as well as desired log message. - */ -#ifdef ENABLE_IOT_DEBUG -#define IOT_DEBUG(...) \ - {\ - printf("DEBUG: %s L#%d ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#undef IOT_DEBUG -#define IOT_DEBUG(...) -#endif - -/** - * @brief Debug level trace logging macro. - * - * Macro to print message function entry and exit - */ -#ifdef ENABLE_IOT_TRACE -#define FUNC_ENTRY \ - {\ - printf("FUNC_ENTRY: %s L#%d \n", __func__, __LINE__); \ - } -#define FUNC_EXIT \ - {\ - printf("FUNC_EXIT: %s L#%d \n", __func__, __LINE__); \ - } -#define FUNC_EXIT_RC(x) \ - {\ - printf("FUNC_EXIT: %s L#%d Return Code : %d \n", __func__, __LINE__, x); \ - return x; \ - } -#else -#undef FUNC_ENTRY -#define FUNC_ENTRY - -#undef FUNC_EXIT -#define FUNC_EXIT -#undef FUNC_EXIT_RC -#define FUNC_EXIT_RC(x) { return x; } -#endif - -/** - * @brief Info level logging macro. - * - * Macro to expose desired log message. Info messages do not include automatic function names and line numbers. - */ -#ifdef ENABLE_IOT_INFO -#define IOT_INFO(...) \ - {\ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#undef IOT_INFO -#define IOT_INFO(...) -#endif - -/** - * @brief Warn level logging macro. - * - * Macro to expose function, line number as well as desired log message. - */ -#ifdef ENABLE_IOT_WARN -#define IOT_WARN(...) \ - { \ - printf("WARN: %s L#%d ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#undef IOT_WARN -#define IOT_WARN(...) -#endif - -/** - * @brief Error level logging macro. - * - * Macro to expose function, line number as well as desired log message. - */ -#ifdef ENABLE_IOT_ERROR -#define IOT_ERROR(...) \ - { \ - printf("ERROR: %s L#%d ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#undef IOT_ERROR -#define IOT_ERROR(...) -#endif - -#ifdef __cplusplus -} -#endif - -#endif // _IOT_LOG_H diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h deleted file mode 100644 index 9ba98c8ba..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client.h - * @brief Client definition for MQTT - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_MQTT_CLIENT_H -#define AWS_IOT_SDK_SRC_IOT_MQTT_CLIENT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Library Header files */ -#include "stdio.h" -#include "stdbool.h" -#include "stdint.h" -#include "stddef.h" - -/* AWS Specific header files */ -#include "aws_iot_error.h" -#include "aws_iot_config.h" - -/* Platform specific implementation header files */ -#include "network_interface.h" -#include "timer_interface.h" - -#ifdef _ENABLE_THREAD_SUPPORT_ -#include "threads_interface.h" -#endif - -/** Greatest packet identifier, per MQTT spec */ -#define MAX_PACKET_ID 65535 - -typedef struct _Client AWS_IoT_Client; - -/** - * @brief Quality of Service Type - * - * Defining a QoS type. - * @note QoS 2 is \b NOT supported by the AWS IoT Service at the time of this SDK release. - * - */ -typedef enum QoS { - QOS0 = 0, - QOS1 = 1 -} QoS; - -/** - * @brief Publish Message Parameters Type - * - * Defines a type for MQTT Publish messages. Used for both incoming and out going messages - * - */ -typedef struct { - QoS qos; ///< Message Quality of Service - uint8_t isRetained; ///< Retained messages are \b NOT supported by the AWS IoT Service at the time of this SDK release. - uint8_t isDup; ///< Is this message a duplicate QoS > 0 message? Handled automatically by the MQTT client. - uint16_t id; ///< Message sequence identifier. Handled automatically by the MQTT client. - void *payload; ///< Pointer to MQTT message payload (bytes). - size_t payloadLen; ///< Length of MQTT payload. -} IoT_Publish_Message_Params; - -/** - * @brief MQTT Version Type - * - * Defining an MQTT version type. Only 3.1.1 is supported at this time - * - */ -typedef enum { - MQTT_3_1_1 = 4 ///< MQTT 3.1.1 (protocol message byte = 4) -} MQTT_Ver_t; - -/** - * @brief Last Will and Testament Definition - * - * Defining a type for the MQTT "Last Will and Testament" (LWT) parameters. - * @note Retained messages are \b NOT supported by the AWS IoT Service at the time of this SDK release. - * - */ -typedef struct { - char struct_id[4]; ///< The eyecatcher for this structure. must be MQTW - char *pTopicName; ///< The LWT topic to which the LWT message will be published - uint16_t topicNameLen; ///< The length of the LWT topic, 16 bit unsinged integer - char *pMessage; ///< Message to be delivered as LWT - uint16_t msgLen; ///< The length of the Message, 16 bit unsinged integer - bool isRetained; ///< NOT supported. The retained flag for the LWT message (see MQTTAsync_message.retained) - QoS qos; ///< QoS of LWT message -} IoT_MQTT_Will_Options; -/** Default initializer for will */ -extern const IoT_MQTT_Will_Options iotMqttWillOptionsDefault; - -/** Default initializer for will */ -#define IoT_MQTT_Will_Options_Initializer { {'M', 'Q', 'T', 'W'}, NULL, 0, NULL, 0, false, QOS0 } - -/** - * @brief MQTT Connection Parameters - * - * Defining a type for MQTT connection parameters. Passed into client when establishing a connection. - * - */ -typedef struct { - char struct_id[4]; ///< The eyecatcher for this structure. must be MQTC - MQTT_Ver_t MQTTVersion; ///< Desired MQTT version used during connection - char *pClientID; ///< Pointer to a string defining the MQTT client ID (this needs to be unique \b per \b device across your AWS account) - uint16_t clientIDLen; ///< Client Id Length. 16 bit unsigned integer - uint16_t keepAliveIntervalInSec; ///< MQTT keep alive interval in seconds. Defines inactivity time allowed before determining the connection has been lost. - bool isCleanSession; ///< MQTT clean session. True = this session is to be treated as clean. Previous server state is cleared and no stated is retained from this connection. - bool isWillMsgPresent; ///< Is there a LWT associated with this connection? - IoT_MQTT_Will_Options will; ///< MQTT LWT parameters. - char *pUsername; ///< Not used in the AWS IoT Service, will need to be cstring if used - uint16_t usernameLen; ///< Username Length. 16 bit unsigned integer - char *pPassword; ///< Not used in the AWS IoT Service, will need to be cstring if used - uint16_t passwordLen; ///< Password Length. 16 bit unsigned integer -} IoT_Client_Connect_Params; -/** Default initializer for connect */ -extern const IoT_Client_Connect_Params iotClientConnectParamsDefault; - -/** Default initializer for connect */ -#define IoT_Client_Connect_Params_initializer { {'M', 'Q', 'T', 'C'}, MQTT_3_1_1, NULL, 0, 60, true, false, \ - IoT_MQTT_Will_Options_Initializer, NULL, 0, NULL, 0 } - -/** - * @brief Disconnect Callback Handler Type - * - * Defining a TYPE for definition of disconnect callback function pointers. - * - */ -typedef void (*iot_disconnect_handler)(AWS_IoT_Client *, void *); - -/** - * @brief MQTT Initialization Parameters - * - * Defining a type for MQTT initialization parameters. - * Passed into client when to initialize the client - * - */ -typedef struct { - bool enableAutoReconnect; ///< Set to true to enable auto reconnect - char *pHostURL; ///< Pointer to a string defining the endpoint for the MQTT service - uint16_t port; ///< MQTT service listening port - char *pRootCALocation; ///< Pointer to a string defining the Root CA file (full file, not path) - char *pDeviceCertLocation; ///< Pointer to a string defining the device identity certificate file (full file, not path) - char *pDevicePrivateKeyLocation; ///< Pointer to a string defining the device private key file (full file, not path) - uint32_t mqttPacketTimeout_ms; ///< Timeout for reading a complete MQTT packet. In milliseconds - uint32_t mqttCommandTimeout_ms; ///< Timeout for MQTT blocking calls. In milliseconds - uint32_t tlsHandshakeTimeout_ms; ///< TLS handshake timeout. In milliseconds - bool isSSLHostnameVerify; ///< Client should perform server certificate hostname validation - iot_disconnect_handler disconnectHandler; ///< Callback to be invoked upon connection loss - void *disconnectHandlerData; ///< Data to pass as argument when disconnect handler is called -#ifdef _ENABLE_THREAD_SUPPORT_ - bool isBlockOnThreadLockEnabled; ///< Timeout for Thread blocking calls. Set to 0 to block until lock is obtained. In milliseconds -#endif -} IoT_Client_Init_Params; -/** Default initializer for client */ -extern const IoT_Client_Init_Params iotClientInitParamsDefault; - -/** Default initializer for client */ -#ifdef _ENABLE_THREAD_SUPPORT_ -#define IoT_Client_Init_Params_initializer { true, NULL, 0, NULL, NULL, NULL, 2000, 20000, 5000, true, NULL, NULL, false } -#else -#define IoT_Client_Init_Params_initializer { true, NULL, 0, NULL, NULL, NULL, 2000, 20000, 5000, true, NULL, NULL } -#endif - -/** - * @brief MQTT Client State Type - * - * Defining a type for MQTT Client State - * - */ -typedef enum _ClientState { - CLIENT_STATE_INVALID = 0, - CLIENT_STATE_INITIALIZED = 1, - CLIENT_STATE_CONNECTING = 2, - CLIENT_STATE_CONNECTED_IDLE = 3, - CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS = 4, - CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS = 5, - CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS = 6, - CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS = 7, - CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS = 8, - CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN = 9, - CLIENT_STATE_DISCONNECTING = 10, - CLIENT_STATE_DISCONNECTED_ERROR = 11, - CLIENT_STATE_DISCONNECTED_MANUALLY = 12, - CLIENT_STATE_PENDING_RECONNECT = 13 -} ClientState; - -/** - * @brief Application Callback Handler Type - * - * Defining a TYPE for definition of application callback function pointers. - * Used to send incoming data to the application - * - */ -typedef void (*pApplicationHandler_t)(AWS_IoT_Client *pClient, char *pTopicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *pParams, void *pClientData); - -/** - * @brief MQTT Message Handler - * - * Defining a type for MQTT Message Handlers. - * Used to pass incoming data back to the application - * - */ -typedef struct _MessageHandlers { - const char *topicName; ///< Topic name of subscription - uint16_t topicNameLen; ///< Length of topic name - char resubscribed; ///< Whether this handler was successfully resubscribed in the reconnect workflow - QoS qos; ///< QoS of subscription - pApplicationHandler_t pApplicationHandler; ///< Application function to invoke - void *pApplicationHandlerData; ///< Context to pass to application handler -} MessageHandlers; /* Message handlers are indexed by subscription topic */ - -/** - * @brief MQTT Client Status - * - * Defining a type for MQTT Client Status - * Contains information about the state of the MQTT Client - * - */ -typedef struct _ClientStatus { - ClientState clientState; ///< The current state of the client's state machine - bool isPingOutstanding; ///< Whether this client is waiting for a ping response - bool isAutoReconnectEnabled; ///< Whether auto-reconnect is enabled for this client -} ClientStatus; - -/** - * @brief MQTT Client Data - * - * Defining a type for MQTT Client Data - * Contains data used by the MQTT Client - * - */ -typedef struct _ClientData { - uint16_t nextPacketId; ///< Packet ID to use for the next generated packet - - /* Packet timeout is unused. See https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/1475 */ - uint32_t packetTimeoutMs; ///< Timeout for reading incoming packets from the network - uint32_t commandTimeoutMs; ///< Timeout for processing outgoing MQTT packets - uint16_t keepAliveInterval; ///< Maximum interval between control packets - uint32_t currentReconnectWaitInterval; ///< Current backoff period for reconnect - uint32_t counterNetworkDisconnected; ///< How many times this client detected a disconnection - - /* The below values are initialized with the - * lengths of the TX/RX buffers and never modified - * afterwards */ - size_t writeBufSize; ///< Size of this client's outgoing data buffer - size_t readBufSize; ///< Size of this client's incoming data buffer - size_t readBufIndex; ///< Current offset into the incoming data buffer - unsigned char writeBuf[AWS_IOT_MQTT_TX_BUF_LEN]; ///< Buffer for outgoing data - unsigned char readBuf[AWS_IOT_MQTT_RX_BUF_LEN]; ///< Buffer for incoming data - -#ifdef _ENABLE_THREAD_SUPPORT_ - bool isBlockOnThreadLockEnabled; ///< Whether to use nonblocking or blocking mutex APIs - IoT_Mutex_t state_change_mutex; ///< Mutex protecting the client's state machine - IoT_Mutex_t tls_read_mutex; ///< Mutex protecting incoming data - IoT_Mutex_t tls_write_mutex; ///< Mutex protecting outgoing data -#endif - - IoT_Client_Connect_Params options; ///< Options passed when the client was initialized - - MessageHandlers messageHandlers[AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS]; ///< Callbacks for incoming messages - iot_disconnect_handler disconnectHandler; ///< Callback when a disconnection is detected - void *disconnectHandlerData; ///< Context for disconnect handler -} ClientData; - -/** - * @brief MQTT Client - * - * Defining a type for MQTT Client - * - */ -struct _Client { - Timer pingReqTimer; ///< Timer to keep track of when to send next PINGREQ - Timer pingRespTimer; ///< Timer to ensure that PINGRESP is received timely - Timer reconnectDelayTimer; ///< Timer for backoff on reconnect - - ClientStatus clientStatus; ///< Client state information - ClientData clientData; ///< Client context - Network networkStack; ///< Table of network function pointers -}; - -/** - * @functionpage{aws_iot_mqtt_get_next_packet_id,mqtt,get_next_packet_id} - * @functionpage{aws_iot_mqtt_set_connect_params,mqtt,set_connect_params} - * @functionpage{aws_iot_mqtt_is_client_connected,mqtt,is_client_connected} - * @functionpage{aws_iot_mqtt_get_client_state,mqtt,get_client_state} - * @functionpage{aws_iot_is_autoreconnect_enabled,mqtt,is_autoreconnect_enabled} - * @functionpage{aws_iot_mqtt_set_disconnect_handler,mqtt,set_disconnect_handler} - * @functionpage{aws_iot_mqtt_autoreconnect_set_status,mqtt,autoreconnect_set_status} - * @functionpage{aws_iot_mqtt_get_network_disconnected_count,mqtt,get_network_disconnected_count} - * @functionpage{aws_iot_mqtt_reset_network_disconnected_count,mqtt,reset_network_disconnected_count} - */ - -/** - * @brief Retrieve and increment the next packet identifier for an MQTT client context. - * - * This function generates a two-byte packet identifier for an outgoing MQTT packet and - * modifies the internal state of the MQTT client context so that the next call generates - * a different packet identifier. Per the MQTT specification, MQTT packet identifiers are - * nonzero, two-byte integers that identify certain MQTT packets. MQTT packet identifiers - * must be unique at any given time: no two concurrent packets may use the same identifier, - * but packet identifiers from previously processed packets may be reused. - * - * @param[in] pClient MQTT client context - * - * @return A two-byte MQTT packet identifier that will be unique for the given MQTT client - * context. - * - * @warning This function is not thread safe. Do not call it concurrently from different - * threads. - */ -/* @[declare_mqtt_get_next_packet_id] */ -uint16_t aws_iot_mqtt_get_next_packet_id(AWS_IoT_Client *pClient); -/* @[declare_mqtt_get_next_packet_id] */ - -/** - * @brief Reset the connection parameters of an initialized MQTT client context. - * - * This function replaces the current connection parameters of an MQTT client - * context with a new set of parameters. Its primary use is to modify the connection - * parameters for the next reconnect attempt if the existing parameters are no longer - * valid. Therefore, it should be called just before a reconnect attempt, i.e. just - * before @ref mqtt_function_attempt_reconnect or @ref mqtt_function_yield. - * - * The new connection parameters take effect at the next connection attempt. - * - * @param[in] pClient MQTT client context - * @param[in] pNewConnectParams The new connection parameters - * - * @return Returns NULL_VALUE_ERROR if provided a bad parameter; otherwise, always - * returns SUCCESS. - * - * @warning Do not call this function if a connection attempt is in progress. Connection - * attempts happen in the context of @ref mqtt_function_connect, @ref mqtt_function_attempt_reconnect, - * or @ref mqtt_function_yield. - */ -/* @[declare_mqtt_set_connect_params] */ -IoT_Error_t aws_iot_mqtt_set_connect_params(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pNewConnectParams); -/* @[declare_mqtt_set_connect_params] */ - -/** - * @brief Determine if the MQTT client context currently connected to a server. - * - * This function checks the internal state of the MQTT client context to determine - * if it is currently connected to the server. - * - * @param[in] pClient MQTT client context - * - * @return true if connected; false otherwise. - * - * @warning Application code should not rely on this function's return value. - * The returned value only represents the internal state of the client and - * does not check the network connection status. - */ -/* @[declare_mqtt_is_client_connected] */ -bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient); -/* @[declare_mqtt_is_client_connected] */ - -/** - * @brief Get the current state of the MQTT client context. - * - * @param[in] pClient MQTT client context - * - * @return The state of the MQTT client context at the time of the function call. - * - * @note The client's state is internal and generally not useful to application code. - * Applications should not make assumptions about the status of the client based on - * its state. - */ -/* @[declare_mqtt_get_client_state] */ -ClientState aws_iot_mqtt_get_client_state(AWS_IoT_Client *pClient); -/* @[declare_mqtt_get_client_state] */ - -/** - * @brief Determine if auto-reconnect is enabled for an MQTT client context. - * - * @param[in] pClient MQTT client context - * - * @return true if auto-reconnect is enabled; false otherwise. - */ -/* @[declare_mqtt_is_autoreconnect_enabled] */ -bool aws_iot_is_autoreconnect_enabled(AWS_IoT_Client *pClient); -/* @[declare_mqtt_is_autoreconnect_enabled] */ - -/** - * @brief Reset the disconnect handler of an initialized MQTT client context. - * - * This function replaces the current disconnect handler of an MQTT client - * context with a new disconnect handler. - * - * The new disconnect handler will be invoked when the next disconnect is detected. - * - * @param[in] pClient MQTT client context - * @param[in] pDisconnectHandler New disconnect handler - * @param[in] pDisconnectHandlerData Context to be passed to new disconnect handler - * - * @return Returns NULL_VALUE_ERROR if provided a bad parameter; otherwise, always - * returns SUCCESS. - * - * @warning Do not call this function if @ref mqtt_function_yield is in progress. - */ -/* @[declare_mqtt_set_disconnect_handler] */ -IoT_Error_t aws_iot_mqtt_set_disconnect_handler(AWS_IoT_Client *pClient, iot_disconnect_handler pDisconnectHandler, - void *pDisconnectHandlerData); -/* @[declare_mqtt_set_disconnect_handler] */ - -/** - * @brief Enable or disable auto-reconnect for an initialized MQTT client context. - * - * This function replaces the current auto-reconnect setting with the provided setting. - * - * @note This function should only be called after @ref mqtt_function_connect has been - * called for the provided client. - * - * @param[in] pClient MQTT client context - * @param[in] newStatus New setting for auto-reconnect - * - * @return Returns NULL_VALUE_ERROR if provided a bad parameter; otherwise, always - * returns SUCCESS. - * - * @warning Do not call this function if a connection attempt is in progress. Connection - * attempts happen in the context of @ref mqtt_function_connect, @ref mqtt_function_attempt_reconnect, - * or @ref mqtt_function_yield. - */ -/* @[declare_mqtt_autoreconnect_set_status] */ -IoT_Error_t aws_iot_mqtt_autoreconnect_set_status(AWS_IoT_Client *pClient, bool newStatus); -/* @[declare_mqtt_autoreconnect_set_status] */ - -/** - * @brief Get the current number of disconnects detected by an MQTT client context. - * - * @param[in] pClient MQTT client context - * - * @return The number of disconnects detected since the client was created - * (or since the last call to @ref mqtt_function_reset_network_disconnected_count). - * - * @warning Do not call this function if @ref mqtt_function_yield is in progress. - */ -/* @[declare_mqtt_get_network_disconnected_count] */ -uint32_t aws_iot_mqtt_get_network_disconnected_count(AWS_IoT_Client *pClient); -/* @[declare_mqtt_get_network_disconnected_count] */ - -/** - * @brief Reset the number of disconnects detected by an MQTT client context to zero. - * - * @param[in] pClient MQTT client context - * - * @warning Do not call this function if @ref mqtt_function_yield is in progress. - */ -/* @[declare_mqtt_reset_network_disconnected_count] */ -void aws_iot_mqtt_reset_network_disconnected_count(AWS_IoT_Client *pClient); -/* @[declare_mqtt_reset_network_disconnected_count] */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h deleted file mode 100644 index ee8ca023e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h +++ /dev/null @@ -1,134 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_common_internal.h - * @brief Internal MQTT functions not exposed to application - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H -#define AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include "aws_iot_log.h" -#include "aws_iot_mqtt_client_interface.h" - -/** Types of MQTT messages */ -typedef enum msgTypes { - UNKNOWN = -1, - CONNECT = 1, - CONNACK = 2, - PUBLISH = 3, - PUBACK = 4, - PUBREC = 5, - PUBREL = 6, - PUBCOMP = 7, - SUBSCRIBE = 8, - SUBACK = 9, - UNSUBSCRIBE = 10, - UNSUBACK = 11, - PINGREQ = 12, - PINGRESP = 13, - DISCONNECT = 14 -} MessageTypes; - -/* Macros for parsing header fields from incoming MQTT frame. */ -#define MQTT_HEADER_FIELD_TYPE(_byte) ((_byte >> 4) & 0x0F) /**< Message type */ -#define MQTT_HEADER_FIELD_DUP(_byte) ((_byte & (1 << 3)) >> 3) /**< DUP flag */ -#define MQTT_HEADER_FIELD_QOS(_byte) ((_byte & (3 << 1)) >> 1) /**< QoS */ -#define MQTT_HEADER_FIELD_RETAIN(_byte) ((_byte & (1 << 0)) >> 0) /**< Retain flag */ - -/** - * Bitfields for the MQTT header byte. - */ -typedef union { - unsigned char byte; /**< the whole byte */ -} MQTTHeader; - -IoT_Error_t aws_iot_mqtt_internal_init_header(MQTTHeader *pHeader, MessageTypes message_type, - QoS qos, uint8_t dup, uint8_t retained); - -IoT_Error_t aws_iot_mqtt_internal_serialize_ack(unsigned char *pTxBuf, size_t txBufLen, - MessageTypes msgType, uint8_t dup, uint16_t packetId, - uint32_t *pSerializedLen); -IoT_Error_t aws_iot_mqtt_internal_deserialize_ack(unsigned char *, unsigned char *, - uint16_t *, unsigned char *, size_t); - -uint32_t aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(uint32_t rem_len); - -size_t aws_iot_mqtt_internal_write_len_to_buffer(unsigned char *buf, uint32_t length); -IoT_Error_t aws_iot_mqtt_internal_decode_remaining_length_from_buffer(unsigned char *buf, uint32_t *decodedLen, - uint32_t *readBytesLen); - -uint16_t aws_iot_mqtt_internal_read_uint16_t(unsigned char **pptr); -void aws_iot_mqtt_internal_write_uint_16(unsigned char **pptr, uint16_t anInt); - -unsigned char aws_iot_mqtt_internal_read_char(unsigned char **pptr); -void aws_iot_mqtt_internal_write_char(unsigned char **pptr, unsigned char c); -void aws_iot_mqtt_internal_write_utf8_string(unsigned char **pptr, const char *string, uint16_t stringLen); - -IoT_Error_t aws_iot_mqtt_internal_flushBuffers( AWS_IoT_Client *pClient ); -IoT_Error_t aws_iot_mqtt_internal_send_packet(AWS_IoT_Client *pClient, size_t length, Timer *pTimer); -IoT_Error_t aws_iot_mqtt_internal_cycle_read(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType); -IoT_Error_t aws_iot_mqtt_internal_wait_for_read(AWS_IoT_Client *pClient, uint8_t packetType, Timer *pTimer); -IoT_Error_t aws_iot_mqtt_internal_serialize_zero(unsigned char *pTxBuf, size_t txBufLen, - MessageTypes packetType, size_t *pSerializedLength); -IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos, - uint8_t *retained, uint16_t *pPacketId, - char **pTopicName, uint16_t *topicNameLen, - unsigned char **payload, size_t *payloadLen, - unsigned char *pRxBuf, size_t rxBufLen); - -IoT_Error_t aws_iot_mqtt_set_client_state(AWS_IoT_Client *pClient, ClientState expectedCurrentState, - ClientState newState); - -#ifdef _ENABLE_THREAD_SUPPORT_ - -IoT_Error_t aws_iot_mqtt_client_lock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex); - -IoT_Error_t aws_iot_mqtt_client_unlock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h deleted file mode 100644 index 65e101951..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h +++ /dev/null @@ -1,305 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_interface.h - * @brief Interface definition for MQTT client. - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_MQTT_INTERFACE_H -#define AWS_IOT_SDK_SRC_IOT_MQTT_INTERFACE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Library Header files */ -#include "stdio.h" -#include "stdbool.h" -#include "stdint.h" -#include "stddef.h" - -/* AWS Specific header files */ -#include "aws_iot_error.h" -#include "aws_iot_config.h" -#include "aws_iot_mqtt_client.h" - -/* Platform specific implementation header files */ -#include "network_interface.h" -#include "timer_interface.h" - -/** - * @functionspage{mqtt,MQTT library} - * - * API functions - * - @functionname{mqtt_function_init} - * - @functionname{mqtt_function_free} - * - @functionname{mqtt_function_connect} - * - @functionname{mqtt_function_publish} - * - @functionname{mqtt_function_subscribe} - * - @functionname{mqtt_function_resubscribe} - * - @functionname{mqtt_function_unsubscribe} - * - @functionname{mqtt_function_disconnect} - * - @functionname{mqtt_function_yield} - * - @functionname{mqtt_function_attempt_reconnect} - * - @functionname{mqtt_function_get_next_packet_id} - * - @functionname{mqtt_function_set_connect_params} - * - @functionname{mqtt_function_is_client_connected} - * - @functionname{mqtt_function_get_client_state} - * - @functionname{mqtt_function_is_autoreconnect_enabled} - * - @functionname{mqtt_function_set_disconnect_handler} - * - @functionname{mqtt_function_autoreconnect_set_status} - * - @functionname{mqtt_function_get_network_disconnected_count} - * - @functionname{mqtt_function_reset_network_disconnected_count} - */ - -/** - * @functionpage{aws_iot_mqtt_init,mqtt,init} - * @functionpage{aws_iot_mqtt_free,mqtt,free} - * @functionpage{aws_iot_mqtt_connect,mqtt,connect} - * @functionpage{aws_iot_mqtt_publish,mqtt,publish} - * @functionpage{aws_iot_mqtt_subscribe,mqtt,subscribe} - * @functionpage{aws_iot_mqtt_resubscribe,mqtt,resubscribe} - * @functionpage{aws_iot_mqtt_unsubscribe,mqtt,unsubscribe} - * @functionpage{aws_iot_mqtt_disconnect,mqtt,disconnect} - * @functionpage{aws_iot_mqtt_yield,mqtt,yield} - * @functionpage{aws_iot_mqtt_attempt_reconnect,mqtt,attempt_reconnect} - */ - -/** - * @brief Initialize a new MQTT client context. - * - * This function should be called before any other MQTT function to initialize - * a new MQTT client context. Once the client context is no longer needed, - * @ref mqtt_function_free should be called. - * - * @param[in] pClient MQTT client context to initialize - * @param[in] pInitParams The MQTT connection parameters - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_init] */ -IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *pInitParams); -/* @[declare_mqtt_init] */ - -/** - * @brief Clean up an MQTT client context that is no longer needed. - * - * This function will free up resources used by an MQTT client context. It should - * only be called when that context is no longer needed. - * - * @param[in] pClient MQTT client context that was previously initialized by - * @ref mqtt_function_init - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_free] */ -IoT_Error_t aws_iot_mqtt_free( AWS_IoT_Client *pClient ); -/* @[declare_mqtt_free] */ - -/** - * @brief Establish a connection with an MQTT server. - * - * This function should be called once and after @ref mqtt_function_init. It sends - * the MQTT CONNECT packet to the server, which establishes an MQTT session. Once - * the session is no longer needed, it can be closed with @ref mqtt_function_disconnect. - * - * @param[in] pClient MQTT client context - * @param[in] pConnectParams MQTT connection parameters - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_connect] */ -IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams); -/* @[declare_mqtt_connect] */ - -/** - * @brief Publish an MQTT message to a topic. - * - * This function sends an MQTT message to the server. The server will then - * forward this message to any clients with subscriptions to topic filters - * that match the message's topic. - * - * For a QoS 0 message, this function returns after the message is successfully - * passed to the TLS layer. For a QoS 1 message, this function returns after the - * receipt of the PUBACK for the transmitted message. - * - * @param pClient MQTT client context - * @param pTopicName Topic name to publish to - * @param topicNameLen Length of the topic name - * @param pParams Publish message parameters - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_publish] */ -IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *pParams); -/* @[declare_mqtt_publish] */ - -/** - * @brief Subscribe to an MQTT topic. - * - * This function sends an MQTT subscribe packet to the server. It registers - * a subscription that will cause the provided callback function to be invoked - * when the server sends a message on a matching topic to the client. - * - * @note Incoming messages are handled by @ref mqtt_function_yield. Therefore, - * @ref mqtt_function_yield must always be called regularly if any subscriptions - * are active. - * - * @param[in] pClient MQTT client context - * @param[in] pTopicName Topic for subscription - * @param[in] topicNameLen Length of topic - * @param[in] qos Quality of service for subscription - * @param[in] pApplicationHandler Callback function for incoming messages that arrive - * on this subscription - * @param[in] pApplicationHandlerData Data passed to the callback - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - * - * @attention The `pTopicName` parameter is not copied. It must remain valid for the duration - * of the subscription (until @ref mqtt_function_unsubscribe) is called. - */ -/* @[declare_mqtt_subscribe] */ -IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData); -/* @[declare_mqtt_subscribe] */ - -/** - * @brief Resubscribe to topic filter subscriptions in a previous MQTT session. - * - * This function restores subscriptions that were previously present in an - * MQTT session. Its primary use is to restore subscriptions after a session - * is manually disconnected and reopened. - * - * @note This function does not need to be called after @ref mqtt_function_attempt_reconnect - * or if auto-reconnect is enabled. - * - * @param[in] pClient MQTT client context - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_resubscribe] */ -IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient); -/* @[declare_mqtt_resubscribe] */ - -/** - * @brief Unsubscribe from an MQTT topic filter. - * - * This function removes an MQTT subscription previously set by @ref mqtt_function_subscribe. - * It sends an MQTT UNSUBSCRIBE packet to the server and removes the topic's message - * handler stored by the client. - * - * @param[in] pClient MQTT client context - * @param[in] pTopicFilter Topic filter of the subscription to remove - * @param[in] topicFilterLen Length of topic filter to remove - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_unsubscribe] */ -IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen); -/* @[declare_mqtt_unsubscribe] */ - -/** - * @brief Disconnect an MQTT session. - * - * This function sends the MQTT DISCONNECT packet, which closes the MQTT session - * between the client and server. After this function returns, the MQTT client - * context should be either freed with @ref mqtt_function_free or reopened with - * @ref mqtt_function_connect. - * - * @param[in] pClient MQTT client context - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_disconnect] */ -IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient); -/* @[declare_mqtt_disconnect] */ - -/** - * @brief Provide time for the MQTT client to process events. - * - * This function processes the following events: - * - Incoming messages from the server
- * Whenever a client publishes a message on a topic, the server sends that - * message to all the clients whose subscriptions match the message's - * topic. The messages sent by the server are received by this function, - * which in turn calls the corresponding message handler. This function - * must be called at a rate faster than the incoming messages, as it is the - * only way the client receives processing time to manage incoming messages. - * - MQTT keep-alive (sending ping requests and processing ping responses)
- * The MQTT keep-alive mechanism involves sending pings to the server if the connection - * is idle. Therefore, in the absence of any other messages, this function must be called - * at least once every keep-alive period to send the ping request. - * - @ref mqtt_autoreconnect (if enabled)
- * If the client detects a disconnect, the reconnection will be performed in this function. - * - * @param[in] pClient MQTT client context - * @param[in] timeout_ms Amount of time to yield. This function will return to the caller - * after AT LEAST this amount of thime has passed. - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - * @return If this call results a negative value, assume the MQTT connection has dropped. - * @ref mqtt_function_is_client_connected can be called to confirm. If a reconnection is - * needed, @ref mqtt_function_attempt_reconnect should be called. - */ -/* @[declare_mqtt_yield] */ -IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms); -/* @[declare_mqtt_yield] */ - -/** - * @brief Attempt to reconnect with the MQTT server. - * - * This function makes a single reconnect attempt with the server. If the - * reconnection is successful, subscriptions from the client's previous - * session are restored as well. - * - * If this function fails, the client's state is set to `CLIENT_STATE_PENDING_RECONNECT`. - * - * @param[in] pClient MQTT client context - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - * - * @note Generally, it is not necessary to call this function if @ref mqtt_autoreconnect - * is enabled. This function may still be called to initiate a reconnect attempt when - * auto-reconnect has exhausted all attempts. - */ -/* @[declare_mqtt_attempt_reconnect] */ -IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient); -/* @[declare_mqtt_attempt_reconnect] */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h deleted file mode 100644 index 279c0cbec..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_interface.h" - -IoT_Error_t aws_iot_shadow_internal_action(const char *pThingName, ShadowActions_t action, - const char *pJsonDocumentToBeSent, size_t jsonSize, fpActionCallback_t callback, - void *pCallbackContext, uint32_t timeout_seconds, bool isSticky); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h deleted file mode 100644 index 241edba70..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -#ifndef AWS_IOT_SDK_SRC_IOT_SHADOW_H_ -#define AWS_IOT_SDK_SRC_IOT_SHADOW_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @file aws_iot_shadow_interface.h - * @brief Interface for thing shadow - * - * These are the functions and structs to manage/interact the Thing Shadow(in the cloud). - * This SDK will let you interact with your own thing shadow or any other shadow using its Thing Name. - * There are totally 3 actions a device can perform on the shadow - Get, Update and Delete. - * - * Currently the device should use MQTT/S underneath. In the future this will also support other protocols. As it supports MQTT, the shadow needs to connect and disconnect. - * It will also work on the pub/sub model. On performing any action, the acknowledgment will be received in either accepted or rejected. For Example: - * If we want to perform a GET on the thing shadow the following messages will be sent and received: - * 1. A MQTT Publish on the topic - $aws/things/{thingName}/shadow/get - * 2. Subscribe to MQTT topics - $aws/things/{thingName}/shadow/get/accepted and $aws/things/{thingName}/shadow/get/rejected. - * If the request was successful we will receive the things json document in the accepted topic. - * - * - */ -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_json_data.h" - -/*! - * @brief Shadow Initialization parameters - * - * As the Shadow SDK uses MQTT underneath, it could be connected and disconnected on events to save some battery. - * @note Always use the \c ShadowIniTParametersDefault to initialize this struct - * - * - * - */ -typedef struct { - char *pHost; ///< This will be unique to a customer and can be retrieved from the console - uint16_t port; ///< Network port for TCP/IP socket - char *pRootCA; ///< Location with the Filename of the Root CA - char *pClientCRT; ///< Location of Device certs signed by AWS IoT service - char *pClientKey; ///< Location of Device private key - bool enableAutoReconnect; ///< Set to true to enable auto reconnect - iot_disconnect_handler disconnectHandler; ///< Callback to be invoked upon connection loss. -} ShadowInitParameters_t; - -/*! - * @brief Shadow Connect parameters - * - * As the Shadow SDK uses MQTT underneath, it could be connected and disconnected on events to save some battery. - * @note Always use the \c ShadowConnectParametersDefault to initialize this struct - * - *d - * - */ -typedef struct { - char *pMyThingName; ///< Every device has a Thing Shadow and this is the placeholder for name - char *pMqttClientId; ///< Currently the Shadow uses MQTT to connect and it is important to ensure we have unique client id - uint16_t mqttClientIdLen; ///< Currently the Shadow uses MQTT to connect and it is important to ensure we have unique client id - pApplicationHandler_t deleteActionHandler; ///< Callback to be invoked when Thing shadow for this device is deleted -} ShadowConnectParameters_t; - -/*! - * @brief This is set to defaults from the configuration file - * The certs are set to NULL because they need the path to the file. shadow_sample.c file demonstrates on how to get the relative path - * - * \relates ShadowInitParameters_t - */ -extern const ShadowInitParameters_t ShadowInitParametersDefault; - -/*! - * @brief This is set to defaults from the configuration file - * The length of the client id is initialized as 0. This is due to C language limitations of using constant literals - * only for creating const variables. The client id will be assigned using the value from aws_iot_config.h but the - * length needs to be assigned in code. shadow_sample.c file demonstrates this. - * - * \relates ShadowConnectParameters_t - */ -extern const ShadowConnectParameters_t ShadowConnectParametersDefault; - -/** -* @brief Clean shadow client from all dynamic memory allocate -* -* This function will free up memory that was dynamically allocated for the client. -* -* @param pClient MQTT Client that was previously created by calling aws_iot_shadow_init -* @return An IoT Error Type defining successful/failed freeing -*/ -IoT_Error_t aws_iot_shadow_free(AWS_IoT_Client *pClient); - -/** - * @brief Initialize the Thing Shadow before use - * - * This function takes care of initializing the internal book-keeping data structures and initializing the IoT client. - * - * @param pClient A new MQTT Client to be used as the protocol layer. Will be initialized with pParams. - * @return An IoT Error Type defining successful/failed Initialization - */ -IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, ShadowInitParameters_t *pParams); - -/** - * @brief Connect to the AWS IoT Thing Shadow service over MQTT - * - * This function does the TLSv1.2 handshake and establishes the MQTT connection - * - * @param pClient MQTT Client used as the protocol layer - * @param pParams Shadow Conenction parameters like TLS cert location - * @return An IoT Error Type defining successful/failed Connection - */ -IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, ShadowConnectParameters_t *pParams); - -/** - * @brief Yield function to let the background tasks of MQTT and Shadow - * - * This function could be use in a separate thread waiting for the incoming messages, ensuring the connection is kept alive with the AWS Service. - * It also ensures the expired requests of Shadow actions are cleared and Timeout callback is executed. - * @note All callbacks ever used in the SDK will be executed in the context of this function. - * - * @param pClient MQTT Client used as the protocol layer - * @param timeout in milliseconds, This is the maximum time the yield function will wait for a message and/or read the messages from the TLS buffer - * @return An IoT Error Type defining successful/failed Yield - */ -IoT_Error_t aws_iot_shadow_yield(AWS_IoT_Client *pClient, uint32_t timeout); - -/** - * @brief Disconnect from the AWS IoT Thing Shadow service over MQTT - * - * This will close the underlying TCP connection, MQTT connection will also be closed - * - * @param pClient MQTT Client used as the protocol layer - * @return An IoT Error Type defining successful/failed disconnect status - */ -IoT_Error_t aws_iot_shadow_disconnect(AWS_IoT_Client *pClient); - -/** - * @brief Thing Shadow Acknowledgment enum - * - * This enum type is use in the callback for the action response - * - */ -typedef enum { - SHADOW_ACK_TIMEOUT, SHADOW_ACK_REJECTED, SHADOW_ACK_ACCEPTED -} Shadow_Ack_Status_t; - -/** - * @brief Thing Shadow Action type enum - * - * This enum type is use in the callback for the action response - * - */ -typedef enum { - SHADOW_GET, SHADOW_UPDATE, SHADOW_DELETE -} ShadowActions_t; - - -/** - * @brief Function Pointer typedef used as the callback for every action - * - * This function will be called from the context of \c aws_iot_shadow_yield() context - * - * @param pThingName Thing Name of the response received - * @param action The response of the action - * @param status Informs if the action was Accepted/Rejected or Timed out - * @param pReceivedJsonDocument Received JSON document - * @param pContextData the void* data passed in during the action call(update, get or delete) - * - */ -typedef void (*fpActionCallback_t)(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData); - -/** - * @brief This function is the one used to perform an Update action to a Thing Name's Shadow. - * - * update is one of the most frequently used functionality by a device. In most cases the device may be just reporting few params to update the thing shadow in the cloud - * Update Action if no callback or if the JSON document does not have a client token then will just publish the update and not track it. - * - * @note The update has to subscribe to two topics update/accepted and update/rejected. This function waits 2 seconds to ensure the subscriptions are registered before publishing the update message. - * The following steps are performed on using this function: - * 1. Subscribe to Shadow topics - $aws/things/{thingName}/shadow/update/accepted and $aws/things/{thingName}/shadow/update/rejected - * 2. wait for 2 seconds for the subscription to take effect - * 3. Publish on the update topic - $aws/things/{thingName}/shadow/update - * 4. In the \c aws_iot_shadow_yield() function the response will be handled. In case of timeout or if the response is received, the subscription to shadow response topics are un-subscribed from. - * On the contrary if the persistent subscription is set to true then the un-subscribe will not be done. The topics will always be listened to. - * - * @param pClient MQTT Client used as the protocol layer - * @param pThingName Thing Name of the shadow that needs to be Updated - * @param pJsonString The update action expects a JSON document to send. The JSON String should be a null terminated string. This JSON document should adhere to the AWS IoT Thing Shadow specification. To help in the process of creating this document- SDK provides apis in \c aws_iot_shadow_json_data.h - * @param callback This is the callback that will be used to inform the caller of the response from the AWS IoT Shadow service.Callback could be set to NULL if response is not important - * @param pContextData This is an extra parameter that could be passed along with the callback. It should be set to NULL if not used - * @param timeout_seconds It is the time the SDK will wait for the response on either accepted/rejected before declaring timeout on the action - * @param isPersistentSubscribe As mentioned above, every time if a device updates the same shadow then this should be set to true to avoid repeated subscription and unsubscription. If the Thing Name is one off update then this should be set to false - * @return An IoT Error Type defining successful/failed update action - */ -IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingName, char *pJsonString, - fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, - bool isPersistentSubscribe); - -/** - * @brief This function is the one used to perform an Get action to a Thing Name's Shadow. - * - * One use of this function is usually to get the config of a device at boot up. - * It is similar to the Update function internally except it does not take a JSON document as the input. The entire JSON document will be sent over the accepted topic - * - * @param pClient MQTT Client used as the protocol layer - * @param pThingName Thing Name of the JSON document that is needed - * @param callback This is the callback that will be used to inform the caller of the response from the AWS IoT Shadow service.Callback could be set to NULL if response is not important - * @param pContextData This is an extra parameter that could be passed along with the callback. It should be set to NULL if not used - * @param timeout_seconds It is the time the SDK will wait for the response on either accepted/rejected before declaring timeout on the action - * @param isPersistentSubscribe As mentioned above, every time if a device gets the same Sahdow (JSON document) then this should be set to true to avoid repeated subscription and un-subscription. If the Thing Name is one off get then this should be set to false - * @return An IoT Error Type defining successful/failed get action - */ -IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe); - -/** - * @brief This function is the one used to perform an Delete action to a Thing Name's Shadow. - * - * This is not a very common use case for device. It is generally the responsibility of the accompanying app to do the delete. - * It is similar to the Update function internally except it does not take a JSON document as the input. The Thing Shadow referred by the ThingName will be deleted. - * - * @param pClient MQTT Client used as the protocol layer - * @param pThingName Thing Name of the Shadow that should be deleted - * @param callback This is the callback that will be used to inform the caller of the response from the AWS IoT Shadow service.Callback could be set to NULL if response is not important - * @param pContextData This is an extra parameter that could be passed along with the callback. It should be set to NULL if not used - * @param timeout_seconds It is the time the SDK will wait for the response on either accepted/rejected before declaring timeout on the action - * @param isPersistentSubscribe As mentioned above, every time if a device deletes the same Shadow (JSON document) then this should be set to true to avoid repeated subscription and un-subscription. If the Thing Name is one off delete then this should be set to false - * @return An IoT Error Type defining successful/failed delete action - */ -IoT_Error_t aws_iot_shadow_delete(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscriptions); - -/** - * @brief This function is used to listen on the delta topic of #AWS_IOT_MY_THING_NAME mentioned in the aws_iot_config.h file. - * - * Any time a delta is published the Json document will be delivered to the pStruct->cb. If you don't want the parsing done by the SDK then use the jsonStruct_t key set to "state". A good example of this is displayed in the sample_apps/shadow_console_echo.c - * - * @param pClient MQTT Client used as the protocol layer - * @param pStruct The struct used to parse JSON value - * @return An IoT Error Type defining successful/failed delta registering - */ -IoT_Error_t aws_iot_shadow_register_delta(AWS_IoT_Client *pClient, jsonStruct_t *pStruct); - -/** - * @brief Reset the last received version number to zero. - * This will be useful if the Thing Shadow is deleted and would like to to reset the local version - * @return no return values - * - */ -void aws_iot_shadow_reset_last_received_version(void); - -/** - * @brief Version of a document is received with every accepted/rejected and the SDK keeps track of the last received version of the JSON document of #AWS_IOT_MY_THING_NAME shadow - * - * One exception to this version tracking is that, the SDK will ignore the version from update/accepted topic. Rest of the responses will be scanned to update the version number. - * Accepting version change for update/accepted may cause version conflicts for delta message if the update message is received before the delta. - * - * @return version number of the last received response - * - */ -uint32_t aws_iot_shadow_get_last_received_version(void); - -/** - * @brief Enable the ignoring of delta messages with old version number - * - * As we use MQTT underneath, there could be more than 1 of the same message if we use QoS 0. To avoid getting called for the same message, this functionality should be enabled. All the old message will be ignored - */ -void aws_iot_shadow_enable_discard_old_delta_msgs(void); - -/** - * @brief Disable the ignoring of delta messages with old version number - */ -void aws_iot_shadow_disable_discard_old_delta_msgs(void); - -/** - * @brief This function is used to enable or disable autoreconnect - * - * Any time a disconnect happens the underlying MQTT client attempts to reconnect if this is set to true - * - * @param pClient MQTT Client used as the protocol layer - * @param newStatus The new status to set the autoreconnect option to - * - * @return An IoT Error Type defining successful/failed operation - */ -IoT_Error_t aws_iot_shadow_set_autoreconnect_status(AWS_IoT_Client *pClient, bool newStatus); - -#ifdef __cplusplus -} -#endif - -#endif //AWS_IOT_SDK_SRC_IOT_SHADOW_H_ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h deleted file mode 100644 index 748ff0884..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -#ifndef AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_ -#define AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include "aws_iot_error.h" -#include "aws_iot_shadow_json_data.h" - -bool isJsonValidAndParse(const char *pJsonDocument, size_t jsonSize, void *pJsonHandler, int32_t *pTokenCount); - -bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, - jsonStruct_t *pDataStruct, uint32_t *pDataLength, int32_t *pDataPosition); - -IoT_Error_t aws_iot_shadow_internal_get_request_json(char *pBuffer, size_t bufferSize); - -IoT_Error_t aws_iot_shadow_internal_delete_request_json(char *pBuffer, size_t bufferSize); - -void resetClientTokenSequenceNum(void); - - -bool isReceivedJsonValid(const char *pJsonDocument, size_t jsonSize); - -bool extractClientToken(const char *pJsonDocument, size_t jsonSize, char *pExtractedClientToken, size_t clientTokenSize); - -bool extractVersionNumber(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, uint32_t *pVersionNumber); - -#ifdef __cplusplus -} -#endif - -#endif // AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h deleted file mode 100644 index e2c61ac51..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file aws_iot_shadow_json_data.h - * @brief This file is the interface for all the Shadow related JSON functions. - */ - -#include - -/** - * @brief This is a static JSON object that could be used in code - * - */ -typedef struct jsonStruct jsonStruct_t; - -/** - * @brief Every JSON name value can have a callback. The callback should follow this signature - */ -typedef void (*jsonStructCallback_t)(const char *pJsonValueBuffer, uint32_t valueLength, jsonStruct_t *pJsonStruct_t); - -/** - * @brief All the JSON object types enum - * - * JSON number types need to be split into proper integer / floating point data types and sizes on embedded platforms. - */ -typedef enum { - SHADOW_JSON_INT32, - SHADOW_JSON_INT16, - SHADOW_JSON_INT8, - SHADOW_JSON_UINT32, - SHADOW_JSON_UINT16, - SHADOW_JSON_UINT8, - SHADOW_JSON_FLOAT, - SHADOW_JSON_DOUBLE, - SHADOW_JSON_BOOL, - SHADOW_JSON_STRING, - SHADOW_JSON_OBJECT -} JsonPrimitiveType; - -/** - * @brief This is the struct form of a JSON Key value pair - */ -struct jsonStruct { - const char *pKey; ///< JSON key - void *pData; ///< pointer to the data (JSON value) - size_t dataLength; ///< Length (in bytes) of pData - JsonPrimitiveType type; ///< type of JSON - jsonStructCallback_t cb; ///< callback to be executed on receiving the Key value pair -}; - -/** - * @brief Initialize the JSON document with Shadow expected name/value - * - * This Function will fill the JSON Buffer with a null terminated string. Internally it uses snprintf - * This function should always be used First, followed by iot_shadow_add_reported and/or iot_shadow_add_desired. - * Always finish the call sequence with iot_finalize_json_document - * - * @note Ensure the size of the Buffer is enough to hold the entire JSON Document. - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_shadow_init_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument); - -/** - * @brief Add the reported section of the JSON document of jsonStruct_t - * - * This is a variadic function and please be careful with the usage. count is the number of jsonStruct_t types that you would like to add in the reported section - * This function will add "reported":{} - * - * @note Ensure the size of the Buffer is enough to hold the reported section + the init section. Always use the same JSON document buffer used in the iot_shadow_init_json_document function. This function will accommodate the size of previous null terminated string, so pass teh max size of the buffer - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @param count total number of arguments(jsonStruct_t object) passed in the arguments - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_shadow_add_reported(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...); - -/** - * @brief Add the desired section of the JSON document of jsonStruct_t - * - * This is a variadic function and please be careful with the usage. count is the number of jsonStruct_t types that you would like to add in the reported section - * This function will add "desired":{} - * - * @note Ensure the size of the Buffer is enough to hold the reported section + the init section. Always use the same JSON document buffer used in the iot_shadow_init_json_document function. This function will accommodate the size of previous null terminated string, so pass the max size of the buffer - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @param count total number of arguments(jsonStruct_t object) passed in the arguments - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_shadow_add_desired(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...); - -/** - * @brief Finalize the JSON document with Shadow expected client Token. - * - * This function will automatically increment the client token every time this function is called. - * - * @note Ensure the size of the Buffer is enough to hold the entire JSON Document. If the finalized section is not invoked then the JSON doucment will not be valid - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_finalize_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument); - -/** - * @brief Fill the given buffer with client token for tracking the Repsonse. - * - * This function will add the AWS_IOT_MQTT_CLIENT_ID with a sequence number. Every time this function is used the sequence number gets incremented - * - * - * @param pBufferToBeUpdatedWithClientToken buffer to be updated with the client token string - * @param maxSizeOfJsonDocument maximum size of the pBufferToBeUpdatedWithClientToken that can be used - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ - -IoT_Error_t aws_iot_fill_with_client_token(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h deleted file mode 100644 index 075a726da..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_KEY_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_KEY_H_ - -#define SHADOW_CLIENT_TOKEN_STRING "clientToken" -#define SHADOW_VERSION_STRING "version" - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_KEY_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h deleted file mode 100644 index fc2de0322..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "aws_iot_shadow_interface.h" -#include "aws_iot_config.h" - - -extern uint32_t shadowJsonVersionNum; -extern bool shadowDiscardOldDeltaFlag; - -extern char myThingName[MAX_SIZE_OF_THING_NAME]; -extern uint16_t myThingNameLen; -extern char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; -extern uint16_t mqttClientIDLen; - -void initializeRecords(AWS_IoT_Client *pClient); -bool isSubscriptionPresent(const char *pThingName, ShadowActions_t action); -IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t action, bool isSticky); -void incrementSubscriptionCnt(const char *pThingName, ShadowActions_t action, bool isSticky); - -IoT_Error_t publishToShadowAction(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent); -void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action, - const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext, - uint32_t timeout_seconds); -bool getNextFreeIndexOfAckWaitList(uint8_t *pIndex); -void HandleExpiredResponseCallbacks(void); -void initDeltaTokens(void); -IoT_Error_t registerJsonTokenOnDelta(jsonStruct_t *pStruct); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h deleted file mode 100644 index 873949b07..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_version.h - * @brief Constants defining the release version of the SDK. - * - * This file contains constants defining the release version of the SDK. - * This file is modified by AWS upon release of the SDK and should not be - * modified by the consumer of the SDK. The provided samples show example - * usage of these constants. - * - * Versioning of the SDK follows the MAJOR.MINOR.PATCH Semantic Versioning guidelines. - * @see http://semver.org/ - */ -#ifndef SRC_UTILS_AWS_IOT_VERSION_H_ -#define SRC_UTILS_AWS_IOT_VERSION_H_ - -/** - * @brief MAJOR version, incremented when incompatible API changes are made. - */ -#define VERSION_MAJOR 3 -/** - * @brief MINOR version when functionality is added in a backwards-compatible manner. - */ -#define VERSION_MINOR 0 -/** - * @brief PATCH version when backwards-compatible bug fixes are made. - */ -#define VERSION_PATCH 1 -/** - * @brief TAG is an (optional) tag appended to the version if a more descriptive verion is needed. - */ -#define VERSION_TAG "" - -#endif /* SRC_UTILS_AWS_IOT_VERSION_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/network_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/network_interface.h deleted file mode 100644 index cf2834106..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/network_interface.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file network_interface.h - * @brief Network interface definition for MQTT client. - * - * Defines an interface to the TLS layer to be used by the MQTT client. - * Starting point for porting the SDK to the networking layer of a new platform. - */ - -#ifndef __NETWORK_INTERFACE_H_ -#define __NETWORK_INTERFACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include "timer_interface.h" -#include "network_platform.h" - -/** - * @brief Network Type - * - * Defines a type for the network struct. See structure definition below. - */ -typedef struct Network Network; - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct { - char *pRootCALocation; ///< Pointer to string containing the filename (including path) of the root CA file. - char *pDeviceCertLocation; ///< Pointer to string containing the filename (including path) of the device certificate. - char *pDevicePrivateKeyLocation; ///< Pointer to string containing the filename (including path) of the device private key file. - char *pDestinationURL; ///< Pointer to string containing the endpoint of the MQTT service. - uint16_t DestinationPort; ///< Integer defining the connection port of the MQTT service. - uint32_t timeout_ms; ///< Unsigned integer defining the TLS handshake timeout value in milliseconds. - bool ServerVerificationFlag; ///< Boolean. True = perform server certificate hostname validation. False = skip validation \b NOT recommended. -} TLSConnectParams; - -/** - * @brief Network Structure - * - * Structure for defining a network connection. - */ -struct Network { - IoT_Error_t (*connect)(Network *, TLSConnectParams *); - - IoT_Error_t (*read)(Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to read from the network - IoT_Error_t (*write)(Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to write to the network - IoT_Error_t (*disconnect)(Network *); ///< Function pointer pointing to the network function to disconnect from the network - IoT_Error_t (*isConnected)(Network *); ///< Function pointer pointing to the network function to check if TLS is connected - IoT_Error_t (*destroy)(Network *); ///< Function pointer pointing to the network function to destroy the network object - - TLSConnectParams tlsConnectParams; ///< TLSConnect params structure containing the common connection parameters - TLSDataParams tlsDataParams; ///< TLSData params structure containing the connection data parameters that are specific to the library being used -}; - -/** - * @brief Initialize the TLS implementation - * - * Perform any initialization required by the TLS layer. - * Connects the interface to implementation by setting up - * the network layer function pointers to platform implementations. - * - * @param pNetwork - Pointer to a Network struct defining the network interface. - * @param pRootCALocation - Path of the location of the Root CA - * @param pDeviceCertLocation - Path to the location of the Device Cert - * @param pDevicyPrivateKeyLocation - Path to the location of the device private key file - * @param pDestinationURL - The target endpoint to connect to - * @param DestinationPort - The port on the target to connect to - * @param timeout_ms - The value to use for timeout of operation - * @param ServerVerificationFlag - used to decide whether server verification is needed or not - * - * @return IoT_Error_t - successful initialization or TLS error - */ -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t DestinationPort, uint32_t timeout_ms, bool ServerVerificationFlag); - -/** - * @brief Create a TLS socket and open the connection - * - * Creates an open socket connection including TLS handshake. - * - * @param pNetwork - Pointer to a Network struct defining the network interface. - * @param TLSParams - TLSConnectParams defines the properties of the TLS connection. - * @return IoT_Error_t - successful connection or TLS error - */ -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *TLSParams); - -/** - * @brief Write bytes to the network socket - * - * @param Network - Pointer to a Network struct defining the network interface. - * @param unsigned char pointer - buffer to write to socket - * @param integer - number of bytes to write - * @param Timer * - operation timer - * @return integer - number of bytes written or TLS error - * @return IoT_Error_t - successful write or TLS error code - */ -IoT_Error_t iot_tls_write(Network *, unsigned char *, size_t, Timer *, size_t *); - -/** - * @brief Read bytes from the network socket - * - * @param Network - Pointer to a Network struct defining the network interface. - * @param unsigned char pointer - pointer to buffer where read bytes should be copied - * @param size_t - number of bytes to read - * @param Timer * - operation timer - * @param size_t - pointer to store number of bytes read - * @return IoT_Error_t - successful read or TLS error code - */ -IoT_Error_t iot_tls_read(Network *, unsigned char *, size_t, Timer *, size_t *); - -/** - * @brief Disconnect from network socket - * - * @param Network - Pointer to a Network struct defining the network interface. - * @return IoT_Error_t - successful read or TLS error code - */ -IoT_Error_t iot_tls_disconnect(Network *pNetwork); - -/** - * @brief Perform any tear-down or cleanup of TLS layer - * - * Called to cleanup any resources required for the TLS layer. - * - * @param Network - Pointer to a Network struct defining the network interface - * @return IoT_Error_t - successful cleanup or TLS error code - */ -IoT_Error_t iot_tls_destroy(Network *pNetwork); - -/** - * @brief Check if TLS layer is still connected - * - * Called to check if the TLS layer is still connected or not. - * - * @param Network - Pointer to a Network struct defining the network interface - * @return IoT_Error_t - TLS error code indicating status of network physical layer connection - */ -IoT_Error_t iot_tls_is_connected(Network *pNetwork); - -#ifdef __cplusplus -} -#endif - -#endif //__NETWORK_INTERFACE_H_ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h deleted file mode 100644 index b4bc3705d..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file threads_interface.h - * @brief Thread interface definition for MQTT client. - * - * Defines an interface that can be used by system components for multithreaded situations. - * Starting point for porting the SDK to the threading hardware layer of a new platform. - */ - -#include "aws_iot_config.h" - -#ifdef _ENABLE_THREAD_SUPPORT_ -#ifndef __THREADS_INTERFACE_H_ -#define __THREADS_INTERFACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The platform specific timer header that defines the Timer struct - */ -#include "threads_platform.h" - -#include - -/** - * @brief Mutex Type - * - * Forward declaration of a mutex struct. The definition of this struct is - * platform dependent. When porting to a new platform add this definition - * in "threads_platform.h". - * - */ -typedef struct _IoT_Mutex_t IoT_Mutex_t; - -/** - * @brief Initialize the provided mutex - * - * Call this function to initialize the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be initialized - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *); - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change - * This is a blocking call. - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *); - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change. - * This is not a blocking call. - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *); - -/** - * @brief Unlock the provided mutex - * - * Call this function to unlock the mutex before performing a state change - * - * @param IoT_Mutex_t - pointer to the mutex to be unlocked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *); - -/** - * @brief Destroy the provided mutex - * - * Call this function to destroy the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be destroyed - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *); - -#ifdef __cplusplus -} -#endif - -#endif /*__THREADS_INTERFACE_H_*/ -#endif /*_ENABLE_THREAD_SUPPORT_*/ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h deleted file mode 100644 index 0bef0fc94..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Allan Stockdill-Mander - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file timer_interface.h - * @brief Timer interface definition for MQTT client. - * - * Defines an interface to timers that can be used by other system - * components. MQTT client requires timers to handle timeouts and - * MQTT keep alive. - * Starting point for porting the SDK to the timer hardware layer of a new platform. - */ - -#ifndef __TIMER_INTERFACE_H_ -#define __TIMER_INTERFACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The platform specific timer header that defines the Timer struct - */ -#include "timer_platform.h" - -#include -#include - -/** - * @brief Timer Type - * - * Forward declaration of a timer struct. The definition of this struct is - * platform dependent. When porting to a new platform add this definition - * in "timer_.h" and include that file above. - * - */ -typedef struct Timer Timer; - -/** - * @brief Check if a timer is expired - * - * Call this function passing in a timer to check if that timer has expired. - * - * @param Timer - pointer to the timer to be checked for expiration - * @return bool - true = timer expired, false = timer not expired - */ -bool has_timer_expired(Timer *); - -/** - * @brief Create a timer (milliseconds) - * - * Sets the timer to expire in a specified number of milliseconds. - * - * @param Timer - pointer to the timer to be set to expire in milliseconds - * @param uint32_t - set the timer to expire in this number of milliseconds - */ -void countdown_ms(Timer *, uint32_t); - -/** - * @brief Create a timer (seconds) - * - * Sets the timer to expire in a specified number of seconds. - * - * @param Timer - pointer to the timer to be set to expire in seconds - * @param uint32_t - set the timer to expire in this number of seconds - */ -void countdown_sec(Timer *, uint32_t); - -/** - * @brief Check the time remaining on a given timer - * - * Checks the input timer and returns the number of milliseconds remaining on the timer. - * - * @param Timer - pointer to the timer to be set to checked - * @return int - milliseconds left on the countdown timer - */ -uint32_t left_ms(Timer *); - -/** - * @brief Initialize a timer - * - * Performs any initialization required to the timer passed in. - * - * @param Timer - pointer to the timer to be initialized - */ -void init_timer(Timer *); - -#ifdef __cplusplus -} -#endif - -#endif //__TIMER_INTERFACE_H_ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c deleted file mode 100644 index d7cc204bd..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file timer.c - * @brief Linux implementation of the timer interface. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include - -#include "timer_platform.h" - -bool has_timer_expired(Timer *timer) { - struct timeval now, res; - gettimeofday(&now, NULL); - timersub(&timer->end_time, &now, &res); - return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0); -} - -void countdown_ms(Timer *timer, uint32_t timeout) { - struct timeval now; -#ifdef __cplusplus - struct timeval interval = {timeout / 1000, static_cast((timeout % 1000) * 1000)}; -#else - struct timeval interval = {timeout / 1000, (int)((timeout % 1000) * 1000)}; -#endif - gettimeofday(&now, NULL); - timeradd(&now, &interval, &timer->end_time); -} - -uint32_t left_ms(Timer *timer) { - struct timeval now, res; - uint32_t result_ms = 0; - gettimeofday(&now, NULL); - timersub(&timer->end_time, &now, &res); - if(res.tv_sec >= 0) { - result_ms = (uint32_t) (res.tv_sec * 1000 + res.tv_usec / 1000); - } - return result_ms; -} - -void countdown_sec(Timer *timer, uint32_t timeout) { - struct timeval now; - struct timeval interval = {timeout, 0}; - gettimeofday(&now, NULL); - timeradd(&now, &interval, &timer->end_time); -} - -void init_timer(Timer *timer) { - timer->end_time = (struct timeval) {0, 0}; -} - -void delay(unsigned milliseconds) -{ - useconds_t sleepTime = (useconds_t)(milliseconds * 1000); - - usleep(sleepTime); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h deleted file mode 100644 index d381447e0..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ -#define SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file timer_platform.h - */ -#include -#include -#include "timer_interface.h" - -/** - * definition of the Timer struct. Platform specific - */ -struct Timer { - struct timeval end_time; -}; - -/** - * @brief Delay (sleep) for the specified number of milliseconds. - * - * @param milliseconds The number of milliseconds to sleep. - */ -void delay(unsigned milliseconds); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c deleted file mode 100644 index a91d4aa61..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "aws_iot_config.h" - -#include -#include - -#include "aws_iot_error.h" -#include "aws_iot_log.h" -#include "network_interface.h" -#include "network_platform.h" - - -/* This is the value used for ssl read timeout */ -#ifndef IOT_SSL_READ_TIMEOUT_MS - #define IOT_SSL_READ_TIMEOUT_MS 3 -#endif - -/* When this much time has elapsed after receiving MBEDTLS_ERR_SSL_WANT_READ - * or MBEDTLS_ERR_SSL_WANT_WRITE, then iot_tls_write will return - * NETWORK_SSL_WRITE_TIMEOUT_ERROR. */ -#ifndef IOT_SSL_WRITE_RETRY_TIMEOUT_MS - #define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 -#endif - -/* When this much time has elapsed after receiving MBEDTLS_ERR_SSL_WANT_READ, - * MBEDTLS_ERR_SSL_WANT_WRITE, or MBEDTLS_ERR_SSL_TIMEOUT, then iot_tls_read - * will return NETWORK_SSL_READ_TIMEOUT_ERROR. */ -#ifndef IOT_SSL_READ_RETRY_TIMEOUT_MS - #define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 -#endif - -/* This defines the value of the debug buffer that gets allocated. - * The value can be altered based on memory constraints - */ -#ifdef ENABLE_IOT_DEBUG -#define MBEDTLS_DEBUG_BUFFER_SIZE 2048 -#endif - -/* - * This is a function to do further verification if needed on the cert received - */ - -static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { - char buf[1024]; - ((void) data); - - IOT_DEBUG("\nVerify requested for (Depth %d):\n", depth); - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); - IOT_DEBUG("%s", buf); - - if((*flags) == 0) { - IOT_DEBUG(" This certificate has no flags\n"); - } else { - IOT_DEBUG(buf, sizeof(buf), " ! ", *flags); - IOT_DEBUG("%s\n", buf); - } - - return 0; -} - -void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - pNetwork->tlsConnectParams.DestinationPort = destinationPort; - pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; - pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; - pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; - pNetwork->tlsConnectParams.timeout_ms = timeout_ms; - pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; -} - -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, - pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); - - pNetwork->connect = iot_tls_connect; - pNetwork->read = iot_tls_read; - pNetwork->write = iot_tls_write; - pNetwork->disconnect = iot_tls_disconnect; - pNetwork->isConnected = iot_tls_is_connected; - pNetwork->destroy = iot_tls_destroy; - - pNetwork->tlsDataParams.flags = 0; - - return SUCCESS; -} - -IoT_Error_t iot_tls_is_connected(Network *pNetwork) { - /* Use this to add implementation which can check for physical layer disconnect */ - return NETWORK_PHYSICAL_LAYER_CONNECTED; -} - -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { - int ret = 0; - const char *pers = "aws_iot_tls_wrapper"; - TLSDataParams *tlsDataParams = NULL; - char portBuffer[6]; - char vrfy_buf[512]; - const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; - -#ifdef ENABLE_IOT_DEBUG - unsigned char buf[MBEDTLS_DEBUG_BUFFER_SIZE]; -#endif - - if(NULL == pNetwork) { - return NULL_VALUE_ERROR; - } - - if(NULL != params) { - _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, - params->pDevicePrivateKeyLocation, params->pDestinationURL, - params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); - } - - tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_init(&(tlsDataParams->server_fd)); - mbedtls_ssl_init(&(tlsDataParams->ssl)); - mbedtls_ssl_config_init(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); - mbedtls_x509_crt_init(&(tlsDataParams->cacert)); - mbedtls_x509_crt_init(&(tlsDataParams->clicert)); - mbedtls_pk_init(&(tlsDataParams->pkey)); - - IOT_DEBUG("\n . Seeding the random number generator..."); - mbedtls_entropy_init(&(tlsDataParams->entropy)); - if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), - (const unsigned char *) pers, strlen(pers))) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); - return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; - } - - IOT_DEBUG(" . Loading the CA root certificate ..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); - if(ret < 0) { - IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret); - return NETWORK_X509_ROOT_CRT_PARSE_ERROR; - } - IOT_DEBUG(" ok (%d skipped)\n", ret); - - IOT_DEBUG(" . Loading the client cert. and key..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation); - if(ret != 0) { - IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret); - return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; - } - - ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, ""); - if(ret != 0) { - IOT_ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret); - IOT_DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation); - return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; - } - IOT_DEBUG(" ok\n"); - snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); - IOT_DEBUG(" . Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); - if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, - portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret); - switch(ret) { - case MBEDTLS_ERR_NET_SOCKET_FAILED: - return NETWORK_ERR_NET_SOCKET_FAILED; - case MBEDTLS_ERR_NET_UNKNOWN_HOST: - return NETWORK_ERR_NET_UNKNOWN_HOST; - case MBEDTLS_ERR_NET_CONNECT_FAILED: - default: - return NETWORK_ERR_NET_CONNECT_FAILED; - }; - } - - ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); - if(ret != 0) { - IOT_ERROR(" failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } IOT_DEBUG(" ok\n"); - - IOT_DEBUG(" . Setting up the SSL/TLS structure..."); - if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); - } else { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); - } - mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); - - mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); - if((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey))) != - 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); - - /* Use the AWS IoT ALPN extension for MQTT if port 443 is requested. */ - if(443 == pNetwork->tlsConnectParams.DestinationPort) { - if((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_conf_alpn_protocols returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } - } - - /* Assign the resulting configuration to the SSL context. */ - if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } - if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); - return SSL_CONNECTION_ERROR; - } - IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); - mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, - mbedtls_net_recv_timeout); - IOT_DEBUG(" ok\n"); - - IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); - IOT_DEBUG(" . Performing the SSL/TLS handshake..."); - while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - IOT_ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret); - if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - IOT_ERROR(" Unable to verify the server's certificate. " - "Either it is invalid,\n" - " or you didn't set ca_file or ca_path " - "to an appropriate value.\n" - " Alternatively, you may want to use " - "auth_mode=optional for testing purposes.\n"); - } - return SSL_CONNECTION_ERROR; - } - } - - IOT_DEBUG(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), - mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); - if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { - IOT_DEBUG(" [ Record expansion is %d ]\n", ret); - } else { - IOT_DEBUG(" [ Record expansion is unknown (compression) ]\n"); - } - - IOT_DEBUG(" . Verifying peer X.509 certificate..."); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { - IOT_ERROR(" failed\n"); - mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", tlsDataParams->flags); - IOT_ERROR("%s\n", vrfy_buf); - ret = SSL_CONNECTION_ERROR; - } else { - IOT_DEBUG(" ok\n"); - ret = SUCCESS; - } - } else { - IOT_DEBUG(" Server Verification skipped\n"); - ret = SUCCESS; - } - -#ifdef ENABLE_IOT_DEBUG - if(mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { - IOT_DEBUG(" . Peer certificate information ...\n"); - mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); - IOT_DEBUG("%s\n", buf); - } -#endif - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), IOT_SSL_READ_TIMEOUT_MS); - -#ifdef IOT_SSL_SOCKET_NON_BLOCKING - mbedtls_net_set_nonblock(&(tlsDataParams->server_fd)); -#endif - - return (IoT_Error_t) ret; -} - -IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) { - mbedtls_ssl_context *pSsl = &(pNetwork->tlsDataParams.ssl); - size_t txLen = 0U; - int ret = 0; - /* This timer checks for a timeout whenever MBEDTLS_ERR_SSL_WANT_READ - * or MBEDTLS_ERR_SSL_WANT_WRITE are returned by mbedtls_ssl_write. - * Timeout is specified by IOT_SSL_WRITE_RETRY_TIMEOUT_MS. */ - Timer writeTimer; - - /* This variable is unused */ - (void) timer; - - /* The timer must be started in case no bytes are written on the first try */ - init_timer(&writeTimer); - countdown_ms(&writeTimer, IOT_SSL_WRITE_RETRY_TIMEOUT_MS); - - while(len > 0U) { - ret = mbedtls_ssl_write(pSsl, pMsg, len); - - if(ret > 0) { - if((size_t) ret > len) { - IOT_ERROR("More bytes written than requested\n\n"); - return NETWORK_SSL_WRITE_ERROR; - } - - /* Successfully sent data, so reset the timeout */ - init_timer(&writeTimer); - countdown_ms(&writeTimer, IOT_SSL_WRITE_RETRY_TIMEOUT_MS); - - txLen += ret; - pMsg += ret; - len -= ret; - } else if(ret == MBEDTLS_ERR_SSL_WANT_READ || - ret == MBEDTLS_ERR_SSL_WANT_WRITE) { - if(has_timer_expired(&writeTimer)) { - *written_len = txLen; - return NETWORK_SSL_WRITE_TIMEOUT_ERROR; - } - } else { - IOT_ERROR(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", (unsigned int) -ret); - /* All other negative return values indicate connection needs to be reset. - * Will be caught in ping request so ignored here */ - return NETWORK_SSL_WRITE_ERROR; - } - } - - *written_len = txLen; - return SUCCESS; -} - -IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) { - mbedtls_ssl_context *pSsl = &(pNetwork->tlsDataParams.ssl); - size_t rxLen = 0U; - int ret; - /* This timer checks for a timeout whenever MBEDTLS_ERR_SSL_WANT_READ, - * MBEDTLS_ERR_SSL_WANT_WRITE, or MBEDTLS_ERR_SSL_TIMEOUT are returned by - * mbedtls_ssl_read. Timeout is specified by IOT_SSL_READ_RETRY_TIMEOUT_MS. */ - Timer readTimer; - - /* This variable is unused */ - (void) timer; - - /* The timer must be started in case no bytes are read on the first try */ - init_timer(&readTimer); - countdown_ms(&readTimer, IOT_SSL_READ_RETRY_TIMEOUT_MS); - - while(len > 0U) { - /* This read will timeout after IOT_SSL_READ_TIMEOUT_MS if there's no data to be read */ - ret = mbedtls_ssl_read(pSsl, pMsg, len); - - if(ret > 0) { - if((size_t) ret > len) { - IOT_ERROR("More bytes read than requested\n\n"); - return NETWORK_SSL_WRITE_ERROR; - } - - /* Successfully received data, so reset the timeout */ - init_timer(&readTimer); - countdown_ms(&readTimer, IOT_SSL_READ_RETRY_TIMEOUT_MS); - - rxLen += ret; - pMsg += ret; - len -= ret; - } else if(ret == MBEDTLS_ERR_SSL_WANT_READ || - ret == MBEDTLS_ERR_SSL_WANT_WRITE || - ret == MBEDTLS_ERR_SSL_TIMEOUT) { - if(has_timer_expired(&readTimer)) { - *read_len = rxLen; - if(rxLen == 0U) { - return NETWORK_SSL_NOTHING_TO_READ; - } else { - return NETWORK_SSL_READ_TIMEOUT_ERROR; - } - } - } else { - IOT_ERROR("Failed\n ! mbedtls_ssl_read returned -0x%x\n\n", (unsigned int) -ret); - return NETWORK_SSL_READ_ERROR; - } - } - - *read_len = rxLen; - return SUCCESS; -} - -IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); - int ret = 0; - do { - ret = mbedtls_ssl_close_notify(ssl); - } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); - - /* All other negative return values indicate connection needs to be reset. - * No further action required since this is disconnect call */ - - return SUCCESS; -} - -IoT_Error_t iot_tls_destroy(Network *pNetwork) { - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_free(&(tlsDataParams->server_fd)); - - mbedtls_x509_crt_free(&(tlsDataParams->clicert)); - mbedtls_x509_crt_free(&(tlsDataParams->cacert)); - mbedtls_pk_free(&(tlsDataParams->pkey)); - mbedtls_ssl_free(&(tlsDataParams->ssl)); - mbedtls_ssl_config_free(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg)); - mbedtls_entropy_free(&(tlsDataParams->entropy)); - - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h deleted file mode 100644 index c2810a1c8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#include "mbedtls/config.h" - -#include "mbedtls/platform.h" -#include "mbedtls/net.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/certs.h" -#include "mbedtls/x509.h" -#include "mbedtls/error.h" -#include "mbedtls/debug.h" -#include "mbedtls/timing.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct _TLSDataParams { - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_context ssl; - mbedtls_ssl_config conf; - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - mbedtls_pk_context pkey; - mbedtls_net_context server_fd; -}TLSDataParams; - -#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#ifdef __cplusplus -} -#endif - -#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h deleted file mode 100644 index 8a520c637..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "threads_interface.h" -#ifdef _ENABLE_THREAD_SUPPORT_ -#ifndef IOTSDKC_THREADS_PLATFORM_H_H -#define IOTSDKC_THREADS_PLATFORM_H_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** - * @brief Mutex Type - * - * definition of the Mutex struct. Platform specific - * - */ -struct _IoT_Mutex_t { - pthread_mutex_t lock; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* IOTSDKC_THREADS_PLATFORM_H_H */ -#endif /* _ENABLE_THREAD_SUPPORT_ */ - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c deleted file mode 100644 index 65a310fb0..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "threads_platform.h" -#ifdef _ENABLE_THREAD_SUPPORT_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize the provided mutex - * - * Call this function to initialize the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be initialized - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *pMutex) { - if(0 != pthread_mutex_init(&(pMutex->lock), NULL)) { - return MUTEX_INIT_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change - * Blocking, thread will block until lock request fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *pMutex) { -int rc = pthread_mutex_lock(&(pMutex->lock)); - if(0 != rc) { - return MUTEX_LOCK_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Try to lock the provided mutex - * - * Call this function to attempt to lock the mutex before performing a state change - * Non-Blocking, immediately returns with failure if lock attempt fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *pMutex) { -int rc = pthread_mutex_trylock(&(pMutex->lock)); - if(0 != rc) { - return MUTEX_LOCK_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Unlock the provided mutex - * - * Call this function to unlock the mutex before performing a state change - * - * @param IoT_Mutex_t - pointer to the mutex to be unlocked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *pMutex) { - if(0 != pthread_mutex_unlock(&(pMutex->lock))) { - return MUTEX_UNLOCK_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Destroy the provided mutex - * - * Call this function to destroy the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be destroyed - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *pMutex) { - if(0 != pthread_mutex_destroy(&(pMutex->lock))) { - return MUTEX_DESTROY_ERROR; - } - - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif - -#endif /* _ENABLE_THREAD_SUPPORT_ */ - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/README.md deleted file mode 100644 index a0017f08a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Sample apps for the AWS IoT Device SDK for Embedded C - -All samples are written in C unless otherwise mentioned. The these sample apps are included in the SDK and described below. - * [`subscribe_publish_sample`](#subscribe-publish-sample) - demonstrates how to publish and subscribe to MQTT messages. - * [`subscribe_publish_library_sample`](#subscribe-publish-library-sample) - demonstrates how to create a library that provides support to publish and subscribe to MQTT messages. - - These sample apps are also provided in this SDK. - * [`shadow_sample`](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/master/samples/linux/shadow_sample) - demonstrates how to use a simple device shadow in a connected window example. - * [`shadow_sample_console_echo`](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/master/samples/linux/shadow_sample_console_echo) - demonstrates how to work with the AWS IoT Console interactive guide. - * [`jobs_sample`](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/master/samples/linux/jobs_sample) - demonstrates how to connect to the AWS IoT MQTT platform and perform several operations that use the basic capabilities of the AWS IoT Jobs platform. - -## Overview -This folder contains several samples that demonstrate various SDK functions. The Readme file also includes a walk-through of the subscribe publish sample to explain how the SDK is used. The samples are currently provided with Makefiles for building them on linux. For each sample: - - * Explore the makefile. The makefile for each sample provides a reference on how to set up makefiles for client applications - * Explore the example. It connects to AWS IoT platform using MQTT and demonstrates few actions that can be performed by the SDK - * Download certificate authority CA file from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem) and place in location referenced in the example (certs/) - * Ensure you have [created a thing](https://docs.aws.amazon.com/iot/latest/developerguide/create-thing.html) through your AWS IoT Console with name matching the definition AWS_IOT_MY_THING_NAME in the `aws_iot_config.h` file - * Place device identity cert and private key in locations referenced in the example (certs/) - * Ensure the names of the cert files are the same as in the `aws_iot_config.h` file - * Ensure the certificate has an attached policy which allows the proper permissions for AWS IoT - * Build the example using make (`make`) - * Run sample application (./subscribe_publish_sample or ./shadow_sample). The sample will print status messages to stdout - -## Subscribe Publish Sample -This is a simple pub/sub MQTT example. It connects a single MQTT client to the server and subscribes to a test topic. Then it proceeds to publish messages on this topic and yields after each publish to ensure that the message was received. - - * The sample first creates an instance of the AWS_IoT_Client - * The next step is to initialize the client. The aws_iot_mqtt_init API is called for this purpose. The API takes the client instance and an IoT_Client_Init_Params variable to set the initial values for the client. The Init params include values like host URL, port, certificates, disconnect handler etc. - * If the call to the init API was successful, we can proceed to call connect. The API is called aws_iot_mqtt_connect. It takes the client instance and IoT_Client_Connect_Params variable as arguments. The IoT_Client_Connect_Params is optional after the first call to connect as the client retains the original values that were provided to support reconnect. The Connect params include values like Client Id, MQTT Version etc. - * If the connect API call was successful, we can proceed to subscribe and publish on this connect. The connect API call will return an error code, specific to the type of error that occurred, in case the call fails. - * It is important to remember here that there is no dynamic memory allocation in the SDK. Any values that are passed as a pointer to the APIs should not be freed unless they are not required any further. For example, if the variable that stores the certificate path is freed after the init call is made, the connect call will fail. Similarly, if it is freed after the connect API returns success, any future connect calls (including reconnects) will fail. - * The next step for this sample is to subscribe to the test topic. The API to be called for subscribe is aws_iot_mqtt_subscribe. It takes as arguments, the IoT Client instance, topic name, the length of the topic name, QoS, the subscribe callback handler and an optional pointer to some data to be returned to the subscribe handler - * The next step it to call the publish API to send a message on the test topic. The sample sends two different messages, one QoS0 and one QoS1. The - * The publish API takes the client instance, topic name to publish to, topic name length and a variable of type IoT_Publish_Message_Params. The IoT_Publish_Message_Params contains the payload, length of the payload and QoS. - * If the publish API calls are successful, the sample proceeds to call the yield API. The yield API takes the client instance and a timeout value in milliseconds as arguments. - * The yield API is called to let the SDK process any incoming messages. It also periodically sends out the PING request to prevent disconnect and, if enabled, it also performs auto-reconnect and resubscribe. - * The yield API should be called periodically to process the PING request as well as read any messages in the receive buffer. It should be called once at least every TTL/2 time periods to ensure disconnect does not happen. There can only be one yield in progress at a time. Therefore, in multi-threaded scenarios one thread can be a dedicated yield thread while other threads handle other operations. - * The sample sends out messages equal to the value set in publish count unless infinite publishing flag is set - -For further information on each API please read the API documentation. - -## Subscribe Publish Library Sample -This is also the same code as the Subscribe Publish sample. In this case, the SDK is built as a separate library and then used in the sample program. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/Makefile deleted file mode 100644 index 4f74593b8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = jobs_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/sdk_config -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/aws_iot_config.h deleted file mode 100644 index 7bff6c89e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/aws_iot_config.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_JOBS_IOT_JOB_CONFIG_H_ -#define SRC_JOBS_IOT_JOB_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename - -// MQTT PubSub -#ifndef DISABLE_IOT_JOBS -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#else -#define AWS_IOT_MQTT_RX_BUF_LEN 2048 -#endif -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Shadow and Job common configs -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_SIZE_OF_THING_NAME 30 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER 512 ///< Maximum size of the SHADOW buffer to store the received Shadow message -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Job specific configs -#ifndef DISABLE_IOT_JOBS -#define MAX_SIZE_OF_JOB_ID 64 -#define MAX_JOB_JSON_TOKEN_EXPECTED 120 -#define MAX_SIZE_OF_JOB_REQUEST AWS_IOT_MQTT_TX_BUF_LEN - -#define MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME 40 -#define MAX_JOB_TOPIC_LENGTH_BYTES MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME + MAX_SIZE_OF_THING_NAME + MAX_SIZE_OF_JOB_ID + 2 -#endif - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_JOBS_IOT_JOB_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/jobs_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/jobs_sample.c deleted file mode 100644 index e79f25f7e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/jobs_sample.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * - * This example takes the parameters from the aws_iot_config.h file and establishes - * a connection to the AWS IoT MQTT Platform. It performs several operations to - * demonstrate the basic capabilities of the AWS IoT Jobs platform. - * - * If all the certs are correct, you should see the list of pending Job Executions - * printed out by the iot_get_pending_callback_handler. If there are any existing pending - * job executions each will be processed one at a time in the iot_next_job_callback_handler. - * After all of the pending jobs have been processed the program will wait for - * notifications for new pending jobs and process them one at a time as they come in. - * - * In the main body you can see how each callback is registered for each corresponding - * Jobs topic. - * - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_json_utils.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_jobs_interface.h" - -/** - * @brief Default cert location - */ -static char certDirectory[PATH_MAX + 1] = "../../../certs"; - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -static char HostAddress[255] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -static uint32_t port = AWS_IOT_MQTT_PORT; - -static jsmn_parser jsonParser; -static jsmntok_t jsonTokenStruct[MAX_JSON_TOKEN_EXPECTED]; -static int32_t tokenCount; - -static void iot_get_pending_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_GET_PENDING_TOPIC callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - jsmn_init(&jsonParser); - - tokenCount = jsmn_parse(&jsonParser, params->payload, (int) params->payloadLen, jsonTokenStruct, MAX_JSON_TOKEN_EXPECTED); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d", tokenCount); - return; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object"); - return; - } - - jsmntok_t *jobs; - - jobs = findToken("inProgressJobs", params->payload, jsonTokenStruct); - - if (jobs) { - IOT_INFO("inProgressJobs: %.*s", jobs->end - jobs->start, (char *)params->payload + jobs->start); - } - - jobs = findToken("queuedJobs", params->payload, jsonTokenStruct); - - if (jobs) { - IOT_INFO("queuedJobs: %.*s", jobs->end - jobs->start, (char *)params->payload + jobs->start); - } -} - -static void iot_next_job_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char topicToPublishUpdate[MAX_JOB_TOPIC_LENGTH_BYTES]; - char messageBuffer[200]; - - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_NOTIFY_NEXT_TOPIC / JOB_DESCRIBE_TOPIC($next) callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - jsmn_init(&jsonParser); - - tokenCount = jsmn_parse(&jsonParser, params->payload, (int) params->payloadLen, jsonTokenStruct, MAX_JSON_TOKEN_EXPECTED); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d", tokenCount); - return; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object"); - return; - } - - jsmntok_t *tokExecution; - - tokExecution = findToken("execution", params->payload, jsonTokenStruct); - - if (tokExecution) { - IOT_INFO("execution: %.*s", tokExecution->end - tokExecution->start, (char *)params->payload + tokExecution->start); - - jsmntok_t *tok; - - tok = findToken("jobId", params->payload, tokExecution); - - if (tok) { - IoT_Error_t rc; - char jobId[MAX_SIZE_OF_JOB_ID + 1]; - AwsIotJobExecutionUpdateRequest updateRequest; - - rc = parseStringValue(jobId, MAX_SIZE_OF_JOB_ID + 1, params->payload, tok); - if(SUCCESS != rc) { - IOT_ERROR("parseStringValue returned error : %d ", rc); - return; - } - - IOT_INFO("jobId: %s", jobId); - - tok = findToken("jobDocument", params->payload, tokExecution); - - /* - * Do your job processing here. - */ - - if (tok) { - IOT_INFO("jobDocument: %.*s", tok->end - tok->start, (char *)params->payload + tok->start); - /* Alternatively if the job still has more steps the status can be set to JOB_EXECUTION_IN_PROGRESS instead */ - updateRequest.status = JOB_EXECUTION_SUCCEEDED; - updateRequest.statusDetails = "{\"exampleDetail\":\"a value appropriate for your successful job\"}"; - } else { - updateRequest.status = JOB_EXECUTION_FAILED; - updateRequest.statusDetails = "{\"failureDetail\":\"Unable to process job document\"}"; - } - - updateRequest.expectedVersion = 0; - updateRequest.executionNumber = 0; - updateRequest.includeJobExecutionState = false; - updateRequest.includeJobDocument = false; - updateRequest.clientToken = NULL; - - rc = aws_iot_jobs_send_update(pClient, QOS0, AWS_IOT_MY_THING_NAME, jobId, &updateRequest, - topicToPublishUpdate, sizeof(topicToPublishUpdate), messageBuffer, sizeof(messageBuffer)); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_jobs_send_update returned error : %d ", rc); - return; - } - } - } else { - IOT_INFO("execution property not found, nothing to do"); - } -} - -static void iot_update_accepted_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_UPDATE_TOPIC / accepted callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); -} - -static void iot_update_rejected_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_UPDATE_TOPIC / rejected callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - /* Do error handling here for when the update was rejected */ -} - -static void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - IOT_WARN("MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - IOT_UNUSED(data); - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - IOT_WARN("Manual Reconnect Successful"); - } else { - IOT_WARN("Manual Reconnect Failed - %d", rc); - } - } -} - -int main(int argc, char **argv) { - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char cPayload[100]; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - mqttInitParams.pRootCALocation = rootCA; - mqttInitParams.pDeviceCertLocation = clientCRT; - mqttInitParams.pDevicePrivateKeyLocation = clientKey; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); - return rc; - } - - connectParams.keepAliveIntervalInSec = 600; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - IOT_INFO("Connecting..."); - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - return rc; - } - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - char topicToSubscribeGetPending[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeNotifyNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeGetNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeUpdateAccepted[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeUpdateRejected[MAX_JOB_TOPIC_LENGTH_BYTES]; - - char topicToPublishGetPending[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToPublishGetNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, NULL, JOB_GET_PENDING_TOPIC, JOB_WILDCARD_REPLY_TYPE, - iot_get_pending_callback_handler, NULL, topicToSubscribeGetPending, sizeof(topicToSubscribeGetPending)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_GET_PENDING_TOPIC: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, NULL, JOB_NOTIFY_NEXT_TOPIC, JOB_REQUEST_TYPE, - iot_next_job_callback_handler, NULL, topicToSubscribeNotifyNext, sizeof(topicToSubscribeNotifyNext)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_NOTIFY_NEXT_TOPIC: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_NEXT, JOB_DESCRIBE_TOPIC, JOB_WILDCARD_REPLY_TYPE, - iot_next_job_callback_handler, NULL, topicToSubscribeGetNext, sizeof(topicToSubscribeGetNext)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_DESCRIBE_TOPIC ($next): %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_WILDCARD, JOB_UPDATE_TOPIC, JOB_ACCEPTED_REPLY_TYPE, - iot_update_accepted_callback_handler, NULL, topicToSubscribeUpdateAccepted, sizeof(topicToSubscribeUpdateAccepted)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_UPDATE_TOPIC/accepted: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_WILDCARD, JOB_UPDATE_TOPIC, JOB_REJECTED_REPLY_TYPE, - iot_update_rejected_callback_handler, NULL, topicToSubscribeUpdateRejected, sizeof(topicToSubscribeUpdateRejected)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_UPDATE_TOPIC/rejected: %d ", rc); - return rc; - } - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - paramsQOS0.payloadLen = strlen(cPayload); - - rc = aws_iot_jobs_send_query(&client, QOS0, AWS_IOT_MY_THING_NAME, NULL, NULL, topicToPublishGetPending, sizeof(topicToPublishGetPending), NULL, 0, JOB_GET_PENDING_TOPIC); - if(SUCCESS != rc) { - IOT_ERROR("Error calling aws_iot_jobs_send_query: %d ", rc); - return rc; - } - - AwsIotDescribeJobExecutionRequest describeRequest; - describeRequest.executionNumber = 0; - describeRequest.includeJobDocument = true; - describeRequest.clientToken = NULL; - - rc = aws_iot_jobs_describe(&client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_NEXT, &describeRequest, topicToPublishGetNext, sizeof(topicToPublishGetNext), NULL, 0); - - while(SUCCESS == rc) { - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 50000); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile deleted file mode 100644 index 9483299fc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile +++ /dev/null @@ -1,72 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = shadow_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a - - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h deleted file mode 100644 index 81f9e39e8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c deleted file mode 100644 index 2a692c70c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file shadow_sample.c - * @brief A simple connected window example demonstrating the use of Thing Shadow - */ - -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" - -/*! - * The goal of this sample application is to demonstrate the capabilities of shadow. - * This device(say Connected Window) will open the window of a room based on temperature - * It can report to the Shadow the following parameters: - * 1. temperature of the room (double) - * 2. status of the window (open or close) - * It can act on commands from the cloud. In this case it will open or close the window based on the json object "windowOpen" data[open/close] - * - * The two variables from a device's perspective are double temperature and bool windowOpen - * The device needs to act on only on windowOpen variable, so we will create a primitiveJson_t object with callback - The Json Document in the cloud will be - { - "reported": { - "temperature": 0, - "windowOpen": false - }, - "desired": { - "windowOpen": false - } - } - */ - -#define ROOMTEMPERATURE_UPPERLIMIT 32.0f -#define ROOMTEMPERATURE_LOWERLIMIT 25.0f -#define STARTING_ROOMTEMPERATURE ROOMTEMPERATURE_LOWERLIMIT - -#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 - -static char certDirectory[PATH_MAX + 1] = "../../../certs"; -#define HOST_ADDRESS_SIZE 255 -static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST; -static uint32_t port = AWS_IOT_MQTT_PORT; -static uint8_t numPubs = 5; - -static void simulateRoomTemperature(float *pRoomTemperature) { - static float deltaChange; - - if(*pRoomTemperature >= ROOMTEMPERATURE_UPPERLIMIT) { - deltaChange = -0.5f; - } else if(*pRoomTemperature <= ROOMTEMPERATURE_LOWERLIMIT) { - deltaChange = 0.5f; - } - - *pRoomTemperature += deltaChange; -} - -static void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(action); - IOT_UNUSED(pReceivedJsonDocument); - IOT_UNUSED(pContextData); - - if(SHADOW_ACK_TIMEOUT == status) { - IOT_INFO("Update Timeout--"); - } else if(SHADOW_ACK_REJECTED == status) { - IOT_INFO("Update RejectedXX"); - } else if(SHADOW_ACK_ACCEPTED == status) { - IOT_INFO("Update Accepted !!"); - } -} - -static void windowActuate_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - IOT_UNUSED(pJsonString); - IOT_UNUSED(JsonStringDataLen); - - if(pContext != NULL) { - IOT_INFO("Delta - Window state changed to %d", *(bool *) (pContext->pData)); - } -} - -static void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:n:"))) { - switch(opt) { - case 'h': - strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("port %s", optarg); - break; - case 'c': - strncpy(certDirectory, optarg, PATH_MAX + 1); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'n': - numPubs = atoi(optarg); - IOT_DEBUG("num pubs %s", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("ERROR in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - IoT_Error_t rc = FAILURE; - - char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER]; - size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]); - float temperature = 0.0; - - bool windowOpen = false; - jsonStruct_t windowActuator; - windowActuator.cb = windowActuate_Callback; - windowActuator.pData = &windowOpen; - windowActuator.dataLength = sizeof(bool); - windowActuator.pKey = "windowOpen"; - windowActuator.type = SHADOW_JSON_BOOL; - - jsonStruct_t temperatureHandler; - temperatureHandler.cb = NULL; - temperatureHandler.pKey = "temperature"; - temperatureHandler.pData = &temperature; - temperatureHandler.dataLength = sizeof(float); - temperatureHandler.type = SHADOW_JSON_FLOAT; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - - parseInputArgsForConnectParams(argc, argv); - - // generate the paths of the credentials - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - // initialize the mqtt client - AWS_IoT_Client mqttClient; - - ShadowInitParameters_t sp = ShadowInitParametersDefault; - sp.pHost = HostAddress; - sp.port = port; - sp.pClientCRT = clientCRT; - sp.pClientKey = clientKey; - sp.pRootCA = rootCA; - sp.enableAutoReconnect = false; - sp.disconnectHandler = NULL; - - IOT_INFO("Shadow Init"); - rc = aws_iot_shadow_init(&mqttClient, &sp); - if(SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - ShadowConnectParameters_t scp = ShadowConnectParametersDefault; - scp.pMyThingName = AWS_IOT_MY_THING_NAME; - scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - - IOT_INFO("Shadow Connect"); - rc = aws_iot_shadow_connect(&mqttClient, &scp); - if(SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - rc = aws_iot_shadow_register_delta(&mqttClient, &windowActuator); - - if(SUCCESS != rc) { - IOT_ERROR("Shadow Register Delta Error"); - } - temperature = STARTING_ROOMTEMPERATURE; - - // loop and publish a change in temperature - while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) { - rc = aws_iot_shadow_yield(&mqttClient, 200); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - sleep(1); - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - IOT_INFO("\n=======================================================================================\n"); - IOT_INFO("On Device: window state %s", windowOpen ? "true" : "false"); - simulateRoomTemperature(&temperature); - - rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 2, &temperatureHandler, - &windowActuator); - if(SUCCESS == rc) { - rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - IOT_INFO("Update Shadow: %s", JsonDocumentBuffer); - rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, JsonDocumentBuffer, - ShadowUpdateStatusCallback, NULL, 4, true); - } - } - } - IOT_INFO("*****************************************************************************************\n"); - sleep(1); - } - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop %d", rc); - } - - IOT_INFO("Disconnecting"); - rc = aws_iot_shadow_disconnect(&mqttClient); - - if(SUCCESS != rc) { - IOT_ERROR("Disconnect error %d", rc); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile deleted file mode 100644 index ebb173636..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = shadow_console_echo -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a - - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(MQTT_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(MQTT_SRC_FILES) -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) - -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h deleted file mode 100644 index 81f9e39e8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c deleted file mode 100644 index 181c8d77a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" - -/** - * @file shadow_console_echo.c - * @brief Echo received Delta message - * - * This application will echo the message received in delta, as reported. - * for example: - * Received Delta message - * { - * "state": { - * "switch": "on" - * } - * } - * This delta message means the desired switch position has changed to "on" - * - * This application will take this delta message and publish it back as the reported message from the device. - * { - * "state": { - * "reported": { - * "switch": "on" - * } - * } - * } - * - * This update message will remove the delta that was created. If this message was not removed then the AWS IoT Thing Shadow is going to always have a delta and keep sending delta any time an update is applied to the Shadow - * This example will not use any of the json builder/helper functions provided in the aws_iot_shadow_json_data.h. - * @note Ensure the buffer sizes in aws_iot_config.h are big enough to receive the delta message. The delta message will also contain the metadata with the timestamps - */ - -static char certDirectory[PATH_MAX + 1] = "../../../certs"; -#define HOST_ADDRESS_SIZE 255 -static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST; -static uint32_t port = AWS_IOT_MQTT_PORT; -static bool messageArrivedOnDelta = false; - -/* - * @note The delta message is always sent on the "state" key in the json - * @note Any time messages are bigger than AWS_IOT_MQTT_RX_BUF_LEN the underlying MQTT library will ignore it. The maximum size of the message that can be received is limited to the AWS_IOT_MQTT_RX_BUF_LEN - */ -static char stringToEchoDelta[SHADOW_MAX_SIZE_OF_RX_BUFFER]; - - -/** - * @brief This function builds a full Shadow expected JSON document by putting the data in the reported section - * - * @param pJsonDocument Buffer to be filled up with the JSON data - * @param maxSizeOfJsonDocument maximum size of the buffer that could be used to fill - * @param pReceivedDeltaData This is the data that will be embedded in the reported section of the JSON document - * @param lengthDelta Length of the data - */ -static bool buildJSONForReported(char *pJsonDocument, size_t maxSizeOfJsonDocument, const char *pReceivedDeltaData, uint32_t lengthDelta) { - int32_t ret; - - if (NULL == pJsonDocument) { - return false; - } - - char tempClientTokenBuffer[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - - if(aws_iot_fill_with_client_token(tempClientTokenBuffer, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE) != SUCCESS){ - return false; - } - - ret = snprintf(pJsonDocument, maxSizeOfJsonDocument, "{\"state\":{\"reported\":%.*s}, \"clientToken\":\"%s\"}", lengthDelta, pReceivedDeltaData, tempClientTokenBuffer); - - if (ret >= maxSizeOfJsonDocument || ret < 0) { - return false; - } - - return true; -} - -// Helper functions -static void parseInputArgsForConnectParams(int argc, char** argv) { - int opt; - - while (-1 != (opt = getopt(argc, argv, "h:p:c:"))) { - switch (opt) { - case 'h': - strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strncpy(certDirectory, optarg, PATH_MAX + 1); - IOT_DEBUG("cert root directory %s", optarg); - break; - case '?': - if (optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if (isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("ERROR in command line argument parsing"); - break; - } - } - -} - -// Shadow Callback for receiving the delta -static void DeltaCallback(const char *pJsonValueBuffer, uint32_t valueLength, jsonStruct_t *pJsonStruct_t) { - IOT_UNUSED(pJsonStruct_t); - - IOT_DEBUG("Received Delta message %.*s", valueLength, pJsonValueBuffer); - - if (buildJSONForReported(stringToEchoDelta, SHADOW_MAX_SIZE_OF_RX_BUFFER, pJsonValueBuffer, valueLength)) { - messageArrivedOnDelta = true; - } -} - -static void UpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(action); - IOT_UNUSED(pReceivedJsonDocument); - IOT_UNUSED(pContextData); - - if(SHADOW_ACK_TIMEOUT == status) { - IOT_INFO("Update Timeout--"); - } else if(SHADOW_ACK_REJECTED == status) { - IOT_INFO("Update RejectedXX"); - } else if(SHADOW_ACK_ACCEPTED == status) { - IOT_INFO("Update Accepted !!"); - } -} - -int main(int argc, char** argv) { - IoT_Error_t rc = SUCCESS; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - - parseInputArgsForConnectParams(argc, argv); - - // initialize the mqtt client - AWS_IoT_Client mqttClient; - - ShadowInitParameters_t sp = ShadowInitParametersDefault; - sp.pHost = AWS_IOT_MQTT_HOST; - sp.port = AWS_IOT_MQTT_PORT; - sp.pClientCRT = clientCRT; - sp.pClientKey = clientKey; - sp.pRootCA = rootCA; - sp.enableAutoReconnect = false; - sp.disconnectHandler = NULL; - - IOT_INFO("Shadow Init"); - rc = aws_iot_shadow_init(&mqttClient, &sp); - if (SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - ShadowConnectParameters_t scp = ShadowConnectParametersDefault; - scp.pMyThingName = AWS_IOT_MY_THING_NAME; - scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - - IOT_INFO("Shadow Connect"); - rc = aws_iot_shadow_connect(&mqttClient, &scp); - if (SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true); - if(SUCCESS != rc){ - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - jsonStruct_t deltaObject; - deltaObject.pData = stringToEchoDelta; - deltaObject.dataLength = SHADOW_MAX_SIZE_OF_RX_BUFFER; - deltaObject.pKey = "state"; - deltaObject.type = SHADOW_JSON_OBJECT; - deltaObject.cb = DeltaCallback; - - /* - * Register the jsonStruct object - */ - rc = aws_iot_shadow_register_delta(&mqttClient, &deltaObject); - - // Now wait in the loop to receive any message sent from the console - while (NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) { - /* - * Lets check for the incoming messages for 200 ms. - */ - rc = aws_iot_shadow_yield(&mqttClient, 200); - - if (NETWORK_ATTEMPTING_RECONNECT == rc) { - sleep(1); - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - if (messageArrivedOnDelta) { - IOT_INFO("\nSending delta message back %s\n", stringToEchoDelta); - rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, stringToEchoDelta, UpdateStatusCallback, NULL, 2, true); - messageArrivedOnDelta = false; - } - - // sleep for some time in seconds - sleep(1); - } - - if (SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop %d", rc); - } - - IOT_INFO("Disconnecting"); - rc = aws_iot_shadow_disconnect(&mqttClient); - - if (SUCCESS != rc) { - IOT_ERROR("Disconnect error %d", rc); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile deleted file mode 100644 index 232260464..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile +++ /dev/null @@ -1,76 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = subscribe_publish_library_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(APP_NAME).c $(COMPILER_FLAGS) -o $(APP_NAME) -L. -lAwsIotSdk $(LD_FLAG) $(INCLUDE_ALL_DIRS) - -all: libAwsIotSdk.a - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -libAwsIotSdk.a: $(SRC_FILES:.c=.o) - ar rcs $@ $^ - -%.o : %.c - $(CC) -c $< -o $@ $(COMPILER_FLAGS) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - rm -f $(APP_DIR)/libAwsIotSdk.a - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h deleted file mode 100644 index 81f9e39e8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c deleted file mode 100644 index 0c3e775e9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file subscribe_publish_library_sample.c - * @brief simple MQTT publish and subscribe on the same topic using the SDK as a library - * - * This example takes the parameters from the aws_iot_config.h file and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "sdkTest/sub" - * - * If all the certs are correct, you should see the messages received by the application in a loop. - * - * The application takes in the certificate path, host name , port and the number of times the publish should happen. - * - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -#define HOST_ADDRESS_SIZE 255 - -/** - * @brief Default cert location - */ -static char certDirectory[PATH_MAX + 1] = "../../../certs"; - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -static uint32_t port = AWS_IOT_MQTT_PORT; - -/** - * @brief This parameter will avoid infinite loop of publish and exit the program after certain number of publishes - */ -uint32_t publishCount = 0; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("Subscribe callback"); - IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *) params->payload); -} - -static void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - IOT_WARN("MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - IOT_UNUSED(data); - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - IOT_WARN("Manual Reconnect Successful"); - } else { - IOT_WARN("Manual Reconnect Failed - %d", rc); - } - } -} - -static void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) { - switch(opt) { - case 'h': - strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strncpy(certDirectory, optarg, PATH_MAX + 1); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'x': - publishCount = atoi(optarg); - IOT_DEBUG("publish %s times\n", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("Error in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - bool infinitePublishFlag = true; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - parseInputArgsForConnectParams(argc, argv); - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - mqttInitParams.pRootCALocation = rootCA; - mqttInitParams.pDeviceCertLocation = clientCRT; - mqttInitParams.pDevicePrivateKeyLocation = clientKey; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); - return rc; - } - - connectParams.keepAliveIntervalInSec = 600; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - IOT_INFO("Connecting..."); - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - return rc; - } - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - IOT_INFO("Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing : %d ", rc); - return rc; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - if(publishCount != 0) { - infinitePublishFlag = false; - } - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) - && (publishCount > 0 || infinitePublishFlag)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - IOT_INFO("-->sleep"); - sleep(1); - sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS0); - if(publishCount > 0) { - publishCount--; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - IOT_WARN("QOS1 publish ack not received.\n"); - rc = SUCCESS; - } - if(publishCount > 0) { - publishCount--; - } - } - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop.\n"); - } else { - IOT_INFO("Publish done\n"); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile deleted file mode 100644 index 1a665a3ae..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = subscribe_publish_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h deleted file mode 100644 index 81f9e39e8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c deleted file mode 100644 index ce7a28f9c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file subscribe_publish_sample.c - * @brief simple MQTT publish and subscribe on the same topic - * - * This example takes the parameters from the aws_iot_config.h file and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "sdkTest/sub" - * - * If all the certs are correct, you should see the messages received by the application in a loop. - * - * The application takes in the certificate path, host name , port and the number of times the publish should happen. - * - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -#define HOST_ADDRESS_SIZE 255 -/** - * @brief Default cert location - */ -static char certDirectory[PATH_MAX + 1] = "../../../certs"; - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -static uint32_t port = AWS_IOT_MQTT_PORT; - -/** - * @brief This parameter will avoid infinite loop of publish and exit the program after certain number of publishes - */ -static uint32_t publishCount = 0; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("Subscribe callback"); - IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *) params->payload); -} - -static void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - IOT_WARN("MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - IOT_UNUSED(data); - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - IOT_WARN("Manual Reconnect Successful"); - } else { - IOT_WARN("Manual Reconnect Failed - %d", rc); - } - } -} - -static void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) { - switch(opt) { - case 'h': - strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strncpy(certDirectory, optarg, PATH_MAX + 1); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'x': - publishCount = atoi(optarg); - IOT_DEBUG("publish %s times\n", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("Error in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - bool infinitePublishFlag = true; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - parseInputArgsForConnectParams(argc, argv); - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - mqttInitParams.pRootCALocation = rootCA; - mqttInitParams.pDeviceCertLocation = clientCRT; - mqttInitParams.pDevicePrivateKeyLocation = clientKey; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); - return rc; - } - - connectParams.keepAliveIntervalInSec = 600; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - IOT_INFO("Connecting..."); - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - return rc; - } - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - IOT_INFO("Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing : %d ", rc); - return rc; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - if(publishCount != 0) { - infinitePublishFlag = false; - } - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) - && (publishCount > 0 || infinitePublishFlag)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - IOT_INFO("-->sleep"); - sleep(1); - sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS0); - if(publishCount > 0) { - publishCount--; - } - - if(publishCount == 0 && !infinitePublishFlag) { - break; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - IOT_WARN("QOS1 publish ack not received.\n"); - rc = SUCCESS; - } - if(publishCount > 0) { - publishCount--; - } - } - - // Wait for all the messages to be received - aws_iot_mqtt_yield(&client, 100); - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop.\n"); - } else { - IOT_INFO("Publish done\n"); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_interface.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_interface.c deleted file mode 100644 index 0452d6786..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_interface.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#include "aws_iot_jobs_interface.h" -#include "aws_iot_log.h" -#include "aws_iot_jobs_json.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define CHECK_GENERATE_STRING_RESULT(result, bufferSize) \ - if (result < 0) { \ - return FAILURE; \ - } else if ((unsigned) result >= bufferSize) { \ - return LIMIT_EXCEEDED_ERROR; \ - } - - -IoT_Error_t aws_iot_jobs_subscribe_to_job_messages( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - AwsIotJobExecutionTopicType topicType, - AwsIotJobExecutionTopicReplyType replyType, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData, - char *topicBuffer, - uint16_t topicBufferSize) -{ - int requiredSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, topicType, replyType, thingName, jobId); - CHECK_GENERATE_STRING_RESULT(requiredSize, topicBufferSize); - - return aws_iot_mqtt_subscribe(pClient, topicBuffer, (uint16_t)strlen(topicBuffer), qos, pApplicationHandler, pApplicationHandlerData); -} - -IoT_Error_t aws_iot_jobs_subscribe_to_all_job_messages( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData, - char *topicBuffer, - uint16_t topicBufferSize) -{ - return aws_iot_jobs_subscribe_to_job_messages(pClient, qos, thingName, NULL, JOB_WILDCARD_TOPIC, JOB_WILDCARD_REPLY_TYPE, - pApplicationHandler, pApplicationHandlerData, topicBuffer, topicBufferSize); -} - -IoT_Error_t aws_iot_jobs_unsubscribe_from_job_messages( - AWS_IoT_Client *pClient, - char *topicBuffer) -{ - return aws_iot_mqtt_unsubscribe(pClient, topicBuffer, (uint16_t)strlen(topicBuffer)); -} - -IoT_Error_t aws_iot_jobs_send_query( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const char *clientToken, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize, - AwsIotJobExecutionTopicType topicType) -{ - if (thingName == NULL || topicBuffer == NULL || (clientToken != NULL && messageBuffer == NULL)) { - return NULL_VALUE_ERROR; - } - - int neededSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, topicType, JOB_REQUEST_TYPE, thingName, jobId); - CHECK_GENERATE_STRING_RESULT(neededSize, topicBufferSize); - uint16_t topicSize = (uint16_t) neededSize; - - char emptyBuffer[1]; - size_t messageLength; - if (clientToken == NULL) { - messageLength = 0; - messageBuffer = emptyBuffer; - } else { - int serializeResult = aws_iot_jobs_json_serialize_client_token_only_request(messageBuffer, messageBufferSize, clientToken); - CHECK_GENERATE_STRING_RESULT(serializeResult, messageBufferSize); - messageLength = (size_t)serializeResult; - } - - IoT_Publish_Message_Params publishParams; - publishParams.qos = qos; - publishParams.isRetained = 0; - publishParams.isDup = 0; - publishParams.id = 0; - publishParams.payload = messageBuffer; - publishParams.payloadLen = messageLength; - - return aws_iot_mqtt_publish(pClient, topicBuffer, topicSize, &publishParams); -} - -IoT_Error_t aws_iot_jobs_start_next( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const AwsIotStartNextPendingJobExecutionRequest *startNextRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize) -{ - if (thingName == NULL || topicBuffer == NULL || startNextRequest == NULL) { - return NULL_VALUE_ERROR; - } - - int neededSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, JOB_START_NEXT_TOPIC, JOB_REQUEST_TYPE, thingName, NULL); - CHECK_GENERATE_STRING_RESULT(neededSize, topicBufferSize); - uint16_t topicSize = (uint16_t) neededSize; - - int serializeResult = aws_iot_jobs_json_serialize_start_next_job_execution_request(messageBuffer, messageBufferSize, startNextRequest); - CHECK_GENERATE_STRING_RESULT(serializeResult, messageBufferSize); - - IoT_Publish_Message_Params publishParams; - publishParams.qos = qos; - publishParams.isRetained = 0; - publishParams.isDup = 0; - publishParams.id = 0; - publishParams.payload = messageBuffer; - publishParams.payloadLen = (size_t) serializeResult; - - return aws_iot_mqtt_publish(pClient, topicBuffer, topicSize, &publishParams); -} - -IoT_Error_t aws_iot_jobs_describe( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const AwsIotDescribeJobExecutionRequest *describeRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize) -{ - if (thingName == NULL || topicBuffer == NULL || describeRequest == NULL) { - return NULL_VALUE_ERROR; - } - - int neededSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, JOB_DESCRIBE_TOPIC, JOB_REQUEST_TYPE, thingName, jobId); - CHECK_GENERATE_STRING_RESULT(neededSize, topicBufferSize); - uint16_t topicSize = (uint16_t) neededSize; - - char emptyBuffer[1]; - size_t messageLength; - if (messageBuffer == NULL) { - messageLength = 0; - messageBuffer = emptyBuffer; - } else { - int serializeResult = aws_iot_jobs_json_serialize_describe_job_execution_request(messageBuffer, messageBufferSize, describeRequest); - CHECK_GENERATE_STRING_RESULT(serializeResult, messageBufferSize); - messageLength = (size_t) serializeResult; - } - - IoT_Publish_Message_Params publishParams; - publishParams.qos = qos; - publishParams.isRetained = 0; - publishParams.isDup = 0; - publishParams.id = 0; - publishParams.payload = messageBuffer; - publishParams.payloadLen = messageLength; - - return aws_iot_mqtt_publish(pClient, topicBuffer, topicSize, &publishParams); -} - -IoT_Error_t aws_iot_jobs_send_update( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const AwsIotJobExecutionUpdateRequest *updateRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize) -{ - if (thingName == NULL || topicBuffer == NULL || jobId == NULL || updateRequest == NULL) { - return NULL_VALUE_ERROR; - } - - int neededSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, JOB_UPDATE_TOPIC, JOB_REQUEST_TYPE, thingName, jobId); - CHECK_GENERATE_STRING_RESULT(neededSize, topicBufferSize); - uint16_t topicSize = (uint16_t) neededSize; - - int serializeResult = aws_iot_jobs_json_serialize_update_job_execution_request(messageBuffer, messageBufferSize, updateRequest); - CHECK_GENERATE_STRING_RESULT(serializeResult, messageBufferSize); - - IoT_Publish_Message_Params publishParams; - publishParams.qos = qos; - publishParams.isRetained = 0; - publishParams.isDup = 0; - publishParams.id = 0; - publishParams.payload = messageBuffer; - publishParams.payloadLen = (size_t) serializeResult; - - return aws_iot_mqtt_publish(pClient, topicBuffer, topicSize, &publishParams); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_json.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_json.c deleted file mode 100644 index 2213ddd7b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_json.c +++ /dev/null @@ -1,197 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#define __STDC_FORMAT_MACROS -#include -#include -#include -#include -#include -#include - -#include "jsmn.h" -#include "aws_iot_jobs_json.h" - -struct _SerializeState { - int totalSize; - char *nextPtr; - size_t remaingSize; -}; - -static void _printToBuffer(struct _SerializeState *state, const char *fmt, ...) { - if (state->totalSize == -1) return; - - va_list vl; - va_start(vl, fmt); - int len = vsnprintf(state->nextPtr, state->remaingSize, fmt, vl); - if (len < 0) { - state->totalSize = -1; - } else { - state->totalSize += len; - if (state->nextPtr != NULL) { - if (state->remaingSize > (size_t) len) { - state->remaingSize -= (size_t) len; - state->nextPtr += len; - } else { - state->remaingSize = 0; - state->nextPtr = NULL; - } - } - } - va_end(vl); -} - -static void _printKey(struct _SerializeState *state, bool first, const char *key) { - if (first) { - _printToBuffer(state, "{\"%s\":", key); - } else { - _printToBuffer(state, ",\"%s\":", key); - } -} - -static void _printStringValue(struct _SerializeState *state, const char *value) { - if (value == NULL) { - _printToBuffer(state, "null"); - } else { - _printToBuffer(state, "\"%s\"", value); - } -} - -static void _printLongValue(struct _SerializeState *state, int64_t value) { - _printToBuffer(state, "%lld", value); -} - -static void _printBooleanValue(struct _SerializeState *state, bool value) { - if(value) { - _printToBuffer(state, "true"); - } else { - _printToBuffer(state, "false"); - } -} - -int aws_iot_jobs_json_serialize_update_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotJobExecutionUpdateRequest *request) -{ - const char *statusStr = aws_iot_jobs_map_status_to_string(request->status); - if (statusStr == NULL) return -1; - if (requestBuffer == NULL) bufferSize = 0; - - struct _SerializeState state = { 0, requestBuffer, bufferSize }; - _printKey(&state, true, "status"); - _printStringValue(&state, statusStr); - if (request->statusDetails != NULL) { - _printKey(&state, false, "statusDetails"); - _printToBuffer(&state, "%s", request->statusDetails); - } - if (request->executionNumber != 0) { - _printKey(&state, false, "executionNumber"); - _printLongValue(&state, request->executionNumber); - } - if (request->expectedVersion != 0) { - _printKey(&state, false, "expectedVersion"); - _printLongValue(&state, request->expectedVersion); - } - if (request->includeJobExecutionState) { - _printKey(&state, false, "includeJobExecutionState"); - _printBooleanValue(&state, request->includeJobExecutionState); - } - if (request->includeJobDocument) { - _printKey(&state, false, "includeJobDocument"); - _printBooleanValue(&state, request->includeJobDocument); - } - if (request->clientToken != NULL) { - _printKey(&state, false, "clientToken"); - _printStringValue(&state, request->clientToken); - } - - _printToBuffer(&state, "}"); - - return state.totalSize; -} - -int aws_iot_jobs_json_serialize_client_token_only_request( - char *requestBuffer, size_t bufferSize, - const char *clientToken) -{ - struct _SerializeState state = { 0, requestBuffer, bufferSize }; - _printKey(&state, true, "clientToken"); - _printStringValue(&state, clientToken); - _printToBuffer(&state, "}"); - - return state.totalSize; -} - -int aws_iot_jobs_json_serialize_describe_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotDescribeJobExecutionRequest *request) -{ - bool first = true; - - if (requestBuffer == NULL) return 0; - - struct _SerializeState state = { 0, requestBuffer, bufferSize }; - if (request->clientToken != NULL) { - _printKey(&state, first, "clientToken"); - _printStringValue(&state, request->clientToken); - first = false; - } - if (request->executionNumber != 0) { - _printKey(&state, first, "executionNumber"); - _printLongValue(&state, request->executionNumber); - first = false; - } - if (request->includeJobDocument) { - _printKey(&state, first, "includeJobDocument"); - _printBooleanValue(&state, request->includeJobDocument); - } - - _printToBuffer(&state, "}"); - - return state.totalSize; -} - -int aws_iot_jobs_json_serialize_start_next_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotStartNextPendingJobExecutionRequest *request) -{ - if (requestBuffer == NULL) bufferSize = 0; - struct _SerializeState state = { 0, requestBuffer, bufferSize }; - if (request->statusDetails != NULL) { - _printKey(&state, true, "statusDetails"); - _printToBuffer(&state, "%s", request->statusDetails); - } - if (request->clientToken != NULL) { - if(request->statusDetails != NULL) { - _printKey(&state, false, "clientToken"); - } else { - _printKey(&state, true, "clientToken"); - } - _printStringValue(&state, request->clientToken); - } - if (request->clientToken == NULL && request->statusDetails == NULL) { - _printToBuffer(&state, "{"); - } - _printToBuffer(&state, "}"); - return state.totalSize; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_topics.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_topics.c deleted file mode 100644 index 39c5cba28..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_topics.c +++ /dev/null @@ -1,129 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_jobs_topics.h" -#include -#include -#include - -#define BASE_THINGS_TOPIC "$aws/things/" - -#define NOTIFY_OPERATION "notify" -#define NOTIFY_NEXT_OPERATION "notify-next" -#define GET_OPERATION "get" -#define START_NEXT_OPERATION "start-next" -#define WILDCARD_OPERATION "+" -#define UPDATE_OPERATION "update" -#define ACCEPTED_REPLY "accepted" -#define REJECTED_REPLY "rejected" -#define WILDCARD_REPLY "+" - -static const char *_get_operation_for_base_topic(AwsIotJobExecutionTopicType topicType) { - switch (topicType) { - case JOB_UPDATE_TOPIC: - return UPDATE_OPERATION; - case JOB_NOTIFY_TOPIC: - return NOTIFY_OPERATION; - case JOB_NOTIFY_NEXT_TOPIC: - return NOTIFY_NEXT_OPERATION; - case JOB_GET_PENDING_TOPIC: - case JOB_DESCRIBE_TOPIC: - return GET_OPERATION; - case JOB_START_NEXT_TOPIC: - return START_NEXT_OPERATION; - case JOB_WILDCARD_TOPIC: - return WILDCARD_OPERATION; - case JOB_UNRECOGNIZED_TOPIC: - default: - return NULL; - } -} - -static bool _base_topic_requires_job_id(AwsIotJobExecutionTopicType topicType) { - switch (topicType) { - case JOB_UPDATE_TOPIC: - case JOB_DESCRIBE_TOPIC: - return true; - case JOB_NOTIFY_TOPIC: - case JOB_NOTIFY_NEXT_TOPIC: - case JOB_START_NEXT_TOPIC: - case JOB_GET_PENDING_TOPIC: - case JOB_WILDCARD_TOPIC: - case JOB_UNRECOGNIZED_TOPIC: - default: - return false; - } -} - -static const char *_get_suffix_for_topic_type(AwsIotJobExecutionTopicReplyType replyType) { - switch (replyType) { - case JOB_REQUEST_TYPE: - return ""; - break; - case JOB_ACCEPTED_REPLY_TYPE: - return "/" ACCEPTED_REPLY; - break; - case JOB_REJECTED_REPLY_TYPE: - return "/" REJECTED_REPLY; - break; - case JOB_WILDCARD_REPLY_TYPE: - return "/" WILDCARD_REPLY; - break; - case JOB_UNRECOGNIZED_TOPIC_TYPE: - default: - return NULL; - } -} - -int aws_iot_jobs_get_api_topic(char *buffer, size_t bufferSize, - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType, - const char* thingName, const char* jobId) -{ - if (thingName == NULL) { - return -1; - } - - if ((topicType == JOB_NOTIFY_TOPIC || topicType == JOB_NOTIFY_NEXT_TOPIC) && replyType != JOB_REQUEST_TYPE) { - return -1; - } - - bool requireJobId = _base_topic_requires_job_id(topicType); - if (jobId == NULL && requireJobId) { - return -1; - } - - const char *operation = _get_operation_for_base_topic(topicType); - if (operation == NULL) { - return -1; - } - - const char *suffix = _get_suffix_for_topic_type(replyType); - - if (requireJobId || (topicType == JOB_WILDCARD_TOPIC && jobId != NULL)) { - return snprintf(buffer, bufferSize, BASE_THINGS_TOPIC "%s/jobs/%s/%s%s", thingName, jobId, operation, suffix); - } else if (topicType == JOB_WILDCARD_TOPIC) { - return snprintf(buffer, bufferSize, BASE_THINGS_TOPIC "%s/jobs/#", thingName); - } else { - return snprintf(buffer, bufferSize, BASE_THINGS_TOPIC "%s/jobs/%s%s", thingName, operation, suffix); - } -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_types.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_types.c deleted file mode 100644 index 9dcbf5081..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_types.c +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "aws_iot_jobs_types.h" - -const char *JOB_EXECUTION_QUEUED_STR = "QUEUED"; -const char *JOB_EXECUTION_IN_PROGRESS_STR = "IN_PROGRESS"; -const char *JOB_EXECUTION_FAILED_STR = "FAILED"; -const char *JOB_EXECUTION_SUCCEEDED_STR = "SUCCEEDED"; -const char *JOB_EXECUTION_CANCELED_STR = "CANCELED"; -const char *JOB_EXECUTION_REJECTED_STR = "REJECTED"; - -JobExecutionStatus aws_iot_jobs_map_string_to_job_status(const char *str) { - if (str == NULL || str[0] == '\0') { - return JOB_EXECUTION_STATUS_NOT_SET; - } else if (strcmp(str, JOB_EXECUTION_QUEUED_STR) == 0) { - return JOB_EXECUTION_QUEUED; - } else if(strcmp(str, JOB_EXECUTION_IN_PROGRESS_STR) == 0) { - return JOB_EXECUTION_IN_PROGRESS; - } else if(strcmp(str, JOB_EXECUTION_FAILED_STR) == 0) { - return JOB_EXECUTION_FAILED; - } else if(strcmp(str, JOB_EXECUTION_SUCCEEDED_STR) == 0) { - return JOB_EXECUTION_SUCCEEDED; - } else if(strcmp(str, JOB_EXECUTION_CANCELED_STR) == 0) { - return JOB_EXECUTION_CANCELED; - } else if(strcmp(str, JOB_EXECUTION_REJECTED_STR) == 0) { - return JOB_EXECUTION_REJECTED; - } else { - return JOB_EXECUTION_UNKNOWN_STATUS; - } -} - -const char *aws_iot_jobs_map_status_to_string(JobExecutionStatus status) { - switch(status) { - case JOB_EXECUTION_QUEUED: - return JOB_EXECUTION_QUEUED_STR; - case JOB_EXECUTION_IN_PROGRESS: - return JOB_EXECUTION_IN_PROGRESS_STR; - case JOB_EXECUTION_FAILED: - return JOB_EXECUTION_FAILED_STR; - case JOB_EXECUTION_SUCCEEDED: - return JOB_EXECUTION_SUCCEEDED_STR; - case JOB_EXECUTION_CANCELED: - return JOB_EXECUTION_CANCELED_STR; - case JOB_EXECUTION_REJECTED: - return JOB_EXECUTION_REJECTED_STR; - case JOB_EXECUTION_STATUS_NOT_SET: - case JOB_EXECUTION_UNKNOWN_STATUS: - default: - return NULL; - } -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c deleted file mode 100644 index f8485695f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_json_utils.c - * @brief Utilities for manipulating JSON - * - * json_utils provides JSON parsing utilities for use with the IoT SDK. - * Underlying JSON parsing relies on the Jasmine JSON parser. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_json_utils.h" - -#include -#include -#include - -#include "aws_iot_log.h" - -int8_t jsoneq(const char *json, jsmntok_t *tok, const char *s) { - if(tok->type == JSMN_STRING) { - if((int) strlen(s) == tok->end - tok->start) { - if(strncmp(json + tok->start, s, (size_t) (tok->end - tok->start)) == 0) { - return 0; - } - } - } - return -1; -} - -IoT_Error_t parseUnsignedInteger32Value(uint32_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%u", i))) { - IOT_WARN("Token was not an unsigned integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%hu", i))) { - IOT_WARN("Token was not an unsigned integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%hhu", i))) { - IOT_WARN("Token was not an unsigned integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%i", i)) { - IOT_WARN("Token was not an integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseInteger16Value(int16_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%hi", i)) { - IOT_WARN("Token was not an integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%hhi", i)) { - IOT_WARN("Token was not an integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not a float."); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%f", f)) { - IOT_WARN("Token was not a float."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not a double."); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%lf", d)) { - IOT_WARN("Token was not a double."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not a primitive."); - return JSON_PARSE_ERROR; - } - if(strncmp(jsonString + token->start, "true", 4) == 0) { - *b = true; - } else if(strncmp(jsonString + token->start, "false", 5) == 0) { - *b = false; - } else { - IOT_WARN("Token was not a bool."); - return JSON_PARSE_ERROR; - } - return SUCCESS; -} - -IoT_Error_t parseStringValue(char *buf, size_t bufLen, const char *jsonString, jsmntok_t *token) { - /* This length does not include a null-terminator. */ - size_t stringLength = (size_t)(token->end - token->start); - - if(token->type != JSMN_STRING) { - IOT_WARN("Token was not a string."); - return JSON_PARSE_ERROR; - } - - if (stringLength+1 > bufLen) { - IOT_WARN("Buffer too small to hold string value."); - return SHADOW_JSON_ERROR; - } - - strncpy(buf, jsonString + token->start, stringLength); - buf[stringLength] = '\0'; - - return SUCCESS; -} - -jsmntok_t *findToken(const char *key, const char *jsonString, jsmntok_t *token) { - jsmntok_t *result = token; - int i; - - if(token->type != JSMN_OBJECT) { - IOT_WARN("Token was not an object."); - return NULL; - } - - if(token->size == 0) { - return NULL; - } - - result = token + 1; - - for (i = 0; i < token->size; i++) { - if (0 == jsoneq(jsonString, result, key)) { - return result + 1; - } - - int propertyEnd = (result + 1)->end; - result += 2; - while (result->start < propertyEnd) - result++; - } - - return NULL; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c deleted file mode 100644 index 21400faf5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c +++ /dev/null @@ -1,397 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client.c - * @brief MQTT client API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "aws_iot_log.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_mqtt_client_common_internal.h" -#include "aws_iot_version.h" - -#if !DISABLE_METRICS -/** Length of metrics username */ -#define SDK_METRICS_LEN 25 -/** Metrics username for AWS IoT */ -#define SDK_METRICS_TEMPLATE "?SDK=C&Version=%d.%d.%d" -/** Buffer for metrics username */ -static char pUsernameTemp[SDK_METRICS_LEN] = {0}; -#endif - -#ifdef _ENABLE_THREAD_SUPPORT_ -#include "threads_interface.h" -#endif - -const IoT_Client_Init_Params iotClientInitParamsDefault = IoT_Client_Init_Params_initializer; -const IoT_MQTT_Will_Options iotMqttWillOptionsDefault = IoT_MQTT_Will_Options_Initializer; -const IoT_Client_Connect_Params iotClientConnectParamsDefault = IoT_Client_Connect_Params_initializer; - -ClientState aws_iot_mqtt_get_client_state(AWS_IoT_Client *pClient) { - FUNC_ENTRY; - if(NULL == pClient) { - return CLIENT_STATE_INVALID; - } - - FUNC_EXIT_RC(pClient->clientStatus.clientState); -} - -#ifdef _ENABLE_THREAD_SUPPORT_ -/** - * @brief Lock a mutex in the MQTT client - * - * @param pClient MQTT client - * @param pMutex Mutex to lock - * - * @return IoT_Error_t of mutex operation - */ -IoT_Error_t aws_iot_mqtt_client_lock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex) { - FUNC_ENTRY; - IoT_Error_t threadRc = FAILURE; - - if(NULL == pClient || NULL == pMutex){ - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(false == pClient->clientData.isBlockOnThreadLockEnabled) { - threadRc = aws_iot_thread_mutex_trylock(pMutex); - } else { - threadRc = aws_iot_thread_mutex_lock(pMutex); - /* Should never return Error because the above request blocks until lock is obtained */ - } - - if(SUCCESS != threadRc) { - FUNC_EXIT_RC(threadRc); - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Unlock a mutex in the MQTT client - * - * @param pClient MQTT client - * @param pMutex Mutex to unlock - * - * @return IoT_Error_t of mutex operation - */ -IoT_Error_t aws_iot_mqtt_client_unlock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex) { - if(NULL == pClient || NULL == pMutex) { - return NULL_VALUE_ERROR; - } - IOT_UNUSED(pClient); - return aws_iot_thread_mutex_unlock(pMutex); -} -#endif - -/** - * @brief Change the state in an MQTT client - * - * @param pClient MQTT client - * @param expectedCurrentState What the current state of the client should be - * @param newState What the new state of the client should be - * - * @return IoT_Error_t of state change - */ -IoT_Error_t aws_iot_mqtt_set_client_state(AWS_IoT_Client *pClient, ClientState expectedCurrentState, - ClientState newState) { - IoT_Error_t rc; -#ifdef _ENABLE_THREAD_SUPPORT_ - IoT_Error_t threadRc = FAILURE; -#endif - - FUNC_ENTRY; - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.state_change_mutex)); - if(SUCCESS != threadRc) { - return threadRc; - } -#endif - if(expectedCurrentState == aws_iot_mqtt_get_client_state(pClient)) { - pClient->clientStatus.clientState = newState; - rc = SUCCESS; - } else { - rc = MQTT_UNEXPECTED_CLIENT_STATE_ERROR; - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.state_change_mutex)); - if(SUCCESS == rc && SUCCESS != threadRc) { - rc = threadRc; - } -#endif - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_mqtt_set_connect_params(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pNewConnectParams) { - FUNC_ENTRY; - if(NULL == pClient || NULL == pNewConnectParams) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - pClient->clientData.options.isWillMsgPresent = pNewConnectParams->isWillMsgPresent; - pClient->clientData.options.MQTTVersion = pNewConnectParams->MQTTVersion; - pClient->clientData.options.pClientID = pNewConnectParams->pClientID; - pClient->clientData.options.clientIDLen = pNewConnectParams->clientIDLen; -#if !DISABLE_METRICS - if (0 == strlen(pUsernameTemp)) { - snprintf(pUsernameTemp, SDK_METRICS_LEN, SDK_METRICS_TEMPLATE, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); - } - pClient->clientData.options.pUsername = (char*)&pUsernameTemp[0]; - pClient->clientData.options.usernameLen = strlen(pUsernameTemp); -#else - pClient->clientData.options.pUsername = pNewConnectParams->pUsername; - pClient->clientData.options.usernameLen = pNewConnectParams->usernameLen; -#endif - pClient->clientData.options.pPassword = pNewConnectParams->pPassword; - pClient->clientData.options.passwordLen = pNewConnectParams->passwordLen; - pClient->clientData.options.will.pTopicName = pNewConnectParams->will.pTopicName; - pClient->clientData.options.will.topicNameLen = pNewConnectParams->will.topicNameLen; - pClient->clientData.options.will.pMessage = pNewConnectParams->will.pMessage; - pClient->clientData.options.will.msgLen = pNewConnectParams->will.msgLen; - pClient->clientData.options.will.qos = pNewConnectParams->will.qos; - pClient->clientData.options.will.isRetained = pNewConnectParams->will.isRetained; - pClient->clientData.options.keepAliveIntervalInSec = pNewConnectParams->keepAliveIntervalInSec; - pClient->clientData.options.isCleanSession = pNewConnectParams->isCleanSession; - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_free(AWS_IoT_Client *pClient) -{ - IoT_Error_t rc = SUCCESS; - - if (NULL == pClient) { - rc = NULL_VALUE_ERROR; - }else - { - #ifdef _ENABLE_THREAD_SUPPORT_ - if (rc == SUCCESS) - { - rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); - } - - if (rc == SUCCESS) - { - rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); - }else{ - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); - } - - if (rc == SUCCESS) - { - rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); - }else{ - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); - } - #endif - } - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *pInitParams) { - uint32_t i; - IoT_Error_t rc; - IoT_Client_Connect_Params default_options = IoT_Client_Connect_Params_initializer; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pInitParams || NULL == pInitParams->pHostURL || 0 == pInitParams->port || - NULL == pInitParams->pRootCALocation || NULL == pInitParams->pDevicePrivateKeyLocation || - NULL == pInitParams->pDeviceCertLocation) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { - pClient->clientData.messageHandlers[i].topicName = NULL; - pClient->clientData.messageHandlers[i].pApplicationHandler = NULL; - pClient->clientData.messageHandlers[i].pApplicationHandlerData = NULL; - pClient->clientData.messageHandlers[i].qos = QOS0; - } - - pClient->clientData.packetTimeoutMs = pInitParams->mqttPacketTimeout_ms; - pClient->clientData.commandTimeoutMs = pInitParams->mqttCommandTimeout_ms; - pClient->clientData.writeBufSize = AWS_IOT_MQTT_TX_BUF_LEN; - pClient->clientData.readBufSize = AWS_IOT_MQTT_RX_BUF_LEN; - pClient->clientData.counterNetworkDisconnected = 0; - pClient->clientData.disconnectHandler = pInitParams->disconnectHandler; - pClient->clientData.disconnectHandlerData = pInitParams->disconnectHandlerData; - pClient->clientData.nextPacketId = 1; - - /* Initialize default connection options */ - rc = aws_iot_mqtt_set_connect_params(pClient, &default_options); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - pClient->clientData.isBlockOnThreadLockEnabled = pInitParams->isBlockOnThreadLockEnabled; - rc = aws_iot_thread_mutex_init(&(pClient->clientData.state_change_mutex)); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_read_mutex)); - if(SUCCESS != rc) { - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); - FUNC_EXIT_RC(rc); - } - rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_write_mutex)); - if(SUCCESS != rc) { - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); - FUNC_EXIT_RC(rc); - } -#endif - - pClient->clientStatus.isPingOutstanding = 0; - pClient->clientStatus.isAutoReconnectEnabled = pInitParams->enableAutoReconnect; - - rc = iot_tls_init(&(pClient->networkStack), pInitParams->pRootCALocation, pInitParams->pDeviceCertLocation, - pInitParams->pDevicePrivateKeyLocation, pInitParams->pHostURL, pInitParams->port, - pInitParams->tlsHandshakeTimeout_ms, pInitParams->isSSLHostnameVerify); - - if(SUCCESS != rc) { - #ifdef _ENABLE_THREAD_SUPPORT_ - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); - #endif - pClient->clientStatus.clientState = CLIENT_STATE_INVALID; - FUNC_EXIT_RC(rc); - } - - init_timer(&(pClient->pingReqTimer)); - init_timer(&(pClient->pingRespTimer)); - init_timer(&(pClient->reconnectDelayTimer)); - - pClient->clientStatus.clientState = CLIENT_STATE_INITIALIZED; - - FUNC_EXIT_RC(SUCCESS); -} - -uint16_t aws_iot_mqtt_get_next_packet_id(AWS_IoT_Client *pClient) { - return pClient->clientData.nextPacketId = (uint16_t) ((MAX_PACKET_ID == pClient->clientData.nextPacketId) ? 1 : ( - pClient->clientData.nextPacketId + 1)); -} - -bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient) { - bool isConnected; - - FUNC_ENTRY; - - if(NULL == pClient) { - IOT_WARN(" Client is null! "); - FUNC_EXIT_RC(false); - } - - switch(pClient->clientStatus.clientState) { - case CLIENT_STATE_INVALID: - case CLIENT_STATE_INITIALIZED: - case CLIENT_STATE_CONNECTING: - isConnected = false; - break; - case CLIENT_STATE_CONNECTED_IDLE: - case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN: - isConnected = true; - break; - case CLIENT_STATE_DISCONNECTING: - case CLIENT_STATE_DISCONNECTED_ERROR: - case CLIENT_STATE_DISCONNECTED_MANUALLY: - case CLIENT_STATE_PENDING_RECONNECT: - default: - isConnected = false; - break; - } - - FUNC_EXIT_RC(isConnected); -} - -bool aws_iot_is_autoreconnect_enabled(AWS_IoT_Client *pClient) { - FUNC_ENTRY; - if(NULL == pClient) { - IOT_WARN(" Client is null! "); - FUNC_EXIT_RC(false); - } - - FUNC_EXIT_RC(pClient->clientStatus.isAutoReconnectEnabled); -} - -IoT_Error_t aws_iot_mqtt_autoreconnect_set_status(AWS_IoT_Client *pClient, bool newStatus) { - FUNC_ENTRY; - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - pClient->clientStatus.isAutoReconnectEnabled = newStatus; - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_set_disconnect_handler(AWS_IoT_Client *pClient, iot_disconnect_handler pDisconnectHandler, - void *pDisconnectHandlerData) { - FUNC_ENTRY; - if(NULL == pClient || NULL == pDisconnectHandler) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - pClient->clientData.disconnectHandler = pDisconnectHandler; - pClient->clientData.disconnectHandlerData = pDisconnectHandlerData; - FUNC_EXIT_RC(SUCCESS); -} - -uint32_t aws_iot_mqtt_get_network_disconnected_count(AWS_IoT_Client *pClient) { - return pClient->clientData.counterNetworkDisconnected; -} - -void aws_iot_mqtt_reset_network_disconnected_count(AWS_IoT_Client *pClient) { - pClient->clientData.counterNetworkDisconnected = 0; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c deleted file mode 100644 index 8aaf4a321..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c +++ /dev/null @@ -1,793 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Sergio R. Caprile - non-blocking packet read functions for stream transport - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_common_internal.c - * @brief MQTT client internal API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "aws_iot_mqtt_client_common_internal.h" - -/** Max length of packet header */ -#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4 - -/** - * @brief Encodes the message length according to the MQTT algorithm - * - * @param buf the buffer into which the encoded data is written - * @param length the length to be encoded - * - * @return the number of bytes written to buffer - */ -size_t aws_iot_mqtt_internal_write_len_to_buffer(unsigned char *buf, uint32_t length) { - size_t outLen = 0; - unsigned char encodedByte; - - FUNC_ENTRY; - do { - encodedByte = (unsigned char) (length % 128); - length /= 128; - /* if there are more digits to encode, set the top bit of this digit */ - if(length > 0) { - encodedByte |= 0x80; - } - buf[outLen++] = encodedByte; - } while(length > 0); - - FUNC_EXIT_RC(outLen); -} - -/** - * @brief Decodes the message length according to the MQTT algorithm - * - * @param buf the buffer containing the message - * @param decodedLen value the decoded length returned - * @param readBytesLen output parameter for the number of bytes read from the socket - * - * @return IoT_Error_t indicating decode status - */ -IoT_Error_t aws_iot_mqtt_internal_decode_remaining_length_from_buffer(unsigned char *buf, uint32_t *decodedLen, - uint32_t *readBytesLen) { - unsigned char encodedByte; - uint32_t multiplier, len; - FUNC_ENTRY; - - multiplier = 1; - len = 0; - *decodedLen = 0; - - do { - if(++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) { - /* bad data */ - FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR); - } - encodedByte = *buf; - buf++; - *decodedLen += (encodedByte & 127) * multiplier; - multiplier *= 128; - } while((encodedByte & 128) != 0); - - *readBytesLen = len; - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Calculates the length of the "remaining length" encoding - * - * @param rem_len "remaining length" to encode - * - * @return length of the remaining length encoding - */ -uint32_t aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(uint32_t rem_len) { - rem_len += 1; /* header byte */ - /* now remaining_length field (MQTT 3.1.1 - 2.2.3)*/ - if(rem_len < 128) { - rem_len += 1; - } else if(rem_len < 16384) { - rem_len += 2; - } else if(rem_len < 2097152) { - rem_len += 3; - } else { - rem_len += 4; - } - return rem_len; -} - -/** - * @brief Calculates uint16 packet id from two bytes read from the input buffer - * - * Checks Endianness at runtime - * - * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned - * @return the value calculated - */ -uint16_t aws_iot_mqtt_internal_read_uint16_t(unsigned char **pptr) { - unsigned char *ptr = *pptr; - uint16_t len = 0; - uint8_t firstByte = (uint8_t) (*ptr); - uint8_t secondByte = (uint8_t) (*(ptr + 1)); - len = (uint16_t) (secondByte + (256 * firstByte)); - - *pptr += 2; - return len; -} - -/** - * @brief Writes an integer as 2 bytes to an output buffer. - * - * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned - * @param anInt the integer to write - */ -void aws_iot_mqtt_internal_write_uint_16(unsigned char **pptr, uint16_t anInt) { - **pptr = (unsigned char) (anInt / 256); - (*pptr)++; - **pptr = (unsigned char) (anInt % 256); - (*pptr)++; -} - -/** - * @brief Reads one character from the input buffer. - * - * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned - * @return the character read - */ -unsigned char aws_iot_mqtt_internal_read_char(unsigned char **pptr) { - unsigned char c = **pptr; - (*pptr)++; - return c; -} - -/** - * @brief Writes one character to an output buffer. - * - * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned - * @param c the character to write - */ -void aws_iot_mqtt_internal_write_char(unsigned char **pptr, unsigned char c) { - **pptr = c; - (*pptr)++; -} - -/** - * @brief Writes a UTF-8 string into an MQTT packet - * - * @param pptr Where the string should be written - * @param string The string to write - * @param stringLen Length to write - */ -void aws_iot_mqtt_internal_write_utf8_string(unsigned char **pptr, const char *string, uint16_t stringLen) { - /* Nothing that calls this function will have a stringLen with a size larger than 2 bytes (MQTT 3.1.1 - 1.5.3) */ - aws_iot_mqtt_internal_write_uint_16(pptr, stringLen); - if(stringLen > 0) { - memcpy(*pptr, string, stringLen); - *pptr += stringLen; - } -} - -/** - * @brief Initialize the MQTTHeader structure. - * - * Used to ensure that Header bits are always initialized using the proper mappings. - * No Endianness issues here since the individual fields are all less than a byte. - * Also generates no warnings since all fields are initialized using hex constants. - * - * @param pHeader Header to initialize - * @param message_type MQTT packet type - * @param qos Quality of service for packet - * @param dup DUP flag of a publish - * @param retained RETAIN flag of a publish - * - * @return Returns SUCCESS unless an invalid packet type is given. - */ -IoT_Error_t aws_iot_mqtt_internal_init_header(MQTTHeader *pHeader, MessageTypes message_type, - QoS qos, uint8_t dup, uint8_t retained) { - FUNC_ENTRY; - - if(NULL == pHeader) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Set all bits to zero */ - pHeader->byte = 0; - uint8_t type = 0; - switch(message_type) { - case UNKNOWN: - /* Should never happen */ - return FAILURE; - case CONNECT: - type = 0x01; - break; - case CONNACK: - type = 0x02; - break; - case PUBLISH: - type = 0x03; - break; - case PUBACK: - type = 0x04; - break; - case PUBREC: - type = 0x05; - break; - case PUBREL: - type = 0x06; - break; - case PUBCOMP: - type = 0x07; - break; - case SUBSCRIBE: - type = 0x08; - break; - case SUBACK: - type = 0x09; - break; - case UNSUBSCRIBE: - type = 0x0A; - break; - case UNSUBACK: - type = 0x0B; - break; - case PINGREQ: - type = 0x0C; - break; - case PINGRESP: - type = 0x0D; - break; - case DISCONNECT: - type = 0x0E; - break; - default: - /* Should never happen */ - FUNC_EXIT_RC(FAILURE); - } - - pHeader->byte = type << 4; - pHeader->byte |= dup << 3; - - switch(qos) { - case QOS0: - break; - case QOS1: - pHeader->byte |= 1 << 1; - break; - default: - /* Using QOS0 as default */ - break; - } - - pHeader->byte |= (1 == retained) ? 0x01 : 0x00; - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Send an MQTT packet on the network - * - * @param pClient MQTT client which holds packet - * @param length Length of packet to send - * @param pTimer Amount of time allowed to send packet - * - * @return IoT_Error_t of send status - */ -IoT_Error_t aws_iot_mqtt_internal_send_packet(AWS_IoT_Client *pClient, size_t length, Timer *pTimer) { - - size_t sentLen, sent; - IoT_Error_t rc = FAILURE; - -#ifdef _ENABLE_THREAD_SUPPORT_ - IoT_Error_t threadRc; -#endif - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pTimer) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(length >= pClient->clientData.writeBufSize) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.tls_write_mutex)); - if(SUCCESS != threadRc) { - FUNC_EXIT_RC(threadRc); - } -#endif - - sentLen = 0; - sent = 0; - - while(sent < length && !has_timer_expired(pTimer)) { - rc = pClient->networkStack.write(&(pClient->networkStack), - &pClient->clientData.writeBuf[sent], - (length - sent), - pTimer, - &sentLen); - if(SUCCESS != rc) { - /* there was an error writing the data */ - break; - } - sent += sentLen; - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.tls_write_mutex)); - if((SUCCESS != threadRc) && ( SUCCESS == rc )) { - FUNC_EXIT_RC(threadRc); - } -#endif - - if(sent == length) { - /* record the fact that we have successfully sent the packet */ - //countdown_sec(&c->pingTimer, c->clientData.keepAliveInterval); - FUNC_EXIT_RC(SUCCESS); - } - - FUNC_EXIT_RC(rc) -} - -static IoT_Error_t _aws_iot_mqtt_internal_readWrapper( AWS_IoT_Client *pClient, size_t offset, size_t size, Timer *pTimer, size_t * read_len ) { - IoT_Error_t rc; - int byteToRead; - size_t byteRead = 0; - - byteToRead = ( offset + size ) - pClient->clientData.readBufIndex; - - if ( byteToRead > 0 ) - { - rc = pClient->networkStack.read( &( pClient->networkStack ), - pClient->clientData.readBuf + pClient->clientData.readBufIndex, - (size_t)byteToRead, - pTimer, - &byteRead ); - pClient->clientData.readBufIndex += byteRead; - - /* refresh byte to read */ - byteToRead = ( offset + size ) - ((int)pClient->clientData.readBufIndex); - *read_len = size - (size_t)byteToRead; - } - else - { - *read_len = size; - rc = SUCCESS; - } - - - - return rc; -} -static IoT_Error_t _aws_iot_mqtt_internal_decode_packet_remaining_len(AWS_IoT_Client *pClient, size_t * offset, - size_t *rem_len, Timer *pTimer) { - size_t multiplier, len; - IoT_Error_t rc; - size_t read_len; - - FUNC_ENTRY; - - multiplier = 1; - len = 0; - *rem_len = 0; - - do { - if(++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) { - /* bad data */ - FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR); - } - rc = _aws_iot_mqtt_internal_readWrapper( pClient, len, 1, pTimer, &read_len ); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - *rem_len += (( pClient->clientData.readBuf[len] & 127) * multiplier); - multiplier *= 128; - } while(( pClient->clientData.readBuf[len] & 128) != 0); - *offset = len + 1; - FUNC_EXIT_RC(rc); -} - -static IoT_Error_t _aws_iot_mqtt_internal_read_packet(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType) { - size_t rem_len, total_bytes_read, bytes_to_be_read, read_len; - IoT_Error_t rc; - size_t offset = 0; - MQTTHeader header = {0}; - - rem_len = 0; - total_bytes_read = 0; - bytes_to_be_read = 0; - read_len = 0; - - rc = _aws_iot_mqtt_internal_readWrapper( pClient, offset, 1, pTimer, &read_len ); - /* 1. read the header byte. This has the packet type in it */ - if(NETWORK_SSL_NOTHING_TO_READ == rc) { - return MQTT_NOTHING_TO_READ; - } else if(SUCCESS != rc) { - return rc; - } - - /* 2. read the remaining length. This is variable in itself */ - rc = _aws_iot_mqtt_internal_decode_packet_remaining_len(pClient, &offset, &rem_len, pTimer); - if(SUCCESS != rc) { - return rc; - } - - /* if the buffer is too short then the message will be dropped silently */ - if((rem_len + offset) >= pClient->clientData.readBufSize) { - bytes_to_be_read = pClient->clientData.readBufSize; - do { - rc = pClient->networkStack.read(&(pClient->networkStack), pClient->clientData.readBuf, bytes_to_be_read, - pTimer, &read_len); - if(SUCCESS == rc) { - total_bytes_read += read_len; - if((rem_len - total_bytes_read) >= pClient->clientData.readBufSize) { - bytes_to_be_read = pClient->clientData.readBufSize; - } else { - bytes_to_be_read = rem_len - total_bytes_read; - } - } - } while(total_bytes_read < rem_len && SUCCESS == rc); - - /* Check buffer was correctly emptied, otherwise, return error message. */ - if ( total_bytes_read == rem_len ) - { - aws_iot_mqtt_internal_flushBuffers( pClient ); - return MQTT_RX_BUFFER_TOO_SHORT_ERROR; - } - else - { - return rc; - } - } - - /* 3. read the rest of the buffer using a callback to supply the rest of the data */ - if(rem_len > 0) { - rc = _aws_iot_mqtt_internal_readWrapper( pClient, offset, rem_len, pTimer, &read_len ); - if(SUCCESS != rc || read_len != rem_len) { - return FAILURE; - } - } - - /* Pack has been received, we can flush the buffers for next call. */ - aws_iot_mqtt_internal_flushBuffers( pClient ); - header.byte = pClient->clientData.readBuf[0]; - *pPacketType = MQTT_HEADER_FIELD_TYPE(header.byte); - - FUNC_EXIT_RC(rc); -} - -// assume topic filter and name is in correct format -// # can only be at end -// + and # can only be next to separator -static bool _aws_iot_mqtt_internal_is_topic_matched(char *pTopicFilter, char *pTopicName, uint16_t topicNameLen) { - - char *curf, *curn, *curn_end; - - if(NULL == pTopicFilter || NULL == pTopicName) { - return false; - } - - curf = pTopicFilter; - curn = pTopicName; - curn_end = curn + topicNameLen; - - while(*curf && (curn < curn_end)) { - if(*curn == '/' && *curf != '/') { - break; - } - if(*curf != '+' && *curf != '#' && *curf != *curn) { - break; - } - if(*curf == '+') { - /* skip until we meet the next separator, or end of string */ - char *nextpos = curn + 1; - while(nextpos < curn_end && *nextpos != '/') - nextpos = ++curn + 1; - } else if(*curf == '#') { - /* skip until end of string */ - curn = curn_end - 1; - } - - curf++; - curn++; - }; - - return (curn == curn_end) && (*curf == '\0'); -} - -static IoT_Error_t _aws_iot_mqtt_internal_deliver_message(AWS_IoT_Client *pClient, char *pTopicName, - uint16_t topicNameLen, - IoT_Publish_Message_Params *pMessageParams) { - uint32_t itr; - IoT_Error_t rc; - ClientState clientState; - - FUNC_ENTRY; - - if(NULL == pTopicName) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* This function can be called from all MQTT APIs - * But while callback return is in progress, Yield should not be called. - * The state for CB_RETURN accomplishes that, as yield cannot be called while in that state */ - clientState = aws_iot_mqtt_get_client_state(pClient); - aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN); - - /* Find the right message handler - indexed by topic */ - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++itr) { - if(NULL != pClient->clientData.messageHandlers[itr].topicName) { - if(((topicNameLen == pClient->clientData.messageHandlers[itr].topicNameLen) - && - (strncmp(pTopicName, (char *) pClient->clientData.messageHandlers[itr].topicName, topicNameLen) == 0)) - || _aws_iot_mqtt_internal_is_topic_matched((char *) pClient->clientData.messageHandlers[itr].topicName, - pTopicName, topicNameLen)) { - if(NULL != pClient->clientData.messageHandlers[itr].pApplicationHandler) { - pClient->clientData.messageHandlers[itr].pApplicationHandler(pClient, pTopicName, topicNameLen, - pMessageParams, - pClient->clientData.messageHandlers[itr].pApplicationHandlerData); - } - } - } - } - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN, clientState); - - FUNC_EXIT_RC(rc); -} - -static IoT_Error_t _aws_iot_mqtt_internal_handle_publish(AWS_IoT_Client *pClient) { - char *topicName; - uint16_t topicNameLen; - uint32_t len; - IoT_Error_t rc; - IoT_Publish_Message_Params msg; - Timer sendTimer; - - FUNC_ENTRY; - - topicName = NULL; - topicNameLen = 0; - len = 0; - - rc = aws_iot_mqtt_internal_deserialize_publish(&msg.isDup, &msg.qos, &msg.isRetained, - &msg.id, &topicName, &topicNameLen, - (unsigned char **) &msg.payload, &msg.payloadLen, - pClient->clientData.readBuf, - pClient->clientData.readBufSize); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Send acknowledgement of QoS 1 message. */ - if(QOS1 == msg.qos) { - /* Initialize timer for sending PUBACK. */ - init_timer(&sendTimer); - countdown_ms(&sendTimer, pClient->clientData.commandTimeoutMs); - - /* Generate and send a PUBACK. Warn if the PUBACK isn't sent; the server - will send the PUBLISH again in that case. */ - rc = aws_iot_mqtt_internal_serialize_ack(pClient->clientData.writeBuf, - pClient->clientData.writeBufSize, PUBACK, 0, msg.id, &len); - - if(SUCCESS == rc) { - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &sendTimer); - - if(SUCCESS != rc) { - IOT_WARN("Failed to send PUBACK"); - } - } else { - IOT_WARN("Failed to generate PUBACK"); - } - } - - rc = _aws_iot_mqtt_internal_deliver_message(pClient, topicName, topicNameLen, &msg); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Read an MQTT packet from the network - * - * @param pClient MQTT client - * @param pTimer Amount of time allowed to read packet - * @param pPacketType Output parameter for packet read from network - * - * @return IoT_Error_t of read status - */ -IoT_Error_t aws_iot_mqtt_internal_cycle_read(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType) { - IoT_Error_t rc; - -#ifdef _ENABLE_THREAD_SUPPORT_ - IoT_Error_t threadRc; -#endif - - if(NULL == pClient || NULL == pTimer) { - return NULL_VALUE_ERROR; - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.tls_read_mutex)); - if(SUCCESS != threadRc) { - FUNC_EXIT_RC(threadRc); - } -#endif - - /* read the socket, see what work is due */ - rc = _aws_iot_mqtt_internal_read_packet(pClient, pTimer, pPacketType); - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.tls_read_mutex)); - if(SUCCESS != threadRc && (MQTT_NOTHING_TO_READ == rc || SUCCESS == rc)) { - return threadRc; - } -#endif - - if(MQTT_NOTHING_TO_READ == rc) { - /* Nothing to read, not a cycle failure */ - return SUCCESS; - } else if(SUCCESS != rc) { - return rc; - } - - switch(*pPacketType) { - case CONNACK: - case PUBACK: - case SUBACK: - case UNSUBACK: - /* SDK is blocking, these responses will be forwarded to calling function to process */ - break; - case PUBLISH: { - rc = _aws_iot_mqtt_internal_handle_publish(pClient); - break; - } - case PUBREC: - case PUBCOMP: - /* QoS2 not supported at this time */ - break; - case PINGRESP: { - /* There is no outstanding ping request anymore. */ - pClient->clientStatus.isPingOutstanding = false; - break; - } - default: { - /* Either unknown packet type or Failure occurred - * Should not happen */ - rc = MQTT_RX_MESSAGE_PACKET_TYPE_INVALID_ERROR; - break; - } - } - - return rc; -} - -/** - * @brief Flush incoming data from the MQTT client - * - * @param pClient Client with data to flush - * - * @return Always returns SUCCESS - */ -IoT_Error_t aws_iot_mqtt_internal_flushBuffers( AWS_IoT_Client *pClient ) { - pClient->clientData.readBufIndex = 0; - return SUCCESS; -} - -/** - * @brief Wait until a packet is read from the network - * - * Only used in single-threaded mode where one command at a time is in process - * - * @param pClient MQTT client - * @param packetType MQTT packet to read - * @param pTimer Amount of time allowed to read packet - * - * @return IoT_Error_t of read status - */ -IoT_Error_t aws_iot_mqtt_internal_wait_for_read(AWS_IoT_Client *pClient, uint8_t packetType, Timer *pTimer) { - IoT_Error_t rc; - uint8_t read_packet_type; - - FUNC_ENTRY; - if(NULL == pClient || NULL == pTimer) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - read_packet_type = 0; - do { - if(has_timer_expired(pTimer)) { - /* we timed out */ - rc = MQTT_REQUEST_TIMEOUT_ERROR; - break; - } - rc = aws_iot_mqtt_internal_cycle_read(pClient, pTimer, &read_packet_type); - } while(((SUCCESS == rc) || (MQTT_NOTHING_TO_READ == rc)) && (read_packet_type != packetType)); - - /* If rc is SUCCESS, we have received the expected - * MQTT packet. Otherwise rc tells the error. */ - FUNC_EXIT_RC(rc); -} - -/** - * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer, to avoid overruns - * @param packetType the message type - * @param pSerializedLength length - * @return IoT_Error_t indicating function execution status - */ -IoT_Error_t aws_iot_mqtt_internal_serialize_zero(unsigned char *pTxBuf, size_t txBufLen, MessageTypes packetType, - size_t *pSerializedLength) { - unsigned char *ptr; - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pTxBuf || NULL == pSerializedLength) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Buffer should have at least 2 bytes for the header */ - if(4 > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - ptr = pTxBuf; - - rc = aws_iot_mqtt_internal_init_header(&header, packetType, QOS0, 0, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* write header */ - aws_iot_mqtt_internal_write_char(&ptr, header.byte); - - /* write remaining length */ - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, 0); - *pSerializedLength = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c deleted file mode 100644 index fbbfbec41..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c +++ /dev/null @@ -1,560 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_connect.c - * @brief MQTT client connect API definition and related functions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_mqtt_client_common_internal.h" - -/** @brief Connect request response codes from server */ -typedef enum { - CONNACK_CONNECTION_ACCEPTED = 0, /**< Connection accepted */ - CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1, /**< Unacceptable protocol version */ - CONNACK_IDENTIFIER_REJECTED_ERROR = 2, /**< Client identifier rejected */ - CONNACK_SERVER_UNAVAILABLE_ERROR = 3, /**< Server unavailable */ - CONNACK_BAD_USERDATA_ERROR = 4, /**< Bad username */ - CONNACK_NOT_AUTHORIZED_ERROR = 5 /**< Not authorized */ -} MQTT_Connack_Return_Codes; - -/** - * Determines the length of the MQTT connect packet that would be produced using the supplied connect options. - * @param options the options to be used to build the connect packet - * @param the length of buffer needed to contain the serialized version of the packet - * @return IoT_Error_t indicating function execution status - */ -static uint32_t _aws_iot_get_connect_packet_length(IoT_Client_Connect_Params *pConnectParams) { - uint32_t len; - /* Enable when adding further MQTT versions */ - /*size_t len = 0; - switch(pConnectParams->MQTTVersion) { - case MQTT_3_1_1: - len = 10; - break; - }*/ - FUNC_ENTRY; - - len = 10; // Len = 10 for MQTT_3_1_1 - len = len + pConnectParams->clientIDLen + 2; - - if(pConnectParams->isWillMsgPresent) { - len = len + pConnectParams->will.topicNameLen + 2 + pConnectParams->will.msgLen + 2; - } - - if(NULL != pConnectParams->pUsername) { - len = len + pConnectParams->usernameLen + 2; - } - - if(NULL != pConnectParams->pPassword) { - len = len + pConnectParams->passwordLen + 2; - } - - FUNC_EXIT_RC(len); -} - -/** - * Serializes the connect options into the buffer. - * @param buf the buffer into which the packet will be serialized - * @param len the length in bytes of the supplied buffer - * @param options the options to be used to build the connect packet - * @param serialized length - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t txBufLen, - IoT_Client_Connect_Params *pConnectParams, - size_t *pSerializedLen) { - unsigned char *ptr; - uint32_t len; - IoT_Error_t rc; - MQTTHeader header = {0}; - uint8_t flags = 0u; - - FUNC_ENTRY; - - if(NULL == pTxBuf || NULL == pConnectParams || NULL == pSerializedLen || - (NULL == pConnectParams->pClientID && 0 != pConnectParams->clientIDLen) || - (NULL != pConnectParams->pClientID && 0 == pConnectParams->clientIDLen)) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Check needed here before we start writing to the Tx buffer */ - switch(pConnectParams->MQTTVersion) { - case MQTT_3_1_1: - break; - default: - return MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR; - } - - ptr = pTxBuf; - len = _aws_iot_get_connect_packet_length(pConnectParams); - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, CONNECT, QOS0, 0, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, len); /* write remaining length */ - - // Enable if adding support for more versions - //if(MQTT_3_1_1 == pConnectParams->MQTTVersion) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, "MQTT", 4); - aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pConnectParams->MQTTVersion); - //} - - flags = 0; - if (pConnectParams->isCleanSession) - { - flags |= 1 << 1; - } - - if (pConnectParams->isWillMsgPresent) - { - flags |= 1 << 2; - flags |= (uint8_t) (pConnectParams->will.qos << 3); - flags |= (uint8_t) (pConnectParams->will.isRetained << 5); - } - - if(pConnectParams->pPassword) { - flags |= 1 << 6; - } - - if(pConnectParams->pUsername) { - flags |= 1 << 7; - } - - aws_iot_mqtt_internal_write_char(&ptr, flags); - aws_iot_mqtt_internal_write_uint_16(&ptr, pConnectParams->keepAliveIntervalInSec); - - /* If the code have passed the check for incorrect values above, no client id was passed as argument */ - if(NULL == pConnectParams->pClientID) { - aws_iot_mqtt_internal_write_uint_16(&ptr, 0); - } else { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pClientID, pConnectParams->clientIDLen); - } - - if(pConnectParams->isWillMsgPresent) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pTopicName, - pConnectParams->will.topicNameLen); - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pMessage, pConnectParams->will.msgLen); - } - - if(pConnectParams->pUsername) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pUsername, pConnectParams->usernameLen); - } - - if(pConnectParams->pPassword) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pPassword, pConnectParams->passwordLen); - } - - *pSerializedLen = (size_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Deserializes the supplied (wire) buffer into connack data - return code - * @param sessionPresent the session present flag returned (only for MQTT 3.1.1) - * @param connack_rc returned integer value of the connack return code - * @param buf the raw buffer data, of the correct length determined by the remaining length field - * @param buflen the length in bytes of the data in the supplied buffer - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_deserialize_connack(unsigned char *pSessionPresent, IoT_Error_t *pConnackRc, - unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char *curdata, *enddata; - unsigned char connack_rc_char; - uint32_t decodedLen, readBytesLen; - IoT_Error_t rc; - uint8_t flags = 0u; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - if(NULL == pSessionPresent || NULL == pConnackRc || NULL == pRxBuf) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* CONNACK header size is fixed at two bytes for fixed and 2 bytes for variable, - * using that as minimum size - * MQTT v3.1.1 Specification 3.2.1 */ - if(4 > rxBufLen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - curdata = pRxBuf; - enddata = NULL; - decodedLen = 0; - readBytesLen = 0; - - header.byte = aws_iot_mqtt_internal_read_char(&curdata); - if(CONNACK != MQTT_HEADER_FIELD_TYPE(header.byte)) { - FUNC_EXIT_RC(FAILURE); - } - - /* read remaining length */ - rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* CONNACK remaining length should always be 2 as per MQTT 3.1.1 spec */ - curdata += (readBytesLen); - enddata = curdata + decodedLen; - if(2 != (enddata - curdata)) { - FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR); - } - - flags = aws_iot_mqtt_internal_read_char(&curdata); - /* Session present is in the LSb. */ - *pSessionPresent = (flags & 0x01); - connack_rc_char = aws_iot_mqtt_internal_read_char(&curdata); - switch(connack_rc_char) { - case CONNACK_CONNECTION_ACCEPTED: - *pConnackRc = MQTT_CONNACK_CONNECTION_ACCEPTED; - break; - case CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR: - *pConnackRc = MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR; - break; - case CONNACK_IDENTIFIER_REJECTED_ERROR: - *pConnackRc = MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR; - break; - case CONNACK_SERVER_UNAVAILABLE_ERROR: - *pConnackRc = MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR; - break; - case CONNACK_BAD_USERDATA_ERROR: - *pConnackRc = MQTT_CONNACK_BAD_USERDATA_ERROR; - break; - case CONNACK_NOT_AUTHORIZED_ERROR: - *pConnackRc = MQTT_CONNACK_NOT_AUTHORIZED_ERROR; - break; - default: - *pConnackRc = MQTT_CONNACK_UNKNOWN_ERROR; - break; - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Check if client state is valid for a connect request - * - * Called to check if client state is valid for a connect request - * @param pClient Reference to the IoT Client - * - * @return bool true = state is valid, false = not valid - */ -static bool _aws_iot_mqtt_is_client_state_valid_for_connect(ClientState clientState) { - bool isValid = false; - - switch(clientState) { - case CLIENT_STATE_INVALID: - isValid = false; - break; - case CLIENT_STATE_INITIALIZED: - isValid = true; - break; - case CLIENT_STATE_CONNECTING: - case CLIENT_STATE_CONNECTED_IDLE: - case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN: - case CLIENT_STATE_DISCONNECTING: - isValid = false; - break; - case CLIENT_STATE_DISCONNECTED_ERROR: - case CLIENT_STATE_DISCONNECTED_MANUALLY: - case CLIENT_STATE_PENDING_RECONNECT: - isValid = true; - break; - default: - break; - } - - return isValid; -} - -/** - * @brief MQTT Connection Function - * - * Called to establish an MQTT connection with the AWS IoT Service - * This is the internal function which is called by the connect API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param pConnectParams Pointer to MQTT connection parameters - * - * @return An IoT Error Type defining successful/failed connection - */ -static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams) { - Timer connect_timer; - IoT_Error_t connack_rc = FAILURE; - char sessionPresent = 0; - size_t len = 0; - IoT_Error_t rc = FAILURE; - - FUNC_ENTRY; - - if(NULL != pConnectParams) { - /* override default options if new options were supplied */ - rc = aws_iot_mqtt_set_connect_params(pClient, pConnectParams); - if(SUCCESS != rc) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - } - - rc = pClient->networkStack.connect(&(pClient->networkStack), NULL); - if(SUCCESS != rc) { - /* TLS Connect failed, return error */ - FUNC_EXIT_RC(rc); - } - - init_timer(&connect_timer); - countdown_ms(&connect_timer, pClient->clientData.commandTimeoutMs); - - pClient->clientData.keepAliveInterval = pClient->clientData.options.keepAliveIntervalInSec; - rc = _aws_iot_mqtt_serialize_connect(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - &(pClient->clientData.options), &len); - if(SUCCESS != rc || 0 >= len) { - FUNC_EXIT_RC(rc); - } - - /* send the connect packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &connect_timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* this will be a blocking call, wait for the CONNACK */ - rc = aws_iot_mqtt_internal_wait_for_read(pClient, CONNACK, &connect_timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Received CONNACK, check the return code */ - rc = _aws_iot_mqtt_deserialize_connack((unsigned char *) &sessionPresent, &connack_rc, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - if(MQTT_CONNACK_CONNECTION_ACCEPTED != connack_rc) { - FUNC_EXIT_RC(connack_rc); - } - - /* Ensure that a ping request is sent after keepAliveInterval. */ - pClient->clientStatus.isPingOutstanding = false; - countdown_sec(&pClient->pingReqTimer, pClient->clientData.keepAliveInterval); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief MQTT Connection Function - * - * Called to establish an MQTT connection with the AWS IoT Service - * This is the outer function which does the validations and calls the internal connect above - * to perform the actual operation. It is also responsible for client state changes - * - * @param pClient Reference to the IoT Client - * @param pConnectParams Pointer to MQTT connection parameters - * - * @return An IoT Error Type defining successful/failed connection - */ -IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams) { - IoT_Error_t rc, disconRc; - ClientState clientState; - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - aws_iot_mqtt_internal_flushBuffers( pClient ); - clientState = aws_iot_mqtt_get_client_state(pClient); - - if(false == _aws_iot_mqtt_is_client_state_valid_for_connect(clientState)) { - /* Don't send connect packet again if we are already connected - * or in the process of connecting/disconnecting */ - FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR); - } - - aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTING); - - rc = _aws_iot_mqtt_internal_connect(pClient, pConnectParams); - - if(SUCCESS != rc) { - pClient->networkStack.disconnect(&(pClient->networkStack)); - disconRc = pClient->networkStack.destroy(&(pClient->networkStack)); - if (SUCCESS != disconRc) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_DISCONNECTED_ERROR); - } else { - aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_CONNECTED_IDLE); - } - - FUNC_EXIT_RC(rc); -} - -/** - * @brief Disconnect an MQTT Connection - * - * Called to send a disconnect message to the broker. - * This is the internal function which is called by the disconnect API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed send of the disconnect control packet. - */ -static IoT_Error_t _aws_iot_mqtt_internal_disconnect(AWS_IoT_Client *pClient) { - /* We might wait for incomplete incoming publishes to complete */ - Timer timer; - size_t serialized_len = 0; - IoT_Error_t rc; - - FUNC_ENTRY; - - rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - DISCONNECT, - &serialized_len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - /* send the disconnect packet */ - if(serialized_len > 0) { - (void)aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer); - } - - /* Clean network stack */ - pClient->networkStack.disconnect(&(pClient->networkStack)); - rc = pClient->networkStack.destroy(&(pClient->networkStack)); - if(SUCCESS != rc) { - /* TLS Destroy failed, return error */ - FUNC_EXIT_RC(FAILURE); - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient) { - ClientState clientState; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(!aws_iot_mqtt_is_client_connected(pClient)) { - /* Network is already disconnected. Do nothing */ - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_DISCONNECTING); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = _aws_iot_mqtt_internal_disconnect(pClient); - - if(SUCCESS != rc) { - pClient->clientStatus.clientState = clientState; - } else { - /* If called from Keepalive, this gets set to CLIENT_STATE_DISCONNECTED_ERROR */ - pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_MANUALLY; - } - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient) { - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Only attempt a connect if not already connected. */ - if(!aws_iot_mqtt_is_client_connected(pClient)) { - /* Ignoring return code. failures expected if network is disconnected */ - aws_iot_mqtt_connect(pClient, NULL); - - /* If still disconnected handle disconnect */ - if(CLIENT_STATE_CONNECTED_IDLE != aws_iot_mqtt_get_client_state(pClient)) { - aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_DISCONNECTED_ERROR, CLIENT_STATE_PENDING_RECONNECT); - FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT); - } - } - else { - /* If already connected and no subscribe operation pending, then return - already connected error. */ - if(CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS != aws_iot_mqtt_get_client_state(pClient)) { - FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR); - } - } - - rc = aws_iot_mqtt_resubscribe(pClient); - if(SUCCESS != rc) { - FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT); - } - - FUNC_EXIT_RC(NETWORK_RECONNECTED); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c deleted file mode 100644 index 61822ad4a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c +++ /dev/null @@ -1,411 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144 - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_publish.c - * @brief MQTT client publish API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * @param stringVar pointer to the String into which the data is to be read - * @param stringLen pointer to variable which has the length of the string - * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned - * @param enddata pointer to the end of the data: do not read beyond - * @return SUCCESS if successful, FAILURE if not - */ -static IoT_Error_t _aws_iot_mqtt_read_string_with_len(char **stringVar, uint16_t *stringLen, - unsigned char **pptr, unsigned char *enddata) { - IoT_Error_t rc = FAILURE; - - FUNC_ENTRY; - /* the first two bytes are the length of the string */ - /* enough length to read the integer? */ - if(enddata - (*pptr) > 1) { - *stringLen = aws_iot_mqtt_internal_read_uint16_t(pptr); /* increments pptr to point past length */ - if(&(*pptr)[*stringLen] <= enddata) { - *stringVar = (char *) *pptr; - *pptr += *stringLen; - rc = SUCCESS; - } - } - - FUNC_EXIT_RC(rc); -} - -/** - * Serializes the supplied publish data into the supplied buffer, ready for sending - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer - * @param dup uint8_t - the MQTT dup flag - * @param qos QoS - the MQTT QoS value - * @param retained uint8_t - the MQTT retained flag - * @param packetId uint16_t - the MQTT packet identifier - * @param pTopicName char * - the MQTT topic in the publish - * @param topicNameLen uint16_t - the length of the Topic Name - * @param pPayload byte buffer - the MQTT publish payload - * @param payloadLen size_t - the length of the MQTT payload - * @param pSerializedLen uint32_t - pointer to the variable that stores serialized len - * - * @return An IoT Error Type defining successful/failed call - */ -static IoT_Error_t _aws_iot_mqtt_internal_serialize_publish(unsigned char *pTxBuf, size_t txBufLen, uint8_t dup, - QoS qos, uint8_t retained, uint16_t packetId, - const char *pTopicName, uint16_t topicNameLen, - const unsigned char *pPayload, size_t payloadLen, - uint32_t *pSerializedLen) { - unsigned char *ptr; - uint32_t rem_len; - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pTxBuf || NULL == pPayload || NULL == pSerializedLen) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - ptr = pTxBuf; - rem_len = 0; - - rem_len += (uint32_t) (topicNameLen + payloadLen + 2); - if(qos > 0) { - rem_len += 2; /* packetId */ - } - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, PUBLISH, qos, dup, retained); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); /* write remaining length */; - - aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicName, topicNameLen); - - if(qos > 0) { - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - } - - memcpy(ptr, pPayload, payloadLen); - ptr += payloadLen; - - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Serializes the ack packet into the supplied buffer. - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer - * @param msgType the MQTT packet type - * @param dup the MQTT dup flag - * @param packetId the MQTT packet identifier - * @param pSerializedLen uint32_t - pointer to the variable that stores serialized len - * - * @return An IoT Error Type defining successful/failed call - */ -IoT_Error_t aws_iot_mqtt_internal_serialize_ack(unsigned char *pTxBuf, size_t txBufLen, - MessageTypes msgType, uint8_t dup, uint16_t packetId, - uint32_t *pSerializedLen) { - unsigned char *ptr; - QoS requestQoS; - IoT_Error_t rc; - MQTTHeader header = {0}; - FUNC_ENTRY; - if(NULL == pTxBuf || pSerializedLen == NULL) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - ptr = pTxBuf; - - /* Minimum byte length required by ACK headers is - * 2 for fixed and 2 for variable part */ - if(4 > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - requestQoS = (PUBREL == msgType) ? QOS1 : QOS0; - rc = aws_iot_mqtt_internal_init_header(&header, msgType, requestQoS, dup, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, 2); /* write remaining length */ - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Publish an MQTT message on a topic - * - * Called to publish an MQTT message on a topic. - * @note Call is blocking. In the case of a QoS 0 message the function returns - * after the message was successfully passed to the TLS layer. In the case of QoS 1 - * the function returns after the receipt of the PUBACK control packet. - * This is the internal function which is called by the publish API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * @param pParams Pointer to Publish Message parameters - * - * @return An IoT Error Type defining successful/failed publish - */ -static IoT_Error_t _aws_iot_mqtt_internal_publish(AWS_IoT_Client *pClient, const char *pTopicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *pParams) { - Timer timer; - uint32_t len = 0; - uint16_t packet_id; - unsigned char dup, type; - IoT_Error_t rc; - - FUNC_ENTRY; - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - if(QOS1 == pParams->qos) { - pParams->id = aws_iot_mqtt_get_next_packet_id(pClient); - } - - rc = _aws_iot_mqtt_internal_serialize_publish(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - pParams->qos, pParams->isRetained, pParams->id, pTopicName, - topicNameLen, (unsigned char *) pParams->payload, - pParams->payloadLen, &len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the publish packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Wait for ack if QoS1 */ - if(QOS1 == pParams->qos) { - rc = aws_iot_mqtt_internal_wait_for_read(pClient, PUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = aws_iot_mqtt_internal_deserialize_ack(&type, &dup, &packet_id, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *pParams) { - IoT_Error_t rc, pubRc; - ClientState clientState; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pTopicName || 0 == topicNameLen || NULL == pParams) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - pubRc = _aws_iot_mqtt_internal_publish(pClient, pTopicName, topicNameLen, pParams); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS, clientState); - if(SUCCESS == pubRc && SUCCESS != rc) { - pubRc = rc; - } - - FUNC_EXIT_RC(pubRc); -} - -/** - * Deserializes the supplied (wire) buffer into publish data - * @param dup returned uint8_t - the MQTT dup flag - * @param qos returned QoS type - the MQTT QoS value - * @param retained returned uint8_t - the MQTT retained flag - * @param pPacketId returned uint16_t - the MQTT packet identifier - * @param pTopicName returned String - the MQTT topic in the publish - * @param topicNameLen returned uint16_t - the length of the MQTT topic in the publish - * @param payload returned byte buffer - the MQTT publish payload - * @param payloadLen returned size_t - the length of the MQTT payload - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBufLen the length in bytes of the data in the supplied buffer - * - * @return An IoT Error Type defining successful/failed call - */ -IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos, - uint8_t *retained, uint16_t *pPacketId, - char **pTopicName, uint16_t *topicNameLen, - unsigned char **payload, size_t *payloadLen, - unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char *curData = pRxBuf; - unsigned char *endData = NULL; - IoT_Error_t rc = FAILURE; - uint32_t decodedLen = 0; - uint32_t readBytesLen = 0; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - if(NULL == dup || NULL == qos || NULL == retained || NULL == pPacketId) { - FUNC_EXIT_RC(FAILURE); - } - - /* Publish header size is at least four bytes. - * Fixed header is two bytes. - * Variable header size depends on QoS And Topic Name. - * QoS level 0 doesn't have a message identifier (0 - 2 bytes) - * Topic Name length fields decide size of topic name field (at least 2 bytes) - * MQTT v3.1.1 Specification 3.3.1 */ - if(4 > rxBufLen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - header.byte = aws_iot_mqtt_internal_read_char(&curData); - if(PUBLISH != MQTT_HEADER_FIELD_TYPE(header.byte)) { - FUNC_EXIT_RC(FAILURE); - } - - *dup = MQTT_HEADER_FIELD_DUP(header.byte); - *qos = (QoS) MQTT_HEADER_FIELD_QOS(header.byte); - *retained = MQTT_HEADER_FIELD_RETAIN(header.byte); - - /* read remaining length */ - rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - curData += (readBytesLen); - endData = curData + decodedLen; - - /* do we have enough data to read the protocol version byte? */ - if(SUCCESS != _aws_iot_mqtt_read_string_with_len(pTopicName, topicNameLen, &curData, endData) - || (0 > (endData - curData))) { - FUNC_EXIT_RC(FAILURE); - } - - if(QOS0 != *qos) { - *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData); - } - - *payloadLen = (size_t) (endData - curData); - *payload = curData; - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Deserializes the supplied (wire) buffer into an ack - * @param pPacketType returned integer - the MQTT packet type - * @param dup returned integer - the MQTT dup flag - * @param pPacketId returned integer - the MQTT packet identifier - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBuflen the length in bytes of the data in the supplied buffer - * - * @return An IoT Error Type defining successful/failed call - */ -IoT_Error_t aws_iot_mqtt_internal_deserialize_ack(unsigned char *pPacketType, unsigned char *dup, - uint16_t *pPacketId, unsigned char *pRxBuf, - size_t rxBuflen) { - IoT_Error_t rc = FAILURE; - unsigned char *curdata = pRxBuf; - unsigned char *enddata = NULL; - uint32_t decodedLen = 0; - uint32_t readBytesLen = 0; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - if(NULL == pPacketType || NULL == dup || NULL == pPacketId || NULL == pRxBuf) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* PUBACK fixed header size is two bytes, variable header is 2 bytes, MQTT v3.1.1 Specification 3.4.1 */ - if(4 > rxBuflen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - - header.byte = aws_iot_mqtt_internal_read_char(&curdata); - *dup = MQTT_HEADER_FIELD_DUP(header.byte); - *pPacketType = MQTT_HEADER_FIELD_TYPE(header.byte); - - /* read remaining length */ - rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - curdata += (readBytesLen); - enddata = curdata + decodedLen; - - if(enddata - curdata < 2) { - FUNC_EXIT_RC(FAILURE); - } - - *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curdata); - - FUNC_EXIT_RC(SUCCESS); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c deleted file mode 100644 index 00e091709..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c +++ /dev/null @@ -1,435 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_subscribe.c - * @brief MQTT client subscribe API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * Serializes the supplied subscribe data into the supplied buffer, ready for sending - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer - * @param dup unsigned char - the MQTT dup flag - * @param packetId uint16_t - the MQTT packet identifier - * @param topicCount - number of members in the topicFilters and reqQos arrays - * @param pTopicNameList - array of topic filter names - * @param pTopicNameLenList - array of length of topic filter names - * @param pRequestedQoSs - array of requested QoS - * @param pSerializedLen - the length of the serialized data - * - * @return An IoT Error Type defining successful/failed operation - */ -static IoT_Error_t _aws_iot_mqtt_serialize_subscribe(unsigned char *pTxBuf, size_t txBufLen, - unsigned char dup, uint16_t packetId, uint32_t topicCount, - const char **pTopicNameList, uint16_t *pTopicNameLenList, - QoS *pRequestedQoSs, uint32_t *pSerializedLen) { - unsigned char *ptr; - uint32_t itr, rem_len; - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pTxBuf || NULL == pSerializedLen) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - ptr = pTxBuf; - rem_len = 2; /* packetId */ - - for(itr = 0; itr < topicCount; ++itr) { - rem_len += (uint32_t) (pTopicNameLenList[itr] + 2 + 1); /* topic + length + req_qos */ - } - - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, SUBSCRIBE, QOS1, dup, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - /* write header */ - aws_iot_mqtt_internal_write_char(&ptr, header.byte); - - /* write remaining length */ - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); - - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - - for(itr = 0; itr < topicCount; ++itr) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[itr], pTopicNameLenList[itr]); - aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pRequestedQoSs[itr]); - } - - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Deserializes the supplied (wire) buffer into suback data - * @param pPacketId returned integer - the MQTT packet identifier - * @param maxExpectedQoSCount - the maximum number of members allowed in the grantedQoSs array - * @param pGrantedQoSCount returned uint32_t - number of members in the grantedQoSs array - * @param pGrantedQoSs returned array of QoS type - the granted qualities of service - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBufLen the length in bytes of the data in the supplied buffer - * - * @return An IoT Error Type defining successful/failed operation - */ -static IoT_Error_t _aws_iot_mqtt_deserialize_suback(uint16_t *pPacketId, uint32_t maxExpectedQoSCount, - uint32_t *pGrantedQoSCount, QoS *pGrantedQoSs, - unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char *curData, *endData; - uint32_t decodedLen, readBytesLen; - IoT_Error_t decodeRc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pPacketId || NULL == pGrantedQoSCount || NULL == pGrantedQoSs) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - curData = pRxBuf; - endData = NULL; - decodeRc = FAILURE; - decodedLen = 0; - readBytesLen = 0; - - /* SUBACK header size is 4 bytes for header and at least one byte for QoS payload - * Need at least a 5 bytes buffer. MQTT3.1.1 specification 3.9 - */ - if(5 > rxBufLen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - header.byte = aws_iot_mqtt_internal_read_char(&curData); - if(SUBACK != MQTT_HEADER_FIELD_TYPE(header.byte)) { - FUNC_EXIT_RC(FAILURE); - } - - /* read remaining length */ - decodeRc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen); - if(SUCCESS != decodeRc) { - FUNC_EXIT_RC(decodeRc); - } - - curData += (readBytesLen); - endData = curData + decodedLen; - if(endData - curData < 2) { - FUNC_EXIT_RC(FAILURE); - } - - *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData); - - *pGrantedQoSCount = 0; - while(curData < endData) { - if(*pGrantedQoSCount > maxExpectedQoSCount) { - FUNC_EXIT_RC(FAILURE); - } - pGrantedQoSs[(*pGrantedQoSCount)++] = (QoS) aws_iot_mqtt_internal_read_char(&curData); - } - - FUNC_EXIT_RC(SUCCESS); -} - -/* Returns MAX_MESSAGE_HANDLERS value if no free index is available */ -static uint32_t _aws_iot_mqtt_get_free_message_handler_index(AWS_IoT_Client *pClient) { - uint32_t itr; - - FUNC_ENTRY; - - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) { - if(pClient->clientData.messageHandlers[itr].topicName == NULL) { - break; - } - } - - FUNC_EXIT_RC(itr); -} - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to send a subscribe message to the broker requesting a subscription - * to an MQTT topic. This is the internal function which is called by the - * subscribe API to perform the operation. Not meant to be called directly as - * it doesn't do validations or client state changes - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * @warning pTopicName and pApplicationHandlerData need to be static in memory. - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to. pTopicName needs to be static in memory since - * no malloc are performed by the SDK - * @param topicNameLen Length of the topic name - * @param pApplicationHandler_t Reference to the handler function for this subscription - * @param pApplicationHandlerData Point to data passed to the callback. - * pApplicationHandlerData also needs to be static in memory since no malloc are performed by the SDK - * - * @return An IoT Error Type defining successful/failed subscription - */ -static IoT_Error_t _aws_iot_mqtt_internal_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, - uint16_t topicNameLen, QoS qos, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData) { - uint16_t txPacketId, rxPacketId; - uint32_t serializedLen, indexOfFreeMessageHandler, count; - IoT_Error_t rc; - Timer timer; - QoS grantedQoS[3] = {QOS0, QOS0, QOS0}; - - FUNC_ENTRY; - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - serializedLen = 0; - count = 0; - txPacketId = aws_iot_mqtt_get_next_packet_id(pClient); - rxPacketId = 0; - - rc = _aws_iot_mqtt_serialize_subscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - txPacketId, 1, &pTopicName, &topicNameLen, &qos, &serializedLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - indexOfFreeMessageHandler = _aws_iot_mqtt_get_free_message_handler_index(pClient); - if(AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS <= indexOfFreeMessageHandler) { - FUNC_EXIT_RC(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR); - } - - /* send the subscribe packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, serializedLen, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* wait for suback */ - rc = aws_iot_mqtt_internal_wait_for_read(pClient, SUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Granted QoS can be 0, 1 or 2 */ - rc = _aws_iot_mqtt_deserialize_suback(&rxPacketId, 1, &count, grantedQoS, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* TODO : Figure out how to test this before activating this check */ - //if(txPacketId != rxPacketId) { - /* Different SUBACK received than expected. Return error - * This can cause issues if the request timeout value is too small */ - // return RX_MESSAGE_INVALID_ERROR; - //} - - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].topicName = - pTopicName; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].topicNameLen = - topicNameLen; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].pApplicationHandler = - pApplicationHandler; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].pApplicationHandlerData = - pApplicationHandlerData; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].qos = qos; - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData) { - ClientState clientState; - IoT_Error_t rc, subRc; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pTopicName || NULL == pApplicationHandler) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - subRc = _aws_iot_mqtt_internal_subscribe(pClient, pTopicName, topicNameLen, qos, - pApplicationHandler, pApplicationHandlerData); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS, clientState); - if(SUCCESS == subRc && SUCCESS != rc) { - subRc = rc; - } - - FUNC_EXIT_RC(subRc); -} - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to send a subscribe message to the broker requesting a subscription - * to an MQTT topic. - * This is the internal function which is called by the resubscribe API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed subscription - */ -static IoT_Error_t _aws_iot_mqtt_internal_resubscribe(AWS_IoT_Client *pClient) { - uint16_t packetId; - uint32_t len, count, existingSubCount, itr; - IoT_Error_t rc; - Timer timer; - QoS grantedQoS[3] = {QOS0, QOS0, QOS0}; - - FUNC_ENTRY; - - packetId = 0; - len = 0; - count = 0; - existingSubCount = _aws_iot_mqtt_get_free_message_handler_index(pClient); - - for(itr = 0; itr < existingSubCount; itr++) { - if(pClient->clientData.messageHandlers[itr].topicName == NULL) { - continue; - } - - /* Do not attempt to subscribe to topics which have already been subscribed - to in the previous re-subscribe attempts. */ - if(pClient->clientData.messageHandlers[itr].resubscribed == 1) { - continue; - } - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - rc = _aws_iot_mqtt_serialize_subscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - aws_iot_mqtt_get_next_packet_id(pClient), 1, - &(pClient->clientData.messageHandlers[itr].topicName), - &(pClient->clientData.messageHandlers[itr].topicNameLen), - &(pClient->clientData.messageHandlers[itr].qos), &len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the subscribe packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* wait for suback */ - rc = aws_iot_mqtt_internal_wait_for_read(pClient, SUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Granted QoS can be 0, 1 or 2 */ - rc = _aws_iot_mqtt_deserialize_suback(&packetId, 1, &count, grantedQoS, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Record that this topic has been subscribed to, so that we do not - * attempt to subscribe again to the same topic. */ - pClient->clientData.messageHandlers[itr].resubscribed = 1; - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient) { - IoT_Error_t rc, resubRc; - ClientState currentState = aws_iot_mqtt_get_client_state(pClient); - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(false == aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - /* At this point, the client state should be either CLIENT_STATE_CONNECTED_IDLE - or CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS. The former means that it - is the first re-subscribe attempt while the latter means that it is second - or subsequent re-subscribe attempt. */ - if((CLIENT_STATE_CONNECTED_IDLE != currentState) && (CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS != currentState)) { - FUNC_EXIT_RC(MQTT_UNEXPECTED_CLIENT_STATE_ERROR); - } - - /* If it is the first re-subscribe attempt (i.e. client state is CLIENT_STATE_CONNECTED_IDLE), - set the client state to CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS. */ - if(CLIENT_STATE_CONNECTED_IDLE == currentState) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - } - - resubRc = _aws_iot_mqtt_internal_resubscribe(pClient); - - /* It is possible that the subscribe operation fails, do not change the state - in that case so that the subscribe is attempted again in the next iteration - of yield. */ - if(SUCCESS == resubRc) { - resubRc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS, CLIENT_STATE_CONNECTED_IDLE); - } - - FUNC_EXIT_RC(resubRc); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c deleted file mode 100644 index 1d78a7477..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c +++ /dev/null @@ -1,234 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_unsubscribe.c - * @brief MQTT client unsubscribe API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending - * @param pTxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param txBufLen the length in bytes of the data in the supplied buffer - * @param dup integer - the MQTT dup flag - * @param packetId integer - the MQTT packet identifier - * @param count - number of members in the topicFilters array - * @param pTopicNameList - array of topic filter names - * @param pTopicNameLenList - array of length of topic filter names in pTopicNameList - * @param pSerializedLen - the length of the serialized data - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_serialize_unsubscribe(unsigned char *pTxBuf, size_t txBufLen, - uint8_t dup, uint16_t packetId, - uint32_t count, const char **pTopicNameList, - uint16_t *pTopicNameLenList, uint32_t *pSerializedLen) { - unsigned char *ptr = pTxBuf; - uint32_t i = 0; - uint32_t rem_len = 2; /* packetId */ - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - for(i = 0; i < count; ++i) { - rem_len += (uint32_t) (pTopicNameLenList[i] + 2); /* topic + length */ - } - - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, UNSUBSCRIBE, QOS1, dup, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); /* write remaining length */ - - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - - for(i = 0; i < count; ++i) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[i], pTopicNameLenList[i]); - } - - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - - -/** - * Deserializes the supplied (wire) buffer into unsuback data - * @param pPacketId returned integer - the MQTT packet identifier - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBufLen the length in bytes of the data in the supplied buffer - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_deserialize_unsuback(uint16_t *pPacketId, unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char type = 0; - unsigned char dup = 0; - IoT_Error_t rc; - - FUNC_ENTRY; - - rc = aws_iot_mqtt_internal_deserialize_ack(&type, &dup, pPacketId, pRxBuf, rxBufLen); - if(SUCCESS == rc && UNSUBACK != type) { - rc = FAILURE; - } - - FUNC_EXIT_RC(rc); -} - -/** - * @brief Unsubscribe to an MQTT topic. - * - * Called to send an unsubscribe message to the broker requesting removal of a subscription - * to an MQTT topic. - * @note Call is blocking. The call returns after the receipt of the UNSUBACK control packet. - * This is the internal function which is called by the unsubscribe API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * - * @return An IoT Error Type defining successful/failed unsubscribe call - */ -static IoT_Error_t _aws_iot_mqtt_internal_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, - uint16_t topicFilterLen) { - /* No NULL checks because this is a static internal function */ - - Timer timer; - - uint16_t packet_id; - uint32_t serializedLen = 0; - uint32_t i = 0; - IoT_Error_t rc; - bool subscriptionExists = false; - - FUNC_ENTRY; - - /* Remove from message handler array */ - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { - if(pClient->clientData.messageHandlers[i].topicName != NULL && - (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) { - subscriptionExists = true; - break; - } - } - - if(false == subscriptionExists) { - FUNC_EXIT_RC(FAILURE); - } - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - rc = _aws_iot_mqtt_serialize_unsubscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - aws_iot_mqtt_get_next_packet_id(pClient), 1, &pTopicFilter, - &topicFilterLen, &serializedLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the unsubscribe packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, serializedLen, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = aws_iot_mqtt_internal_wait_for_read(pClient, UNSUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = _aws_iot_mqtt_deserialize_unsuback(&packet_id, pClient->clientData.readBuf, pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Remove from message handler array */ - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { - if(pClient->clientData.messageHandlers[i].topicName != NULL && - (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) { - pClient->clientData.messageHandlers[i].topicName = NULL; - /* We don't want to break here, in case the same topic is registered - * with 2 callbacks. Unlikely scenario */ - } - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen) { - IoT_Error_t rc, unsubRc; - ClientState clientState; - - if(NULL == pClient || NULL == pTopicFilter) { - return NULL_VALUE_ERROR; - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - return NETWORK_DISCONNECTED_ERROR; - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { - return MQTT_CLIENT_NOT_IDLE_ERROR; - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS); - if(SUCCESS != rc) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState); - return rc; - } - - unsubRc = _aws_iot_mqtt_internal_unsubscribe(pClient, pTopicFilter, topicFilterLen); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState); - if(SUCCESS == unsubRc && SUCCESS != rc) { - unsubRc = rc; - } - - return unsubRc; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c deleted file mode 100644 index 25a46cbfe..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c +++ /dev/null @@ -1,325 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_yield.c - * @brief MQTT client yield API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * This is for the case when the aws_iot_mqtt_internal_send_packet Fails. - */ -static void _aws_iot_mqtt_force_client_disconnect(AWS_IoT_Client *pClient) { - pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR; - pClient->networkStack.disconnect(&(pClient->networkStack)); - pClient->networkStack.destroy(&(pClient->networkStack)); -} - -static IoT_Error_t _aws_iot_mqtt_handle_disconnect(AWS_IoT_Client *pClient) { - IoT_Error_t rc; - - FUNC_ENTRY; - - rc = aws_iot_mqtt_disconnect(pClient); - if(rc != SUCCESS) { - // If the aws_iot_mqtt_internal_send_packet prevents us from sending a disconnect packet then we have to clean the stack - _aws_iot_mqtt_force_client_disconnect(pClient); - } - - pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR; - - if(NULL != pClient->clientData.disconnectHandler) { - pClient->clientData.disconnectHandler(pClient, pClient->clientData.disconnectHandlerData); - } - - if (pClient->clientStatus.clientState == CLIENT_STATE_CONNECTED_IDLE) { - FUNC_EXIT_RC(SUCCESS); - } - - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); -} - - -static IoT_Error_t _aws_iot_mqtt_handle_reconnect(AWS_IoT_Client *pClient) { - IoT_Error_t rc; - - FUNC_ENTRY; - - if(!has_timer_expired(&(pClient->reconnectDelayTimer))) { - /* Timer has not expired. Not time to attempt reconnect yet. - * Return attempting reconnect */ - FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT); - } - - rc = NETWORK_PHYSICAL_LAYER_DISCONNECTED; - if(NULL != pClient->networkStack.isConnected) { - rc = pClient->networkStack.isConnected(&(pClient->networkStack)); - } - - if(NETWORK_PHYSICAL_LAYER_CONNECTED == rc) { - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, - CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - FUNC_EXIT_RC(NETWORK_RECONNECTED); - } - } - - pClient->clientData.currentReconnectWaitInterval *= 2; - - if(AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL < pClient->clientData.currentReconnectWaitInterval) { - FUNC_EXIT_RC(NETWORK_RECONNECT_TIMED_OUT_ERROR); - } - countdown_ms(&(pClient->reconnectDelayTimer), pClient->clientData.currentReconnectWaitInterval); - FUNC_EXIT_RC(rc); -} - -static IoT_Error_t _aws_iot_mqtt_keep_alive(AWS_IoT_Client *pClient) { - IoT_Error_t rc = SUCCESS; - Timer timer; - size_t serialized_len; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(0 == pClient->clientData.keepAliveInterval) { - FUNC_EXIT_RC(SUCCESS); - } - - if(pClient->clientStatus.isPingOutstanding) { - /* We are waiting for a PINGRESP from the broker. If the pingRespTimer, - * has expired, it indicates that the transport layer connection is - * lost and therefore, we initiate MQTT disconnect (which will triggger) - * the re-connect workflow, if enabled. If the pingRespTimer is not - * expired, there is nothing to do and we continue waiting for PINGRESP. */ - if(has_timer_expired(&pClient->pingRespTimer)) { - rc = _aws_iot_mqtt_handle_disconnect(pClient); - FUNC_EXIT_RC(rc); - } else { - FUNC_EXIT_RC(SUCCESS); - } - } else { - /* We are not waiting for a PINGRESP from the broker. If the - * pingReqTimer has expired, we send a PINGREQ. Otherwise, there is - * nothing to do. */ - if(!has_timer_expired(&pClient->pingReqTimer)) { - FUNC_EXIT_RC(SUCCESS); - } - } - - - /* there is no ping outstanding - send one */ - init_timer(&timer); - - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - serialized_len = 0; - rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - PINGREQ, &serialized_len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the ping packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer); - if(SUCCESS != rc) { - //If sending a PING fails we can no longer determine if we are connected. In this case we decide we are disconnected and begin reconnection attempts - rc = _aws_iot_mqtt_handle_disconnect(pClient); - FUNC_EXIT_RC(rc); - } - - pClient->clientStatus.isPingOutstanding = true; - /* Start a timer to wait for PINGRESP from server. */ - countdown_sec(&pClient->pingRespTimer, pClient->clientData.keepAliveInterval); - /* Start a timer to keep track of when to send the next PINGREQ. */ - countdown_sec(&pClient->pingReqTimer, pClient->clientData.keepAliveInterval); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Yield to the MQTT client - * - * Called to yield the current thread to the underlying MQTT client. This time is used by - * the MQTT client to manage PING requests to monitor the health of the TCP connection as - * well as periodically check the socket receive buffer for subscribe messages. Yield() - * must be called at a rate faster than the keepalive interval. It must also be called - * at a rate faster than the incoming message rate as this is the only way the client receives - * processing time to manage incoming messages. - * This is the internal function which is called by the yield API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param timeout_ms Maximum number of milliseconds to pass thread execution to the client. - * - * @return An IoT Error Type defining successful/failed client processing. - * If this call results in an error it is likely the MQTT connection has dropped. - * iot_is_mqtt_connected can be called to confirm. - */ - -static IoT_Error_t _aws_iot_mqtt_internal_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms) { - IoT_Error_t yieldRc = SUCCESS; - int itr = 0; - - uint8_t packet_type; - ClientState clientState; - Timer timer; - init_timer(&timer); - countdown_ms(&timer, timeout_ms); - - FUNC_ENTRY; - - // evaluate timeout at the end of the loop to make sure the actual yield runs at least once - do { - clientState = aws_iot_mqtt_get_client_state(pClient); - - /* If the client state is pending reconnect or resubscribe in progress, - we keep retrying _aws_iot_mqtt_handle_reconnect. This function only - attempts to connect if not already connected thereby ensuring that the - subsequent invocations only attempt remaining subscribes. */ - if((CLIENT_STATE_PENDING_RECONNECT == clientState) || - (CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS == clientState)) { - if(AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL < pClient->clientData.currentReconnectWaitInterval) { - yieldRc = NETWORK_RECONNECT_TIMED_OUT_ERROR; - break; - } - yieldRc = _aws_iot_mqtt_handle_reconnect(pClient); - /* Network reconnect attempted, check if yield timer expired before - * doing anything else */ - continue; - } - - yieldRc = aws_iot_mqtt_internal_cycle_read(pClient, &timer, &packet_type); - if(SUCCESS == yieldRc) { - yieldRc = _aws_iot_mqtt_keep_alive(pClient); - } else { - // SSL read and write errors are terminal, connection must be closed and retried - if(NETWORK_SSL_READ_ERROR == yieldRc || NETWORK_SSL_WRITE_ERROR == yieldRc || NETWORK_SSL_WRITE_TIMEOUT_ERROR == yieldRc) { - yieldRc = _aws_iot_mqtt_handle_disconnect(pClient); - } - } - - if(NETWORK_DISCONNECTED_ERROR == yieldRc) { - pClient->clientData.counterNetworkDisconnected++; - /* Always clear resubscribe flags. */ - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) { - pClient->clientData.messageHandlers[itr].resubscribed = 0; - } - - if(1 == pClient->clientStatus.isAutoReconnectEnabled) { - yieldRc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_DISCONNECTED_ERROR, - CLIENT_STATE_PENDING_RECONNECT); - if(SUCCESS != yieldRc) { - FUNC_EXIT_RC(yieldRc); - } - - pClient->clientData.currentReconnectWaitInterval = AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL; - countdown_ms(&(pClient->reconnectDelayTimer), pClient->clientData.currentReconnectWaitInterval); - - /* Depending on timer values, it is possible that yield timer has expired - * Set to rc to attempting reconnect to inform client that autoreconnect - * attempt has started */ - yieldRc = NETWORK_ATTEMPTING_RECONNECT; - } else { - break; - } - } else if(SUCCESS != yieldRc) { - break; - } - } while(!has_timer_expired(&timer)); - - FUNC_EXIT_RC(yieldRc); -} - -IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms) { - IoT_Error_t rc, yieldRc; - ClientState clientState; - - if(NULL == pClient || 0 == timeout_ms) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - /* Check if network was manually disconnected */ - if(CLIENT_STATE_DISCONNECTED_MANUALLY == clientState) { - FUNC_EXIT_RC(NETWORK_MANUALLY_DISCONNECTED); - } - - /* If we are in the pending reconnect or resubscribe in progress state, skip other checks. - * Pending reconnect or resubscribe in progress state is only set when auto-reconnect - * is enabled */ - if((CLIENT_STATE_PENDING_RECONNECT != clientState) && - (CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS != clientState)) { - /* Check if network is disconnected and auto-reconnect is not enabled */ - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - /* Check if client is idle, if not another operation is in progress and we should return */ - if(CLIENT_STATE_CONNECTED_IDLE != clientState) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, - CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - } - - yieldRc = _aws_iot_mqtt_internal_yield(pClient, timeout_ms); - - if(NETWORK_DISCONNECTED_ERROR != yieldRc && NETWORK_ATTEMPTING_RECONNECT != yieldRc) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS, - CLIENT_STATE_CONNECTED_IDLE); - if(SUCCESS == yieldRc && SUCCESS != rc) { - yieldRc = rc; - } - } - - FUNC_EXIT_RC(yieldRc); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c deleted file mode 100644 index 5c69edb05..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_shadow.c - * @brief Shadow client API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" -#include "aws_iot_error.h" -#include "aws_iot_log.h" -#include "aws_iot_shadow_actions.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_shadow_key.h" -#include "aws_iot_shadow_records.h" - -const ShadowInitParameters_t ShadowInitParametersDefault = {(char *) AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, NULL, NULL, - NULL, false, NULL}; - -const ShadowConnectParameters_t ShadowConnectParametersDefault = {(char *) AWS_IOT_MY_THING_NAME, - (char *) AWS_IOT_MQTT_CLIENT_ID, 0, NULL}; - -static char deleteAcceptedTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - -void aws_iot_shadow_reset_last_received_version(void) { - shadowJsonVersionNum = 0; -} - -uint32_t aws_iot_shadow_get_last_received_version(void) { - return shadowJsonVersionNum; -} - -void aws_iot_shadow_enable_discard_old_delta_msgs(void) { - shadowDiscardOldDeltaFlag = true; -} - -void aws_iot_shadow_disable_discard_old_delta_msgs(void) { - shadowDiscardOldDeltaFlag = false; -} - -IoT_Error_t aws_iot_shadow_free(AWS_IoT_Client *pClient) -{ - IoT_Error_t rc; - - if (NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - rc = aws_iot_mqtt_free(pClient); - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, ShadowInitParameters_t *pParams) { - IoT_Client_Init_Params mqttInitParams = IoT_Client_Init_Params_initializer; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pParams) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - mqttInitParams.enableAutoReconnect = pParams->enableAutoReconnect; - mqttInitParams.pHostURL = pParams->pHost; - mqttInitParams.port = pParams->port; - mqttInitParams.pRootCALocation = pParams->pRootCA; - mqttInitParams.pDeviceCertLocation = pParams->pClientCRT; - mqttInitParams.pDevicePrivateKeyLocation = pParams->pClientKey; - mqttInitParams.mqttPacketTimeout_ms = 5000; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = pParams->disconnectHandler; - - rc = aws_iot_mqtt_init(pClient, &mqttInitParams); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - resetClientTokenSequenceNum(); - aws_iot_shadow_reset_last_received_version(); - initDeltaTokens(); - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, ShadowConnectParameters_t *pParams) { - IoT_Error_t rc = SUCCESS; - uint16_t deleteAcceptedTopicLen; - IoT_Client_Connect_Params ConnectParams = iotClientConnectParamsDefault; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pParams || NULL == pParams->pMqttClientId) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - snprintf(myThingName, MAX_SIZE_OF_THING_NAME, "%s", pParams->pMyThingName); - snprintf(mqttClientID, MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES, "%s", pParams->pMqttClientId); - - ConnectParams.keepAliveIntervalInSec = 600; // NOTE: Temporary fix - ConnectParams.MQTTVersion = MQTT_3_1_1; - ConnectParams.isCleanSession = true; - ConnectParams.isWillMsgPresent = false; - ConnectParams.pClientID = pParams->pMqttClientId; - ConnectParams.clientIDLen = pParams->mqttClientIdLen; - ConnectParams.pPassword = NULL; - ConnectParams.pUsername = NULL; - - rc = aws_iot_mqtt_connect(pClient, &ConnectParams); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - initializeRecords(pClient); - - if(NULL != pParams->deleteActionHandler) { - snprintf(deleteAcceptedTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, - "$aws/things/%s/shadow/delete/accepted", myThingName); - deleteAcceptedTopicLen = (uint16_t) strlen(deleteAcceptedTopic); - rc = aws_iot_mqtt_subscribe(pClient, deleteAcceptedTopic, deleteAcceptedTopicLen, QOS1, - pParams->deleteActionHandler, (void *) myThingName); - } - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_register_delta(AWS_IoT_Client *pMqttClient, jsonStruct_t *pStruct) { - if(NULL == pMqttClient || NULL == pStruct) { - return NULL_VALUE_ERROR; - } - - if(!aws_iot_mqtt_is_client_connected(pMqttClient)) { - return MQTT_CONNECTION_ERROR; - } - - return registerJsonTokenOnDelta(pStruct); -} - -IoT_Error_t aws_iot_shadow_yield(AWS_IoT_Client *pClient, uint32_t timeout) { - if(NULL == pClient) { - return NULL_VALUE_ERROR; - } - - HandleExpiredResponseCallbacks(); - return aws_iot_mqtt_yield(pClient, timeout); -} - -IoT_Error_t aws_iot_shadow_disconnect(AWS_IoT_Client *pClient) { - return aws_iot_mqtt_disconnect(pClient); -} - -IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingName, char *pJsonString, - fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, - bool isPersistentSubscribe) { - IoT_Error_t rc; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - - rc = aws_iot_shadow_internal_action(pThingName, SHADOW_UPDATE, pJsonString, strlen(pJsonString), callback, pContextData, - timeout_seconds, isPersistentSubscribe); - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_delete(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) { - char deleteRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - - rc = aws_iot_shadow_internal_delete_request_json(deleteRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE ); - if ( SUCCESS != rc ) { - FUNC_EXIT_RC( rc ); - } - - rc = aws_iot_shadow_internal_action(pThingName, SHADOW_DELETE, deleteRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE, callback, pContextData, - timeout_seconds, isPersistentSubscribe); - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) { - char getRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - - rc = aws_iot_shadow_internal_get_request_json(getRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE ); - if (SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = aws_iot_shadow_internal_action(pThingName, SHADOW_GET, getRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE, callback, pContextData, - timeout_seconds, isPersistentSubscribe); - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_set_autoreconnect_status(AWS_IoT_Client *pClient, bool newStatus) { - return aws_iot_mqtt_autoreconnect_set_status(pClient, newStatus); -} - -#ifdef __cplusplus -} -#endif - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c deleted file mode 100644 index 95b81c56f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_shadow_actions.c - * @brief Shadow client Action API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_actions.h" - -#include "aws_iot_log.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_shadow_records.h" -#include "aws_iot_config.h" - -IoT_Error_t aws_iot_shadow_internal_action(const char *pThingName, ShadowActions_t action, - const char *pJsonDocumentToBeSent, size_t jsonSize, fpActionCallback_t callback, - void *pCallbackContext, uint32_t timeout_seconds, bool isSticky) { - IoT_Error_t ret_val = SUCCESS; - bool isClientTokenPresent = false; - bool isAckWaitListFree = false; - uint8_t indexAckWaitList; - char extractedClientToken[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; - - FUNC_ENTRY; - - if(NULL == pThingName || NULL == pJsonDocumentToBeSent) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - isClientTokenPresent = extractClientToken(pJsonDocumentToBeSent, jsonSize, extractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE ); - - if(isClientTokenPresent && (NULL != callback)) { - if(getNextFreeIndexOfAckWaitList(&indexAckWaitList)) { - isAckWaitListFree = true; - } - - if(isAckWaitListFree) { - if(!isSubscriptionPresent(pThingName, action)) { - ret_val = subscribeToShadowActionAcks(pThingName, action, isSticky); - } else { - incrementSubscriptionCnt(pThingName, action, isSticky); - } - } - else { - ret_val = FAILURE; - } - } - - if(SUCCESS == ret_val) { - ret_val = publishToShadowAction(pThingName, action, pJsonDocumentToBeSent); - } - - if(isClientTokenPresent && (NULL != callback) && (SUCCESS == ret_val) && isAckWaitListFree) { - addToAckWaitList(indexAckWaitList, pThingName, action, extractedClientToken, callback, pCallbackContext, - timeout_seconds); - } - - FUNC_EXIT_RC(ret_val); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c deleted file mode 100644 index b1d777836..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_shadow_json.c - * @brief Shadow client JSON parsing API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_json.h" - -#include -#include - -#include "aws_iot_json_utils.h" -#include "aws_iot_log.h" -#include "aws_iot_shadow_key.h" -#include "aws_iot_config.h" - -extern char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; -#define AWS_IOT_SHADOW_CLIENT_TOKEN_KEY "{\"clientToken\":\"" -static uint32_t clientTokenNum = 0; - -//helper functions -static IoT_Error_t convertDataToString(char *pStringBuffer, size_t maxSizoStringBuffer, JsonPrimitiveType type, - void *pData); - -void resetClientTokenSequenceNum(void) { - clientTokenNum = 0; -} - -static IoT_Error_t emptyJsonWithClientToken(char *pBuffer, size_t bufferSize) { - - IoT_Error_t rc = SUCCESS; - size_t dataLenInBuffer = 0; - - if(pBuffer != NULL) - { - dataLenInBuffer = (size_t)snprintf(pBuffer, bufferSize, AWS_IOT_SHADOW_CLIENT_TOKEN_KEY); - }else - { - IOT_ERROR("NULL buffer in emptyJsonWithClientToken\n"); - rc = FAILURE; - } - - if(rc == SUCCESS) - { - if ( dataLenInBuffer < bufferSize ) - { - dataLenInBuffer += (size_t)snprintf(pBuffer + dataLenInBuffer, bufferSize - dataLenInBuffer, "%s-%d", mqttClientID, ( int )clientTokenNum++); - } - else - { - rc = FAILURE; - IOT_ERROR("Supplied buffer too small to create JSON file\n"); - } - } - - if(rc == SUCCESS) - { - if ( dataLenInBuffer < bufferSize ) - { - dataLenInBuffer += (size_t)snprintf( pBuffer + dataLenInBuffer, bufferSize - dataLenInBuffer, "\"}" ); - if ( dataLenInBuffer > bufferSize ) - { - rc = FAILURE; - IOT_ERROR( "Supplied buffer too small to create JSON file\n" ); - } - } - else - { - rc = FAILURE; - IOT_ERROR( "Supplied buffer too small to create JSON file\n" ); - } - } - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_internal_get_request_json(char *pBuffer, size_t bufferSize) { - return emptyJsonWithClientToken( pBuffer, bufferSize); -} - -IoT_Error_t aws_iot_shadow_internal_delete_request_json(char *pBuffer, size_t bufferSize ) { - return emptyJsonWithClientToken( pBuffer, bufferSize); -} - -static inline IoT_Error_t checkReturnValueOfSnPrintf(int32_t snPrintfReturn, size_t maxSizeOfJsonDocument) { - if(snPrintfReturn < 0) { - return SHADOW_JSON_ERROR; - } else if((size_t) snPrintfReturn >= maxSizeOfJsonDocument) { - return SHADOW_JSON_BUFFER_TRUNCATED; - } - return SUCCESS; -} - -IoT_Error_t aws_iot_shadow_init_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument) { - - IoT_Error_t ret_val = SUCCESS; - int32_t snPrintfReturn = 0; - - if(pJsonDocument == NULL) { - return NULL_VALUE_ERROR; - } - snPrintfReturn = snprintf(pJsonDocument, maxSizeOfJsonDocument, "{\"state\":{"); - - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, maxSizeOfJsonDocument); - - return ret_val; - -} - -IoT_Error_t aws_iot_shadow_add_desired(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...) { - IoT_Error_t ret_val = SUCCESS; - size_t tempSize = 0; - int8_t i; - size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; - int32_t snPrintfReturn = 0; - va_list pArgs; - jsonStruct_t *pTemporary = NULL; - va_start(pArgs, count); - - if(pJsonDocument == NULL) { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - va_end(pArgs); - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"desired\":{"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - - for(i = 0; i < count; i++) { - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - va_end(pArgs); - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - pTemporary = va_arg (pArgs, jsonStruct_t *); - if(pTemporary != NULL) { - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"%s\":", - pTemporary->pKey); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - if(pTemporary->pKey != NULL && pTemporary->pData != NULL) { - ret_val = convertDataToString(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, - pTemporary->type, pTemporary->pData); - } else { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - } else { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - } - - va_end(pArgs); - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "},"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - return ret_val; -} - -IoT_Error_t aws_iot_shadow_add_reported(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...) { - IoT_Error_t ret_val = SUCCESS; - - int8_t i; - size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; - int32_t snPrintfReturn = 0; - size_t tempSize = 0; - jsonStruct_t *pTemporary; - va_list pArgs; - va_start(pArgs, count); - - if(pJsonDocument == NULL) { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - - - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - va_end(pArgs); - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"reported\":{"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - - for(i = 0; i < count; i++) { - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - va_end(pArgs); - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - pTemporary = va_arg (pArgs, jsonStruct_t *); - if(pTemporary != NULL) { - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"%s\":", - pTemporary->pKey); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - if(pTemporary->pKey != NULL && pTemporary->pData != NULL) { - ret_val = convertDataToString(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, - pTemporary->type, pTemporary->pData); - } else { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - } else { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - } - - va_end(pArgs); - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "},"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - return ret_val; -} - - -int32_t FillWithClientTokenSize(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument) { - int32_t snPrintfReturn; - snPrintfReturn = snprintf(pBufferToBeUpdatedWithClientToken, maxSizeOfJsonDocument, "%s-%d", mqttClientID, - (int) clientTokenNum++); - - return snPrintfReturn; -} - -IoT_Error_t aws_iot_fill_with_client_token(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument) { - - int32_t snPrintfRet = 0; - snPrintfRet = FillWithClientTokenSize(pBufferToBeUpdatedWithClientToken, maxSizeOfJsonDocument); - return checkReturnValueOfSnPrintf(snPrintfRet, maxSizeOfJsonDocument); - -} - -IoT_Error_t aws_iot_finalize_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument) { - size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; - int32_t snPrintfReturn = 0; - size_t tempSize = 0; - IoT_Error_t ret_val = SUCCESS; - - if(pJsonDocument == NULL) { - return NULL_VALUE_ERROR; - } - - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - // strlen(ShadowTxBuffer) - 1 is to ensure we remove the last ,(comma) that was added - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "}, \"%s\":\"", - SHADOW_CLIENT_TOKEN_STRING); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - return ret_val; - } - // refactor this XXX repeated code - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - - snPrintfReturn = FillWithClientTokenSize(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - return ret_val; - } - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"}"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - return ret_val; -} - -static IoT_Error_t convertDataToString(char *pStringBuffer, size_t maxSizoStringBuffer, JsonPrimitiveType type, - void *pData) { - int32_t snPrintfReturn = 0; - IoT_Error_t ret_val = SUCCESS; - - if(maxSizoStringBuffer == 0) { - return SHADOW_JSON_ERROR; - } - - if(type == SHADOW_JSON_INT32) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%i,", *(int32_t *) (pData)); - } else if(type == SHADOW_JSON_INT16) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%hi,", *(int16_t *) (pData)); - } else if(type == SHADOW_JSON_INT8) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%hhi,", *(int8_t *) (pData)); - } else if(type == SHADOW_JSON_UINT32) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%u,", *(uint32_t *) (pData)); - } else if(type == SHADOW_JSON_UINT16) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%hu,", *(uint16_t *) (pData)); - } else if(type == SHADOW_JSON_UINT8) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%hhu,", *(uint8_t *) (pData)); - } else if(type == SHADOW_JSON_DOUBLE) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%f,", *(double *) (pData)); - } else if(type == SHADOW_JSON_FLOAT) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%f,", *(float *) (pData)); - } else if(type == SHADOW_JSON_BOOL) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%s,", *(bool *) (pData) ? "true" : "false"); - } else if(type == SHADOW_JSON_STRING) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "\"%s\",", (char *) (pData)); - } else if(type == SHADOW_JSON_OBJECT) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%s,", (char *) (pData)); - } - - - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, maxSizoStringBuffer); - - return ret_val; -} - -static jsmn_parser shadowJsonParser; -static jsmntok_t jsonTokenStruct[MAX_JSON_TOKEN_EXPECTED]; - -bool isJsonValidAndParse(const char *pJsonDocument, size_t jsonSize, void *pJsonHandler, int32_t *pTokenCount) { - int32_t tokenCount; - - IOT_UNUSED(pJsonHandler); - - jsmn_init(&shadowJsonParser); - - tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, jsonSize, jsonTokenStruct, - sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d\n", tokenCount); - return false; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object\n"); - return false; - } - - *pTokenCount = tokenCount; - - return true; -} - -static IoT_Error_t UpdateValueIfNoObject(const char *pJsonString, jsonStruct_t *pDataStruct, jsmntok_t token) { - IoT_Error_t ret_val = SHADOW_JSON_ERROR; - if(pDataStruct->type == SHADOW_JSON_BOOL && pDataStruct->dataLength >= sizeof(bool)) { - ret_val = parseBooleanValue((bool *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_INT32 && pDataStruct->dataLength >= sizeof(int32_t)) { - ret_val = parseInteger32Value((int32_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_INT16 && pDataStruct->dataLength >= sizeof(int16_t)) { - ret_val = parseInteger16Value((int16_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_INT8 && pDataStruct->dataLength >= sizeof(int8_t)) { - ret_val = parseInteger8Value((int8_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_UINT32 && pDataStruct->dataLength >= sizeof(uint32_t)) { - ret_val = parseUnsignedInteger32Value((uint32_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_UINT16 && pDataStruct->dataLength >= sizeof(uint16_t)) { - ret_val = parseUnsignedInteger16Value((uint16_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_UINT8 && pDataStruct->dataLength >= sizeof(uint8_t)) { - ret_val = parseUnsignedInteger8Value((uint8_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_FLOAT && pDataStruct->dataLength >= sizeof(float)) { - ret_val = parseFloatValue((float *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_DOUBLE && pDataStruct->dataLength >= sizeof(double)) { - ret_val = parseDoubleValue((double *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_STRING) { - ret_val = parseStringValue((char *) pDataStruct->pData, pDataStruct->dataLength, pJsonString, &token); - } - - return ret_val; -} - -bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, - jsonStruct_t *pDataStruct, uint32_t *pDataLength, int32_t *pDataPosition) { - int32_t i, metadataEnd; - uint32_t dataLength; - jsmntok_t dataToken; - - IOT_UNUSED(pJsonHandler); - - for(i = 1; i < tokenCount; ) { - if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), pDataStruct->pKey) == 0) { - dataToken = jsonTokenStruct[i + 1]; - dataLength = (uint32_t) (dataToken.end - dataToken.start); - UpdateValueIfNoObject(pJsonDocument, pDataStruct, dataToken); - *pDataPosition = dataToken.start; - *pDataLength = dataLength; - return true; - } else if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), "metadata") == 0) { - /* Sanity check: must not be at the last key in the json object. */ - if(i >= tokenCount-2) - { - return false; - } - - /* Record where the metadata object ends. */ - metadataEnd = jsonTokenStruct[i+1].end; - - /* Skip past the "metadata" key and jsmn object element. */ - i+= 2; - - /* Skip past every key inside "metadata". Keys inside "metadata" have - * have an end character before the end of the metadata object. - */ - while(jsonTokenStruct[i].end < metadataEnd) - { - i++; - } - } - else - { - /* Only increment the loop counter if the current object doesn't - * match AND isn't "metadata". - */ - i++; - } - } - return false; -} - -bool isReceivedJsonValid(const char *pJsonDocument, size_t jsonSize ) { - int32_t tokenCount; - - jsmn_init(&shadowJsonParser); - - tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, jsonSize, jsonTokenStruct, - sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d\n", tokenCount); - return false; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - return false; - } - - return true; -} - -bool extractClientToken(const char *pJsonDocument, size_t jsonSize, char *pExtractedClientToken, size_t clientTokenSize) { - int32_t tokenCount, i; - size_t length; - jsmntok_t ClientJsonToken; - jsmn_init(&shadowJsonParser); - - tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, jsonSize, jsonTokenStruct, - sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d\n", tokenCount); - return false; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - return false; - } - - for(i = 1; i < tokenCount; i++) { - if(jsoneq(pJsonDocument, &jsonTokenStruct[i], SHADOW_CLIENT_TOKEN_STRING) == 0) { - ClientJsonToken = jsonTokenStruct[i + 1]; - length = (size_t) (ClientJsonToken.end - ClientJsonToken.start); - if (clientTokenSize >= length + 1) - { - strncpy( pExtractedClientToken, pJsonDocument + ClientJsonToken.start, length); - pExtractedClientToken[length] = '\0'; - return true; - }else{ - IOT_WARN( "Token size %zu too small for string %zu \n", clientTokenSize, length); - return false; - } - } - } - - return false; -} - -bool extractVersionNumber(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, uint32_t *pVersionNumber) { - int32_t i; - IoT_Error_t ret_val = SUCCESS; - - IOT_UNUSED(pJsonHandler); - - for(i = 1; i < tokenCount; i++) { - if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), SHADOW_VERSION_STRING) == 0) { - ret_val = parseUnsignedInteger32Value(pVersionNumber, pJsonDocument, &jsonTokenStruct[i + 1]); - if(ret_val == SUCCESS) { - return true; - } - } - } - return false; -} - -#ifdef __cplusplus -} -#endif - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c deleted file mode 100644 index d3a2c7720..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_mqtt_client_subscribe.c - * @brief MQTT client subscribe API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_records.h" - -#include -#include - -#include "timer_interface.h" -#include "aws_iot_json_utils.h" -#include "aws_iot_log.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_config.h" - -typedef struct { - char clientTokenID[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; - char thingName[MAX_SIZE_OF_THING_NAME]; - ShadowActions_t action; - fpActionCallback_t callback; - void *pCallbackContext; - bool isFree; - Timer timer; -} ToBeReceivedAckRecord_t; - -typedef struct { - const char *pKey; - void *pStruct; - jsonStructCallback_t callback; - bool isFree; -} JsonTokenTable_t; - -typedef struct { - char Topic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - uint8_t count; - bool isFree; - bool isSticky; -} SubscriptionRecord_t; - -typedef enum { - SHADOW_ACCEPTED, SHADOW_REJECTED, SHADOW_ACTION -} ShadowAckTopicTypes_t; - -ToBeReceivedAckRecord_t AckWaitList[MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME]; - -AWS_IoT_Client *pMqttClient; - -char myThingName[MAX_SIZE_OF_THING_NAME]; -char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; - -char shadowDeltaTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - -#define MAX_TOPICS_AT_ANY_GIVEN_TIME 2*MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME -SubscriptionRecord_t SubscriptionList[MAX_TOPICS_AT_ANY_GIVEN_TIME]; - -#define SUBSCRIBE_SETTLING_TIME 2 -char shadowRxBuf[SHADOW_MAX_SIZE_OF_RX_BUFFER]; - -static JsonTokenTable_t tokenTable[MAX_JSON_TOKEN_EXPECTED]; -static uint32_t tokenTableIndex = 0; -static bool deltaTopicSubscribedFlag = false; -uint32_t shadowJsonVersionNum = 0; -bool shadowDiscardOldDeltaFlag = true; - -// local helper functions -static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData); - -static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData); - -static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action, - ShadowAckTopicTypes_t ackType); - -static int16_t getNextFreeIndexOfSubscriptionList(void); - -static void unsubscribeFromAcceptedAndRejected(uint8_t index); - -void initDeltaTokens(void) { - uint32_t i; - for(i = 0; i < MAX_JSON_TOKEN_EXPECTED; i++) { - tokenTable[i].isFree = true; - } - tokenTableIndex = 0; - deltaTopicSubscribedFlag = false; -} - -IoT_Error_t registerJsonTokenOnDelta(jsonStruct_t *pStruct) { - - IoT_Error_t rc = SUCCESS; - - if(!deltaTopicSubscribedFlag) { - snprintf(shadowDeltaTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/update/delta", myThingName); - rc = aws_iot_mqtt_subscribe(pMqttClient, shadowDeltaTopic, (uint16_t) strlen(shadowDeltaTopic), QOS0, - shadow_delta_callback, NULL); - deltaTopicSubscribedFlag = true; - } - - if(tokenTableIndex >= MAX_JSON_TOKEN_EXPECTED) { - return FAILURE; - } - - tokenTable[tokenTableIndex].pKey = pStruct->pKey; - tokenTable[tokenTableIndex].callback = pStruct->cb; - tokenTable[tokenTableIndex].pStruct = pStruct; - tokenTable[tokenTableIndex].isFree = false; - tokenTableIndex++; - - return rc; -} - -static int16_t getNextFreeIndexOfSubscriptionList(void) { - uint8_t i; - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(SubscriptionList[i].isFree) { - SubscriptionList[i].isFree = false; - return i; - } - } - return -1; -} - -static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action, - ShadowAckTopicTypes_t ackType) { - - char actionBuf[10]; - char ackTypeBuf[10]; - - if(SHADOW_GET == action) { - strncpy(actionBuf, "get", 10); - } else if(SHADOW_UPDATE == action) { - strncpy(actionBuf, "update", 10); - } else if(SHADOW_DELETE == action) { - strncpy(actionBuf, "delete", 10); - } - - if(SHADOW_ACCEPTED == ackType) { - strncpy(ackTypeBuf, "accepted", 10); - } else if(SHADOW_REJECTED == ackType) { - strncpy(ackTypeBuf, "rejected", 10); - } - - if(SHADOW_ACTION == ackType) { - snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s", pThingName, actionBuf); - } else { - snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s/%s", pThingName, actionBuf, - ackTypeBuf); - } -} - -static bool isValidShadowVersionUpdate(const char *pTopicName) { - if(strstr(pTopicName, myThingName) != NULL && - ((strstr(pTopicName, "get/accepted") != NULL) || - (strstr(pTopicName, "delta") != NULL))) { - return true; - } - return false; -} - -static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - int32_t tokenCount; - uint8_t i; - void *pJsonHandler = NULL; - char temporaryClientToken[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(params->payloadLen >= SHADOW_MAX_SIZE_OF_RX_BUFFER) { - IOT_WARN("Payload larger than RX Buffer"); - return; - } - - memcpy(shadowRxBuf, params->payload, params->payloadLen); - shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string - - if(!isJsonValidAndParse(shadowRxBuf, SHADOW_MAX_SIZE_OF_RX_BUFFER, pJsonHandler, &tokenCount)) { - IOT_WARN("Received JSON is not valid"); - return; - } - - if(isValidShadowVersionUpdate(topicName)) { - uint32_t tempVersionNumber = 0; - if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { - if(tempVersionNumber > shadowJsonVersionNum) { - shadowJsonVersionNum = tempVersionNumber; - } - } - } - - if(extractClientToken(shadowRxBuf, SHADOW_MAX_SIZE_OF_RX_BUFFER, temporaryClientToken, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE)) { - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - if(!AckWaitList[i].isFree) { - if(strcmp(AckWaitList[i].clientTokenID, temporaryClientToken) == 0) { - Shadow_Ack_Status_t status = SHADOW_ACK_REJECTED; - if(strstr(topicName, "accepted") != NULL) { - status = SHADOW_ACK_ACCEPTED; - } else if(strstr(topicName, "rejected") != NULL) { - status = SHADOW_ACK_REJECTED; - } - if(status == SHADOW_ACK_ACCEPTED || status == SHADOW_ACK_REJECTED) { - if(AckWaitList[i].callback != NULL) { - AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, status, - shadowRxBuf, AckWaitList[i].pCallbackContext); - } - unsubscribeFromAcceptedAndRejected(i); - AckWaitList[i].isFree = true; - return; - } - } - } - } - } -} - -static int16_t findIndexOfSubscriptionList(const char *pTopic) { - uint8_t i; - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(!SubscriptionList[i].isFree) { - if((strcmp(pTopic, SubscriptionList[i].Topic) == 0)) { - return i; - } - } - } - return -1; -} - -static void unsubscribeFromAcceptedAndRejected(uint8_t index) { - - char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - IoT_Error_t ret_val = SUCCESS; - - int16_t indexSubList; - - topicNameFromThingAndAction(TemporaryTopicNameAccepted, AckWaitList[index].thingName, AckWaitList[index].action, - SHADOW_ACCEPTED); - topicNameFromThingAndAction(TemporaryTopicNameRejected, AckWaitList[index].thingName, AckWaitList[index].action, - SHADOW_REJECTED); - - indexSubList = findIndexOfSubscriptionList(TemporaryTopicNameAccepted); - if((indexSubList >= 0)) { - if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) { - ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameAccepted, - (uint16_t) strlen(TemporaryTopicNameAccepted)); - if(ret_val == SUCCESS) { - SubscriptionList[indexSubList].isFree = true; - } - } else if(SubscriptionList[indexSubList].count > 1) { - SubscriptionList[indexSubList].count--; - } - } - - indexSubList = findIndexOfSubscriptionList(TemporaryTopicNameRejected); - if((indexSubList >= 0)) { - if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) { - ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameRejected, - (uint16_t) strlen(TemporaryTopicNameRejected)); - if(ret_val == SUCCESS) { - SubscriptionList[indexSubList].isFree = true; - } - } else if(SubscriptionList[indexSubList].count > 1) { - SubscriptionList[indexSubList].count--; - } - } -} - -void initializeRecords(AWS_IoT_Client *pClient) { - uint8_t i; - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - AckWaitList[i].isFree = true; - } - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - SubscriptionList[i].isFree = true; - SubscriptionList[i].count = 0; - SubscriptionList[i].isSticky = false; - } - - pMqttClient = pClient; -} - -bool isSubscriptionPresent(const char *pThingName, ShadowActions_t action) { - - uint8_t i = 0; - bool isAcceptedPresent = false; - bool isRejectedPresent = false; - char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - - topicNameFromThingAndAction(TemporaryTopicNameAccepted, pThingName, action, SHADOW_ACCEPTED); - topicNameFromThingAndAction(TemporaryTopicNameRejected, pThingName, action, SHADOW_REJECTED); - - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(!SubscriptionList[i].isFree) { - if((strcmp(TemporaryTopicNameAccepted, SubscriptionList[i].Topic) == 0)) { - isAcceptedPresent = true; - } else if((strcmp(TemporaryTopicNameRejected, SubscriptionList[i].Topic) == 0)) { - isRejectedPresent = true; - } - } - } - - if(isRejectedPresent && isAcceptedPresent) { - return true; - } - - return false; -} - -IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t action, bool isSticky) { - IoT_Error_t ret_val = SUCCESS; - - bool clearBothEntriesFromList = true; - int16_t indexAcceptedSubList = 0; - int16_t indexRejectedSubList = 0; - Timer subSettlingtimer; - indexAcceptedSubList = getNextFreeIndexOfSubscriptionList(); - indexRejectedSubList = getNextFreeIndexOfSubscriptionList(); - - if(indexAcceptedSubList >= 0 && indexRejectedSubList >= 0) { - topicNameFromThingAndAction(SubscriptionList[indexAcceptedSubList].Topic, pThingName, action, SHADOW_ACCEPTED); - ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic, - (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic), QOS0, - AckStatusCallback, NULL); - if(ret_val == SUCCESS) { - SubscriptionList[indexAcceptedSubList].count = 1; - SubscriptionList[indexAcceptedSubList].isSticky = isSticky; - topicNameFromThingAndAction(SubscriptionList[indexRejectedSubList].Topic, pThingName, action, - SHADOW_REJECTED); - ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexRejectedSubList].Topic, - (uint16_t) strlen(SubscriptionList[indexRejectedSubList].Topic), QOS0, - AckStatusCallback, NULL); - if(ret_val == SUCCESS) { - SubscriptionList[indexRejectedSubList].count = 1; - SubscriptionList[indexRejectedSubList].isSticky = isSticky; - clearBothEntriesFromList = false; - - // wait for SUBSCRIBE_SETTLING_TIME seconds to let the subscription take effect - init_timer(&subSettlingtimer); - countdown_sec(&subSettlingtimer, SUBSCRIBE_SETTLING_TIME); - while(!has_timer_expired(&subSettlingtimer)); - - } - } - } - - if(clearBothEntriesFromList) { - if(indexAcceptedSubList >= 0) { - SubscriptionList[indexAcceptedSubList].isFree = true; - - if(SubscriptionList[indexAcceptedSubList].count == 1) { - aws_iot_mqtt_unsubscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic, - (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic)); - } - } - if(indexRejectedSubList >= 0) { - SubscriptionList[indexRejectedSubList].isFree = true; - } - - } - - return ret_val; -} - -void incrementSubscriptionCnt(const char *pThingName, ShadowActions_t action, bool isSticky) { - char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - uint8_t i; - topicNameFromThingAndAction(TemporaryTopicNameAccepted, pThingName, action, SHADOW_ACCEPTED); - topicNameFromThingAndAction(TemporaryTopicNameRejected, pThingName, action, SHADOW_REJECTED); - - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(!SubscriptionList[i].isFree) { - if((strcmp(TemporaryTopicNameAccepted, SubscriptionList[i].Topic) == 0) - || (strcmp(TemporaryTopicNameRejected, SubscriptionList[i].Topic) == 0)) { - SubscriptionList[i].count++; - SubscriptionList[i].isSticky = isSticky; - } - } - } -} - -IoT_Error_t publishToShadowAction(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent) { - IoT_Error_t ret_val = SUCCESS; - char TemporaryTopicName[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - IoT_Publish_Message_Params msgParams; - - if(NULL == pThingName || NULL == pJsonDocumentToBeSent) { - return NULL_VALUE_ERROR; - } - - topicNameFromThingAndAction(TemporaryTopicName, pThingName, action, SHADOW_ACTION); - - msgParams.qos = QOS0; - msgParams.isRetained = 0; - msgParams.payloadLen = strlen(pJsonDocumentToBeSent); - msgParams.payload = (char *) pJsonDocumentToBeSent; - ret_val = aws_iot_mqtt_publish(pMqttClient, TemporaryTopicName, (uint16_t) strlen(TemporaryTopicName), &msgParams); - - return ret_val; -} - -bool getNextFreeIndexOfAckWaitList(uint8_t *pIndex) { - uint8_t i; - bool rc = false; - - if(NULL == pIndex) { - return false; - } - - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - if(AckWaitList[i].isFree) { - *pIndex = i; - rc = true; - break; - } - } - - return rc; -} - -void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action, - const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext, - uint32_t timeout_seconds) { - AckWaitList[indexAckWaitList].callback = callback; - memcpy(AckWaitList[indexAckWaitList].clientTokenID, pExtractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE); - memcpy(AckWaitList[indexAckWaitList].thingName, pThingName, MAX_SIZE_OF_THING_NAME); - AckWaitList[indexAckWaitList].pCallbackContext = pCallbackContext; - AckWaitList[indexAckWaitList].action = action; - init_timer(&(AckWaitList[indexAckWaitList].timer)); - countdown_sec(&(AckWaitList[indexAckWaitList].timer), timeout_seconds); - AckWaitList[indexAckWaitList].isFree = false; -} - -void HandleExpiredResponseCallbacks(void) { - uint8_t i; - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - if(!AckWaitList[i].isFree) { - if(has_timer_expired(&(AckWaitList[i].timer))) { - if(AckWaitList[i].callback != NULL) { - AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, SHADOW_ACK_TIMEOUT, - shadowRxBuf, AckWaitList[i].pCallbackContext); - } - AckWaitList[i].isFree = true; - unsubscribeFromAcceptedAndRejected(i); - } - } - } -} - -static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - int32_t tokenCount; - uint32_t i = 0; - void *pJsonHandler = NULL; - int32_t DataPosition; - uint32_t dataLength; - uint32_t tempVersionNumber = 0; - - FUNC_ENTRY; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(params->payloadLen >= SHADOW_MAX_SIZE_OF_RX_BUFFER) { - IOT_WARN("Payload larger than RX Buffer"); - return; - } - - memcpy(shadowRxBuf, params->payload, params->payloadLen); - shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string - - if(!isJsonValidAndParse(shadowRxBuf, SHADOW_MAX_SIZE_OF_RX_BUFFER, pJsonHandler, &tokenCount)) { - IOT_WARN("Received JSON is not valid"); - return; - } - - if(shadowDiscardOldDeltaFlag) { - if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { - if(tempVersionNumber > shadowJsonVersionNum) { - shadowJsonVersionNum = tempVersionNumber; - } else { - IOT_WARN("Old Delta Message received - Ignoring rx: %d local: %d", tempVersionNumber, - shadowJsonVersionNum); - return; - } - } - } - - for(i = 0; i < tokenTableIndex; i++) { - if(!tokenTable[i].isFree) { - if(isJsonKeyMatchingAndUpdateValue(shadowRxBuf, pJsonHandler, tokenCount, - (jsonStruct_t *) tokenTable[i].pStruct, &dataLength, &DataPosition)) { - if(tokenTable[i].callback != NULL) { - tokenTable[i].callback(shadowRxBuf + DataPosition, dataLength, - (jsonStruct_t *) tokenTable[i].pStruct); - } - } - } - } -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/README.md deleted file mode 100644 index 3625bae68..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Tests -This folder contains tests to verify SDK functionality. These have been tested to work with Linux but haven't been ported to any specific platform. For additional information about porting the Device SDK for embedded C onto additional platforms please refer to the [PortingGuide](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/PortingGuide.md/). -A description for each folder is given below - -## integration -This folder contains integration tests that run directly against the server. For further information on how to run these tests check out the [Integration Test README](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/integration/README.md/). - -## unit -This folder contains unit tests that test SDK functionality against a Mock TLS layer. They are built using the CppUTest testing framework. For further information on how to run these tests check out the [Unit Test README](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/unit/README.md/). \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile deleted file mode 100644 index e18648941..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile +++ /dev/null @@ -1,108 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc -RM = rm - -DEBUG = - -#IoT client directory -IOT_CLIENT_DIR = ../.. - -APP_DIR = $(IOT_CLIENT_DIR)/tests/integration -APP_NAME = integration_tests_mbedtls -MT_APP_NAME = integration_tests_mbedtls_mt -APP_SRC_FILES = $(shell find $(APP_DIR)/src/ -name '*.c') -MT_APP_SRC_FILES = $(shell find $(APP_DIR)/multithreadingTest/ -name '*.c') -APP_INCLUDE_DIRS = -I $(APP_DIR)/include - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux - -#MbedTLS directory -TEMP_MBEDTLS_SRC_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(TEMP_MBEDTLS_SRC_DIR)/library -CRYPTO_LIB_DIR = $(TEMP_MBEDTLS_SRC_DIR)/library -TLS_INCLUDE_DIR = -I $(TEMP_MBEDTLS_SRC_DIR)/include - -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -# Logging level control -#LOG_FLAGS += -DENABLE_IOT_DEBUG -#LOG_FLAGS += -DENABLE_IOT_TRACE -#LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR -COMPILER_FLAGS += $(LOG_FLAGS) - -#IoT client directory -PLATFORM_COMMON_DIR = $(PLATFORM_DIR)/common -PLATFORM_THREAD_DIR = $(PLATFORM_DIR)/pthread -PLATFORM_NETWORK_DIR = $(PLATFORM_DIR)/mbedtls - -IOT_INCLUDE_DIRS = -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_THREAD_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_NETWORK_DIR) -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_NETWORK_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_THREAD_DIR)/ -name '*.c') - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -MT_SRC_FILES += $(MT_APP_SRC_FILES) -MT_SRC_FILES += $(IOT_SRC_FILES) - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) -PRE_MAKE_CMDS += cd $(TEMP_MBEDTLS_SRC_DIR) && make - -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -g3 -D_ENABLE_THREAD_SUPPORT_ -o $(APP_DIR)/$(APP_NAME) $(EXTERNAL_LIBS) $(LD_FLAG) $(INCLUDE_ALL_DIRS); -MAKE_MT_CMD = $(CC) $(MT_SRC_FILES) $(COMPILER_FLAGS) -g3 -D_ENABLE_THREAD_SUPPORT_ -o $(APP_DIR)/$(MT_APP_NAME) $(EXTERNAL_LIBS) $(LD_FLAG) $(INCLUDE_ALL_DIRS); - -ifeq ($(CODE_SIZE_ENABLE),Y) -POST_MAKE_CMDS += $(CC) -c $(SRC_FILES) $(INCLUDE_ALL_DIRS) -fstack-usage; -POST_MAKE_CMDS += (size --format=Berkeley *.o > $(APP_NAME)_size_info.txt); -POST_MAKE_CMDS += (cat *.su >> $(APP_NAME)_stack_usage.txt); -POST_MAKE_CMDS += ($(RM) *.o); -POST_MAKE_CMDS += ($(RM) *.su); -CLEAN_CMD += ($(RM) -f $(APP_NAME)_size_info.txt); -CLEAN_CMD += ($(RM) -f $(APP_NAME)_stack_usage.txt); -endif - -all: - $(PRE_MAKE_CMDS) - $(DEBUG)$(MAKE_CMD) - $(DEBUG)$(MAKE_MT_CMD) - ./$(APP_NAME) - ./$(MT_APP_NAME) - $(POST_MAKE_CMDS) - -app: - $(PRE_MAKE_CMDS) - $(DEBUG)$(MAKE_CMD) - $(DEBUG)$(MAKE_MT_CMD) - -tests: - ./$(APP_NAME) - ./$(MT_APP_NAME) - $(POST_MAKE_CMDS) - -clean: - $(RM) -f $(APP_DIR)/$(APP_NAME) - $(RM) -f $(APP_DIR)/$(MT_APP_NAME) - $(CLEAN_CMD) - -ALL_TARGETS_CLEAN += test-integration-assert-clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md deleted file mode 100644 index b3ea04b25..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md +++ /dev/null @@ -1,44 +0,0 @@ -## Integration Tests -This folder contains integration tests to verify Embedded C SDK functionality. These have been tested to work with Linux but haven't been ported to any specific platform. For additional information about porting the Device SDK for embedded C onto additional platforms please refer to the [PortingGuide](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/PortingGuide.md/). -To run these tests, follow the below steps: - - * Place device identity cert and private key in locations referenced in the `certs` folder - * Download certificate authority CA file from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem) and place in `certs` folder - * Ensure the names of the cert files are the same as in the `aws_iot_config.h` file - * Ensure the certificate has an attached policy which allows the proper permissions for AWS IoT - * Update the Host endpoint in the `aws_iot_config.h` file - * Build the example using make. (''make''). The tests will run automatically as a part of the build process - * For more detailed Debug output, enable the IOT_DEBUG flag in `Logging level control` section of the Makefile. IOT_TRACE can be enabled as well for very detailed information on what functions are being executed - * More information on the each test is below - -### Integration test configuration -For all the tests below, there is additional configuration in the `integ_tests_config.h`. The configuration options are explained below: - - * PUBLISH_COUNT - Number of messages to publish in each publish thread - * MAX_PUB_THREAD_COUNT - Maximum number of threads to create for the multi-threading test - * RX_RECEIVE_PERCENTAGE - Minimum percentage of messages that must be received back by the yield thread. This is here ONLY because sometimes the yield thread doesn't get scheduled before the publish thread when it is created. In every other case, 100% messages should be received - * CONNECT_MAX_ATTEMPT_COUNT - Max number of initial connect retries - * THREAD_SLEEP_INTERVAL_USEC - Interval that each thread sleeps for - * INTEGRATION_TEST_TOPIC - Test topic to publish on - * INTEGRATION_TEST_CLIENT_ID - Client ID to be used for single client tests - * INTEGRATION_TEST_CLIENT_ID_PUB, INTEGRATION_TEST_CLIENT_ID_SUB - Client IDs to be used for multiple client tests - -### Test 1 - Basic Connectivity Test -This test verifies basic connectivity with the server. It creates one client instance and connects to the server. It subscribes to the Integration Test topic. Then it creates two threads, one publish thread and one yield thread. The publish thread publishes `PUBLISH_COUNT` messages on the test topic and the yield thread receives them. Once all the messages are published, the program waits for 1 sec to ensure all the messages have sufficient time to be received. -The test ends with the program verifying that all the messages were received and no other errors occurred. - -### Test 2 - Multiple Client Connectivity Test -This test verifies usage of multiple clients in the same application. It creates two client instances and both connect to the server. One client instance subscribes to the Integration Test topic. The other client instance publishes `PUBLISH_COUNT` messages on the test topic and the yield instance receives them. Once all the messages are published, the program waits for 1 sec to ensure all the messages have sufficient time to be received. -The test ends with the program verifying that all the messages were received and no other errors occurred. - -### Test 3 - Auto Reconnect Test -This test verifies Auto-reconnect functionality. It creates one client instance. Then it performs 3 separate tests - - * Tests the disconnect handler by causing a TLS layer disconnect. - * Tests manual reconnect API by causing a TLS layer disconnect with auto-reconnect disabled - * Lastly, it tests the Auto-reconnect API by enabling auto-reconnect. It renames the rootCA file to a different name to prevent immediate reconnect, verifies the error codes are returned properly and that the reconnect algorithm is running. Once that check is satisfied, it renames the rootCA file back to the original names and verifies the client was able to reconnect. - -### Test 4 - Multi-threading Validation Test -This test is used to validate thread-safe operations. This creates on client instance, one yield thread, one thread to test subscribe/unsubscribe behavior and MAX_PUB_THREAD_COUNT number of publish threads. Then it proceeds to publish PUBLISH_COUNT messages on the test topic from each publish thread. The subscribe/unsubscribe thread runs in the background constantly subscribing and unsubscribing to a second test topic. The yield threads records which messages were received. - -The test verifies whether all the messages that were published were received or not. It also checks for errors that could occur in multi-threaded scenarios. The test has been run with 10 threads sending 500 messages each and verified to be working fine. It can be used as a reference testing application to validate whether your use case will work with multi-threading enabled. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h deleted file mode 100644 index 5d249bfef..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename - -// MQTT PubSub -#ifndef DISABLE_IOT_JOBS -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#else -#define AWS_IOT_MQTT_RX_BUF_LEN 2048 -#endif -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Shadow and Job common configs -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_SIZE_OF_THING_NAME 30 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER 512 ///< Maximum size of the SHADOW buffer to store the received Shadow message -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Job specific configs -#ifndef DISABLE_IOT_JOBS -#define MAX_SIZE_OF_JOB_ID 64 -#define MAX_JOB_JSON_TOKEN_EXPECTED 120 -#define MAX_SIZE_OF_JOB_REQUEST AWS_IOT_MQTT_TX_BUF_LEN - -#define MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME 40 -#define MAX_JOB_TOPIC_LENGTH_BYTES MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME + MAX_SIZE_OF_THING_NAME + MAX_SIZE_OF_JOB_ID + 2 -#endif - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h deleted file mode 100644 index a10933806..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef TESTS_INTEGRATION_INTEG_TESTS_CONFIG_H_ -#define TESTS_INTEGRATION_INTEG_TESTS_CONFIG_H_ - -/* Number of messages to publish in each publish thread */ -#define PUBLISH_COUNT 100 - -/* Maximum number of threads to create for the multi-threading test */ -#define MAX_PUB_THREAD_COUNT 3 - -/* Minimum percentage of messages that must be received back by the yield thread. - * This is here ONLY because sometimes the yield thread doesn't get scheduled before the publish - * thread when it is created. In every other case, 100% messages should be received. */ -#define RX_RECEIVE_PERCENTAGE 99.0f - -/* Max number of initial connect retries */ -#define CONNECT_MAX_ATTEMPT_COUNT 3 - -/* Interval that each thread sleeps for */ -#define THREAD_SLEEP_INTERVAL_USEC 500000 - -/* Test topic to publish on */ -#define INTEGRATION_TEST_TOPIC "Tests/Integration/EmbeddedC" - -/* Client ID to be used for single client tests */ -#define INTEGRATION_TEST_CLIENT_ID "EMB_C_SDK_INTEG_TESTER" - -/* Client IDs to be used for multiple client tests */ -#define INTEGRATION_TEST_CLIENT_ID_PUB "EMB_C_SDK_INTEG_TESTER_PUB" -#define INTEGRATION_TEST_CLIENT_ID_SUB "EMB_C_SDK_INTEG_TESTER_SUB" - -#endif /* TESTS_INTEGRATION_INTEG_TESTS_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h deleted file mode 100644 index 39da671ce..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h +++ /dev/null @@ -1,43 +0,0 @@ - -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_integration_common.h - * @brief Integration Test common header - */ - -#ifndef TESTS_INTEGRATION_H_ -#define TESTS_INTEGRATION_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_log.h" -#include "aws_iot_integ_tests_config.h" -#include "aws_iot_config.h" - -int aws_iot_mqtt_tests_basic_connectivity(); -int aws_iot_mqtt_tests_multiple_clients(); -int aws_iot_mqtt_tests_auto_reconnect(); - -#endif /* TESTS_INTEGRATION_COMMON_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c deleted file mode 100644 index 032661d4f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * multithreadedTest.c - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_log.h" - -#include "aws_iot_integ_tests_config.h" -#include "aws_iot_config.h" - -#define BUFFER_SIZE 100 - -static bool terminate_yield_thread; -static bool terminate_subUnsub_thread; - -static unsigned int countArray[MAX_PUB_THREAD_COUNT][PUBLISH_COUNT]; -static unsigned int rxMsgBufferTooBigCounter; -static unsigned int rxUnexpectedNumberCounter; -static unsigned int rePublishCount; -static unsigned int wrongYieldCount; -static unsigned int threadStatus[MAX_PUB_THREAD_COUNT]; - -typedef struct ThreadData { - int threadId; - AWS_IoT_Client *client; -} ThreadData; - -static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - char tempBuf[BUFFER_SIZE]; - char *temp = NULL; - char *next_token; - unsigned int tempRow = 0, tempCol = 0; - - IoT_Error_t rc; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(BUFFER_SIZE >= params->payloadLen) { - snprintf(tempBuf, params->payloadLen, params->payload); - printf("\n Message received : %s", tempBuf); - temp = strtok_r(tempBuf, " ,:", &next_token); - temp = strtok_r(NULL, " ,:", &next_token); - if(NULL == temp) { - return; - } - tempRow = atoi(temp); - temp = strtok_r(NULL, " ,:", &next_token); - temp = strtok_r(NULL, " ,:", &next_token); - - if(NULL == temp) { - return; - } - - tempCol = atoi(temp); - - if(((tempRow - 1) < MAX_PUB_THREAD_COUNT) && (tempCol < PUBLISH_COUNT)) { - countArray[tempRow - 1][tempCol]++; - } else { - IOT_ERROR(" \nUnexpected Thread : %d, Message : %d ", tempRow, tempCol); - rxUnexpectedNumberCounter++; - } - rc = aws_iot_mqtt_yield(pClient, 10); - if(MQTT_CLIENT_NOT_IDLE_ERROR != rc) { - IOT_ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n", - aws_iot_mqtt_get_client_state(pClient), rc); - wrongYieldCount++; - } - } else { - rxMsgBufferTooBigCounter++; - } -} - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { - IOT_UNUSED(pClient); - IOT_UNUSED(param); -} - -static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pClient, QoS qos, struct timeval *pSubscribeTime) { - IoT_Error_t rc = SUCCESS; - struct timeval start, end; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos, - aws_iot_mqtt_tests_message_aggregator, NULL); - IOT_DEBUG(" Sub response : %d\n", rc); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - while(SUCCESS == rc && false == terminate_yield_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - //DEBUG("\n Yielding \n"); - rc = aws_iot_mqtt_yield(pClient, 100); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("\nYield Returned : %d ", rc); - } - } - - return NULL; -} - -static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int itr = 0; - char cPayload[100]; - IoT_Publish_Message_Params params; - IoT_Error_t rc = SUCCESS; - ThreadData *threadData = (ThreadData *) ptr; - AWS_IoT_Client *pClient = threadData->client; - int threadId = threadData->threadId; - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - snprintf(cPayload, 100, "%s_Thread : %d, Msg : %d", AWS_IOT_MY_THING_NAME, threadId, itr); - printf("\nMsg being published: %s \n", cPayload); - params.payload = (void *) cPayload; - params.payloadLen = strlen(cPayload) + 1; - params.qos = QOS1; - params.isRetained = 0; - - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - if(SUCCESS != rc) { - IOT_WARN("\nFailed attempt 1 Publishing Thread : %d, Msg : %d, cs : %d --> %d\n ", threadId, itr, rc, - aws_iot_mqtt_get_client_state(pClient)); - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - rePublishCount++; - if(SUCCESS != rc) { - IOT_ERROR("\nFailed attempt 2 Publishing Thread : %d, Msg : %d, cs : %d --> %d Second Attempt \n", threadId, - itr, rc, aws_iot_mqtt_get_client_state(pClient)); - } - } - } - threadStatus[threadId - 1] = 1; - return 0; - -} - -static void *aws_iot_mqtt_tests_sub_unsub_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - char testTopic[50]; - snprintf(testTopic, 50, "%s_temp", INTEGRATION_TEST_TOPIC); - while(SUCCESS == rc && false == terminate_subUnsub_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_subscribe(pClient, testTopic, strlen(testTopic), QOS1, - aws_iot_mqtt_tests_message_aggregator, NULL); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("Subscribe Returned : %d ", rc); - } - - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_unsubscribe(pClient, testTopic, strlen(testTopic)); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("Unsubscribe Returned : %d ", rc); - } - } - - return NULL; -} - -int aws_iot_mqtt_tests_multi_threading_validation() { - pthread_t publish_thread[MAX_PUB_THREAD_COUNT], yield_thread, sub_unsub_thread; - char certDirectory[15] = "../../certs"; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char root_CA[PATH_MAX + 1]; - - char clientId[50]; - IoT_Client_Init_Params initParams = IoT_Client_Init_Params_initializer; - IoT_Client_Connect_Params connectParams; - int threadId[MAX_PUB_THREAD_COUNT]; - int pubThreadReturn[MAX_PUB_THREAD_COUNT]; - int yieldThreadReturn = 0, subUnsubThreadReturn = 0; - float percentOfRxMsg = 0.0; - int finishedThreadCount = 0; - IoT_Error_t rc = SUCCESS; - int i, rxMsgCount = 0, j = 0; - struct timeval subscribeTopic; - unsigned int connectCounter = 0; - int test_result = 0; - ThreadData threadData[MAX_PUB_THREAD_COUNT]; - AWS_IoT_Client client; - terminate_yield_thread = false; - rxMsgBufferTooBigCounter = 0; - rxUnexpectedNumberCounter = 0; - rePublishCount = 0; - wrongYieldCount = 0; - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - threadId[j] = j + 1; - threadStatus[j] = 0; - for(i = 0; i < PUBLISH_COUNT; i++) { - countArray[j][i] = 0; - } - } - - printf("\nConnecting Client "); - do { - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int)time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - IOT_DEBUG(" Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 10000; - initParams.tlsHandshakeTimeout_ms = 10000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - initParams.isBlockOnThreadLockEnabled = true; - aws_iot_mqtt_init(&client, &initParams); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *)&clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = false; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("ERROR Connecting %d\n", rc); - return -1; - } - - connectCounter++; - } while(SUCCESS != rc && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - printf("\n## Connect Success.\n"); - } else { - IOT_ERROR("## Connect Failed. error code %d\n", rc); - return -1; - } - - aws_iot_mqtt_tests_subscribe_to_test_topic(&client, QOS1, &subscribeTopic); - - printf("\nRunning Test! "); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_thread_runner, &client); - subUnsubThreadReturn = pthread_create(&sub_unsub_thread, NULL, aws_iot_mqtt_tests_sub_unsub_thread_runner, &client); - - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { - threadData[i].client = &client; - threadData[i].threadId = threadId[i]; - pubThreadReturn[i] = pthread_create(&publish_thread[i], NULL, aws_iot_mqtt_tests_publish_thread_runner, - &threadData[i]); - } - - /* Wait until all publish threads have finished */ - do { - finishedThreadCount = 0; - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { finishedThreadCount += threadStatus[i]; } - printf("\nFinished thread count : %d \n", finishedThreadCount); - sleep(1); - } while(finishedThreadCount < MAX_PUB_THREAD_COUNT); - - printf("\nFinished publishing!!"); - - terminate_yield_thread = true; - terminate_subUnsub_thread = true; - pthread_join(yield_thread, NULL); - pthread_join(sub_unsub_thread, NULL); - - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { - pthread_join(publish_thread[i], NULL); - } - - /* Not using pthread_join because all threads should have terminated gracefully at this point. If they haven't, - * which should not be possible, something below will fail. */ - - printf("\n\nCalculating Results!! \n\n"); - for(i = 0; i < PUBLISH_COUNT; i++) { - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - if(countArray[j][i] > 0) { - rxMsgCount++; - } - } - } - - printf("\n\nResult : \n"); - percentOfRxMsg = (float) rxMsgCount * 100 / (PUBLISH_COUNT * MAX_PUB_THREAD_COUNT); - if(RX_RECEIVE_PERCENTAGE <= percentOfRxMsg && 0 == rxMsgBufferTooBigCounter && 0 == rxUnexpectedNumberCounter && - 0 == wrongYieldCount) { - printf("\nSuccess: %f \%\n", percentOfRxMsg); - printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT * MAX_PUB_THREAD_COUNT, rxMsgCount); - printf("QoS 1 re publish count %d\n", rePublishCount); - printf("Connection Attempts %d\n", connectCounter); - printf("Yield count without error during callback %d\n", wrongYieldCount); - test_result = 0; - } else { - printf("\nFailure: %f\n", percentOfRxMsg); - printf("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter); - printf("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter); - printf("Yield count without error during callback %d\n", wrongYieldCount); - test_result = -2; - } - aws_iot_mqtt_disconnect(&client); - return test_result; -} - -int main() { - printf("\n\n"); - printf("******************************************************************\n"); - printf("* Starting MQTT Version 3.1.1 Multithreading Validation Test *\n"); - printf("******************************************************************\n"); - int rc = aws_iot_mqtt_tests_multi_threading_validation(); - if(0 != rc) { - printf("\n*******************************************************************\n"); - printf("*MQTT Version 3.1.1 Multithreading Validation Test FAILED! RC : %d \n", rc); - printf("*******************************************************************\n"); - return 1; - } - - printf("******************************************************************\n"); - printf("* MQTT Version 3.1.1 Multithreading Validation Test SUCCESS!! *\n"); - printf("******************************************************************\n"); - - return 0; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c deleted file mode 100644 index 267d9dc05..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c +++ /dev/null @@ -1,236 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_auto_reconnect.c - * @brief Integration Test for automatic reconnect - */ - -#include "aws_iot_test_integration_common.h" - -static char ModifiedPathBuffer[PATH_MAX + 1]; -char root_CA[PATH_MAX + 1]; - -bool terminate_yield_with_rc_thread = false; -IoT_Error_t yieldRC; -bool captureYieldReturnCode = false; -char * dummyLocation = "dummyLocation"; -char * savedLocation; -/** - * This function renames the rootCA.crt file to a temporary name to cause connect failure - */ -void aws_iot_mqtt_tests_block_tls_connect(AWS_IoT_Client *pClient) { - savedLocation = pClient->networkStack.tlsConnectParams.pRootCALocation; - pClient->networkStack.tlsConnectParams.pRootCALocation = dummyLocation; -} - -/** - * Always ensure this function is called after block_tls_connect - */ -void aws_iot_mqtt_tests_unblock_tls_connect(AWS_IoT_Client *pClient) { - pClient->networkStack.tlsConnectParams.pRootCALocation = savedLocation; -} - -void *aws_iot_mqtt_tests_yield_with_rc(void *ptr) { - IoT_Error_t rc = SUCCESS; - - struct timeval start, end, result; - static int cntr = 0; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - - while(terminate_yield_with_rc_thread == false - && (NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)) { - usleep(500000); - printf(" Client state : %d ", aws_iot_mqtt_get_client_state(pClient)); - rc = aws_iot_mqtt_yield(pClient, 100); - printf("yield rc %d\n", rc); - if(captureYieldReturnCode && SUCCESS != rc) { - printf("yield rc capture %d\n", rc); - captureYieldReturnCode = false; - yieldRC = rc; - } - } - - return NULL; -} - -unsigned int disconnectedCounter = 0; - -void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { - disconnectedCounter++; -} - -int aws_iot_mqtt_tests_auto_reconnect() { - pthread_t reconnectTester_thread, yield_thread; - int yieldThreadReturn = 0; - int test_result = 0; - - char certDirectory[15] = "../../certs"; - char CurrentWD[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char clientId[50]; - AWS_IoT_Client client; - - IoT_Error_t rc = SUCCESS; - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int) time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - printf(" Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - IoT_Client_Init_Params initParams = IoT_Client_Init_Params_initializer; - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 20000; - initParams.tlsHandshakeTimeout_ms = 5000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - aws_iot_mqtt_init(&client, &initParams); - - IoT_Client_Connect_Params connectParams; - connectParams.keepAliveIntervalInSec = 5; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *) &clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = 0; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(rc != SUCCESS) { - printf("ERROR Connecting %d\n", rc); - return -1; - } - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client); - - /* - * Test disconnect handler - */ - printf("1. Test Disconnect Handler\n"); - aws_iot_mqtt_tests_block_tls_connect(&client); - iot_tls_disconnect(&(client.networkStack)); - sleep(connectParams.keepAliveIntervalInSec + 1); - if(disconnectedCounter == 1) { - printf("Success invoking Disconnect Handler\n"); - } else { - aws_iot_mqtt_tests_unblock_tls_connect(&client); - printf("Failure to invoke Disconnect Handler\n"); - return -1; - } - - terminate_yield_with_rc_thread = true; - pthread_join(yield_thread, NULL); - aws_iot_mqtt_tests_unblock_tls_connect(&client); - - /* - * Manual Reconnect Test - */ - printf("2. Test Manual Reconnect, Current Client state : %d \n", aws_iot_mqtt_get_client_state(&client)); - rc = aws_iot_mqtt_attempt_reconnect(&client); - if(rc != NETWORK_RECONNECTED) { - printf("ERROR reconnecting manually %d\n", rc); - return -4; - } - terminate_yield_with_rc_thread = false; - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client); - - yieldRC = FAILURE; - captureYieldReturnCode = true; - - // ensure atleast 1 cycle of yield is executed to get the yield status to SUCCESS - sleep(1); - if(!captureYieldReturnCode) { - if(yieldRC == NETWORK_ATTEMPTING_RECONNECT) { - printf("Success reconnecting manually\n"); - } else { - printf("Failure to reconnect manually\n"); - return -3; - } - } - terminate_yield_with_rc_thread = true; - pthread_join(yield_thread, NULL); - - /* - * Auto Reconnect Test - */ - - printf("3. Test Auto_reconnect \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(rc != SUCCESS) { - printf("Error: Failed to enable auto-reconnect %d \n", rc); - } - - yieldRC = FAILURE; - captureYieldReturnCode = true; - - // Disconnect - aws_iot_mqtt_tests_block_tls_connect(&client); - iot_tls_disconnect(&(client.networkStack)); - - terminate_yield_with_rc_thread = false; - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client); - - sleep(connectParams.keepAliveIntervalInSec + 1); - if(!captureYieldReturnCode) { - if(yieldRC == NETWORK_ATTEMPTING_RECONNECT) { - printf("Success attempting reconnect\n"); - } else { - printf("Failure to attempt to reconnect\n"); - return -6; - } - } - if(disconnectedCounter == 2) { - printf("Success: disconnect handler invoked on enabling auto-reconnect\n"); - } else { - printf("Failure: disconnect handler not invoked on enabling auto-reconnect : %d\n", disconnectedCounter); - return -7; - } - aws_iot_mqtt_tests_unblock_tls_connect(&client); - sleep(connectParams.keepAliveIntervalInSec + 1); - captureYieldReturnCode = true; - sleep(connectParams.keepAliveIntervalInSec + 1); - if(!captureYieldReturnCode) { - if(yieldRC == SUCCESS) { - printf("Success attempting reconnect\n"); - } else { - printf("Failure to attempt to reconnect\n"); - return -6; - } - } - - terminate_yield_with_rc_thread = true; - pthread_join(yield_thread, NULL); - - if(true == aws_iot_mqtt_is_client_connected(&client)) { - printf("Success: is Mqtt connected api\n"); - } else { - printf("Failure: is Mqtt Connected api\n"); - return -7; - } - - rc = aws_iot_mqtt_disconnect(&client); - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c deleted file mode 100644 index 8d08980ee..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c +++ /dev/null @@ -1,281 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_basic_connectivity.c - * @brief Integration Test for basic client connectivity - */ - -#include "aws_iot_test_integration_common.h" - -#define BUFFER_SIZE 100 - -static bool terminate_yield_thread; - -static unsigned int countArray[PUBLISH_COUNT]; -static unsigned int rxMsgBufferTooBigCounter; -static unsigned int rxUnexpectedNumberCounter; -static unsigned int rePublishCount; -static unsigned int wrongYieldCount; - -typedef struct ThreadData { - AWS_IoT_Client *client; - int threadId; -} ThreadData; - -static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - char tempBuf[BUFFER_SIZE]; - char *next_token; - char *temp = NULL; - unsigned int tempRow = 0, tempCol = 0; - IoT_Error_t rc; - - if(params->payloadLen <= BUFFER_SIZE) { - snprintf(tempBuf, params->payloadLen, params->payload); - printf("\nMsg received : %s", tempBuf); - temp = strtok_r(tempBuf, " ,:", &next_token); - temp = strtok_r(NULL, " ,:", &next_token); - if(NULL == temp) { - return; - } - tempRow = atoi(temp); - temp = strtok_r(NULL, " ,:", &next_token); - temp = strtok_r(NULL, " ,:", &next_token); - if(NULL == temp) { - return; - } - - tempCol = atoi(temp); - - if(tempCol > 0 && tempCol <= PUBLISH_COUNT) { - countArray[tempCol - 1]++; - } else { - IOT_WARN(" \n Thread : %d, Msg : %d ", tempRow, tempCol); - rxUnexpectedNumberCounter++; - } - rc = aws_iot_mqtt_yield(pClient, 10); - if(MQTT_CLIENT_NOT_IDLE_ERROR != rc) { - IOT_ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n", - aws_iot_mqtt_get_client_state(pClient), rc); - wrongYieldCount++; - } - } else { - rxMsgBufferTooBigCounter++; - } -} - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { -} - -static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pClient, QoS qos, - struct timeval *pSubscribeTime) { - IoT_Error_t rc = SUCCESS; - struct timeval start, end; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos, - aws_iot_mqtt_tests_message_aggregator, NULL); - IOT_DEBUG("Sub response : %d\n", rc); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - while(SUCCESS == rc && terminate_yield_thread == false) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_yield(pClient, 100); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); // Client is busy, wait to get lock - - if(SUCCESS != rc) { - IOT_DEBUG("\nYield Returned : %d ", rc); - } - } - - return NULL; -} - -static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int i = 0; - char cPayload[100]; - IoT_Publish_Message_Params params; - IoT_Error_t rc = SUCCESS; - ThreadData *threadData = (ThreadData *) ptr; - AWS_IoT_Client *pClient = threadData->client; - int threadId = threadData->threadId; - - for(i = 0; i < PUBLISH_COUNT; i++) { - snprintf(cPayload, 100, "%s_Thread : %d, Msg : %d", AWS_IOT_MY_THING_NAME, threadId, i + 1); - printf("\nMsg being published: %s \n", cPayload); - params.payload = (void *) cPayload; - params.payloadLen = strlen(cPayload) + 1; - params.qos = QOS1; - params.isRetained = 0; - - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - if(rc != SUCCESS) { - IOT_WARN("Error Publishing #%d --> %d\n ", i, rc); - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - rePublishCount++; - if(rc != SUCCESS) { - IOT_ERROR("Error Publishing #%d --> %d Second Attempt \n", i, rc); - } - } - } - return 0; -} - -int aws_iot_mqtt_tests_basic_connectivity() { - pthread_t publish_thread, yield_thread; - char certDirectory[15] = "../../certs"; - char clientCRT[PATH_MAX + 1]; - char root_CA[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char clientId[50]; - IoT_Client_Init_Params initParams; - IoT_Client_Connect_Params connectParams; - int pubThreadReturn; - int yieldThreadReturn = 0; - float percentOfRxMsg = 0.0; - IoT_Error_t rc = SUCCESS; - int i, rxMsgCount = 0, j = 0; - struct timeval connectTime, subscribeTopic; - struct timeval start, end; - unsigned int connectCounter = 0; - int test_result = 0; - ThreadData threadData; - AWS_IoT_Client client; - - terminate_yield_thread = false; - - rxMsgBufferTooBigCounter = 0; - rxUnexpectedNumberCounter = 0; - rePublishCount = 0; - wrongYieldCount = 0; - for(i = 0; i < PUBLISH_COUNT; i++) { - countArray[i] = 0; - } - - IOT_DEBUG("\nConnecting Client "); - do { - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int)time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - printf("\n\nClient ID : %s \n", clientId); - - IOT_DEBUG("Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 10000; - initParams.tlsHandshakeTimeout_ms = 10000; - initParams.mqttPacketTimeout_ms = 5000; - initParams.isSSLHostnameVerify = true; - initParams.disconnectHandlerData = NULL; - initParams.isBlockOnThreadLockEnabled = true; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - aws_iot_mqtt_init(&client, &initParams); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *)&clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = false; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_connect(&client, &connectParams); - gettimeofday(&end, NULL); - timersub(&end, &start, &connectTime); - - connectCounter++; - } while(rc != SUCCESS && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - IOT_DEBUG("## Connect Success. Time sec: %d, usec: %d\n", connectTime.tv_sec, connectTime.tv_usec); - } else { - IOT_ERROR("## Connect Failed. error code %d\n", rc); - return -1; - } - - aws_iot_mqtt_tests_subscribe_to_test_topic(&client, QOS1, &subscribeTopic); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_thread_runner, &client); - sleep(1); - - threadData.client = &client; - threadData.threadId = 1; - pubThreadReturn = pthread_create(&publish_thread, NULL, aws_iot_mqtt_tests_publish_thread_runner, &threadData); - - pthread_join(publish_thread, NULL); - // This sleep is to ensure that the last publish message has enough time to be received by us - sleep(1); - - terminate_yield_thread = true; - pthread_join(yield_thread, NULL); - - /* Not using pthread_join because all threads should have terminated gracefully at this point. If they haven't, - * which should not be possible, something below will fail. */ - - for(i = 0; i < PUBLISH_COUNT; i++) { - if(countArray[i] > 0) { - rxMsgCount++; - } - } - - IOT_DEBUG("\n\nResult : \n"); - percentOfRxMsg = (float) rxMsgCount * 100 / PUBLISH_COUNT; - if(percentOfRxMsg >= RX_RECEIVE_PERCENTAGE && rxMsgBufferTooBigCounter == 0 && rxUnexpectedNumberCounter == 0 && - wrongYieldCount == 0) { - IOT_DEBUG("\n\nSuccess: %f \%\n", percentOfRxMsg); - IOT_DEBUG("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT, rxMsgCount); - IOT_DEBUG("QoS 1 re publish count %d\n", rePublishCount); - IOT_DEBUG("Connection Attempts %d\n", connectCounter); - IOT_DEBUG("Yield count without error during callback %d\n", wrongYieldCount); - test_result = 0; - } else { - IOT_ERROR("\n\nFailure: %f\n", percentOfRxMsg); - IOT_ERROR("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter); - IOT_ERROR("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter); - IOT_ERROR("Yield count without error during callback %d\n", wrongYieldCount); - test_result = -2; - } - aws_iot_mqtt_disconnect(&client); - return test_result; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c deleted file mode 100644 index 61ec00fab..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_integration_runner.c - * @brief Integration Test runner - */ - -#include "aws_iot_test_integration_common.h" - -int main() { - int rc = 0; - - printf("\n\n"); - printf("*************************************************************************************************\n"); - printf("* Starting TEST 1 MQTT Version 3.1.1 Basic Subscribe QoS 1 Publish QoS 1 with Single Client *\n"); - printf("*************************************************************************************************\n"); - rc = aws_iot_mqtt_tests_basic_connectivity(); - if(0 != rc) { - printf("\n********************************************************************************************************\n"); - printf("* TEST 1 MQTT Version 3.1.1 Basic Subscribe QoS 1 Publish QoS 1 with Single Client FAILED! RC : %4d *\n", rc); - printf("********************************************************************************************************\n"); - return 1; - } - printf("\n*************************************************************************************************\n"); - printf("* TEST 1 MQTT Version 3.1.1 Basic Subscribe QoS 1 Publish QoS 1 with Single Client SUCCESS!! *\n"); - printf("*************************************************************************************************\n"); - - printf("\n\n"); - printf("************************************************************************************************************\n"); - printf("* Starting TEST 2 MQTT Version 3.1.1 Multithreaded Subscribe QoS 1 Publish QoS 1 with Multiple Clients *\n"); - printf("************************************************************************************************************\n"); - rc = aws_iot_mqtt_tests_multiple_clients(); - if(0 != rc) { - printf("\n*******************************************************************************************************************\n"); - printf("* TEST 2 MQTT Version 3.1.1 Multithreaded Subscribe QoS 1 Publish QoS 1 with Multiple Clients FAILED! RC : %4d *\n", rc); - printf("*******************************************************************************************************************\n"); - return 1; - } - printf("\n*************************************************************************************************************\n"); - printf("* TEST 2 MQTT Version 3.1.1 Multithreaded Subscribe QoS 1 Publish QoS 1 with Multiple Clients SUCCESS!! *\n"); - printf("*************************************************************************************************************\n"); - - printf("\n\n"); - printf("*********************************************************\n"); - printf("* Starting TEST 3 MQTT Version 3.1.1 Auto Reconnect *\n"); - printf("*********************************************************\n"); - rc = aws_iot_mqtt_tests_auto_reconnect(); - if(0 != rc) { - printf("\n***************************************************************\n"); - printf("* TEST 3 MQTT Version 3.1.1 Auto Reconnect FAILED! RC : %4d *\n", rc); - printf("***************************************************************\n"); - return 1; - } - printf("\n**********************************************************\n"); - printf("* TEST 3 MQTT Version 3.1.1 Auto Reconnect SUCCESS!! *\n"); - printf("**********************************************************\n"); - -#ifndef DISABLE_IOT_JOBS -#ifndef DISABLE_IOT_JOBS_INTERFACE - printf("\n\n"); - printf("*************************************************************************************************\n"); - printf("* Starting TEST 4 Jobs API Test *\n"); - printf("*************************************************************************************************\n"); - rc = aws_iot_jobs_basic_test(); - if(0 != rc) { - printf("\n********************************************************************************************************\n"); - printf("* TEST 4 Jobs API Test FAILED! RC : %4d *\n", rc); - printf("********************************************************************************************************\n"); - return 1; - } - printf("\n*************************************************************************************************\n"); - printf("* TEST 4 Jobs API Test SUCCESS!! *\n"); - printf("*************************************************************************************************\n"); -#endif -#endif - - return 0; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_jobs_api.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_jobs_api.c deleted file mode 100644 index 4974eb857..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_jobs_api.c +++ /dev/null @@ -1,284 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#ifndef DISABLE_IOT_JOBS -#ifndef DISABLE_IOT_JOBS_INTERFACE - -#include "aws_iot_test_integration_common.h" -#include -#include -#include -#include -#include - -static AWS_IoT_Client client; - -static jsmn_parser jsonParser; -static jsmntok_t jsonTokenStruct[MAX_JSON_TOKEN_EXPECTED]; -static int32_t tokenCount; - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { -} - -void iot_get_pending_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IoT_Error_t rc = SUCCESS; - char topicToPublishGetNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_GET_PENDING_TOPIC callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - jsmn_init(&jsonParser); - - tokenCount = jsmn_parse(&jsonParser, params->payload, (int) params->payloadLen, jsonTokenStruct, MAX_JSON_TOKEN_EXPECTED); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d", tokenCount); - return; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object"); - return; - } - - jsmntok_t *jobs; - - jobs = findToken("inProgressJobs", params->payload, jsonTokenStruct); - - if (jobs) { - IOT_INFO("inProgressJobs: %.*s", jobs->end - jobs->start, (char *)params->payload + jobs->start); - } - - jobs = findToken("queuedJobs", params->payload, jsonTokenStruct); - - if (jobs) { - IOT_INFO("queuedJobs: %.*s", jobs->end - jobs->start, (char *)params->payload + jobs->start); - } - - AwsIotDescribeJobExecutionRequest describeRequest; - describeRequest.executionNumber = 0; - describeRequest.includeJobDocument = true; - describeRequest.clientToken = NULL; - - rc = aws_iot_jobs_describe(&client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_NEXT, &describeRequest, topicToPublishGetNext, sizeof(topicToPublishGetNext), NULL, 0); -} - -void iot_next_job_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char topicToPublishUpdate[MAX_JOB_TOPIC_LENGTH_BYTES]; - char messageBuffer[200]; - - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_NOTIFY_NEXT_TOPIC / JOB_DESCRIBE_TOPIC($next) callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - jsmn_init(&jsonParser); - - tokenCount = jsmn_parse(&jsonParser, params->payload, (int) params->payloadLen, jsonTokenStruct, MAX_JSON_TOKEN_EXPECTED); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d", tokenCount); - return; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object"); - return; - } - - jsmntok_t *tokExecution; - - tokExecution = findToken("execution", params->payload, jsonTokenStruct); - - if (tokExecution) { - IOT_INFO("execution: %.*s", tokExecution->end - tokExecution->start, (char *)params->payload + tokExecution->start); - - jsmntok_t *tok; - - tok = findToken("jobId", params->payload, tokExecution); - - if (tok) { - IoT_Error_t rc; - char jobId[MAX_SIZE_OF_JOB_ID + 1]; - AwsIotJobExecutionUpdateRequest updateRequest; - - rc = parseStringValue(jobId, MAX_SIZE_OF_JOB_ID + 1, params->payload, tok); - if(SUCCESS != rc) { - IOT_ERROR("parseStringValue returned error : %d ", rc); - return; - } - - IOT_INFO("jobId: %s", jobId); - - tok = findToken("jobDocument", params->payload, tokExecution); - - /* - * Do your job processing here. - */ - - if (tok) { - IOT_INFO("jobDocument: %.*s", tok->end - tok->start, (char *)params->payload + tok->start); - /* Alternatively if the job still has more steps the status can be set to JOB_EXECUTION_IN_PROGRESS instead */ - updateRequest.status = JOB_EXECUTION_SUCCEEDED; - updateRequest.statusDetails = "{\"exampleDetail\":\"a value appropriate for your successful job\"}"; - } else { - updateRequest.status = JOB_EXECUTION_FAILED; - updateRequest.statusDetails = "{\"failureDetail\":\"Unable to process job document\"}"; - } - - updateRequest.expectedVersion = 0; - updateRequest.executionNumber = 0; - updateRequest.includeJobExecutionState = false; - updateRequest.includeJobDocument = false; - updateRequest.clientToken = NULL; - - rc = aws_iot_jobs_send_update(pClient, QOS0, AWS_IOT_MY_THING_NAME, jobId, &updateRequest, - topicToPublishUpdate, sizeof(topicToPublishUpdate), messageBuffer, sizeof(messageBuffer)); - } - } else { - IOT_INFO("execution property not found, nothing to do, jobs integration test complete"); - - bool *callbackDone = (bool *) pData; - *callbackDone = true; - } -} - -int aws_iot_jobs_basic_test() { - char certDirectory[15] = "../../certs"; - char clientCRT[PATH_MAX + 1]; - char root_CA[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char clientId[50]; - char cPayload[100]; - IoT_Client_Init_Params initParams = IoT_Client_Init_Params_initializer; - IoT_Client_Connect_Params connectParams; - IoT_Publish_Message_Params paramsQOS0; - IoT_Error_t rc = SUCCESS; - struct timeval connectTime, waitCallBackTime; - struct timeval start, end; - unsigned int connectCounter = 0; - - IOT_DEBUG("\nConnecting Client "); - do { - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int)time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - printf("\n\nClient ID : %s \n", clientId); - - IOT_DEBUG("Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 10000; - initParams.tlsHandshakeTimeout_ms = 10000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - aws_iot_mqtt_init(&client, &initParams); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *)&clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = false; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_connect(&client, &connectParams); - gettimeofday(&end, NULL); - timersub(&end, &start, &connectTime); - - connectCounter++; - } while(rc != SUCCESS && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - IOT_DEBUG("## Connect Success. Time sec: %ld, usec: %ld\n", (long int)connectTime.tv_sec, (long int)connectTime.tv_usec); - } else { - IOT_ERROR("## Connect Failed. error code %d\n", rc); - return -1; - } - - bool callbackDone = false; - char topicToSubscribeGetPending[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeNotifyNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeGetNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - - char topicToPublishGetPending[MAX_JOB_TOPIC_LENGTH_BYTES]; - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, NULL, JOB_GET_PENDING_TOPIC, JOB_WILDCARD_REPLY_TYPE, - iot_get_pending_callback_handler, &callbackDone, topicToSubscribeGetPending, sizeof(topicToSubscribeGetPending)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_GET_PENDING_TOPIC: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, NULL, JOB_NOTIFY_NEXT_TOPIC, JOB_REQUEST_TYPE, - iot_next_job_callback_handler, &callbackDone, topicToSubscribeNotifyNext, sizeof(topicToSubscribeNotifyNext)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_NOTIFY_NEXT_TOPIC: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_NEXT, JOB_DESCRIBE_TOPIC, JOB_WILDCARD_REPLY_TYPE, - iot_next_job_callback_handler, &callbackDone, topicToSubscribeGetNext, sizeof(topicToSubscribeGetNext)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_DESCRIBE_TOPIC ($next): %d ", rc); - return rc; - } - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - paramsQOS0.payloadLen = strlen(cPayload); - - rc = aws_iot_jobs_send_query(&client, QOS0, AWS_IOT_MY_THING_NAME, NULL, NULL, topicToPublishGetPending, sizeof(topicToPublishGetPending), NULL, 0, JOB_GET_PENDING_TOPIC); - gettimeofday(&start, NULL); - while (!callbackDone) { - aws_iot_mqtt_yield(&client, 5000); - - gettimeofday(&end, NULL); - timersub(&end, &start, &waitCallBackTime); - - if(waitCallBackTime.tv_sec > 10) break; - } - - return 0; -} - -#endif -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c deleted file mode 100644 index 3ea85aae4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c +++ /dev/null @@ -1,286 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_test_multiple_clients.c - * @brief Integration Test for multiple clients from the same application - */ - -#include "aws_iot_test_integration_common.h" - - -#define MAX_ERROR_DISPLAY 50 -static bool terminate_yield_thread; - -static unsigned int countArray[PUBLISH_COUNT]; -static unsigned int rxMsgBufferTooBigCounter; -static unsigned int rxUnexpectedNumberCounter; -static unsigned int rePublishCount; - -static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char tempBuf[10]; - unsigned int tempInt = 0; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(10 >= params->payloadLen) { - snprintf(tempBuf, params->payloadLen, params->payload); - printf("\nMsg received : %s", tempBuf); - tempInt = atoi(tempBuf); - if(0 < tempInt && PUBLISH_COUNT >= tempInt) { - countArray[tempInt - 1]++; - } else { - rxUnexpectedNumberCounter++; - } - } else { - if( params->payloadLen > MAX_ERROR_DISPLAY) - { - ((char *)params->payload)[MAX_ERROR_DISPLAY-1] = '\0'; - IOT_ERROR("\nWrong Msg received : %s", (char *)params->payload); - }else - { - IOT_ERROR("\nWrong Msg received : %s", (char *)params->payload); - } - rxMsgBufferTooBigCounter++; - } -} - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { - IOT_UNUSED(pClient); - IOT_UNUSED(param); -} - -static IoT_Error_t aws_iot_mqtt_tests_connect_client_to_service(AWS_IoT_Client *pClient, struct timeval *pConnectTime, - char *clientId, char *rootCA, char *clientCRT, - char *clientKey) { - IoT_Client_Init_Params initParams; - IoT_Client_Connect_Params connectParams; - IoT_Error_t rc; - struct timeval start, end; - - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = rootCA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 5000; - initParams.tlsHandshakeTimeout_ms = 2000; - initParams.mqttPacketTimeout_ms = 5000; - initParams.isSSLHostnameVerify = true; - initParams.disconnectHandlerData = NULL; - initParams.isBlockOnThreadLockEnabled = true; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - rc = aws_iot_mqtt_init(pClient, &initParams); - printf("\n Init response : %d", rc); - - printf("\nRoot CA Path : %s\nClientCRT : %s\nClientKey : %s \nClient ID : %s", rootCA, clientCRT, - clientKey, clientId); - connectParams.keepAliveIntervalInSec = 5; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = 0; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_connect(pClient, &connectParams); - printf("\nConnect response : %d ", rc); - gettimeofday(&end, NULL); - timersub(&end, &start, pConnectTime); - - return rc; -} - -static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pClient, QoS qos, struct timeval *pSubscribeTime) { - IoT_Error_t rc = SUCCESS; - struct timeval start, end; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos, - aws_iot_mqtt_tests_message_aggregator, NULL); - printf("\nSub response : %d\n", rc); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - while(SUCCESS == rc && false == terminate_yield_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_yield(pClient, 100); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("\nYield Returned : %d ", rc); - } - } - - return NULL; -} - -static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int itr = 0; - char cPayload[10]; - IoT_Publish_Message_Params params; - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - sprintf(cPayload, "%d", itr + 1); - params.payload = (void *) cPayload; - params.payloadLen = strlen(cPayload) + 1; - params.qos = QOS1; - params.isRetained = 0; - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - printf("\n Publishing %s", cPayload); - if(SUCCESS != rc) { - printf("Error Publishing #%d --> %d\n ", itr, rc); - usleep(300000); - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - rePublishCount++; - if(SUCCESS != rc) { - printf("Error Publishing #%d --> %d Second Attempt \n", itr, rc); - } - } - usleep(300000); - } - - return NULL; -} - - -int aws_iot_mqtt_tests_multiple_clients() { - char certDirectory[15] = "../../certs"; - char CurrentWD[PATH_MAX + 1]; - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - - char subClientId[50]; - char pubClientId[50]; - - int itr = 0; - int rxMsgCount = 0; - int test_result = 0; - int pubThreadReturn = 0; - int yieldThreadReturn = 0; - unsigned int connectCounter = 0; - float percentOfRxMsg = 0.0; - - IoT_Error_t rc = SUCCESS; - pthread_t yield_thread; - pthread_t publish_thread; - struct timeval connectTime; - struct timeval subscribeTopic; - - AWS_IoT_Client pubClient; - AWS_IoT_Client subClient; - - terminate_yield_thread = false; - rxMsgBufferTooBigCounter = 0; - rxUnexpectedNumberCounter = 0; - rePublishCount = 0; - - srand((unsigned int)time(NULL)); - snprintf(subClientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID_SUB, rand() % 10000); - snprintf(pubClientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID_PUB, rand() % 10000); - - getcwd(CurrentWD, sizeof(CurrentWD)); - - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - countArray[itr] = 0; - } - - printf(" \n Connecting Pub Client "); - do { - rc = aws_iot_mqtt_tests_connect_client_to_service(&pubClient, &connectTime, pubClientId, rootCA, - clientCRT, clientKey); - connectCounter++; - } while(SUCCESS != rc && CONNECT_MAX_ATTEMPT_COUNT > connectCounter); - - if(SUCCESS == rc) { - printf("\n## Connect Success. Time sec: %ld, usec: %ld\n", (long int)connectTime.tv_sec, (long int)connectTime.tv_usec); - } else { - printf("\n## Connect Failed. error code %d\n", rc); - return -1; - } - - printf("\n Connecting Sub Client "); - do { - rc = aws_iot_mqtt_tests_connect_client_to_service(&subClient, &connectTime, subClientId, rootCA, - clientCRT, clientKey); - connectCounter++; - } while(SUCCESS != rc && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - printf("## Connect Success. Time sec: %ld, usec: %ld\n", (long int)connectTime.tv_sec, (long int)connectTime.tv_usec); - } else { - printf("## Connect Failed. error code %d\n", rc); - return -1; - } - - aws_iot_mqtt_tests_subscribe_to_test_topic(&subClient, QOS1, &subscribeTopic); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_thread_runner, &subClient); - pubThreadReturn = pthread_create(&publish_thread, NULL, aws_iot_mqtt_tests_publish_thread_runner, &pubClient); - - pthread_join(publish_thread, NULL); - - /* Kill yield thread */ - terminate_yield_thread = true; - pthread_join(yield_thread, NULL); - - aws_iot_mqtt_disconnect(&pubClient); - aws_iot_mqtt_disconnect(&subClient); - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - if(countArray[itr] > 0) { - rxMsgCount++; - } - } - - percentOfRxMsg = (float) rxMsgCount * 100 / PUBLISH_COUNT; - if(percentOfRxMsg >= RX_RECEIVE_PERCENTAGE && rxMsgBufferTooBigCounter == 0 && rxUnexpectedNumberCounter == 0) { - printf("\nSuccess: %f \%\n", percentOfRxMsg); - printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT, rxMsgCount); - printf("QoS 1 re publish count %d\n", rePublishCount); - printf("Connection Attempts %d\n", connectCounter); - test_result = 0; - } else { - printf("\nFailure: %f\n", percentOfRxMsg); - printf("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter); - printf("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter); - test_result = -2; - } - return test_result; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md deleted file mode 100644 index a58e2e475..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## Unit Tests -This folder contains unit tests to verify Embedded C SDK functionality. These have been tested to work with Linux using CppUTest as the testing framework. -CppUTest is not provided along with this code. It needs to be separately downloaded. These tests have been verified to work with CppUTest v3.6, which can be found [here](https://github.com/cpputest/cpputest/tree/v3.6). -Each test contains a comment describing what is being tested. The Tests can be run using the Makefile provided in the root folder for the SDK. There are a total of 187 tests. - -To run these tests, follow the below steps: - - * Copy the code for CppUTest v3.6 from github to external_libs/CppUTest - * Navigate to SDK Root folder - * run `make run-unit-tests` - -This will run all unit tests and generate coverage report in the build_output folder. The report can be viewed by opening /build_output/generated-coverage/index.html in a browser. \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h deleted file mode 100644 index b75d6e3b4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_config.h - * @brief IoT Client Unit Testing - IoT Config - */ - -#ifndef IOT_TESTS_UNIT_CONFIG_H_ -#define IOT_TESTS_UNIT_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "localhost" -#define AWS_IOT_MQTT_PORT 443 -#define AWS_IOT_MQTT_CLIENT_ID "C-SDK_UnitTestClient" -#define AWS_IOT_MY_THING_NAME "C-SDK_UnitTestThing" -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" -#define AWS_IOT_CERTIFICATE_FILENAME "cert.crt" -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" -// ================================================= - - -// MQTT PubSub -#ifndef DISABLE_IOT_JOBS -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#else -#define AWS_IOT_MQTT_RX_BUF_LEN 2048 -#endif -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Shadow and Job common configs -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_SIZE_OF_THING_NAME 30 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER 512 ///< Maximum size of the SHADOW buffer to store the received Shadow message -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Job specific configs -#ifndef DISABLE_IOT_JOBS -#define MAX_SIZE_OF_JOB_ID 64 -#define MAX_JOB_JSON_TOKEN_EXPECTED 120 -#define MAX_SIZE_OF_JOB_REQUEST AWS_IOT_MQTT_TX_BUF_LEN - -#define MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME 40 -#define MAX_JOB_TOPIC_LENGTH_BYTES MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME + MAX_SIZE_OF_THING_NAME + MAX_SIZE_OF_JOB_ID + 2 -#endif - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#endif /* IOT_TESTS_UNIT_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h deleted file mode 100644 index 337353af4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_helper_functions.h - * @brief IoT Client Unit Testing - Helper Functions - */ - -#ifndef IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ -#define IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ - -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_jobs_topics.h" - -typedef struct { - unsigned char PacketType; - unsigned int RemainingLength; - unsigned int ProtocolLength; - unsigned char ProtocolName[4]; - unsigned int ProtocolLevel; - unsigned char ConnectFlag; - unsigned int KeepAlive; -} ConnectBufferProofread; - -void ResetInvalidParameters(void); - -void InitMQTTParamsSetup(IoT_Client_Init_Params *params, char *pHost, uint16_t port, bool enableAutoReconnect, - iot_disconnect_handler disconnectHandler); - -void ConnectMQTTParamsSetup(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen); - -void ConnectMQTTParamsSetup_Detailed(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen, - QoS qos, bool isCleanSession, bool isWillMsgPresent, char *pWillTopicName, - uint16_t willTopicNameLen, char *pWillMessage, uint16_t willMsgLen, - char *pUsername, uint16_t userNameLen, char *pPassword, - uint16_t passwordLen); - -void printBuffer(unsigned char *buffer, size_t len); - -void setTLSRxBufferForConnack(IoT_Client_Connect_Params *params, unsigned char sessionPresent, - unsigned char connackResponseCode); - -void setTLSRxBufferForPuback(void); - -void setTLSRxBufferForSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params); - -void setTLSRxBufferForDoubleSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params); - -void setTLSRxBufferForSubFail(void); - -void setTLSRxBufferWithMsgOnSubscribedTopic(char *topicName, size_t topicNameLen, QoS qos, - IoT_Publish_Message_Params params, char *pMsg); - -void setTLSRxBufferForUnsuback(void); - -void setTLSRxBufferForPingresp(void); - -void setTLSRxBufferForError(IoT_Error_t error); - -void setTLSTxBufferForError(IoT_Error_t error); - -void setTLSRxBufferForConnackAndSuback(IoT_Client_Connect_Params *conParams, unsigned char sessionPresent, - char *topicName, size_t topicNameLen, QoS qos); - -unsigned char isLastTLSTxMessagePuback(void); - -unsigned char isLastTLSTxMessagePingreq(void); - -unsigned char isLastTLSTxMessageDisconnect(void); - -void setTLSRxBufferDelay(int seconds, int microseconds); - -void ResetTLSBuffer(void); - -unsigned char generateMultipleSubTopics(char *des, int boundary); - -void encodeRemainingLength(unsigned char *buf, size_t *st, size_t length); - -unsigned char *connectTxBufferHeaderParser(ConnectBufferProofread *params, unsigned char *buf); - -bool isConnectTxBufFlagCorrect(IoT_Client_Connect_Params *settings, ConnectBufferProofread *readRes); - -bool isConnectTxBufPayloadCorrect(IoT_Client_Connect_Params *settings, unsigned char *payloadBuf); - -void printPrfrdParams(ConnectBufferProofread *params); - -const char *getJobTopicTypeName(AwsIotJobExecutionTopicType topicType); - -const char *getJobReplyTypeName(AwsIotJobExecutionTopicReplyType replyType); - -#endif /* IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h deleted file mode 100644 index 455a387b3..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_helper.h - * @brief IoT Client Unit Testing - Shadow Helper functions - */ - -#ifndef IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ -#define IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ - -#define AWS_THINGS_TOPIC "$aws/things/" -#define SHADOW_TOPIC "/shadow/" -#define ACCEPTED_TOPIC "/accepted" -#define REJECTED_TOPIC "/rejected" -#define UPDATE_TOPIC "update" -#define GET_TOPIC "get" -#define DELETE_TOPIC "delete" - - -#define GET_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC ACCEPTED_TOPIC -#define GET_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC REJECTED_TOPIC -#define GET_PUB_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC - -#define DELETE_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC DELETE_TOPIC ACCEPTED_TOPIC -#define DELETE_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC DELETE_TOPIC REJECTED_TOPIC - -#define UPDATE_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC UPDATE_TOPIC ACCEPTED_TOPIC -#define UPDATE_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC UPDATE_TOPIC REJECTED_TOPIC - -#endif /* IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp deleted file mode 100644 index 449647ecc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_common_tests.cpp - * @brief IoT Client Unit Testing - Common Tests - */ - -#include -#include - -TEST_GROUP_C(CommonTests){ - TEST_GROUP_C_SETUP_WRAPPER(CommonTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(CommonTests) -}; - -TEST_GROUP_C_WRAPPER(CommonTests, NullClientGetState) -TEST_GROUP_C_WRAPPER(CommonTests, NullClientSetAutoreconnect) - -TEST_GROUP_C_WRAPPER(CommonTests, UnexpectedAckFiltering) -TEST_GROUP_C_WRAPPER(CommonTests, BigMQTTRxMessageIgnore) -TEST_GROUP_C_WRAPPER(CommonTests, BigMQTTRxMessageReadNextMessage) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c deleted file mode 100644 index 9d1604211..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c +++ /dev/null @@ -1,186 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_common_tests_helper.h - * @brief IoT Client Unit Testing - Common Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_log.h" -#include "aws_iot_tests_unit_helper_functions.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static AWS_IoT_Client iotClient; - -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; -char cPayload[100]; - -char cbBuffer[AWS_IOT_MQTT_TX_BUF_LEN + 2]; - -static void iot_tests_unit_common_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, IoT_Publish_Message_Params *params, - void *pData) { - char *tmp = params->payload; - unsigned int i; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - for(i = 0; i < params->payloadLen; i++) { - cbBuffer[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(CommonTests) { - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - IoT_Error_t rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("\n\nMQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(CommonTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -TEST_C(CommonTests, NullClientGetState) { - ClientState cs = aws_iot_mqtt_get_client_state(NULL); - CHECK_EQUAL_C_INT(CLIENT_STATE_INVALID, cs); -} - -TEST_C(CommonTests, NullClientSetAutoreconnect) { - IoT_Error_t rc = aws_iot_mqtt_autoreconnect_set_status(NULL, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -// Unexpected Ack section -TEST_C(CommonTests, UnexpectedAckFiltering) { - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("\n-->Running CommonTests - Unexpected Ack Filtering\n"); - // Assume we are connected and have not done anything yet - // Connack - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Puback - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Suback: OoS1 - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Suback: QoS0 - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Unsuback - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); -} - -TEST_C(CommonTests, BigMQTTRxMessageIgnore) { - uint32_t i = 0; - IoT_Error_t rc = FAILURE; - char expectedCallbackString[AWS_IOT_MQTT_RX_BUF_LEN + 2]; - - IOT_DEBUG("\n-->Running CommonTests - Ignore Large Incoming Message \n"); - - setTLSRxBufferForSuback("limitTest/topic1", 16, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "limitTest/topic1", 16, QOS0, iot_tests_unit_common_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - for(i = 0; i < AWS_IOT_MQTT_RX_BUF_LEN; i++) { - expectedCallbackString[i] = 'X'; - } - expectedCallbackString[i + 1] = '\0'; - - setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, rc); -} - -/** - * - * On receiving a big message into the TLS buffer the MQTT client should flush it out, otherwise it can cause undefined behavior. - */ -TEST_C(CommonTests, BigMQTTRxMessageReadNextMessage) { - uint32_t i = 0; - IoT_Error_t rc = FAILURE; - char expectedCallbackString[AWS_IOT_MQTT_RX_BUF_LEN + 2]; - - IOT_DEBUG("\n-->Running CommonTests - Clear Buffer when large message received and continue reading \n"); - - setTLSRxBufferForSuback("limitTest/topic1", 16, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "limitTest/topic1", 16, QOS0, iot_tests_unit_common_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - for(i = 0; i < AWS_IOT_MQTT_RX_BUF_LEN; i++) { - expectedCallbackString[i] = 'X'; - } - expectedCallbackString[i + 1] = '\0'; - - setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, rc); - - ResetTLSBuffer(); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - expectedCallbackString[3] = '\0'; - setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(rc, SUCCESS); - CHECK_EQUAL_C_STRING("XXX", cbBuffer); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp deleted file mode 100644 index 5b7ae0897..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_connect.cpp - * @brief IoT Client Unit Testing - Connect API Tests - */ - -#include -#include - -TEST_GROUP_C(ConnectTests){ - TEST_GROUP_C_SETUP_WRAPPER(ConnectTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(ConnectTests) -}; - -/* B:1 - Init with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientInit) -/* B:2 - Connect with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientConnect) -/* B:3 - Connect with Null/Empty endpoint */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullHost) -/* B:4 - Connect with Null/Empty port */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullPort) -/* B:5 - Connect with Null/Empty root CA path */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullRootCAPath) -/* B:6 - Connect with Null/Empty Client certificate path */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientCertificate) -/* B:7 - Connect with Null/Empty private key Path */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullPrivateKeyPath) -/* B:8 - Connect with Null/Empty client ID */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientID) -/* B:9 - Connect with invalid Endpoint */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidEndpoint) -/* B:10 - Connect with invalid correct endpoint but invalid port */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidPort) -/* B:11 - Connect with invalid Root CA path */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidRootCAPath) -/* B:12 - Connect with invalid Client certificate path */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidClientCertPath) -/* B:13 - Connect with invalid private key path */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidPrivateKeyPath) -/* B:14 - Connect, no response timeout */ -TEST_GROUP_C_WRAPPER(ConnectTests, NoResponseTimeout) -/* B:15 - Connect, connack malformed, too large */ -TEST_GROUP_C_WRAPPER(ConnectTests, ConnackTooLarge) -/* B:16 - Connect, connack malformed, fixed header corrupted */ -TEST_GROUP_C_WRAPPER(ConnectTests, FixedHeaderCorrupted) -/* B:17 - Connect, connack malformed, invalid remaining length */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidRemainingLength) -/* B:18 - Connect, connack returned error, unacceptable protocol version */ -TEST_GROUP_C_WRAPPER(ConnectTests, UnacceptableProtocolVersion) -/* B:19 - Connect, connack returned error, identifier rejected */ -TEST_GROUP_C_WRAPPER(ConnectTests, IndentifierRejected) -/* B:20 - Connect, connack returned error, Server unavailable */ -TEST_GROUP_C_WRAPPER(ConnectTests, ServerUnavailable) -/* B:21 - Connect, connack returned error, bad user name or password */ -TEST_GROUP_C_WRAPPER(ConnectTests, BadUserNameOrPassword) -/* B:22 - Connect, connack returned error, not authorized */ -TEST_GROUP_C_WRAPPER(ConnectTests, NotAuthorized) -/* B:23 - Connect, connack return after half command timeout delay, success */ -TEST_GROUP_C_WRAPPER(ConnectTests, SuccessAfterDelayedConnack) -/* B:24 - Connect, connack returned success */ -TEST_GROUP_C_WRAPPER(ConnectTests, ConnectSuccess) -/* B:25 - Connect, flag settings and parameters are recorded in buffer */ -TEST_GROUP_C_WRAPPER(ConnectTests, FlagSettingsAndParamsAreRecordedIntoBuf) -/* B:26 - Connect attempt, Disconnect, Manually reconnect */ -TEST_GROUP_C_WRAPPER(ConnectTests, ConnectDisconnectConnect) -/* B:27 - Connect attempt, Clean session, Subscribe */ -TEST_GROUP_C_WRAPPER(ConnectTests, cleanSessionInitSubscribers) -/* B:28 - Connect attempt, power cycle with clean session false */ -TEST_GROUP_C_WRAPPER(ConnectTests, PowerCycleWithCleanSessionFalse) -/* B:29 - Reconnect attempt succeeds, but resubscribes fail */ -TEST_GROUP_C_WRAPPER(ConnectTests, ReconnectAndResubscribe) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c deleted file mode 100644 index 40a0298cc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c +++ /dev/null @@ -1,792 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_connect_helper.c - * @brief IoT Client Unit Testing - Connect API Tests Helper - */ - -#include -#include -#include -#include -#include - -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" - -#include "aws_iot_log.h" - -#include "aws_iot_mqtt_client_common_internal.h" - -static bool unitTestIsMqttConnected = false; - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static AWS_IoT_Client iotClient; - -static IoT_Publish_Message_Params testPubMsgParams; -static ConnectBufferProofread prfrdParams; - -static char subTopic1[12] = "sdk/Topic1"; -static char subTopic2[12] = "sdk/Topic2"; - -#define NO_MSG_XXXX "XXXX" -static char CallbackMsgStringclean[100] = NO_MSG_XXXX; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char *tmp = params->payload; - unsigned int i; - - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgStringclean[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(ConnectTests) { - unitTestIsMqttConnected = false; - ( void ) aws_iot_mqtt_disconnect(&iotClient); - ResetTLSBuffer(); - ResetInvalidParameters(); -} - -TEST_GROUP_C_TEARDOWN(ConnectTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -/* B:1 - Init with Null/empty client instance */ -TEST_C(ConnectTests, NullClientInit) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:1 - Init with Null/empty client instance \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(NULL, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:1 - Init with Null/empty client instance \n"); -} - -/* B:2 - Connect with Null/empty client instance */ -TEST_C(ConnectTests, NullClientConnect) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:2 - Connect with Null/empty client instance \n"); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(NULL, &connectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:2 - Connect with Null/empty client instance \n"); -} - -/* B:3 - Connect with Null/Empty endpoint */ -TEST_C(ConnectTests, NullHost) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:3 - Connect with Null/Empty endpoint \n"); - - InitMQTTParamsSetup(&initParams, NULL, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:3 - Connect with Null/Empty endpoint \n"); -} - -/* B:4 - Connect with Null/Empty port */ -TEST_C(ConnectTests, NullPort) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:4 - Connect with Null/Empty port \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, 0, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:4 - Connect with Null/Empty port \n"); -} - -/* B:5 - Connect with Null/Empty root CA path */ -TEST_C(ConnectTests, NullRootCAPath) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:6 - Connect with Null/Empty root CA path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.pRootCALocation = NULL; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:6 - Connect with Null/Empty root CA path \n"); -} - -/* B:6 - Connect with Null/Empty Client certificate path */ -TEST_C(ConnectTests, NullClientCertificate) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:7 - Connect with Null/Empty Client certificate path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.pDeviceCertLocation = NULL; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:7 - Connect with Null/Empty Client certificate path \n"); -} - -/* B:7 - Connect with Null/Empty private key Path */ -TEST_C(ConnectTests, NullPrivateKeyPath) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:8 - Connect with Null/Empty private key Path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.pDevicePrivateKeyLocation = NULL; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:8 - Connect with Null/Empty private key Path \n"); -} - -/* B:8 - Connect with Null/Empty client ID */ -TEST_C(ConnectTests, NullClientID) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:8 - Connect with Null/Empty client ID \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - setTLSRxBufferForConnack(&connectParams, 0, 0); - - /* If no client id is passed but a length was passed, return error */ - ConnectMQTTParamsSetup(&connectParams, NULL, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - /* If client id is passed but 0 length was passed, return error */ - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - /* If client id is NULL and length is 0 then request succeeds */ - ConnectMQTTParamsSetup(&connectParams, NULL, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - B:8 - Connect with Null/Empty client ID \n"); -} - -/* B:9 - Connect with invalid Endpoint */ -TEST_C(ConnectTests, InvalidEndpoint) { - IoT_Error_t rc = SUCCESS; - char invalidEndPoint[20]; - snprintf(invalidEndPoint, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:9 - Connect with invalid Endpoint \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidEndpointFilter = invalidEndPoint; - initParams.pHostURL = invalidEndpointFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:9 - Connect with invalid Endpoint \n"); -} - -/* B:10 - Connect with invalid correct endpoint but invalid port */ -TEST_C(ConnectTests, InvalidPort) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:10 - Connect with invalid correct endpoint but invalid port \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidPortFilter = 1234; - initParams.port = invalidPortFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:10 - Connect with invalid correct endpoint but invalid port \n"); -} - -/* B:11 - Connect with invalid Root CA path */ -TEST_C(ConnectTests, InvalidRootCAPath) { - IoT_Error_t rc = SUCCESS; - char invalidRootCAPath[20]; - snprintf(invalidRootCAPath, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:11 - Connect with invalid Root CA path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidRootCAPathFilter = invalidRootCAPath; - initParams.pRootCALocation = invalidRootCAPathFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:11 - Connect with invalid Root CA path \n"); -} - -/* B:12 - Connect with invalid Client certificate path */ -TEST_C(ConnectTests, InvalidClientCertPath) { - IoT_Error_t rc = SUCCESS; - char invalidCertPath[20]; - snprintf(invalidCertPath, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:12 - Connect with invalid Client certificate path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidCertPathFilter = invalidCertPath; - initParams.pDeviceCertLocation = invalidCertPathFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:12 - Connect with invalid Client certificate path \n"); -} - -/* B:13 - Connect with invalid private key path */ -TEST_C(ConnectTests, InvalidPrivateKeyPath) { - IoT_Error_t rc = SUCCESS; - char invalidPrivKeyPath[20]; - snprintf(invalidPrivKeyPath, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:13 - Connect with invalid private key path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidPrivKeyPathFilter = invalidPrivKeyPath; - initParams.pDevicePrivateKeyLocation = invalidPrivKeyPathFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:13 - Connect with invalid private key path \n"); -} - -/* B:14 - Connect, no response timeout */ -TEST_C(ConnectTests, NoResponseTimeout) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:14 - Connect, no response timeout \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - B:14 - Connect, no response timeout \n"); -} - -/* B:15 - Connect, connack malformed, too large */ -TEST_C(ConnectTests, ConnackTooLarge) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:15 - Connect, connack malformed, too large \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - RxBuffer.pBuffer[1] = (char) (0x15); /* Set remaining length to a larger than expected value */ - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:15 - Connect, connack malformed, too large \n"); -} - -/* B:16 - Connect, connack malformed, fixed header corrupted */ -TEST_C(ConnectTests, FixedHeaderCorrupted) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:16 - Connect, connack malformed, fixed header corrupted \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - RxBuffer.pBuffer[0] = (char) (0x00); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:16 - Connect, connack malformed, fixed header corrupted \n"); -} - -/* B:17 - Connect, connack malformed, invalid remaining length */ -TEST_C(ConnectTests, InvalidRemainingLength) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:17 - Connect, connack malformed, invalid remaining length \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - RxBuffer.pBuffer[1] = (char) (0x00); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_DECODE_REMAINING_LENGTH_ERROR, rc); - - IOT_DEBUG("-->Success - B:17 - Connect, connack malformed, invalid remaining length \n"); -} - -/* B:18 - Connect, connack returned error, unacceptable protocol version */ -TEST_C(ConnectTests, UnacceptableProtocolVersion) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:18 - Connect, connack returned error, unacceptable protocol version \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.MQTTVersion = 7; - setTLSRxBufferForConnack(&connectParams, 0, 1); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR, rc); - - IOT_DEBUG("-->Success - B:18 - Connect, connack returned error, unacceptable protocol version \n"); -} - -/* B:19 - Connect, connack returned error, identifier rejected */ -TEST_C(ConnectTests, IndentifierRejected) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:19 - Connect, connack returned error, identifier rejected \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 2); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR, rc); - - IOT_DEBUG("-->Success - B:19 - Connect, connack returned error, identifier rejected \n"); -} - -/* B:20 - Connect, connack returned error, Server unavailable */ -TEST_C(ConnectTests, ServerUnavailable) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:20 - Connect, connack returned error, Server unavailable \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 3); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR, rc); - - IOT_DEBUG("-->Success - B:20 - Connect, connack returned error, Server unavailable \n"); -} - -/* B:21 - Connect, connack returned error, bad user name or password */ -TEST_C(ConnectTests, BadUserNameOrPassword) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:21 - Connect, connack returned error, bad user name or password \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 4); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_BAD_USERDATA_ERROR, rc); - - IOT_DEBUG("-->Success - B:21 - Connect, connack returned error, bad user name or password \n"); -} - -/* B:22 - Connect, connack returned error, not authorized */ -TEST_C(ConnectTests, NotAuthorized) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("\n-->Running Connect Tests - B:22 - Connect, connack returned error, not authorized \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 5); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_NOT_AUTHORIZED_ERROR, rc); - - IOT_DEBUG("\n-->Success - B:22 - Connect, connack returned error, not authorized \n"); -} - -/* B:23 - Connect, connack return after half command timeout delay, success */ -TEST_C(ConnectTests, SuccessAfterDelayedConnack) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:23 - Connect, connack return after half command timeout delay, success \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - setTLSRxBufferDelay(0, (int) initParams.mqttCommandTimeout_ms/2); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - B:23 - Connect, connack return after half command timeout delay, success \n"); -} - -/* B:24 - Connect, connack returned success */ -TEST_C(ConnectTests, ConnectSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:24 - Connect, connack returned success \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - B:24 - Connect, connack returned success \n"); -} - -/* B:25 - Connect, flag settings and parameters are recorded in buffer */ -TEST_C(ConnectTests, FlagSettingsAndParamsAreRecordedIntoBuf) { - IoT_Error_t rc = SUCCESS; - unsigned char *currPayload = NULL; - - IOT_DEBUG("-->Running Connect Tests - B:25 - Connect, flag settings and parameters are recorded in buffer \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - ConnectMQTTParamsSetup_Detailed(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID), - QOS1, false, true, "willTopicName", (uint16_t) strlen("willTopicName"), "willMsg", - (uint16_t) strlen("willMsg"), NULL, 0, NULL, 0); - connectParams.keepAliveIntervalInSec = (1 << 16) - 1; - setTLSRxBufferForConnack(&connectParams, 0, 0); - - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer); - CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams)); - CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload)); - - IOT_DEBUG("-->Success - B:25 - Connect, flag settings and parameters are recorded in buffer \n"); -} - -/* B:26 - Connect attempt, Disconnect, Manually reconnect */ -TEST_C(ConnectTests, ConnectDisconnectConnect) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:26 - Connect attempt, Disconnect, Manually reconnect \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - - // connect - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // check the is_connected call - unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(true, unitTestIsMqttConnected); - - // disconnect - rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // check the is_connected call - unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(false, unitTestIsMqttConnected); - - ResetTLSBuffer(); - setTLSRxBufferForConnack(&connectParams, 0, 0); - - // connect - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // check the is_connected call - unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(true, unitTestIsMqttConnected); - - IOT_DEBUG("-->Success - B:26 - Connect attempt, Disconnect, Manually reconnect \n"); -} - -/* B:27 - Connect attempt, Clean session, Subscribe - * connect with clean session true and subscribe to a topic1, set msg to topic1 and ensure it is received - * connect cs false, set msg to topic1 and nothing should come in, Sub to topic2 and check if msg is received - * connect cs false and send msg to topic2 and should be received - * cs true and everything should be clean again - */ -TEST_C(ConnectTests, cleanSessionInitSubscribers) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "msg topic"; - - IOT_DEBUG("-->Running Connect Tests - B:27 - Connect attempt, Clean session, Subscribe \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); - - //1. connect with clean session true and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = true; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //1. subscribe to a topic1 and - testPubMsgParams.payload = expectedCallbackString; - testPubMsgParams.payloadLen = (uint16_t) strlen(expectedCallbackString); - setTLSRxBufferForSuback(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic1, (uint16_t) strlen(subTopic1), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - //1. receive message - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - ResetTLSBuffer(); - rc = aws_iot_mqtt_disconnect(&iotClient); - - //2. connect cs false and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = false; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - //3. set msg to topic1 and should receive the topic1 message - snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - ResetTLSBuffer(); - //4. ,sub to topic2 - snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX); - setTLSRxBufferForSuback(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic2, (uint16_t) strlen(subTopic2), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - //5. and check if topic 2 msg is received - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic2, strlen(subTopic2), QOS0, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - rc = aws_iot_mqtt_disconnect(&iotClient); - - //6. connect cs false and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = false; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //7. set msg to topic2 and - snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic2, strlen(subTopic2), QOS0, testPubMsgParams, - expectedCallbackString); - //8. should be received - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - IOT_DEBUG("-->Success - B:27 - Connect attempt, Clean session, Subscribe \n"); - -} - -/* B:28 - Connect attempt, power cycle with clean session false - * This test is to ensure we can initialize the subscribe table in mqtt even when connecting with CS = false - * currently the AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS is set to 5 - */ -TEST_C(ConnectTests, PowerCycleWithCleanSessionFalse) { - IoT_Error_t rc = SUCCESS; - int itr = 0; - char subTestTopic[12]; - uint16_t subTestTopicLen = 0; - - IOT_DEBUG("-->Running Connect Tests - B:28 - Connect attempt, power cycle with clean session false \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); - - //1. connect with clean session false and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = true; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //2. subscribe to max number of topics - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) { - snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1); - subTestTopicLen = (uint16_t) strlen(subTestTopic); - setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - //3. Subscribe to one more topic. Should return error - snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1); - subTestTopicLen = (uint16_t) strlen(subTestTopic); - setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc); - - IOT_DEBUG("-->Success - B:28 - Connect attempt, power cycle with clean session false \n"); -} - -/* B:29 - Reconnect attempt succeeds, but resubscribes fail. - * This test verifies the behaviour that if a subscribe operation fails after - * connect during the auto-reconnect sequence, the client must not disconnect - * and must only re-attempt the subscribe operation. */ -TEST_C(ConnectTests, ReconnectAndResubscribe) { - IoT_Error_t rc = SUCCESS; - int itr = 0; - char subTestTopic[12] = { 0 }; - uint16_t subTestTopicLen = 0; - IoT_Publish_Message_Params publish = { 0 }; - - IOT_DEBUG("-->Running Connect Tests - B:29 - Reconnect attempt succeeds, but resubscribes fail \n"); - - #if AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS < 3 - #error "ReconnectAndResubscribe needs at least 3 subscription handlers to run" - #endif - - // 1. Initialize client - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, true, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); - - // 2. Establish connection - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = true; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // 3. Add 3 subscriptions - for(itr = 0; itr < 3; itr++) - { - snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1); - subTestTopicLen = (uint16_t) strlen(subTestTopic); - setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - // 4. Trigger a reconnect by mocking NETWORK_SSL_READ_ERROR and calling yield. - // Place a CONNACK and SUBACK in the Rx buffer so that connect and 1 subscribe - // succeed. Note that the CONNACK and SUBACK placed in the Rx buffer are not - // effected by the mocked error as it does not change thr content of the Rx - // buffer. - setTLSRxBufferForError(NETWORK_SSL_READ_ERROR); - setTLSRxBufferForConnackAndSuback(&connectParams, 0, "sdk/topic0", 10, QOS0); - rc = aws_iot_mqtt_yield(&iotClient, AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL * 2); - - // 5. Check results of yield call. As only 1 SUBACK was present in the Rx - // buffer, 2 resubscribes must fail. Client should be in a pending - // resubscribe state and the auto reconnect interval should have doubled. - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - CHECK_EQUAL_C_INT(1, iotClient.clientData.messageHandlers[0].resubscribed); - CHECK_EQUAL_C_INT(0, iotClient.clientData.messageHandlers[1].resubscribed); - CHECK_EQUAL_C_INT(0, iotClient.clientData.messageHandlers[2].resubscribed); - CHECK_EQUAL_C_INT(CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS, aws_iot_mqtt_get_client_state(&iotClient)); - CHECK_EQUAL_C_INT(2 * AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL, (int) iotClient.clientData.currentReconnectWaitInterval); - - // 6. Add 2 more SUBACKs to the Rx buffer to complete the resubscribe. - setTLSRxBufferForDoubleSuback("sdk/topic1", 10, QOS0, publish); - rc = aws_iot_mqtt_yield(&iotClient, 2 * AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL * 2); - CHECK_EQUAL_C_INT(CLIENT_STATE_CONNECTED_IDLE, aws_iot_mqtt_get_client_state(&iotClient)); - CHECK_EQUAL_C_INT(1, iotClient.clientData.messageHandlers[0].resubscribed); - CHECK_EQUAL_C_INT(1, iotClient.clientData.messageHandlers[1].resubscribed); - CHECK_EQUAL_C_INT(1, iotClient.clientData.messageHandlers[2].resubscribed); - - IOT_DEBUG("-->Success - B:29 - Reconnect attempt succeeds, but resubscribes fail \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp deleted file mode 100644 index 09edca39b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_disconnect.cpp - * @brief IoT Client Unit Testing - Disconnect API Tests - */ - -#include -#include - -TEST_GROUP_C(DisconnectTests){ - TEST_GROUP_C_SETUP_WRAPPER(DisconnectTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(DisconnectTests) -}; - -/* F:1 - Disconnect with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(DisconnectTests, NullClientDisconnect) -/* F:2 - Set Disconnect Handler with Null/empty Client */ -TEST_GROUP_C_WRAPPER(DisconnectTests, NullClientSetDisconnectHandler) -/* F:3 - Call Set Disconnect handler with Null handler */ -TEST_GROUP_C_WRAPPER(DisconnectTests, SetDisconnectHandlerNullHandler) -/* F:4 - Disconnect attempt, not connected */ -TEST_GROUP_C_WRAPPER(DisconnectTests, disconnectNotConnected) -/* F:5 - Disconnect success */ -TEST_GROUP_C_WRAPPER(DisconnectTests, disconnectNoAckSuccess) -/* F:6 - Disconnect, Handler invoked on disconnect */ -TEST_GROUP_C_WRAPPER(DisconnectTests, HandlerInvokedOnDisconnect) -/* F:7 - Disconnect, with set handler and invoked on disconnect */ -TEST_GROUP_C_WRAPPER(DisconnectTests, SetHandlerAndInvokedOnDisconnect) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c deleted file mode 100644 index 681862b43..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c +++ /dev/null @@ -1,244 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_disconnect_helper.c - * @brief IoT Client Unit Testing - Disconnect Tests helper - */ - -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static AWS_IoT_Client iotClient; - -static bool handlerInvoked = false; - -void disconnectTestHandler(AWS_IoT_Client *pClient, void *disconHandlerParam) { - IOT_UNUSED(pClient); - IOT_UNUSED(disconHandlerParam); - - handlerInvoked = true; -} - -TEST_GROUP_C_SETUP(DisconnectTests) { - IoT_Error_t rc; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, true, disconnectTestHandler); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.keepAliveIntervalInSec = 5; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(DisconnectTests) { } - - -/* F:1 - Disconnect with Null/empty client instance */ -TEST_C(DisconnectTests, NullClientDisconnect) { - IoT_Error_t rc = aws_iot_mqtt_disconnect(NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* F:2 - Set Disconnect Handler with Null/empty Client */ -TEST_C(DisconnectTests, NullClientSetDisconnectHandler) { - IoT_Error_t rc = aws_iot_mqtt_set_disconnect_handler(NULL, disconnectTestHandler, NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* F:3 - Call Set Disconnect handler with Null handler */ -TEST_C(DisconnectTests, SetDisconnectHandlerNullHandler) { - IoT_Error_t rc = aws_iot_mqtt_set_disconnect_handler(&iotClient, NULL, NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* F:4 - Disconnect attempt, not connected */ -TEST_C(DisconnectTests, disconnectNotConnected) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Disconnect Tests - F:4 - Disconnect attempt, not connected \n"); - - /* First make sure client is disconnected */ - rc = aws_iot_mqtt_disconnect(&iotClient); - - /* Check client is disconnected */ - CHECK_EQUAL_C_INT(false, aws_iot_mqtt_is_client_connected(&iotClient)); - - /* Now call disconnect again */ - rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - - IOT_DEBUG("-->Success - F:4 - Disconnect attempt, not connected \n"); -} - -/* F:5 - Disconnect success */ -TEST_C(DisconnectTests, disconnectNoAckSuccess) { - IoT_Error_t rc = SUCCESS; - rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(SUCCESS, rc); -} - -/* F:6 - Disconnect, Handler invoked on disconnect */ -TEST_C(DisconnectTests, HandlerInvokedOnDisconnect) { - bool connected = false; - bool currentAutoReconnectStatus = false; - int i; - int j; - int attempt = 3; - uint32_t dcCount = 0; - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Disconnect Tests - F:6 - Disconnect, Handler invoked on disconnect \n"); - - handlerInvoked = false; - - IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", connectParams.keepAliveIntervalInSec); - currentAutoReconnectStatus = aws_iot_is_autoreconnect_enabled(&iotClient); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(1, connected); - - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - - // 3 cycles of half keep alive time expiring - // verify a ping request is sent and give a ping response - for(i = 0; i < attempt; i++) { - /* Set TLS buffer for ping response */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - for(j = 0; j <= connectParams.keepAliveIntervalInSec; j++) { - sleep(1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq()); - } - - // keepalive() waits for 1/2 of keepalive time after sending ping request - // to receive a pingresponse before determining the connection is not alive - // wait for keepalive time and then yield() - sleep(connectParams.keepAliveIntervalInSec); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(0, connected); - - CHECK_EQUAL_C_INT(true, handlerInvoked); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(1 == dcCount); - - aws_iot_mqtt_reset_network_disconnected_count(&iotClient); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(0 == dcCount); - - ResetTLSBuffer(); - aws_iot_mqtt_autoreconnect_set_status(&iotClient, currentAutoReconnectStatus); - - IOT_DEBUG("-->Success - F:6 - Disconnect, Handler invoked on disconnect \n"); -} - - -/* F:7 - Disconnect, with set handler and invoked on disconnect */ -TEST_C(DisconnectTests, SetHandlerAndInvokedOnDisconnect) { - bool connected = false; - bool currentAutoReconnectStatus = false; - int i; - int j; - int attempt = 3; - uint32_t dcCount = 0; - IoT_Error_t rc = SUCCESS; - IOT_DEBUG("-->Running Disconnect Tests - F:7 - Disconnect, with set handler and invoked on disconnect \n"); - - handlerInvoked = false; - InitMQTTParamsSetup(&initParams, "localhost", AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.keepAliveIntervalInSec = 5; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - aws_iot_mqtt_set_disconnect_handler(&iotClient, disconnectTestHandler, NULL); - aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - - IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", connectParams.keepAliveIntervalInSec); - currentAutoReconnectStatus = aws_iot_is_autoreconnect_enabled(&iotClient); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(1, connected); - - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - - // 3 cycles of keep alive time expiring - // verify a ping request is sent and give a ping response - for(i = 0; i < attempt; i++) { - /* Set TLS buffer for ping response */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - for(j = 0; j <= connectParams.keepAliveIntervalInSec; j++) { - sleep(1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq()); - } - ResetTLSBuffer(); - - // keepalive() waits for 1/2 of keepalive time after sending ping request - // to receive a pingresponse before determining the connection is not alive - // wait for keepalive time and then yield() - sleep(connectParams.keepAliveIntervalInSec); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(0, connected); - - CHECK_EQUAL_C_INT(true, handlerInvoked); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(1 == dcCount); - - aws_iot_mqtt_reset_network_disconnected_count(&iotClient); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(0 == dcCount); - - ResetTLSBuffer(); - aws_iot_mqtt_autoreconnect_set_status(&iotClient, currentAutoReconnectStatus); - - IOT_DEBUG("-->Success - F:7 - Disconnect, with set handler and invoked on disconnect \n"); -} - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c deleted file mode 100644 index 2f71b1435..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c +++ /dev/null @@ -1,571 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_helper_functions.c - * @brief IoT Client Unit Testing - Helper Functions - */ - -#include -#include -#include "aws_iot_mqtt_client.h" -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_version.h" - -#if !DISABLE_METRICS -#define SDK_METRICS_LEN 25 -#define SDK_METRICS_TEMPLATE "?SDK=C&Version=%d.%d.%d" -static char pUsernameTemp[SDK_METRICS_LEN] = {0}; -#endif - -#define CONNACK_SUBACK_PACKET_SIZE 9 -#define PUBACK_PACKET_SIZE 4 -#define SUBACK_PACKET_SIZE 5 -#define UNSUBACK_PACKET_SIZE 4 -#define PINGRESP_PACKET_SIZE 2 - -void ResetInvalidParameters(void) { - invalidEndpointFilter = NULL; - invalidRootCAPathFilter = NULL; - invalidCertPathFilter = NULL; - invalidPrivKeyPathFilter = NULL; - invalidPortFilter = 0; -} - -void InitMQTTParamsSetup(IoT_Client_Init_Params *params, char *pHost, uint16_t port, bool enableAutoReconnect, - iot_disconnect_handler disconnectHandler) { - params->pHostURL = pHost; - params->port = port; - params->mqttCommandTimeout_ms = 5000; - params->tlsHandshakeTimeout_ms = 5000; - params->enableAutoReconnect = enableAutoReconnect; - params->disconnectHandler = disconnectHandler; - params->disconnectHandlerData = NULL; - params->isSSLHostnameVerify = true; - params->pDeviceCertLocation = AWS_IOT_ROOT_CA_FILENAME; - params->pDevicePrivateKeyLocation = AWS_IOT_CERTIFICATE_FILENAME; - params->pRootCALocation = AWS_IOT_PRIVATE_KEY_FILENAME; -} - -void ConnectMQTTParamsSetup(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen) { - params->keepAliveIntervalInSec = 10; - params->isCleanSession = 1; - params->MQTTVersion = MQTT_3_1_1; - params->pClientID = pClientID; - params->clientIDLen = clientIDLen; - params->isWillMsgPresent = false; - params->pUsername = NULL; - params->usernameLen = 0; - params->pPassword = NULL; - params->passwordLen = 0; -} - -void ConnectMQTTParamsSetup_Detailed(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen, QoS qos, - bool isCleanSession, bool isWillMsgPresent, char *pWillTopicName, - uint16_t willTopicNameLen, char *pWillMessage, uint16_t willMsgLen, - char *pUsername, uint16_t userNameLen, char *pPassword, uint16_t passwordLen) { - params->keepAliveIntervalInSec = 10; - params->isCleanSession = isCleanSession; - params->MQTTVersion = MQTT_3_1_1; - params->pClientID = pClientID; - params->clientIDLen = clientIDLen; - params->pUsername = pUsername; - params->usernameLen = userNameLen; - params->pPassword = pPassword; - params->passwordLen = passwordLen; - params->isWillMsgPresent = isWillMsgPresent; - params->will.pMessage = pWillMessage; - params->will.msgLen = willMsgLen; - params->will.pTopicName = pWillTopicName; - params->will.topicNameLen = willTopicNameLen; - params->will.qos = qos; - params->will.isRetained = false; -} - -void printBuffer(unsigned char *buffer, size_t len) { - size_t i; - printf("\n--\n"); - for(i = 0; i < len; i++) { - printf("%d: %c, %d\n", (uint32_t)i, buffer[i], buffer[i]); - } - printf("\n--\n"); -} - -#define CONNACK_PACKET_SIZE 4 - -void setTLSRxBufferForConnack(IoT_Client_Connect_Params *params, unsigned char sessionPresent, - unsigned char connackResponseCode) { - RxBuffer.NoMsgFlag = false; - - if(params->isCleanSession) { - sessionPresent = 0; - } - - RxBuffer.pBuffer[0] = (unsigned char) (0x20); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - RxBuffer.pBuffer[2] = sessionPresent; - RxBuffer.pBuffer[3] = connackResponseCode; - - RxBuffer.len = CONNACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForConnackAndSuback(IoT_Client_Connect_Params *conParams, unsigned char sessionPresent, - char *topicName, size_t topicNameLen, QoS qos) { - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - - RxBuffer.NoMsgFlag = false; - - if(conParams->isCleanSession) { - sessionPresent = 0; - } - - RxBuffer.pBuffer[0] = (unsigned char) (0x20); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - RxBuffer.pBuffer[2] = sessionPresent; - RxBuffer.pBuffer[3] = (unsigned char) (0x0); - - RxBuffer.pBuffer[4] = (unsigned char) (0x90); - RxBuffer.pBuffer[5] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[6] = (unsigned char) (2); - RxBuffer.pBuffer[7] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[8] = (unsigned char) (qos); - - RxBuffer.len = CONNACK_SUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForPuback(void) { - size_t i; - - RxBuffer.NoMsgFlag = true; - RxBuffer.len = PUBACK_PACKET_SIZE; - RxIndex = 0; - - for(i = 0; i < RxBuffer.BufMaxSize; i++) { - RxBuffer.pBuffer[i] = 0; - } - - RxBuffer.pBuffer[0] = (unsigned char) (0x40); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - RxBuffer.pBuffer[2] = (unsigned char) (0x02); - RxBuffer.pBuffer[3] = (unsigned char) (0x00); - RxBuffer.NoMsgFlag = false; -} - -void setTLSRxBufferForSubFail(void) { - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x90); - RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[4] = (unsigned char) (128); - - RxBuffer.len = SUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForDoubleSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params) { - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(params); - - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x90); - RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[4] = (unsigned char) (qos); - - RxBuffer.pBuffer[5] = (unsigned char) (0x90); - RxBuffer.pBuffer[6] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[7] = (unsigned char) (2); - RxBuffer.pBuffer[8] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[9] = (unsigned char) (qos); - - RxBuffer.len = SUBACK_PACKET_SIZE * 2; - RxIndex = 0; -} - -void setTLSRxBufferForSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params) { - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(params); - - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x90); - RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[4] = (unsigned char) (qos); - - RxBuffer.len = SUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForUnsuback(void) { - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0xB0); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // No payload - RxBuffer.len = UNSUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForPingresp(void) { - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0xD0); - RxBuffer.pBuffer[1] = (unsigned char) (0x00); - RxBuffer.len = PINGRESP_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForError(IoT_Error_t error) { - RxBuffer.mockedError = error; -} - -void setTLSTxBufferForError(IoT_Error_t error) { - TxBuffer.mockedError = error; -} - -void ResetTLSBuffer(void) { - size_t i; - RxBuffer.len = 0; - RxBuffer.NoMsgFlag = true; - - for(i = 0; i < RxBuffer.BufMaxSize; i++) { - RxBuffer.pBuffer[i] = 0; - } - - RxIndex = 0; - RxBuffer.expiry_time.tv_sec = 0; - RxBuffer.expiry_time.tv_usec = 0; - TxBuffer.len = 0; - for(i = 0; i < TxBuffer.BufMaxSize; i++) { - TxBuffer.pBuffer[i] = 0; - } -} - -void setTLSRxBufferDelay(int seconds, int microseconds) { - struct timeval now, duration, result; - duration.tv_sec = seconds; - duration.tv_usec = microseconds; - - gettimeofday(&now, NULL); - timeradd(&now, &duration, &result); - RxBuffer.expiry_time.tv_sec = result.tv_sec; - RxBuffer.expiry_time.tv_usec = result.tv_usec; -} - -void setTLSRxBufferWithMsgOnSubscribedTopic(char *topicName, size_t topicNameLen, QoS qos, - IoT_Publish_Message_Params params, char *pMsg) { - size_t VariableLen = topicNameLen + 2 + 2; - size_t i = 0, cursor = 0, packetIdStartLoc = 0, payloadStartLoc = 0, VarHeaderStartLoc = 0; - size_t PayloadLen = strlen(pMsg) + 1; - - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x30 | ((params.qos << 1) & 0xF));// QoS1 - cursor++; // Move the cursor - - // Remaining Length - // Translate the Remaining Length into packet bytes - encodeRemainingLength(RxBuffer.pBuffer, &cursor, VariableLen + PayloadLen); - - VarHeaderStartLoc = cursor - 1; - // Variable header - RxBuffer.pBuffer[VarHeaderStartLoc + 1] = (unsigned char) ((topicNameLen & 0xFF00) >> 8); - RxBuffer.pBuffer[VarHeaderStartLoc + 2] = (unsigned char) (topicNameLen & 0xFF); - for(i = 0; i < topicNameLen; i++) { - RxBuffer.pBuffer[VarHeaderStartLoc + 3 + i] = (unsigned char) topicName[i]; - } - - packetIdStartLoc = VarHeaderStartLoc + topicNameLen + 2; - payloadStartLoc = (packetIdStartLoc + 1); - - if(QOS0 != qos) { - // packet id only for QoS 1 or 2 - RxBuffer.pBuffer[packetIdStartLoc + 1] = 2; - RxBuffer.pBuffer[packetIdStartLoc + 2] = 3; - payloadStartLoc = packetIdStartLoc + 3; - } - - // payload - for(i = 0; i < PayloadLen; i++) { - RxBuffer.pBuffer[payloadStartLoc + i] = (unsigned char) pMsg[i]; - } - - RxBuffer.len = VariableLen + PayloadLen + 2; // 2 for fixed header - RxIndex = 0; - //printBuffer(RxBuffer.pBuffer, RxBuffer.len); -} - -unsigned char isLastTLSTxMessagePuback() { - return (unsigned char) (TxBuffer.pBuffer[0] == 0x40 ? 1 : 0); -} - -unsigned char isLastTLSTxMessagePingreq() { - return (unsigned char) (TxBuffer.pBuffer[0] == 0xC0 ? 1 : 0); -} - -unsigned char isLastTLSTxMessageDisconnect() { - return (unsigned char) (TxBuffer.pBuffer[0] == 0xE0 ? 1 : 0); -} - -unsigned char generateMultipleSubTopics(char *des, int boundary) { - int i; - int currLen = 0; - char *op1 = des; - unsigned char ret = (unsigned char) (des == NULL ? 0 : 1); - while(*op1 != '\0') { - currLen++; - op1++; - } - // Save 1 byte for terminator '\0' - for(i = 0; i < boundary - currLen - 1; i++) { - //printf("%d\n", i); - strcat(des, "a"); - } - return ret; -} - -void encodeRemainingLength(unsigned char *buf, size_t *st, size_t length) { - unsigned char c; - // watch out for the type of length, could be over flow. Limits = 256MB - // No boundary check for 256MB!! - do { - c = (unsigned char) (length % 128); - length /= 128; - if(length > 0) c |= (unsigned char) (0x80); // If there is still another byte following - buf[(*st)++] = c; - } while(length > 0); - // At this point, *st should be the next position for a new part of data in the packet -} - -unsigned char *connectTxBufferHeaderParser(ConnectBufferProofread *params, unsigned char *buf) { - unsigned char *op = buf; - // Get packet type - unsigned char *ele1 = op; - unsigned int multiplier = 1; - int cnt = 0; - unsigned char *ele2; - unsigned int x; - unsigned char *op2; - params->PacketType = *ele1; - op++; - // Get remaining length (length bytes more than 4 bytes are ignored) - params->RemainingLength = 0; - do { - ele2 = op; - params->RemainingLength += ((unsigned int) (*ele2 & (0x7F)) * multiplier); - multiplier *= 128; - cnt++; - op++; - } while((*ele2 & (0x80)) != 0 && cnt < 4); - // At this point, op should be updated to the start address of the next chunk of information - // Get protocol length - params->ProtocolLength = 0; - params->ProtocolLength += (256 * (unsigned int) (*op++)); - params->ProtocolLength += (unsigned int) (*op++); - // Get protocol name - for(x = 0; x < params->ProtocolLength; x++) { - params->ProtocolName[x] = *op; - op++; - } - // Get protocol level - params->ProtocolLevel = (unsigned int) (*op++); - // Get connect flags - params->ConnectFlag = (*op++); - // Get keepalive - op2 = op; - params->KeepAlive = 0; - params->KeepAlive += (256 * (unsigned int) (*op2++)); // get rid of the sign bit - op++; - params->KeepAlive += (unsigned int) (*op2++); - op++; - - return op; -} - -bool isConnectTxBufFlagCorrect(IoT_Client_Connect_Params *settings, ConnectBufferProofread *readRes) { - bool ret = true; - int i; - unsigned char myByte[8]; // Construct our own connect flag byte according to the settings -#if !DISABLE_METRICS - myByte[0] = (unsigned char) (1); // User Name Flag -#else - myByte[0] = (unsigned char) (settings->pUsername == NULL ? 0 : 1); // User Name Flag -#endif - myByte[1] = (unsigned char) (settings->pPassword == NULL ? 0 : 1); // Password Flag - myByte[2] = 0; // Will Retain - // QoS - if(QOS1 == settings->will.qos) { - myByte[3] = 0; - myByte[4] = 1; - } else { // default QoS is QOS0 - myByte[3] = 0; - myByte[4] = 0; - } - // - myByte[5] = (unsigned char) settings->isWillMsgPresent; // Will Flag - myByte[6] = (unsigned char) settings->isCleanSession; // Clean Session - myByte[7] = 0; // Retained - // - for(i = 0; i < 8; i++) { - if(myByte[i] != (unsigned char) (((readRes->ConnectFlag) >> (7 - i)) & 0x01)) { - printf("ex %x ac %x\n", (unsigned char) (((readRes->ConnectFlag) >> (7 - i)) & 0x01) + '0', myByte[i]); - ret = false; - break; - } - } - return ret; -} - -bool isConnectTxBufPayloadCorrect(IoT_Client_Connect_Params *settings, unsigned char *payloadBuf) { - // Construct our own payload according to the settings to see if the real one matches with it - unsigned int ClientIDLen = (unsigned int) strlen(settings->pClientID); - unsigned int WillTopicLen = (unsigned int) strlen(settings->will.pTopicName); - unsigned int WillMsgLen = (unsigned int) strlen(settings->will.pMessage); -#if !DISABLE_METRICS - if (0 == strlen(pUsernameTemp)) { - snprintf(pUsernameTemp, SDK_METRICS_LEN, SDK_METRICS_TEMPLATE, - VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); - } - unsigned int UsernameLen = (unsigned int)strlen(pUsernameTemp); -#else - unsigned int UsernameLen = (unsigned int) settings->usernameLen; -#endif - unsigned int PasswordLen = (unsigned int) settings->passwordLen; - unsigned int myPayloadLen = ClientIDLen + 2 + WillTopicLen + 2 + WillMsgLen + UsernameLen + 2 + PasswordLen; - char *myPayload = (char *) malloc(sizeof(char) * (myPayloadLen + 1)); // reserve 1 byte for '\0' - // Construction starts... - unsigned int i; - bool ret = false; - char *op = myPayload; - *op = (char) (ClientIDLen & 0x0FF00); // MSB There is a writeInt inside paho... MQTTString.lenstring.len != 0 - op++; - *op = (char) (ClientIDLen & 0x00FF); // LSB - op++; - // ClientID - for(i = 0; i < ClientIDLen; i++) { - *op = settings->pClientID[i]; - op++; - } - if(true == settings->isWillMsgPresent) { - // WillTopic - for(i = 0; i < WillTopicLen; i++) { - *op = settings->will.pTopicName[i]; - op++; - } - // WillMsg Len - *op = (char) (WillMsgLen & 0x0FF00); // MSB - op++; - *op = (char) (WillMsgLen & 0x00FF); // LSB - op++; - // WillMsg - for(i = 0; i < WillMsgLen; i++) { - *op = settings->will.pMessage[i]; - op++; - } - } - // Username -#if !DISABLE_METRICS - for(i = 0; i < strlen(pUsernameTemp); i++) - { - *op = pUsernameTemp[i]; - op++; - } -#else - if(NULL != settings->pUsername) { - for(i = 0; i < UsernameLen; i++) { - *op = settings->pUsername[i]; - op++; - } - } -#endif - // PasswordLen + Password - if(NULL != settings->pPassword) { - *op = (char) (PasswordLen & 0x0FF00); // MSB - op++; - *op = (char) (PasswordLen & 0x00FF); // LSB - op++; - // - for(i = 0; i < PasswordLen; i++) { - *op = settings->pPassword[i]; - op++; - } - } - // - *op = '\0'; - ret = strcmp(myPayload, (const char *)payloadBuf) == 0 ? true : false; - free(myPayload); - return ret; -} - -void printPrfrdParams(ConnectBufferProofread *params) { - unsigned int i; - printf("\n----------------\n"); - printf("PacketType: %x\n", params->PacketType); - printf("RemainingLength: %u\n", params->RemainingLength); - printf("ProtocolLength: %u\n", params->ProtocolLength); - printf("ProtocolName: "); - for(i = 0; i < params->ProtocolLength; i++) { - printf("%c", params->ProtocolName[i]); - } - printf("\n"); - printf("ProtocolLevel: %u\n", params->ProtocolLevel); - printf("ConnectFlag: %x\n", params->ConnectFlag); - printf("KeepAliveInterval: %u\n", params->KeepAlive); - printf("----------------\n"); -} - -const char *getJobTopicTypeName(AwsIotJobExecutionTopicType topicType) { - switch (topicType) { - case JOB_UPDATE_TOPIC: return "JOB_UPDATE_TOPIC"; - case JOB_NOTIFY_TOPIC: return "JOB_NOTIFY_TOPIC"; - case JOB_NOTIFY_NEXT_TOPIC: return "JOB_NOTIFY_NEXT_TOPIC"; - case JOB_GET_PENDING_TOPIC: return "JOB_GET_PENDING_TOPIC"; - case JOB_DESCRIBE_TOPIC: return "JOB_DESCRIBE_TOPIC"; - case JOB_START_NEXT_TOPIC: return "JOB_START_NEXT_TOPIC"; - case JOB_WILDCARD_TOPIC: return "JOB_WILDCARD_TOPIC"; - case JOB_UNRECOGNIZED_TOPIC: return "JOB_UNRECOGNIZED_TOPIC"; - default: return "invalid"; - } -} - -const char *getJobReplyTypeName(AwsIotJobExecutionTopicReplyType replyType) { - switch (replyType) { - case JOB_REQUEST_TYPE: return "JOB_REQUEST_TYPE"; - case JOB_ACCEPTED_REPLY_TYPE: return "JOB_ACCEPTED_REPLY_TYPE"; - case JOB_REJECTED_REPLY_TYPE: return "JOB_REJECTED_REPLY_TYPE"; - case JOB_WILDCARD_REPLY_TYPE: return "JOB_WILDCARD_REPLY_TYPE"; - case JOB_UNRECOGNIZED_TOPIC_TYPE: return "JOB_UNRECOGNIZED_TOPIC_TYPE"; - default: return "invalid"; - } -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs.cpp deleted file mode 100644 index edbf8cee4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#include -#include - - -TEST_GROUP_C(JobsTypesTests) { - TEST_GROUP_C_SETUP_WRAPPER(JobsTypesTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(JobsTypesTests) -}; - -TEST_GROUP_C_WRAPPER(JobsTypesTests, StringToStatus) -TEST_GROUP_C_WRAPPER(JobsTypesTests, StatusToString) - -TEST_GROUP_C(JobsJsonTests) { - TEST_GROUP_C_SETUP_WRAPPER(JobsJsonTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(JobsJsonTests) -}; - -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeUpdateRequest) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeUpdateRequestWithNullBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeUpdateRequestWithTooSmallBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeDescribeJobExecutionRequest) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeDescribeJobExecutionRequestWithNullBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeDescribeJobExecutionRequestWithTooSmallBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeStartNextRequest) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeStartNextRequestWithNullBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeStartNextRequestWithTooSmallBuffer) - -TEST_GROUP_C(JobsTopicsTests) { - TEST_GROUP_C_SETUP_WRAPPER(JobsTopicsTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(JobsTopicsTests) -}; - -TEST_GROUP_C_WRAPPER(JobsTopicsTests, GenerateValidTopics) -TEST_GROUP_C_WRAPPER(JobsTopicsTests, GenerateWithMissingJobId) -TEST_GROUP_C_WRAPPER(JobsTopicsTests, GenerateWithInvalidTopicOrReplyType) -TEST_GROUP_C_WRAPPER(JobsTopicsTests, GenerateWithInvalidCombinations) - -TEST_GROUP_C(JobsInterfaceTest) { - TEST_GROUP_C_SETUP_WRAPPER(JobsInterfaceTest) - TEST_GROUP_C_TEARDOWN_WRAPPER(JobsInterfaceTest) -}; - -TEST_GROUP_C_WRAPPER(JobsInterfaceTest, TestSubscribeAndUnsubscribe) -TEST_GROUP_C_WRAPPER(JobsInterfaceTest, TestSendQuery) -TEST_GROUP_C_WRAPPER(JobsInterfaceTest, TestSendUpdate) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_interface.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_interface.c deleted file mode 100644 index c19a38d88..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_interface.c +++ /dev/null @@ -1,337 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#include - -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_config.h" -#include -#include -#include - -static AWS_IoT_Client client; -static IoT_Client_Connect_Params connectParams; -static IoT_Client_Init_Params mqttInitParams; - -static const char *THING_NAME = "T1"; -static const char *JOB_ID = "J1"; - -static int CALLBACK_DATA = 5; - -static const char *expectedTopic; -static const void *expectedData; -static size_t expectedDataLen; - -static int callbackCount = 0; - -static bool expectError; -static bool expectedJsonContext; - - -static void testCallback( - AWS_IoT_Client *pClient, - char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) -{ - callbackCount++; - - CHECK_C(pData == &CALLBACK_DATA); - CHECK_C(pClient == &client); - - CHECK_EQUAL_C_INT((int)strlen(expectedTopic), (int)topicNameLen); - CHECK_C(strncmp(expectedTopic, topicName, (size_t) topicNameLen) == 0); - - CHECK_C(memcmp(expectedData, params->payload, expectedDataLen) == 0); -} - -TEST_GROUP_C_SETUP(JobsInterfaceTest) { - IoT_Error_t ret_val = SUCCESS; - - InitMQTTParamsSetup(&mqttInitParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - ret_val = aws_iot_mqtt_init(&client, &mqttInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ConnectMQTTParamsSetup(&connectParams, (char *) AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_mqtt_connect(&client, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - - /* Ensure that old data can't be used */ - lastSubscribeMsgLen = 0; - lastUnsubscribeMsgLen = 0; - lastPublishMessageTopicLen = 0; - lastPublishMessagePayloadLen = 0; - - callbackCount = 0; - expectedTopic = NULL; - expectedData = NULL; - expectedDataLen = 0; - - expectError = false; - expectedJsonContext = false; -} - -TEST_GROUP_C_TEARDOWN(JobsInterfaceTest) { - IoT_Error_t rc = aws_iot_mqtt_disconnect(&client); - IOT_UNUSED(rc); -} - -static void publishTestMessage(AwsIotJobExecutionTopicType topicType, bool withJobId) { - char replyTopic[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - AwsIotJobExecutionTopicReplyType replyType; - char * message; - - if (topicType == JOB_NOTIFY_TOPIC) { - replyType = JOB_REQUEST_TYPE; - message = "{\"jobs\":{\"IN_PROGRESS\":[{}]},\"timestamp\":5}"; - } else if (topicType == JOB_NOTIFY_NEXT_TOPIC) { - replyType = JOB_REQUEST_TYPE; - message = "{\"execution\":{\"jobId\":\"J1\",\"status\":\"IN_PROGRESS\",\"queuedAt\":50,\"versionNumber\":20},\"timestamp\":5}"; - } - else { - replyType = JOB_REJECTED_REPLY_TYPE; - message = "{\"code\":\"foo\",\"message\":\"bar\", \"clientToken\":\"baz\",\"timestamp\":6}"; - } - - const char *passedJobId = NULL; - if (withJobId) { - if (topicType == JOB_WILDCARD_TOPIC) { - topicType = JOB_DESCRIBE_TOPIC; - } - passedJobId = JOB_ID; - } - - int replyTopicLen = aws_iot_jobs_get_api_topic( - replyTopic, MAX_JOB_TOPIC_LENGTH_BYTES + 1, - topicType, replyType, THING_NAME, passedJobId); - - expectedData = message; - expectedDataLen = strlen(message) + 1; - expectedTopic = replyTopic; - - IoT_Publish_Message_Params params; - params.payload = message; - params.payloadLen = strlen(message); - params.qos = QOS0; - - int preSendCount = callbackCount; - - setTLSRxBufferWithMsgOnSubscribedTopic(replyTopic, (size_t)replyTopicLen, QOS0, params, message); - IoT_Error_t error = aws_iot_mqtt_yield(&client, 100); - - CHECK_EQUAL_C_INT(SUCCESS, error); - CHECK_EQUAL_C_INT(preSendCount + 1, callbackCount); -} - -static void testSubscribeAndUnsubscribe(AwsIotJobExecutionTopicType topicType, bool withJobId) { - char expectedTopic[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char topicBuffer[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - - IOT_DEBUG("\n-->Running Jobs Interface Tests - test subscribe/unsubscribe %s %s \n", getJobTopicTypeName(topicType), (withJobId ? "(w/ job id)" : "")); - - AwsIotJobExecutionTopicReplyType replyType; - if (topicType != JOB_NOTIFY_TOPIC && topicType != JOB_NOTIFY_NEXT_TOPIC) { - replyType = JOB_WILDCARD_REPLY_TYPE; - } else { - replyType = JOB_REQUEST_TYPE; - } - - const char *passedJobId = NULL; - if (withJobId) passedJobId = JOB_ID; - - int expectedTopicLength = aws_iot_jobs_get_api_topic( - expectedTopic, MAX_JOB_TOPIC_LENGTH_BYTES + 1, - topicType, replyType, - THING_NAME, passedJobId); - - CHECK_C(expectedTopicLength > 0 && expectedTopicLength < MAX_JOB_TOPIC_LENGTH_BYTES); - - /* Clear to make sure old data doesn't cause the test to pass when we shouldn't */ - lastSubscribeMsgLen = 0; - lastPublishMessageTopicLen = 0; - - IoT_Publish_Message_Params unused; - - setTLSRxBufferForSuback(expectedTopic, (size_t)expectedTopicLength, QOS0, unused); - - IoT_Error_t iotError; - if (topicType == JOB_WILDCARD_TOPIC && !withJobId) { - iotError = aws_iot_jobs_subscribe_to_all_job_messages( - &client, QOS0, THING_NAME, testCallback, &CALLBACK_DATA, topicBuffer, sizeof(topicBuffer)); - } else { - iotError = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, THING_NAME, passedJobId, topicType, replyType, testCallback, &CALLBACK_DATA, topicBuffer, sizeof(topicBuffer)); - } - - CHECK_EQUAL_C_INT(SUCCESS, iotError); - - CHECK_EQUAL_C_INT(expectedTopicLength, (int)strlen(topicBuffer)); - CHECK_EQUAL_C_INT(expectedTopicLength, (int)lastSubscribeMsgLen); - CHECK_EQUAL_C_STRING(expectedTopic, topicBuffer); - CHECK_EQUAL_C_STRING(expectedTopic, LastSubscribeMessage); - - publishTestMessage(topicType, withJobId); - - LastUnsubscribeMessage[0] = 0; - lastUnsubscribeMsgLen = 0; - - setTLSRxBufferForUnsuback(); - iotError = aws_iot_jobs_unsubscribe_from_job_messages(&client, topicBuffer); - - CHECK_EQUAL_C_INT(SUCCESS, iotError); - - CHECK_EQUAL_C_STRING(expectedTopic, LastUnsubscribeMessage); - - IOT_DEBUG("-->Success - test subscribe/unsubscribe %s %s \n", getJobTopicTypeName(topicType), (withJobId ? "(w/ job id)" : "")); -} - -TEST_C(JobsInterfaceTest, TestSubscribeAndUnsubscribe) { - testSubscribeAndUnsubscribe(JOB_NOTIFY_TOPIC, false); - testSubscribeAndUnsubscribe(JOB_NOTIFY_NEXT_TOPIC, false); - testSubscribeAndUnsubscribe(JOB_DESCRIBE_TOPIC, true); - testSubscribeAndUnsubscribe(JOB_GET_PENDING_TOPIC, false); - testSubscribeAndUnsubscribe(JOB_UPDATE_TOPIC, true); - testSubscribeAndUnsubscribe(JOB_WILDCARD_TOPIC, true); - testSubscribeAndUnsubscribe(JOB_WILDCARD_TOPIC, false); - testSubscribeAndUnsubscribe(JOB_START_NEXT_TOPIC, false); -} - -static void testSendQuery(bool withJobId, bool withClientToken, AwsIotJobExecutionTopicType topicType) { - char expectedTopic[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char topicBuffer[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char messageBuffer[MAX_SIZE_OF_JOB_REQUEST + 1]; - - IOT_DEBUG("\n-->Running Jobs Interface Tests - test send query %s %s \n", getJobTopicTypeName(topicType), (withClientToken ? "(w/ clientToken)" : "")); - - char *clientToken = NULL; - char *bufferToPass = NULL; - size_t bufferLenToPass = 0; - if (withClientToken) { - clientToken = "FooBar"; - bufferToPass = messageBuffer; - bufferLenToPass = MAX_SIZE_OF_JOB_REQUEST + 1; - } - - const char *passedJobId = NULL; - if (withJobId) passedJobId = JOB_ID; - - int expectedTopicLength = aws_iot_jobs_get_api_topic( - expectedTopic, MAX_JOB_TOPIC_LENGTH_BYTES + 1, - topicType, JOB_REQUEST_TYPE, - THING_NAME, passedJobId); - - CHECK_C(expectedTopicLength > 0 && expectedTopicLength <= MAX_JOB_TOPIC_LENGTH_BYTES); - - LastPublishMessageTopic[0] = 0; - lastPublishMessageTopicLen = 0; - LastPublishMessagePayload[0] = 0; - lastPublishMessagePayloadLen = 0; - - setTLSRxBufferForPuback(); - IoT_Error_t iotError; - - if (topicType == JOB_DESCRIBE_TOPIC) { - AwsIotDescribeJobExecutionRequest request; - request.executionNumber = 0; - request.includeJobDocument = false; - request.clientToken = clientToken; - - iotError = aws_iot_jobs_describe( - &client, QOS0, THING_NAME, passedJobId, &request, topicBuffer, sizeof(topicBuffer), bufferToPass, bufferLenToPass); - } else if (topicType == JOB_START_NEXT_TOPIC) { - AwsIotStartNextPendingJobExecutionRequest request; - request.statusDetails = NULL; - request.clientToken = clientToken; - - iotError = aws_iot_jobs_start_next( - &client, QOS0, THING_NAME, &request, topicBuffer, sizeof(topicBuffer), messageBuffer, sizeof(messageBuffer)); - } else { - iotError = aws_iot_jobs_send_query( - &client, QOS0, THING_NAME, passedJobId, clientToken, topicBuffer, sizeof(topicBuffer), bufferToPass, bufferLenToPass, topicType); - } - - CHECK_EQUAL_C_INT(SUCCESS, iotError); - CHECK_EQUAL_C_INT(expectedTopicLength, (int)lastPublishMessageTopicLen); - CHECK_EQUAL_C_STRING(expectedTopic, LastPublishMessageTopic); - - if (withClientToken) { - CHECK_EQUAL_C_INT((int)strlen(LastPublishMessagePayload), (int)lastPublishMessagePayloadLen); - CHECK_EQUAL_C_STRING("{\"clientToken\":\"FooBar\"}", LastPublishMessagePayload); - } else if (topicType == JOB_START_NEXT_TOPIC) { - CHECK_EQUAL_C_INT(2, (int)lastPublishMessagePayloadLen); - CHECK_EQUAL_C_STRING("{}", LastPublishMessagePayload); - } else { - CHECK_EQUAL_C_INT(0, (int)lastPublishMessagePayloadLen); - } - - IOT_DEBUG("-->Success - test send query %s %s \n", getJobTopicTypeName(topicType), (withClientToken ? "(w/ clientToken)" : "")); -} - -TEST_C(JobsInterfaceTest, TestSendQuery) { - int token; - for (token = 0; token < 2; ++token) { - testSendQuery(false, token == 0, JOB_GET_PENDING_TOPIC); - testSendQuery(true, token == 0, JOB_DESCRIBE_TOPIC); - testSendQuery(false, token == 0, JOB_START_NEXT_TOPIC); - } -} - -TEST_C(JobsInterfaceTest, TestSendUpdate) { - AwsIotJobExecutionUpdateRequest updateRequest; - updateRequest.clientToken = "FooBar"; - updateRequest.status = JOB_EXECUTION_SUCCEEDED; - updateRequest.expectedVersion = 1; - updateRequest.executionNumber = 0; - updateRequest.statusDetails = NULL; - updateRequest.includeJobExecutionState = false; - updateRequest.includeJobDocument = false; - - char expectedTopic[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char topicBuffer[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char messageBuffer[AWS_IOT_MQTT_TX_BUF_LEN + 1]; - - IOT_DEBUG("\n-->Running Jobs Interface Tests - test send update \n"); - - int expectedTopicLength = aws_iot_jobs_get_api_topic( - expectedTopic, MAX_JOB_TOPIC_LENGTH_BYTES + 1, - JOB_UPDATE_TOPIC, JOB_REQUEST_TYPE, - THING_NAME, JOB_ID); - - CHECK_C(expectedTopicLength > 0 && expectedTopicLength <= MAX_JOB_TOPIC_LENGTH_BYTES); - - LastPublishMessageTopic[0] = 0; - lastPublishMessageTopicLen = 0; - LastPublishMessagePayload[0] = 0; - lastPublishMessagePayloadLen = 0; - - setTLSRxBufferForPuback(); - IoT_Error_t iotError; - iotError = aws_iot_jobs_send_update( - &client, QOS0, THING_NAME, JOB_ID, &updateRequest, - topicBuffer, sizeof(topicBuffer), - messageBuffer, sizeof(messageBuffer)); - - CHECK_EQUAL_C_INT(SUCCESS, iotError); - - CHECK_EQUAL_C_INT(expectedTopicLength, (int)lastPublishMessageTopicLen); - CHECK_EQUAL_C_STRING(expectedTopic, LastPublishMessageTopic); - - CHECK_EQUAL_C_STRING("{\"status\":\"SUCCEEDED\",\"expectedVersion\":1,\"clientToken\":\"FooBar\"}", LastPublishMessagePayload); - - IOT_DEBUG("-->Success - test send update \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_json.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_json.c deleted file mode 100644 index 5a04554e1..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_json.c +++ /dev/null @@ -1,244 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define NUM_TOKENS 50 - -static jsmntok_t tokens[NUM_TOKENS]; - -TEST_GROUP_C_SETUP(JobsJsonTests) { -} - -TEST_GROUP_C_TEARDOWN(JobsJsonTests) { -} - -static const char *defaultUpdateRequestSerialized = - "{\"status\":\"IN_PROGRESS\",\"statusDetails\":{\"Step\":\"1\",\"StepStatus\":\"Foo\"}," - "\"executionNumber\":2,\"expectedVersion\":1,\"includeJobExecutionState\":true,\"includeJobDocument\":true,\"clientToken\":\"1234\"}"; - -static void fillDefaultUpdateRequest(AwsIotJobExecutionUpdateRequest *request) -{ - request->status = JOB_EXECUTION_IN_PROGRESS; - request->statusDetails = "{\"Step\":\"1\",\"StepStatus\":\"Foo\"}"; - request->expectedVersion = 1; - request->executionNumber = 2; - request->includeJobExecutionState = true; - request->includeJobDocument = true; - request->clientToken = "1234"; -} - -TEST_C(JobsJsonTests, SerializeUpdateRequest) { - AwsIotJobExecutionUpdateRequest updateRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize update request \n"); - - fillDefaultUpdateRequest(&updateRequest); - - char buffer[256]; - int charsUsed = aws_iot_jobs_json_serialize_update_job_execution_request(buffer, sizeof(buffer), &updateRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultUpdateRequestSerialized), charsUsed); - CHECK_EQUAL_C_STRING(defaultUpdateRequestSerialized, buffer); - - jsmn_parser parser; - jsmn_init(&parser); - - int num_parsed_tokens = jsmn_parse(&parser, buffer, (size_t)charsUsed, tokens, NUM_TOKENS); - CHECK_C(num_parsed_tokens > 0); - - IOT_DEBUG("-->Success - serialize update request \n"); -} - -TEST_C(JobsJsonTests, SerializeUpdateRequestWithNullBuffer) { - AwsIotJobExecutionUpdateRequest updateRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize update request w/ null buffer \n"); - - fillDefaultUpdateRequest(&updateRequest); - - int charsUsed = aws_iot_jobs_json_serialize_update_job_execution_request(NULL, 0, &updateRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultUpdateRequestSerialized), charsUsed); - - IOT_DEBUG("-->Success - serialize update request w/ null buffer \n"); -} - -TEST_C(JobsJsonTests, SerializeUpdateRequestWithTooSmallBuffer) { - AwsIotJobExecutionUpdateRequest updateRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize update request w/ too small buffer \n"); - - fillDefaultUpdateRequest(&updateRequest); - - char buffer[11]; - // A check character which shouldn't be overwritten as we pass a length of 10 - buffer[10] = -1; - - int charsUsed = aws_iot_jobs_json_serialize_update_job_execution_request(buffer, 10, &updateRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultUpdateRequestSerialized), charsUsed); - - CHECK_EQUAL_C_CHAR(-1, buffer[10]); - CHECK_EQUAL_C_CHAR(0, buffer[9]); - // 9 because the 10th is \0 - CHECK_C(strncmp(defaultUpdateRequestSerialized, buffer, 9) == 0); - - IOT_DEBUG("-->Success - serialize update request w/ too small buffer \n"); -} - -static void fillDefaultDescribeJobExecutionRequest( - AwsIotDescribeJobExecutionRequest *request) -{ - request->executionNumber = 1; - request->includeJobDocument = true; - request->clientToken = "1234"; -} - -static const char *defaultDescribeJobExecutionRequestSerialized = - "{\"clientToken\":\"1234\",\"executionNumber\":1,\"includeJobDocument\":true}"; - -TEST_C(JobsJsonTests, SerializeDescribeJobExecutionRequest) { - AwsIotDescribeJobExecutionRequest describeJobExecutionRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize describe job execution request \n"); - - fillDefaultDescribeJobExecutionRequest(&describeJobExecutionRequest); - - char buffer[256]; - int charsUsed = aws_iot_jobs_json_serialize_describe_job_execution_request(buffer, 256, &describeJobExecutionRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultDescribeJobExecutionRequestSerialized), charsUsed); - - CHECK_EQUAL_C_STRING(defaultDescribeJobExecutionRequestSerialized, buffer); - - jsmn_parser parser; - jsmn_init(&parser); - - int num_parsed_tokens = jsmn_parse(&parser, buffer, (size_t)charsUsed, tokens, NUM_TOKENS); - CHECK_C(num_parsed_tokens > 0); - - IOT_DEBUG("-->Success - serialize describe job execution request \n"); -} - -TEST_C(JobsJsonTests, SerializeDescribeJobExecutionRequestWithNullBuffer) { - AwsIotDescribeJobExecutionRequest describeJobExecutionRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize describe job execution request w/ null buffer \n"); - - fillDefaultDescribeJobExecutionRequest(&describeJobExecutionRequest); - - int charsUsed = aws_iot_jobs_json_serialize_describe_job_execution_request(NULL, 0, &describeJobExecutionRequest); - CHECK_EQUAL_C_INT(0, charsUsed); - - IOT_DEBUG("-->Success - serialize describe job execution request w/ null buffer \n"); -} - -TEST_C(JobsJsonTests, SerializeDescribeJobExecutionRequestWithTooSmallBuffer) { - AwsIotDescribeJobExecutionRequest describeJobExecutionRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize describe job execution request w/ too small buffer \n"); - - fillDefaultDescribeJobExecutionRequest(&describeJobExecutionRequest); - - char buffer[11]; - // A check character which shouldn't be overwritten as we pass a length of 10 - buffer[10] = -1; - - int charsUsed = aws_iot_jobs_json_serialize_describe_job_execution_request(buffer, 10, &describeJobExecutionRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultDescribeJobExecutionRequestSerialized), charsUsed); - - CHECK_EQUAL_C_CHAR(-1, buffer[10]); - CHECK_EQUAL_C_CHAR(0, buffer[9]); - // 9 because the 10th is \0 - CHECK_C(strncmp(defaultDescribeJobExecutionRequestSerialized, buffer, 9) == 0); - - IOT_DEBUG("-->Success - serialize describe job execution request w/ too small buffer \n"); -} - -static void fillDefaultStartNextRequest(AwsIotStartNextPendingJobExecutionRequest *request) -{ - request->statusDetails = "{\"Step\":\"1\",\"StepStatus\":\"Foo\"}"; - request->clientToken = "1234"; -} - -static const char *defaultStartNextRequestSerialized = - "{\"statusDetails\":{\"Step\":\"1\",\"StepStatus\":\"Foo\"},\"clientToken\":\"1234\"}"; - -TEST_C(JobsJsonTests, SerializeStartNextRequest) { - AwsIotStartNextPendingJobExecutionRequest startNextRequest; - fillDefaultStartNextRequest(&startNextRequest); - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize start next request \n"); - - char buffer[256]; - int charsUsed = aws_iot_jobs_json_serialize_start_next_job_execution_request(buffer, 256, &startNextRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultStartNextRequestSerialized), charsUsed); - - CHECK_EQUAL_C_STRING(defaultStartNextRequestSerialized, buffer); - jsmn_parser parser; - jsmn_init(&parser); - - int num_parsed_tokens = jsmn_parse(&parser, buffer, (size_t)charsUsed, tokens, NUM_TOKENS); - CHECK_C(num_parsed_tokens > 0); - - IOT_DEBUG("-->Success - serialize start next request \n"); -} - -TEST_C(JobsJsonTests, SerializeStartNextRequestWithNullBuffer) { - AwsIotStartNextPendingJobExecutionRequest startNextRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize start next request w/ null buffer \n"); - - fillDefaultStartNextRequest(&startNextRequest); - - int charsUsed = aws_iot_jobs_json_serialize_start_next_job_execution_request(NULL, 0, &startNextRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultStartNextRequestSerialized), charsUsed); - - IOT_DEBUG("-->Success - serialize start next request w/ null buffer \n"); -} - -TEST_C(JobsJsonTests, SerializeStartNextRequestWithTooSmallBuffer) { - AwsIotStartNextPendingJobExecutionRequest startNextRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize start next request w/ too small buffer \n"); - - fillDefaultStartNextRequest(&startNextRequest); - - char buffer[11]; - // A check character which shouldn't be overwritten as we pass a length of 10 - buffer[10] = -1; - - int charsUsed = aws_iot_jobs_json_serialize_start_next_job_execution_request(buffer, 10, &startNextRequest); - CHECK_EQUAL_C_INT((int) strlen(defaultStartNextRequestSerialized), charsUsed); - - CHECK_EQUAL_C_CHAR(-1, buffer[10]); - CHECK_EQUAL_C_CHAR(0, buffer[9]); - // 9 because the 10th is \0 - CHECK_C(strncmp(defaultStartNextRequestSerialized, buffer, 9) == 0); - - IOT_DEBUG("-->Success - serialize start next request w/ too small buffer \n"); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_topics.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_topics.c deleted file mode 100644 index b6c6ace08..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_topics.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#include "aws_iot_jobs_topics.h" -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -TEST_GROUP_C_SETUP(JobsTopicsTests) { -} - -TEST_GROUP_C_TEARDOWN(JobsTopicsTests) { -} - -#define TEST_THING_NAME "TestThing" -#define TEST_TOPIC_PREFIX "$aws/things/" TEST_THING_NAME "/jobs" -#define TEST_JOB_ID "TestJob" -#define TEST_NEXT_JOB_ID "$next" -#define TEST_TOPIC_W_JOB_PREFIX TEST_TOPIC_PREFIX "/" TEST_JOB_ID - -static int generateTopicForTestThingAndJob( - char *buffer, size_t bufferSize, - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType) -{ - return aws_iot_jobs_get_api_topic( - buffer, bufferSize, topicType, replyType, TEST_THING_NAME, TEST_JOB_ID); -} - -static int generateTopicForTestThing( - char *buffer, size_t bufferSize, - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType) -{ - return aws_iot_jobs_get_api_topic( - buffer, bufferSize, topicType, replyType, TEST_THING_NAME, NULL); -} - -static void testGenerateValidApiTopic( - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType, - bool includeThingName, const char *expectedOutput) -{ - int requestedSize; - int expectedSize = (int)strlen(expectedOutput); - - IOT_DEBUG("\n-->Running Jobs Topics Tests - generate valid topics %s w/ reply type \n", getJobTopicTypeName(topicType), getJobReplyTypeName(replyType)); - - if (includeThingName) { - requestedSize = generateTopicForTestThingAndJob(NULL, 0, topicType, replyType); - CHECK_EQUAL_C_INT(expectedSize, requestedSize); - } else { - requestedSize = generateTopicForTestThing(NULL, 0, topicType, replyType); - CHECK_EQUAL_C_INT(expectedSize, requestedSize); - } - - CHECK_C(requestedSize > 3); - char *buffer = (char *) malloc((size_t)(requestedSize + 1) * sizeof(char)); - buffer[3] = -1; - - if (includeThingName) { - requestedSize = generateTopicForTestThingAndJob(buffer, 3, topicType, replyType); - } else { - requestedSize = generateTopicForTestThing(buffer, 3, topicType, replyType); - } - CHECK_EQUAL_C_INT(expectedSize, requestedSize); - - CHECK_EQUAL_C_CHAR(expectedOutput[0], buffer[0]); - CHECK_EQUAL_C_CHAR(expectedOutput[1], buffer[1]); - CHECK_EQUAL_C_CHAR('\0', buffer[2]); - CHECK_EQUAL_C_CHAR(-1, buffer[3]); - - if (includeThingName) { - requestedSize = generateTopicForTestThingAndJob(buffer, (size_t)requestedSize + 1, topicType, replyType); - } else { - requestedSize = generateTopicForTestThing(buffer, (size_t)requestedSize + 1, topicType, replyType); - } - - CHECK_EQUAL_C_INT(expectedSize, requestedSize); - CHECK_EQUAL_C_STRING(expectedOutput, buffer); - - free(buffer); - - IOT_DEBUG("-->Success - generate valid topics %s w/ reply type \n", getJobTopicTypeName(topicType), getJobReplyTypeName(replyType)); -} - -static void testGenerateValidApiTopicWithAllReplyTypes( - AwsIotJobExecutionTopicType topicType, bool includeThingName, - const char *expectedBaseTopic) -{ - char buffer[1024]; - - testGenerateValidApiTopic( - topicType, JOB_REQUEST_TYPE, includeThingName, expectedBaseTopic); - - snprintf(buffer, 1024, "%s/accepted", expectedBaseTopic); - testGenerateValidApiTopic( - topicType, JOB_ACCEPTED_REPLY_TYPE, includeThingName, buffer); - - snprintf(buffer, 1024, "%s/rejected", expectedBaseTopic); - testGenerateValidApiTopic( - topicType, JOB_REJECTED_REPLY_TYPE, includeThingName, buffer); - - snprintf(buffer, 1024, "%s/+", expectedBaseTopic); - testGenerateValidApiTopic( - topicType, JOB_WILDCARD_REPLY_TYPE, includeThingName, buffer); - -} - -TEST_C(JobsTopicsTests, GenerateValidTopics) { - testGenerateValidApiTopicWithAllReplyTypes(JOB_UPDATE_TOPIC, true, TEST_TOPIC_W_JOB_PREFIX "/update"); - testGenerateValidApiTopicWithAllReplyTypes(JOB_DESCRIBE_TOPIC, true, TEST_TOPIC_W_JOB_PREFIX "/get"); - testGenerateValidApiTopicWithAllReplyTypes(JOB_WILDCARD_TOPIC, true, TEST_TOPIC_W_JOB_PREFIX "/+"); - testGenerateValidApiTopic(JOB_WILDCARD_TOPIC, JOB_REQUEST_TYPE, false, TEST_TOPIC_PREFIX "/#"); - testGenerateValidApiTopic(JOB_NOTIFY_TOPIC, JOB_REQUEST_TYPE, false, TEST_TOPIC_PREFIX "/notify"); - testGenerateValidApiTopic(JOB_NOTIFY_NEXT_TOPIC, JOB_REQUEST_TYPE, false, TEST_TOPIC_PREFIX "/notify-next"); - testGenerateValidApiTopic(JOB_START_NEXT_TOPIC, JOB_REQUEST_TYPE, false, TEST_TOPIC_PREFIX "/start-next"); -} - -TEST_C(JobsTopicsTests, GenerateWithMissingJobId) { - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_UPDATE_TOPIC, JOB_REQUEST_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_DESCRIBE_TOPIC, JOB_REQUEST_TYPE)); -} - -TEST_C(JobsTopicsTests, GenerateWithInvalidTopicOrReplyType) { - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_UNRECOGNIZED_TOPIC, JOB_REQUEST_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, -1, JOB_REQUEST_TYPE)); - - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_DESCRIBE_TOPIC, JOB_UNRECOGNIZED_TOPIC_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_DESCRIBE_TOPIC, -1)); -} - -TEST_C(JobsTopicsTests, GenerateWithInvalidCombinations) { - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_TOPIC, JOB_ACCEPTED_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_TOPIC, JOB_REJECTED_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_TOPIC, JOB_WILDCARD_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_NEXT_TOPIC, JOB_ACCEPTED_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_NEXT_TOPIC, JOB_REJECTED_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_NEXT_TOPIC, JOB_WILDCARD_REPLY_TYPE)); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_types.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_types.c deleted file mode 100644 index 60dc8c9d3..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_types.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -TEST_GROUP_C_SETUP(JobsTypesTests) { -} - -TEST_GROUP_C_TEARDOWN(JobsTypesTests) { -} - -TEST_C(JobsTypesTests, StringToStatus) { - char emptyString = '\0'; - - IOT_DEBUG("\n-->Running Jobs Types Tests - string to status \n"); - - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_STATUS_NOT_SET, (int)aws_iot_jobs_map_string_to_job_status(NULL)); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_STATUS_NOT_SET, (int)aws_iot_jobs_map_string_to_job_status(&emptyString)); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_QUEUED, (int)aws_iot_jobs_map_string_to_job_status("QUEUED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_IN_PROGRESS, (int)aws_iot_jobs_map_string_to_job_status("IN_PROGRESS")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_FAILED, (int)aws_iot_jobs_map_string_to_job_status("FAILED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_SUCCEEDED, (int)aws_iot_jobs_map_string_to_job_status("SUCCEEDED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_CANCELED, (int)aws_iot_jobs_map_string_to_job_status("CANCELED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_REJECTED, (int)aws_iot_jobs_map_string_to_job_status("REJECTED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_UNKNOWN_STATUS, (int)aws_iot_jobs_map_string_to_job_status("invalidStatus")); - - IOT_DEBUG("-->Success - string to status \n"); -} - -TEST_C(JobsTypesTests, StatusToString) { - IOT_DEBUG("\n-->Running Jobs Types Tests - status to string \n"); - - CHECK_EQUAL_C_STRING("QUEUED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_QUEUED)); - CHECK_EQUAL_C_STRING("IN_PROGRESS", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_IN_PROGRESS)); - CHECK_EQUAL_C_STRING("FAILED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_FAILED)); - CHECK_EQUAL_C_STRING("SUCCEEDED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_SUCCEEDED)); - CHECK_EQUAL_C_STRING("CANCELED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_CANCELED)); - CHECK_EQUAL_C_STRING("REJECTED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_REJECTED)); - CHECK_EQUAL_C_STRING(NULL, aws_iot_jobs_map_status_to_string(JOB_EXECUTION_STATUS_NOT_SET)); - CHECK_EQUAL_C_STRING(NULL, aws_iot_jobs_map_status_to_string(JOB_EXECUTION_UNKNOWN_STATUS)); - - IOT_DEBUG("-->Success - status to string \n"); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp deleted file mode 100644 index f1fe2e33b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_json_utils.cpp - * @brief IoT Client Unit Testing - JSON Utility Tests - */ - -#include -#include - -TEST_GROUP_C(JsonUtils) { - TEST_GROUP_C_SETUP_WRAPPER(JsonUtils) - TEST_GROUP_C_TEARDOWN_WRAPPER(JsonUtils) -}; - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringLongerStringIsValid) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringWithBufferTooSmall) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringEmptyStringIsValid) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringErrorOnInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringErrorOnBoolean) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanTrue) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanFalse) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanErrorOnString) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanErrorOnInvalidJson) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleNumberWithNoDecimal) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleSmallDouble) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnString) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnJsonObject) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleNegativeNumber) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatNumberWithNoDecimal) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatSmallFloat) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnString) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnJsonObject) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatNegativeNumber) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnString) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c deleted file mode 100644 index 864d379d7..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c +++ /dev/null @@ -1,834 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_json_utils_helper.c - * @brief IoT Client Unit Testing - JSON Utility Tests helper - */ - -#include -#include -#include -#include - -#include "aws_iot_json_utils.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -#define STRING_BUFFER_LENGTH (50) - -static IoT_Error_t rc = SUCCESS; - -static jsmn_parser test_parser; -static jsmntok_t t[128]; - -TEST_GROUP_C_SETUP(JsonUtils) { - jsmn_init(&test_parser); -} - -TEST_GROUP_C_TEARDOWN(JsonUtils) { - -} - -TEST_C(JsonUtils, ParseStringBasic) { - int r; - const char *json = "{\"x\":\"test1\"}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - Basic String Parsing \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("test1", parsedString); -} - -TEST_C(JsonUtils, ParseStringLongerStringIsValid) { - int r; - const char *json = "{\"x\":\"this is a longer string for test 2\"}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse long string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("this is a longer string for test 2", parsedString); -} - -/* Test that parsing a string doesn't overflow the given buffer. */ -TEST_C(JsonUtils, ParseStringWithBufferTooSmall) { - static const char* const pJsonString = "{\"key\":\"This value is longer than JSON_BUFFER_LENGTH, which should be 50.\"}"; - char parsedString[STRING_BUFFER_LENGTH] = {0}; - int jsmnReturn, i; - - IOT_DEBUG("\n-->Running Json Utils Tests - String parsing with buffer too small. \n"); - - jsmnReturn = jsmn_parse(&test_parser, pJsonString, strlen(pJsonString), t, sizeof(t)/sizeof(t[0])); - CHECK_EQUAL_C_INT(3, jsmnReturn); - - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, pJsonString, t + 2); - - CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, rc); - - /* Ensure there was no attempt to write to a buffer that's too small. */ - for(i = 0; i < STRING_BUFFER_LENGTH; i++) - { - CHECK_EQUAL_C_CHAR(0, parsedString[i]); - } -} - -TEST_C(JsonUtils, ParseStringEmptyStringIsValid) { int r; - const char *json = "{\"x\":\"\"}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse empty string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("", parsedString); -} - -TEST_C(JsonUtils, ParseStringErrorOnInteger) { - int r; - const char *json = "{\"x\":3}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse integer as string returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseStringErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean as string returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseBooleanTrue) { - int r; - const char *json = "{\"x\":true}"; - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean with true value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, (int) parsedBool); -} - -TEST_C(JsonUtils, ParseBooleanFalse) { - int r; - const char *json = "{\"x\":false}"; - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean with false value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(0, (int) parsedBool); -} - -TEST_C(JsonUtils, ParseBooleanErrorOnString) { - int r; - const char *json = "{\"x\":\"not a bool\"}"; - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse string as boolean returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseBooleanErrorOnInvalidJson) { - int r; - const char *json = "{\"x\":frue}"; // Invalid - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean returns error with invalid json \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleBasic) { - int r; - const char *json = "{\"x\":20.5}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse double test \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(20.5, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseDoubleNumberWithNoDecimal) { - int r; - const char *json = "{\"x\":100}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse double number with no decimal \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(100, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseDoubleSmallDouble) { - int r; - const char *json = "{\"x\":0.000004}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse small double value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(0.000004, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseDoubleErrorOnString) { - int r; - const char *json = "{\"x\":\"20.5\"}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse string as double returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse boolean as double returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleErrorOnJsonObject) { - int r; - const char *json = "{\"x\":{}}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse json object as double returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleNegativeNumber) { - int r; - const char *json = "{\"x\":-56.78}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative double value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(-56.78, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseFloatBasic) { - int r; - const char *json = "{\"x\":20.5}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse float test \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(20.5, parsedFloat, 0.0); -} - -TEST_C(JsonUtils, ParseFloatNumberWithNoDecimal) { - int r; - const char *json = "{\"x\":100}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse float number with no decimal \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(100, parsedFloat, 0.0); -} - -TEST_C(JsonUtils, ParseFloatSmallFloat) { - int r; - const char *json = "{\"x\":0.0004}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse small float value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(0.0004f == parsedFloat); -} - -TEST_C(JsonUtils, ParseFloatErrorOnString) { - int r; - const char *json = "{\"x\":\"20.5\"}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse string as float returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseFloatErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse boolean as float returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseFloatErrorOnJsonObject) { - int r; - const char *json = "{\"x\":{}}"; - float parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse json object as float returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseFloatNegativeNumber) { - int r; - const char *json = "{\"x\":-56.78}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative float value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(-56.78f == parsedFloat); -} - -TEST_C(JsonUtils, ParseIntegerBasic) { - int r; - const char *json = "{\"x\":1}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseIntegerLargeInteger) { - int r; - const char *json = "{\"x\":2147483647}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(2147483647, parsedInteger); -} - -TEST_C(JsonUtils, ParseIntegerNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(-308, parsedInteger); -} - -TEST_C(JsonUtils, ParseIntegerErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseIntegerErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger16bitBasic) { - int r; - const char *json = "{\"x\":1}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger16bitLargeInteger) { - int r; - const char *json = "{\"x\":32767}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(32767, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger16bitNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(-308, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger16bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger16bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger8bitBasic) { - int r; - const char *json = "{\"x\":1}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger8bitLargeInteger) { - int r; - const char *json = "{\"x\":127}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(127, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger8bitNegativeInteger) { - int r; - const char *json = "{\"x\":-30}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(-30, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger8bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger8bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerBasic) { - int r; - const char *json = "{\"x\":1}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(1 == parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerLargeInteger) { - int r; - const char *json = "{\"x\":2147483647}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(2147483647 == parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error with negative value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitBasic) { - int r; - const char *json = "{\"x\":1}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitLargeInteger) { - int r; - const char *json = "{\"x\":65535}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(65535, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error on negative value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitBasic) { - int r; - const char *json = "{\"x\":1}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitLargeInteger) { - int r; - const char *json = "{\"x\":255}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(255, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnNegativeInteger) { - int r; - const char *json = "{\"x\":-30}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error on negative value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp deleted file mode 100644 index da188e0fe..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_publish.cpp - * @brief IoT Client Unit Testing - Publish API Tests - */ - -#include -#include - -TEST_GROUP_C(PublishTests) { - TEST_GROUP_C_SETUP_WRAPPER(PublishTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(PublishTests) -}; - -/* E:1 - Publish with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNullClient) -/* E:2 - Publish with Null/empty Topic Name */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNullTopic) -/* E:3 - Publish with Null/empty payload */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNullParams) -/* E:4 - Publish with network disconnected */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNetworkDisconnected) -/* E:5 - Publish with QoS2 */ -/* Not required here, enum value doesn't exist for QoS2 */ -/* E:6 - Publish with QoS1 send success, Puback not received */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1FailureToReceivePuback) -/* E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1FailureDelayedPuback) -/* E:8 - Publish with send success, Delayed Puback received before command timeout */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1Success10msDelayedPuback) -/* E:9 - Publish QoS0 success */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS0NoPubackSuccess) -/* E:10 - Publish with QoS1 send success, Puback received */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1Success) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c deleted file mode 100644 index 2f2c6406c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c +++ /dev/null @@ -1,205 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_publish_helper.c - * @brief IoT Client Unit Testing - Publish API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static AWS_IoT_Client iotClient; -char cPayload[100]; - -TEST_GROUP_C_SETUP(PublishTests) { - IoT_Error_t rc = SUCCESS; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - sprintf(cPayload, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(PublishTests) { } - -/* E:1 - Publish with Null/empty client instance */ -TEST_C(PublishTests, PublishNullClient) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:1 - Publish with Null/empty client instance \n"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = "Message"; - testPubMsgParams.payloadLen = 7; - - rc = aws_iot_mqtt_publish(NULL, "sdkTest/Sub", 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - E:1 - Publish with Null/empty client instance \n"); -} - -/* E:2 - Publish with Null/empty Topic Name */ -TEST_C(PublishTests, PublishNullTopic) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:2 - Publish with Null/empty Topic Name \n"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = "Message"; - testPubMsgParams.payloadLen = 7; - - rc = aws_iot_mqtt_publish(&iotClient, NULL, 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 0, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - E:2 - Publish with Null/empty Topic Name \n"); -} - -/* E:3 - Publish with Null/empty payload */ -TEST_C(PublishTests, PublishNullParams) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:3 - Publish with Null/empty payload \n"); - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = NULL; - testPubMsgParams.payloadLen = 0; - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - E:3 - Publish with Null/empty payload \n"); -} - -/* E:4 - Publish with network disconnected */ -TEST_C(PublishTests, PublishNetworkDisconnected) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:4 - Publish with network disconnected \n"); - - /* Ensure network is disconnected */ - rc = aws_iot_mqtt_disconnect(&iotClient); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = NULL; - testPubMsgParams.payloadLen = 0; - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - - IOT_DEBUG("-->Success - E:4 - Publish with network disconnected \n"); -} - -/* E:6 - Publish with QoS1 send success, Puback not received */ -TEST_C(PublishTests, publishQoS1FailureToReceivePuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:6 - Publish with QoS1 send success, Puback not received \n"); - - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - E:6 - Publish with QoS1 send success, Puback not received \n"); -} - -/* E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout */ -TEST_C(PublishTests, publishQoS1FailureDelayedPuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout \n"); - - setTLSRxBufferDelay(10, 0); - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout \n"); -} - -/* E:8 - Publish with send success, Delayed Puback received before command timeout */ -TEST_C(PublishTests, publishQoS1Success10msDelayedPuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:8 - Publish with send success, Delayed Puback received before command timeout \n"); - - ResetTLSBuffer(); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - E:8 - Publish with send success, Delayed Puback received before command timeout \n"); -} - -/* E:9 - Publish QoS0 success */ -TEST_C(PublishTests, publishQoS0NoPubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:9 - Publish QoS0 success \n"); - - testPubMsgParams.qos = QOS0; // switch to a Qos0 PUB - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - E:9 - Publish QoS0 success \n"); -} - -/* E:10 - Publish with QoS1 send success, Puback received */ -TEST_C(PublishTests, publishQoS1Success) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:10 - Publish with QoS1 send success, Puback received \n"); - - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - E:10 - Publish with QoS1 send success, Puback received \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp deleted file mode 100644 index ba1f5cb48..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_runner.cpp - * @brief IoT Client Unit Testing - Runner - */ - -#include - -int main(int ac, char **argv) { - return CommandLineTestRunner::RunAllTests(ac, argv); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp deleted file mode 100644 index 32f1be2e1..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_action.cpp - * @brief IoT Client Unit Testing - Shadow Action Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowActionTests) { - TEST_GROUP_C_SETUP_WRAPPER(ShadowActionTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowActionTests) -}; - -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetTheFullJSONDocument) -TEST_GROUP_C_WRAPPER(ShadowActionTests, DeleteTheJSONDocument) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UpdateTheJSONDocument) -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetTheFullJSONDocumentTimeout) -TEST_GROUP_C_WRAPPER(ShadowActionTests, SubscribeToAcceptedRejectedOnGet) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeout) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeoutWithSticky) -TEST_GROUP_C_WRAPPER(ShadowActionTests, WrongTokenInGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, NoTokenInGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, InvalidInboundJSONInGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, AcceptedSubFailsGetRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, RejectedSubFailsGetRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, PublishFailsGetRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetVersionFromAckStatus) -TEST_GROUP_C_WRAPPER(ShadowActionTests, StickyNonStickyNeverConflict) -TEST_GROUP_C_WRAPPER(ShadowActionTests, ACKWaitingMoreThanAllowed) -TEST_GROUP_C_WRAPPER(ShadowActionTests, InboundDataTooBigForBuffer) -TEST_GROUP_C_WRAPPER(ShadowActionTests, NoClientTokenForShadowAction) -TEST_GROUP_C_WRAPPER(ShadowActionTests, NoCallbackForShadowAction) -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetAndDeleteRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, ExtractClientToken) -TEST_GROUP_C_WRAPPER(ShadowActionTests, IsReceivedJsonValid) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c deleted file mode 100644 index 86e603197..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c +++ /dev/null @@ -1,944 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_action_helper.c - * @brief IoT Client Unit Testing - Shadow Action API Tests Helper - */ - -#include -#include -#include -#include -#include - -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_tests_unit_shadow_helper.h" - -#include "aws_iot_shadow_interface.h" -#include "aws_iot_shadow_actions.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_log.h" - -#define SIZE_OF_UPDATE_DOCUMENT 200 -#define TEST_JSON_RESPONSE_FULL_DOCUMENT "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" -#define TEST_JSON_RESPONSE_DELETE_DOCUMENT "{\"version\":2,\"timestamp\":1443473857,\"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" -#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" -#define TEST_JSON_SIZE 120 -static AWS_IoT_Client client; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -static Shadow_Ack_Status_t ackStatusRx; -static char jsonFullDocument[200]; -static ShadowActions_t actionRx; - -static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action) { - char actionBuf[10]; - - if(SHADOW_GET == action) { - strcpy(actionBuf, "get"); - } else if(SHADOW_UPDATE == action) { - strcpy(actionBuf, "update"); - } else if(SHADOW_DELETE == action) { - strcpy(actionBuf, "delete"); - } - - snprintf(pTopic, 100, "$aws/things/%s/shadow/%s", pThingName, actionBuf); -} - -TEST_GROUP_C_SETUP(ShadowActionTests) { - IoT_Error_t ret_val = SUCCESS; - char cPayload[100]; - char topic[120]; - - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - ret_val = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_shadow_connect(&client, &shadowConnectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - setTLSRxBufferForPuback(); - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload) + 1; - topicNameFromThingAndAction(topic, AWS_IOT_MY_THING_NAME, SHADOW_GET); - setTLSRxBufferForDoubleSuback(topic, strlen(topic), QOS1, testPubMsgParams); -} - -TEST_GROUP_C_TEARDOWN(ShadowActionTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_shadow_disconnect(&client); - IOT_UNUSED(rc); -} - -static void actionCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(pContextData); - IOT_DEBUG("%s", pReceivedJsonDocument); - actionRx = action; - ackStatusRx = status; - if(SHADOW_ACK_TIMEOUT != status) { - strcpy(jsonFullDocument, pReceivedJsonDocument); - } -} - -// Happy path for Get, Update, Delete -TEST_C(ShadowActionTests, GetTheFullJSONDocument) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Get full json document \n"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - IOT_DEBUG("-->Success - Get full json document \n"); -} - -TEST_C(ShadowActionTests, DeleteTheJSONDocument) { - IoT_Error_t ret_val = SUCCESS; - IoT_Publish_Message_Params params; - char deleteRequestJson[TEST_JSON_SIZE]; - - IOT_DEBUG("-->Running Shadow Action Tests - Delete json document \n"); - - aws_iot_shadow_internal_delete_request_json(deleteRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_DELETE, deleteRequestJson, TEST_JSON_SIZE, actionCallback, - NULL, 4, false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_DELETE_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_DELETE_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(DELETE_ACCEPTED_TOPIC, strlen(DELETE_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_DELETE_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_DELETE, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - IOT_DEBUG("-->Success - Delete json document \n"); -} - -TEST_C(ShadowActionTests, UpdateTheJSONDocument) { - IoT_Error_t ret_val = SUCCESS; - char updateRequestJson[SIZE_OF_UPDATE_DOCUMENT]; - char expectedUpdateRequestJson[SIZE_OF_UPDATE_DOCUMENT]; - double doubleData = 4.0908f; - float floatData = 3.445f; - bool boolData = true; - jsonStruct_t dataFloatHandler; - jsonStruct_t dataDoubleHandler; - jsonStruct_t dataBoolHandler; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Update json document \n"); - - dataFloatHandler.cb = NULL; - dataFloatHandler.pData = &floatData; - dataFloatHandler.dataLength = sizeof(float); - dataFloatHandler.pKey = "floatData"; - dataFloatHandler.type = SHADOW_JSON_FLOAT; - - dataDoubleHandler.cb = NULL; - dataDoubleHandler.pData = &doubleData; - dataDoubleHandler.dataLength = sizeof(double); - dataDoubleHandler.pKey = "doubleData"; - dataDoubleHandler.type = SHADOW_JSON_DOUBLE; - - dataBoolHandler.cb = NULL; - dataBoolHandler.pData = &boolData; - dataBoolHandler.dataLength = sizeof(bool); - dataBoolHandler.pKey = "boolData"; - dataBoolHandler.type = SHADOW_JSON_BOOL; - - ret_val = aws_iot_shadow_init_json_document(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_reported(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, 2, &dataDoubleHandler, - &dataFloatHandler); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_desired(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, 1, &dataBoolHandler); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_finalize_json_document(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - snprintf(expectedUpdateRequestJson, SIZE_OF_UPDATE_DOCUMENT, - "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000},\"desired\":{\"boolData\":true}}, \"clientToken\":\"%s-0\"}", - AWS_IOT_MQTT_CLIENT_ID); - CHECK_EQUAL_C_STRING(expectedUpdateRequestJson, updateRequestJson); - - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_UPDATE, updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, actionCallback, - NULL, 4, false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - snprintf(jsonFullDocument, 200, "%s", ""); - params.payloadLen = strlen(TEST_JSON_RESPONSE_UPDATE_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_UPDATE_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(UPDATE_ACCEPTED_TOPIC, strlen(UPDATE_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_UPDATE_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_UPDATE, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - IOT_DEBUG("-->Success - Update json document \n"); -} - -TEST_C(ShadowActionTests, GetTheFullJSONDocumentTimeout) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Get full json document timeout \n"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx); - - IOT_DEBUG("-->Success - Get full json document timeout \n"); -} - -// Subscribe and UnSubscribe on reception of thing names. Will perform the test with Get operation -TEST_C(ShadowActionTests, SubscribeToAcceptedRejectedOnGet) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - char topicName[128] = "test"; - - IOT_DEBUG("-->Running Shadow Action Tests - Subscribe to get/accepted and get/rejected \n"); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - firstByte = (uint8_t)(TxBuffer.pBuffer[2]); - secondByte = (uint8_t)(TxBuffer.pBuffer[3]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character - - // Verify publish happens - CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName); - - IOT_DEBUG("-->Success - Subscribe to get/accepted and get/rejected \n"); -} - -TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - unsubscribe to get/accepted and get/rejected on response \n"); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - unsubscribe to get/accepted and get/rejected on response \n"); -} - -TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeout) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Unsubscribe to get/accepted and get/rejected on get timeout \n"); - - snprintf(jsonFullDocument, 200, "aa"); - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("aa", jsonFullDocument); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - Unsubscribe to get/accepted and get/rejected on get timeout \n"); -} - - -TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeoutWithSticky) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - No unsubscribe to get/accepted and get/rejected on get timeout with a sticky subscription \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - true); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("timeout", jsonFullDocument); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - No unsubscribe to get/accepted and get/rejected on get timeout with a sticky subscription \n"); -} - -#define TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(num) "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\",\"version\":" #num "}" - -TEST_C(ShadowActionTests, GetVersionFromAckStatus) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - IoT_Publish_Message_Params params2; - - IOT_DEBUG("-->Running Shadow Action Tests - Get version from Ack status \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - true); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(1); - params.payloadLen = strlen(params.payload); - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_C(1u == aws_iot_shadow_get_last_received_version()); - - ResetTLSBuffer(); - params2.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(132387); - params2.payloadLen = strlen(params2.payload); - params2.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params2, - params2.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_C(132387u == aws_iot_shadow_get_last_received_version()); - - IOT_DEBUG("-->Success - Get version from Ack status \n"); -} - -#define TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"TroubleToken1234\"}" - -TEST_C(ShadowActionTests, WrongTokenInGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Wrong token in get response \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("timeout", jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx); - - IOT_DEBUG("-->Success - Wrong token in get response \n"); -} - -#define TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}}" - -TEST_C(ShadowActionTests, NoTokenInGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - No token in get response \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("timeout", jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx); - - IOT_DEBUG("-->Success - No token in get response \n"); -} - -TEST_C(ShadowActionTests, InvalidInboundJSONInGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Invalid inbound json in get response \n"); - - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen("{\"state\":{{"); - params.payload = "{\"state\":{{"; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - IOT_DEBUG("-->Success - Invalid inbound json in get response \n"); -} - -TEST_C(ShadowActionTests, AcceptedSubFailsGetRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Accepted sub fails get request \n"); - - snprintf(jsonFullDocument, 200, "NOT_SENT"); - - ResetTLSBuffer(); - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback - - IOT_DEBUG("-->Success - Accepted sub fails get request \n"); -} - -TEST_C(ShadowActionTests, RejectedSubFailsGetRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Rejected sub fails get request \n"); - - snprintf(jsonFullDocument, 200, "NOT_SENT"); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params); - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(GET_REJECTED_TOPIC, strlen(GET_REJECTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback - - IOT_DEBUG("-->Success - Rejected sub fails get request \n"); -} - -TEST_C(ShadowActionTests, PublishFailsGetRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - publish fails on get request \n"); - - snprintf(jsonFullDocument, 200, "NOT_SENT"); - - ResetTLSBuffer(); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback - - IOT_DEBUG("-->Success - publish fails on get request \n"); -} - -TEST_C(ShadowActionTests, StickyNonStickyNeverConflict) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Sticky and non-sticky subscriptions do not conflict \n"); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - true); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - // Non-sticky shadow get, same thing name. Should never unsub since they are sticky - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - CHECK_EQUAL_C_STRING("No Message", LastSubscribeMessage); - CHECK_EQUAL_C_STRING("No Message", SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - Sticky and non-sticky subscriptions do not conflict \n"); - -} - -TEST_C(ShadowActionTests, ACKWaitingMoreThanAllowed) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - - IOT_DEBUG("-->Running Shadow Action Tests - Ack waiting more than allowed wait time \n"); - - // 1st - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 2nd - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 3rd - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 4th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 5th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 6th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 7th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 8th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 9th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 10th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 11th - // Should return some error code, since we are running out of ACK space - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - IOT_DEBUG("-->Success - Ack waiting more than allowed wait time \n"); -} - -TEST_C(ShadowActionTests, InboundDataTooBigForBuffer) { - uint32_t i = 0; - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - char expectedCallbackString[AWS_IOT_MQTT_RX_BUF_LEN + 2]; - - IOT_DEBUG("-->Running Shadow Action Tests - Inbound data too big for buffer \n"); - - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - for(i = 0; i < AWS_IOT_MQTT_RX_BUF_LEN; i++) { - expectedCallbackString[i] = 'X'; - } - expectedCallbackString[i + 1] = '\0'; - - params.payloadLen = strlen(expectedCallbackString); - params.payload = expectedCallbackString; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, ret_val); - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - IOT_DEBUG("-->Success - Inbound data too big for buffer \n"); -} - -#define TEST_JSON_RESPONSE_NO_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}}" - -TEST_C(ShadowActionTests, NoClientTokenForShadowAction) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - char topicName[128] = "test"; - - IOT_DEBUG("-->Running Shadow Action Tests - No client token for shadow action \n"); - - snprintf(getRequestJson, TEST_JSON_SIZE, "{}"); - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_NO_TOKEN); - params.payload = TEST_JSON_RESPONSE_NO_TOKEN; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // Should never subscribe to accepted/rejected topics since we have no token to track the response - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - firstByte = (uint8_t)(TxBuffer.pBuffer[2]); - secondByte = (uint8_t)(TxBuffer.pBuffer[3]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character - - // Verify publish happens - CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName); - - IOT_DEBUG("-->Success - No client token for shadow action \n"); -} - -TEST_C(ShadowActionTests, IsReceivedJsonValid) -{ - bool ret_val; - char getRequestJson[TEST_JSON_SIZE]; - - IOT_DEBUG("-->Running Shadow Action Tests - IsReceivedJsonValid \n"); - - snprintf(getRequestJson, TEST_JSON_SIZE, TEST_JSON_RESPONSE_FULL_DOCUMENT); - - //Test by cutting the JSON document - ret_val = isReceivedJsonValid(getRequestJson, 3); - CHECK_EQUAL_C_INT(false, ret_val); - - //Happy path - ret_val = isReceivedJsonValid(getRequestJson, TEST_JSON_SIZE); - CHECK_EQUAL_C_INT(true, ret_val); - - IOT_DEBUG("-->Success - IsReceivedJsonValid"); -} - -TEST_C(ShadowActionTests, ExtractClientToken) -{ - bool ret_val; - char getRequestJson[TEST_JSON_SIZE]; - char extractedClientToken[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; - - IOT_DEBUG("-->Running Shadow Action Tests - ExtractClientToken \n"); - - //Try JSON with no token - snprintf(getRequestJson, TEST_JSON_SIZE, "{}"); - ret_val = extractClientToken(getRequestJson, TEST_JSON_SIZE, extractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE ); - CHECK_EQUAL_C_INT(false, ret_val); - - //Try JSON with token but not enough memory - snprintf(getRequestJson, TEST_JSON_SIZE, TEST_JSON_RESPONSE_FULL_DOCUMENT); - ret_val = extractClientToken(getRequestJson, TEST_JSON_SIZE, extractedClientToken, 1 ); - CHECK_EQUAL_C_INT(false, ret_val); - - //Happy path - ret_val = extractClientToken(getRequestJson, TEST_JSON_SIZE, extractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE ); - CHECK_EQUAL_C_INT(true, ret_val); - - IOT_DEBUG("-->Success - ExtractClientToken"); -} - -TEST_C(ShadowActionTests, GetAndDeleteRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - - IOT_DEBUG("-->Running Shadow Action Tests - GetAndDeleteRequest \n"); - - ret_val = aws_iot_shadow_internal_get_request_json(NULL, TEST_JSON_SIZE); - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - ret_val = aws_iot_shadow_internal_get_request_json(getRequestJson, 1); - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - ret_val = aws_iot_shadow_internal_delete_request_json(NULL, TEST_JSON_SIZE); - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - ret_val = aws_iot_shadow_internal_delete_request_json(getRequestJson, 1); - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - IOT_DEBUG("-->Success - GetAndDeleteRequest"); -} - -TEST_C(ShadowActionTests, NoCallbackForShadowAction) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - char topicName[128] = "test"; - - IOT_DEBUG("-->Running Shadow Action Tests - No callback for shadow action \n"); - - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, NULL, NULL, 4, false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // Should never subscribe to accepted/rejected topics since we have no callback to track the response - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - firstByte = (uint8_t)(TxBuffer.pBuffer[2]); - secondByte = (uint8_t)(TxBuffer.pBuffer[3]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character - - // Verify publish happens - CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName); - - IOT_DEBUG("-->Success - No callback for shadow action"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp deleted file mode 100644 index db9c0b25d..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_delta.cpp - * @brief IoT Client Unit Testing - Shadow Delta Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowDeltaTest){ - TEST_GROUP_C_SETUP_WRAPPER(ShadowDeltaTest) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowDeltaTest) -}; - -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaSuccess) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaInt) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaIntNoCallback) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, DeltaNestedObject) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, DeltaVersionIgnoreOldVersion) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c deleted file mode 100644 index 1e6cc2a0a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c +++ /dev/null @@ -1,324 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_delta_helper.c - * @brief IoT Client Unit Testing - Shadow Delta Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_shadow_interface.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static AWS_IoT_Client client; -static IoT_Client_Connect_Params connectParams; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -static char receivedNestedObject[100] = ""; -static char sentNestedObjectData[100] = "{\"sensor1\":23}"; -static char shadowDeltaTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - -#define SHADOW_DELTA_UPDATE "$aws/things/%s/shadow/update/delta" - -#undef AWS_IOT_MY_THING_NAME -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" - -void genericCallback(const char *pJsonStringData, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - printf("\nkey[%s]==Data[%.*s]\n", pContext->pKey, JsonStringDataLen, pJsonStringData); -} - -void nestedObjectCallback(const char *pJsonStringData, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - printf("\nkey[%s]==Data[%.*s]\n", pContext->pKey, JsonStringDataLen, pJsonStringData); - snprintf(receivedNestedObject, 100, "%.*s", JsonStringDataLen, pJsonStringData); -} - -TEST_GROUP_C_SETUP(ShadowDeltaTest) { - IoT_Error_t ret_val = SUCCESS; - - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - ret_val = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_shadow_connect(&client, &shadowConnectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - snprintf(shadowDeltaTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, SHADOW_DELTA_UPDATE, AWS_IOT_MY_THING_NAME); -} - -TEST_GROUP_C_TEARDOWN(ShadowDeltaTest) { - -} - -TEST_C(ShadowDeltaTest, registerDeltaSuccess) { - jsonStruct_t windowHandler; - char deltaJSONString[] = "{\"state\":{\"delta\":{\"window\":true}},\"version\":1}"; - bool windowOpenData = false; - IoT_Publish_Message_Params params; - IoT_Error_t ret_val = SUCCESS; - - IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta success \n"); - - windowHandler.cb = genericCallback; - windowHandler.pKey = "window"; - windowHandler.type = SHADOW_JSON_BOOL; - windowHandler.pData = &windowOpenData; - windowHandler.dataLength = sizeof(bool); - - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &windowHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - ret_val = aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_INT(true, windowOpenData); -} - - -TEST_C(ShadowDeltaTest, registerDeltaInt) { - IoT_Error_t ret_val = SUCCESS; - jsonStruct_t intHandler; - int32_t intData = 0; - char deltaJSONString[] = "{\"state\":{\"delta\":{\"length\":23}},\"version\":1}"; - IoT_Publish_Message_Params params; - - IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta integer \n"); - - intHandler.cb = genericCallback; - intHandler.pKey = "length"; - intHandler.type = SHADOW_JSON_INT32; - intHandler.pData = &intData; - intHandler.dataLength = sizeof(int32_t); - - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &intHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_INT(23, intData); -} - -TEST_C(ShadowDeltaTest, registerDeltaIntNoCallback) { - IoT_Error_t ret_val = SUCCESS; - jsonStruct_t intHandler; - int32_t intData = 0; - char deltaJSONString[] = "{\"state\":{\"delta\":{\"length_nocb\":23}},\"version\":1}"; - IoT_Publish_Message_Params params; - - IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta integer with no callback \n"); - - intHandler.cb = NULL; - intHandler.pKey = "length_nocb"; - intHandler.type = SHADOW_JSON_INT32; - intHandler.pData = &intData; - intHandler.dataLength = sizeof(int32_t); - - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &intHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_INT(23, intData); -} - -TEST_C(ShadowDeltaTest, DeltaNestedObject) { - IoT_Error_t ret_val = SUCCESS; - IoT_Publish_Message_Params params; - jsonStruct_t nestedObjectHandler; - char nestedObject[100]; - char deltaJSONString[100]; - - printf("\n-->Running Shadow Delta Tests - Delta received with nested object \n"); - - nestedObjectHandler.cb = nestedObjectCallback; - nestedObjectHandler.pKey = "sensors"; - nestedObjectHandler.type = SHADOW_JSON_OBJECT; - nestedObjectHandler.pData = &nestedObject; - nestedObjectHandler.dataLength = 100; - - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":1}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &nestedObjectHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); -} - - -// Send back to back version and ensure a wrong version is ignored with old message enabled -TEST_C(ShadowDeltaTest, DeltaVersionIgnoreOldVersion) { - IoT_Error_t ret_val = SUCCESS; - char deltaJSONString[100]; - jsonStruct_t nestedObjectHandler; - char nestedObject[100]; - IoT_Publish_Message_Params params; - - printf("\n-->Running Shadow Delta Tests - delta received, old version ignored \n"); - - nestedObjectHandler.cb = nestedObjectCallback; - nestedObjectHandler.pKey = "sensors"; - nestedObjectHandler.type = SHADOW_JSON_OBJECT; - nestedObjectHandler.pData = &nestedObject; - nestedObjectHandler.dataLength = 100; - - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":1}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &nestedObjectHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":2}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":2}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(" ", receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - aws_iot_shadow_reset_last_received_version(); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(" ", receivedNestedObject); - - aws_iot_shadow_disable_discard_old_delta_msgs(); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp deleted file mode 100644 index 8feb144e5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_json_builder.cpp - * @brief IoT Client Unit Testing - Shadow JSON Builder Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowJsonBuilderTests){ - TEST_GROUP_C_SETUP_WRAPPER(ShadowJsonBuilderTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowJsonBuilderTests) -}; - -TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, UpdateTheJSONDocumentBuilder) -TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, PassingNullValue) -TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, SmallBuffer) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c deleted file mode 100644 index 3541341b5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c +++ /dev/null @@ -1,131 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_json_builder_helper.c - * @brief IoT Client Unit Testing - Shadow JSON Builder Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_shadow_actions.h" -#include "aws_iot_log.h" -#include "aws_iot_tests_unit_helper_functions.h" - -static jsonStruct_t dataFloatHandler; -static jsonStruct_t dataDoubleHandler; -static double doubleData = 4.0908f; -static float floatData = 3.445f; -static AWS_IoT_Client iotClient; -static IoT_Client_Connect_Params connectParams; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -TEST_GROUP_C_SETUP(ShadowJsonBuilderTests) { - IoT_Error_t ret_val; - - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - ret_val = aws_iot_shadow_init(&iotClient, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_shadow_connect(&iotClient, &shadowConnectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - dataFloatHandler.cb = NULL; - dataFloatHandler.pData = &floatData; - dataFloatHandler.pKey = "floatData"; - dataFloatHandler.type = SHADOW_JSON_FLOAT; - dataFloatHandler.dataLength = sizeof(float); - - dataDoubleHandler.cb = NULL; - dataDoubleHandler.pData = &doubleData; - dataDoubleHandler.pKey = "doubleData"; - dataDoubleHandler.type = SHADOW_JSON_DOUBLE; - dataDoubleHandler.dataLength = sizeof(double); -} - -TEST_GROUP_C_TEARDOWN(ShadowJsonBuilderTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" - -#define SIZE_OF_UPFATE_BUF 200 - -TEST_C(ShadowJsonBuilderTests, UpdateTheJSONDocumentBuilder) { - IoT_Error_t ret_val; - char updateRequestJson[SIZE_OF_UPFATE_BUF]; - size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]); - - IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Update the Json document builder \n"); - - ret_val = aws_iot_shadow_init_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_reported(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_finalize_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_UPDATE_DOCUMENT, updateRequestJson); -} - -TEST_C(ShadowJsonBuilderTests, PassingNullValue) { - IoT_Error_t ret_val; - - IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Passing Null value to Shadow json builder \n"); - - ret_val = aws_iot_shadow_init_json_document(NULL, SIZE_OF_UPFATE_BUF); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); - ret_val = aws_iot_shadow_add_reported(NULL, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); - ret_val = aws_iot_shadow_add_desired(NULL, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); - ret_val = aws_iot_finalize_json_document(NULL, SIZE_OF_UPFATE_BUF); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); -} - -TEST_C(ShadowJsonBuilderTests, SmallBuffer) { - IoT_Error_t ret_val; - char updateRequestJson[14]; - size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]); - - IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Json Buffer is too small \n"); - - ret_val = aws_iot_shadow_init_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_reported(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(SHADOW_JSON_BUFFER_TRUNCATED, ret_val); - ret_val = aws_iot_shadow_add_desired(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, ret_val); - ret_val = aws_iot_finalize_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, ret_val); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp deleted file mode 100644 index dd4d02a6b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_null_fields.cpp - * @brief IoT Client Unit Testing - Shadow APIs NULL field Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowNullFields){ - TEST_GROUP_C_SETUP_WRAPPER(ShadowNullFields) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowNullFields) -}; - -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientInit) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientConnect) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullHost) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullPort) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientID) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullUpdateDocument) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientYield) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientDisconnect) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowGet) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowUpdate) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowDelete) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientSetAutoreconnect) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c deleted file mode 100644 index 0848bd0a5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_shadow_null_fields_helper.c - * @brief IoT Client Unit Testing - Shadow APIs NULL field Tests helper - */ - -#include -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_shadow_interface.h" -#include "aws_iot_shadow_actions.h" -#include "aws_iot_log.h" - -static AWS_IoT_Client client; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -static Shadow_Ack_Status_t ackStatusRx; -static ShadowActions_t actionRx; -static char jsonFullDocument[200]; - -void actionCallbackNullTest(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(pContextData); - IOT_DEBUG("%s", pReceivedJsonDocument); - actionRx = action; - ackStatusRx = status; - if(status != SHADOW_ACK_TIMEOUT) { - strcpy(jsonFullDocument, pReceivedJsonDocument); - } -} - -TEST_GROUP_C_SETUP(ShadowNullFields) { - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(ShadowNullFields) { } - -TEST_C(ShadowNullFields, NullHost) { - shadowInitParams.pHost = NULL; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.disconnectHandler = NULL; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullPort) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = 0; - shadowInitParams.disconnectHandler = NULL; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientID) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = NULL; - rc = aws_iot_shadow_connect(&client, &shadowConnectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientInit) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.disconnectHandler = NULL; - IoT_Error_t rc = aws_iot_shadow_init(NULL, &shadowInitParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientConnect) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - rc = aws_iot_shadow_connect(NULL, &shadowConnectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullUpdateDocument) { - IoT_Error_t rc = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_UPDATE, NULL, 0, actionCallbackNullTest, - NULL, 4, false); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientYield) { - IoT_Error_t rc = aws_iot_shadow_yield(NULL, 1000); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientDisconnect) { - IoT_Error_t rc = aws_iot_shadow_disconnect(NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientShadowGet) { - IoT_Error_t rc = aws_iot_shadow_get(NULL, AWS_IOT_MY_THING_NAME, actionCallbackNullTest, NULL, 100, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientShadowUpdate) { - IoT_Error_t rc = aws_iot_shadow_update(NULL, AWS_IOT_MY_THING_NAME, jsonFullDocument, - actionCallbackNullTest, NULL, 100, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientShadowDelete) { - IoT_Error_t rc = aws_iot_shadow_delete(NULL, AWS_IOT_MY_THING_NAME, actionCallbackNullTest, NULL, 100, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientSetAutoreconnect) { - IoT_Error_t rc = aws_iot_shadow_set_autoreconnect_status(NULL, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp deleted file mode 100644 index f19a7c9c7..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_subscribe.cpp - * @brief IoT Client Unit Testing - Subscribe API Tests - */ - -#include -#include - -TEST_GROUP_C(SubscribeTests){ - TEST_GROUP_C_SETUP_WRAPPER(SubscribeTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(SubscribeTests) -}; - -/* C:1 - Subscribe with Null/empty Client Instance */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullClient) -/* C:2 - Subscribe with Null/empty Topic Name */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullTopic) -/* C:3 - Subscribe with Null client callback */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullSubscribeHandler) -/* C:4 - Subscribe with Null client callback data */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullSubscribeHandlerData) -/* C:5 - Subscribe with no connection */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNoConnection) -/* C:6 - Subscribe QoS2, error */ -/* Not required, QoS enum doesn't have value for QoS2 */ - -/* C:7 - Subscribe attempt, QoS0, no response timeout */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0FailureOnNoSuback) -/* C:8 - Subscribe attempt, QoS1, no response timeout */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1FailureOnNoSuback) - -/* C:9 - Subscribe QoS0 success, suback received */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0Success) -/* C:10 - Subscribe QoS1 success, suback received */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1Success) - -/* C:11 - Subscribe, QoS0, delayed suback, success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0WithDelayedSubackSuccess) -/* C:12 - Subscribe, QoS1, delayed suback, success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1WithDelayedSubackSuccess) - -/* C:13 - Subscribe QoS0 success, no puback sent on message */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0MsgReceivedAndNoPubackSent) -/* C:14 - Subscribe QoS1 success, puback sent on message */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1MsgReceivedAndSendPuback) - -/* C:15 - Subscribe, malformed response */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeMalformedResponse) - -/* C:16 - Subscribe, multiple topics, messages on each topic */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeToMultipleTopicsSuccess) -/* C:17 - Subscribe, max topics, messages on each topic */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeToMaxAllowedTopicsSuccess) -/* C:18 - Subscribe, max topics, another subscribe */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeToMaxPlusOneAllowedTopicsFailure) - -/* C:19 - Subscribe, '#' not last character in topic name, Failure */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicWithHashkeyAllSubTopicSuccess) -/* C:20 - Subscribe with '#', subscribed to all subtopics */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicHashkeyMustBeTheLastFail) -/* C:21 - Subscribe with '+' as wildcard success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicWithPluskeySuccess) -/* C:22 - Subscribe with '+' as last character in topic name, Success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicPluskeyComesLastSuccess) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c deleted file mode 100644 index 53e4c67fc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c +++ /dev/null @@ -1,606 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_subscribe_helper.c - * @brief IoT Client Unit Testing - Subscribe API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static AWS_IoT_Client iotClient; -static char CallbackMsgString[100]; -char cPayload[100]; - -static char CallbackMsgString1[100] = {"XXXX"}; -static char CallbackMsgString2[100] = {"XXXX"}; -static char CallbackMsgString3[100] = {"XXXX"}; -static char CallbackMsgString4[100] = {"XXXX"}; -static char CallbackMsgString5[100] = {"XXXX"}; -static char CallbackMsgString6[100] = {"XXXX"}; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler1(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - printf("callback topic %.*s\n", topicNameLen, topicName); - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString1[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler2(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString2[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler3(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString3[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler4(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString4[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler5(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString5[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler6(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString6[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(SubscribeTests) { - IoT_Error_t rc; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(SubscribeTests) { } - - - -/* C:1 - Subscribe with Null/empty Client Instance */ -TEST_C(SubscribeTests, SubscribeNullClient) { - IoT_Error_t rc = aws_iot_mqtt_subscribe(NULL, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, &iotClient); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* C:2 - Subscribe with Null/empty Topic Name */ -TEST_C(SubscribeTests, SubscribeNullTopic) { - IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, NULL, 11, QOS1, iot_subscribe_callback_handler, &iotClient); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* C:3 - Subscribe with Null client callback */ -TEST_C(SubscribeTests, SubscribeNullSubscribeHandler) { - IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, NULL, &iotClient); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} -/* C:4 - Subscribe with Null client callback data */ -TEST_C(SubscribeTests, SubscribeNullSubscribeHandlerData) { - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); -} -/* C:5 - Subscribe with no connection */ -TEST_C(SubscribeTests, SubscribeNoConnection) { - /* Disconnect first */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - - rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); -} -/* C:6 - Subscribe QoS2, error */ -/* Not required, QoS enum doesn't have value for QoS2 */ - -/* C:7 - Subscribe attempt, QoS0, no response timeout */ -TEST_C(SubscribeTests, subscribeQoS0FailureOnNoSuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:7 - Subscribe attempt, QoS0, no response timeout \n"); - - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - C:7 - Subscribe attempt, QoS0, no response timeout \n"); -} -/* C:8 - Subscribe attempt, QoS1, no response timeout */ -TEST_C(SubscribeTests, subscribeQoS1FailureOnNoSuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:8 - Subscribe attempt, QoS1, no response timeout \n"); - - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - C:8 - Subscribe attempt, QoS1, no response timeout \n"); -} - -/* C:9 - Subscribe QoS0 success, suback received */ -TEST_C(SubscribeTests, subscribeQoS0Success) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:9 - Subscribe QoS0 success, suback received \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:9 - Subscribe QoS0 success, suback received \n"); -} - -/* C:10 - Subscribe QoS1 success, suback received */ -TEST_C(SubscribeTests, subscribeQoS1Success) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:10 - Subscribe QoS1 success, suback received \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:10 - Subscribe QoS1 success, suback received \n"); -} - -/* C:11 - Subscribe, QoS0, delayed suback, success */ -TEST_C(SubscribeTests, subscribeQoS0WithDelayedSubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:11 - Subscribe, QoS0, delayed suback, success \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:11 - Subscribe, QoS0, delayed suback, success \n"); -} - -/* C:12 - Subscribe, QoS1, delayed suback, success */ -TEST_C(SubscribeTests, subscribeQoS1WithDelayedSubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:12 - Subscribe, QoS1, delayed suback, success \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:12 - Subscribe, QoS1, delayed suback, success \n"); -} - -/* C:13 - Subscribe QoS0 success, no puback sent on message */ -TEST_C(SubscribeTests, subscribeQoS0MsgReceivedAndNoPubackSent) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "Test msg - unit test"; - - IOT_DEBUG("-->Running Subscribe Tests - C:13 - Subscribe QoS0 success, no puback sent on message \n"); - - ResetTLSBuffer(); - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS == rc) { - testPubMsgParams.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - } - } - CHECK_EQUAL_C_INT(0, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:13 - Subscribe QoS0 success, no puback sent on message \n"); -} - -/* C:14 - Subscribe QoS1 success, puback sent on message */ -TEST_C(SubscribeTests, subscribeQoS1MsgReceivedAndSendPuback) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "0xA5A5A3"; - - IOT_DEBUG("-->Running Subscribe Tests - C:14 - Subscribe QoS1 success, puback sent on message \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - if(SUCCESS == rc) { - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - } - - IOT_DEBUG("-->Success - C:14 - Subscribe QoS1 success, puback sent on message \n"); -} - -/* C:15 - Subscribe, malformed response */ -TEST_C(SubscribeTests, subscribeMalformedResponse) {} - -/* C:16 - Subscribe, multiple topics, messages on each topic */ -TEST_C(SubscribeTests, SubscribeToMultipleTopicsSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "0xA5A5A3"; - - IOT_DEBUG("-->Running Subscribe Tests - C:16 - Subscribe, multiple topics, messages on each topic \n"); - - setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test1", 9, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString1); - - IOT_DEBUG("-->Success - C:16 - Subscribe, multiple topics, messages on each topic \n"); -} -/* C:17 - Subscribe, max topics, messages on each topic */ -TEST_C(SubscribeTests, SubscribeToMaxAllowedTopicsSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "topics sdk/Test1"; - char expectedCallbackString2[] = "topics sdk/Test2"; - char expectedCallbackString3[] = "topics sdk/Test3"; - char expectedCallbackString4[] = "topics sdk/Test4"; - char expectedCallbackString5[] = "topics sdk/Test5"; - - IOT_DEBUG("-->Running Subscribe Tests - C:17 - Subscribe, max topics, messages on each topic \n"); - - setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test3", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test3", 9, QOS1, iot_subscribe_callback_handler3, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test4", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test4", 9, QOS1, iot_subscribe_callback_handler4, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test5", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test5", 9, QOS1, iot_subscribe_callback_handler5, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test1", 9, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test2", 9, QOS1, testPubMsgParams, expectedCallbackString2); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test3", 9, QOS1, testPubMsgParams, expectedCallbackString3); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test4", 9, QOS1, testPubMsgParams, expectedCallbackString4); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test5", 9, QOS1, testPubMsgParams, expectedCallbackString5); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString1); - CHECK_EQUAL_C_STRING(expectedCallbackString2, CallbackMsgString2); - CHECK_EQUAL_C_STRING(expectedCallbackString3, CallbackMsgString3); - CHECK_EQUAL_C_STRING(expectedCallbackString4, CallbackMsgString4); - CHECK_EQUAL_C_STRING(expectedCallbackString5, CallbackMsgString5); - - IOT_DEBUG("-->Success - C:17 - Subscribe, max topics, messages on each topic \n"); -} -/* C:18 - Subscribe, max topics, another subscribe */ -TEST_C(SubscribeTests, SubscribeToMaxPlusOneAllowedTopicsFailure) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:18 - Subscribe, max topics, another subscribe \n"); - - setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test3", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test3", 9, QOS1, iot_subscribe_callback_handler3, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test4", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test4", 9, QOS1, iot_subscribe_callback_handler4, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test5", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test5", 9, QOS1, iot_subscribe_callback_handler5, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test6", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test6", 9, QOS1, iot_subscribe_callback_handler6, NULL); - CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc); - - IOT_DEBUG("-->Success - C:18 - Subscribe, max topics, another subscribe \n"); -} - -/* C:19 - Subscribe, '#' not last character in topic name, Failure */ -TEST_C(SubscribeTests, subscribeTopicWithHashkeyAllSubTopicSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: sub/sub, Hashkey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:19 - Subscribe, '#' not last character in topic name, Failure \n"); - - // Set up the subscribed topic, including '#' - setTLSRxBufferForSuback("sdk/Test/#", strlen("sdk/Test/#"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/#", strlen("sdk/Test/#"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // Now provide a published message from a sub topic - IOT_DEBUG("[Matching '#'] Checking first sub topic message, with '#' be the last..\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/sub/sub", strlen("sdk/Test/sub/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - // Re-initialize Rx Tx Buffer - ResetTLSBuffer(); - - // Now provide another message from a different sub topic - IOT_DEBUG("[Matching '#'] Checking second sub topic message, with '#' be the last...\n"); - snprintf(expectedCallbackString, 100, "New message: sub2, Hashkey"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/sub2", strlen("sdk/Test/sub2"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:19 - Subscribe, '#' not last character in topic name, Failure \n"); -} -/* C:20 - Subscribe with '#', subscribed to all subtopics */ -TEST_C(SubscribeTests, subscribeTopicHashkeyMustBeTheLastFail) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: foo1/sub, Hashkey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:20 - Subscribe with '#', subscribed to all subtopics \n"); - - // Set up the subscribed topic, with '#' in the middle - // Topic directory not permitted, should fail - setTLSRxBufferForSuback("sdk/#/sub", strlen("sdk/#/sub"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/#/sub", strlen("sdk/#/sub"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Now provide a published message from a sub directoy with this sub topic - IOT_DEBUG("[Matching '#'] Checking sub topic message, with '#' in the middle...\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo1/sub", strlen("sdk/Test/foo1/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("NOT_VISITED", CallbackMsgString); - - IOT_DEBUG("-->Success - C:20 - Subscribe with '#', subscribed to all subtopics \n"); -} -/* C:21 - Subscribe with '+' as wildcard success */ -TEST_C(SubscribeTests, subscribeTopicWithPluskeySuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: 1/sub, Pluskey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:21 - Subscribe with '+' as wildcard success \n"); - - // Set up the subscribed topic, including '+' - setTLSRxBufferForSuback("sdk/Test/+/sub", strlen("sdk/Test/+/sub"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/+/sub", strlen("sdk/Test/+/sub"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // Now provide a published message from a sub topic - IOT_DEBUG("[Matching '+'] Checking first sub topic message, with '+' in the middle...\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/1/sub", strlen("sdk/Test/1/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - // Re-initialize Rx Tx Buffer - ResetTLSBuffer(); - - // Now provide another message from a different sub topic - IOT_DEBUG("[Matching '+'] Checking second sub topic message, with '+' in the middle...\n"); - snprintf(expectedCallbackString, 100, "New message: 2/sub, Pluskey"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/2/sub", strlen("sdk/Test/2/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:21 - Subscribe with '+' as wildcard success \n"); -} -/* C:22 - Subscribe with '+' as last character in topic name, Success */ -TEST_C(SubscribeTests, subscribeTopicPluskeyComesLastSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: foo1, Pluskey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:22 - Subscribe with '+' as last character in topic name, Success \n"); - - // Set up the subscribed topic, with '+' comes the last - setTLSRxBufferForSuback("sdk/Test/+", strlen("sdk/Test/+"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/+", strlen("sdk/Test/+"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // Now provide a published message from a single layer of sub directroy - IOT_DEBUG("[Matching '+'] Checking first sub topic message, with '+' be the last...\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo1", strlen("sdk/Test/foo1"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - // Re-initialize Rx Tx Buffer - ResetTLSBuffer(); - - // Now provide a published message from another single layer of sub directroy - IOT_DEBUG("[Matching '+'] Checking second sub topic message, with '+' be the last...\n"); - snprintf(expectedCallbackString, 100, "New message: foo2, Pluskey"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo2", strlen("sdk/Test/foo2"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:22 - Subscribe with '+' as last character in topic name, Success \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp deleted file mode 100644 index bedea1f38..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_unsubscribe.cpp - * @brief IoT Client Unit Testing - Unsubscribe API Tests - */ - -#include -#include - -TEST_GROUP_C(UnsubscribeTests){ - TEST_GROUP_C_SETUP_WRAPPER(UnsubscribeTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(UnsubscribeTests) -}; - -/* D:1 - Unsubscribe with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNullClient) -/* D:2 - Unsubscribe with Null/empty topic name */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNullTopic) -/* D:3 - Unsubscribe, Not subscribed to topic */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNotSubscribed) - -/* D:4 - Unsubscribe, QoS0, No response, timeout */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0FailureOnNoUnsuback) -/* D:5 - Unsubscribe, QoS1, No response, timeout */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1FailureOnNoUnsuback) - -/* D:6 - Unsubscribe, QoS0, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0WithUnsubackSuccess) -/* D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0WithDelayedUnsubackSuccess) -/* D:8 - Unsubscribe, QoS1, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1WithUnsubackSuccess) -/* D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1WithDelayedUnsubackSuccess) - -/* D:10 - Unsubscribe, success, message on topic ignored */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, MsgAfterUnsubscribe) -/* D:11 - Unsubscribe after max topics reached */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, MaxTopicsSubscription) -/* D:12 - Repeated Subscribe and Unsubscribe */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, RepeatedSubUnSub) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c deleted file mode 100644 index a4d245378..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c +++ /dev/null @@ -1,343 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_unsubscribe_helper.c - * @brief IoT Client Unit Testing - Unsubscribe API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static AWS_IoT_Client iotClient; -static char CallbackMsgString[100]; -char cPayload[100]; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(UnsubscribeTests) { - IoT_Error_t rc = SUCCESS; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(UnsubscribeTests) { } - -/* D:1 - Unsubscribe with Null/empty client instance */ -TEST_C(UnsubscribeTests, UnsubscribeNullClient) { - IoT_Error_t rc = aws_iot_mqtt_unsubscribe(NULL, "sdkTest/Sub", 11); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* D:2 - Unsubscribe with Null/empty topic name */ -TEST_C(UnsubscribeTests, UnsubscribeNullTopic) { - IoT_Error_t rc = aws_iot_mqtt_unsubscribe(&iotClient, NULL, 11); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* D:3 - Unsubscribe, Not subscribed to topic */ -TEST_C(UnsubscribeTests, UnsubscribeNotSubscribed) { - IoT_Error_t rc = aws_iot_mqtt_unsubscribe(&iotClient, "sdkTest/Sub", 11); - CHECK_EQUAL_C_INT(FAILURE, rc); -} - -/* D:4 - Unsubscribe, QoS0, No response, timeout */ -TEST_C(UnsubscribeTests, unsubscribeQoS0FailureOnNoUnsuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:4 - Unsubscribe, QoS0, No response, timeout \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - } - - IOT_DEBUG("-->Success - D:4 - Unsubscribe, QoS0, No response, timeout \n"); -} - -/* D:5 - Unsubscribe, QoS1, No response, timeout */ -TEST_C(UnsubscribeTests, unsubscribeQoS1FailureOnNoUnsuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:5 - Unsubscribe, QoS1, No response, timeout \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - } - - IOT_DEBUG("-->Success - D:5 - Unsubscribe, QoS1, No response, timeout \n"); -} - -/* D:6 - Unsubscribe, QoS0, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS0WithUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:6 - Unsubscribe, QoS0, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:6 - Unsubscribe, QoS0, success \n"); -} - -/* D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS0WithDelayedUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success \n"); -} - -/* D:8 - Unsubscribe, QoS1, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS1WithUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:8 - Unsubscribe, QoS1, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:8 - Unsubscribe, QoS1, success \n"); -} - -/* D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS1WithDelayedUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success \n"); -} - -/* D:10 - Unsubscribe, success, message on topic ignored - * 1. Subscribe to topic 1 - * 2. Send message and receive it - * 3. Unsubscribe to topic 1 - * 4. Should not receive message - */ -TEST_C(UnsubscribeTests, MsgAfterUnsubscribe) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100]; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:10 - Unsubscribe, success, message on topic ignored \n"); - - // 1. - setTLSRxBufferForSuback("topic1", 6, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "topic1", 6, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // 2. - snprintf(expectedCallbackString, 100, "Message for topic1"); - setTLSRxBufferWithMsgOnSubscribedTopic("topic1", 6, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - //3. - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, "topic1", 6); - CHECK_EQUAL_C_INT(SUCCESS, rc); - //reset the string - snprintf(CallbackMsgString, 100, " "); - - // 4. - // Have a new message published to that topic coming in - snprintf(expectedCallbackString, 100, "Message after unsubscribe"); - setTLSRxBufferWithMsgOnSubscribedTopic("topic1", 6, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // No new msg was received - CHECK_EQUAL_C_STRING(" ", CallbackMsgString); - - IOT_DEBUG("-->Success - D:10 - Unsubscribe, success, message on topic ignored \n"); -} - -/* D:11 - Unsubscribe after max topics reached - * 1. Subscribe to max topics + 1 fail for last subscription - * 2. Unsubscribe from one topic - * 3. Subscribe again and should have no error - * 4. Receive msg test - last subscribed topic - */ -TEST_C(UnsubscribeTests, MaxTopicsSubscription) { - IoT_Error_t rc = SUCCESS; - int i = 0; - char topics[AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS + 1][10]; - char expectedCallbackString[] = "Message after subscribe - topic[i]"; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:11 - Unsubscribe after max topics reached \n"); - - // 1. - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; i++) { - snprintf(topics[i], 10, "topic-%d", i); - setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - snprintf(topics[i], 10, "topic-%d", i); - setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc); - - // 2. - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, topics[i - 1], (uint16_t) strlen(topics[i - 1])); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //3. - setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //4. - setTLSRxBufferWithMsgOnSubscribedTopic(topics[i], strlen(topics[i]), QOS1, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - IOT_DEBUG("-->Success - D:11 - Unsubscribe after max topics reached \n"); -} - -/* D:12 - Repeated Subscribe and Unsubscribe - * 1. subscribe and unsubscribe for more than the max subscribed topic - * 2. ensure every time the subscribed topic msg is received - */ -TEST_C(UnsubscribeTests, RepeatedSubUnSub) { - IoT_Error_t rc = SUCCESS; - int i = 0; - char expectedCallbackString[100]; - char topics[3 * AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS][10]; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:12 - Repeated Subscribe and Unsubscribe \n"); - - - for(i = 0; i < 3 * AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; i++) { - //1. - snprintf(topics[i], 10, "topic-%d", i); - setTLSRxBufferForSuback(topics[i], 10, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], 10, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - snprintf(expectedCallbackString, 10, "message##%d", i); - testPubMsgParams.payload = (void *) expectedCallbackString; - testPubMsgParams.payloadLen = strlen(expectedCallbackString); - setTLSRxBufferWithMsgOnSubscribedTopic(topics[i], strlen(topics[i]), QOS1, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - //2. - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i])); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:12 - Repeated Subscribe and Unsubscribe \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp deleted file mode 100644 index afca69c5c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_yield.cpp - * @brief IoT Client Unit Testing - Yield API Tests - */ - -#include -#include - -TEST_GROUP_C(YieldTests){ - TEST_GROUP_C_SETUP_WRAPPER(YieldTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(YieldTests) -}; - -/* G:1 - Yield with Null/empty Client Instance */ -TEST_GROUP_C_WRAPPER(YieldTests, NullClientYield) -/* G:2 - Yield with zero yield timeout */ -TEST_GROUP_C_WRAPPER(YieldTests, ZeroTimeoutYield) -/* G:3 - Yield, network disconnected, never connected */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldNetworkDisconnectedNeverConnected) -/* G:4 - Yield, network disconnected, disconnected manually */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldNetworkDisconnectedDisconnectedManually) -/* G:5 - Yield, network connected, yield called while in subscribe application callback */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldInSubscribeCallback) -/* G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectNoAutoReconnect) - -/* G:7 - Yield, network connected, no incoming messages */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldSuccessNoMessages) -/* G:8 - Yield, network connected, ping request/response */ -TEST_GROUP_C_WRAPPER(YieldTests, PingRequestPingResponse) - -/* G:9 - Yield, disconnected, Auto-reconnect timed-out */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectAutoReconnectTimeout) -/* G:10 - Yield, disconnected, Auto-reconnect successful */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectAutoReconnectSuccess) -/* G:11 - Yield, disconnected, Manual reconnect */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectManualAutoReconnect) -/* G:12 - Yield, resubscribe to all topics on reconnect */ -TEST_GROUP_C_WRAPPER(YieldTests, resubscribeSuccessfulReconnect) - -/* G:13 - Delayed Ping response. */ -TEST_GROUP_C_WRAPPER(YieldTests, delayedPingResponse) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c deleted file mode 100644 index bc4aa0523..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c +++ /dev/null @@ -1,493 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_yield_helper.c - * @brief IoT Client Unit Testing - Yield API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static AWS_IoT_Client iotClient; -static IoT_Publish_Message_Params testPubMsgParams; - -static ConnectBufferProofread prfrdParams; -static char CallbackMsgString[100]; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static bool dcHandlerInvoked = false; - -static void iot_tests_unit_acr_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char *tmp = params->payload; - unsigned int i; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - for(i = 0; i < params->payloadLen; i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -static void iot_tests_unit_yield_test_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char *tmp = params->payload; - unsigned int i; - IoT_Error_t rc = SUCCESS; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - rc = aws_iot_mqtt_yield(pClient, 1000); - CHECK_EQUAL_C_INT(MQTT_CLIENT_NOT_IDLE_ERROR, rc); - - for(i = 0; i < params->payloadLen; i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -void iot_tests_unit_disconnect_handler(AWS_IoT_Client *pClient, void *disconParam) { - IOT_UNUSED(pClient); - IOT_UNUSED(disconParam); - dcHandlerInvoked = true; -} - - -TEST_GROUP_C_SETUP(YieldTests) { - IoT_Error_t rc = SUCCESS; - dcHandlerInvoked = false; - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, iot_tests_unit_disconnect_handler); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - - ConnectMQTTParamsSetup_Detailed(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID), - QOS1, false, true, "willTopicName", (uint16_t) strlen("willTopicName"), "willMsg", - (uint16_t) strlen("willMsg"), NULL, 0, NULL, 0); - connectParams.keepAliveIntervalInSec = 5; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(YieldTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -/* G:1 - Yield with Null/empty Client Instance */ -TEST_C(YieldTests, NullClientYield) { - IoT_Error_t rc = aws_iot_mqtt_yield(NULL, 1000); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* G:2 - Yield with zero yield timeout */ - -TEST_C(YieldTests, ZeroTimeoutYield) { - IoT_Error_t rc = aws_iot_mqtt_yield(&iotClient, 0); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} -/* G:3 - Yield, network disconnected, never connected */ - -TEST_C(YieldTests, YieldNetworkDisconnectedNeverConnected) { - AWS_IoT_Client tempIotClient; - IoT_Error_t rc; - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, iot_tests_unit_disconnect_handler); - rc = aws_iot_mqtt_init(&tempIotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - rc = aws_iot_mqtt_yield(&tempIotClient, 1000); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); -} - -/* G:4 - Yield, network disconnected, disconnected manually */ -TEST_C(YieldTests, YieldNetworkDisconnectedDisconnectedManually) { - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(NETWORK_MANUALLY_DISCONNECTED, rc); -} - -/* G:5 - Yield, network connected, yield called while in subscribe application callback */ -TEST_C(YieldTests, YieldInSubscribeCallback) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "0xA5A5A3"; - - IOT_DEBUG("-->Running Yield Tests - G:5 - Yield, network connected, yield called while in subscribe application callback \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, - iot_tests_unit_yield_test_subscribe_callback_handler, NULL); - if(SUCCESS == rc) { - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - } - - IOT_DEBUG("-->Success - G:5 - Yield, network connected, yield called while in subscribe application callback \n"); -} - -/* G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled */ -TEST_C(YieldTests, disconnectNoAutoReconnect) { - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("-->Running Yield Tests - G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient)); - - /* Disable Autoreconnect, then let ping request time out and call yield */ - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - sleep((uint16_t)(iotClient.clientData.keepAliveInterval)); - - ResetTLSBuffer(); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - CHECK_EQUAL_C_INT(0, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled \n"); -} - -/* G:7 - Yield, network connected, no incoming messages */ -TEST_C(YieldTests, YieldSuccessNoMessages) { - IoT_Error_t rc; - int i; - - IOT_DEBUG("-->Running Yield Tests - G:7 - Yield, network connected, no incoming messages \n"); - - for(i = 0; i < 100; i++) { - CallbackMsgString[i] = 'x'; - } - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - /* Check no messages were received */ - for(i = 0; i < 100; i++) { - if('x' != CallbackMsgString[i]) { - rc = FAILURE; - } - } - } - - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - G:7 - Yield, network connected, no incoming messages \n"); -} - -/* G:8 - Yield, network connected, ping request/response */ -TEST_C(YieldTests, PingRequestPingResponse) { - IoT_Error_t rc = SUCCESS; - int i = 0; - int j = 0; - int attempt = 3; - - IOT_DEBUG("-->Running Yield Tests - G:8 - Yield, network connected, ping request/response \n"); - IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", iotClient.clientData.keepAliveInterval); - - for(i = 0; i < attempt; i++) { - IOT_DEBUG("[Round_%d/Total_%d] Waiting for %d sec...\n", i + 1, attempt, iotClient.clientData.keepAliveInterval); - /* Set TLS buffer for ping response */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - - for(j = 0; j <= iotClient.clientData.keepAliveInterval; j++) { - sleep(1); - IOT_DEBUG("[Waited %d secs]", j + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - /* Check whether ping was processed correctly and new Ping request was generated */ - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq()); - } - - IOT_DEBUG("-->Success - G:8 - Yield, network connected, ping request/response \n"); -} - -/* G:9 - Yield, disconnected, Auto-reconnect timed-out */ -TEST_C(YieldTests, disconnectAutoReconnectTimeout) { - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("-->Running Yield Tests - G:9 - Yield, disconnected, Auto-reconnect timed-out \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient)); - - ResetTLSBuffer(); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - CHECK_EQUAL_C_INT(0, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:9 - Yield, disconnected, Auto-reconnect timed-out \n"); -} - -/* G:10 - Yield, disconnected, Auto-reconnect successful */ -TEST_C(YieldTests, disconnectAutoReconnectSuccess) { - IoT_Error_t rc = FAILURE; - unsigned char *currPayload = NULL; - - IOT_DEBUG("-->Running Yield Tests - G:10 - Yield, disconnected, Auto-reconnect successful \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - - sleep(2); /* Default min reconnect delay is 1 sec */ - printf("\nWakeup"); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer); - CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams)); - CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload)); - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:10 - Yield, disconnected, Auto-reconnect successful \n"); -} - -/* G:11 - Yield, disconnected, Manual reconnect */ -TEST_C(YieldTests, disconnectManualAutoReconnect) { - IoT_Error_t rc = FAILURE; - unsigned char *currPayload = NULL; - - IOT_DEBUG("-->Running Yield Tests - G:11 - Yield, disconnected, Manual reconnect \n"); - - CHECK_C(aws_iot_mqtt_is_client_connected(&iotClient)); - - /* Disable Autoreconnect, then let ping request time out and call yield */ - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - CHECK_C(!aws_iot_is_autoreconnect_enabled(&iotClient)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - CHECK_C(!aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - dcHandlerInvoked = false; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_attempt_reconnect(&iotClient); - CHECK_EQUAL_C_INT(NETWORK_RECONNECTED, rc); - - currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer); - CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams)); - CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload)); - CHECK_C(aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(false, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:11 - Yield, disconnected, Manual reconnect \n"); -} - -/* G:12 - Yield, resubscribe to all topics on reconnect */ -TEST_C(YieldTests, resubscribeSuccessfulReconnect) { - IoT_Error_t rc = FAILURE; - char cPayload[100]; - bool connected = false; - bool autoReconnectEnabled = false; - char expectedCallbackString[100]; - - IOT_DEBUG("-->Running Yield Tests - G:12 - Yield, resubscribe to all topics on reconnect \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(1, connected); - - ResetTLSBuffer(); - - /* Subscribe to a topic */ - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_tests_unit_acr_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - - /* Check subscribe */ - snprintf(expectedCallbackString, 100, "Message for %s", subTopic); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - ResetTLSBuffer(); - - autoReconnectEnabled = aws_iot_is_autoreconnect_enabled(&iotClient); - CHECK_EQUAL_C_INT(1, autoReconnectEnabled); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - - sleep(2); /* Default min reconnect delay is 1 sec */ - - ResetTLSBuffer(); - setTLSRxBufferForConnackAndSuback(&connectParams, 0, subTopic, subTopicLen, QOS1); - - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - /* Test if reconnect worked */ - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(true, connected); - - ResetTLSBuffer(); - - /* Check subscribe */ - snprintf(expectedCallbackString, 100, "Message for %s after resub", subTopic); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:12 - Yield, resubscribe to all topics on reconnect \n"); -} - -/* G:13 - Delayed Ping response. */ -TEST_C(YieldTests, delayedPingResponse) -{ - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("-->Running Yield Tests - G:13 - Delayed Ping response. \n"); - - ResetTLSBuffer(); - - /* Sleep for keep alive interval to allow the first ping to be sent out. */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Sleep for half of the keep alive interval to simulate a delayed ping - * response. */ - sleep(iotClient.clientData.keepAliveInterval / 2); - - /* Receive the delayed ping response. */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - /* Sleep for half of the keep alive interval - at this time a ping request - * must be sent out because a full keep alive interval has passed since we - * last sent a ping request. This ensures that the timer which tracks when - * to send a ping request does not incorrectly get reset upon receipt of a - * ping response. +1 is done to ensure that we don't hit boundry condition - * where timer does not expire because the time elasped is exactly equal to - * the keep alive interval (as opposed to more than that). */ - sleep(iotClient.clientData.keepAliveInterval / 2 + 1); - ResetTLSBuffer(); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - IOT_DEBUG("-->Success - G:13 - Delayed Ping response. \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c deleted file mode 100644 index 720202a5f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c +++ /dev/null @@ -1,223 +0,0 @@ -#include -#include -#include - -#include "network_interface.h" -#include "aws_iot_tests_unit_mock_tls_params.h" - - -void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - pNetwork->tlsConnectParams.DestinationPort = destinationPort; - pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; - pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; - pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; - pNetwork->tlsConnectParams.timeout_ms = timeout_ms; - pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; -} - -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, - pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); - - pNetwork->connect = iot_tls_connect; - pNetwork->read = iot_tls_read; - pNetwork->write = iot_tls_write; - pNetwork->disconnect = iot_tls_disconnect; - pNetwork->isConnected = iot_tls_is_connected; - pNetwork->destroy = iot_tls_destroy; - - return SUCCESS; -} - -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { - IOT_UNUSED(pNetwork); - - if(NULL != params) { - _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, - params->pDevicePrivateKeyLocation, params->pDestinationURL, params->DestinationPort, - params->timeout_ms, params->ServerVerificationFlag); - } - - if(NULL != invalidEndpointFilter && 0 == strcmp(invalidEndpointFilter, pNetwork->tlsConnectParams.pDestinationURL)) { - return NETWORK_ERR_NET_UNKNOWN_HOST; - } - - if(invalidPortFilter == pNetwork->tlsConnectParams.DestinationPort) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - - if(NULL != invalidRootCAPathFilter && 0 == strcmp(invalidRootCAPathFilter, pNetwork->tlsConnectParams.pRootCALocation)) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - - if(NULL != invalidCertPathFilter && 0 == strcmp(invalidCertPathFilter, pNetwork->tlsConnectParams.pDeviceCertLocation)) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - - if(NULL != invalidPrivKeyPathFilter && 0 == strcmp(invalidPrivKeyPathFilter, pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - return SUCCESS; -} - -IoT_Error_t iot_tls_is_connected(Network *pNetwork) { - IOT_UNUSED(pNetwork); - - /* Use this to add implementation which can check for physical layer disconnect */ - return NETWORK_PHYSICAL_LAYER_CONNECTED; -} - -static size_t iot_tls_mqtt_read_variable_length_int(const unsigned char *buffer, size_t startPos) { - size_t result = 0; - size_t pos = startPos; - size_t multiplier = 1; - do { - result = (buffer[pos] & 0x7f) * multiplier; - multiplier *= 0x80; - pos++; - } while ((buffer[pos - 1] & 0x80) && pos - startPos < 4); - - return result; -} - -static size_t iot_tls_mqtt_get_end_of_variable_length_int(const unsigned char *buffer, size_t startPos) { - size_t pos = startPos; - while ((buffer[pos] & 0x80) && pos - startPos < 3) pos++; - pos++; - - return pos; -} - -static uint16_t iot_tls_mqtt_get_fixed_uint16_from_message(const unsigned char *msgBuffer, size_t startPos) { - uint8_t firstByte = (uint8_t)(msgBuffer[startPos]); - uint8_t secondByte = (uint8_t)(msgBuffer[startPos + 1]); - return (uint16_t) (secondByte + (256 * firstByte)); -} - -static uint16_t iot_tls_mqtt_copy_string_from_message(char *dest, const unsigned char *msgBuffer, size_t startPos) { - uint16_t length = iot_tls_mqtt_get_fixed_uint16_from_message(msgBuffer, startPos); - - snprintf(dest, length + 1u, "%s", &(msgBuffer[startPos + 2])); // Added one for null character - return length; -} - -IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) { - size_t i = 0; - uint8_t firstPacketByte; - size_t mqttPacketLength; - size_t variableHeaderStart; - IoT_Error_t status = SUCCESS; - IOT_UNUSED(pNetwork); - IOT_UNUSED(timer); - - if(TxBuffer.mockedError != SUCCESS ) { - status = TxBuffer.mockedError; - - /* Clear the error before returning. */ - TxBuffer.mockedError = SUCCESS; - - return status; - } - - for(i = 0; (i < len) && left_ms(timer) > 0; i++) { - TxBuffer.pBuffer[i] = pMsg[i]; - } - TxBuffer.len = len; - *written_len = len; - - mqttPacketLength = iot_tls_mqtt_read_variable_length_int(TxBuffer.pBuffer, 1); - variableHeaderStart = iot_tls_mqtt_get_end_of_variable_length_int(TxBuffer.pBuffer, 1); - - firstPacketByte = TxBuffer.pBuffer[0]; - /* Save last two subscribed topics */ - if((firstPacketByte == 0x82 ? true : false)) { - snprintf(SecondLastSubscribeMessage, lastSubscribeMsgLen + 1u, "%s", LastSubscribeMessage); - secondLastSubscribeMsgLen = lastSubscribeMsgLen; - - lastSubscribeMsgLen = iot_tls_mqtt_copy_string_from_message( - LastSubscribeMessage, TxBuffer.pBuffer, variableHeaderStart + 2); - } else if (firstPacketByte == 0xA2) { - lastUnsubscribeMsgLen = iot_tls_mqtt_copy_string_from_message( - LastUnsubscribeMessage, TxBuffer.pBuffer, variableHeaderStart + 2); - } else if ((firstPacketByte & 0x30) == 0x30) { - QoS qos = (QoS) (firstPacketByte & 0x6 >> 1); - - lastPublishMessageTopicLen = - iot_tls_mqtt_copy_string_from_message(LastPublishMessageTopic, TxBuffer.pBuffer, variableHeaderStart); - - size_t payloadStart = variableHeaderStart + 2 + lastPublishMessageTopicLen; - - if (qos > QOS0) { - payloadStart += 2; - } - - lastPublishMessagePayloadLen = mqttPacketLength - payloadStart + 2; /* + 2 as the first two bytes don't count towards the length */ - memcpy(LastPublishMessagePayload, TxBuffer.pBuffer + payloadStart, lastPublishMessagePayloadLen); - LastPublishMessagePayload[lastPublishMessagePayloadLen] = 0; - } - - return status; -} - -static unsigned char isTimerExpired(struct timeval target_time) { - unsigned char ret_val = 0; - struct timeval now, result; - - if(target_time.tv_sec != 0 || target_time.tv_usec != 0) { - gettimeofday(&now, NULL); - timersub(&(target_time), &now, &result); - if(result.tv_sec < 0 || (result.tv_sec == 0 && result.tv_usec <= 0)) { - ret_val = 1; - } - } else { - ret_val = 1; - } - return ret_val; -} - -IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *pTimer, size_t *read_len) { - IoT_Error_t status = SUCCESS; - - IOT_UNUSED(pNetwork); - IOT_UNUSED(pTimer); - - if(RxBuffer.mockedError != SUCCESS) { - status = RxBuffer.mockedError; - - /* Clear the error before returning. */ - RxBuffer.mockedError = SUCCESS; - - return status; - } - - if(RxIndex > TLSMaxBufferSize - 1) { - RxIndex = TLSMaxBufferSize - 1; - } - - if(RxBuffer.len <= RxIndex || !isTimerExpired(RxBuffer.expiry_time)) { - return NETWORK_SSL_NOTHING_TO_READ; - } - - if((false == RxBuffer.NoMsgFlag) && (RxIndex < RxBuffer.len)) { - memcpy(pMsg, &(RxBuffer.pBuffer[RxIndex]), len); - RxIndex += len; - *read_len = len; - } - - return status; -} - -IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - IOT_UNUSED(pNetwork); - return SUCCESS; -} - -IoT_Error_t iot_tls_destroy(Network *pNetwork) { - IOT_UNUSED(pNetwork); - return SUCCESS; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c deleted file mode 100644 index c816a7d2d..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_mock_tls_params.c - * @brief IoT Client Unit Testing Mock TLS Params - */ - -#include "aws_iot_tests_unit_mock_tls_params.h" - -unsigned char RxBuf[TLSMaxBufferSize]; -unsigned char TxBuf[TLSMaxBufferSize]; -char LastSubscribeMessage[TLSMaxBufferSize]; -size_t lastSubscribeMsgLen; -char SecondLastSubscribeMessage[TLSMaxBufferSize]; -size_t secondLastSubscribeMsgLen; - -char LastUnsubscribeMessage[TLSMaxBufferSize]; -size_t lastUnsubscribeMsgLen; - -char LastPublishMessageTopic[TLSMaxBufferSize]; -size_t lastPublishMessageTopicLen; -char LastPublishMessagePayload[TLSMaxBufferSize]; -size_t lastPublishMessagePayloadLen; - -TlsBuffer RxBuffer = {.pBuffer = RxBuf,.len = 512, .NoMsgFlag=1, .expiry_time = {0, 0}, .BufMaxSize = TLSMaxBufferSize, .mockedError = SUCCESS}; -TlsBuffer TxBuffer = {.pBuffer = TxBuf,.len = 512, .NoMsgFlag=1, .expiry_time = {0, 0}, .BufMaxSize = TLSMaxBufferSize, .mockedError = SUCCESS}; - -size_t RxIndex = 0; - -char *invalidEndpointFilter; -char *invalidRootCAPathFilter; -char *invalidCertPathFilter; -char *invalidPrivKeyPathFilter; -uint16_t invalidPortFilter; diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h deleted file mode 100644 index 20262d5bd..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file is distributed -* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -* express or implied. See the License for the specific language governing -* permissions and limitations under the License. -*/ - -/** - * @file aws_iot_tests_unit_mock_tls_params.h - * @brief IoT Client Unit Testing Mock TLS Params - */ - -#ifndef UNITTESTS_MOCKS_TLS_PARAMS_H_ -#define UNITTESTS_MOCKS_TLS_PARAMS_H_ - -#include -#include -#include -#include -#include - -#define TLSMaxBufferSize 2560 -#define NO_MSG_LENGTH_MENTIONED -1 - -typedef struct { - unsigned char *pBuffer; - size_t len; - bool NoMsgFlag; - struct timeval expiry_time; - size_t BufMaxSize; - IoT_Error_t mockedError; -} TlsBuffer; - - -extern TlsBuffer RxBuffer; -extern TlsBuffer TxBuffer; - -extern size_t RxIndex; -extern unsigned char RxBuf[TLSMaxBufferSize]; -extern unsigned char TxBuf[TLSMaxBufferSize]; -extern char LastSubscribeMessage[TLSMaxBufferSize]; -extern size_t lastSubscribeMsgLen; -extern char SecondLastSubscribeMessage[TLSMaxBufferSize]; -extern size_t secondLastSubscribeMsgLen; - -extern char LastUnsubscribeMessage[TLSMaxBufferSize]; -extern size_t lastUnsubscribeMsgLen; - -extern char LastPublishMessageTopic[TLSMaxBufferSize]; -extern size_t lastPublishMessageTopicLen; -extern char LastPublishMessagePayload[TLSMaxBufferSize]; -extern size_t lastPublishMessagePayloadLen; - -extern char hostAddress[512]; -extern uint16_t port; -extern uint32_t handshakeTimeout_ms; - -extern char *invalidEndpointFilter; -extern char *invalidRootCAPathFilter; -extern char *invalidCertPathFilter; -extern char *invalidPrivKeyPathFilter; -extern uint16_t invalidPortFilter; - -#endif /* UNITTESTS_MOCKS_TLS_PARAMS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h deleted file mode 100644 index 1bbec842f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by chaurah on 3/22/16. -// - -#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct _TLSDataParams { - uint32_t flags; -}TLSDataParams; - -#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/component.mk b/examples/espidf-aws-iot/components/esp-aws-iot/component.mk deleted file mode 100644 index b9a705a27..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/component.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -# Component Makefile -# - -COMPONENT_ADD_INCLUDEDIRS := port/include aws-iot-device-sdk-embedded-C/include - -COMPONENT_SRCDIRS := aws-iot-device-sdk-embedded-C/src port - -# Check the submodule is initialised -COMPONENT_SUBMODULES := aws-iot-device-sdk-embedded-C diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/README.md deleted file mode 100644 index 4a898d1df..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# Amazon Web Services IoT Examples - -These examples are adaptations of some of the [AWS IoT C SDK](https://github.com/aws/aws-iot-device-sdk-embedded-C) examples. - -The provisioning/configuration steps for these examples are the same, and are given in this README. - -This README also contains some troubleshooting information for common problems found when connecting to AWS IoT. - -# Provisioning/Configuration - -There are some additional steps that need to be run before you can build this example. - -The [Getting Started section of the AWS IoT Developer Guide](http://docs.aws.amazon.com/iot/latest/developerguide/iot-gs.html) lays out the steps to get started with AWS IoT. - -To build and use this example, follow all the AWS IoT Getting Started steps from the beginning ("Sign in to the AWS Iot Console") up until "Configuring Your Device". For configuring the device, these are the steps: - -# Authentication (Based on X.509 certificates) - -### Device Authentication - -AWS IoT can use AWS IoT-generated certificates or certificates signed by a CA certificate for device authentication. To use a certificate that is not created by AWS IoT, you must register a CA certificate. All device certificates must be signed by the CA certificate you register. Please refer to guide at https://docs.aws.amazon.com/iot/latest/developerguide/device-certs-your-own.html for step-by-step instructions to register custom X.509 certificates. - -### Server Authentication - -Server certificates allow devices to verify that they're communicating with AWS IoT and not another server impersonating AWS IoT. By default [Amazon Root CA 1](https://www.amazontrust.com/repository/AmazonRootCA1.pem) (signed by Amazon Trust Services Endpoints CA) is embedded in applications, for more information please refer to https://docs.aws.amazon.com/iot/latest/developerguide/managing-device-certs.html#server-authentication - -## Configuring Your Device - -### Installing Private Key & Certificate - -As part of creating a device certificate, you downloaded a Private Key (`xxx-private.pem.key`) and a Certificate file (`xxx-certificate.pem.crt`). These keys need to be loaded by the ESP32 to identify itself. - -There are currently two options for how to load the key & cert. - -* Embed the files into the app binary (default) -* Load the files from SD card - -### Option 1: Embedded Key & Cert into App Binary - -Copy the `.pem.key` and `.pem.crt` files to the `main/certs` subdirectory of the example. Rename them by removing the device-specific prefix - the new names are `private.pem.key` and `certificate.pem.crt`. - -As these files are bound to your AWS IoT account, take care not to accidentally commit them to public source control. In a commercial IoT device these files would be flashed to the device via a provisioning step, but for these examples they are compiled in. - -### Option 2: Loading Key & Cert from SD Card - -The alternative to embedding the key and certificate is to load them from a FAT filesystem on an SD card. - -Before loading data from SD, format your SD card as FAT and run the `examples/storage/sd_card` example on it to verify that it's working as expected in ESP-IDF. This helps cut down the possible causes of errors in the more complex AWS IoT examples! - -Run `make menuconfig`, navigate to "Example Configuration" and change "AWS IoT Certificate Source" to "Load from SD card". - -Three new prompts will appear for filenames for the device key, device certificate and root CA certificate path. These paths start with `/sdcard/` as this is where the example mounts the (FAT formatted) SD card. - -Copy the certificate and key files to the SD card, and make sure the file names match the names given in the example configuration (either rename the files, or change the config). For the Root CA certificate file (which is not device-specific), you can find the file in the `main/certs` directory or download it from AWS. - -*Note: By default, esp-idf's FATFS support only allows 8.3 character filenames. However, the AWS IoT examples pre-configure the sdkconfig to enable long filenames. If you're setting up your projects, you will probably want to enable these options as well (under Component Config -> FAT Filesystem Support). You can also consider configure the FAT filesystem for read-only support, if you don't need to write to the SD card.* - -## Find & Set AWS Endpoint Hostname - -Your AWS IoT account has a unique endpoint hostname to connect to. To find it, open the AWS IoT Console and click the "Settings" button on the bottom left side. The endpoint hostname is shown under the "Custom Endpoint" heading on this page. - -Run `make menuconfig` and navigate to `Component Config` -> `Amazon Web Service IoT Config` -> `AWS IoT MQTT Hostname`. Enter the host name here. - -*Note: It may seem odd that you have to configure parts of the AWS settings under Component Config and some under Example Configuration.* The IoT MQTT Hostname and Port are set as part of the component because when using the AWS IoT SDK's Thing Shadow API (in examples or in other projects) the `ShadowInitParametersDefault` structure means the Thing Shadow connection will default to that host & port. You're not forced to use these config values in your own projects, you can set the values in code via the AWS IoT SDK's init parameter structures - `ShadowInitParameters_t` for Thing Shadow API or `IoT_Client_Init_Params` for MQTT API. - -### (Optional) Set Client ID - -Run `make menuconfig`. Under `Example Configuration`, set the `AWS IoT Client ID` to a unique value. - -The Client ID is used in the MQTT protocol used to send messages to/from AWS IoT. AWS IoT requires that each connected device within a single AWS account uses a unique Client ID. Other than this restriction, the Client ID can be any value that you like. The example default should be fine if you're only connecting one ESP32 at a time. - -In a production IoT app this ID would be set dynamically, but for these examples it is compiled in via menuconfig. - -### (Optional) Locally Check The Root Certificate - -The Root CA certificate provides a root-of-trust when the ESP32 connects to AWS IoT. We have supplied the root CA certificate already (in PEM format) in the file `main/certs/aws-root-ca.pem`. - -If you want to locally verify that this Root CA certificate hasn't changed, you can run the following command against your AWS MQTT Host: - -``` -openssl s_client -showcerts -connect hostname:8883 < /dev/null -``` - -(Replace hostname with your AWS MQTT endpoint host.) The Root CA certificate is the last certificate in the list of certificates printed. You can copy-paste this in place of the existing `aws-root-ca.pem` file. - - -# Troubleshooting - -## Tips - -* Raise the ESP debug log level to Debug in order to see messages about the connection to AWS, certificate contents, etc. - -* Enable mbedTLS debugging (under Components -> mbedTLS -> mbedTLS Debug) in order to see even more low-level debug output from the mbedTLS layer. - -* To create a successful AWS IoT connection, the following factors must all be present: - - Endpoint hostname is correct for your AWS account. - - Certificate & private key are both attached to correct Thing in AWS IoT Console. - - Certificate is activated. - - Policy is attached to the Certificate in AWS IoT Console. - - Policy contains sufficient permissions to authorize AWS IoT connection. - -## TLS connection fails - -If connecting fails entirely (handshake doesn't complete), this usually indicates a problem with certification configuration. The error usually looks like this: - -``` -aws_iot: failed! mbedtls_ssl_handshake returned -0x7780 -``` - -(0x7780 is the mbedTLS error code when the server sends an alert message and closes the connection.) - -* Check your client private key and certificate file match a Certificate registered and **activated** in AWS IoT console. You can find the Certificate in IoT Console in one of two ways, via the Thing or via Certificates: - - To find the Certificate directly, click on "Registry" -> "Security Certificates". Then click on the Certificate itself to view it. - - To find the Certificate via the Thing, click on "Registry" -> "Things", then click on the particular Thing you are using. Click "Certificates" in the sidebar to view all Certificates attached to that Thing. Then click on the Certificate itself to view it. - -Verify the Certificate is activated (when viewing the Certificate, it will say "ACTIVE" or "INACTIVE" near the top under the certificate name). - -If the Certificate appears correct and activated, verify that you are connecting to the correct AWS IoT endpoint (see above.) - -## TLS connection closes immediately - -Sometimes connecting is successful (the handshake completes) but as soon as the client sends its `MQTT CONNECT` message the server sends back a TLS alert and closes the connection, without anything else happening. - -The error returned from AWS IoT is usually -28 (`MQTT_REQUEST_TIMEOUT_ERROR`). You may also see mbedtls error `-0x7780` (server alert), although if this error comes during `mbedtls_ssl_handshake` then it's usually a different problem (see above). - -In the subscribe_publish example, the error may look like this in the log: - -``` -subpub: Error(-28) connecting to (endpoint)... -``` - -In the thing_shadow example, the error may look like this in the log: - -``` -shadow: aws_iot_shadow_connect returned error -28, aborting... -``` - -This error implies the Certificate is recognised, but the Certificate is either missing the correct Thing or the correct Policy attached to it. - -* Check in the AWS IoT console that your certificate is activated and has both a **security policy** and a **Thing** attached to it. You can find this in IoT Console by clicking "Registry" -> "Security Certificates", then click the Certificate. Once viewing the Certificate, you can click the "Policies" and "Things" links in the sidebar. - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/CMakeLists.txt deleted file mode 100644 index a415bf5de..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set (EXTRA_COMPONENT_DIRS "../..") -project(subscribe_publish) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/Makefile deleted file mode 100644 index 798941a9f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := subscribe_publish - -EXTRA_COMPONENT_DIRS := $(realpath ../..) - -include $(IDF_PATH)/make/project.mk - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/README.md deleted file mode 100644 index 031dc72a9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Amazon Web Services IoT MQTT Subscribe/Publish Example - -This is an adaptation of the [AWS IoT C SDK](https://github.com/aws/aws-iot-device-sdk-embedded-C) "subscribe_publish" example for ESP-IDF. - -# Configuration - -See the README.md in the parent directory for information about configuring the AWS IoT examples. - -# Monitoring MQTT Data from the device - -After flashing the example to your ESP32, it should connect to Amazon and start subscribing/publishing MQTT data. - -The example code publishes MQTT data to the topic `test_topic/esp32`. Amazon provides a web interface to subscribe to MQTT topics for testing: - -* On the AWS IoT console, click "MQTT Client" near the top-right. -* Click "Generate Client ID" to generate a random client ID. -* Click "Connect" - -One connection succeeds, you can subscribe to the data published by the ESP32: - -* Click "Subscribe to Topic" -* Enter "Subscription Topic" `test_topic/esp32` -* Click "Subscribe" - -... you should see MQTT data published from the running example. - -To publish data back to the device: - -* Click "Publish to Topic" -* Enter "Publish Topic" `test_topic/esp32` -* Enter a message in the payload field -* Click Publish - -# Important Note - -This example has dependency on `esp-aws-iot` component which is added through `EXTRA_COMPONENT_DIRS` in its `Makefile` or `CMakeLists.txt` (using relative path). Hence if example is moved outside of this repository then this dependency can be resolved by copying `esp_aws_iot` under `components` subdirectory of the example project. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/CMakeLists.txt deleted file mode 100644 index 807ad6ea0..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(COMPONENT_SRCS "subscribe_publish_sample.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - - -register_component() - -if(CONFIG_EXAMPLE_EMBEDDED_CERTS) -target_add_binary_data(${COMPONENT_TARGET} "certs/aws-root-ca.pem" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/private.pem.key" TEXT) -endif() diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/Kconfig.projbuild b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/Kconfig.projbuild deleted file mode 100644 index 96a022a5c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/Kconfig.projbuild +++ /dev/null @@ -1,60 +0,0 @@ -menu "Example Configuration" - - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - - config AWS_EXAMPLE_CLIENT_ID - string "AWS IoT Client ID" - default "myesp32" - help - AWS IoT Client ID for the example. Should be unique for every device. - - choice EXAMPLE_CERT_SOURCE - prompt "AWS IoT Certificate Source" - default EXAMPLE_EMBEDDED_CERTS - help - AWS IoT requires loading of a device-specific certificate and private key, - and a common Root CA Certificate. These can be compiled into the example - app, or they can be loaded via the filesystem from an SD card. - - config EXAMPLE_EMBEDDED_CERTS - bool "Embed into app" - config EXAMPLE_SDCARD_CERTS - bool "Load from SD card" - select EXAMPLE_FILESYSTEM_CERTS - endchoice - - # Currently this is equivalent to EXAMPLE_SDCARD_CERTS, - # however eventually we want to support more filesystem - # sources (SPIFFS, etc.) So this hidden config item - # is selected whenever the item should load from filesystem. - config EXAMPLE_FILESYSTEM_CERTS - bool - - config EXAMPLE_CERTIFICATE_PATH - string "Device Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/certificate.pem.crt" - - config EXAMPLE_PRIVATE_KEY_PATH - string "Device Private Key Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/private.pem.key" - - config EXAMPLE_ROOT_CA_PATH - string "Root CA Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/aws-root-ca.pem" - -endmenu diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/README.md deleted file mode 100644 index d445cc62b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Copy certificate files for AWS IoT SDK example here - -See README.md in main example directory for details. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/aws-root-ca.pem b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/aws-root-ca.pem deleted file mode 100644 index a6f3e92af..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/aws-root-ca.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/component.mk b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/component.mk deleted file mode 100644 index 401de47a5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/component.mk +++ /dev/null @@ -1,14 +0,0 @@ -# -# Main Makefile. This is basically the same as a component makefile. -# - -ifdef CONFIG_EXAMPLE_EMBEDDED_CERTS -# Certificate files. certificate.pem.crt & private.pem.key must be downloaded -# from AWS, see README for details. -COMPONENT_EMBED_TXTFILES := certs/aws-root-ca.pem certs/certificate.pem.crt certs/private.pem.key - -# Print an error if the certificate/key files are missing -$(COMPONENT_PATH)/certs/certificate.pem.crt $(COMPONENT_PATH)/certs/private.pem.key: - @echo "Missing PEM file $@. This file identifies the ESP32 to AWS for the example, see README for details." - exit 1 -endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/subscribe_publish_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/subscribe_publish_sample.c deleted file mode 100644 index c5b48ae8e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/subscribe_publish_sample.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -/** - * @file subscribe_publish_sample.c - * @brief simple MQTT publish and subscribe on the same topic - * - * This example takes the parameters from the build configuration and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "test_topic/esp32" - * - * Some setup is required. See example README for details. - * - */ -#include -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "esp_vfs_fat.h" -#include "driver/sdmmc_host.h" - -#include "nvs.h" -#include "nvs_flash.h" - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -static const char *TAG = "subpub"; - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - - -/* CA Root certificate, device ("Thing") certificate and device - * ("Thing") key. - - Example can be configured one of two ways: - - "Embedded Certs" are loaded from files in "certs/" and embedded into the app binary. - - "Filesystem Certs" are loaded from the filesystem (SD card, etc.) - - See example README for more details. -*/ -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - -extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start"); -extern const uint8_t aws_root_ca_pem_end[] asm("_binary_aws_root_ca_pem_end"); -extern const uint8_t certificate_pem_crt_start[] asm("_binary_certificate_pem_crt_start"); -extern const uint8_t certificate_pem_crt_end[] asm("_binary_certificate_pem_crt_end"); -extern const uint8_t private_pem_key_start[] asm("_binary_private_pem_key_start"); -extern const uint8_t private_pem_key_end[] asm("_binary_private_pem_key_end"); - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - -static const char * DEVICE_CERTIFICATE_PATH = CONFIG_EXAMPLE_CERTIFICATE_PATH; -static const char * DEVICE_PRIVATE_KEY_PATH = CONFIG_EXAMPLE_PRIVATE_KEY_PATH; -static const char * ROOT_CA_PATH = CONFIG_EXAMPLE_ROOT_CA_PATH; - -#else -#error "Invalid method for loading certs" -#endif - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -char HostAddress[255] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -uint32_t port = AWS_IOT_MQTT_PORT; - - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - ESP_LOGI(TAG, "Subscribe callback"); - ESP_LOGI(TAG, "%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *)params->payload); -} - -void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - ESP_LOGW(TAG, "MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - ESP_LOGI(TAG, "Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - ESP_LOGW(TAG, "Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - ESP_LOGW(TAG, "Manual Reconnect Successful"); - } else { - ESP_LOGW(TAG, "Manual Reconnect Failed - %d", rc); - } - } -} - -void aws_iot_task(void *param) { - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - ESP_LOGI(TAG, "AWS IoT SDK Version %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - mqttInitParams.pRootCALocation = (const char *)aws_root_ca_pem_start; - mqttInitParams.pDeviceCertLocation = (const char *)certificate_pem_crt_start; - mqttInitParams.pDevicePrivateKeyLocation = (const char *)private_pem_key_start; - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - mqttInitParams.pRootCALocation = ROOT_CA_PATH; - mqttInitParams.pDeviceCertLocation = DEVICE_CERTIFICATE_PATH; - mqttInitParams.pDevicePrivateKeyLocation = DEVICE_PRIVATE_KEY_PATH; -#endif - - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - -#ifdef CONFIG_EXAMPLE_SDCARD_CERTS - ESP_LOGI(TAG, "Mounting SD card..."); - sdmmc_host_t host = SDMMC_HOST_DEFAULT(); - sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = 3, - }; - sdmmc_card_t* card; - esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount SD card VFAT filesystem. Error: %s", esp_err_to_name(ret)); - abort(); - } -#endif - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "aws_iot_mqtt_init returned error : %d ", rc); - abort(); - } - - /* Wait for WiFI to show as connected */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - /* Client ID is set in the menuconfig of the example */ - connectParams.pClientID = CONFIG_AWS_EXAMPLE_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(CONFIG_AWS_EXAMPLE_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - ESP_LOGI(TAG, "Connecting to AWS..."); - do { - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - vTaskDelay(1000 / portTICK_RATE_MS); - } - } while(SUCCESS != rc); - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Unable to set Auto Reconnect to true - %d", rc); - abort(); - } - - const char *TOPIC = "test_topic/esp32"; - const int TOPIC_LEN = strlen(TOPIC); - - ESP_LOGI(TAG, "Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, TOPIC, TOPIC_LEN, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Error subscribing : %d ", rc); - abort(); - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - ESP_LOGI(TAG, "Stack remaining for task '%s' is %d bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); - vTaskDelay(1000 / portTICK_RATE_MS); - sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS0)", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS0); - - sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS1)", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - ESP_LOGW(TAG, "QOS1 publish ack not received."); - rc = SUCCESS; - } - } - - ESP_LOGE(TAG, "An error occurred in the main loop."); - abort(); -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - - -void app_main() -{ - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); - - initialise_wifi(); - xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 9216, NULL, 5, NULL, 1); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.ci b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.ci deleted file mode 100644 index b59dfb870..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.ci +++ /dev/null @@ -1,2 +0,0 @@ -# For CI build example assuming certificates stored on sdcard -CONFIG_EXAMPLE_SDCARD_CERTS=y diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.defaults b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.defaults deleted file mode 100644 index 1b9028247..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.defaults +++ /dev/null @@ -1,9 +0,0 @@ -# Enable FATFS read only with long filename support -# for loading Cert/CA/etc from filesystem -# (if enabled in config) -CONFIG_FATFS_READONLY=y -CONFIG_FATFS_CODEPAGE_437=y -CONFIG_FATFS_LFN_HEAP=y - -# Enable TLS asymmetric in/out content length -CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/CMakeLists.txt deleted file mode 100644 index 54aa85bc1..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set (EXTRA_COMPONENT_DIRS "../..") -project(thing_shadow) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/Makefile deleted file mode 100644 index db8d0136c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := thing_shadow - -EXTRA_COMPONENT_DIRS := $(realpath ../..) - -include $(IDF_PATH)/make/project.mk - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/README.md deleted file mode 100644 index a508e73a4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Amazon Web Services IoT Thing Shadow Example - -This is an adaptation of the [AWS IoT C SDK](https://github.com/aws/aws-iot-device-sdk-embedded-C) "shadow_sample" example for ESP-IDF. - -# Provisioning/Configuration - -See the README.md in the parent directory for information about configuring the AWS IoT examples. - -After following those steps, there is one additional step for this exmaple: - -## Set Thing Name - -For this example, you will need to set a Thing Name under `make menuconfig` -> `Example Configuration` -> `AWS IoT Thing Name`. - -The Thing Name should match a Thing that you created while following the Getting Started guide (to check the Things you have registered, go t othe AWS IoT console web interface, click Registry and then click Things). - -# Monitoring Thing Status - -After flashing the example to your ESP32, it should connect to Amazon and start updating the example Thing's shadow. - -In the ESP32's serial output, you should see the message "Update accepted" logged every couple of seconds. - -You can monitor the Thing status from the AWS IoT console web interface: - -* On the left-hand toolbar, click Registry and then click Things. -* Click on the "Thing" you set up for the example. -* Click on the "Shadow" sidebar link. You should see the Thing Shadow updating regularly. -* Click on the "Activity" sidebar link to see all Thing Shadow updates in a list. You can examine each update individually. - -# Troubleshooting - -If you're having problems with the AWS IoT connection itself, check the Troubleshooting section of the README in the parent directory. - -* If your Thing is connecting and appears to be successfully updating, but you don't see any updates in the AWS IoT console, then check that the Thing Name in the Example Configuration under menuconfig matches exactly the thing name in AWS IoT console (including case). - -# Important Note - -This example has dependency on `esp-aws-iot` component which is added through `EXTRA_COMPONENT_DIRS` in its `Makefile` or `CMakeLists.txt` (using relative path). Hence if example is moved outside of this repository then this dependency can be resolved by copying `esp_aws_iot` under `components` subdirectory of the example project. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/CMakeLists.txt deleted file mode 100644 index f97a426c6..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(COMPONENT_SRCS "thing_shadow_sample.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - - -register_component() - -if(CONFIG_EXAMPLE_EMBEDDED_CERTS) -target_add_binary_data(${COMPONENT_TARGET} "certs/aws-root-ca.pem" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/private.pem.key" TEXT) -endif() diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/Kconfig.projbuild b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/Kconfig.projbuild deleted file mode 100644 index d0ee5c2cb..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/Kconfig.projbuild +++ /dev/null @@ -1,66 +0,0 @@ -menu "Example Configuration" - - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - - config AWS_EXAMPLE_CLIENT_ID - string "AWS IoT Client ID" - default "myesp32" - help - AWS IoT Client ID for the example. Should be unique for every device. - - config AWS_EXAMPLE_THING_NAME - string "AWS IoT Thing Name" - default "myesp32" - help - AWS IoT Thing Name for the example. Should be unique for every device. - - choice EXAMPLE_CERT_SOURCE - prompt "AWS IoT Certificate Source" - default EXAMPLE_EMBEDDED_CERTS - help - AWS IoT requires loading of a device-specific certificate and private key, - and a common Root CA Certificate. These can be compiled into the example - app, or they can be loaded via the filesystem from an SD card. - - config EXAMPLE_EMBEDDED_CERTS - bool "Embed into app" - config EXAMPLE_SDCARD_CERTS - bool "Load from SD card" - select EXAMPLE_FILESYSTEM_CERTS - endchoice - - # Currently this is equivalent to EXAMPLE_SDCARD_CERTS, - # however eventually we want to support more filesystem - # sources (SPIFFS, etc.) So this hidden config item - # is selected whenever the item should load from filesystem. - config EXAMPLE_FILESYSTEM_CERTS - bool - - config EXAMPLE_CERTIFICATE_PATH - string "Device Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/certificate.pem.crt" - - config EXAMPLE_PRIVATE_KEY_PATH - string "Device Private Key Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/private.pem.key" - - config EXAMPLE_ROOT_CA_PATH - string "Root CA Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/aws-root-ca.pem" - -endmenu diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/README.md deleted file mode 100644 index d445cc62b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Copy certificate files for AWS IoT SDK example here - -See README.md in main example directory for details. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/aws-root-ca.pem b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/aws-root-ca.pem deleted file mode 100644 index a6f3e92af..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/aws-root-ca.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/component.mk b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/component.mk deleted file mode 100644 index 401de47a5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/component.mk +++ /dev/null @@ -1,14 +0,0 @@ -# -# Main Makefile. This is basically the same as a component makefile. -# - -ifdef CONFIG_EXAMPLE_EMBEDDED_CERTS -# Certificate files. certificate.pem.crt & private.pem.key must be downloaded -# from AWS, see README for details. -COMPONENT_EMBED_TXTFILES := certs/aws-root-ca.pem certs/certificate.pem.crt certs/private.pem.key - -# Print an error if the certificate/key files are missing -$(COMPONENT_PATH)/certs/certificate.pem.crt $(COMPONENT_PATH)/certs/private.pem.key: - @echo "Missing PEM file $@. This file identifies the ESP32 to AWS for the example, see README for details." - exit 1 -endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/thing_shadow_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/thing_shadow_sample.c deleted file mode 100644 index 82ef78358..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/thing_shadow_sample.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -/** - * @file thing_shadow_sample.c - * @brief A simple connected window example demonstrating the use of Thing Shadow - * - * See example README for more details. - */ -#include -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "esp_vfs_fat.h" -#include "driver/sdmmc_host.h" - -#include "nvs.h" -#include "nvs_flash.h" - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" - -/*! - * The goal of this sample application is to demonstrate the capabilities of shadow. - * This device(say Connected Window) will open the window of a room based on temperature - * It can report to the Shadow the following parameters: - * 1. temperature of the room (double) - * 2. status of the window (open or close) - * It can act on commands from the cloud. In this case it will open or close the window based on the json object "windowOpen" data[open/close] - * - * The two variables from a device's perspective are double temperature and bool windowOpen - * The device needs to act on only on windowOpen variable, so we will create a primitiveJson_t object with callback - The Json Document in the cloud will be - { - "reported": { - "temperature": 0, - "windowOpen": false - }, - "desired": { - "windowOpen": false - } - } - */ - -static const char *TAG = "shadow"; - -#define ROOMTEMPERATURE_UPPERLIMIT 32.0f -#define ROOMTEMPERATURE_LOWERLIMIT 25.0f -#define STARTING_ROOMTEMPERATURE ROOMTEMPERATURE_LOWERLIMIT - -#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - - -/* CA Root certificate, device ("Thing") certificate and device - * ("Thing") key. - - Example can be configured one of two ways: - - "Embedded Certs" are loaded from files in "certs/" and embedded into the app binary. - - "Filesystem Certs" are loaded from the filesystem (SD card, etc.) - - See example README for more details. -*/ -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - -extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start"); -extern const uint8_t aws_root_ca_pem_end[] asm("_binary_aws_root_ca_pem_end"); -extern const uint8_t certificate_pem_crt_start[] asm("_binary_certificate_pem_crt_start"); -extern const uint8_t certificate_pem_crt_end[] asm("_binary_certificate_pem_crt_end"); -extern const uint8_t private_pem_key_start[] asm("_binary_private_pem_key_start"); -extern const uint8_t private_pem_key_end[] asm("_binary_private_pem_key_end"); - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - -static const char * DEVICE_CERTIFICATE_PATH = CONFIG_EXAMPLE_CERTIFICATE_PATH; -static const char * DEVICE_PRIVATE_KEY_PATH = CONFIG_EXAMPLE_PRIVATE_KEY_PATH; -static const char * ROOT_CA_PATH = CONFIG_EXAMPLE_ROOT_CA_PATH; - -#else -#error "Invalid method for loading certs" -#endif - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void simulateRoomTemperature(float *pRoomTemperature) { - static float deltaChange; - - if(*pRoomTemperature >= ROOMTEMPERATURE_UPPERLIMIT) { - deltaChange = -0.5f; - } else if(*pRoomTemperature <= ROOMTEMPERATURE_LOWERLIMIT) { - deltaChange = 0.5f; - } - - *pRoomTemperature += deltaChange; -} - -static bool shadowUpdateInProgress; - -void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(action); - IOT_UNUSED(pReceivedJsonDocument); - IOT_UNUSED(pContextData); - - shadowUpdateInProgress = false; - - if(SHADOW_ACK_TIMEOUT == status) { - ESP_LOGE(TAG, "Update timed out"); - } else if(SHADOW_ACK_REJECTED == status) { - ESP_LOGE(TAG, "Update rejected"); - } else if(SHADOW_ACK_ACCEPTED == status) { - ESP_LOGI(TAG, "Update accepted"); - } -} - -void windowActuate_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - IOT_UNUSED(pJsonString); - IOT_UNUSED(JsonStringDataLen); - - if(pContext != NULL) { - ESP_LOGI(TAG, "Delta - Window state changed to %d", *(bool *) (pContext->pData)); - } -} - -void aws_iot_task(void *param) { - IoT_Error_t rc = FAILURE; - - char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER]; - size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]); - float temperature = 0.0; - - bool windowOpen = false; - jsonStruct_t windowActuator; - windowActuator.cb = windowActuate_Callback; - windowActuator.pData = &windowOpen; - windowActuator.pKey = "windowOpen"; - windowActuator.type = SHADOW_JSON_BOOL; - windowActuator.dataLength = sizeof(bool); - - jsonStruct_t temperatureHandler; - temperatureHandler.cb = NULL; - temperatureHandler.pKey = "temperature"; - temperatureHandler.pData = &temperature; - temperatureHandler.type = SHADOW_JSON_FLOAT; - temperatureHandler.dataLength = sizeof(float); - - ESP_LOGI(TAG, "AWS IoT SDK Version %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - // initialize the mqtt client - AWS_IoT_Client mqttClient; - - ShadowInitParameters_t sp = ShadowInitParametersDefault; - sp.pHost = AWS_IOT_MQTT_HOST; - sp.port = AWS_IOT_MQTT_PORT; - -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - sp.pClientCRT = (const char *)certificate_pem_crt_start; - sp.pClientKey = (const char *)private_pem_key_start; - sp.pRootCA = (const char *)aws_root_ca_pem_start; -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - sp.pClientCRT = DEVICE_CERTIFICATE_PATH; - sp.pClientKey = DEVICE_PRIVATE_KEY_PATH; - sp.pRootCA = ROOT_CA_PATH; -#endif - sp.enableAutoReconnect = false; - sp.disconnectHandler = NULL; - -#ifdef CONFIG_EXAMPLE_SDCARD_CERTS - ESP_LOGI(TAG, "Mounting SD card..."); - sdmmc_host_t host = SDMMC_HOST_DEFAULT(); - sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = 3, - }; - sdmmc_card_t* card; - esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount SD card VFAT filesystem. Error: %s", esp_err_to_name(ret)); - abort(); - } -#endif - - /* Wait for WiFI to show as connected */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - - ESP_LOGI(TAG, "Shadow Init"); - rc = aws_iot_shadow_init(&mqttClient, &sp); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "aws_iot_shadow_init returned error %d, aborting...", rc); - abort(); - } - - ShadowConnectParameters_t scp = ShadowConnectParametersDefault; - scp.pMyThingName = CONFIG_AWS_EXAMPLE_THING_NAME; - scp.pMqttClientId = CONFIG_AWS_EXAMPLE_CLIENT_ID; - scp.mqttClientIdLen = (uint16_t) strlen(CONFIG_AWS_EXAMPLE_CLIENT_ID); - - ESP_LOGI(TAG, "Shadow Connect"); - rc = aws_iot_shadow_connect(&mqttClient, &scp); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "aws_iot_shadow_connect returned error %d, aborting...", rc); - abort(); - } - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Unable to set Auto Reconnect to true - %d, aborting...", rc); - abort(); - } - - rc = aws_iot_shadow_register_delta(&mqttClient, &windowActuator); - - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Shadow Register Delta Error"); - } - temperature = STARTING_ROOMTEMPERATURE; - - // loop and publish a change in temperature - while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) { - rc = aws_iot_shadow_yield(&mqttClient, 200); - if(NETWORK_ATTEMPTING_RECONNECT == rc || shadowUpdateInProgress) { - rc = aws_iot_shadow_yield(&mqttClient, 1000); - // If the client is attempting to reconnect, or already waiting on a shadow update, - // we will skip the rest of the loop. - continue; - } - ESP_LOGI(TAG, "======================================================================================="); - ESP_LOGI(TAG, "On Device: window state %s", windowOpen ? "true" : "false"); - simulateRoomTemperature(&temperature); - - rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 2, &temperatureHandler, - &windowActuator); - if(SUCCESS == rc) { - rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - ESP_LOGI(TAG, "Update Shadow: %s", JsonDocumentBuffer); - rc = aws_iot_shadow_update(&mqttClient, CONFIG_AWS_EXAMPLE_THING_NAME, JsonDocumentBuffer, - ShadowUpdateStatusCallback, NULL, 4, true); - shadowUpdateInProgress = true; - } - } - } - ESP_LOGI(TAG, "*****************************************************************************************"); - ESP_LOGI(TAG, "Stack remaining for task '%s' is %d bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); - - vTaskDelay(1000 / portTICK_RATE_MS); - } - - if(SUCCESS != rc) { - ESP_LOGE(TAG, "An error occurred in the loop %d", rc); - } - - ESP_LOGI(TAG, "Disconnecting"); - rc = aws_iot_shadow_disconnect(&mqttClient); - - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Disconnect error %d", rc); - } - - vTaskDelete(NULL); -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - - -void app_main() -{ - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); - - initialise_wifi(); - /* Temporarily pin task to core, due to FPU uncertainty */ - xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 9216, NULL, 5, NULL, 1); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.ci b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.ci deleted file mode 100644 index b59dfb870..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.ci +++ /dev/null @@ -1,2 +0,0 @@ -# For CI build example assuming certificates stored on sdcard -CONFIG_EXAMPLE_SDCARD_CERTS=y diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.defaults b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.defaults deleted file mode 100644 index 8d8e882fc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.defaults +++ /dev/null @@ -1,8 +0,0 @@ -# Enable FATFS read only with long filename support -# for loading Cert/CA/etc from filesystem -# (if enabled in config) -CONFIG_FATFS_CODEPAGE_437=y -CONFIG_FATFS_LFN_HEAP=y - -# Enable TLS asymmetric in/out content length -CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_config.h deleted file mode 100644 index c98f7dea2..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_config.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef _AWS_IOT_CONFIG_H_ -#define _AWS_IOT_CONFIG_H_ - -#include "aws_iot_log.h" - -// This configuration macro needs to be available globally to enable threading -#define _ENABLE_THREAD_SUPPORT_ - -// These values are defined in the menuconfig of the AWS IoT component. -// However, you can override these constants from your own code. -#define AWS_IOT_MQTT_HOST CONFIG_AWS_IOT_MQTT_HOST ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT CONFIG_AWS_IOT_MQTT_PORT ///< default port for MQTT/S - -// These values are defaults and are used for ShadowConnectParametersDefault. -// You should override them from your own code. -#define AWS_IOT_MQTT_CLIENT_ID "ESP32" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "ESP32" ///< Thing Name of the Shadow this device is associated with - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN CONFIG_AWS_IOT_MQTT_TX_BUF_LEN ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN CONFIG_AWS_IOT_MQTT_RX_BUF_LEN ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#ifdef CONFIG_AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER -#define SHADOW_MAX_SIZE_OF_RX_BUFFER CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_RX_BUFFER ///< Maximum size of the SHADOW buffer to store the received Shadow message, including NULL terminating byte -#else -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN + 1) -#endif - -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE (MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10) ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE (MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20) ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME ///< All shadow actions have to be published or subscribed to a topic which is of the formablogt $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES (MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME) ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#endif /* _AWS_IOT_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_log.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_log.h deleted file mode 100644 index 7d83960cc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_log.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -/* (these two headers aren't used here, but AWS IoT SDK code relies on them - being included from here...) */ -#include -#include - -#include "esp_log.h" - -/* This is a stub replacement for the aws_iot_log.h header in the AWS IoT SDK, - which redirects their logging framework into the esp-idf logging framework. - - The current (2.1.1) upstream AWS IoT SDK doesn't allow this as some of its - headers include aws_iot_log.h, but our modified fork does. -*/ - -// redefine the AWS IoT log functions to call into the IDF log layer -#undef IOT_DEBUG -#define IOT_DEBUG(format, ...) ESP_LOGD("aws_iot", format, ##__VA_ARGS__) -#undef IOT_INFO -#define IOT_INFO(format, ...) ESP_LOGI("aws_iot", format, ##__VA_ARGS__) -#undef IOT_WARN -#define IOT_WARN(format, ...) ESP_LOGW("aws_iot", format, ##__VA_ARGS__) -#undef IOT_ERROR -#define IOT_ERROR(format, ...) ESP_LOGE("aws_iot", format, ##__VA_ARGS__) - -/* Function tracing macros used in AWS IoT SDK, - mapped to "verbose" level output -*/ -#undef FUNC_ENTRY -#define FUNC_ENTRY ESP_LOGV("aws_iot", "FUNC_ENTRY: %s L#%d \n", __func__, __LINE__) -#undef FUNC_EXIT_RC -#define FUNC_EXIT_RC(x) \ - do { \ - ESP_LOGV("aws_iot", "FUNC_EXIT: %s L#%d Return Code : %d \n", __func__, __LINE__, x); \ - return x; \ - } while(0) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/network_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/network_platform.h deleted file mode 100644 index a5e87d71a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/network_platform.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/platform.h" -#include "mbedtls/net_sockets.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/certs.h" -#include "mbedtls/x509.h" -#include "mbedtls/error.h" -#include "mbedtls/debug.h" -#include "mbedtls/timing.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct _TLSDataParams { - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_context ssl; - mbedtls_ssl_config conf; - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - mbedtls_pk_context pkey; - mbedtls_net_context server_fd; -}TLSDataParams; - -#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#ifdef __cplusplus -} -#endif - -#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/threads_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/threads_platform.h deleted file mode 100644 index 011a1a0b2..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/threads_platform.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "threads_interface.h" - -#ifndef AWS_IOTSDK_THREADS_PLATFORM_H -#define AWS_IOTSDK_THREADS_PLATFORM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" - -/** - * @brief Mutex Type - * - * definition of the Mutex struct. Platform specific - * - */ -struct _IoT_Mutex_t { - SemaphoreHandle_t mutex; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOTSDK_THREADS_PLATFORM_H */ - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/timer_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/timer_platform.h deleted file mode 100644 index 07e7385db..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/timer_platform.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#ifndef AWS_IOT_PLATFORM_H -#define AWS_IOT_PLATFORM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "timer_interface.h" - -/** - * definition of the Timer struct. Platform specific - */ -struct Timer { - uint32_t start_ticks; - uint32_t timeout_ticks; - uint32_t last_polled_ticks; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_PLATFORM_H */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/network_mbedtls_wrapper.c b/examples/espidf-aws-iot/components/esp-aws-iot/port/network_mbedtls_wrapper.c deleted file mode 100644 index 61ddec02b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/network_mbedtls_wrapper.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_error.h" -#include "network_interface.h" -#include "network_platform.h" - -#include "mbedtls/esp_debug.h" - -#include "esp_log.h" -#include "esp_vfs.h" - -static const char *TAG = "aws_iot"; - -/* This is the value used for ssl read timeout */ -#define IOT_SSL_READ_TIMEOUT 10 - -/* - * This is a function to do further verification if needed on the cert received. - * - * Currently used to print debug-level information about each cert. - */ -static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { - char buf[256]; - ((void) data); - - if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { - ESP_LOGD(TAG, "Verify requested for (Depth %d):", depth); - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); - ESP_LOGD(TAG, "%s", buf); - - if((*flags) == 0) { - ESP_LOGD(TAG, " This certificate has no flags"); - } else { - ESP_LOGD(TAG, "Verify result:%s", buf); - } - } - - return 0; -} - -static void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - pNetwork->tlsConnectParams.DestinationPort = destinationPort; - pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; - pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; - pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; - pNetwork->tlsConnectParams.timeout_ms = timeout_ms; - pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; -} - -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, - pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); - - pNetwork->connect = iot_tls_connect; - pNetwork->read = iot_tls_read; - pNetwork->write = iot_tls_write; - pNetwork->disconnect = iot_tls_disconnect; - pNetwork->isConnected = iot_tls_is_connected; - pNetwork->destroy = iot_tls_destroy; - - pNetwork->tlsDataParams.flags = 0; - - return SUCCESS; -} - -IoT_Error_t iot_tls_is_connected(Network *pNetwork) { - /* Use this to add implementation which can check for physical layer disconnect */ - return NETWORK_PHYSICAL_LAYER_CONNECTED; -} - -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { - int ret = SUCCESS; - TLSDataParams *tlsDataParams = NULL; - char portBuffer[6]; - char info_buf[256]; - - if(NULL == pNetwork) { - return NULL_VALUE_ERROR; - } - - if(NULL != params) { - _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, - params->pDevicePrivateKeyLocation, params->pDestinationURL, - params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); - } - - tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_init(&(tlsDataParams->server_fd)); - mbedtls_ssl_init(&(tlsDataParams->ssl)); - mbedtls_ssl_config_init(&(tlsDataParams->conf)); - -#ifdef CONFIG_MBEDTLS_DEBUG - mbedtls_esp_enable_debug_log(&(tlsDataParams->conf), 4); -#endif - - mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); - mbedtls_x509_crt_init(&(tlsDataParams->cacert)); - mbedtls_x509_crt_init(&(tlsDataParams->clicert)); - mbedtls_pk_init(&(tlsDataParams->pkey)); - - ESP_LOGD(TAG, "Seeding the random number generator..."); - mbedtls_entropy_init(&(tlsDataParams->entropy)); - if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), - (const unsigned char *) TAG, strlen(TAG))) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ctr_drbg_seed returned -0x%x", -ret); - return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; - } - - /* Load root CA... - - Certs/keys can be paths or they can be raw data. These use a - very basic heuristic: if the cert starts with '/' then it's a - path, if it's longer than this then it's raw cert data (PEM or DER, - neither of which can start with a slash. */ - if (pNetwork->tlsConnectParams.pRootCALocation[0] == '/') { - ESP_LOGD(TAG, "Loading CA root certificate from file ..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); - } else { - ESP_LOGD(TAG, "Loading embedded CA root certificate ..."); - ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation, - strlen(pNetwork->tlsConnectParams.pRootCALocation)+1); - } - - if(ret < 0) { - ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing root cert", -ret); - return NETWORK_X509_ROOT_CRT_PARSE_ERROR; - } - ESP_LOGD(TAG, "ok (%d skipped)", ret); - - /* Load client certificate... */ - if (pNetwork->tlsConnectParams.pDeviceCertLocation[0] == '/') { - ESP_LOGD(TAG, "Loading client cert from file..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), - pNetwork->tlsConnectParams.pDeviceCertLocation); - } else { - ESP_LOGD(TAG, "Loading embedded client certificate..."); - ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert), - (const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation, - strlen(pNetwork->tlsConnectParams.pDeviceCertLocation)+1); - } - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing device cert", -ret); - return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; - } - - /* Parse client private key... */ - if (pNetwork->tlsConnectParams.pDevicePrivateKeyLocation[0] == '/') { - ESP_LOGD(TAG, "Loading client private key from file..."); - ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, - ""); - } else { - ESP_LOGD(TAG, "Loading embedded client private key..."); - ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey), - (const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, - strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)+1, - (const unsigned char *)"", 0); - } - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_pk_parse_key returned -0x%x while parsing private key", -ret); - return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; - } - - /* Done parsing certs */ - ESP_LOGD(TAG, "ok"); - snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); - ESP_LOGD(TAG, "Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); - if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, - portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_net_connect returned -0x%x", -ret); - switch(ret) { - case MBEDTLS_ERR_NET_SOCKET_FAILED: - return NETWORK_ERR_NET_SOCKET_FAILED; - case MBEDTLS_ERR_NET_UNKNOWN_HOST: - return NETWORK_ERR_NET_UNKNOWN_HOST; - case MBEDTLS_ERR_NET_CONNECT_FAILED: - default: - return NETWORK_ERR_NET_CONNECT_FAILED; - }; - } - - ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); - if(ret != 0) { - ESP_LOGE(TAG, "failed! net_set_(non)block() returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } ESP_LOGD(TAG, "ok"); - - ESP_LOGD(TAG, "Setting up the SSL/TLS structure..."); - if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_config_defaults returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); - } else { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); - } - mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); - - mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); - ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey)); - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_own_cert returned %d", ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); - -#ifdef CONFIG_MBEDTLS_SSL_ALPN - /* Use the AWS IoT ALPN extension for MQTT, if port 443 is requested */ - if (pNetwork->tlsConnectParams.DestinationPort == 443) { - const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; - if ((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - } -#endif - - if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_set_hostname returned %d", ret); - return SSL_CONNECTION_ERROR; - } - ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); - mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, - mbedtls_net_recv_timeout); - ESP_LOGD(TAG, "ok"); - - ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); - ESP_LOGD(TAG, "Performing the SSL/TLS handshake..."); - while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_handshake returned -0x%x", -ret); - if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - ESP_LOGE(TAG, " Unable to verify the server's certificate. "); - } - return SSL_CONNECTION_ERROR; - } - } - - ESP_LOGD(TAG, "ok [ Protocol is %s ] [ Ciphersuite is %s ]", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), - mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); - if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { - ESP_LOGD(TAG, " [ Record expansion is %d ]", ret); - } else { - ESP_LOGD(TAG, " [ Record expansion is unknown (compression) ]"); - } - - ESP_LOGD(TAG, "Verifying peer X.509 certificate..."); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { - ESP_LOGE(TAG, "failed"); - mbedtls_x509_crt_verify_info(info_buf, sizeof(info_buf), " ! ", tlsDataParams->flags); - ESP_LOGE(TAG, "%s", info_buf); - ret = SSL_CONNECTION_ERROR; - } else { - ESP_LOGD(TAG, "ok"); - ret = SUCCESS; - } - } else { - ESP_LOGW(TAG, " Server Verification skipped"); - ret = SUCCESS; - } - - if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { - if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { - ESP_LOGD(TAG, "Peer certificate information:"); - mbedtls_x509_crt_info((char *) info_buf, sizeof(info_buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); - ESP_LOGD(TAG, "%s", info_buf); - } - } - - return (IoT_Error_t) ret; -} - -IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) { - size_t written_so_far; - bool isErrorFlag = false; - int frags, ret = 0; - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - for(written_so_far = 0, frags = 0; - written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) { - while(!has_timer_expired(timer) && - (ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_write returned -0x%x", -ret); - /* All other negative return values indicate connection needs to be reset. - * Will be caught in ping request so ignored here */ - isErrorFlag = true; - break; - } - } - if(isErrorFlag) { - break; - } - } - - *written_len = written_so_far; - - if(isErrorFlag) { - return NETWORK_SSL_WRITE_ERROR; - } else if(has_timer_expired(timer) && written_so_far != len) { - return NETWORK_SSL_WRITE_TIMEOUT_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) { - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - mbedtls_ssl_context *ssl = &(tlsDataParams->ssl); - mbedtls_ssl_config *ssl_conf = &(tlsDataParams->conf); - uint32_t read_timeout; - size_t rxLen = 0; - int ret; - - read_timeout = ssl_conf->read_timeout; - - while (len > 0) { - - /* Make sure we never block on read for longer than timer has left, - but also that we don't block indefinitely (ie read_timeout > 0) */ - mbedtls_ssl_conf_read_timeout(ssl_conf, MAX(1, MIN(read_timeout, left_ms(timer)))); - - ret = mbedtls_ssl_read(ssl, pMsg, len); - - /* Restore the old timeout */ - mbedtls_ssl_conf_read_timeout(ssl_conf, read_timeout); - - if (ret > 0) { - rxLen += ret; - pMsg += ret; - len -= ret; - } else if (ret == 0 || (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_TIMEOUT)) { - return NETWORK_SSL_READ_ERROR; - } - - // Evaluate timeout after the read to make sure read is done at least once - if (has_timer_expired(timer)) { - break; - } - } - - if (len == 0) { - *read_len = rxLen; - return SUCCESS; - } - - if (rxLen == 0) { - return NETWORK_SSL_NOTHING_TO_READ; - } else { - return NETWORK_SSL_READ_TIMEOUT_ERROR; - } -} - -IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); - int ret = 0; - do { - ret = mbedtls_ssl_close_notify(ssl); - } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); - - /* All other negative return values indicate connection needs to be reset. - * No further action required since this is disconnect call */ - - return SUCCESS; -} - -IoT_Error_t iot_tls_destroy(Network *pNetwork) { - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_free(&(tlsDataParams->server_fd)); - - mbedtls_x509_crt_free(&(tlsDataParams->clicert)); - mbedtls_x509_crt_free(&(tlsDataParams->cacert)); - mbedtls_pk_free(&(tlsDataParams->pkey)); - mbedtls_ssl_free(&(tlsDataParams->ssl)); - mbedtls_ssl_config_free(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg)); - mbedtls_entropy_free(&(tlsDataParams->entropy)); - - return SUCCESS; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/threads_freertos.c b/examples/espidf-aws-iot/components/esp-aws-iot/port/threads_freertos.c deleted file mode 100644 index 065ead78c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/threads_freertos.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "threads_platform.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize the provided mutex - * - * Call this function to initialize the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be initialized - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *pMutex) { - - pMutex->mutex = xSemaphoreCreateRecursiveMutex(); - return pMutex->mutex ? SUCCESS : MUTEX_INIT_ERROR; -} - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change - * Blocking, thread will block until lock request fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *pMutex) { - xSemaphoreTakeRecursive(pMutex->mutex, portMAX_DELAY); - return SUCCESS; -} - -/** - * @brief Try to lock the provided mutex - * - * Call this function to attempt to lock the mutex before performing a state change - * Non-Blocking, immediately returns with failure if lock attempt fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *pMutex) { - if (xSemaphoreTakeRecursive(pMutex->mutex, 0)) { - return SUCCESS; - } else { - return MUTEX_LOCK_ERROR; - } -} - -/** - * @brief Unlock the provided mutex - * - * Call this function to unlock the mutex before performing a state change - * - * @param IoT_Mutex_t - pointer to the mutex to be unlocked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *pMutex) { - if (xSemaphoreGiveRecursive(pMutex->mutex)) { - return SUCCESS; - } else { - return MUTEX_UNLOCK_ERROR; - } -} - -/** - * @brief Destroy the provided mutex - * - * Call this function to destroy the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be destroyed - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *pMutex) { - vSemaphoreDelete(pMutex->mutex); - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/timer.c b/examples/espidf-aws-iot/components/esp-aws-iot/port/timer.c deleted file mode 100644 index ee4d8b5be..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/timer.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -/** - * @file timer.c - * @brief FreeRTOS implementation of the timer interface uses ticks. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "timer_platform.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" - -const static char *TAG = "aws_timer"; - -bool has_timer_expired(Timer *timer) { - uint32_t now = xTaskGetTickCount(); - bool expired = (now - timer->start_ticks) >= timer->timeout_ticks; - - /* AWS IoT SDK isn't very RTOS friendly because it polls for "done - timers" a lot without ever sleeping on them. So we hack in some - amount of sleeping here: if it seems like the caller is polling - an unexpired timer in a tight loop then we delay a tick to let - things progress elsewhere. - */ - if(!expired && now == timer->last_polled_ticks) { - vTaskDelay(1); - } - timer->last_polled_ticks = now; - return expired; -} - -void countdown_ms(Timer *timer, uint32_t timeout) { - timer->start_ticks = xTaskGetTickCount(); - timer->timeout_ticks = timeout / portTICK_PERIOD_MS; - timer->last_polled_ticks = 0; -} - -uint32_t left_ms(Timer *timer) { - uint32_t now = xTaskGetTickCount(); - uint32_t elapsed = now - timer->start_ticks; - if (elapsed < timer->timeout_ticks) { - return (timer->timeout_ticks - elapsed) * portTICK_PERIOD_MS; - } else { - return 0; - } -} - -void countdown_sec(Timer *timer, uint32_t timeout) { - if (timeout > UINT32_MAX / 1000) { - ESP_LOGE(TAG, "timeout is out of range: %ds", timeout); - } - countdown_ms(timer, timeout * 1000); -} - -void init_timer(Timer *timer) { - timer->start_ticks = 0; - timer->timeout_ticks = 0; - timer->last_polled_ticks = 0; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/include/README b/examples/espidf-aws-iot/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/espidf-aws-iot/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-aws-iot/lib/README b/examples/espidf-aws-iot/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/espidf-aws-iot/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-aws-iot/platformio.ini b/examples/espidf-aws-iot/platformio.ini deleted file mode 100644 index 5bf94f9d8..000000000 --- a/examples/espidf-aws-iot/platformio.ini +++ /dev/null @@ -1,26 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[env:esp32dev] -platform = espressif32 -framework = espidf -board = esp32dev -monitor_speed = 115200 -monitor_filters = colorize - -board_build.embed_txtfiles = - src/certs/private.pem.key - src/certs/certificate.pem.crt - src/certs/aws-root-ca.pem - -# IDF v5 is not supported by ASW-IoT SDK -# https://github.com/espressif/esp-aws-iot/blob/bbaf03d7d1fbf8a3f91dc18489d7bd27d5b9e9df/README.md?plain=1#L21 -platform_packages = - framework-espidf @ ~3.40403.0 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5 diff --git a/examples/espidf-aws-iot/sdkconfig.defaults b/examples/espidf-aws-iot/sdkconfig.defaults deleted file mode 100644 index b1a90483c..000000000 --- a/examples/espidf-aws-iot/sdkconfig.defaults +++ /dev/null @@ -1,13 +0,0 @@ -# Enable FATFS read only with long filename support -# for loading Cert/CA/etc from filesystem -# (if enabled in config) -CONFIG_FATFS_READONLY=y -CONFIG_FATFS_CODEPAGE_437=y -CONFIG_FATFS_LFN_HEAP=y - -# Enable TLS asymmetric in/out content length -CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y - -# Example configs -CONFIG_EXAMPLE_WIFI_SSID="MYSSID" -CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" diff --git a/examples/espidf-aws-iot/src/CMakeLists.txt b/examples/espidf-aws-iot/src/CMakeLists.txt deleted file mode 100644 index 807ad6ea0..000000000 --- a/examples/espidf-aws-iot/src/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(COMPONENT_SRCS "subscribe_publish_sample.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - - -register_component() - -if(CONFIG_EXAMPLE_EMBEDDED_CERTS) -target_add_binary_data(${COMPONENT_TARGET} "certs/aws-root-ca.pem" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/private.pem.key" TEXT) -endif() diff --git a/examples/espidf-aws-iot/src/Kconfig.projbuild b/examples/espidf-aws-iot/src/Kconfig.projbuild deleted file mode 100644 index 96a022a5c..000000000 --- a/examples/espidf-aws-iot/src/Kconfig.projbuild +++ /dev/null @@ -1,60 +0,0 @@ -menu "Example Configuration" - - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - - config AWS_EXAMPLE_CLIENT_ID - string "AWS IoT Client ID" - default "myesp32" - help - AWS IoT Client ID for the example. Should be unique for every device. - - choice EXAMPLE_CERT_SOURCE - prompt "AWS IoT Certificate Source" - default EXAMPLE_EMBEDDED_CERTS - help - AWS IoT requires loading of a device-specific certificate and private key, - and a common Root CA Certificate. These can be compiled into the example - app, or they can be loaded via the filesystem from an SD card. - - config EXAMPLE_EMBEDDED_CERTS - bool "Embed into app" - config EXAMPLE_SDCARD_CERTS - bool "Load from SD card" - select EXAMPLE_FILESYSTEM_CERTS - endchoice - - # Currently this is equivalent to EXAMPLE_SDCARD_CERTS, - # however eventually we want to support more filesystem - # sources (SPIFFS, etc.) So this hidden config item - # is selected whenever the item should load from filesystem. - config EXAMPLE_FILESYSTEM_CERTS - bool - - config EXAMPLE_CERTIFICATE_PATH - string "Device Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/certificate.pem.crt" - - config EXAMPLE_PRIVATE_KEY_PATH - string "Device Private Key Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/private.pem.key" - - config EXAMPLE_ROOT_CA_PATH - string "Root CA Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/aws-root-ca.pem" - -endmenu diff --git a/examples/espidf-aws-iot/src/certs/README.md b/examples/espidf-aws-iot/src/certs/README.md deleted file mode 100644 index d445cc62b..000000000 --- a/examples/espidf-aws-iot/src/certs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Copy certificate files for AWS IoT SDK example here - -See README.md in main example directory for details. diff --git a/examples/espidf-aws-iot/src/certs/aws-root-ca.pem b/examples/espidf-aws-iot/src/certs/aws-root-ca.pem deleted file mode 100644 index a6f3e92af..000000000 --- a/examples/espidf-aws-iot/src/certs/aws-root-ca.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- diff --git a/examples/espidf-aws-iot/src/certs/certificate.pem.crt b/examples/espidf-aws-iot/src/certs/certificate.pem.crt deleted file mode 100644 index d831f6f16..000000000 --- a/examples/espidf-aws-iot/src/certs/certificate.pem.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -DUMMY CONTENT ------END CERTIFICATE----- \ No newline at end of file diff --git a/examples/espidf-aws-iot/src/certs/private.pem.key b/examples/espidf-aws-iot/src/certs/private.pem.key deleted file mode 100644 index d831f6f16..000000000 --- a/examples/espidf-aws-iot/src/certs/private.pem.key +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -DUMMY CONTENT ------END CERTIFICATE----- \ No newline at end of file diff --git a/examples/espidf-aws-iot/src/subscribe_publish_sample.c b/examples/espidf-aws-iot/src/subscribe_publish_sample.c deleted file mode 100644 index 833261c86..000000000 --- a/examples/espidf-aws-iot/src/subscribe_publish_sample.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -/** - * @file subscribe_publish_sample.c - * @brief simple MQTT publish and subscribe on the same topic - * - * This example takes the parameters from the build configuration and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "test_topic/esp32" - * - * Some setup is required. See example README for details. - * - */ -#include -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event.h" -#include "esp_log.h" -#include "esp_vfs_fat.h" -#include "driver/sdmmc_host.h" - -#include "nvs.h" -#include "nvs_flash.h" - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -static const char *TAG = "subpub"; - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - - -/* CA Root certificate, device ("Thing") certificate and device - * ("Thing") key. - - Example can be configured one of two ways: - - "Embedded Certs" are loaded from files in "certs/" and embedded into the app binary. - - "Filesystem Certs" are loaded from the filesystem (SD card, etc.) - - See example README for more details. -*/ -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - -extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start"); -extern const uint8_t aws_root_ca_pem_end[] asm("_binary_aws_root_ca_pem_end"); -extern const uint8_t certificate_pem_crt_start[] asm("_binary_certificate_pem_crt_start"); -extern const uint8_t certificate_pem_crt_end[] asm("_binary_certificate_pem_crt_end"); -extern const uint8_t private_pem_key_start[] asm("_binary_private_pem_key_start"); -extern const uint8_t private_pem_key_end[] asm("_binary_private_pem_key_end"); - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - -static const char * DEVICE_CERTIFICATE_PATH = CONFIG_EXAMPLE_CERTIFICATE_PATH; -static const char * DEVICE_PRIVATE_KEY_PATH = CONFIG_EXAMPLE_PRIVATE_KEY_PATH; -static const char * ROOT_CA_PATH = CONFIG_EXAMPLE_ROOT_CA_PATH; - -#else -#error "Invalid method for loading certs" -#endif - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -char HostAddress[255] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -uint32_t port = AWS_IOT_MQTT_PORT; - - -static void event_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data) -{ - ESP_LOGI(TAG, "event_handler: %s:%d", base, id); - - if(base == WIFI_EVENT) { - switch(id) { - case WIFI_EVENT_STA_START: - esp_wifi_connect(); - break; - case WIFI_EVENT_STA_CONNECTED: - break; - case WIFI_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - } - else if(base == IP_EVENT) { - switch(id) { - case IP_EVENT_STA_GOT_IP: - { - ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; - ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - } - } - } -} - -void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - ESP_LOGI(TAG, "Subscribe callback"); - ESP_LOGI(TAG, "%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *)params->payload); -} - -void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - ESP_LOGW(TAG, "MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - ESP_LOGI(TAG, "Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - ESP_LOGW(TAG, "Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - ESP_LOGW(TAG, "Manual Reconnect Successful"); - } else { - ESP_LOGW(TAG, "Manual Reconnect Failed - %d", rc); - } - } -} - -void aws_iot_task(void *param) { - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - ESP_LOGI(TAG, "AWS IoT SDK Version %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - mqttInitParams.pRootCALocation = (char *)aws_root_ca_pem_start; - mqttInitParams.pDeviceCertLocation = (char *)certificate_pem_crt_start; - mqttInitParams.pDevicePrivateKeyLocation = (char *)private_pem_key_start; - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - mqttInitParams.pRootCALocation = ROOT_CA_PATH; - mqttInitParams.pDeviceCertLocation = DEVICE_CERTIFICATE_PATH; - mqttInitParams.pDevicePrivateKeyLocation = DEVICE_PRIVATE_KEY_PATH; -#endif - - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - -#ifdef CONFIG_EXAMPLE_SDCARD_CERTS - ESP_LOGI(TAG, "Mounting SD card..."); - sdmmc_host_t host = SDMMC_HOST_DEFAULT(); - sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = 3, - }; - sdmmc_card_t* card; - esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount SD card VFAT filesystem. Error: %s", esp_err_to_name(ret)); - abort(); - } -#endif - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "aws_iot_mqtt_init returned error : %d ", rc); - abort(); - } - - /* Wait for WiFI to show as connected */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - /* Client ID is set in the menuconfig of the example */ - connectParams.pClientID = CONFIG_AWS_EXAMPLE_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(CONFIG_AWS_EXAMPLE_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - ESP_LOGI(TAG, "Connecting to AWS with client ID '%s'", connectParams.pClientID); - do { - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - vTaskDelay(1000 / portTICK_RATE_MS); - } - } while(SUCCESS != rc); - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Unable to set Auto Reconnect to true - %d", rc); - abort(); - } - - const char *TOPIC = "test_topic/esp32"; - const int TOPIC_LEN = strlen(TOPIC); - - ESP_LOGI(TAG, "Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, TOPIC, TOPIC_LEN, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Error subscribing : %d ", rc); - abort(); - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - ESP_LOGI(TAG, "Stack remaining for task '%s' is %d bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); - vTaskDelay(1000 / portTICK_RATE_MS); - sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS0)", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS0); - - sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS1)", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - ESP_LOGW(TAG, "QOS1 publish ack not received."); - rc = SUCCESS; - } - } - - ESP_LOGE(TAG, "An error occurred in the main loop."); - abort(); -} - -static void initialise_wifi(void) -{ - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_netif_init()); - - ESP_ERROR_CHECK(esp_event_loop_create_default()); - esp_netif_create_default_wifi_sta(); - - ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, - ESP_EVENT_ANY_ID, - &event_handler, - NULL, - NULL)); - ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, - IP_EVENT_STA_GOT_IP, - &event_handler, - NULL, - NULL)); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - - -void app_main() -{ - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); - - initialise_wifi(); - xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 9216, NULL, 5, NULL, 1); -} diff --git a/examples/espidf-aws-iot/test/README b/examples/espidf-aws-iot/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/espidf-aws-iot/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/espidf-hello-world/platformio.ini b/examples/espidf-hello-world/platformio.ini index 8347b1654..44102cc88 100644 --- a/examples/espidf-hello-world/platformio.ini +++ b/examples/espidf-hello-world/platformio.ini @@ -23,3 +23,5 @@ board = esp32-c3-devkitm-1 [env:esp32-c6-devkitc-1] board = esp32-c6-devkitc-1 +board_build.cmake_extra_args = + -DSDKCONFIG_DEFAULTS="sdkconfig.defaults.esp32c6" diff --git a/examples/espidf-hello-world/sdkconfig.defaults.esp32c6 b/examples/espidf-hello-world/sdkconfig.defaults.esp32c6 new file mode 100644 index 000000000..6c73965bc --- /dev/null +++ b/examples/espidf-hello-world/sdkconfig.defaults.esp32c6 @@ -0,0 +1,2 @@ +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +CONFIG_ESPTOOLPY_FLASHSIZE="8MB" diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes b/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes deleted file mode 100644 index 2342decc3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes +++ /dev/null @@ -1,25 +0,0 @@ -# Set the default behavior, in case people don't have core.autocrlf set. -* text=auto - -*.c text -*.cpp text -*.h text -*.icf text -*.js text -*.json text -*.ld text -*.md text -*.mk text -*.py text -*.rst text -*.s text -*.txt text -*.xml text -*.yml text - -Makefile text - -# Windows-only Visual Studio things - -*.sln text eol=crlf -*.csproj text eol=crlf diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore b/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore deleted file mode 100644 index 87a5faa80..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -html -latex -*.d -*.o -*.P -*.map -*.axf -*.bin -*.jlink -*.emSession -*.elf -*.ind -.env -.settings/ -.idea/ -.gdb_history -/examples/*/*/build* -test_old/ -tests_obsolete/ -_build -/examples/*/*/ses -/examples/*/*/ozone -/examples/obsolete -# coverity intermediate files -cov-int -# cppcheck build directories -*-build-dir -/_bin/ -__pycache__ - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml b/examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml deleted file mode 100644 index e83cd90fd..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# .readthedocs.yaml -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -version: 2 - -sphinx: - configuration: docs/conf.py - -python: - version: 3.8 - install: - - requirements: docs/requirements.txt - -submodules: - include: [] - recursive: false - \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CHANGELOG.md b/examples/espidf-peripherals-usb/components/esp_tinyusb/CHANGELOG.md new file mode 100644 index 000000000..78608a7a4 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/CHANGELOG.md @@ -0,0 +1,53 @@ +## 1.4.4 + +- esp_tinyusb: Added HighSpeed and Qualifier device descriptors in tinyusb configuration +- CDC-ACM: Removed MIN() definition if already defined +- MSC: Fixed EP size selecting in default configuration descriptor + +## 1.4.3 + +- esp_tinyusb: Added ESP32P4 support (HS only) + +## 1.4.2 + +- MSC: Fixed maximum files open +- Added uninstall function + +## 1.4.0 + +- MSC: Fixed integer overflows +- CDC-ACM: Removed intermediate RX ringbuffer +- CDC-ACM: Increased default FIFO size to 512 bytes +- CDC-ACM: Fixed Virtual File System binding + +## 1.3.0 + +- Added NCM extension + +## 1.2.1 - 1.2.2 + +- Minor bugfixes + +## 1.2.0 + +- Added MSC extension for accessing SPI Flash on memory card https://github.com/espressif/idf-extra-components/commit/a8c00d7707ba4ceeb0970c023d702c7768dba3dc + +## 1.1.0 + +- Added support for NCM, ECM/RNDIS, DFU and Bluetooth TinyUSB drivers https://github.com/espressif/idf-extra-components/commit/79f35c9b047b583080f93a63310e2ee7d82ef17b + +## 1.0.4 + +- Cleaned up string descriptors handling https://github.com/espressif/idf-extra-components/commit/046cc4b02f524d5c7e3e56480a473cfe844dc3d6 + +## 1.0.2 - 1.0.3 + +- Minor bugfixes + +## 1.0.1 + +- CDC-ACM: Return ESP_OK if there is nothing to flush https://github.com/espressif/idf-extra-components/commit/388ff32eb09aa572d98c54cb355f1912ce42707c + +## 1.0.0 + +- Initial version based on [esp-idf v4.4.3](https://github.com/espressif/esp-idf/tree/v4.4.3/components/tinyusb) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt index 019a6f489..98fc960e7 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt @@ -1,73 +1,53 @@ -idf_build_get_property(target IDF_TARGET) - -if(target STREQUAL "esp32s3") - set(tusb_mcu "OPT_MCU_ESP32S3") - set(tusb_family "esp32sx") -elseif(target STREQUAL "esp32s2") - set(tusb_mcu "OPT_MCU_ESP32S2") - set(tusb_family "esp32sx") -else() - message(FATAL_ERROR "TinyUSB is not support on ${target}.") - return() -endif() - -set(compile_options - "-DCFG_TUSB_MCU=${tusb_mcu}" - "-DCFG_TUSB_DEBUG=${CONFIG_TINYUSB_DEBUG_LEVEL}" - ) - -idf_component_get_property(freertos_component_dir freertos COMPONENT_DIR) - -set(includes_private - "hw/bsp/" - "src/" - "src/device" - "additions/include_private" - ) - -set(includes_public - "src/" - "additions/include" - # The FreeRTOS API include convention in tinyusb is different from esp-idf - "${freertos_component_dir}/FreeRTOS-Kernel/include/freertos" - ) - set(srcs - "src/portable/espressif/${tusb_family}/dcd_${tusb_family}.c" - "src/class/cdc/cdc_device.c" - "src/class/hid/hid_device.c" - "src/class/midi/midi_device.c" - "src/class/msc/msc_device.c" - "src/class/vendor/vendor_device.c" - "src/common/tusb_fifo.c" - "src/device/usbd_control.c" - "src/device/usbd.c" - "src/tusb.c" - "additions/src/descriptors_control.c" - "additions/src/tinyusb.c" - "additions/src/usb_descriptors.c" + "descriptors_control.c" + "tinyusb.c" + "usb_descriptors.c" ) if(NOT CONFIG_TINYUSB_NO_DEFAULT_TASK) - list(APPEND srcs "additions/src/tusb_tasks.c") -endif() + list(APPEND srcs "tusb_tasks.c") +endif() # CONFIG_TINYUSB_NO_DEFAULT_TASK if(CONFIG_TINYUSB_CDC_ENABLED) list(APPEND srcs - "additions/src/cdc.c" - "additions/src/tusb_cdc_acm.c" - "additions/src/tusb_console.c" - "additions/src/vfs_tinyusb.c" + "cdc.c" + "tusb_cdc_acm.c" ) + if(CONFIG_VFS_SUPPORT_IO) + list(APPEND srcs + "tusb_console.c" + "vfs_tinyusb.c" + ) + endif() # CONFIG_VFS_SUPPORT_IO endif() # CONFIG_TINYUSB_CDC_ENABLED +if(CONFIG_TINYUSB_MSC_ENABLED) + list(APPEND srcs + tusb_msc_storage.c + ) +endif() # CONFIG_TINYUSB_MSC_ENABLED + +if(CONFIG_TINYUSB_NET_MODE_NCM) + list(APPEND srcs + tinyusb_net.c + ) +endif() # CONFIG_TINYUSB_NET_MODE_NCM + idf_component_register(SRCS ${srcs} - INCLUDE_DIRS ${includes_public} - PRIV_INCLUDE_DIRS ${includes_private} - PRIV_REQUIRES "vfs" "usb" "driver" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "include_private" + PRIV_REQUIRES usb + REQUIRES fatfs vfs ) -target_compile_options(${COMPONENT_LIB} PRIVATE ${compile_options}) +# Determine whether tinyusb is fetched from component registry or from local path +idf_build_get_property(build_components BUILD_COMPONENTS) +if(tinyusb IN_LIST build_components) + set(tinyusb_name tinyusb) # Local component +else() + set(tinyusb_name espressif__tinyusb) # Managed component +endif() -# when no builtin class driver is enabled, an uint8_t data compared with `BUILTIN_DRIVER_COUNT` will always be false -set_source_files_properties("src/device/usbd.c" PROPERTIES COMPILE_FLAGS "-Wno-type-limits") +# Pass tusb_config.h from this component to TinyUSB +idf_component_get_property(tusb_lib ${tinyusb_name} COMPONENT_LIB) +target_include_directories(${tusb_lib} PRIVATE "include") diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst b/examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst deleted file mode 100644 index 4035c528f..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst +++ /dev/null @@ -1,88 +0,0 @@ -*************** -Code of Conduct -*************** - -Our Pledge ----------- - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our -project and our community a harassment-free experience for everyone, -regardless of age, body size, disability, ethnicity, sex -characteristics, gender identity and expression, level of experience, -education, socio-economic status, nationality, personal appearance, -race, religion, or sexual identity and orientation. - -Our Standards -------------- - -Examples of behavior that contributes to creating a positive environment -include: - -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -- The use of sexualized language or imagery and unwelcome sexual - attention or advances -- Trolling, insulting/derogatory comments, and personal or political - attacks -- Public or private harassment -- Publishing others' private information, such as a physical or - electronic address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -Our Responsibilities --------------------- - -Project maintainers are responsible for clarifying the standards of -acceptable behavior and are expected to take appropriate and fair -corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, -or reject comments, commits, code, wiki edits, issues, and other -contributions that are not aligned to this Code of Conduct, or to ban -temporarily or permanently any contributor for other behaviors that they -deem inappropriate, threatening, offensive, or harmful. - -Scope ------ - -This Code of Conduct applies both within project spaces and in public -spaces when an individual is representing the project or its community. -Examples of representing a project or community include using an -official project e-mail address, posting via an official social media -account, or acting as an appointed representative at an online or -offline event. Representation of a project may be further defined and -clarified by project maintainers. - -Enforcement ------------ - -Instances of abusive, harassing, or otherwise unacceptable behavior may -be reported by contacting the project team at thach@tinyusb.org. All -complaints will be reviewed and investigated and will result in a -response that is deemed necessary and appropriate to the circumstances. -The project team is obligated to maintain confidentiality with regard to -the reporter of an incident. Further details of specific enforcement -policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in -good faith may face temporary or permanent repercussions as determined -by other members of the project's leadership. - -Attribution ------------ - -This Code of Conduct is adapted from the `Contributor -Covenant `__, version 1.4, -available at -https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst b/examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst deleted file mode 100644 index e3186f086..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst +++ /dev/null @@ -1,192 +0,0 @@ -************ -Contributors -************ - -Special thanks to all the people who spent their precious time and effort to help this project so far. -list contributors and their awesome work for the stack: - -Notable contributors -==================== - -(sorted alphabetically) - -`Adafruit Team `__ ------------------------------------------------ - -- Main supporter and sponsor for hardware boards and kits -- Discussion and suggestion for feature and improvement -- Design the project logo - - -`Ha Thach `__ ------------------------------------------ - -- *Author and maintainer* -- Most features development - - -`Hristo Gochkov `__ -------------------------------------------------- - -- Improve ESP32s2 DCD - - -`Jacob Berg Potter `__ ------------------------------------------------- - -- Add new class driver for network CDC-NCM - - -`Jan Dümpelmann `__ ------------------------------------------------ - -- Improve transfer performance for Synopsys DCD for STM32 MCUs - - -`Jeff Epler `__ ------------------------------------------- - -- Improve MIDI class driver - - -`Jerzy Kasenberg `__ ------------------------------------------------ - -- Add new DCD port for Dialog DA1469x -- Add new class driver for Bluetooth HCI -- Add ISO transfer for STM32 Synopsys, Nordic nRF, Dialog DA1469x -- Improve Audio driver and add uac2\_headset example -- Improve STM32 Synopsys DCD with various PRs - - -`J McCarthy `__ --------------------------------------------------- - -- Add new DFU 1.1 class driver -- Add new example for dfu - - -`Kamil Tomaszewski `__ ----------------------------------------------------- - -- Add new DCD port for Sony CXD56 (spresnese board) - - -`Kay Sievers `__ ------------------------------------------------ - -- Improve MIDI driver with packet API - - -`Koji KITAYAMA `__ ------------------------------------------------ - -- Add new DCD port for NXP Kinetis KL25 -- Add new DCD port for Renesas RX family (RX600, RX700 ..) with GR-CITRUS, RX65n target board -- Add new class driver for USB Video Class (UVC 1.5) - - -`Nathan Conrad `__ ---------------------------------------------- - -- Add new DCD port for STM32 fsdev Fullspeed device for STM32 L0, - F0, F1, F3 etc ... -- Add new class driver for USB Test and Measurement Class (USBTMC) -- Various improvement e.g Zero-length packet, Lint setup -- Board support for STM32F070RB Nucleo, STM32F303 Discovery - - -`Peter Lawrence `__ ------------------------------------------------- - -- Add new DCD port for Nuvoton NUC 120, 121, 125, 126, 505 -- Add new class driver for network RNDIS, CDC-ECM -- Enhance CDC-NCM network driver to compatible with RNDIS/ECM -- Add *net\_lwip\_webserver* example for demonstration of usbnet with lwip -- Board support for NuTiny NUC120, NUC121s, NUC125s, NUC126V, NUC505 -- Improve multiple cdc interfaces API & add cdc\_dual\_ports example - - -`Rafael Silva `__ ----------------------------------------------- - -- Port DCD Synopsys to support Silabs EFM32GG12 with SLTB009A board -- Rewrite documentation in rst and setup for readthedocs - - -`Raspberry Pi Team `__ ------------------------------------------------------- - -- Add new DCD port for Raspberry Pi RP2040 -- Add new HCD port for Raspberry Pi RP2040 - - -`Reinhard Panhuber `__ ------------------------------------------------- - -- Add new class driver for USB Audio Class 2.0 (UAC2) -- Rework tu\_fifo with unmasked pointer, add DMA support, and constant address support -- Add new DCD/USBD edpt\_xfer\_fifo() API for optimizing endpoint transfer -- Add and greatly improve Isochronous transfer -- Add new audio examples: audio\_test and audio\_4\_channel\_mic - - -`Scott Shawcroft `__ ------------------------------------------------- - -- Add new DCD port for SAMD21 and SAMD51 -- Add new class driver for Musical Instrument Digital Interface (MIDI) -- Improve USBD control transfer, MSC, CDC class driver -- Board support for Metro M0 & M4 express -- Write the excellent porting.md documentation -- Add initial Makefile - -`Sean Cross `__ ----------------------------------------- - -- Add new DCD port for ValentyUSB eptri (fomu board) - - -`Sylvain "tnt" Munaut `__ ------------------------------------------------------ - -- Add new class driver for DFU Runtime - - -`Timon Skerutsch `__ ----------------------------------------------- - -- Add hid\_test.js script and extensive test for bi-directional raw HID - - -`Tod E. Kurt `__ -------------------------------------------- - -- Add hid\_test.js script and extensive test for bi-directional raw HID - - -`Uwe Bonnes `__ ---------------------------------------------- - -- Improve STM32 Synopsys highspeed DCD - - -`William D. Jones `__ ------------------------------------------------- - -- Add new DCD port for Synopsys DesignWare for STM32 L4, F2, F4, - F7, H7 etc ... -- Add new DCD port for TI MSP430 -- Board support for STM32F407 Discovery, STM32H743 Nucleo, pyboard v1.1, msp\_exp430f5529lp etc ... - - -`Zixun Li `__ -------------------------------------------- - -- Add new DCD port for Microchip SAMx7x -- Add IAR compiler support -- Improve UAC2, CDC, DFU class driver - - -`Full contributors list `__ -============================================================================ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig b/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig index 324fe70ec..7b01f4c37 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig @@ -1,11 +1,22 @@ menu "TinyUSB Stack" config TINYUSB_DEBUG_LEVEL int "TinyUSB log level (0-3)" - default 0 + default 1 range 0 3 help Specify verbosity of TinyUSB log output. + choice TINYUSB_RHPORT + depends on IDF_TARGET_ESP32P4 + prompt "TinyUSB PHY" + default TINYUSB_RHPORT_HS + help + Allows set the USB PHY Controller for TinyUSB: HS (USB OTG2.0 PHY for HighSpeed) + + config TINYUSB_RHPORT_HS + bool "HS" + endchoice + menu "TinyUSB task configuration" config TINYUSB_NO_DEFAULT_TASK bool "Do not create a TinyUSB task" @@ -27,9 +38,43 @@ menu "TinyUSB Stack" depends on !TINYUSB_NO_DEFAULT_TASK help Set the stack size of the default TinyUSB main task. + + choice TINYUSB_TASK_AFFINITY + prompt "TinyUSB task affinity" + default TINYUSB_TASK_AFFINITY_NO_AFFINITY + depends on !TINYUSB_NO_DEFAULT_TASK + help + Allows setting TinyUSB tasks affinity, i.e. whether the task is pinned to + CPU0, pinned to CPU1, or allowed to run on any CPU. + + config TINYUSB_TASK_AFFINITY_NO_AFFINITY + bool "No affinity" + config TINYUSB_TASK_AFFINITY_CPU0 + bool "CPU0" + config TINYUSB_TASK_AFFINITY_CPU1 + bool "CPU1" + depends on !FREERTOS_UNICORE + endchoice + + config TINYUSB_TASK_AFFINITY + hex + default FREERTOS_NO_AFFINITY if TINYUSB_TASK_AFFINITY_NO_AFFINITY + default 0x0 if TINYUSB_TASK_AFFINITY_CPU0 + default 0x1 if TINYUSB_TASK_AFFINITY_CPU1 + + config TINYUSB_INIT_IN_DEFAULT_TASK + bool "Initialize TinyUSB stack within the default TinyUSB task" + default n + depends on !TINYUSB_NO_DEFAULT_TASK + help + Run TinyUSB stack initialization just after starting the default TinyUSB task. + This is especially useful in multicore scenarios, when we need to pin the task + to a specific core and, at the same time initialize TinyUSB stack + (i.e. install interrupts) on the same core. endmenu menu "Descriptor configuration" + comment "You can provide your custom descriptors via tinyusb_driver_install()" config TINYUSB_DESC_USE_ESPRESSIF_VID bool "VID: Use Espressif's vendor ID" default y @@ -110,6 +155,13 @@ menu "TinyUSB Stack" range 64 10000 help MSC FIFO size, in bytes. + + config TINYUSB_MSC_MOUNT_PATH + depends on TINYUSB_MSC_ENABLED + string "Mount Path" + default "/data" + help + MSC Mount Path of storage. endmenu # "Massive Storage Class" menu "Communication Device Class (CDC)" @@ -130,7 +182,7 @@ menu "TinyUSB Stack" config TINYUSB_CDC_RX_BUFSIZE depends on TINYUSB_CDC_ENABLED int "CDC FIFO size of RX channel" - default 64 + default 512 range 64 10000 help CDC FIFO size of RX channel. @@ -138,7 +190,7 @@ menu "TinyUSB Stack" config TINYUSB_CDC_TX_BUFSIZE depends on TINYUSB_CDC_ENABLED int "CDC FIFO size of TX channel" - default 64 + default 512 help CDC FIFO size of TX channel. endmenu # "Communication Device Class" @@ -160,4 +212,61 @@ menu "TinyUSB Stack" help Setting value greater than 0 will enable TinyUSB HID feature. endmenu # "HID Device Class (HID)" + + menu "Device Firmware Upgrade (DFU)" + choice TINYUSB_DFU_MODE + prompt "DFU mode" + default TINYUSB_DFU_MODE_NONE + help + Select which DFU driver you want to use. + + config TINYUSB_DFU_MODE_DFU + bool "DFU" + + config TINYUSB_DFU_MODE_DFU_RUNTIME + bool "DFU Runtime" + + config TINYUSB_DFU_MODE_NONE + bool "None" + endchoice + config TINYUSB_DFU_BUFSIZE + depends on TINYUSB_DFU_MODE_DFU + int "DFU XFER BUFFSIZE" + default 512 + help + DFU XFER BUFFSIZE. + endmenu # Device Firmware Upgrade (DFU) + + menu "Bluetooth Host Class (BTH)" + config TINYUSB_BTH_ENABLED + bool "Enable TinyUSB BTH feature" + default n + help + Enable TinyUSB BTH feature. + + config TINYUSB_BTH_ISO_ALT_COUNT + depends on TINYUSB_BTH_ENABLED + int "BTH ISO ALT COUNT" + default 0 + help + BTH ISO ALT COUNT. + endmenu # "Bluetooth Host Device Class" + + menu "Network driver (ECM/NCM/RNDIS)" + choice TINYUSB_NET_MODE + prompt "Network mode" + default TINYUSB_NET_MODE_NONE + help + Select network driver you want to use. + + config TINYUSB_NET_MODE_ECM_RNDIS + bool "ECM/RNDIS" + + config TINYUSB_NET_MODE_NCM + bool "NCM" + + config TINYUSB_NET_MODE_NONE + bool "None" + endchoice + endmenu # "Network driver (ECM/NCM/RNDIS)" endmenu # "TinyUSB Stack" diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE b/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE index ddd4ab410..d64569567 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE @@ -1,21 +1,202 @@ -The MIT License (MIT) - -Copyright (c) 2018, hathach (tinyusb.org) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/README.md b/examples/espidf-peripherals-usb/components/esp_tinyusb/README.md new file mode 100644 index 000000000..478f206a5 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/README.md @@ -0,0 +1,32 @@ +# Espressif's additions to TinyUSB + +[![Component Registry](https://components.espressif.com/components/espressif/esp_tinyusb/badge.svg)](https://components.espressif.com/components/espressif/esp_tinyusb) + +This component adds features to TinyUSB that help users with integrating TinyUSB with their ESP-IDF application. + +It contains: +* Configuration of USB device and string descriptors +* USB Serial Device (CDC-ACM) with optional Virtual File System support +* Input and output streams through USB Serial Device. This feature is available only when Virtual File System support is enabled. +* Other USB classes (MIDI, MSC, HID…) support directly via TinyUSB +* VBUS monitoring for self-powered devices +* SPI Flash or sd-card access via MSC USB device Class. + +## Documentation and examples +You can find documentation in [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_device.html). + +You can find examples in [ESP-IDF on GitHub](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb/device). +## How to use? + +This component is distributed via [IDF component manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html). Just add `idf_component.yml` file to your main component with the following content: + +``` yaml +## IDF Component Manager Manifest File +dependencies: + esp_tinyusb: "~1.0.0" +``` + +Or simply run: +``` +idf.py add-dependency esp_tinyusb~1.0.0 +``` diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst b/examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst deleted file mode 100644 index 4946e997e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst +++ /dev/null @@ -1,145 +0,0 @@ -.. figure:: docs/assets/logo.svg - :alt: TinyUSB - -|Build Status| |Documentation Status| |License| - -TinyUSB is an open-source cross-platform USB Host/Device stack for -embedded system, designed to be memory-safe with no dynamic allocation -and thread-safe with all interrupt events are deferred then handled in -the non-ISR task function. - -Please take a look at the online `documentation `__. - -.. figure:: docs/assets/stack.svg - :width: 500px - :alt: stackup - -:: - - . - ├── docs # Documentation - ├── examples # Sample with Makefile build support - ├── hw - │   ├── bsp # Supported boards source files - │   └── mcu # Low level mcu core & peripheral drivers - ├── lib # Sources from 3rd party such as freeRTOS, fatfs ... - ├── src # All sources files for TinyUSB stack itself. - ├── test # Unit tests for the stack - └── tools # Files used internally - -Supported MCUs -============== - -The stack supports the following MCUs: - -- **Broadcom:** BCM2837, BCM2711 -- **Dialog:** DA1469x -- **Espressif:** ESP32-S2, ESP32-S3 -- **GigaDevice:** GD32VF103 -- **Infineon:** XMC4500 -- **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55, SAML21, SAML22, SAME7x -- **NordicSemi:** nRF52833, nRF52840, nRF5340 -- **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505 -- **NXP:** - - - iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064 - - Kinetis: KL25, K32L2 - - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55 - -- **Raspberry Pi:** RP2040 -- **Renesas:** RX63N, RX65N, RX72N -- **Silabs:** EFM32GG -- **Sony:** CXD56 -- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+ -- **TI:** MSP430, MSP432E4, TM4C123 -- **ValentyUSB:** eptri - -Here is the list of `Supported Devices`_ that can be used with provided examples. - -Device Stack -============ - -Supports multiple device configurations by dynamically changing USB descriptors, low power functions such like suspend, resume, and remote wakeup. The following device classes are supported: - -- Audio Class 2.0 (UAC2) -- Bluetooth Host Controller Interface (BTH HCI) -- Communication Device Class (CDC) -- Device Firmware Update (DFU): DFU mode (WIP) and Runtinme -- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ... -- Mass Storage Class (MSC): with multiple LUNs -- Musical Instrument Digital Interface (MIDI) -- Network with RNDIS, Ethernet Control Model (ECM), Network Control Model (NCM) -- Test and Measurement Class (USBTMC) -- Video class 1.5 (UVC): work in progress -- Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file. -- `WebUSB `__ with vendor-specific class - -If you have a special requirement, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface `raspberrypi/pico-sdk#197 `_ - -Host Stack -========== - -- Human Interface Device (HID): Keyboard, Mouse, Generic -- Mass Storage Class (MSC) -- Hub currently only supports 1 level of hub (due to my laziness) - -OS Abstraction layer -==================== - -TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) events into a central queue, then processing them later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as Communication Device Class (CDC) FIFO. Therefore the stack needs to use some of the OS's basic APIs. Following OSes are already supported out of the box. - -- **No OS** -- **FreeRTOS** -- `RT-Thread `_ -- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its `own repo `_ - -Local Docs -========== - -- Info - - - `Uses`_ - - `Changelog`_ - - `Contributors`_ - -- `Reference`_ - - - `Supported Devices`_ - - `Getting Started`_ - - `Concurrency`_ - -- `Contributing`_ - - - `Code of Conduct`_ - - `Structure`_ - - `Porting`_ - -License -======= - -All TinyUSB sources in the ``src`` folder are licensed under MIT -license, the `Full license is here `__. However, each file can be -individually licensed especially those in ``lib`` and ``hw/mcu`` folder. -Please make sure you understand all the license term for files you use -in your project. - - -.. |Build Status| image:: https://github.com/hathach/tinyusb/workflows/Build/badge.svg - :target: https://github.com/hathach/tinyusb/actions -.. |Documentation Status| image:: https://readthedocs.org/projects/tinyusb/badge/?version=latest - :target: https://docs.tinyusb.org/en/latest/?badge=latest -.. |License| image:: https://img.shields.io/badge/license-MIT-brightgreen.svg - :target: https://opensource.org/licenses/MIT - - -.. _Uses: docs/info/uses.rst -.. _Changelog: docs/info/changelog.rst -.. _Contributors: CONTRIBUTORS.rst -.. _Reference: docs/reference/index.rst -.. _Supported Devices: docs/reference/supported.rst -.. _Getting Started: docs/reference/getting_started.rst -.. _Concurrency: docs/reference/concurrency.rst -.. _Contributing: docs/contributing/index.rst -.. _Code of Conduct: CODE_OF_CONDUCT.rst -.. _Structure: docs/contributing/structure.rst -.. _Porting: docs/contributing/porting.rst diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h deleted file mode 100644 index 1f01fe132..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#define USB_ESPRESSIF_VID 0x303A -#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8 // (4 + TINYUSB_STR_DESC_LEN) - -typedef enum{ - TINYUSB_USBDEV_0, -} tinyusb_usbdev_t; - -typedef const char *tusb_desc_strarray_device_t[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h deleted file mode 100644 index 79c69bd72..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Register TinyUSB CDC at VFS with path - * @param cdc_intf - interface number of TinyUSB's CDC - * @param path - path where the CDC will be registered, `/dev/tusb_cdc` will be used if left NULL. - * - * @return esp_err_t ESP_OK or ESP_FAIL - */ -esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path); - -/** - * @brief Unregister TinyUSB CDC from VFS - * @param path - path where the CDC will be unregistered if NULL will be used `/dev/tusb_cdc` - * - * @return esp_err_t ESP_OK or ESP_FAIL - */ -esp_err_t esp_vfs_tusb_cdc_unregister(char const *path); - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h deleted file mode 100644 index b6516e1a7..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "tusb.h" -#include "tinyusb_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void tusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, const uint8_t *cfg_desc); -tusb_desc_device_t *tusb_get_active_desc(void); -char **tusb_get_active_str_desc(void); -void tusb_clear_descriptor(void); - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h deleted file mode 100644 index 215010c94..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "tusb.h" -#include "tinyusb_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) - -extern tusb_desc_device_t descriptor_tinyusb; -extern tusb_desc_strarray_device_t descriptor_str_tinyusb; - -extern const tusb_desc_device_t descriptor_dev_kconfig; -extern tusb_desc_strarray_device_t descriptor_str_kconfig; -extern const uint8_t descriptor_cfg_kconfig[]; - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c deleted file mode 100644 index 7e9ed4cbe..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "esp_log.h" -#include "descriptors_control.h" - -static const char *TAG = "tusb_desc"; -static tusb_desc_device_t s_device_descriptor; -static const uint8_t *s_configuration_descriptor; -static char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; -#define MAX_DESC_BUF_SIZE 32 - -// ============================================================================= -// CALLBACKS -// ============================================================================= - -/** - * @brief Invoked when received GET DEVICE DESCRIPTOR. - * Application returns pointer to descriptor - * - * @return uint8_t const* - */ -uint8_t const *tud_descriptor_device_cb(void) -{ - return (uint8_t const *)&s_device_descriptor; -} - -/** - * @brief Invoked when received GET CONFIGURATION DESCRIPTOR. - * Descriptor contents must exist long enough for transfer to complete - * - * @param index - * @return uint8_t const* Application return pointer to descriptor - */ -uint8_t const *tud_descriptor_configuration_cb(uint8_t index) -{ - (void)index; // for multiple configurations - return s_configuration_descriptor; -} - -static uint16_t _desc_str[MAX_DESC_BUF_SIZE]; - -// Invoked when received GET STRING DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) -{ - (void) langid; - - uint8_t chr_count; - - if ( index == 0) { - memcpy(&_desc_str[1], s_str_descriptor[0], 2); - chr_count = 1; - } else { - // Convert ASCII string into UTF-16 - - if ( index >= sizeof(s_str_descriptor) / sizeof(s_str_descriptor[0]) ) { - ESP_LOGE(TAG, "String index (%u) is out of bounds, check your string descriptor", index); - return NULL; - } - - if (s_str_descriptor[index] == NULL) { - ESP_LOGE(TAG, "String index (%u) points to NULL, check your string descriptor", index); - return NULL; - } - - const char *str = s_str_descriptor[index]; - - // Cap at max char - chr_count = strlen(str); - if ( chr_count > MAX_DESC_BUF_SIZE - 1 ) { - chr_count = MAX_DESC_BUF_SIZE - 1; - } - - for (uint8_t i = 0; i < chr_count; i++) { - _desc_str[1 + i] = str[i]; - } - } - - // first byte is length (including header), second byte is string type - _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2); - - return _desc_str; -} - -// ============================================================================= -// Driver functions -// ============================================================================= - -void tusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, const uint8_t *cfg_desc) -{ - ESP_LOGI(TAG, "\n" - "┌─────────────────────────────────┐\n" - "│ USB Device Descriptor Summary │\n" - "├───────────────────┬─────────────┤\n" - "│bDeviceClass │ %-4u │\n" - "├───────────────────┼─────────────┤\n" - "│bDeviceSubClass │ %-4u │\n" - "├───────────────────┼─────────────┤\n" - "│bDeviceProtocol │ %-4u │\n" - "├───────────────────┼─────────────┤\n" - "│bMaxPacketSize0 │ %-4u │\n" - "├───────────────────┼─────────────┤\n" - "│idVendor │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│idProduct │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│bcdDevice │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│iManufacturer │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│iProduct │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│iSerialNumber │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│bNumConfigurations │ %-#10x │\n" - "└───────────────────┴─────────────┘", - dev_desc->bDeviceClass, dev_desc->bDeviceSubClass, - dev_desc->bDeviceProtocol, dev_desc->bMaxPacketSize0, - dev_desc->idVendor, dev_desc->idProduct, dev_desc->bcdDevice, - dev_desc->iManufacturer, dev_desc->iProduct, dev_desc->iSerialNumber, - dev_desc->bNumConfigurations); - s_device_descriptor = *dev_desc; - s_configuration_descriptor = cfg_desc; - - if (str_desc != NULL) { - memcpy(s_str_descriptor, str_desc, - sizeof(s_str_descriptor[0])*USB_STRING_DESCRIPTOR_ARRAY_SIZE); - } -} - -tusb_desc_device_t *tusb_get_active_desc(void) -{ - return &s_device_descriptor; -} - -char **tusb_get_active_str_desc(void) -{ - return s_str_descriptor; -} - -void tusb_clear_descriptor(void) -{ - memset(&s_device_descriptor, 0, sizeof(s_device_descriptor)); - memset(&s_str_descriptor, 0, sizeof(s_str_descriptor)); -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c deleted file mode 100644 index bf0681db5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "esp_check.h" -#include "tinyusb.h" -#include "tusb_tasks.h" - -const static char *TAG = "tusb_tsk"; -static TaskHandle_t s_tusb_tskh; - -/** - * @brief This top level thread processes all usb events and invokes callbacks - */ -static void tusb_device_task(void *arg) -{ - ESP_LOGD(TAG, "tinyusb task started"); - while (1) { // RTOS forever loop - tud_task(); - } -} - -esp_err_t tusb_run_task(void) -{ - // This function is not garanteed to be thread safe, if invoked multiple times without calling `tusb_stop_task`, will cause memory leak - // doing a sanity check anyway - ESP_RETURN_ON_FALSE(!s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task already started"); - // Create a task for tinyusb device stack: - xTaskCreate(tusb_device_task, "TinyUSB", CONFIG_TINYUSB_TASK_STACK_SIZE, NULL, CONFIG_TINYUSB_TASK_PRIORITY, &s_tusb_tskh); - ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed"); - return ESP_OK; -} - -esp_err_t tusb_stop_task(void) -{ - ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task not started yet"); - vTaskDelete(s_tusb_tskh); - s_tusb_tskh = NULL; - return ESP_OK; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/cdc.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/cdc.c similarity index 100% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/cdc.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/cdc.c diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/descriptors_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/descriptors_control.c new file mode 100644 index 000000000..67b6cb3e2 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/descriptors_control.c @@ -0,0 +1,294 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_log.h" +#include "esp_check.h" +#include "esp_err.h" +#include "descriptors_control.h" +#include "usb_descriptors.h" + +#define MAX_DESC_BUF_SIZE 32 // Max length of string descriptor (can be extended, USB supports lengths up to 255 bytes) + +static const char *TAG = "tusb_desc"; + +// ============================================================================= +// STRUCTS +// ============================================================================= + +/** + * @brief Descriptor pointers for tinyusb descriptor requests callbacks + * + */ +typedef struct { + const tusb_desc_device_t *dev; /*!< Pointer to device descriptor */ + union { + const uint8_t *cfg; /*!< Pointer to FullSpeed configuration descriptor when device one-speed only */ + const uint8_t *fs_cfg; /*!< Pointer to FullSpeed configuration descriptor when device support HighSpeed */ + }; +#if (TUD_OPT_HIGH_SPEED) + const uint8_t *hs_cfg; /*!< Pointer to HighSpeed configuration descriptor */ + const tusb_desc_device_qualifier_t *qualifier; /*!< Pointer to Qualifier descriptor */ + uint8_t *other_speed; /*!< Pointer for other speed configuration descriptor */ +#endif // TUD_OPT_HIGH_SPEED + const char *str[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; /*!< Pointer to array of UTF-8 strings */ + int str_count; /*!< Number of descriptors in str */ +} tinyusb_descriptor_config_t; + +static tinyusb_descriptor_config_t s_desc_cfg; + +// ============================================================================= +// CALLBACKS +// ============================================================================= + +/** + * @brief Invoked when received GET DEVICE DESCRIPTOR. + * Descriptor contents must exist long enough for transfer to complete + * + * @return Pointer to device descriptor + */ +uint8_t const *tud_descriptor_device_cb(void) +{ + assert(s_desc_cfg.dev); + return (uint8_t const *)s_desc_cfg.dev; +} + +/** + * @brief Invoked when received GET CONFIGURATION DESCRIPTOR. + * Descriptor contents must exist long enough for transfer to complete + * + * @param[in] index Index of required configuration + * @return Pointer to configuration descriptor + */ +uint8_t const *tud_descriptor_configuration_cb(uint8_t index) +{ + (void)index; // Unused, this driver supports only 1 configuration + assert(s_desc_cfg.cfg); + +#if (TUD_OPT_HIGH_SPEED) + // HINT: cfg and fs_cfg are union, no need to assert(fs_cfg) + assert(s_desc_cfg.hs_cfg); + // Return configuration descriptor based on Host speed + return (TUSB_SPEED_HIGH == tud_speed_get()) + ? s_desc_cfg.hs_cfg + : s_desc_cfg.fs_cfg; +#else + return s_desc_cfg.cfg; +#endif // TUD_OPT_HIGH_SPEED +} + +#if (TUD_OPT_HIGH_SPEED) +/** + * @brief Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request + * Descriptor contents must exist long enough for transfer to complete + * If not highspeed capable stall this request + */ +uint8_t const *tud_descriptor_device_qualifier_cb(void) +{ + assert(s_desc_cfg.qualifier); + return (uint8_t const *)s_desc_cfg.qualifier; +} + +/** + * @brief Invoked when received GET OTHER SPEED CONFIGURATION DESCRIPTOR request + * Descriptor contents must exist long enough for transfer to complete + * Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa + */ +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) +{ + assert(s_desc_cfg.other_speed); + + const uint8_t *other_speed = (TUSB_SPEED_HIGH == tud_speed_get()) + ? s_desc_cfg.fs_cfg + : s_desc_cfg.hs_cfg; + + memcpy(s_desc_cfg.other_speed, + other_speed, + ((tusb_desc_configuration_t *)other_speed)->wTotalLength); + + ((tusb_desc_configuration_t *)s_desc_cfg.other_speed)->bDescriptorType = TUSB_DESC_OTHER_SPEED_CONFIG; + return s_desc_cfg.other_speed; +} +#endif // TUD_OPT_HIGH_SPEED + +/** + * @brief Invoked when received GET STRING DESCRIPTOR request + * + * @param[in] index Index of required descriptor + * @param[in] langid Language of the descriptor + * @return Pointer to UTF-16 string descriptor + */ +uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; // Unused, this driver supports only one language in string descriptors + assert(s_desc_cfg.str); + uint8_t chr_count; + static uint16_t _desc_str[MAX_DESC_BUF_SIZE]; + + if (index == 0) { + memcpy(&_desc_str[1], s_desc_cfg.str[0], 2); + chr_count = 1; + } else { + if (index >= USB_STRING_DESCRIPTOR_ARRAY_SIZE) { + ESP_LOGW(TAG, "String index (%u) is out of bounds, check your string descriptor", index); + return NULL; + } + + if (s_desc_cfg.str[index] == NULL) { + ESP_LOGW(TAG, "String index (%u) points to NULL, check your string descriptor", index); + return NULL; + } + + const char *str = s_desc_cfg.str[index]; + chr_count = strnlen(str, MAX_DESC_BUF_SIZE - 1); // Buffer len - header + + // Convert ASCII string into UTF-16 + for (uint8_t i = 0; i < chr_count; i++) { + _desc_str[1 + i] = str[i]; + } + } + + // First byte is length in bytes (including header), second byte is descriptor type (TUSB_DESC_STRING) + _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2); + + return _desc_str; +} + +// ============================================================================= +// Driver functions +// ============================================================================= +esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config) +{ + esp_err_t ret = ESP_FAIL; + assert(config); + const char **pstr_desc; + // Flush descriptors control struct + memset(&s_desc_cfg, 0x00, sizeof(tinyusb_descriptor_config_t)); + // Parse configuration and save descriptors's pointer + // Select Device Descriptor + if (config->device_descriptor == NULL) { + ESP_LOGW(TAG, "No Device descriptor provided, using default."); + s_desc_cfg.dev = &descriptor_dev_default; + } else { + s_desc_cfg.dev = config->device_descriptor; + } + + // Select FullSpeed configuration descriptor + if (config->configuration_descriptor == NULL) { + // Default configuration descriptor is provided only for CDC, MSC and NCM classes +#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0) + ESP_GOTO_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, fail, TAG, "Configuration descriptor must be provided for this device"); +#else + ESP_LOGW(TAG, "No FullSpeed configuration descriptor provided, using default."); + s_desc_cfg.cfg = descriptor_fs_cfg_default; +#endif + } else { + s_desc_cfg.cfg = config->configuration_descriptor; + } + +#if (TUD_OPT_HIGH_SPEED) + // High Speed + if (config->hs_configuration_descriptor == NULL) { + // Default configuration descriptor is provided only for CDC, MSC and NCM classes +#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0) + ESP_GOTO_ON_FALSE(config->hs_configuration_descriptor, ESP_ERR_INVALID_ARG, fail, TAG, "HighSpeed configuration descriptor must be provided for this device"); +#else + ESP_LOGW(TAG, "No HighSpeed configuration descriptor provided, using default."); + s_desc_cfg.hs_cfg = descriptor_hs_cfg_default; +#endif + } else { + s_desc_cfg.hs_cfg = config->hs_configuration_descriptor; + } + + // HS and FS cfg desc should be equal length + ESP_GOTO_ON_FALSE(((tusb_desc_configuration_t *)s_desc_cfg.hs_cfg)->wTotalLength == + ((tusb_desc_configuration_t *)s_desc_cfg.fs_cfg)->wTotalLength, + ESP_ERR_INVALID_ARG, fail, TAG, "HighSpeed and FullSpeed configuration descriptors must be same length"); + + // Qualifier Descriptor + if (config->qualifier_descriptor == NULL) { + ESP_GOTO_ON_FALSE((s_desc_cfg.dev == &descriptor_dev_default), ESP_ERR_INVALID_ARG, fail, TAG, "Qualifier descriptor must be present (Device Descriptor not default)."); + // Get default qualifier if device descriptor is default + ESP_LOGW(TAG, "No Qulifier descriptor provided, using default."); + s_desc_cfg.qualifier = &descriptor_qualifier_default; + } else { + s_desc_cfg.qualifier = config->qualifier_descriptor; + } + + // Other Speed buffer allocate + s_desc_cfg.other_speed = calloc(1, ((tusb_desc_configuration_t *)s_desc_cfg.hs_cfg)->wTotalLength); + ESP_GOTO_ON_FALSE(s_desc_cfg.other_speed, ESP_ERR_NO_MEM, fail, TAG, "Other speed memory allocation error"); +#endif // TUD_OPT_HIGH_SPEED + + // Select String Descriptors and count them + if (config->string_descriptor == NULL) { + ESP_LOGW(TAG, "No String descriptors provided, using default."); + pstr_desc = descriptor_str_default; + while (descriptor_str_default[++s_desc_cfg.str_count] != NULL); + } else { + pstr_desc = config->string_descriptor; + s_desc_cfg.str_count = (config->string_descriptor_count != 0) + ? config->string_descriptor_count + : 8; // '8' is for backward compatibility with esp_tinyusb v1.0.0. Do NOT remove! + } + + ESP_GOTO_ON_FALSE(s_desc_cfg.str_count <= USB_STRING_DESCRIPTOR_ARRAY_SIZE, ESP_ERR_NOT_SUPPORTED, fail, TAG, "String descriptors exceed limit"); + memcpy(s_desc_cfg.str, pstr_desc, s_desc_cfg.str_count * sizeof(pstr_desc[0])); + + ESP_LOGI(TAG, "\n" + "┌─────────────────────────────────┐\n" + "│ USB Device Descriptor Summary │\n" + "├───────────────────┬─────────────┤\n" + "│bDeviceClass │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│bDeviceSubClass │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│bDeviceProtocol │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│bMaxPacketSize0 │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│idVendor │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│idProduct │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│bcdDevice │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│iManufacturer │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│iProduct │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│iSerialNumber │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│bNumConfigurations │ %-#10x │\n" + "└───────────────────┴─────────────┘", + s_desc_cfg.dev->bDeviceClass, s_desc_cfg.dev->bDeviceSubClass, + s_desc_cfg.dev->bDeviceProtocol, s_desc_cfg.dev->bMaxPacketSize0, + s_desc_cfg.dev->idVendor, s_desc_cfg.dev->idProduct, s_desc_cfg.dev->bcdDevice, + s_desc_cfg.dev->iManufacturer, s_desc_cfg.dev->iProduct, s_desc_cfg.dev->iSerialNumber, + s_desc_cfg.dev->bNumConfigurations); + + return ESP_OK; + +fail: +#if (TUD_OPT_HIGH_SPEED) + free(s_desc_cfg.other_speed); +#endif // TUD_OPT_HIGH_SPEED + return ret; +} + +void tinyusb_set_str_descriptor(const char *str, int str_idx) +{ + assert(str_idx < USB_STRING_DESCRIPTOR_ARRAY_SIZE); + s_desc_cfg.str[str_idx] = str; +} + +void tinyusb_free_descriptors(void) +{ +#if (TUD_OPT_HIGH_SPEED) + assert(s_desc_cfg.other_speed); + free(s_desc_cfg.other_speed); +#endif // TUD_OPT_HIGH_SPEED +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h deleted file mode 100644 index 35342cfe5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_board - * \defgroup group_ansi_esc ANSI Esacpe Code - * @{ */ - -#ifndef _TUSB_ANSI_ESC_CODE_H_ -#define _TUSB_ANSI_ESC_CODE_H_ - - -#ifdef __cplusplus - extern "C" { -#endif - -#define CSI_CODE(seq) "\33[" seq -#define CSI_SGR(x) CSI_CODE(#x) "m" - -//------------- Cursor movement -------------// -/** \defgroup group_ansi_cursor Cursor Movement - * @{ */ -#define ANSI_CURSOR_UP(n) CSI_CODE(#n "A") ///< Move cursor up -#define ANSI_CURSOR_DOWN(n) CSI_CODE(#n "B") ///< Move cursor down -#define ANSI_CURSOR_FORWARD(n) CSI_CODE(#n "C") ///< Move cursor forward -#define ANSI_CURSOR_BACKWARD(n) CSI_CODE(#n "D") ///< Move cursor backward -#define ANSI_CURSOR_LINE_DOWN(n) CSI_CODE(#n "E") ///< Move cursor to the beginning of the line (n) down -#define ANSI_CURSOR_LINE_UP(n) CSI_CODE(#n "F") ///< Move cursor to the beginning of the line (n) up -#define ANSI_CURSOR_POSITION(n, m) CSI_CODE(#n ";" #m "H") ///< Move cursor to position (n, m) -/** @} */ - -//------------- Screen -------------// -/** \defgroup group_ansi_screen Screen Control - * @{ */ -#define ANSI_ERASE_SCREEN(n) CSI_CODE(#n "J") ///< Erase the screen -#define ANSI_ERASE_LINE(n) CSI_CODE(#n "K") ///< Erase the line (n) -#define ANSI_SCROLL_UP(n) CSI_CODE(#n "S") ///< Scroll the whole page up (n) lines -#define ANSI_SCROLL_DOWN(n) CSI_CODE(#n "T") ///< Scroll the whole page down (n) lines -/** @} */ - -//------------- Text Color -------------// -/** \defgroup group_ansi_text Text Color - * @{ */ -#define ANSI_TEXT_BLACK CSI_SGR(30) -#define ANSI_TEXT_RED CSI_SGR(31) -#define ANSI_TEXT_GREEN CSI_SGR(32) -#define ANSI_TEXT_YELLOW CSI_SGR(33) -#define ANSI_TEXT_BLUE CSI_SGR(34) -#define ANSI_TEXT_MAGENTA CSI_SGR(35) -#define ANSI_TEXT_CYAN CSI_SGR(36) -#define ANSI_TEXT_WHITE CSI_SGR(37) -#define ANSI_TEXT_DEFAULT CSI_SGR(39) -/** @} */ - -//------------- Background Color -------------// -/** \defgroup group_ansi_background Background Color - * @{ */ -#define ANSI_BG_BLACK CSI_SGR(40) -#define ANSI_BG_RED CSI_SGR(41) -#define ANSI_BG_GREEN CSI_SGR(42) -#define ANSI_BG_YELLOW CSI_SGR(43) -#define ANSI_BG_BLUE CSI_SGR(44) -#define ANSI_BG_MAGENTA CSI_SGR(45) -#define ANSI_BG_CYAN CSI_SGR(46) -#define ANSI_BG_WHITE CSI_SGR(47) -#define ANSI_BG_DEFAULT CSI_SGR(49) -/** @} */ - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_ANSI_ESC_CODE_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c deleted file mode 100644 index e208624ba..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018, hathach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#include "board.h" - -#if 0 -#define LED_PHASE_MAX 8 - -static struct -{ - uint32_t phase[LED_PHASE_MAX]; - uint8_t phase_count; - - bool led_state; - uint8_t current_phase; - uint32_t current_ms; -}led_pattern; - -void board_led_pattern(uint32_t const phase_ms[], uint8_t count) -{ - memcpy(led_pattern.phase, phase_ms, 4*count); - led_pattern.phase_count = count; - - // reset with 1st phase is on - led_pattern.current_ms = board_millis(); - led_pattern.current_phase = 0; - led_pattern.led_state = true; - board_led_on(); -} - -void board_led_task(void) -{ - if ( led_pattern.phase_count == 0 ) return; - - uint32_t const duration = led_pattern.phase[led_pattern.current_phase]; - - // return if not enough time - if (board_millis() - led_pattern.current_ms < duration) return; - - led_pattern.led_state = !led_pattern.led_state; - board_led_write(led_pattern.led_state); - - led_pattern.current_ms += duration; - led_pattern.current_phase++; - - if (led_pattern.current_phase == led_pattern.phase_count) - { - led_pattern.current_phase = 0; - led_pattern.led_state = true; - board_led_on(); - } -} -#endif - -//--------------------------------------------------------------------+ -// newlib read()/write() retarget -//--------------------------------------------------------------------+ - -#if defined(__MSP430__) || defined(__RX__) - #define sys_write write - #define sys_read read -#else - #define sys_write _write - #define sys_read _read -#endif - -#if defined(LOGGER_RTT) -// Logging with RTT - -// If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead -#if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM) -#include "SEGGER_RTT.h" - -TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) -{ - (void) fhdl; - SEGGER_RTT_Write(0, (const char*) buf, (int) count); - return count; -} - -TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) -{ - (void) fhdl; - return SEGGER_RTT_Read(0, buf, count); -} -#endif - -#elif defined(LOGGER_SWO) -// Logging with SWO for ARM Cortex - -#include "board_mcu.h" - -TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) -{ - (void) fhdl; - uint8_t const* buf8 = (uint8_t const*) buf; - for(size_t i=0; i -#include - -#include "ansi_escape.h" -#include "tusb.h" - -#define CFG_BOARD_UART_BAUDRATE 115200 - -//--------------------------------------------------------------------+ -// Board Porting API -// For simplicity, only one LED and one Button are used -//--------------------------------------------------------------------+ - -// Initialize on-board peripherals : led, button, uart and USB -void board_init(void); - -// Turn LED on or off -void board_led_write(bool state); - -// Control led pattern using phase duration in ms. -// For each phase, LED is toggle then repeated, board_led_task() is required to be called -//void board_led_pattern(uint32_t const phase_ms[], uint8_t count); - -// Get the current state of button -// a '1' means active (pressed), a '0' means inactive. -uint32_t board_button_read(void); - -// Get characters from UART -int board_uart_read(uint8_t* buf, int len); - -// Send characters to UART -int board_uart_write(void const * buf, int len); - -#if CFG_TUSB_OS == OPT_OS_NONE - // Get current milliseconds, must be implemented when no RTOS is used - uint32_t board_millis(void); - -#elif CFG_TUSB_OS == OPT_OS_FREERTOS - static inline uint32_t board_millis(void) - { - return ( ( ((uint64_t) xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ ); - } - -#elif CFG_TUSB_OS == OPT_OS_MYNEWT - static inline uint32_t board_millis(void) - { - return os_time_ticks_to_ms32( os_time_get() ); - } - -#elif CFG_TUSB_OS == OPT_OS_PICO - #include "pico/time.h" - static inline uint32_t board_millis(void) - { - return to_ms_since_boot(get_absolute_time()); - } - -#elif CFG_TUSB_OS == OPT_OS_RTTHREAD - static inline uint32_t board_millis(void) - { - return (((uint64_t)rt_tick_get()) * 1000 / RT_TICK_PER_SECOND); - } - -#else - #error "board_millis() is not implemented for this OS" -#endif - -//--------------------------------------------------------------------+ -// Helper functions -//--------------------------------------------------------------------+ -static inline void board_led_on(void) -{ - board_led_write(true); -} - -static inline void board_led_off(void) -{ - board_led_write(false); -} - -// TODO remove -static inline void board_delay(uint32_t ms) -{ - uint32_t start_ms = board_millis(); - while (board_millis() - start_ms < ms) - { - #if TUSB_OPT_DEVICE_ENABLED - // take chance to run usb background - tud_task(); - #endif - } -} - -static inline int board_uart_getchar(void) -{ - uint8_t c; - return board_uart_read(&c, 1) ? (int) c : (-1); -} - -static inline int board_uart_putchar(uint8_t c) -{ - return board_uart_write(&c, 1); -} - -#ifdef __cplusplus - } -#endif - -#endif /* _BSP_BOARD_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h deleted file mode 100644 index b911e1e53..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef BOARD_MCU_H_ -#define BOARD_MCU_H_ - -#include "tusb_option.h" - -//--------------------------------------------------------------------+ -// Low Level MCU header include. TinyUSB stack and example should be -// platform independent and mostly doesn't need to include this file. -// However there are still certain situation where this file is needed: -// - FreeRTOSConfig.h to set up correct clock and NVIC interrupts for ARM Cortex -// - SWO logging for Cortex M with ITM_SendChar() / ITM_ReceiveChar() -//--------------------------------------------------------------------+ - -// Include order follows OPT_MCU_ number -#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC15XX || CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX - #include "chip.h" - -#elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX || CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || \ - CFG_TUSB_MCU == OPT_MCU_K32L2BXX - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NRF5X - #include "nrf.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ - CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21 - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMG - #undef LITTLE_ENDIAN // hack to suppress "LITTLE_ENDIAN" redefined - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F0 - #include "stm32f0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 - #include "stm32f2xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - #include "stm32f3xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F4 - #include "stm32f4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - #include "stm32f7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H7 - #include "stm32h7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 - #include "stm32l0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 - #include "stm32l1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_CXD56 - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_MSP430x5xx - #include "msp430.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MSP432E4 - #include "msp.h" - -#elif CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC120 - #include "NUC100Series.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC121 || CFG_TUSB_MCU == OPT_MCU_NUC126 - #include "NuMicro.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC505 - #include "NUC505Series.h" - -#elif CFG_TUSB_MCU == OPT_MCU_ESP32S2 - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_DA1469X - #include "DA1469xAB.h" - -#elif CFG_TUSB_MCU == OPT_MCU_RP2040 - #include "pico.h" - -#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG - #include "em_device.h" - -#elif CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_GD32VF103 - #include "gd32vf103.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MM32F327X - #include "mm32_device.h" - -#elif CFG_TUSB_MCU == OPT_MCU_XMC4000 - #include "xmc_device.h" - -#elif CFG_TUSB_MCU == OPT_MCU_TM4C123 - #include "TM4C123.h" - -#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) - // no header needed - -#else - #error "Missing MCU header" -#endif - - -#endif /* BOARD_MCU_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt deleted file mode 100644 index c3c687a70..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -idf_component_register(SRCS esp32s2.c - INCLUDE_DIRS "." "${BOARD}" - PRIV_REQUIRES "driver" - REQUIRES freertos src led_strip) - -# Apply board specific content -include("${BOARD}/board.cmake") - -target_include_directories(${COMPONENT_TARGET} PUBLIC - "${TOP}/hw" - "${TOP}/src" -) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake deleted file mode 100644 index d33962676..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET}(${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h deleted file mode 100644 index 43e00901d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 33 -#define NEOPIXEL_POWER_PIN 21 -#define NEOPIXEL_POWER_STATE 1 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake deleted file mode 100644 index d33962676..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET}(${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h deleted file mode 100644 index 16e30b685..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 1 -#define NEOPIXEL_POWER_PIN 21 -#define NEOPIXEL_POWER_STATE 0 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake deleted file mode 100644 index d5c17b9be..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h deleted file mode 100644 index 49a2474bc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 45 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c deleted file mode 100644 index a81181672..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "../../board.h" -#include "board.h" - -#include "esp_rom_gpio.h" -#include "hal/gpio_ll.h" -#include "hal/usb_hal.h" -#include "soc/usb_periph.h" - -#include "driver/periph_ctrl.h" -#include "driver/rmt.h" - -#ifdef NEOPIXEL_PIN -#include "led_strip.h" -static led_strip_t *strip; -#endif - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -static void configure_pins(usb_hal_context_t *usb); - -// Initialize on-board peripherals : led, button, uart and USB -void board_init(void) -{ - -#ifdef NEOPIXEL_PIN - #ifdef NEOPIXEL_POWER_PIN - gpio_reset_pin(NEOPIXEL_POWER_PIN); - gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT); - gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE); - #endif - - // WS2812 Neopixel driver with RMT peripheral - rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0); - config.clk_div = 2; // set counter clock to 40MHz - - rmt_config(&config); - rmt_driver_install(config.channel, 0, 0); - - led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel); - strip = led_strip_new_rmt_ws2812(&strip_config); - strip->clear(strip, 100); // off led -#endif - - // Button - esp_rom_gpio_pad_select_gpio(BUTTON_PIN); - gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); - gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); - - // USB Controller Hal init - periph_module_reset(PERIPH_USB_MODULE); - periph_module_enable(PERIPH_USB_MODULE); - - usb_hal_context_t hal = { - .use_external_phy = false // use built-in PHY - }; - usb_hal_init(&hal); - configure_pins(&hal); -} - -static void configure_pins(usb_hal_context_t *usb) -{ - /* usb_periph_iopins currently configures USB_OTG as USB Device. - * Introduce additional parameters in usb_hal_context_t when adding support - * for USB Host. - */ - for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { - if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { - esp_rom_gpio_pad_select_gpio(iopin->pin); - if (iopin->is_output) { - esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false); - } else { - esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false); -#if ESP_IDF_VERSION_MAJOR > 4 - if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT)) -#else - if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) -#endif - { - gpio_ll_input_enable(&GPIO, iopin->pin); - } - } - esp_rom_gpio_pad_unhold(iopin->pin); - } - } - if (!usb->use_external_phy) { - gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); - gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); - } -} - -// Turn LED on or off -void board_led_write(bool state) -{ -#ifdef NEOPIXEL_PIN - strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00); - strip->refresh(strip, 100); -#endif -} - -// Get the current state of button -// a '1' means active (pressed), a '0' means inactive. -uint32_t board_button_read(void) -{ - return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE; -} - -// Get characters from UART -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -// Send characters to UART -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; - return 0; -} - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake deleted file mode 100644 index d5c17b9be..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h deleted file mode 100644 index 6bb44f76d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// Note: need to insert jumper next to WS2812 pixel -#define NEOPIXEL_PIN 45 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake deleted file mode 100644 index d5c17b9be..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h deleted file mode 100644 index f450b9a8b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// Note: On the production version (v1.2) WS2812 is connected to GPIO 18, -// however earlier revision v1.1 WS2812 is connected to GPIO 17 -#define NEOPIXEL_PIN 18 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt deleted file mode 100644 index 6d0fcbc86..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(component_srcs "src/led_strip_rmt_ws2812.c") - -idf_component_register(SRCS "${component_srcs}" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "" - PRIV_REQUIRES "driver" - REQUIRES "") - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h deleted file mode 100644 index a9dffc325..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "esp_err.h" - -/** -* @brief LED Strip Type -* -*/ -typedef struct led_strip_s led_strip_t; - -/** -* @brief LED Strip Device Type -* -*/ -typedef void *led_strip_dev_t; - -/** -* @brief Declare of LED Strip Type -* -*/ -struct led_strip_s { - /** - * @brief Set RGB for a specific pixel - * - * @param strip: LED strip - * @param index: index of pixel to set - * @param red: red part of color - * @param green: green part of color - * @param blue: blue part of color - * - * @return - * - ESP_OK: Set RGB for a specific pixel successfully - * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters - * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred - */ - esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); - - /** - * @brief Refresh memory colors to LEDs - * - * @param strip: LED strip - * @param timeout_ms: timeout value for refreshing task - * - * @return - * - ESP_OK: Refresh successfully - * - ESP_ERR_TIMEOUT: Refresh failed because of timeout - * - ESP_FAIL: Refresh failed because some other error occurred - * - * @note: - * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. - */ - esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Clear LED strip (turn off all LEDs) - * - * @param strip: LED strip - * @param timeout_ms: timeout value for clearing task - * - * @return - * - ESP_OK: Clear LEDs successfully - * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout - * - ESP_FAIL: Clear LEDs failed because some other error occurred - */ - esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Free LED strip resources - * - * @param strip: LED strip - * - * @return - * - ESP_OK: Free resources successfully - * - ESP_FAIL: Free resources failed because error occurred - */ - esp_err_t (*del)(led_strip_t *strip); -}; - -/** -* @brief LED Strip Configuration Type -* -*/ -typedef struct { - uint32_t max_leds; /*!< Maximum LEDs in a single strip */ - led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ -} led_strip_config_t; - -/** - * @brief Default configuration for LED strip - * - */ -#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ - { \ - .max_leds = number, \ - .dev = dev_hdl, \ - } - -/** -* @brief Install a new ws2812 driver (based on RMT peripheral) -* -* @param config: LED strip configuration -* @return -* LED strip instance or NULL -*/ -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c deleted file mode 100644 index 025d3c590..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include -#include -#include -#include "esp_log.h" -#include "esp_attr.h" -#include "led_strip.h" -#include "driver/rmt.h" - -static const char *TAG = "ws2812"; -#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ - do \ - { \ - if (!(a)) \ - { \ - ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret = ret_value; \ - goto goto_tag; \ - } \ - } while (0) - -#define WS2812_T0H_NS (350) -#define WS2812_T0L_NS (1000) -#define WS2812_T1H_NS (1000) -#define WS2812_T1L_NS (350) -#define WS2812_RESET_US (280) - -static uint32_t ws2812_t0h_ticks = 0; -static uint32_t ws2812_t1h_ticks = 0; -static uint32_t ws2812_t0l_ticks = 0; -static uint32_t ws2812_t1l_ticks = 0; - -typedef struct { - led_strip_t parent; - rmt_channel_t rmt_channel; - uint32_t strip_len; - uint8_t buffer[0]; -} ws2812_t; - -/** - * @brief Conver RGB data to RMT format. - * - * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) - * - * @param[in] src: source data, to converted to RMT format - * @param[in] dest: place where to store the convert result - * @param[in] src_size: size of source data - * @param[in] wanted_num: number of RMT items that want to get - * @param[out] translated_size: number of source data that got converted - * @param[out] item_num: number of RMT items which are converted from source data - */ -static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, - size_t wanted_num, size_t *translated_size, size_t *item_num) -{ - if (src == NULL || dest == NULL) { - *translated_size = 0; - *item_num = 0; - return; - } - const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 - const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 - size_t size = 0; - size_t num = 0; - uint8_t *psrc = (uint8_t *)src; - rmt_item32_t *pdest = dest; - while (size < src_size && num < wanted_num) { - for (int i = 0; i < 8; i++) { - // MSB first - if (*psrc & (1 << (7 - i))) { - pdest->val = bit1.val; - } else { - pdest->val = bit0.val; - } - num++; - pdest++; - } - size++; - psrc++; - } - *translated_size = size; - *item_num = num; -} - -static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); - uint32_t start = index * 3; - // In thr order of GRB - ws2812->buffer[start + 0] = green & 0xFF; - ws2812->buffer[start + 1] = red & 0xFF; - ws2812->buffer[start + 2] = blue & 0xFF; - return ESP_OK; -err: - return ret; -} - -static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, - "transmit RMT samples failed", err, ESP_FAIL); - return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); -err: - return ret; -} - -static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - // Write zero to turn off all leds - memset(ws2812->buffer, 0, ws2812->strip_len * 3); - return ws2812_refresh(strip, timeout_ms); -} - -static esp_err_t ws2812_del(led_strip_t *strip) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - free(ws2812); - return ESP_OK; -} - -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) -{ - led_strip_t *ret = NULL; - STRIP_CHECK(config, "configuration can't be null", err, NULL); - - // 24 bits per led - uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; - ws2812_t *ws2812 = calloc(1, ws2812_size); - STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); - - uint32_t counter_clk_hz = 0; - STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, - "get rmt counter clock failed", err, NULL); - // ns -> ticks - float ratio = (float)counter_clk_hz / 1e9; - ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); - ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); - ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); - ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); - - // set ws2812 to rmt adapter - rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); - - ws2812->rmt_channel = (rmt_channel_t)config->dev; - ws2812->strip_len = config->max_leds; - - ws2812->parent.set_pixel = ws2812_set_pixel; - ws2812->parent.refresh = ws2812_refresh; - ws2812->parent.clear = ws2812_clear; - ws2812->parent.del = ws2812_del; - - return &ws2812->parent; -err: - return ret; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake deleted file mode 100644 index f3d41d041..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -# Add example src and bsp directories -set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components") -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set(SUPPORTED_TARGETS esp32s2) -set(FAMILY_MCUS ESP32S2) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk deleted file mode 100644 index 4b9000a6a..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk +++ /dev/null @@ -1,23 +0,0 @@ -#DEPS_SUBMODULES += - -.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu - -all: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) -DIDF_TARGET=esp32s2 build - -build: all - -fullclean: - if test -f sdkconfig; then $(RM) -f sdkconfig ; fi - if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi - -clean flash bootloader-flash app-flash erase monitor dfu-flash dfu size size-components size-files: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ - -uf2: $(BUILD)/$(PROJECT).uf2 - -UF2_FAMILY_ID = 0xbfdd4eee -$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin - @echo CREATE $@ - $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt deleted file mode 100644 index e1b921ae9..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -idf_component_register(SRCS esp32s3.c - INCLUDE_DIRS "." "${BOARD}" - PRIV_REQUIRES "driver" - REQUIRES freertos src led_strip) - -# Apply board specific content -include("${BOARD}/board.cmake") - -idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) -target_include_directories(${COMPONENT_TARGET} PUBLIC - "${FREERTOS_ORIG_INCLUDE_PATH}" - "${TOP}/hw" - "${TOP}/src" -) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c deleted file mode 100644 index a81181672..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "../../board.h" -#include "board.h" - -#include "esp_rom_gpio.h" -#include "hal/gpio_ll.h" -#include "hal/usb_hal.h" -#include "soc/usb_periph.h" - -#include "driver/periph_ctrl.h" -#include "driver/rmt.h" - -#ifdef NEOPIXEL_PIN -#include "led_strip.h" -static led_strip_t *strip; -#endif - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -static void configure_pins(usb_hal_context_t *usb); - -// Initialize on-board peripherals : led, button, uart and USB -void board_init(void) -{ - -#ifdef NEOPIXEL_PIN - #ifdef NEOPIXEL_POWER_PIN - gpio_reset_pin(NEOPIXEL_POWER_PIN); - gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT); - gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE); - #endif - - // WS2812 Neopixel driver with RMT peripheral - rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0); - config.clk_div = 2; // set counter clock to 40MHz - - rmt_config(&config); - rmt_driver_install(config.channel, 0, 0); - - led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel); - strip = led_strip_new_rmt_ws2812(&strip_config); - strip->clear(strip, 100); // off led -#endif - - // Button - esp_rom_gpio_pad_select_gpio(BUTTON_PIN); - gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); - gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); - - // USB Controller Hal init - periph_module_reset(PERIPH_USB_MODULE); - periph_module_enable(PERIPH_USB_MODULE); - - usb_hal_context_t hal = { - .use_external_phy = false // use built-in PHY - }; - usb_hal_init(&hal); - configure_pins(&hal); -} - -static void configure_pins(usb_hal_context_t *usb) -{ - /* usb_periph_iopins currently configures USB_OTG as USB Device. - * Introduce additional parameters in usb_hal_context_t when adding support - * for USB Host. - */ - for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { - if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { - esp_rom_gpio_pad_select_gpio(iopin->pin); - if (iopin->is_output) { - esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false); - } else { - esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false); -#if ESP_IDF_VERSION_MAJOR > 4 - if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT)) -#else - if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) -#endif - { - gpio_ll_input_enable(&GPIO, iopin->pin); - } - } - esp_rom_gpio_pad_unhold(iopin->pin); - } - } - if (!usb->use_external_phy) { - gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); - gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); - } -} - -// Turn LED on or off -void board_led_write(bool state) -{ -#ifdef NEOPIXEL_PIN - strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00); - strip->refresh(strip, 100); -#endif -} - -// Get the current state of button -// a '1' means active (pressed), a '0' means inactive. -uint32_t board_button_read(void) -{ - return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE; -} - -// Get characters from UART -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -// Send characters to UART -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; - return 0; -} - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake deleted file mode 100644 index 8996ff9dc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h deleted file mode 100644 index fff24ba44..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// Note: On the production version (v1.1) WS2812 is connected to GPIO 47 -#define NEOPIXEL_PIN 47 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake deleted file mode 100644 index 8996ff9dc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h deleted file mode 100644 index c7940c56e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 48 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake deleted file mode 100644 index 8996ff9dc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h deleted file mode 100644 index c7940c56e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 48 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt deleted file mode 100644 index 6d0fcbc86..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(component_srcs "src/led_strip_rmt_ws2812.c") - -idf_component_register(SRCS "${component_srcs}" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "" - PRIV_REQUIRES "driver" - REQUIRES "") - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h deleted file mode 100644 index a9dffc325..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "esp_err.h" - -/** -* @brief LED Strip Type -* -*/ -typedef struct led_strip_s led_strip_t; - -/** -* @brief LED Strip Device Type -* -*/ -typedef void *led_strip_dev_t; - -/** -* @brief Declare of LED Strip Type -* -*/ -struct led_strip_s { - /** - * @brief Set RGB for a specific pixel - * - * @param strip: LED strip - * @param index: index of pixel to set - * @param red: red part of color - * @param green: green part of color - * @param blue: blue part of color - * - * @return - * - ESP_OK: Set RGB for a specific pixel successfully - * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters - * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred - */ - esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); - - /** - * @brief Refresh memory colors to LEDs - * - * @param strip: LED strip - * @param timeout_ms: timeout value for refreshing task - * - * @return - * - ESP_OK: Refresh successfully - * - ESP_ERR_TIMEOUT: Refresh failed because of timeout - * - ESP_FAIL: Refresh failed because some other error occurred - * - * @note: - * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. - */ - esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Clear LED strip (turn off all LEDs) - * - * @param strip: LED strip - * @param timeout_ms: timeout value for clearing task - * - * @return - * - ESP_OK: Clear LEDs successfully - * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout - * - ESP_FAIL: Clear LEDs failed because some other error occurred - */ - esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Free LED strip resources - * - * @param strip: LED strip - * - * @return - * - ESP_OK: Free resources successfully - * - ESP_FAIL: Free resources failed because error occurred - */ - esp_err_t (*del)(led_strip_t *strip); -}; - -/** -* @brief LED Strip Configuration Type -* -*/ -typedef struct { - uint32_t max_leds; /*!< Maximum LEDs in a single strip */ - led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ -} led_strip_config_t; - -/** - * @brief Default configuration for LED strip - * - */ -#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ - { \ - .max_leds = number, \ - .dev = dev_hdl, \ - } - -/** -* @brief Install a new ws2812 driver (based on RMT peripheral) -* -* @param config: LED strip configuration -* @return -* LED strip instance or NULL -*/ -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c deleted file mode 100644 index 025d3c590..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include -#include -#include -#include "esp_log.h" -#include "esp_attr.h" -#include "led_strip.h" -#include "driver/rmt.h" - -static const char *TAG = "ws2812"; -#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ - do \ - { \ - if (!(a)) \ - { \ - ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret = ret_value; \ - goto goto_tag; \ - } \ - } while (0) - -#define WS2812_T0H_NS (350) -#define WS2812_T0L_NS (1000) -#define WS2812_T1H_NS (1000) -#define WS2812_T1L_NS (350) -#define WS2812_RESET_US (280) - -static uint32_t ws2812_t0h_ticks = 0; -static uint32_t ws2812_t1h_ticks = 0; -static uint32_t ws2812_t0l_ticks = 0; -static uint32_t ws2812_t1l_ticks = 0; - -typedef struct { - led_strip_t parent; - rmt_channel_t rmt_channel; - uint32_t strip_len; - uint8_t buffer[0]; -} ws2812_t; - -/** - * @brief Conver RGB data to RMT format. - * - * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) - * - * @param[in] src: source data, to converted to RMT format - * @param[in] dest: place where to store the convert result - * @param[in] src_size: size of source data - * @param[in] wanted_num: number of RMT items that want to get - * @param[out] translated_size: number of source data that got converted - * @param[out] item_num: number of RMT items which are converted from source data - */ -static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, - size_t wanted_num, size_t *translated_size, size_t *item_num) -{ - if (src == NULL || dest == NULL) { - *translated_size = 0; - *item_num = 0; - return; - } - const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 - const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 - size_t size = 0; - size_t num = 0; - uint8_t *psrc = (uint8_t *)src; - rmt_item32_t *pdest = dest; - while (size < src_size && num < wanted_num) { - for (int i = 0; i < 8; i++) { - // MSB first - if (*psrc & (1 << (7 - i))) { - pdest->val = bit1.val; - } else { - pdest->val = bit0.val; - } - num++; - pdest++; - } - size++; - psrc++; - } - *translated_size = size; - *item_num = num; -} - -static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); - uint32_t start = index * 3; - // In thr order of GRB - ws2812->buffer[start + 0] = green & 0xFF; - ws2812->buffer[start + 1] = red & 0xFF; - ws2812->buffer[start + 2] = blue & 0xFF; - return ESP_OK; -err: - return ret; -} - -static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, - "transmit RMT samples failed", err, ESP_FAIL); - return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); -err: - return ret; -} - -static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - // Write zero to turn off all leds - memset(ws2812->buffer, 0, ws2812->strip_len * 3); - return ws2812_refresh(strip, timeout_ms); -} - -static esp_err_t ws2812_del(led_strip_t *strip) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - free(ws2812); - return ESP_OK; -} - -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) -{ - led_strip_t *ret = NULL; - STRIP_CHECK(config, "configuration can't be null", err, NULL); - - // 24 bits per led - uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; - ws2812_t *ws2812 = calloc(1, ws2812_size); - STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); - - uint32_t counter_clk_hz = 0; - STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, - "get rmt counter clock failed", err, NULL); - // ns -> ticks - float ratio = (float)counter_clk_hz / 1e9; - ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); - ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); - ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); - ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); - - // set ws2812 to rmt adapter - rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); - - ws2812->rmt_channel = (rmt_channel_t)config->dev; - ws2812->strip_len = config->max_leds; - - ws2812->parent.set_pixel = ws2812_set_pixel; - ws2812->parent.refresh = ws2812_refresh; - ws2812->parent.clear = ws2812_clear; - ws2812->parent.del = ws2812_del; - - return &ws2812->parent; -err: - return ret; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake deleted file mode 100644 index 511dd58bb..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -# Add example src and bsp directories -set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s3/boards" "${TOP}/hw/bsp/esp32s3/components") -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set(SUPPORTED_TARGETS esp32s3) -set(FAMILY_MCUS ESP32S3) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk deleted file mode 100644 index cf153ffc2..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk +++ /dev/null @@ -1,26 +0,0 @@ -#DEPS_SUBMODULES += - -.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu - -all: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) -DIDF_TARGET=esp32s3 build - -build: all - -clean: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) clean - -fullclean: - if test -f sdkconfig; then $(RM) -f sdkconfig ; fi - if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi - -flash bootloader-flash app-flash erase monitor dfu-flash dfu: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ - -uf2: $(BUILD)/$(PROJECT).uf2 - -UF2_FAMILY_ID = 0xc47e5767 -$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin - @echo CREATE $@ - $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake deleted file mode 100644 index a8cc1f363..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake +++ /dev/null @@ -1,100 +0,0 @@ -if (NOT TARGET _family_support_marker) - add_library(_family_support_marker INTERFACE) - - if (NOT FAMILY) - message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, eps32s2, esp32s3). You can do this via -DFAMILY=xxx on the camke command line") - endif() - - if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake) - message(FATAL_ERROR "Family '${FAMILY}' is not known/supported") - endif() - - function(family_filter RESULT DIR) - get_filename_component(DIR ${DIR} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - - if (EXISTS "${DIR}/only.txt") - file(READ "${DIR}/only.txt" ONLYS) - # Replace newlines with semicolon so that it is treated as a list by CMake - string(REPLACE "\n" ";" ONLYS_LINES ${ONLYS}) - # For each mcu - foreach(MCU IN LISTS FAMILY_MCUS) - # For each line in only.txt - foreach(_line ${ONLYS_LINES}) - # If mcu:xxx exists for this mcu then include - if (${_line} STREQUAL "mcu:${MCU}") - set(${RESULT} 1 PARENT_SCOPE) - return() - endif() - endforeach() - endforeach() - - # Didn't find it in only file so don't build - set(${RESULT} 0 PARENT_SCOPE) - - elseif (EXISTS "${DIR}/skip.txt") - file(READ "${DIR}/skip.txt" SKIPS) - # Replace newlines with semicolon so that it is treated as a list by CMake - string(REPLACE "\n" ";" SKIPS_LINES ${SKIPS}) - # For each mcu - foreach(MCU IN LISTS FAMILY_MCUS) - # For each line in only.txt - foreach(_line ${SKIPS_LINES}) - # If mcu:xxx exists for this mcu then skip - if (${_line} STREQUAL "mcu:${MCU}") - set(${RESULT} 0 PARENT_SCOPE) - return() - endif() - endforeach() - endforeach() - - # Didn't find in skip file so build - set(${RESULT} 1 PARENT_SCOPE) - - else() - - # Didn't find skip or only file so build - set(${RESULT} 1 PARENT_SCOPE) - - endif() - - endfunction() - - function(family_add_subdirectory DIR) - family_filter(SHOULD_ADD "${DIR}") - if (SHOULD_ADD) - add_subdirectory(${DIR}) - endif() - endfunction() - - function(family_get_project_name OUTPUT_NAME DIR) - get_filename_component(SHORT_NAME ${DIR} NAME) - set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE) - endfunction() - - function(family_initialize_project PROJECT DIR) - family_filter(ALLOWED "${DIR}") - if (NOT ALLOWED) - get_filename_component(SHORT_NAME ${DIR} NAME) - message(FATAL_ERROR "${SHORT_NAME} is not supported on FAMILY=${FAMILY}") - endif() - endfunction() - - # configure an executable target to link to tinyusb in device mode, and add the board implementation - function(family_configure_device_example TARGET) - # default implentation is empty, the function should be redefined in the FAMILY/family.cmake - endfunction() - - # configure an executable target to link to tinyusb in host mode, and add the board implementation - function(family_configure_host_example TARGET) - # default implentation is empty, the function should be redefined in the FAMILY/family.cmake - endfunction() - - include(${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake) - - if (NOT FAMILY_MCUS) - set(FAMILY_MCUS ${FAMILY}) - endif() - - # save it in case of re-inclusion - set(FAMILY_MCUS ${FAMILY_MCUS} CACHE INTERNAL "") -endif() \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml index f9bc726e5..45421d9d1 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml @@ -1,8 +1,14 @@ dependencies: - idf: '>=5.0' -description: TinyUSB ported to Espressif's SoCs -targets: -- esp32s2 -- esp32s3 -url: https://github.com/espressif/tinyusb -version: 0.0.1 + idf: + version: '>=5.0' + tinyusb: + public: true + version: '>=0.14.2' +description: Espressif's additions to TinyUSB +documentation: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_device.html +repository: git://github.com/espressif/esp-usb.git +repository_info: + commit_sha: 4b6a798d0bed444fff48147c8dcdbbd038e92892 + path: device/esp_tinyusb +url: https://github.com/espressif/esp-usb/tree/master/device/esp_tinyusb +version: 1.4.4 diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb.h similarity index 65% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb.h index 255cf3bed..484c86e6a 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,11 +9,8 @@ #include #include "esp_err.h" #include "tusb.h" -#include "tusb_option.h" -#include "tusb_config.h" #include "tinyusb_types.h" - #ifdef __cplusplus extern "C" { #endif @@ -31,9 +28,23 @@ typedef struct { const tusb_desc_device_t *device_descriptor; /*!< Pointer to a device descriptor. If set to NULL, the TinyUSB device will use a default device descriptor whose values are set in Kconfig */ const tusb_desc_device_t *descriptor __attribute__((deprecated)); /*!< Alias to `device_descriptor` for backward compatibility */ }; - const char **string_descriptor; /*!< Pointer to an array of string descriptors */ + const char **string_descriptor; /*!< Pointer to array of string descriptors. If set to NULL, TinyUSB device will use a default string descriptors whose values are set in Kconfig */ + int string_descriptor_count; /*!< Number of descriptors in above array */ bool external_phy; /*!< Should USB use an external PHY */ - const uint8_t *configuration_descriptor; /*!< Pointer to a configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + union { + struct { + const uint8_t *configuration_descriptor; /*!< Pointer to a configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + }; +#if (TUD_OPT_HIGH_SPEED) + struct { + const uint8_t *fs_configuration_descriptor; /*!< Pointer to a FullSpeed configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + }; + }; + const uint8_t *hs_configuration_descriptor; /*!< Pointer to a HighSpeed configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + const tusb_desc_device_qualifier_t *qualifier_descriptor; /*!< Pointer to a qualifier descriptor */ +#else + }; +#endif // TUD_OPT_HIGH_SPEED bool self_powered; /*!< This is a self-powered USB device. USB VBUS must be monitored. */ int vbus_monitor_io; /*!< GPIO for VBUS monitoring. Ignored if not self_powered. */ } tinyusb_config_t; @@ -57,7 +68,7 @@ typedef struct { */ esp_err_t tinyusb_driver_install(const tinyusb_config_t *config); -// TODO esp_err_t tinyusb_driver_uninstall(void); (IDF-1474) +esp_err_t tinyusb_driver_uninstall(void); #ifdef __cplusplus } diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_net.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_net.h new file mode 100644 index 000000000..19e53c4da --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_net.h @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "tinyusb_types.h" +#include "esp_err.h" +#include "sdkconfig.h" + +#if (CONFIG_TINYUSB_NET_MODE_NONE != 1) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief On receive callback type + */ +typedef esp_err_t (*tusb_net_rx_cb_t)(void *buffer, uint16_t len, void *ctx); + +/** + * @brief Free Tx buffer callback type + */ +typedef void (*tusb_net_free_tx_cb_t)(void *buffer, void *ctx); + +/** + * @brief On init callback type + */ +typedef void (*tusb_net_init_cb_t)(void *ctx); + +/** + * @brief ESP TinyUSB NCM driver configuration structure + */ +typedef struct { + uint8_t mac_addr[6]; /*!< MAC address. Must be 6 bytes long. */ + tusb_net_rx_cb_t on_recv_callback; /*!< TinyUSB receive data callbeck */ + tusb_net_free_tx_cb_t free_tx_buffer; /*!< User function for freeing the Tx buffer. + * - could be NULL, if user app is responsible for freeing the buffer + * - must be used in asynchronous send mode + * - is only called if the used tinyusb_net_send...() function returns ESP_OK + * - in sync mode means that the packet was accepted by TinyUSB + * - in async mode means that the packet was queued to be processed in TinyUSB task + */ + tusb_net_init_cb_t on_init_callback; /*!< TinyUSB init network callback */ + void *user_context; /*!< User context to be passed to any of the callback */ +} tinyusb_net_config_t; + +/** + * @brief Initialize TinyUSB NET driver + * + * @param[in] usb_dev USB device to use + * @param[in] cfg Configuration of the driver + * @return esp_err_t + */ +esp_err_t tinyusb_net_init(tinyusb_usbdev_t usb_dev, const tinyusb_net_config_t *cfg); + +/** + * @brief TinyUSB NET driver send data synchronously + * + * @note It is possible to use sync and async send interchangeably. + * This function needs some synchronization primitives, so using sync mode (even once) uses more heap + * + * @param[in] buffer USB send data + * @param[in] len Send data len + * @param[in] buff_free_arg Pointer to be passed to the free_tx_buffer() callback + * @param[in] timeout Send data len + * @return ESP_OK on success == packet has been consumed by tusb and would be eventually freed + * by free_tx_buffer() callback (if non null) + * ESP_ERR_TIMEOUT on timeout + * ESP_ERR_INVALID_STATE if tusb not initialized, ESP_ERR_NO_MEM on alloc failure + */ +esp_err_t tinyusb_net_send_sync(void *buffer, uint16_t len, void *buff_free_arg, TickType_t timeout); + +/** + * @brief TinyUSB NET driver send data asynchronously + * + * @note If using asynchronous sends, you must free the buffer using free_tx_buffer() callback. + * @note It is possible to use sync and async send interchangeably. + * @note Async flavor of the send is useful when the USB stack runs faster than the caller, + * since we have no control over the transmitted packets, if they get accepted or discarded. + * + * @param[in] buffer USB send data + * @param[in] len Send data len + * @param[in] buff_free_arg Pointer to be passed to the free_tx_buffer() callback + * @return ESP_OK on success == packet has been consumed by tusb and will be freed + * by free_tx_buffer() callback (if non null) + * ESP_ERR_INVALID_STATE if tusb not initialized + */ +esp_err_t tinyusb_net_send_async(void *buffer, uint16_t len, void *buff_free_arg); + +#endif // (CONFIG_TINYUSB_NET_MODE_NONE != 1) + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_types.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_types.h new file mode 100644 index 000000000..106aaaf15 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_types.h @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define USB_ESPRESSIF_VID 0x303A + +typedef enum { + TINYUSB_USBDEV_0, +} tinyusb_usbdev_t; + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_cdc_acm.h similarity index 68% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_cdc_acm.h index 266ca86c8..8f64ba457 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_cdc_acm.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,11 +11,16 @@ extern "C" { #endif #include -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "freertos/timers.h" -#include "tusb.h" -#include "tinyusb.h" +#include "sdkconfig.h" +#include "esp_err.h" + +#include "tinyusb_types.h" +#include "class/cdc/cdc.h" + +#if (CONFIG_TINYUSB_CDC_ENABLED != 1) +#error "TinyUSB CDC driver must be enabled in menuconfig" +#endif + /** * @brief CDC ports available to setup @@ -88,7 +93,7 @@ typedef void(*tusb_cdcacm_callback_t)(int itf, cdcacm_event_t *event); typedef struct { tinyusb_usbdev_t usb_dev; /*!< Usb device to set up */ tinyusb_cdcacm_itf_t cdc_port; /*!< CDC port */ - size_t rx_unread_buf_sz; /*!< Amount of data that can be passed to the ACM at once */ + size_t rx_unread_buf_sz __attribute__((deprecated("This parameter is not used any more. Configure RX buffer in menuconfig."))); tusb_cdcacm_callback_t callback_rx; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ tusb_cdcacm_callback_t callback_rx_wanted_char; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ tusb_cdcacm_callback_t callback_line_state_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ @@ -102,89 +107,95 @@ typedef struct { * @brief Initialize CDC ACM. Initialization will be finished with * the `tud_cdc_line_state_cb` callback * - * @param cfg - init configuration structure + * @param[in] cfg Configuration structure * @return esp_err_t */ esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg); +/** + * @brief De-initialize CDC ACM. + * + * @param[in] itf Index of CDC interface + * @return esp_err_t + */ +esp_err_t tusb_cdc_acm_deinit(int itf); /** * @brief Register a callback invoking on CDC event. If the callback had been * already registered, it will be overwritten * - * @param itf - number of a CDC object - * @param event_type - type of registered event for a callback - * @param callback - callback function + * @param[in] itf Index of CDC interface + * @param[in] event_type Type of registered event for a callback + * @param[in] callback Callback function * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG */ esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type, tusb_cdcacm_callback_t callback); - /** - * @brief Unregister a callback invoking on CDC event. + * @brief Unregister a callback invoking on CDC event * - * @param itf - number of a CDC object - * @param event_type - type of registered event for a callback + * @param[in] itf Index of CDC interface + * @param[in] event_type Type of registered event for a callback * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG */ esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type); - /** * @brief Sent one character to a write buffer * - * @param itf - number of a CDC object - * @param ch - character to send + * @param[in] itf Index of CDC interface + * @param[in] ch Character to send * @return size_t - amount of queued bytes */ size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch); - /** - * @brief Write data to write buffer from a byte array + * @brief Write data to write buffer * - * @param itf - number of a CDC object - * @param in_buf - a source array - * @param in_size - size to write from arr_src + * @param[in] itf Index of CDC interface + * @param[in] in_buf Data + * @param[in] in_size Data size in bytes * @return size_t - amount of queued bytes */ size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size); /** - * @brief Send all data from a write buffer. Use `tinyusb_cdcacm_write_queue` to add data to the buffer. + * @brief Flush data in write buffer of CDC interface + * + * Use `tinyusb_cdcacm_write_queue` to add data to the buffer * * WARNING! TinyUSB can block output Endpoint for several RX callbacks, after will do additional flush - * after the each trasfer. That can leads to the situation when you requested a flush, but it will fail until - * ont of the next callbacks ends. - * SO USING OF THE FLUSH WITH TIMEOUTS IN CALLBACKS IS NOT RECOMENDED - YOU CAN GET A LOCK FOR THE TIMEOUT + * after the each transfer. That can leads to the situation when you requested a flush, but it will fail until + * one of the next callbacks ends. + * SO USING OF THE FLUSH WITH TIMEOUTS IN CALLBACKS IS NOT RECOMMENDED - YOU CAN GET A LOCK FOR THE TIMEOUT * - * @param itf - number of a CDC object - * @param timeout_ticks - waiting until flush will be considered as failed - * @return esp_err_t - ESP_OK if (timeout_ticks > 0) and and flush was successful, - * ESP_ERR_TIMEOUT if timeout occurred3 or flush was successful with (timeout_ticks == 0) - * ESP_FAIL if flush was unsuccessful + * @param[in] itf Index of CDC interface + * @param[in] timeout_ticks Transfer timeout. Set to zero for non-blocking mode + * @return - ESP_OK All data flushed + * - ESP_ERR_TIMEOUT Time out occurred in blocking mode + * - ESP_NOT_FINISHED The transfer is still in progress in non-blocking mode */ esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks); /** - * @brief Read a content to the array, and defines it's size to the sz_store + * @brief Receive data from CDC interface * - * @param itf - number of a CDC object - * @param out_buf - to this array will be stored the object from a CDC buffer - * @param out_buf_sz - size of buffer for results - * @param rx_data_size - to this address will be stored the object's size + * @param[in] itf Index of CDC interface + * @param[out] out_buf Data buffer + * @param[in] out_buf_sz Data buffer size in bytes + * @param[out] rx_data_size Number of bytes written to out_buf * @return esp_err_t ESP_OK, ESP_FAIL or ESP_ERR_INVALID_STATE */ esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size); - /** - * @brief Check if the ACM initialized + * @brief Check if the CDC interface is initialized * - * @param itf - number of a CDC object - * @return true or false + * @param[in] itf Index of CDC interface + * @return - true Initialized + * - false Not Initialized */ bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf); diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_config.h similarity index 65% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_config.h index da2a5f9e7..adcea7c3e 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_config.h @@ -1,5 +1,7 @@ /* - * The MIT License (MIT) + * SPDX-FileCopyrightText: 2019 Ha Thach (tinyusb.org), + * SPDX-FileContributor: 2020 Espressif Systems (Shanghai) CO LTD + * SPDX-License-Identifier: MIT * * Copyright (c) 2019 Ha Thach (tinyusb.org), * Additions Copyright (c) 2020, Espressif Systems (Shanghai) PTE LTD @@ -57,7 +59,37 @@ extern "C" { # define CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED 0 #endif -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED +#ifndef CONFIG_TINYUSB_NET_MODE_ECM_RNDIS +# define CONFIG_TINYUSB_NET_MODE_ECM_RNDIS 0 +#endif + +#ifndef CONFIG_TINYUSB_NET_MODE_NCM +# define CONFIG_TINYUSB_NET_MODE_NCM 0 +#endif + +#ifndef CONFIG_TINYUSB_DFU_MODE_DFU +# define CONFIG_TINYUSB_DFU_MODE_DFU 0 +#endif + +#ifndef CONFIG_TINYUSB_DFU_MODE_DFU_RUNTIME +# define CONFIG_TINYUSB_DFU_MODE_DFU_RUNTIME 0 +#endif + +#ifndef CONFIG_TINYUSB_BTH_ENABLED +# define CONFIG_TINYUSB_BTH_ENABLED 0 +# define CONFIG_TINYUSB_BTH_ISO_ALT_COUNT 0 +#endif + +#ifndef CONFIG_TINYUSB_DEBUG_LEVEL +# define CONFIG_TINYUSB_DEBUG_LEVEL 0 +#endif + +#ifdef CONFIG_TINYUSB_RHPORT_HS +# define CFG_TUSB_RHPORT1_MODE OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED +#else +# define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED +#endif + #define CFG_TUSB_OS OPT_OS_FREERTOS /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. @@ -79,6 +111,9 @@ extern "C" { #define CFG_TUD_ENDPOINT0_SIZE 64 #endif +// Debug Level +#define CFG_TUSB_DEBUG CONFIG_TINYUSB_DEBUG_LEVEL + // CDC FIFO size of TX and RX #define CFG_TUD_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE #define CFG_TUD_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE @@ -86,17 +121,34 @@ extern "C" { // MSC Buffer size of Device Mass storage #define CFG_TUD_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE +// MIDI macros #define CFG_TUD_MIDI_EP_BUFSIZE 64 #define CFG_TUD_MIDI_EPSIZE CFG_TUD_MIDI_EP_BUFSIZE #define CFG_TUD_MIDI_RX_BUFSIZE 64 #define CFG_TUD_MIDI_TX_BUFSIZE 64 +// Vendor FIFO size of TX and RX +// If not configured vendor endpoints will not be buffered +#define CFG_TUD_VENDOR_RX_BUFSIZE 64 +#define CFG_TUD_VENDOR_TX_BUFSIZE 64 + +// DFU macros +#define CFG_TUD_DFU_XFER_BUFSIZE CONFIG_TINYUSB_DFU_BUFSIZE + +// Number of BTH ISO alternatives +#define CFG_TUD_BTH_ISO_ALT_COUNT CONFIG_TINYUSB_BTH_ISO_ALT_COUNT + // Enabled device class driver #define CFG_TUD_CDC CONFIG_TINYUSB_CDC_COUNT #define CFG_TUD_MSC CONFIG_TINYUSB_MSC_ENABLED #define CFG_TUD_HID CONFIG_TINYUSB_HID_COUNT #define CFG_TUD_MIDI CONFIG_TINYUSB_MIDI_COUNT #define CFG_TUD_CUSTOM_CLASS CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED +#define CFG_TUD_ECM_RNDIS CONFIG_TINYUSB_NET_MODE_ECM_RNDIS +#define CFG_TUD_NCM CONFIG_TINYUSB_NET_MODE_NCM +#define CFG_TUD_DFU CONFIG_TINYUSB_DFU_MODE_DFU +#define CFG_TUD_DFU_RUNTIME CONFIG_TINYUSB_DFU_MODE_DFU_RUNTIME +#define CFG_TUD_BTH CONFIG_TINYUSB_BTH_ENABLED #ifdef __cplusplus } diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_console.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_console.h similarity index 100% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_console.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_console.h diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_msc_storage.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_msc_storage.h new file mode 100644 index 000000000..35e3fb3f1 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_msc_storage.h @@ -0,0 +1,188 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "esp_err.h" +#include "wear_levelling.h" +#include "esp_vfs_fat.h" +#if SOC_SDMMC_HOST_SUPPORTED +#include "driver/sdmmc_host.h" +#endif + +/** + * @brief Data provided to the input of the `callback_mount_changed` and `callback_premount_changed` callback + */ +typedef struct { + bool is_mounted; /*!< Flag if storage is mounted or not */ +} tinyusb_msc_event_mount_changed_data_t; + +/** + * @brief Types of MSC events + */ +typedef enum { + TINYUSB_MSC_EVENT_MOUNT_CHANGED, /*!< Event type AFTER mount/unmount operation is successfully finished */ + TINYUSB_MSC_EVENT_PREMOUNT_CHANGED /*!< Event type BEFORE mount/unmount operation is started */ +} tinyusb_msc_event_type_t; + +/** + * @brief Describes an event passing to the input of a callbacks + */ +typedef struct { + tinyusb_msc_event_type_t type; /*!< Event type */ + union { + tinyusb_msc_event_mount_changed_data_t mount_changed_data; /*!< Data input of the callback */ + }; +} tinyusb_msc_event_t; + +/** + * @brief MSC callback that is delivered whenever a specific event occurs. + */ +typedef void(*tusb_msc_callback_t)(tinyusb_msc_event_t *event); + +#if SOC_SDMMC_HOST_SUPPORTED +/** + * @brief Configuration structure for sdmmc initialization + * + * User configurable parameters that are used while + * initializing the sdmmc media. + */ +typedef struct { + sdmmc_card_t *card; /*!< Pointer to sdmmc card configuration structure */ + tusb_msc_callback_t callback_mount_changed; /*!< Pointer to the function callback that will be delivered AFTER mount/unmount operation is successfully finished */ + tusb_msc_callback_t callback_premount_changed; /*!< Pointer to the function callback that will be delivered BEFORE mount/unmount operation is started */ + const esp_vfs_fat_mount_config_t mount_config; /*!< FATFS mount config */ +} tinyusb_msc_sdmmc_config_t; +#endif + +/** + * @brief Configuration structure for spiflash initialization + * + * User configurable parameters that are used while + * initializing the SPI Flash media. + */ +typedef struct { + wl_handle_t wl_handle; /*!< Pointer to spiflash wera-levelling handle */ + tusb_msc_callback_t callback_mount_changed; /*!< Pointer to the function callback that will be delivered AFTER mount/unmount operation is successfully finished */ + tusb_msc_callback_t callback_premount_changed; /*!< Pointer to the function callback that will be delivered BEFORE mount/unmount operation is started */ + const esp_vfs_fat_mount_config_t mount_config; /*!< FATFS mount config */ +} tinyusb_msc_spiflash_config_t; + +/** + * @brief Register storage type spiflash with tinyusb driver + * + * @param config pointer to the spiflash configuration + * @return esp_err_t + * - ESP_OK, if success; + * - ESP_ERR_NO_MEM, if there was no memory to allocate storage components; + */ +esp_err_t tinyusb_msc_storage_init_spiflash(const tinyusb_msc_spiflash_config_t *config); + +#if SOC_SDMMC_HOST_SUPPORTED +/** + * @brief Register storage type sd-card with tinyusb driver + * + * @param config pointer to the sd card configuration + * @return esp_err_t + * - ESP_OK, if success; + * - ESP_ERR_NO_MEM, if there was no memory to allocate storage components; + */ +esp_err_t tinyusb_msc_storage_init_sdmmc(const tinyusb_msc_sdmmc_config_t *config); +#endif +/** + * @brief Deregister storage with tinyusb driver and frees the memory + * + */ +void tinyusb_msc_storage_deinit(void); + +/** + * @brief Register a callback invoking on MSC event. If the callback had been + * already registered, it will be overwritten + * + * @param event_type - type of registered event for a callback + * @param callback - callback function + * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG + */ +esp_err_t tinyusb_msc_register_callback(tinyusb_msc_event_type_t event_type, + tusb_msc_callback_t callback); + + +/** + * @brief Unregister a callback invoking on MSC event. + * + * @param event_type - type of registered event for a callback + * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG + */ +esp_err_t tinyusb_msc_unregister_callback(tinyusb_msc_event_type_t event_type); + +/** + * @brief Mount the storage partition locally on the firmware application. + * + * Get the available drive number. Register spi flash partition. + * Connect POSIX and C standard library IO function with FATFS. + * Mounts the partition. + * This API is used by the firmware application. If the storage partition is + * mounted by this API, host (PC) can't access the storage via MSC. + * When this function is called from the tinyusb callback functions, care must be taken + * so as to make sure that user callbacks must be completed within a + * specific time. Otherwise, MSC device may re-appear again on Host. + * + * @param base_path path prefix where FATFS should be registered + * @return esp_err_t + * - ESP_OK, if success; + * - ESP_ERR_NOT_FOUND if the maximum count of volumes is already mounted + * - ESP_ERR_NO_MEM if not enough memory or too many VFSes already registered; + */ +esp_err_t tinyusb_msc_storage_mount(const char *base_path); + +/** + * @brief Unmount the storage partition from the firmware application. + * + * Unmount the partition. Unregister diskio driver. + * Unregister the SPI flash partition. + * Finally, Un-register FATFS from VFS. + * After this function is called, storage device can be seen (recognized) by host (PC). + * When this function is called from the tinyusb callback functions, care must be taken + * so as to make sure that user callbacks must be completed within a specific time. + * Otherwise, MSC device may not appear on Host. + * + * @return esp_err_t + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS + */ +esp_err_t tinyusb_msc_storage_unmount(void); + +/** + * @brief Get number of sectors in storage media + * + * @return usable size, in bytes + */ +uint32_t tinyusb_msc_storage_get_sector_count(void); + +/** + * @brief Get sector size of storage media + * + * @return sector count + */ +uint32_t tinyusb_msc_storage_get_sector_size(void); + +/** + * @brief Get status if storage media is exposed over USB to Host + * + * @return bool + * - true, if the storage media is exposed to Host + * - false, if the stoarge media is mounted on application (not exposed to Host) + */ +bool tinyusb_msc_storage_in_use_by_usb_host(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_tasks.h similarity index 80% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_tasks.h index 22b6df6c2..38bd7dea7 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_tasks.h @@ -20,7 +20,8 @@ extern "C" { * If you have more requirements for this task, you can create your own task which calls tud_task as the last step. * * @retval ESP_OK run tinyusb main task successfully - * @retval ESP_FAIL run tinyusb main task failed of internal error + * @retval ESP_FAIL run tinyusb main task failed of internal error or initialization within the task failed when TINYUSB_INIT_IN_DEFAULT_TASK=y + * @retval ESP_FAIL initialization within the task failed if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK is enabled * @retval ESP_ERR_INVALID_STATE tinyusb main task has been created before */ esp_err_t tusb_run_task(void); @@ -28,7 +29,7 @@ esp_err_t tusb_run_task(void); /** * @brief This helper function stops and destroys the task created by `tusb_run_task()` * - * @retval ESP_OK stop and destory tinyusb main task successfully + * @retval ESP_OK stop and destroy tinyusb main task successfully * @retval ESP_ERR_INVALID_STATE tinyusb main task hasn't been created yet */ esp_err_t tusb_stop_task(void); diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include/vfs_tinyusb.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/vfs_tinyusb.h new file mode 100644 index 000000000..9c9ba910b --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/vfs_tinyusb.h @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_err.h" +#include "esp_vfs_common.h" // For esp_line_endings_t definitions + +#ifdef __cplusplus +extern "C" { +#endif + +#define VFS_TUSB_MAX_PATH 16 +#define VFS_TUSB_PATH_DEFAULT "/dev/tusb_cdc" + +/** + * @brief Register TinyUSB CDC at VFS with path + * + * Know limitation: + * In case there are multiple CDC interfaces in the system, only one of them can be registered to VFS. + * + * @param[in] cdc_intf Interface number of TinyUSB's CDC + * @param[in] path Path where the CDC will be registered, `/dev/tusb_cdc` will be used if left NULL. + * @return esp_err_t ESP_OK or ESP_FAIL + */ +esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path); + +/** + * @brief Unregister TinyUSB CDC from VFS + * + * @param[in] path Path where the CDC will be unregistered if NULL will be used `/dev/tusb_cdc` + * @return esp_err_t ESP_OK or ESP_FAIL + */ +esp_err_t esp_vfs_tusb_cdc_unregister(char const *path); + +/** + * @brief Set the line endings to sent + * + * This specifies the conversion between newlines ('\n', LF) on stdout and line + * endings sent: + * + * - ESP_LINE_ENDINGS_CRLF: convert LF to CRLF + * - ESP_LINE_ENDINGS_CR: convert LF to CR + * - ESP_LINE_ENDINGS_LF: no modification + * + * @param[in] mode line endings to send + */ +void esp_vfs_tusb_cdc_set_tx_line_endings(esp_line_endings_t mode); + +/** + * @brief Set the line endings expected to be received + * + * This specifies the conversion between line endings received and + * newlines ('\n', LF) passed into stdin: + * + * - ESP_LINE_ENDINGS_CRLF: convert CRLF to LF + * - ESP_LINE_ENDINGS_CR: convert CR to LF + * - ESP_LINE_ENDINGS_LF: no modification + * + * @param[in] mode line endings expected + */ +void esp_vfs_tusb_cdc_set_rx_line_endings(esp_line_endings_t mode); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/cdc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/cdc.h similarity index 100% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/cdc.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/cdc.h diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/descriptors_control.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/descriptors_control.h new file mode 100644 index 000000000..fcf352226 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/descriptors_control.h @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "tinyusb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8 // Max 8 string descriptors for a device. LANGID, Manufacturer, Product, Serial number + 4 user defined + +/** + * @brief Parse tinyusb configuration and prepare the device configuration pointer list to configure tinyusb driver + * + * @attention All descriptors passed to this function must exist for the duration of USB device lifetime + * + * @param[in] config tinyusb stack specific configuration + * @retval ESP_ERR_INVALID_ARG Default configuration descriptor is provided only for CDC, MSC and NCM classes + * @retval ESP_ERR_NO_MEM Memory allocation error + * @retval ESP_OK Descriptors configured without error + */ +esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config); + +/** + * @brief Set specific string descriptor + * + * @attention The descriptor passed to this function must exist for the duration of USB device lifetime + * + * @param[in] str UTF-8 string + * @param[in] str_idx String descriptor index + */ +void tinyusb_set_str_descriptor(const char *str, int str_idx); + +/** + * @brief Free memory allocated during tinyusb_set_descriptors + * + */ +void tinyusb_free_descriptors(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/usb_descriptors.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/usb_descriptors.h new file mode 100644 index 000000000..be1979ab7 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/usb_descriptors.h @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "tusb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Device descriptor generated from Kconfig + * + * This descriptor is used by default. + * The user can provide their own device descriptor via tinyusb_driver_install() call + */ +extern const tusb_desc_device_t descriptor_dev_default; + +#if (TUD_OPT_HIGH_SPEED) +/** + * @brief Qualifier Device descriptor generated from Kconfig + * + * This descriptor is used by default. + * The user can provide their own descriptor via tinyusb_driver_install() call + */ +extern const tusb_desc_device_qualifier_t descriptor_qualifier_default; +#endif // TUD_OPT_HIGH_SPEED + +/** + * @brief Array of string descriptors generated from Kconfig + * + * This descriptor is used by default. + * The user can provide their own descriptor via tinyusb_driver_install() call + */ +extern const char *descriptor_str_default[]; + +/** + * @brief FullSpeed configuration descriptor generated from Kconfig + * This descriptor is used by default. + * The user can provide their own FullSpeed configuration descriptor via tinyusb_driver_install() call + */ +extern const uint8_t descriptor_fs_cfg_default[]; + +#if (TUD_OPT_HIGH_SPEED) +/** + * @brief HighSpeed Configuration descriptor generated from Kconfig + * + * This descriptor is used by default. + * The user can provide their own HighSpeed configuration descriptor via tinyusb_driver_install() call + */ +extern const uint8_t descriptor_hs_cfg_default[]; +#endif // TUD_OPT_HIGH_SPEED + +uint8_t tusb_get_mac_string_id(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt deleted file mode 100644 index e1f5f89ff..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt +++ /dev/null @@ -1,34 +0,0 @@ -Important - Read carefully: - -SEGGER RTT - Real Time Transfer for embedded targets - -All rights reserved. - -SEGGER strongly recommends to not make any changes -to or modify the source code of this software in order to stay -compatible with the RTT protocol and J-Link. - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the following -condition is met: - -o Redistributions of source code must retain the above copyright - notice, this condition and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. - - -(c) 2014 - 2016 SEGGER Microcontroller GmbH -www.segger.com diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt deleted file mode 100644 index 49ec655c4..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt +++ /dev/null @@ -1,20 +0,0 @@ -README.txt for the SEGGER RTT Implementation Pack. - -Included files: -=============== -Root Directory - - Examples - - Main_RTT_InputEchoApp.c - Sample application which echoes input on Channel 0. - - Main_RTT_MenuApp.c - Sample application to demonstrate RTT bi-directional functionality. - - Main_RTT_PrintfTest.c - Sample application to test RTT small printf implementation. - - Main_RTT_SpeedTestApp.c - Sample application for measuring RTT performance. embOS needed. - - RTT - - SEGGER_RTT.c - The RTT implementation. - - SEGGER_RTT.h - Header for RTT implementation. - - SEGGER_RTT_Conf.h - Pre-processor configuration for the RTT implementation. - - SEGGER_RTT_Printf.c - Simple implementation of printf to write formatted strings via RTT. - - Syscalls - - RTT_Syscalls_GCC.c - Low-level syscalls to retarget printf() to RTT with GCC / Newlib. - - RTT_Syscalls_IAR.c - Low-level syscalls to retarget printf() to RTT with IAR compiler. - - RTT_Syscalls_KEIL.c - Low-level syscalls to retarget printf() to RTT with KEIL/uVision compiler. - - RTT_Syscalls_SES.c - Low-level syscalls to retarget printf() to RTT with SEGGER Embedded Studio. diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c deleted file mode 100644 index 3ad2b1a12..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c +++ /dev/null @@ -1,2005 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.c -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. -Revision: $Rev: 17697 $ - -Additional information: - Type "int" is assumed to be 32-bits in size - H->T Host to target communication - T->H Target to host communication - - RTT channel 0 is always present and reserved for Terminal usage. - Name is fixed to "Terminal" - - Effective buffer size: SizeOfBuffer - 1 - - WrOff == RdOff: Buffer is empty - WrOff == (RdOff - 1): Buffer is full - WrOff > RdOff: Free space includes wrap-around - WrOff < RdOff: Used space includes wrap-around - (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): - Buffer full and wrap-around after next byte - - ----------------------------------------------------------------------- -*/ - -#include "SEGGER_RTT.h" - -#include // for memcpy - -/********************************************************************* -* -* Configuration, default values -* -********************************************************************** -*/ - -#ifndef BUFFER_SIZE_UP - #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host -#endif - -#ifndef BUFFER_SIZE_DOWN - #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) -#endif - -#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS - #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target -#endif - -#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS - #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target -#endif - -#ifndef SEGGER_RTT_BUFFER_SECTION - #if defined(SEGGER_RTT_SECTION) - #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION - #endif -#endif - -#ifndef SEGGER_RTT_ALIGNMENT - #define SEGGER_RTT_ALIGNMENT 0 -#endif - -#ifndef SEGGER_RTT_BUFFER_ALIGNMENT - #define SEGGER_RTT_BUFFER_ALIGNMENT 0 -#endif - -#ifndef SEGGER_RTT_MODE_DEFAULT - #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP -#endif - -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() -#endif - -#ifndef STRLEN - #define STRLEN(a) strlen((a)) -#endif - -#ifndef STRCPY - #define STRCPY(pDest, pSrc, NumBytes) strcpy((pDest), (pSrc)) -#endif - -#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP - #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 -#endif - -#ifndef SEGGER_RTT_MEMCPY - #ifdef MEMCPY - #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) - #else - #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) - #endif -#endif - -#ifndef MIN - #define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef MAX - #define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif -// -// For some environments, NULL may not be defined until certain headers are included -// -#ifndef NULL - #define NULL 0 -#endif - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ -#if (defined __ICCARM__) || (defined __ICCRX__) - #define RTT_PRAGMA(P) _Pragma(#P) -#endif - -#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT - #if (defined __GNUC__) - #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) - #elif (defined __ICCARM__) || (defined __ICCRX__) - #define PRAGMA(A) _Pragma(#A) -#define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ - Var - #elif (defined __CC_ARM) - #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) - #else - #error "Alignment not supported for this compiler." - #endif -#else - #define SEGGER_RTT_ALIGN(Var, Alignment) Var -#endif - -#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) - #if (defined __GNUC__) - #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var - #elif (defined __ICCARM__) || (defined __ICCRX__) -#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ - Var - #elif (defined __CC_ARM) - #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var - #else - #error "Section placement not supported for this compiler." - #endif -#else - #define SEGGER_RTT_PUT_SECTION(Var, Section) Var -#endif - - -#if SEGGER_RTT_ALIGNMENT - #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) -#else - #define SEGGER_RTT_CB_ALIGN(Var) Var -#endif - -#if SEGGER_RTT_BUFFER_ALIGNMENT - #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) -#else - #define SEGGER_RTT_BUFFER_ALIGN(Var) Var -#endif - - -#if defined(SEGGER_RTT_SECTION) - #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) -#else - #define SEGGER_RTT_PUT_CB_SECTION(Var) Var -#endif - -#if defined(SEGGER_RTT_BUFFER_SECTION) - #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) -#else - #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var -#endif - -/********************************************************************* -* -* Static const data -* -********************************************************************** -*/ - -static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - -/********************************************************************* -* -* Static data -* -********************************************************************** -*/ -// -// RTT Control Block and allocate buffers for channel 0 -// -SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); - -SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); -SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); - -static unsigned char _ActiveTerminal; - -/********************************************************************* -* -* Static functions -* -********************************************************************** -*/ - -/********************************************************************* -* -* _DoInit() -* -* Function description -* Initializes the control block an buffers. -* May only be called via INIT() to avoid overriding settings. -* -*/ -#define INIT() do { \ - if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ - } while (0) -static void _DoInit(void) { - SEGGER_RTT_CB* p; - // - // Initialize control block - // - p = &_SEGGER_RTT; - p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; - p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; - // - // Initialize up buffer 0 - // - p->aUp[0].sName = "Terminal"; - p->aUp[0].pBuffer = _acUpBuffer; - p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); - p->aUp[0].RdOff = 0u; - p->aUp[0].WrOff = 0u; - p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Initialize down buffer 0 - // - p->aDown[0].sName = "Terminal"; - p->aDown[0].pBuffer = _acDownBuffer; - p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); - p->aDown[0].RdOff = 0u; - p->aDown[0].WrOff = 0u; - p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Finish initialization of the control block. - // Copy Id string in three steps to make sure "SEGGER RTT" is not found - // in initializer memory (usually flash) by J-Link - // - STRCPY(&p->acID[7], "RTT", 9); - STRCPY(&p->acID[0], "SEGGER", 7); - p->acID[6] = ' '; -} - -/********************************************************************* -* -* _WriteBlocking() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* The caller is responsible for managing the write chunk sizes as -* _WriteBlocking() will block until all data has been posted successfully. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* >= 0 - Number of bytes written into buffer. -*/ -static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { - unsigned NumBytesToWrite; - unsigned NumBytesWritten; - unsigned RdOff; - unsigned WrOff; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - // - // Write data to buffer and handle wrap-around if necessary - // - NumBytesWritten = 0u; - WrOff = pRing->WrOff; - do { - RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime - if (RdOff > WrOff) { - NumBytesToWrite = RdOff - WrOff - 1u; - } else { - NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); - } - NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around - NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - NumBytesWritten += NumBytesToWrite; - NumBytes -= NumBytesToWrite; - WrOff += NumBytesToWrite; - while (NumBytesToWrite--) { - *pDst++ = *pBuffer++; - }; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); - NumBytesWritten += NumBytesToWrite; - pBuffer += NumBytesToWrite; - NumBytes -= NumBytesToWrite; - WrOff += NumBytesToWrite; -#endif - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0u; - } - pRing->WrOff = WrOff; - } while (NumBytes); - // - return NumBytesWritten; -} - -/********************************************************************* -* -* _WriteNoCheck() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* It is callers responsibility to make sure data actually fits in buffer. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking -*/ -static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { - unsigned NumBytesAtOnce; - unsigned WrOff; - unsigned Rem; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - - WrOff = pRing->WrOff; - Rem = pRing->SizeOfBuffer - WrOff; - if (Rem > NumBytes) { - // - // All data fits before wrap around - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - WrOff += NumBytes; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff = WrOff; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; -#endif - } else { - // - // We reach the end of the buffer, so need to wrap around - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - NumBytesAtOnce = Rem; - while (NumBytesAtOnce--) { - *pDst++ = *pData++; - }; - pDst = pRing->pBuffer; - NumBytesAtOnce = NumBytes - Rem; - while (NumBytesAtOnce--) { - *pDst++ = *pData++; - }; - pRing->WrOff = NumBytes - Rem; -#else - NumBytesAtOnce = Rem; - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); - NumBytesAtOnce = NumBytes - Rem; - SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce); - pRing->WrOff = NumBytesAtOnce; -#endif - } -} - -/********************************************************************* -* -* _PostTerminalSwitch() -* -* Function description -* Switch terminal to the given terminal ID. It is the caller's -* responsibility to ensure the terminal ID is correct and there is -* enough space in the buffer for this to complete successfully. -* -* Parameters -* pRing Ring buffer to post to. -* TerminalId Terminal ID to switch to. -*/ -static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { - unsigned char ac[2]; - - ac[0] = 0xFFu; - ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit - _WriteBlocking(pRing, (const char*)ac, 2u); -} - -/********************************************************************* -* -* _GetAvailWriteSpace() -* -* Function description -* Returns the number of bytes that can be written to the ring -* buffer without blocking. -* -* Parameters -* pRing Ring buffer to check. -* -* Return value -* Number of bytes that are free in the buffer. -*/ -static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { - unsigned RdOff; - unsigned WrOff; - unsigned r; - // - // Avoid warnings regarding volatile access order. It's not a problem - // in this case, but dampen compiler enthusiasm. - // - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - if (RdOff <= WrOff) { - r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; - } else { - r = RdOff - WrOff - 1u; - } - return r; -} - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ -/********************************************************************* -* -* SEGGER_RTT_ReadUpBufferNoLock() -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the application. -* Do not lock against interrupts and multiple access. -* Used to do the same operation that J-Link does, to transfer -* RTT data via other channels, such as TCP/IP or UART. -* -* Parameters -* BufferIndex Index of Up-buffer to be used. -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -* -* Additional information -* This function must not be called when J-Link might also do RTT. -*/ -unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - unsigned NumBytesRem; - unsigned NumBytesRead; - unsigned RdOff; - unsigned WrOff; - unsigned char* pBuffer; - SEGGER_RTT_BUFFER_UP* pRing; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - const char* pSrc; -#endif - // - INIT(); - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - pBuffer = (unsigned char*)pData; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - NumBytesRead = 0u; - // - // Read from current read position to wrap-around of buffer, first - // - if (RdOff > WrOff) { - NumBytesRem = pRing->SizeOfBuffer - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - // - // Handle wrap-around of buffer - // - if (RdOff == pRing->SizeOfBuffer) { - RdOff = 0u; - } - } - // - // Read remaining items of buffer - // - NumBytesRem = WrOff - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - if (NumBytesRem > 0u) { -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - } - // - // Update read offset of buffer - // - if (NumBytesRead) { - pRing->RdOff = RdOff; - } - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_ReadNoLock() -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* Do not lock against interrupts and multiple access. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - unsigned NumBytesRem; - unsigned NumBytesRead; - unsigned RdOff; - unsigned WrOff; - unsigned char* pBuffer; - SEGGER_RTT_BUFFER_DOWN* pRing; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - const char* pSrc; -#endif - // - INIT(); - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - pBuffer = (unsigned char*)pData; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - NumBytesRead = 0u; - // - // Read from current read position to wrap-around of buffer, first - // - if (RdOff > WrOff) { - NumBytesRem = pRing->SizeOfBuffer - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - // - // Handle wrap-around of buffer - // - if (RdOff == pRing->SizeOfBuffer) { - RdOff = 0u; - } - } - // - // Read remaining items of buffer - // - NumBytesRem = WrOff - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - if (NumBytesRem > 0u) { -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - } - if (NumBytesRead) { - pRing->RdOff = RdOff; - } - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_ReadUpBuffer -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the application. -* Used to do the same operation that J-Link does, to transfer -* RTT data via other channels, such as TCP/IP or UART. -* -* Parameters -* BufferIndex Index of Up-buffer to be used. -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -* -* Additional information -* This function must not be called when J-Link might also do RTT. -* This function locks against all other RTT operations. I.e. during -* the read operation, writing is also locked. -* If only one consumer reads from the up buffer, -* call sEGGER_RTT_ReadUpBufferNoLock() instead. -*/ -unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { - unsigned NumBytesRead; - // - SEGGER_RTT_LOCK(); - // - // Call the non-locking read function - // - NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_Read -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { - unsigned NumBytesRead; - // - SEGGER_RTT_LOCK(); - // - // Call the non-locking read function - // - NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteWithOverwriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block. -* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application -* and overwrites data if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, data is overwritten. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link -* connection reads RTT data. -*/ -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Check if we will overwrite data and need to adjust the RdOff. - // - if (pRing->WrOff == pRing->RdOff) { - Avail = pRing->SizeOfBuffer - 1u; - } else if ( pRing->WrOff < pRing->RdOff) { - Avail = pRing->RdOff - pRing->WrOff - 1u; - } else { - Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; - } - if (NumBytes > Avail) { - pRing->RdOff += (NumBytes - Avail); - while (pRing->RdOff >= pRing->SizeOfBuffer) { - pRing->RdOff -= pRing->SizeOfBuffer; - } - } - // - // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds - // - Avail = pRing->SizeOfBuffer - pRing->WrOff; - do { - if (Avail > NumBytes) { - // - // Last round - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + pRing->WrOff; - Avail = NumBytes; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff += Avail; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes); - pRing->WrOff += NumBytes; -#endif - break; - } else { - // - // Wrap-around necessary, write until wrap-around and reset WrOff - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + pRing->WrOff; - NumBytes -= Avail; - while (Avail--) { - *pDst++ = *pData++; - }; - pRing->WrOff = 0; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail); - pData += Avail; - pRing->WrOff = 0; - NumBytes -= Avail; -#endif - Avail = (pRing->SizeOfBuffer - 1); - } - } while (NumBytes); -} - -/********************************************************************* -* -* SEGGER_RTT_WriteSkipNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteSkipNoLock does not lock the application and -* skips all data, if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* MUST be > 0!!! -* This is done for performance reasons, so no initial check has do be done. -* -* Return value -* 1: Data has been copied -* 0: No space, data has not been copied -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, all data is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -#if (RTT_USE_ASM == 0) -unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - unsigned RdOff; - unsigned WrOff; - unsigned Rem; - // - // Cases: - // 1) RdOff <= WrOff => Space until wrap-around is sufficient - // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) - // 3) RdOff < WrOff => No space in buf - // 4) RdOff > WrOff => Space is sufficient - // 5) RdOff > WrOff => No space in buf - // - // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough - // - pData = (const char *)pBuffer; - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - if (RdOff <= WrOff) { // Case 1), 2) or 3) - Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) - if (Avail >= NumBytes) { // Case 1)? -CopyStraight: - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - return 1; - } - Avail += RdOff; // Space incl. wrap-around - if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit) - Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer - memcpy(pRing->pBuffer + WrOff, pData, Rem); // Copy 1st chunk - NumBytes -= Rem; - // - // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used - // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element - // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks - // Therefore, check if 2nd memcpy is necessary at all - // - if (NumBytes) { - memcpy(pRing->pBuffer, pData + Rem, NumBytes); - } - pRing->WrOff = NumBytes; - return 1; - } - } else { // Potential case 4) - Avail = RdOff - WrOff - 1u; - if (Avail >= NumBytes) { // Case 4)? => If not, we have case 5) (does not fit) - goto CopyStraight; - } - } - return 0; // No space in buffer -} -#endif - -/********************************************************************* -* -* SEGGER_RTT_WriteDownBufferNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block inside a buffer. -* SEGGER_RTT_WriteDownBufferNoLock does not lock the application. -* Used to do the same operation that J-Link does, to transfer -* RTT data from other channels, such as TCP/IP or UART. -* -* Parameters -* BufferIndex Index of "Down"-buffer to be used. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Down"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -* -* Additional information -* This function must not be called when J-Link might also do RTT. -*/ -unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - unsigned Avail; - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - - pData = (const char *)pBuffer; - // - // Get "to-target" ring buffer. - // It is save to cast that to a "to-host" buffer. Up and Down buffer differ in volatility of offsets that might be modified by J-Link. - // - pRing = (SEGGER_RTT_BUFFER_UP*)&_SEGGER_RTT.aDown[BufferIndex]; - // - // How we output depends upon the mode... - // - switch (pRing->Flags) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother. - // - Avail = _GetAvailWriteSpace(pRing); - if (Avail < NumBytes) { - Status = 0u; - } else { - Status = NumBytes; - _WriteNoCheck(pRing, pData, NumBytes); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode, trim to what we can output without blocking. - // - Avail = _GetAvailWriteSpace(pRing); - Status = Avail < NumBytes ? Avail : NumBytes; - _WriteNoCheck(pRing, pData, Status); - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - Status = _WriteBlocking(pRing, pData, NumBytes); - break; - default: - Status = 0u; - break; - } - // - // Finish up. - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteNoLock does not lock the application. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - unsigned Avail; - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // How we output depends upon the mode... - // - switch (pRing->Flags) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother. - // - Avail = _GetAvailWriteSpace(pRing); - if (Avail < NumBytes) { - Status = 0u; - } else { - Status = NumBytes; - _WriteNoCheck(pRing, pData, NumBytes); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode, trim to what we can output without blocking. - // - Avail = _GetAvailWriteSpace(pRing); - Status = Avail < NumBytes ? Avail : NumBytes; - _WriteNoCheck(pRing, pData, Status); - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - Status = _WriteBlocking(pRing, pData, NumBytes); - break; - default: - Status = 0u; - break; - } - // - // Finish up. - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteDownBuffer -* -* Function description -* Stores a specified number of characters in SEGGER RTT control block in a buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Down"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* -* Additional information -* This function must not be called when J-Link might also do RTT. -* This function locks against all other RTT operations. I.e. during -* the write operation, writing from the application is also locked. -* If only one consumer writes to the down buffer, -* call SEGGER_RTT_WriteDownBufferNoLock() instead. -*/ -unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Call the non-locking write function - // - Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_Write -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -*/ -unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Call the non-locking write function - // - Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteString -* -* Function description -* Stores string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* s Pointer to string. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* (2) String passed to this function has to be \0 terminated -* (3) \0 termination character is *not* stored in RTT buffer -*/ -unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { - unsigned Len; - - Len = STRLEN(s); - return SEGGER_RTT_Write(BufferIndex, s, Len); -} - -/********************************************************************* -* -* SEGGER_RTT_PutCharSkipNoLock -* -* Function description -* Stores a single character/byte in SEGGER RTT buffer. -* SEGGER_RTT_PutCharSkipNoLock does not lock the application and -* skips the byte, if it does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* c Byte to be stored. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, the character is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ - -unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned WrOff; - unsigned Status; - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Get write position and handle wrap-around if necessary - // - WrOff = pRing->WrOff + 1; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0; - } - // - // Output byte if free space is available - // - if (WrOff != pRing->RdOff) { - pRing->pBuffer[pRing->WrOff] = c; - pRing->WrOff = WrOff; - Status = 1; - } else { - Status = 0; - } - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_PutCharSkip -* -* Function description -* Stores a single character/byte in SEGGER RTT buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* c Byte to be stored. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, the character is dropped. -*/ - -unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned WrOff; - unsigned Status; - // - // Prepare - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Get write position and handle wrap-around if necessary - // - WrOff = pRing->WrOff + 1; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0; - } - // - // Output byte if free space is available - // - if (WrOff != pRing->RdOff) { - pRing->pBuffer[pRing->WrOff] = c; - pRing->WrOff = WrOff; - Status = 1; - } else { - Status = 0; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - - /********************************************************************* -* -* SEGGER_RTT_PutChar -* -* Function description -* Stores a single character/byte in SEGGER RTT buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* c Byte to be stored. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -*/ - -unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned WrOff; - unsigned Status; - // - // Prepare - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Get write position and handle wrap-around if necessary - // - WrOff = pRing->WrOff + 1; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0; - } - // - // Wait for free space if mode is set to blocking - // - if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { - while (WrOff == pRing->RdOff) { - ; - } - } - // - // Output byte if free space is available - // - if (WrOff != pRing->RdOff) { - pRing->pBuffer[pRing->WrOff] = c; - pRing->WrOff = WrOff; - Status = 1; - } else { - Status = 0; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_GetKey -* -* Function description -* Reads one character from the SEGGER RTT buffer. -* Host has previously stored data there. -* -* Return value -* < 0 - No character available (buffer empty). -* >= 0 - Character which has been read. (Possible values: 0 - 255) -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0. -*/ -int SEGGER_RTT_GetKey(void) { - char c; - int r; - - r = (int)SEGGER_RTT_Read(0u, &c, 1u); - if (r == 1) { - r = (int)(unsigned char)c; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_WaitKey -* -* Function description -* Waits until at least one character is avaible in the SEGGER RTT buffer. -* Once a character is available, it is read and this function returns. -* -* Return value -* >=0 - Character which has been read. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -* (2) This function is blocking if no character is present in RTT buffer -*/ -int SEGGER_RTT_WaitKey(void) { - int r; - - do { - r = SEGGER_RTT_GetKey(); - } while (r < 0); - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasKey -* -* Function description -* Checks if at least one character for reading is available in the SEGGER RTT buffer. -* -* Return value -* == 0 - No characters are available to read. -* == 1 - At least one character is available. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -*/ -int SEGGER_RTT_HasKey(void) { - unsigned RdOff; - int r; - - INIT(); - RdOff = _SEGGER_RTT.aDown[0].RdOff; - if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { - r = 1; - } else { - r = 0; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasData -* -* Function description -* Check if there is data from the host in the given buffer. -* -* Return value: -* ==0: No data -* !=0: Data in buffer -* -*/ -unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { - SEGGER_RTT_BUFFER_DOWN* pRing; - unsigned v; - - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - v = pRing->WrOff; - return v - pRing->RdOff; -} - -/********************************************************************* -* -* SEGGER_RTT_HasDataUp -* -* Function description -* Check if there is data remaining to be sent in the given buffer. -* -* Return value: -* ==0: No data -* !=0: Data in buffer -* -*/ -unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned v; - - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - v = pRing->RdOff; - return pRing->WrOff - v; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocDownBuffer -* -* Function description -* Run-time configuration of the next down-buffer (H->T). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocUpBuffer -* -* Function description -* Run-time configuration of the next up-buffer (T->H). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer (T->H). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. -* < 0 - Error -* -* Additional information -* Buffer 0 is configured on compile-time. -* May only be called once per buffer. -* Buffer name and flags can be reconfigured using the appropriate functions. -*/ -int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigDownBuffer -* -* Function description -* Run-time configuration of a specific down-buffer (H->T). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 O.K. -* < 0 Error -* -* Additional information -* Buffer 0 is configured on compile-time. -* May only be called once per buffer. -* Buffer name and flags can be reconfigured using the appropriate functions. -*/ -int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameDownBuffer -* -* Function description -* Run-time configuration of a specific Down-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetFlagsUpBuffer -* -* Function description -* Run-time configuration of specific up-buffer flags (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer. -* Flags Flags to set for the buffer. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetFlagsDownBuffer -* -* Function description -* Run-time configuration of specific Down-buffer flags (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* Flags Flags to set for the buffer. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_Init -* -* Function description -* Initializes the RTT Control Block. -* Should be used in RAM targets, at start of the application. -* -*/ -void SEGGER_RTT_Init (void) { - _DoInit(); -} - -/********************************************************************* -* -* SEGGER_RTT_SetTerminal -* -* Function description -* Sets the terminal to be used for output on channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* -* Return value -* >= 0 O.K. -* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) -*/ -int SEGGER_RTT_SetTerminal (unsigned char TerminalId) { - unsigned char ac[2]; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - int r; - // - INIT(); - // - r = 0; - ac[0] = 0xFFu; - if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels - ac[1] = _aTerminalId[TerminalId]; - pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed - SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing - if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { - _ActiveTerminal = TerminalId; - _WriteBlocking(pRing, (const char*)ac, 2u); - } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes - Avail = _GetAvailWriteSpace(pRing); - if (Avail >= 2) { - _ActiveTerminal = TerminalId; // Only change active terminal in case of success - _WriteNoCheck(pRing, (const char*)ac, 2u); - } else { - r = -1; - } - } - SEGGER_RTT_UNLOCK(); - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_TerminalOut -* -* Function description -* Writes a string to the given terminal -* without changing the terminal for channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* s String to be printed on the terminal. -* -* Return value -* >= 0 - Number of bytes written. -* < 0 - Error. -* -*/ -int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) { - int Status; - unsigned FragLen; - unsigned Avail; - SEGGER_RTT_BUFFER_UP* pRing; - // - INIT(); - // - // Validate terminal ID. - // - if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[0]; - // - // Need to be able to change terminal, write data, change back. - // Compute the fixed and variable sizes. - // - FragLen = STRLEN(s); - // - // How we output depends upon the mode... - // - SEGGER_RTT_LOCK(); - Avail = _GetAvailWriteSpace(pRing); - switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother switching terminals at all. - // - if (Avail < (FragLen + 4u)) { - Status = 0; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode and there is not enough space for everything, - // trim the output but always include the terminal switch. If no room - // for terminal switch, skip that totally. - // - if (Avail < 4u) { - Status = -1; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - break; - default: - Status = -1; - break; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - } else { - Status = -1; - } - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_GetAvailWriteSpace -* -* Function description -* Returns the number of bytes available in the ring buffer. -* -* Parameters -* BufferIndex Index of the up buffer. -* -* Return value -* Number of bytes that are free in the selected up buffer. -*/ -unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex){ - return _GetAvailWriteSpace(&_SEGGER_RTT.aUp[BufferIndex]); -} - - -/********************************************************************* -* -* SEGGER_RTT_GetBytesInBuffer() -* -* Function description -* Returns the number of bytes currently used in the up buffer. -* -* Parameters -* BufferIndex Index of the up buffer. -* -* Return value -* Number of bytes that are used in the buffer. -*/ -unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) { - unsigned RdOff; - unsigned WrOff; - unsigned r; - // - // Avoid warnings regarding volatile access order. It's not a problem - // in this case, but dampen compiler enthusiasm. - // - RdOff = _SEGGER_RTT.aUp[BufferIndex].RdOff; - WrOff = _SEGGER_RTT.aUp[BufferIndex].WrOff; - if (RdOff <= WrOff) { - r = WrOff - RdOff; - } else { - r = _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff); - } - return r; -} - -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h deleted file mode 100644 index 3c04df55f..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h +++ /dev/null @@ -1,321 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.h -Purpose : Implementation of SEGGER real-time transfer which allows - real-time communication on targets which support debugger - memory accesses while the CPU is running. -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ - -#ifndef SEGGER_RTT_H -#define SEGGER_RTT_H - -#include "SEGGER_RTT_Conf.h" - - - -/********************************************************************* -* -* Defines, defaults -* -********************************************************************** -*/ -#ifndef RTT_USE_ASM - #if (defined __SES_ARM) // SEGGER Embedded Studio - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __CROSSWORKS_ARM) // Rowley Crossworks - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __GNUC__) // GCC - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __clang__) // Clang compiler - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __IASMARM__) // IAR assembler - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ICCARM__) // IAR compiler - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #else - #define _CC_HAS_RTT_ASM_SUPPORT 0 - #endif - #if (defined __ARM_ARCH_7M__) // Cortex-M3/4 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ARM_ARCH_7EM__) // Cortex-M7 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ARM7M__) // IAR Cortex-M3/4 - #if (__CORE__ == __ARM7M__) - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #else - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - #elif (defined __ARM7EM__) // IAR Cortex-M7 - #if (__CORE__ == __ARM7EM__) - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #else - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - #else - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - // - // If IDE and core support the ASM version, enable ASM version by default - // - #if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT) - #define RTT_USE_ASM (1) - #else - #define RTT_USE_ASM (0) - #endif -#endif - -#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file -#include -#include - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as up-buffer (T->H) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - unsigned WrOff; // Position of next item to be written by either target. - volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_UP; - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as down-buffer (H->T) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. - unsigned RdOff; // Position of next item to be read by target (down-buffer). - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_DOWN; - -// -// RTT control block which describes the number of buffers available -// as well as the configuration for each buffer -// -// -typedef struct { - char acID[16]; // Initialized to "SEGGER RTT" - int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) - int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) - SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host - SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target -} SEGGER_RTT_CB; - -/********************************************************************* -* -* Global data -* -********************************************************************** -*/ -extern SEGGER_RTT_CB _SEGGER_RTT; - -/********************************************************************* -* -* RTT API functions -* -********************************************************************** -*/ -#ifdef __cplusplus - extern "C" { -#endif -int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_GetKey (void); -unsigned SEGGER_RTT_HasData (unsigned BufferIndex); -int SEGGER_RTT_HasKey (void); -unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); -void SEGGER_RTT_Init (void); -unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); -int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); -int SEGGER_RTT_WaitKey (void); -unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); -unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); -// -// Function macro for performance optimization -// -#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) - -#if RTT_USE_ASM - #define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock -#endif - -/********************************************************************* -* -* RTT transfer functions to send RTT data via other channels. -* -********************************************************************** -*/ -unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); - -#define SEGGER_RTT_HASDATA_UP(n) (_SEGGER_RTT.aUp[n].WrOff - _SEGGER_RTT.aUp[n].RdOff) - -/********************************************************************* -* -* RTT "Terminal" API functions -* -********************************************************************** -*/ -int SEGGER_RTT_SetTerminal (unsigned char TerminalId); -int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s); - -/********************************************************************* -* -* RTT printf functions (require SEGGER_RTT_printf.c) -* -********************************************************************** -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); - -#ifdef __cplusplus - } -#endif - -#endif // ifndef(SEGGER_RTT_ASM) - -/********************************************************************* -* -* Defines -* -********************************************************************** -*/ - -// -// Operating modes. Define behavior if buffer is full (not enough space for entire message) -// -#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) -#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. -#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. -#define SEGGER_RTT_MODE_MASK (3) - -// -// Control sequences, based on ANSI. -// Can be used to control color, and clear the screen -// -#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors -#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left - -#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" -#define RTT_CTRL_TEXT_RED "\x1B[2;31m" -#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" -#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" -#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" -#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" -#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" -#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" - -#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" -#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" -#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" -#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" -#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" -#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" -#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" -#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" - -#define RTT_CTRL_BG_BLACK "\x1B[24;40m" -#define RTT_CTRL_BG_RED "\x1B[24;41m" -#define RTT_CTRL_BG_GREEN "\x1B[24;42m" -#define RTT_CTRL_BG_YELLOW "\x1B[24;43m" -#define RTT_CTRL_BG_BLUE "\x1B[24;44m" -#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" -#define RTT_CTRL_BG_CYAN "\x1B[24;46m" -#define RTT_CTRL_BG_WHITE "\x1B[24;47m" - -#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" -#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" -#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" -#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" -#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" -#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" -#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" -#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" - - -#endif - -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S deleted file mode 100644 index 78cde4d75..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S +++ /dev/null @@ -1,235 +0,0 @@ -/********************************************************************* -* (c) SEGGER Microcontroller GmbH * -* The Embedded Experts * -* www.segger.com * -********************************************************************** - --------------------------- END-OF-HEADER ----------------------------- - -File : SEGGER_RTT_ASM_ARMv7M.S -Purpose : Assembler implementation of RTT functions for ARMv7M - -Additional information: - This module is written to be assembler-independent and works with - GCC and clang (Embedded Studio) and IAR. -*/ - -#define SEGGER_RTT_ASM // Used to control processed input from header file -#include "SEGGER_RTT.h" - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ -#define _CCIAR 0 -#define _CCCLANG 1 - -#if (defined __SES_ARM) || (defined __GNUC__) || (defined __clang__) - #define _CC_TYPE _CCCLANG - #define _PUB_SYM .global - #define _EXT_SYM .extern - #define _END .end - #define _WEAK .weak - #define _THUMB_FUNC .thumb_func - #define _THUMB_CODE .code 16 - #define _WORD .word - #define _SECTION(Sect, Type, AlignExp) .section Sect ##, "ax" - #define _ALIGN(Exp) .align Exp - #define _PLACE_LITS .ltorg - #define _DATA_SECT_START - #define _C_STARTUP _start - #define _STACK_END __stack_end__ - #define _RAMFUNC - // - // .text => Link to flash - // .fast => Link to RAM - // OtherSect => Usually link to RAM - // Alignment is 2^x - // -#elif defined (__IASMARM__) - #define _CC_TYPE _CCIAR - #define _PUB_SYM PUBLIC - #define _EXT_SYM EXTERN - #define _END END - #define _WEAK _WEAK - #define _THUMB_FUNC - #define _THUMB_CODE THUMB - #define _WORD DCD - #define _SECTION(Sect, Type, AlignExp) SECTION Sect ## : ## Type ## :REORDER:NOROOT ## (AlignExp) - #define _ALIGN(Exp) alignrom Exp - #define _PLACE_LITS - #define _DATA_SECT_START DATA - #define _C_STARTUP __iar_program_start - #define _STACK_END sfe(CSTACK) - #define _RAMFUNC SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR - // - // .text => Link to flash - // .textrw => Link to RAM - // OtherSect => Usually link to RAM - // NOROOT => Allows linker to throw away the function, if not referenced - // Alignment is 2^x - // -#endif - -#if (_CC_TYPE == _CCIAR) - NAME SEGGER_RTT_ASM_ARMv7M -#else - .syntax unified -#endif - -#if defined (RTT_USE_ASM) && (RTT_USE_ASM == 1) - #define SHT_PROGBITS 0x1 - -/********************************************************************* -* -* Public / external symbols -* -********************************************************************** -*/ - - _EXT_SYM __aeabi_memcpy - _EXT_SYM __aeabi_memcpy4 - _EXT_SYM _SEGGER_RTT - - _PUB_SYM SEGGER_RTT_ASM_WriteSkipNoLock - -/********************************************************************* -* -* SEGGER_RTT_WriteSkipNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteSkipNoLock does not lock the application and -* skips all data, if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* MUST be > 0!!! -* This is done for performance reasons, so no initial check has do be done. -* -* Return value -* 1: Data has been copied -* 0: No space, data has not been copied -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, all data is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ - _SECTION(.text, CODE, 2) - _ALIGN(2) - _THUMB_FUNC -SEGGER_RTT_ASM_WriteSkipNoLock: // unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pData, unsigned NumBytes) { - // - // Cases: - // 1) RdOff <= WrOff => Space until wrap-around is sufficient - // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) - // 3) RdOff < WrOff => No space in buf - // 4) RdOff > WrOff => Space is sufficient - // 5) RdOff > WrOff => No space in buf - // - // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough - // - // Register usage: - // R0 Temporary needed as RdOff, register later on - // R1 pData - // R2 - // R3 register. Hold free for subroutine calls - // R4 - // R5 pRing->pBuffer - // R6 pRing (Points to active struct SEGGER_RTT_BUFFER_DOWN) - // R7 WrOff - // - PUSH {R4-R7} - ADD R3,R0,R0, LSL #+1 - LDR.W R0,=_SEGGER_RTT // pRing = &_SEGGER_RTT.aUp[BufferIndex]; - ADD R0,R0,R3, LSL #+3 - ADD R6,R0,#+24 - LDR R0,[R6, #+16] // RdOff = pRing->RdOff; - LDR R7,[R6, #+12] // WrOff = pRing->WrOff; - LDR R5,[R6, #+4] // pRing->pBuffer - CMP R7,R0 - BCC.N _CheckCase4 // if (RdOff <= WrOff) { => Case 1), 2) or 3) - // - // Handling for case 1, later on identical to case 4 - // - LDR R3,[R6, #+8] // Avail = pRing->SizeOfBuffer - WrOff - 1u; => Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) - SUBS R4,R3,R7 // (Used in case we jump into case 2 afterwards) - SUBS R3,R4,#+1 // - CMP R3,R2 - BCC.N _CheckCase2 // if (Avail >= NumBytes) { => Case 1)? -_Case4: - ADDS R5,R7,R5 // pBuffer += WrOff - ADDS R0,R2,R7 // v = WrOff + NumBytes - // - // 2x unrolling for the copy loop that is used most of the time - // This is a special optimization for small SystemView packets and makes them even faster - // - _ALIGN(2) -_LoopCopyStraight: // memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - LDRB R3,[R1], #+1 - STRB R3,[R5], #+1 // *pDest++ = *pSrc++ - SUBS R2,R2,#+1 - BEQ _CSDone - LDRB R3,[R1], #+1 - STRB R3,[R5], #+1 // *pDest++ = *pSrc++ - SUBS R2,R2,#+1 - BNE _LoopCopyStraight -_CSDone: - STR R0,[R6, #+12] // pRing->WrOff = WrOff + NumBytes; - MOVS R0,#+1 - POP {R4-R7} - BX LR // Return 1 -_CheckCase2: - ADDS R0,R0,R3 // Avail += RdOff; => Space incl. wrap-around - CMP R0,R2 - BCC.N _Case3 // if (Avail >= NumBytes) { => Case 2? => If not, we have case 3) (does not fit) - // - // Handling for case 2 - // - ADDS R0,R7,R5 // v = pRing->pBuffer + WrOff => Do not change pRing->pBuffer here because 2nd chunk needs org. value - SUBS R2,R2,R4 // NumBytes -= Rem; (Rem = pRing->SizeOfBuffer - WrOff; => Space until end of buffer) -_LoopCopyBeforeWrapAround: // memcpy(pRing->pBuffer + WrOff, pData, Rem); => Copy 1st chunk - LDRB R3,[R1], #+1 - STRB R3,[R0], #+1 // *pDest++ = *pSrc++ - SUBS R4,R4,#+1 - BNE _LoopCopyBeforeWrapAround - // - // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used - // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element - // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks - // Therefore, check if 2nd memcpy is necessary at all - // - ADDS R4,R2,#+0 // Save (needed as counter in loop but must be written to after the loop). Also use this inst to update the flags to skip 2nd loop if possible - BEQ.N _No2ChunkNeeded // if (NumBytes) { -_LoopCopyAfterWrapAround: // memcpy(pRing->pBuffer, pData + Rem, NumBytes); - LDRB R3,[R1], #+1 // pData already points to the next src byte due to copy loop increment before this loop - STRB R3,[R5], #+1 // *pDest++ = *pSrc++ - SUBS R2,R2,#+1 - BNE _LoopCopyAfterWrapAround -_No2ChunkNeeded: - STR R4,[R6, #+12] // pRing->WrOff = NumBytes; => Must be written after copying data because J-Link may read control block asynchronously while writing into buffer - MOVS R0,#+1 - POP {R4-R7} - BX LR // Return 1 -_CheckCase4: - SUBS R0,R0,R7 - SUBS R0,R0,#+1 // Avail = RdOff - WrOff - 1u; - CMP R0,R2 - BCS.N _Case4 // if (Avail >= NumBytes) { => Case 4) == 1) ? => If not, we have case 5) == 3) (does not fit) -_Case3: - MOVS R0,#+0 - POP {R4-R7} - BX LR // Return 0 - _PLACE_LITS - -#endif // defined (RTT_USE_ASM) && (RTT_USE_ASM == 1) - _END - -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h deleted file mode 100644 index 5e79d7e67..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h +++ /dev/null @@ -1,384 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Conf.h -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. -Revision: $Rev: 18601 $ - -*/ - -#ifndef SEGGER_RTT_CONF_H -#define SEGGER_RTT_CONF_H - -#ifdef __IAR_SYSTEMS_ICC__ - #include -#endif - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ -#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS - #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3) -#endif - -#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS - #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3) -#endif - -#ifndef BUFFER_SIZE_UP - #define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) -#endif - -#ifndef BUFFER_SIZE_DOWN - #define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) -#endif - -#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE - #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) -#endif - -#ifndef SEGGER_RTT_MODE_DEFAULT - #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) -#endif - -/********************************************************************* -* -* RTT memcpy configuration -* -* memcpy() is good for large amounts of data, -* but the overhead is big for small amounts, which are usually stored via RTT. -* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. -* -* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. -* This is may be required with memory access restrictions, -* such as on Cortex-A devices with MMU. -*/ -#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP - #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop -#endif -// -// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets -// -//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) -// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) -//#endif - -// -// Target is not allowed to perform other RTT operations while string still has not been stored completely. -// Otherwise we would probably end up with a mixed string in the buffer. -// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. -// -// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. -// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. -// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. -// (Higher priority = lower priority number) -// Default value for embOS: 128u -// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC -// or define SEGGER_RTT_LOCK() to completely disable interrupts. -// -#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) -#endif - -/********************************************************************* -* -* RTT lock configuration for SEGGER Embedded Studio, -* Rowley CrossStudio and GCC -*/ -#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32)) - #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, primask \n\t" \ - "movs r1, $1 \n\t" \ - "msr primask, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, basepri \n\t" \ - "mov r1, %1 \n\t" \ - "msr basepri, r1 \n\t" \ - : "=r" (LockState) \ - : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - - #elif defined(__ARM_ARCH_7A__) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs r1, CPSR \n\t" \ - "mov %0, r1 \n\t" \ - "orr r1, r1, #0xC0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ - "mrs r1, CPSR \n\t" \ - "bic r1, r1, #0xC0 \n\t" \ - "and r0, r0, #0xC0 \n\t" \ - "orr r1, r1, r0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : \ - : "r" (LockState) \ - : "r0", "r1" \ - ); \ - } - #elif defined(__riscv) || defined(__riscv_xlen) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("csrr %0, mstatus \n\t" \ - "csrci mstatus, 8 \n\t" \ - "andi %0, %0, 8 \n\t" \ - : "=r" (LockState) \ - : \ - : \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \ - "or %0, %0, a1 \n\t" \ - "csrs mstatus, %0 \n\t" \ - : \ - : "r" (LockState) \ - : "a1" \ - ); \ - } - #else - #define SEGGER_RTT_LOCK() - #define SEGGER_RTT_UNLOCK() - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR EWARM -*/ -#ifdef __ICCARM__ - #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \ - (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ - } - #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \ - (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \ - (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \ - (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_BASEPRI(); \ - __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR RX -*/ -#ifdef __ICCRX__ - #define SEGGER_RTT_LOCK() { \ - unsigned long LockState; \ - LockState = __get_interrupt_state(); \ - __disable_interrupt(); - - #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR RL78 -*/ -#ifdef __ICCRL78__ - #define SEGGER_RTT_LOCK() { \ - __istate_t LockState; \ - LockState = __get_interrupt_state(); \ - __disable_interrupt(); - - #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for KEIL ARM -*/ -#ifdef __CC_ARM - #if (defined __TARGET_ARCH_6S_M) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char PRIMASK __asm( "primask"); \ - LockState = PRIMASK; \ - PRIMASK = 1u; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ - __schedule_barrier(); \ - } - #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char BASEPRI __asm( "basepri"); \ - LockState = BASEPRI; \ - BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ - __schedule_barrier(); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for TI ARM -*/ -#ifdef __TI_ARM__ - #if defined (__TI_ARM_V6M0__) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ - } - #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for CCRX -*/ -#ifdef __RX - #define SEGGER_RTT_LOCK() { \ - unsigned long LockState; \ - LockState = get_psw() & 0x010000; \ - clrpsw_i(); - - #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for embOS Simulation on Windows -* (Can also be used for generic RTT locking with embOS) -*/ -#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS) - -void OS_SIM_EnterCriticalSection(void); -void OS_SIM_LeaveCriticalSection(void); - -#define SEGGER_RTT_LOCK() { \ - OS_SIM_EnterCriticalSection(); - -#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration fallback -*/ -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) -#endif - -#endif -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c deleted file mode 100644 index 4c996b408..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c +++ /dev/null @@ -1,500 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_printf.c -Purpose : Replacement for printf to write formatted data via RTT -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ -#include "SEGGER_RTT.h" -#include "SEGGER_RTT_Conf.h" - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE - #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) -#endif - -#include -#include - - -#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) -#define FORMAT_FLAG_PAD_ZERO (1u << 1) -#define FORMAT_FLAG_PRINT_SIGN (1u << 2) -#define FORMAT_FLAG_ALTERNATE (1u << 3) - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -typedef struct { - char* pBuffer; - unsigned BufferSize; - unsigned Cnt; - - int ReturnValue; - - unsigned RTTBufferIndex; -} SEGGER_RTT_PRINTF_DESC; - -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ - -/********************************************************************* -* -* Static code -* -********************************************************************** -*/ -/********************************************************************* -* -* _StoreChar -*/ -static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { - unsigned Cnt; - - Cnt = p->Cnt; - if ((Cnt + 1u) <= p->BufferSize) { - *(p->pBuffer + Cnt) = c; - p->Cnt = Cnt + 1u; - p->ReturnValue++; - } - // - // Write part of string, when the buffer is full - // - if (p->Cnt == p->BufferSize) { - if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { - p->ReturnValue = -1; - } else { - p->Cnt = 0u; - } - } -} - -/********************************************************************* -* -* _PrintUnsigned -*/ -static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { - static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - unsigned Div; - unsigned Digit; - unsigned Number; - unsigned Width; - char c; - - Number = v; - Digit = 1u; - // - // Get actual field width - // - Width = 1u; - while (Number >= Base) { - Number = (Number / Base); - Width++; - } - if (NumDigits > Width) { - Width = NumDigits; - } - // - // Print leading chars if necessary - // - if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { - if (FieldWidth != 0u) { - if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { - c = '0'; - } else { - c = ' '; - } - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, c); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - if (pBufferDesc->ReturnValue >= 0) { - // - // Compute Digit. - // Loop until Digit has the value of the highest digit required. - // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. - // - while (1) { - if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) - NumDigits--; - } else { - Div = v / Digit; - if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done - break; - } - } - Digit *= Base; - } - // - // Output digits - // - do { - Div = v / Digit; - v -= Div * Digit; - _StoreChar(pBufferDesc, _aV2C[Div]); - if (pBufferDesc->ReturnValue < 0) { - break; - } - Digit /= Base; - } while (Digit); - // - // Print trailing spaces if necessary - // - if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, ' '); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - } -} - -/********************************************************************* -* -* _PrintInt -*/ -static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { - unsigned Width; - int Number; - - Number = (v < 0) ? -v : v; - - // - // Get actual field width - // - Width = 1u; - while (Number >= (int)Base) { - Number = (Number / (int)Base); - Width++; - } - if (NumDigits > Width) { - Width = NumDigits; - } - if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { - FieldWidth--; - } - - // - // Print leading spaces if necessary - // - if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, ' '); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - // - // Print sign if necessary - // - if (pBufferDesc->ReturnValue >= 0) { - if (v < 0) { - v = -v; - _StoreChar(pBufferDesc, '-'); - } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { - _StoreChar(pBufferDesc, '+'); - } else { - - } - if (pBufferDesc->ReturnValue >= 0) { - // - // Print leading zeros if necessary - // - if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, '0'); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - if (pBufferDesc->ReturnValue >= 0) { - // - // Print number without sign - // - _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); - } - } - } -} - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ -/********************************************************************* -* -* SEGGER_RTT_vprintf -* -* Function description -* Stores a formatted string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") -* sFormat Pointer to format string -* pParamList Pointer to the list of arguments for the format string -* -* Return values -* >= 0: Number of bytes which have been stored in the "Up"-buffer. -* < 0: Error -*/ -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { - char c; - SEGGER_RTT_PRINTF_DESC BufferDesc; - int v; - unsigned NumDigits; - unsigned FormatFlags; - unsigned FieldWidth; - char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; - - BufferDesc.pBuffer = acBuffer; - BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; - BufferDesc.Cnt = 0u; - BufferDesc.RTTBufferIndex = BufferIndex; - BufferDesc.ReturnValue = 0; - - do { - c = *sFormat; - sFormat++; - if (c == 0u) { - break; - } - if (c == '%') { - // - // Filter out flags - // - FormatFlags = 0u; - v = 1; - do { - c = *sFormat; - switch (c) { - case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; - case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; - case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; - case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; - default: v = 0; break; - } - } while (v); - // - // filter out field with - // - FieldWidth = 0u; - do { - c = *sFormat; - if ((c < '0') || (c > '9')) { - break; - } - sFormat++; - FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); - } while (1); - - // - // Filter out precision (number of digits to display) - // - NumDigits = 0u; - c = *sFormat; - if (c == '.') { - sFormat++; - do { - c = *sFormat; - if ((c < '0') || (c > '9')) { - break; - } - sFormat++; - NumDigits = NumDigits * 10u + ((unsigned)c - '0'); - } while (1); - } - // - // Filter out length modifier - // - c = *sFormat; - do { - if ((c == 'l') || (c == 'h')) { - sFormat++; - c = *sFormat; - } else { - break; - } - } while (1); - // - // Handle specifiers - // - switch (c) { - case 'c': { - char c0; - v = va_arg(*pParamList, int); - c0 = (char)v; - _StoreChar(&BufferDesc, c0); - break; - } - case 'd': - v = va_arg(*pParamList, int); - _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); - break; - case 'u': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); - break; - case 'x': - case 'X': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); - break; - case 's': - { - const char * s = va_arg(*pParamList, const char *); - do { - c = *s; - s++; - if (c == '\0') { - break; - } - _StoreChar(&BufferDesc, c); - } while (BufferDesc.ReturnValue >= 0); - } - break; - case 'p': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); - break; - case '%': - _StoreChar(&BufferDesc, '%'); - break; - default: - break; - } - sFormat++; - } else { - _StoreChar(&BufferDesc, c); - } - } while (BufferDesc.ReturnValue >= 0); - - if (BufferDesc.ReturnValue > 0) { - // - // Write remaining data, if any - // - if (BufferDesc.Cnt != 0u) { - SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); - } - BufferDesc.ReturnValue += (int)BufferDesc.Cnt; - } - return BufferDesc.ReturnValue; -} - -/********************************************************************* -* -* SEGGER_RTT_printf -* -* Function description -* Stores a formatted string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") -* sFormat Pointer to format string, followed by the arguments for conversion -* -* Return values -* >= 0: Number of bytes which have been stored in the "Up"-buffer. -* < 0: Error -* -* Notes -* (1) Conversion specifications have following syntax: -* %[flags][FieldWidth][.Precision]ConversionSpecifier -* (2) Supported flags: -* -: Left justify within the field width -* +: Always print sign extension for signed conversions -* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision -* Supported conversion specifiers: -* c: Print the argument as one char -* d: Print the argument as a signed integer -* u: Print the argument as an unsigned integer -* x: Print the argument as an hexadecimal integer -* s: Print the string pointed to by the argument -* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { - int r; - va_list ParamList; - - va_start(ParamList, sFormat); - r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); - va_end(ParamList); - return r; -} -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c deleted file mode 100644 index da4a4b5f5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c +++ /dev/null @@ -1,120 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Syscalls_GCC.c -Purpose : Low-level functions for using printf() via RTT in GCC. - To use RTT for printf output, include this file in your - application. -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ -#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) - -#include // required for _write_r -#include "SEGGER_RTT.h" - - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ -// -// If necessary define the _reent struct -// to match the one passed by the used standard library. -// -struct _reent; - -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ -int _write(int file, char *ptr, int len); -int _write_r(struct _reent *r, int file, const void *ptr, int len); - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ - -/********************************************************************* -* -* _write() -* -* Function description -* Low-level write function. -* libc subroutines will use this system routine for output to all files, -* including stdout. -* Write data via RTT. -*/ -int _write(int file, char *ptr, int len) { - (void) file; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, ptr, len); - return len; -} - -/********************************************************************* -* -* _write_r() -* -* Function description -* Low-level reentrant write function. -* libc subroutines will use this system routine for output to all files, -* including stdout. -* Write data via RTT. -*/ -int _write_r(struct _reent *r, int file, const void *ptr, int len) { - (void) file; /* Not used, avoid warning */ - (void) r; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, ptr, len); - return len; -} - -#endif -/****** End Of File *************************************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c deleted file mode 100644 index 4c76752b3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c +++ /dev/null @@ -1,115 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Syscalls_IAR.c -Purpose : Low-level functions for using printf() via RTT in IAR. - To use RTT for printf output, include this file in your - application and set the Library Configuration to Normal. -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ -#ifdef __IAR_SYSTEMS_ICC__ - -// -// Since IAR EWARM V8 and EWRX V4, yfuns.h is considered as deprecated and LowLevelIOInterface.h -// shall be used instead. To not break any compatibility with older compiler versions, we have a -// version check in here. -// -#if ((defined __ICCARM__) && (__VER__ >= 8000000)) || ((defined __ICCRX__) && (__VER__ >= 400)) - #include -#else - #include -#endif - -#include "SEGGER_RTT.h" -#pragma module_name = "?__write" - -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ -size_t __write(int handle, const unsigned char * buffer, size_t size); - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ -/********************************************************************* -* -* __write() -* -* Function description -* Low-level write function. -* Standard library subroutines will use this system routine -* for output to all files, including stdout. -* Write data via RTT. -*/ -size_t __write(int handle, const unsigned char * buffer, size_t size) { - (void) handle; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, (const char*)buffer, size); - return size; -} - -/********************************************************************* -* -* __write_buffered() -* -* Function description -* Low-level write function. -* Standard library subroutines will use this system routine -* for output to all files, including stdout. -* Write data via RTT. -*/ -size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) { - (void) handle; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, (const char*)buffer, size); - return size; -} - -#endif -/****** End Of File *************************************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c deleted file mode 100644 index f7f5aed48..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c +++ /dev/null @@ -1,386 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : RTT_Syscalls_KEIL.c -Purpose : Retargeting module for KEIL MDK-CM3. - Low-level functions for using printf() via RTT -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ -#ifdef __CC_ARM - -#include -#include -#include -#include -#include - -#include "SEGGER_RTT.h" -/********************************************************************* -* -* #pragmas -* -********************************************************************** -*/ -#pragma import(__use_no_semihosting) - -#ifdef _MICROLIB - #pragma import(__use_full_stdio) -#endif - -/********************************************************************* -* -* Defines non-configurable -* -********************************************************************** -*/ - -/* Standard IO device handles - arbitrary, but any real file system handles must be - less than 0x8000. */ -#define STDIN 0x8001 // Standard Input Stream -#define STDOUT 0x8002 // Standard Output Stream -#define STDERR 0x8003 // Standard Error Stream - -/********************************************************************* -* -* Public const -* -********************************************************************** -*/ -#if __ARMCC_VERSION < 5000000 -//const char __stdin_name[] = "STDIN"; -const char __stdout_name[] = "STDOUT"; -const char __stderr_name[] = "STDERR"; -#endif - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ - -/********************************************************************* -* -* _ttywrch -* -* Function description: -* Outputs a character to the console -* -* Parameters: -* c - character to output -* -*/ -void _ttywrch(int c) { - fputc(c, stdout); // stdout - fflush(stdout); -} - -/********************************************************************* -* -* _sys_open -* -* Function description: -* Opens the device/file in order to do read/write operations -* -* Parameters: -* sName - sName of the device/file to open -* OpenMode - This parameter is currently ignored -* -* Return value: -* != 0 - Handle to the object to open, otherwise -* == 0 -"device" is not handled by this module -* -*/ -FILEHANDLE _sys_open(const char * sName, int OpenMode) { - (void)OpenMode; - // Register standard Input Output devices. - if (strcmp(sName, __stdout_name) == 0) { - return (STDOUT); - } else if (strcmp(sName, __stderr_name) == 0) { - return (STDERR); - } else - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_close -* -* Function description: -* Closes the handle to the open device/file -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* 0 - device/file closed -* -*/ -int _sys_close(FILEHANDLE hFile) { - (void)hFile; - return 0; // Not implemented -} - -/********************************************************************* -* -* _sys_write -* -* Function description: -* Writes the data to an open handle. -* Currently this function only outputs data to the console -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* pBuffer - Pointer to the data that shall be written -* NumBytes - Number of bytes to write -* Mode - The Mode that shall be used -* -* Return value: -* Number of bytes *not* written to the file/device -* -*/ -int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) { - int r = 0; - - (void)Mode; - if (hFile == STDOUT) { - SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes); - return 0; - } - return r; -} - -/********************************************************************* -* -* _sys_read -* -* Function description: -* Reads data from an open handle. -* Currently this modules does nothing. -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* pBuffer - Pointer to buffer to store the read data -* NumBytes - Number of bytes to read -* Mode - The Mode that shall be used -* -* Return value: -* Number of bytes read from the file/device -* -*/ -int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) { - (void)hFile; - (void)pBuffer; - (void)NumBytes; - (void)Mode; - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_istty -* -* Function description: -* This function shall return whether the opened file -* is a console device or not. -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* 1 - Device is a console -* 0 - Device is not a console -* -*/ -int _sys_istty(FILEHANDLE hFile) { - if (hFile > 0x8000) { - return (1); - } - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_seek -* -* Function description: -* Seeks via the file to a specific position -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* Pos - -* -* Return value: -* int - -* -*/ -int _sys_seek(FILEHANDLE hFile, long Pos) { - (void)hFile; - (void)Pos; - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_ensure -* -* Function description: -* -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* int - -* -*/ -int _sys_ensure(FILEHANDLE hFile) { - (void)hFile; - return (-1); // Not implemented -} - -/********************************************************************* -* -* _sys_flen -* -* Function description: -* Returns the length of the opened file handle -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* Length of the file -* -*/ -long _sys_flen(FILEHANDLE hFile) { - (void)hFile; - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_tmpnam -* -* Function description: -* This function converts the file number fileno for a temporary -* file to a unique filename, for example, tmp0001. -* -* Parameters: -* pBuffer - Pointer to a buffer to store the name -* FileNum - file number to convert -* MaxLen - Size of the buffer -* -* Return value: -* 1 - Error -* 0 - Success -* -*/ -int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) { - (void)pBuffer; - (void)FileNum; - (void)MaxLen; - return (1); // Not implemented -} - -/********************************************************************* -* -* _sys_command_string -* -* Function description: -* This function shall execute a system command. -* -* Parameters: -* cmd - Pointer to the command string -* len - Length of the string -* -* Return value: -* == NULL - Command was not successfully executed -* == sCmd - Command was passed successfully -* -*/ -char * _sys_command_string(char * cmd, int len) { - (void)len; - return cmd; // Not implemented -} - -/********************************************************************* -* -* _sys_exit -* -* Function description: -* This function is called when the application returns from main -* -* Parameters: -* ReturnCode - Return code from the main function -* -* -*/ -void _sys_exit(int ReturnCode) { - (void)ReturnCode; - while (1); // Not implemented -} - -#if __ARMCC_VERSION >= 5000000 -/********************************************************************* -* -* stdout_putchar -* -* Function description: -* Put a character to the stdout -* -* Parameters: -* ch - Character to output -* -* -*/ -int stdout_putchar(int ch) { - (void)ch; - return ch; // Not implemented -} -#endif - -#endif -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c deleted file mode 100644 index 5ce8457e1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c +++ /dev/null @@ -1,247 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Syscalls_SES.c -Purpose : Reimplementation of printf, puts and __getchar using RTT - in SEGGER Embedded Studio. - To use RTT for printf output, include this file in your - application. -Revision: $Rev: 18539 $ ----------------------------------------------------------------------- -*/ -#if (defined __SES_ARM) || (defined __SES_RISCV) || (defined __CROSSWORKS_ARM) - -#include "SEGGER_RTT.h" -#include -#include -#include "limits.h" -#include "__libc.h" -#include "__vfprintf.h" - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ -// -// Select string formatting implementation. -// -// RTT printf formatting -// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h) -// - No maximum string length. -// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c) -// Standard library printf formatting -// - Configurable formatting capabilities. -// - Full conversion specifier and flag support. -// - Maximum string length has to be known or (slightly) slower character-wise output. -// -// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting -// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting -// -#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING - #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 -#endif -// -// If using standard library formatting, -// select maximum output string buffer size or character-wise output. -// -// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output -// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length -// -#ifndef PRINTF_BUFFER_SIZE - #define PRINTF_BUFFER_SIZE 128 -#endif - -#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); - -/********************************************************************* -* -* Global functions, printf -* -********************************************************************** -*/ -/********************************************************************* -* -* printf() -* -* Function description -* print a formatted string using RTT and SEGGER RTT formatting. -*/ -int printf(const char *fmt,...) { - int n; - va_list args; - - va_start (args, fmt); - n = SEGGER_RTT_vprintf(0, fmt, &args); - va_end(args); - return n; -} - -#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output - -/********************************************************************* -* -* Static functions -* -********************************************************************** -*/ -static int _putchar(int x, __printf_tag_ptr ctx) { - (void)ctx; - SEGGER_RTT_Write(0, (char *)&x, 1); - return x; -} - -/********************************************************************* -* -* Global functions, printf -* -********************************************************************** -*/ -/********************************************************************* -* -* printf() -* -* Function description -* print a formatted string character-wise, using RTT and standard -* library formatting. -*/ -int printf(const char *fmt, ...) { - int n; - va_list args; - __printf_t iod; - - va_start(args, fmt); - iod.string = 0; - iod.maxchars = INT_MAX; - iod.output_fn = _putchar; - SEGGER_RTT_LOCK(); - n = __vfprintf(&iod, fmt, args); - SEGGER_RTT_UNLOCK(); - va_end(args); - return n; -} - -#else // Use standard library formatting with static buffer - -/********************************************************************* -* -* Global functions, printf -* -********************************************************************** -*/ -/********************************************************************* -* -* printf() -* -* Function description -* print a formatted string using RTT and standard library formatting. -*/ -int printf(const char *fmt,...) { - int n; - char aBuffer[PRINTF_BUFFER_SIZE]; - va_list args; - - va_start (args, fmt); - n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args); - if (n > (int)sizeof(aBuffer)) { - SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer)); - } else if (n > 0) { - SEGGER_RTT_Write(0, aBuffer, n); - } - va_end(args); - return n; -} -#endif - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ -/********************************************************************* -* -* puts() -* -* Function description -* print a string using RTT. -*/ -int puts(const char *s) { - return SEGGER_RTT_WriteString(0, s); -} - -/********************************************************************* -* -* __putchar() -* -* Function description -* Write one character via RTT. -*/ -int __putchar(int x, __printf_tag_ptr ctx) { - (void)ctx; - SEGGER_RTT_Write(0, (char *)&x, 1); - return x; -} - -/********************************************************************* -* -* __getchar() -* -* Function description -* Wait for and get a character via RTT. -*/ -int __getchar() { - return SEGGER_RTT_WaitKey(); -} - -#endif -/****** End Of File *************************************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt deleted file mode 100644 index f7330e924..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt +++ /dev/null @@ -1,138 +0,0 @@ -FatFs Module Source Files R0.09b (C)ChaN, 2013 - - -FILES - - ffconf.h Configuration file for FatFs module. - ff.h Common include file for FatFs and application module. - ff.c FatFs module. - diskio.h Common include file for FatFs and disk I/O module. - diskio.c An example of glue function to attach existing disk I/O module to FatFs. - integer.h Integer type definitions for FatFs. - option Optional external functions. - - Low level disk I/O module is not included in this archive because the FatFs - module is only a generic file system layer and not depend on any specific - storage device. You have to provide a low level disk I/O module that written - to control your storage device. - - - -AGREEMENTS - - FatFs module is an open source software to implement FAT file system to - small embedded systems. This is a free software and is opened for education, - research and commercial developments under license policy of following trems. - - Copyright (C) 2012, ChaN, all right reserved. - - * The FatFs module is a free software and there is NO WARRANTY. - * No restriction on use. You can use, modify and redistribute it for - personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. - * Redistributions of source code must retain the above copyright notice. - - - -REVISION HISTORY - - Feb 26, 2006 R0.00 Prototype - - Apr 29, 2006 R0.01 First release. - - Jun 01, 2006 R0.02 Added FAT12. - Removed unbuffered mode. - Fixed a problem on small (<32M) patition. - - Jun 10, 2006 R0.02a Added a configuration option _FS_MINIMUM. - - Sep 22, 2006 R0.03 Added f_rename. - Changed option _FS_MINIMUM to _FS_MINIMIZE. - - Dec 11, 2006 R0.03a Improved cluster scan algolithm to write files fast. - Fixed f_mkdir creates incorrect directory on FAT32. - - Feb 04, 2007 R0.04 Supported multiple drive system. (FatFs) - Changed some APIs for multiple drive system. - Added f_mkfs. (FatFs) - Added _USE_FAT32 option. (Tiny-FatFs) - - Apr 01, 2007 R0.04a Supported multiple partitions on a plysical drive. (FatFs) - Fixed an endian sensitive code in f_mkfs. (FatFs) - Added a capability of extending the file size to f_lseek. - Added minimization level 3. - Fixed a problem that can collapse a sector when recreate an - existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs) - - May 05, 2007 R0.04b Added _USE_NTFLAG option. - Added FSInfo support. - Fixed some problems corresponds to FAT32. (Tiny-FatFs) - Fixed DBCS name can result FR_INVALID_NAME. - Fixed short seek (0 < ofs <= csize) collapses the file object. - - Aug 25, 2007 R0.05 Changed arguments of f_read, f_write. - Changed arguments of f_mkfs. (FatFs) - Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs) - Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs) - - Feb 03, 2008 R0.05a Added f_truncate(). - Added f_utime(). - Fixed off by one error at FAT sub-type determination. - Fixed btr in f_read() can be mistruncated. - Fixed cached sector is not flushed when create and close without write. - - Apr 01, 2008 R0.06 Added f_forward(). (Tiny-FatFs) - Added string functions: fputc(), fputs(), fprintf() and fgets(). - Improved performance of f_lseek() on move to the same or following cluster. - - Apr 01, 2009, R0.07 Merged Tiny-FatFs as a buffer configuration option. - Added long file name support. - Added multiple code page support. - Added re-entrancy for multitask operation. - Added auto cluster size selection to f_mkfs(). - Added rewind option to f_readdir(). - Changed result code of critical errors. - Renamed string functions to avoid name collision. - - Apr 14, 2009, R0.07a Separated out OS dependent code on reentrant cfg. - Added multiple sector size support. - - Jun 21, 2009, R0.07c Fixed f_unlink() may return FR_OK on error. - Fixed wrong cache control in f_lseek(). - Added relative path feature. - Added f_chdir(). - Added f_chdrive(). - Added proper case conversion for extended characters. - - Nov 03, 2009 R0.07e Separated out configuration options from ff.h to ffconf.h. - Added a configuration option, _LFN_UNICODE. - Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. - Fixed name matching error on the 13 char boundary. - Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. - - May 15, 2010, R0.08 Added a memory configuration option. (_USE_LFN) - Added file lock feature. (_FS_SHARE) - Added fast seek feature. (_USE_FASTSEEK) - Changed some types on the API, XCHAR->TCHAR. - Changed fname member in the FILINFO structure on Unicode cfg. - String functions support UTF-8 encoding files on Unicode cfg. - - Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) - Added sector erase feature. (_USE_ERASE) - Moved file lock semaphore table from fs object to the bss. - Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. - Fixed f_mkfs() creates wrong FAT32 volume. - - Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). - f_lseek() reports required table size on creating CLMP. - Extended format syntax of f_printf function. - Ignores duplicated directory separators in given path names. - - Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. - Added f_fdisk(). (_MULTI_PARTITION = 2) - - Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16. - Changed f_open() and f_opendir() reject null object pointer to avoid crash. - Changed option name _FS_SHARE to _FS_LOCK. - - Jan 23,'13 R0.09b Added f_getlabel() and f_setlabel(). (_USE_LABEL == 1) - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c deleted file mode 100644 index 07d6f0983..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c +++ /dev/null @@ -1,543 +0,0 @@ -/*------------------------------------------------------------------------*/ -/* Unicode - Local code bidirectional converter (C)ChaN, 2012 */ -/* (SBCS code pages) */ -/*------------------------------------------------------------------------*/ -/* 437 U.S. (OEM) -/ 720 Arabic (OEM) -/ 1256 Arabic (Windows) -/ 737 Greek (OEM) -/ 1253 Greek (Windows) -/ 1250 Central Europe (Windows) -/ 775 Baltic (OEM) -/ 1257 Baltic (Windows) -/ 850 Multilingual Latin 1 (OEM) -/ 852 Latin 2 (OEM) -/ 1252 Latin 1 (Windows) -/ 855 Cyrillic (OEM) -/ 1251 Cyrillic (Windows) -/ 866 Russian (OEM) -/ 857 Turkish (OEM) -/ 1254 Turkish (Windows) -/ 858 Multilingual Latin 1 + Euro (OEM) -/ 862 Hebrew (OEM) -/ 1255 Hebrew (Windows) -/ 874 Thai (OEM, Windows) -/ 1258 Vietnam (OEM, Windows) -*/ - -#include "ff.h" - -#if CFG_TUH_MSC - -#if _CODE_PAGE == 437 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, - 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 720 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */ - 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, - 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, - 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, - 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, - 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 737 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */ - 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, - 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, - 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, - 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, - 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, - 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, - 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, - 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 775 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */ - 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, - 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, - 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, - 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, - 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, - 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, - 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, - 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, - 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, - 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, - 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 850 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, - 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, - 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, - 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, - 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, - 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 852 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, - 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, - 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, - 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, - 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, - 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, - 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, - 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, - 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, - 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 855 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */ - 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, - 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, - 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, - 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, - 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, - 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, - 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, - 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, - 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, - 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, - 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, - 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 857 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, - 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, - 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, - 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, - 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, - 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, - 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 858 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, - 0x00A9, 0x2563, 0x2551, 0x2557, 0x2550, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE, - 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 0x00CC, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, - 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, - 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, - 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 862 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */ - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, - 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 866 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */ - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 874 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, - 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, - 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, - 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, - 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, - 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, - 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, - 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, - 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 -}; - -#elif _CODE_PAGE == 1250 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, - 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, - 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, - 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, - 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, - 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, - 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, - 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, - 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, - 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, - 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 -}; - -#elif _CODE_PAGE == 1251 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */ - 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, - 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, - 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, - 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, - 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, - 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, - 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F -}; - -#elif _CODE_PAGE == 1252 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF -}; - -#elif _CODE_PAGE == 1253 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, - 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, - 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF, - 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 -}; - -#elif _CODE_PAGE == 1254 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF -}; - -#elif _CODE_PAGE == 1255 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, - 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, - 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, - 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 -}; - -#elif _CODE_PAGE == 1256 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, - 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, - 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, - 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, - 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, - 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643, - 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, - 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, - 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2 -} - -#elif _CODE_PAGE == 1257 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, - 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, - 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, - 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, - 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, - 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, - 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, - 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, - 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, - 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, - 0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9 -}; - -#elif _CODE_PAGE == 1258 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, - 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, - 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF -}; - -#endif - - -#if !_TBLDEF || !_USE_LFN -#error This file is not needed in current configuration. Remove from the project. -#endif - - -WCHAR ff_convert ( /* Converted character, Returns zero on error */ - WCHAR chr, /* Character code to be converted */ - UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ -) -{ - WCHAR c; - - - if (chr < 0x80) { /* ASCII */ - c = chr; - - } else { - if (dir) { /* OEMCP to Unicode */ - c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80]; - - } else { /* Unicode to OEMCP */ - for (c = 0; c < 0x80; c++) { - if (chr == Tbl[c]) break; - } - c = (c + 0x80) & 0xFF; - } - } - - return c; -} - - -WCHAR ff_wtoupper ( /* Upper converted character */ - WCHAR chr /* Input character */ -) -{ - static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; - static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; - int i; - - - for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; - - return tbl_lower[i] ? tbl_upper[i] : chr; -} - -#endif // CFG_TUH_MSC diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c deleted file mode 100644 index a6132f27b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb.h" - -#if CFG_TUH_MSC -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "ffconf.h" -#include "diskio.h" -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -// TODO change it to portable init -static DSTATUS disk_state[CFG_TUH_DEVICE_MAX]; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ -static DRESULT wait_for_io_complete(uint8_t usb_addr) -{ - // TODO with RTOS, this should use semaphore instead of blocking - while ( !tuh_msc_ready(usb_addr) ) - { - // TODO should have timeout here - #if CFG_TUSB_OS != OPT_OS_NONE - osal_task_delay(10); - #endif - } - - return RES_OK; -} - -void diskio_init(void) -{ - memset(disk_state, STA_NOINIT, CFG_TUH_DEVICE_MAX); -} - -//pdrv Specifies the physical drive number. -DSTATUS disk_initialize ( BYTE pdrv ) -{ - disk_state[pdrv] &= (~STA_NOINIT); // clear NOINIT bit - return disk_state[pdrv]; -} - -void disk_deinitialize ( BYTE pdrv ) -{ - disk_state[pdrv] |= STA_NOINIT; // set NOINIT bit -} - -DSTATUS disk_status (BYTE pdrv) -{ - return disk_state[pdrv]; -} - -//pdrv -// Specifies the physical drive number --> == dev_addr-1 -//buff -// Pointer to the byte array to store the read data. The size of buffer must be in sector size * sector count. -//sector -// Specifies the start sector number in logical block address (LBA). -//count -// Specifies number of sectors to read. The value can be 1 to 128. Generally, a multiple sector transfer request -// must not be split into single sector transactions to the device, or you may not get good read performance. -DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, BYTE count) -{ - uint8_t usb_addr = pdrv+1; - - if ( TUSB_ERROR_NONE != tuh_msc_read10(usb_addr, 0, buff, sector, count) ) return RES_ERROR; - - return wait_for_io_complete(usb_addr); -} - - -DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, BYTE count) -{ - uint8_t usb_addr = pdrv+1; - - if ( TUSB_ERROR_NONE != tuh_msc_write10(usb_addr, 0, buff, sector, count) ) return RES_ERROR; - - return wait_for_io_complete(usb_addr); -} - -/* [IN] Drive number */ -/* [IN] Control command code */ -/* [I/O] Parameter and data buffer */ -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) -{ - (void) buff; (void) pdrv; // compiler warnings - - if (cmd != CTRL_SYNC) return RES_ERROR; - return RES_OK; -} - -static inline uint8_t month2number(char* p_ch) -{ - char const * const month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - - for(uint8_t i=0; i<12; i++) - { - if ( strncmp(p_ch, month_str[i], 3) == 0 ) return i+1; - } - - return 1; -} - -static inline uint8_t c2i(char ch) -{ - return ch - '0'; -} - -DWORD get_fattime (void) -{ - union { - struct { - DWORD second : 5; - DWORD minute : 6; - DWORD hour : 5; - DWORD day_in_month : 5; - DWORD month : 4; - DWORD year : 7; - }; - - DWORD value; - } timestamp; - - //------------- Date is compiled date-------------// - char compile_date[] = __DATE__; // eg. "Sep 26 2013" - char* p_ch; - - p_ch = strtok (compile_date, " "); - timestamp.month = month2number(p_ch); - - p_ch = strtok (NULL, " "); - timestamp.day_in_month = 10*c2i(p_ch[0])+ c2i(p_ch[1]); - - p_ch = strtok (NULL, " "); - timestamp.year = 1000*c2i(p_ch[0]) + 100*c2i(p_ch[1]) + 10*c2i(p_ch[2]) + c2i(p_ch[3]) - 1980; - - //------------- Time each time this function call --> sec ++ -------------// - static uint8_t sec = 0; - static uint8_t min = 0; - static uint8_t hour = 0; - - if (++sec >= 60) - { - sec = 0; - if (++min >= 60) - { - min = 0; - if (++hour >= 24) - { - hour = 0; // assume demo wont call this function more than 24*60*60 times - } - } - } - - timestamp.hour = hour; - timestamp.minute = min; - timestamp.second = sec; - - return timestamp.value; -} - -#endif // CFG_TUH_MSC diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h deleted file mode 100644 index f1f4bd327..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h +++ /dev/null @@ -1,95 +0,0 @@ -/*----------------------------------------------------------------------- -/ Low level disk interface modlue include file (C)ChaN, 2013 -/-----------------------------------------------------------------------*/ - -#ifndef _DISKIO_DEFINED -#define _DISKIO_DEFINED - -#ifdef __cplusplus -extern "C" { -#endif - -#define _USE_WRITE 1 /* 1: Enable disk_write function */ -#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ - -#include "integer.h" -#include - -/* Status of Disk Functions */ -typedef BYTE DSTATUS; - -/* Results of Disk Functions */ -typedef enum { - RES_OK = 0, /* 0: Successful */ - RES_ERROR, /* 1: R/W Error */ - RES_WRPRT, /* 2: Write Protected */ - RES_NOTRDY, /* 3: Not Ready */ - RES_PARERR /* 4: Invalid Parameter */ -} DRESULT; - - -/* Disk Status Bits (DSTATUS) */ -#define STA_NOINIT 0x01 /* Drive not initialized */ -#define STA_NODISK 0x02 /* No medium in the drive */ -#define STA_PROTECT 0x04 /* Write protected */ - - -/* Command code for disk_ioctrl fucntion */ - -/* Generic command (used by FatFs) */ -#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ -#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ -#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ -#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ -#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ - -/* Generic command (not used by FatFs) */ -#define CTRL_POWER 5 /* Get/Set power status */ -#define CTRL_LOCK 6 /* Lock/Unlock media removal */ -#define CTRL_EJECT 7 /* Eject media */ -#define CTRL_FORMAT 8 /* Create physical format on the media */ - -/* MMC/SDC specific ioctl command */ -#define MMC_GET_TYPE 10 /* Get card type */ -#define MMC_GET_CSD 11 /* Get CSD */ -#define MMC_GET_CID 12 /* Get CID */ -#define MMC_GET_OCR 13 /* Get OCR */ -#define MMC_GET_SDSTAT 14 /* Get SD status */ - -/* ATA/CF specific ioctl command */ -#define ATA_GET_REV 20 /* Get F/W revision */ -#define ATA_GET_MODEL 21 /* Get model name */ -#define ATA_GET_SN 22 /* Get serial number */ - - -/* MMC card type flags (MMC_GET_TYPE) */ -#define CT_MMC 0x01 /* MMC ver 3 */ -#define CT_SD1 0x02 /* SD ver 1 */ -#define CT_SD2 0x04 /* SD ver 2 */ -#define CT_SDC (CT_SD1|CT_SD2) /* SD */ -#define CT_BLOCK 0x08 /* Block addressing */ - -/*---------------------------------------*/ -/* Prototypes for disk control functions */ - -void diskio_init(void); -void disk_deinitialize ( BYTE pdrv ); -DSTATUS disk_initialize (BYTE pdrv); -DSTATUS disk_status (BYTE pdrv); -DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, BYTE count); -DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, BYTE count); -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); - -static inline bool disk_is_ready(BYTE pdrv); -static inline bool disk_is_ready(BYTE pdrv) -{ - return (pdrv < CFG_TUH_DEVICE_MAX) && - ( (disk_status(pdrv) & (STA_NOINIT | STA_NODISK)) == 0 ); -} - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c deleted file mode 100644 index 79414af07..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c +++ /dev/null @@ -1,4330 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ FatFs - FAT file system module R0.09b (C)ChaN, 2013 -/-----------------------------------------------------------------------------/ -/ FatFs module is a generic FAT file system module for small embedded systems. -/ This is a free software that opened for education, research and commercial -/ developments under license policy of following terms. -/ -/ Copyright (C) 2013, ChaN, all right reserved. -/ -/ * The FatFs module is a free software and there is NO WARRANTY. -/ * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. -/ * Redistributions of source code must retain the above copyright notice. -/ -/-----------------------------------------------------------------------------/ -/ Feb 26,'06 R0.00 Prototype. -/ -/ Apr 29,'06 R0.01 First stable version. -/ -/ Jun 01,'06 R0.02 Added FAT12 support. -/ Removed unbuffered mode. -/ Fixed a problem on small (<32M) partition. -/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM). -/ -/ Sep 22,'06 R0.03 Added f_rename(). -/ Changed option _FS_MINIMUM to _FS_MINIMIZE. -/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast. -/ Fixed f_mkdir() creates incorrect directory on FAT32. -/ -/ Feb 04,'07 R0.04 Supported multiple drive system. -/ Changed some interfaces for multiple drive system. -/ Changed f_mountdrv() to f_mount(). -/ Added f_mkfs(). -/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive. -/ Added a capability of extending file size to f_lseek(). -/ Added minimization level 3. -/ Fixed an endian sensitive code in f_mkfs(). -/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG. -/ Added FSInfo support. -/ Fixed DBCS name can result FR_INVALID_NAME. -/ Fixed short seek (<= csize) collapses the file object. -/ -/ Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs(). -/ Fixed f_mkfs() on FAT32 creates incorrect FSInfo. -/ Fixed f_mkdir() on FAT32 creates incorrect directory. -/ Feb 03,'08 R0.05a Added f_truncate() and f_utime(). -/ Fixed off by one error at FAT sub-type determination. -/ Fixed btr in f_read() can be mistruncated. -/ Fixed cached sector is not flushed when create and close without write. -/ -/ Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets(). -/ Improved performance of f_lseek() on moving to the same or following cluster. -/ -/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY) -/ Added long file name feature. -/ Added multiple code page feature. -/ Added re-entrancy for multitask operation. -/ Added auto cluster size selection to f_mkfs(). -/ Added rewind option to f_readdir(). -/ Changed result code of critical errors. -/ Renamed string functions to avoid name collision. -/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg. -/ Added multiple sector size feature. -/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error. -/ Fixed wrong cache control in f_lseek(). -/ Added relative path feature. -/ Added f_chdir() and f_chdrive(). -/ Added proper case conversion to extended char. -/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h. -/ Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. -/ Fixed name matching error on the 13 char boundary. -/ Added a configuration option, _LFN_UNICODE. -/ Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. -/ -/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3) -/ Added file lock feature. (_FS_SHARE) -/ Added fast seek feature. (_USE_FASTSEEK) -/ Changed some types on the API, XCHAR->TCHAR. -/ Changed fname member in the FILINFO structure on Unicode cfg. -/ String functions support UTF-8 encoding files on Unicode cfg. -/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) -/ Added sector erase feature. (_USE_ERASE) -/ Moved file lock semaphore table from fs object to the bss. -/ Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. -/ Fixed f_mkfs() creates wrong FAT32 volume. -/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). -/ f_lseek() reports required table size on creating CLMP. -/ Extended format syntax of f_printf function. -/ Ignores duplicated directory separators in given path name. -/ -/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. -/ Added f_fdisk(). (_MULTI_PARTITION = 2) -/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume. -/ Changed f_open() and f_opendir reject null object pointer to avoid crash. -/ Changed option name _FS_SHARE to _FS_LOCK. -/ Jan 24,'13 R0.09b Added f_setlabel() and f_getlabel(). (_USE_LABEL = 1) -/---------------------------------------------------------------------------*/ - -#include "ff.h" /* FatFs configurations and declarations */ -#include "diskio.h" /* Declarations of low level disk I/O functions */ - -#if CFG_TUH_MSC -/*-------------------------------------------------------------------------- - - Module Private Definitions - ----------------------------------------------------------------------------*/ - -#if _FATFS != 82786 /* Revision ID */ -#error Wrong include file (ff.h). -#endif - - -/* Definitions on sector size */ -#if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096 -#error Wrong sector size. -#endif -#if _MAX_SS != 512 -#define SS(fs) ((fs)->ssize) /* Variable sector size */ -#else -#define SS(fs) 512U /* Fixed sector size */ -#endif - - -/* Reentrancy related */ -#if _FS_REENTRANT -#if _USE_LFN == 1 -#error Static LFN work area must not be used in re-entrant configuration. -#endif -#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } -#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } -#else -#define ENTER_FF(fs) -#define LEAVE_FF(fs, res) return res -#endif - -#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } - - -/* File access control feature */ -#if _FS_LOCK -#if _FS_READONLY -#error _FS_LOCK must be 0 on read-only cfg. -#endif -typedef struct { - FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ - DWORD clu; /* File ID 2, directory */ - WORD idx; /* File ID 3, directory index */ - WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ -} FILESEM; -#endif - - - -/* DBCS code ranges and SBCS extend char conversion table */ - -#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ -#define _DF1S 0x81 /* DBC 1st byte range 1 start */ -#define _DF1E 0x9F /* DBC 1st byte range 1 end */ -#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ -#define _DF2E 0xFC /* DBC 1st byte range 2 end */ -#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ -#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ -#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ -#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ - -#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0x80 -#define _DS2E 0xFE - -#elif _CODE_PAGE == 949 /* Korean */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x41 -#define _DS1E 0x5A -#define _DS2S 0x61 -#define _DS2E 0x7A -#define _DS3S 0x81 -#define _DS3E 0xFE - -#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0xA1 -#define _DS2E 0xFE - -#elif _CODE_PAGE == 437 /* U.S. (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 720 /* Arabic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 737 /* Greek (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ - 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 775 /* Baltic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} - -#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ - 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ - 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 857 /* Turkish (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 866 /* Russian (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} - -#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} - -#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} - -#elif _CODE_PAGE == 1253 /* Greek (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ - 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} - -#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} - -#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} - -#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} - -#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ -#if _USE_LFN -#error Cannot use LFN feature without valid code page. -#endif -#define _DF1S 0 - -#else -#error Unknown code page - -#endif - - -/* Character code support macros */ -#define IsUpper(c) (((c)>='A')&&((c)<='Z')) -#define IsLower(c) (((c)>='a')&&((c)<='z')) -#define IsDigit(c) (((c)>='0')&&((c)<='9')) - -#if _DF1S /* Code page is DBCS */ - -#ifdef _DF2S /* Two 1st byte areas */ -#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) -#else /* One 1st byte area */ -#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) -#endif - -#ifdef _DS3S /* Three 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) -#else /* Two 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) -#endif - -#else /* Code page is SBCS */ - -#define IsDBCS1(c) 0 -#define IsDBCS2(c) 0 - -#endif /* _DF1S */ - - -/* Name status flags */ -#define NS 11 /* Index of name status byte in fn[] */ -#define NS_LOSS 0x01 /* Out of 8.3 format */ -#define NS_LFN 0x02 /* Force to create LFN entry */ -#define NS_LAST 0x04 /* Last segment */ -#define NS_BODY 0x08 /* Lower case flag (body) */ -#define NS_EXT 0x10 /* Lower case flag (ext) */ -#define NS_DOT 0x20 /* Dot entry */ - - -/* FAT sub-type boundaries */ -/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ -#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ -#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ - - -/* FatFs refers the members in the FAT structures as byte array instead of -/ structure member because the structure is not binary compatible between -/ different platforms */ - -#define BS_jmpBoot 0 /* Jump instruction (3) */ -#define BS_OEMName 3 /* OEM name (8) */ -#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ -#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ -#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ -#define BPB_NumFATs 16 /* Number of FAT copies (1) */ -#define BPB_RootEntCnt 17 /* Number of root dir entries for FAT12/16 (2) */ -#define BPB_TotSec16 19 /* Volume size [sector] (2) */ -#define BPB_Media 21 /* Media descriptor (1) */ -#define BPB_FATSz16 22 /* FAT size [sector] (2) */ -#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ -#define BPB_NumHeads 26 /* Number of heads (2) */ -#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ -#define BPB_TotSec32 32 /* Volume size [sector] (4) */ -#define BS_DrvNum 36 /* Physical drive number (2) */ -#define BS_BootSig 38 /* Extended boot signature (1) */ -#define BS_VolID 39 /* Volume serial number (4) */ -#define BS_VolLab 43 /* Volume label (8) */ -#define BS_FilSysType 54 /* File system type (1) */ -#define BPB_FATSz32 36 /* FAT size [sector] (4) */ -#define BPB_ExtFlags 40 /* Extended flags (2) */ -#define BPB_FSVer 42 /* File system version (2) */ -#define BPB_RootClus 44 /* Root dir first cluster (4) */ -#define BPB_FSInfo 48 /* Offset of FSInfo sector (2) */ -#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */ -#define BS_DrvNum32 64 /* Physical drive number (2) */ -#define BS_BootSig32 66 /* Extended boot signature (1) */ -#define BS_VolID32 67 /* Volume serial number (4) */ -#define BS_VolLab32 71 /* Volume label (8) */ -#define BS_FilSysType32 82 /* File system type (1) */ -#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ -#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ -#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ -#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ -#define MBR_Table 446 /* MBR: Partition table offset (2) */ -#define SZ_PTE 16 /* MBR: Size of a partition table entry */ -#define BS_55AA 510 /* Boot sector signature (2) */ - -#define DIR_Name 0 /* Short file name (11) */ -#define DIR_Attr 11 /* Attribute (1) */ -#define DIR_NTres 12 /* NT flag (1) */ -#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */ -#define DIR_CrtTime 14 /* Created time (2) */ -#define DIR_CrtDate 16 /* Created date (2) */ -#define DIR_LstAccDate 18 /* Last accessed date (2) */ -#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ -#define DIR_WrtTime 22 /* Modified time (2) */ -#define DIR_WrtDate 24 /* Modified date (2) */ -#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */ -#define DIR_FileSize 28 /* File size (4) */ -#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */ -#define LDIR_Attr 11 /* LFN attribute (1) */ -#define LDIR_Type 12 /* LFN type (1) */ -#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ -#define LDIR_FstClusLO 26 /* Filled by zero (0) */ -#define SZ_DIR 32 /* Size of a directory entry */ -#define LLE 0x40 /* Last long entry flag in LDIR_Ord */ -#define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */ -#define NDDE 0x05 /* Replacement of the character collides with DDE */ - - -/*------------------------------------------------------------*/ -/* Module private work area */ -/*------------------------------------------------------------*/ -/* Note that uninitialized variables with static duration are -/ zeroed/nulled at start-up. If not, the compiler or start-up -/ routine is out of ANSI-C standard. -*/ - -#if _VOLUMES -static -FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ -#else -#error Number of volumes must not be 0. -#endif - -static -WORD Fsid; /* File system mount ID */ - -#if _FS_RPATH -static -BYTE CurrVol; /* Current drive */ -#endif - -#if _FS_LOCK -static -FILESEM Files[_FS_LOCK]; /* File lock semaphores */ -#endif - -#if _USE_LFN == 0 /* No LFN feature */ -#define DEF_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) (dobj).fn = sfn -#define FREE_BUF() - -#elif _USE_LFN == 1 /* LFN feature with static working buffer */ -static WCHAR LfnBuf[_MAX_LFN+1]; -#define DEF_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } -#define FREE_BUF() - -#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */ -#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } -#define FREE_BUF() - -#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */ -#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn -#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ - if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ - (dobj).lfn = lfn; (dobj).fn = sfn; } -#define FREE_BUF() ff_memfree(lfn) - -#else -#error Wrong LFN configuration. -#endif - - -#ifdef _EXCVT -static -const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for extended chars */ -#endif - - - - - - -/*-------------------------------------------------------------------------- - - Module Private Functions - ----------------------------------------------------------------------------*/ - - -/*-----------------------------------------------------------------------*/ -/* String functions */ -/*-----------------------------------------------------------------------*/ - -/* Copy memory to memory */ -static -void mem_cpy (void* dst, const void* src, UINT cnt) { - BYTE *d = (BYTE*)dst; - const BYTE *s = (const BYTE*)src; - -#if _WORD_ACCESS == 1 - while (cnt >= sizeof (int)) { - *(int*)d = *(int*)s; - d += sizeof (int); s += sizeof (int); - cnt -= sizeof (int); - } -#endif - while (cnt--) - *d++ = *s++; -} - -/* Fill memory */ -static -void mem_set (void* dst, int val, UINT cnt) { - BYTE *d = (BYTE*)dst; - - while (cnt--) - *d++ = (BYTE)val; -} - -/* Compare memory to memory */ -static -int mem_cmp (const void* dst, const void* src, UINT cnt) { - const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; - int r = 0; - - while (cnt-- && (r = *d++ - *s++) == 0) ; - return r; -} - -/* Check if chr is contained in the string */ -static -int chk_chr (const char* str, int chr) { - while (*str && *str != chr) str++; - return *str; -} - - - -/*-----------------------------------------------------------------------*/ -/* Request/Release grant to access the volume */ -/*-----------------------------------------------------------------------*/ -#if _FS_REENTRANT - -static -int lock_fs ( - FATFS *fs /* File system object */ -) -{ - return ff_req_grant(fs->sobj); -} - - -static -void unlock_fs ( - FATFS *fs, /* File system object */ - FRESULT res /* Result code to be returned */ -) -{ - if (fs && - res != FR_NOT_ENABLED && - res != FR_INVALID_DRIVE && - res != FR_INVALID_OBJECT && - res != FR_TIMEOUT) { - ff_rel_grant(fs->sobj); - } -} -#endif - - - -/*-----------------------------------------------------------------------*/ -/* File lock control functions */ -/*-----------------------------------------------------------------------*/ -#if _FS_LOCK - -static -FRESULT chk_lock ( /* Check if the file can be accessed */ - DIR* dj, /* Directory object pointing the file to be checked */ - int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ -) -{ - UINT i, be; - - /* Search file semaphore table */ - for (i = be = 0; i < _FS_LOCK; i++) { - if (Files[i].fs) { /* Existing entry */ - if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ - Files[i].clu == dj->sclust && - Files[i].idx == dj->index) break; - } else { /* Blank entry */ - be++; - } - } - if (i == _FS_LOCK) /* The file is not opened */ - return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ - - /* The file has been opened. Reject any open against writing file and all write mode open */ - return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; -} - - -static -int enq_lock (void) /* Check if an entry is available for a new file */ -{ - UINT i; - - for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; - return (i == _FS_LOCK) ? 0 : 1; -} - - -static -UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ - DIR* dj, /* Directory object pointing the file to register or increment */ - int acc /* Desired access mode (0:Read, !0:Write) */ -) -{ - UINT i; - - - for (i = 0; i < _FS_LOCK; i++) { /* Find the file */ - if (Files[i].fs == dj->fs && - Files[i].clu == dj->sclust && - Files[i].idx == dj->index) break; - } - - if (i == _FS_LOCK) { /* Not opened. Register it as new. */ - for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; - if (i == _FS_LOCK) return 0; /* No space to register (int err) */ - Files[i].fs = dj->fs; - Files[i].clu = dj->sclust; - Files[i].idx = dj->index; - Files[i].ctr = 0; - } - - if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ - - Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ - - return i + 1; -} - - -static -FRESULT dec_lock ( /* Decrement file open counter */ - UINT i /* Semaphore index */ -) -{ - WORD n; - FRESULT res; - - - if (--i < _FS_LOCK) { - n = Files[i].ctr; - if (n == 0x100) n = 0; - if (n) n--; - Files[i].ctr = n; - if (!n) Files[i].fs = 0; - res = FR_OK; - } else { - res = FR_INT_ERR; - } - return res; -} - - -static -void clear_lock ( /* Clear lock entries of the volume */ - FATFS *fs -) -{ - UINT i; - - for (i = 0; i < _FS_LOCK; i++) { - if (Files[i].fs == fs) Files[i].fs = 0; - } -} -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Move/Flush disk access window */ -/*-----------------------------------------------------------------------*/ - - -#if !_FS_READONLY -static -FRESULT sync_window ( - FATFS *fs /* File system object */ -) -{ - DWORD wsect; - UINT nf; - - - if (fs->wflag) { /* Write back the sector if it is dirty */ - wsect = fs->winsect; /* Current sector number */ - if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) - return FR_DISK_ERR; - fs->wflag = 0; - if (wsect >= fs->fatbase && wsect < (fs->fatbase + fs->fsize)) { /* In FAT area? */ - for (nf = fs->n_fats; nf >= 2; nf--) { /* Reflect the change to all FAT copies */ - wsect += fs->fsize; - disk_write(fs->drv, fs->win, wsect, 1); - } - } - } - return FR_OK; -} -#endif - - -static -FRESULT move_window ( - FATFS *fs, /* File system object */ - DWORD sector /* Sector number to make appearance in the fs->win[] */ -) -{ - if (sector != fs->winsect) { /* Changed current window */ -#if !_FS_READONLY - if (sync_window(fs) != FR_OK) - return FR_DISK_ERR; -#endif - if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) - return FR_DISK_ERR; - fs->winsect = sector; - } - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Synchronize file system and strage device */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */ - FATFS *fs /* File system object */ -) -{ - FRESULT res; - - - res = sync_window(fs); - if (res == FR_OK) { - /* Update FSInfo sector if needed */ - if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { - fs->winsect = 0; - /* Create FSInfo structure */ - mem_set(fs->win, 0, 512); - ST_WORD(fs->win+BS_55AA, 0xAA55); - ST_DWORD(fs->win+FSI_LeadSig, 0x41615252); - ST_DWORD(fs->win+FSI_StrucSig, 0x61417272); - ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust); - ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust); - /* Write it into the FSInfo sector */ - disk_write(fs->drv, fs->win, fs->fsi_sector, 1); - fs->fsi_flag = 0; - } - /* Make sure that no pending write process in the physical drive */ - if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) - res = FR_DISK_ERR; - } - - return res; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Get sector# from cluster# */ -/*-----------------------------------------------------------------------*/ - - -DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to be converted */ -) -{ - clst -= 2; - if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ - return clst * fs->csize + fs->database; -} - - - - -/*-----------------------------------------------------------------------*/ -/* FAT access - Read value of a FAT entry */ -/*-----------------------------------------------------------------------*/ - - -DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to get the link information */ -) -{ - UINT wc, bc; - BYTE *p; - - - if (clst < 2 || clst >= fs->n_fatent) /* Check range */ - return 1; - - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; - if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; - wc = fs->win[bc % SS(fs)]; bc++; - if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; - wc |= fs->win[bc % SS(fs)] << 8; - return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); - - case FS_FAT16 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; - p = &fs->win[clst * 2 % SS(fs)]; - return LD_WORD(p); - - case FS_FAT32 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; - p = &fs->win[clst * 4 % SS(fs)]; - return LD_DWORD(p) & 0x0FFFFFFF; - } - - return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* FAT access - Change value of a FAT entry */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY - -FRESULT put_fat ( - FATFS *fs, /* File system object */ - DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ - DWORD val /* New value to mark the cluster */ -) -{ - UINT bc; - BYTE *p; - FRESULT res; - - - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; - - } else { - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc % SS(fs)]; - *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; - bc++; - fs->wflag = 1; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc % SS(fs)]; - *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); - break; - - case FS_FAT16 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); - if (res != FR_OK) break; - p = &fs->win[clst * 2 % SS(fs)]; - ST_WORD(p, (WORD)val); - break; - - case FS_FAT32 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); - if (res != FR_OK) break; - p = &fs->win[clst * 4 % SS(fs)]; - val |= LD_DWORD(p) & 0xF0000000; - ST_DWORD(p, val); - break; - - default : - res = FR_INT_ERR; - } - fs->wflag = 1; - } - - return res; -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Remove a cluster chain */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT remove_chain ( - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to remove a chain from */ -) -{ - FRESULT res; - DWORD nxt; -#if _USE_ERASE - DWORD scl = clst, ecl = clst, rt[2]; -#endif - - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; - - } else { - res = FR_OK; - while (clst < fs->n_fatent) { /* Not a last link? */ - nxt = get_fat(fs, clst); /* Get cluster status */ - if (nxt == 0) break; /* Empty cluster? */ - if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ - if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ - res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ - if (res != FR_OK) break; - if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */ - fs->free_clust++; - fs->fsi_flag = 1; - } -#if _USE_ERASE - if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ - ecl = nxt; - } else { /* End of contiguous clusters */ - rt[0] = clust2sect(fs, scl); /* Start sector */ - rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ - disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */ - scl = ecl = nxt; - } -#endif - clst = nxt; /* Next cluster */ - } - } - - return res; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Stretch or Create a cluster chain */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ -) -{ - DWORD cs, ncl, scl; - FRESULT res; - - - if (clst == 0) { /* Create a new chain */ - scl = fs->last_clust; /* Get suggested start point */ - if (!scl || scl >= fs->n_fatent) scl = 1; - } - else { /* Stretch the current chain */ - cs = get_fat(fs, clst); /* Check the cluster status */ - if (cs < 2) return 1; /* It is an invalid cluster */ - if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ - scl = clst; - } - - ncl = scl; /* Start cluster */ - for (;;) { - ncl++; /* Next cluster */ - if (ncl >= fs->n_fatent) { /* Wrap around */ - ncl = 2; - if (ncl > scl) return 0; /* No free cluster */ - } - cs = get_fat(fs, ncl); /* Get the cluster status */ - if (cs == 0) break; /* Found a free cluster */ - if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ - return cs; - if (ncl == scl) return 0; /* No free cluster */ - } - - res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ - if (res == FR_OK && clst != 0) { - res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ - } - if (res == FR_OK) { - fs->last_clust = ncl; /* Update FSINFO */ - if (fs->free_clust != 0xFFFFFFFF) { - fs->free_clust--; - fs->fsi_flag = 1; - } - } else { - ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; - } - - return ncl; /* Return new cluster number or error code */ -} -#endif /* !_FS_READONLY */ - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Convert offset into cluster with link map table */ -/*-----------------------------------------------------------------------*/ - -#if _USE_FASTSEEK -static -DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ - FIL* fp, /* Pointer to the file object */ - DWORD ofs /* File offset to be converted to cluster# */ -) -{ - DWORD cl, ncl, *tbl; - - - tbl = fp->cltbl + 1; /* Top of CLMT */ - cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */ - for (;;) { - ncl = *tbl++; /* Number of cluters in the fragment */ - if (!ncl) return 0; /* End of table? (error) */ - if (cl < ncl) break; /* In this fragment? */ - cl -= ncl; tbl++; /* Next fragment */ - } - return cl + *tbl; /* Return the cluster number */ -} -#endif /* _USE_FASTSEEK */ - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Set directory index */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT dir_sdi ( - DIR *dj, /* Pointer to directory object */ - WORD idx /* Index of directory table */ -) -{ - DWORD clst; - WORD ic; - - - dj->index = idx; - clst = dj->sclust; - if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */ - return FR_INT_ERR; - if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ - clst = dj->fs->dirbase; - - if (clst == 0) { /* Static table (root-dir in FAT12/16) */ - dj->clust = clst; - if (idx >= dj->fs->n_rootdir) /* Index is out of range */ - return FR_INT_ERR; - dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ - } - else { /* Dynamic table (sub-dirs or root-dir in FAT32) */ - ic = SS(dj->fs) / SZ_DIR * dj->fs->csize; /* Entries per cluster */ - while (idx >= ic) { /* Follow cluster chain */ - clst = get_fat(dj->fs, clst); /* Get next cluster */ - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ - if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */ - return FR_INT_ERR; - idx -= ic; - } - dj->clust = clst; - dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ - } - - dj->dir = dj->fs->win + (idx % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */ - - return FR_OK; /* Seek succeeded */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Move directory table index next */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ - DIR *dj, /* Pointer to the directory object */ - int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ -) -{ - DWORD clst; - WORD i; - - - stretch = stretch; /* To suppress warning on read-only cfg. */ - i = dj->index + 1; - if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ - return FR_NO_FILE; - - if (!(i % (SS(dj->fs) / SZ_DIR))) { /* Sector changed? */ - dj->sect++; /* Next sector */ - - if (dj->clust == 0) { /* Static table */ - if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */ - return FR_NO_FILE; - } - else { /* Dynamic table */ - if (((i / (SS(dj->fs) / SZ_DIR)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ - clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ - if (clst <= 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */ -#if !_FS_READONLY - BYTE c; - if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */ - clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */ - if (clst == 0) return FR_DENIED; /* No free cluster */ - if (clst == 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - /* Clean-up stretched table */ - if (sync_window(dj->fs)) return FR_DISK_ERR; /* Flush active window */ - mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */ - dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */ - for (c = 0; c < dj->fs->csize; c++) { /* Fill the new cluster with 0 */ - dj->fs->wflag = 1; - if (sync_window(dj->fs)) return FR_DISK_ERR; - dj->fs->winsect++; - } - dj->fs->winsect -= c; /* Rewind window address */ -#else - return FR_NO_FILE; /* Report EOT */ -#endif - } - dj->clust = clst; /* Initialize data for new cluster */ - dj->sect = clust2sect(dj->fs, clst); - } - } - } - - dj->index = i; - dj->dir = dj->fs->win + (i % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Reserve directory entry */ -/*-----------------------------------------------------------------------*/ - -#if !_FS_READONLY -static -FRESULT dir_alloc ( - DIR* dj, /* Pointer to the directory object */ - UINT nent /* Number of contiguous entries to allocate (1-21) */ -) -{ - FRESULT res; - UINT n; - - - res = dir_sdi(dj, 0); - if (res == FR_OK) { - n = 0; - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - if (dj->dir[0] == DDE || dj->dir[0] == 0) { /* Is it a blank entry? */ - if (++n == nent) break; /* A block of contiguous entry is found */ - } else { - n = 0; /* Not a blank entry. Restart to search */ - } - res = dir_next(dj, 1); /* Next entry with table stretch enabled */ - } while (res == FR_OK); - } - return res; -} -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Load/Store start cluster number */ -/*-----------------------------------------------------------------------*/ - -static -DWORD ld_clust ( - FATFS *fs, /* Pointer to the fs object */ - BYTE *dir /* Pointer to the directory entry */ -) -{ - DWORD cl; - - cl = LD_WORD(dir+DIR_FstClusLO); - if (fs->fs_type == FS_FAT32) - cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16; - - return cl; -} - - -#if !_FS_READONLY -static -void st_clust ( - BYTE *dir, /* Pointer to the directory entry */ - DWORD cl /* Value to be set */ -) -{ - ST_WORD(dir+DIR_FstClusLO, cl); - ST_WORD(dir+DIR_FstClusHI, cl >> 16); -} -#endif - - - -/*-----------------------------------------------------------------------*/ -/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ -/*-----------------------------------------------------------------------*/ -#if _USE_LFN -static -const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN chars in the directory entry */ - - -static -int cmp_lfn ( /* 1:Matched, 0:Not matched */ - WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ - BYTE *dir /* Pointer to the directory entry containing a part of LFN */ -) -{ - UINT i, s; - WCHAR wc, uc; - - - i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */ - s = 0; wc = 1; - do { - uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last char has not been processed */ - wc = ff_wtoupper(uc); /* Convert it to upper case */ - if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ - return 0; /* Not matched */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Repeat until all chars in the entry are checked */ - - if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */ - return 0; - - return 1; /* The part of LFN matched */ -} - - - -static -int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ - WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ - BYTE *dir /* Pointer to the directory entry */ -) -{ - UINT i, s; - WCHAR wc, uc; - - - i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ - - s = 0; wc = 1; - do { - uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last char has not been processed */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i++] = wc = uc; /* Store it */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Read all character in the entry */ - - if (dir[LDIR_Ord] & LLE) { /* Put terminator if it is the last LFN part */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i] = 0; - } - - return 1; -} - - -#if !_FS_READONLY -static -void fit_lfn ( - const WCHAR *lfnbuf, /* Pointer to the LFN buffer */ - BYTE *dir, /* Pointer to the directory entry */ - BYTE ord, /* LFN order (1-20) */ - BYTE sum /* SFN sum */ -) -{ - UINT i, s; - WCHAR wc; - - - dir[LDIR_Chksum] = sum; /* Set check sum */ - dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ - dir[LDIR_Type] = 0; - ST_WORD(dir+LDIR_FstClusLO, 0); - - i = (ord - 1) * 13; /* Get offset in the LFN buffer */ - s = wc = 0; - do { - if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */ - ST_WORD(dir+LfnOfs[s], wc); /* Put it */ - if (!wc) wc = 0xFFFF; /* Padding chars following last char */ - } while (++s < 13); - if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE; /* Bottom LFN part is the start of LFN sequence */ - dir[LDIR_Ord] = ord; /* Set the LFN order */ -} - -#endif -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Create numbered name */ -/*-----------------------------------------------------------------------*/ -#if _USE_LFN -void gen_numname ( - BYTE *dst, /* Pointer to generated SFN */ - const BYTE *src, /* Pointer to source SFN to be modified */ - const WCHAR *lfn, /* Pointer to LFN */ - WORD seq /* Sequence number */ -) -{ - BYTE ns[8], c; - UINT i, j; - - - mem_cpy(dst, src, 11); - - if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ - do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); - } - - /* itoa (hexdecimal) */ - i = 7; - do { - c = (seq % 16) + '0'; - if (c > '9') c += 7; - ns[i--] = c; - seq /= 16; - } while (seq); - ns[i] = '~'; - - /* Append the number */ - for (j = 0; j < i && dst[j] != ' '; j++) { - if (IsDBCS1(dst[j])) { - if (j == i - 1) break; - j++; - } - } - do { - dst[j++] = (i < 8) ? ns[i++] : ' '; - } while (j < 8); -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Calculate sum of an SFN */ -/*-----------------------------------------------------------------------*/ -#if _USE_LFN -static -BYTE sum_sfn ( - const BYTE *dir /* Ptr to directory entry */ -) -{ - BYTE sum = 0; - UINT n = 11; - - do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); - return sum; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Find an object in the directory */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT dir_find ( - DIR *dj /* Pointer to the directory object linked to the file name */ -) -{ - FRESULT res; - BYTE c, *dir; -#if _USE_LFN - BYTE a, ord, sum; -#endif - - res = dir_sdi(dj, 0); /* Rewind directory object */ - if (res != FR_OK) return res; - -#if _USE_LFN - ord = sum = 0xFF; -#endif - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - dir = dj->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ -#if _USE_LFN /* LFN configuration */ - a = dir[DIR_Attr] & AM_MASK; - if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (dj->lfn) { - if (c & LLE) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= ~LLE; ord = c; /* LFN start order */ - dj->lfn_idx = dj->index; - } - /* Check validity of the LFN entry and compare it with given name */ - ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; - } - } else { /* An SFN entry is found */ - if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */ - ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */ - if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break; /* SFN matched? */ - } - } -#else /* Non LFN configuration */ - if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ - break; -#endif - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK); - - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read an object from the directory */ -/*-----------------------------------------------------------------------*/ -#if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 -static -FRESULT dir_read ( - DIR *dj, /* Pointer to the directory object */ - int vol /* Filtered by 0:file/dir or 1:volume label */ -) -{ - FRESULT res; - BYTE a, c, *dir; -#if _USE_LFN - BYTE ord = 0xFF, sum = 0xFF; -#endif - - res = FR_NO_FILE; - while (dj->sect) { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - dir = dj->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ - a = dir[DIR_Attr] & AM_MASK; -#if _USE_LFN /* LFN configuration */ - if (c == DDE || (!_FS_RPATH && c == '.') || (a == AM_VOL) != vol) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (c & LLE) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= ~LLE; ord = c; - dj->lfn_idx = dj->index; - } - /* Check LFN validity and capture it */ - ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; - } else { /* An SFN entry is found */ - if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */ - dj->lfn_idx = 0xFFFF; /* It has no LFN. */ - break; - } - } -#else /* Non LFN configuration */ - if (c != DDE && (_FS_RPATH || c != '.') && a != AM_LFN && (a == AM_VOL) == vol) /* Is it a valid entry? */ - break; -#endif - res = dir_next(dj, 0); /* Next entry */ - if (res != FR_OK) break; - } - - if (res != FR_OK) dj->sect = 0; - - return res; -} -#endif /* _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 */ - - - -/*-----------------------------------------------------------------------*/ -/* Register an object to the directory */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ - DIR *dj /* Target directory with object name to be created */ -) -{ - FRESULT res; -#if _USE_LFN /* LFN configuration */ - WORD n, ne; - BYTE sn[12], *fn, sum; - WCHAR *lfn; - - - fn = dj->fn; lfn = dj->lfn; - mem_cpy(sn, fn, 12); - - if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */ - return FR_INVALID_NAME; - - if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ - fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ - for (n = 1; n < 100; n++) { - gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ - res = dir_find(dj); /* Check if the name collides with existing SFN */ - if (res != FR_OK) break; - } - if (n == 100) return FR_DENIED; /* Abort if too many collisions */ - if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ - fn[NS] = sn[NS]; dj->lfn = lfn; - } - - if (sn[NS] & NS_LFN) { /* When LFN is to be created, allocate entries for an SFN + LFNs. */ - for (n = 0; lfn[n]; n++) ; - ne = (n + 25) / 13; - } else { /* Otherwise allocate an entry for an SFN */ - ne = 1; - } - res = dir_alloc(dj, ne); /* Allocate entries */ - - if (res == FR_OK && --ne) { /* Set LFN entry if needed */ - res = dir_sdi(dj, (WORD)(dj->index - ne)); - if (res == FR_OK) { - sum = sum_sfn(dj->fn); /* Sum value of the SFN tied to the LFN */ - do { /* Store LFN entries in bottom first */ - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum); - dj->fs->wflag = 1; - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK && --ne); - } - } -#else /* Non LFN configuration */ - res = dir_alloc(dj, 1); /* Allocate an entry for SFN */ -#endif - - if (res == FR_OK) { /* Set SFN entry */ - res = move_window(dj->fs, dj->sect); - if (res == FR_OK) { - mem_set(dj->dir, 0, SZ_DIR); /* Clean the entry */ - mem_cpy(dj->dir, dj->fn, 11); /* Put SFN */ -#if _USE_LFN - dj->dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */ -#endif - dj->fs->wflag = 1; - } - } - - return res; -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Remove an object from the directory */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY && !_FS_MINIMIZE -static -FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ - DIR *dj /* Directory object pointing the entry to be removed */ -) -{ - FRESULT res; -#if _USE_LFN /* LFN configuration */ - WORD i; - - i = dj->index; /* SFN index */ - res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */ - if (res == FR_OK) { - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - *dj->dir = DDE; /* Mark the entry "deleted" */ - dj->fs->wflag = 1; - if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR; - } - -#else /* Non LFN configuration */ - res = dir_sdi(dj, dj->index); - if (res == FR_OK) { - res = move_window(dj->fs, dj->sect); - if (res == FR_OK) { - *dj->dir = DDE; /* Mark the entry "deleted" */ - dj->fs->wflag = 1; - } - } -#endif - - return res; -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Pick a segment and create the object name in directory form */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT create_name ( - DIR *dj, /* Pointer to the directory object */ - const TCHAR **path /* Pointer to pointer to the segment in the path string */ -) -{ -#if _USE_LFN /* LFN configuration */ - BYTE b, cf; - WCHAR w, *lfn; - UINT i, ni, si, di; - const TCHAR *p; - - /* Create LFN in Unicode */ - for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ - lfn = dj->lfn; - si = di = 0; - for (;;) { - w = p[si++]; /* Get a character */ - if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ - if (di >= _MAX_LFN) /* Reject too long name */ - return FR_INVALID_NAME; -#if !_LFN_UNICODE - w &= 0xFF; - if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - b = (BYTE)p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(b)) - return FR_INVALID_NAME; /* Reject invalid sequence */ - w = (w << 8) + b; /* Create a DBC */ - } - w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ - if (!w) return FR_INVALID_NAME; /* Reject invalid code */ -#endif - if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */ - return FR_INVALID_NAME; - lfn[di++] = w; /* Store the Unicode char */ - } - *path = &p[si]; /* Return pointer to the next segment */ - cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ -#if _FS_RPATH - if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */ - (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) { - lfn[di] = 0; - for (i = 0; i < 11; i++) - dj->fn[i] = (i < di) ? '.' : ' '; - dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ - return FR_OK; - } -#endif - while (di) { /* Strip trailing spaces and dots */ - w = lfn[di-1]; - if (w != ' ' && w != '.') break; - di--; - } - if (!di) return FR_INVALID_NAME; /* Reject nul string */ - - lfn[di] = 0; /* LFN is created */ - - /* Create SFN in directory form */ - mem_set(dj->fn, ' ', 11); - for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ - if (si) cf |= NS_LOSS | NS_LFN; - while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ - - b = i = 0; ni = 8; - for (;;) { - w = lfn[si++]; /* Get an LFN char */ - if (!w) break; /* Break on end of the LFN */ - if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ - cf |= NS_LOSS | NS_LFN; continue; - } - - if (i >= ni || si == di) { /* Extension or end of SFN */ - if (ni == 11) { /* Long extension */ - cf |= NS_LOSS | NS_LFN; break; - } - if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ - if (si > di) break; /* No extension */ - si = di; i = 8; ni = 11; /* Enter extension section */ - b <<= 2; continue; - } - - if (w >= 0x80) { /* Non ASCII char */ -#ifdef _EXCVT - w = ff_convert(w, 0); /* Unicode -> OEM code */ - if (w) w = ExCvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ -#else - w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ -#endif - cf |= NS_LFN; /* Force create LFN entry */ - } - - if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */ - if (i >= ni - 1) { - cf |= NS_LOSS | NS_LFN; i = ni; continue; - } - dj->fn[i++] = (BYTE)(w >> 8); - } else { /* Single byte char */ - if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ - w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ - } else { - if (IsUpper(w)) { /* ASCII large capital */ - b |= 2; - } else { - if (IsLower(w)) { /* ASCII small capital */ - b |= 1; w -= 0x20; - } - } - } - } - dj->fn[i++] = (BYTE)w; - } - - if (dj->fn[0] == DDE) dj->fn[0] = NDDE; /* If the first char collides with deleted mark, replace it with 0x05 */ - - if (ni == 8) b <<= 2; - if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ - cf |= NS_LFN; - if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */ - if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ - if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ - } - - dj->fn[NS] = cf; /* SFN is created */ - - return FR_OK; - - -#else /* Non-LFN configuration */ - BYTE b, c, d, *sfn; - UINT ni, si, i; - const char *p; - - /* Create file name in directory form */ - for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ - sfn = dj->fn; - mem_set(sfn, ' ', 11); - si = i = b = 0; ni = 8; -#if _FS_RPATH - if (p[si] == '.') { /* Is this a dot entry? */ - for (;;) { - c = (BYTE)p[si++]; - if (c != '.' || si >= 3) break; - sfn[i++] = c; - } - if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; - *path = &p[si]; /* Return pointer to the next segment */ - sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ - return FR_OK; - } -#endif - for (;;) { - c = (BYTE)p[si++]; - if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ - if (c == '.' || i >= ni) { - if (ni != 8 || c != '.') return FR_INVALID_NAME; - i = 8; ni = 11; - b <<= 2; continue; - } - if (c >= 0x80) { /* Extended char? */ - b |= 3; /* Eliminate NT flag */ -#ifdef _EXCVT - c = ExCvt[c - 0x80]; /* To upper extended chars (SBCS cfg) */ -#else -#if !_DF1S - return FR_INVALID_NAME; /* Reject extended chars (ASCII cfg) */ -#endif -#endif - } - if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - d = (BYTE)p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ - return FR_INVALID_NAME; - sfn[i++] = c; - sfn[i++] = d; - } else { /* Single byte code */ - if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ - return FR_INVALID_NAME; - if (IsUpper(c)) { /* ASCII large capital? */ - b |= 2; - } else { - if (IsLower(c)) { /* ASCII small capital? */ - b |= 1; c -= 0x20; - } - } - sfn[i++] = c; - } - } - *path = &p[si]; /* Return pointer to the next segment */ - c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ - - if (!i) return FR_INVALID_NAME; /* Reject nul string */ - if (sfn[0] == DDE) sfn[0] = NDDE; /* When first char collides with DDE, replace it with 0x05 */ - - if (ni == 8) b <<= 2; - if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ - if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ - - sfn[NS] = c; /* Store NT flag, File name is created */ - - return FR_OK; -#endif -} - - - - -/*-----------------------------------------------------------------------*/ -/* Get file information from directory entry */ -/*-----------------------------------------------------------------------*/ -#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 -static -void get_fileinfo ( /* No return code */ - DIR *dj, /* Pointer to the directory object */ - FILINFO *fno /* Pointer to the file information to be filled */ -) -{ - UINT i; - BYTE nt, *dir; - TCHAR *p, c; - - - p = fno->fname; - if (dj->sect) { - dir = dj->dir; - nt = dir[DIR_NTres]; /* NT flag */ - for (i = 0; i < 8; i++) { /* Copy name body */ - c = dir[i]; - if (c == ' ') break; - if (c == NDDE) c = (TCHAR)DDE; - if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20; -#if _LFN_UNICODE - if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1])) - c = (c << 8) | dir[++i]; - c = ff_convert(c, 1); - if (!c) c = '?'; -#endif - *p++ = c; - } - if (dir[8] != ' ') { /* Copy name extension */ - *p++ = '.'; - for (i = 8; i < 11; i++) { - c = dir[i]; - if (c == ' ') break; - if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20; -#if _LFN_UNICODE - if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1])) - c = (c << 8) | dir[++i]; - c = ff_convert(c, 1); - if (!c) c = '?'; -#endif - *p++ = c; - } - } - fno->fattrib = dir[DIR_Attr]; /* Attribute */ - fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ - fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ - fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ - } - *p = 0; /* Terminate SFN str by a \0 */ - -#if _USE_LFN - if (fno->lfname && fno->lfsize) { - TCHAR *tp = fno->lfname; - WCHAR w, *lfn; - - i = 0; - if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */ - lfn = dj->lfn; - while ((w = *lfn++) != 0) { /* Get an LFN char */ -#if !_LFN_UNICODE - w = ff_convert(w, 0); /* Unicode -> OEM conversion */ - if (!w) { i = 0; break; } /* Could not convert, no LFN */ - if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ - tp[i++] = (TCHAR)(w >> 8); -#endif - if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */ - tp[i++] = (TCHAR)w; - } - } - tp[i] = 0; /* Terminate the LFN str by a \0 */ - } -#endif -} -#endif /* _FS_MINIMIZE <= 1 || _FS_RPATH >= 2*/ - - - - -/*-----------------------------------------------------------------------*/ -/* Follow a file path */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ - DIR *dj, /* Directory object to return last directory and found object */ - const TCHAR *path /* Full-path string to find a file or directory */ -) -{ - FRESULT res; - BYTE *dir, ns; - - -#if _FS_RPATH - if (*path == '/' || *path == '\\') { /* There is a heading separator */ - path++; dj->sclust = 0; /* Strip it and start from the root dir */ - } else { /* No heading separator */ - dj->sclust = dj->fs->cdir; /* Start from the current dir */ - } -#else - if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ - path++; - dj->sclust = 0; /* Start from the root dir */ -#endif - - if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ - res = dir_sdi(dj, 0); - dj->dir = 0; - } else { /* Follow path */ - for (;;) { - res = create_name(dj, &path); /* Get a segment */ - if (res != FR_OK) break; - res = dir_find(dj); /* Find it */ - ns = *(dj->fn+NS); - if (res != FR_OK) { /* Failed to find the object */ - if (res != FR_NO_FILE) break; /* Abort if any hard error occurred */ - /* Object not found */ - if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ - dj->sclust = 0; dj->dir = 0; /* It is the root dir */ - res = FR_OK; - if (!(ns & NS_LAST)) continue; - } else { /* Could not find the object */ - if (!(ns & NS_LAST)) res = FR_NO_PATH; - } - break; - } - if (ns & NS_LAST) break; /* Last segment match. Function completed. */ - dir = dj->dir; /* There is next segment. Follow the sub directory */ - if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ - res = FR_NO_PATH; break; - } - dj->sclust = ld_clust(dj->fs, dir); - } - } - - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Load a sector and check if it is an FAT Volume Boot Record */ -/*-----------------------------------------------------------------------*/ - -static -BYTE check_fs ( /* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */ - FATFS *fs, /* File system object */ - DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ -) -{ - if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */ - return 3; - if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ - return 2; - - if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ - return 0; - if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) - return 0; - - return 1; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Check if the file system object is valid or not */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ - const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ - FATFS **rfs, /* Pointer to pointer to the found file system object */ - BYTE wmode /* !=0: Check write protection for write access */ -) -{ - BYTE fmt, b, pi, *tbl; - UINT vol; - DSTATUS stat; - DWORD bsect, fasize, tsect, sysect, nclst, szbfat; - WORD nrsv; - const TCHAR *p = *path; - FATFS *fs; - - - /* Get logical drive number from the path name */ - vol = p[0] - '0'; /* Is there a drive number? */ - if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ - p += 2; *path = p; /* Return pointer to the path name */ - } else { /* No drive number, use default drive */ -#if _FS_RPATH - vol = CurrVol; /* Use current drive */ -#else - vol = 0; /* Use drive 0 */ -#endif - } - - /* Check if the file system object is valid or not */ - *rfs = 0; - if (vol >= _VOLUMES) /* Is the drive number valid? */ - return FR_INVALID_DRIVE; - fs = FatFs[vol]; /* Get corresponding file system object */ - if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ - - ENTER_FF(fs); /* Lock volume */ - - *rfs = fs; /* Return pointer to the corresponding file system object */ - if (fs->fs_type) { /* If the volume has been mounted */ - stat = disk_status(fs->drv); - if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ - if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */ - return FR_WRITE_PROTECTED; - return FR_OK; /* The file system object is valid */ - } - } - - /* The file system object is not valid. */ - /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ - - fs->fs_type = 0; /* Clear the file system object */ - fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drv); /* Initialize the physical drive */ - if (stat & STA_NOINIT) /* Check if the initialization succeeded */ - return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ - if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */ - return FR_WRITE_PROTECTED; -#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ - if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) - return FR_DISK_ERR; -#endif - /* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */ - fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */ - if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */ - if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */ - /* Check the partition listed in the partition table */ - pi = LD2PT(vol); - if (pi) pi--; - tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */ - if (tbl[4]) { /* Is the partition existing? */ - bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ - fmt = check_fs(fs, bsect); /* Check the partition */ - } - } - if (fmt == 3) return FR_DISK_ERR; - if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ - - /* An FAT volume is found. Following code initializes the file system object */ - - if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ - return FR_NO_FILESYSTEM; - - fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ - if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32); - fs->fsize = fasize; - - fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ - if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ - fasize *= b; /* Number of sectors for FAT area */ - - fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ - if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ - - fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ - if (fs->n_rootdir % (SS(fs) / SZ_DIR)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ - - tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ - if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); - - nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */ - if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ - - /* Determine the FAT sub type */ - sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR); /* RSV+FAT+DIR */ - if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ - if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - fmt = FS_FAT12; - if (nclst >= MIN_FAT16) fmt = FS_FAT16; - if (nclst >= MIN_FAT32) fmt = FS_FAT32; - - /* Boundaries and Limits */ - fs->n_fatent = nclst + 2; /* Number of FAT entries */ - fs->volbase = bsect; /* Volume start sector */ - fs->fatbase = bsect + nrsv; /* FAT start sector */ - fs->database = bsect + sysect; /* Data start sector */ - if (fmt == FS_FAT32) { - if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ - fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ - szbfat = fs->n_fatent * 4; /* (Required FAT size) */ - } else { - if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ - fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ - szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ - fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); - } - if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than required) */ - return FR_NO_FILESYSTEM; - -#if !_FS_READONLY - /* Initialize cluster allocation information */ - fs->free_clust = 0xFFFFFFFF; - fs->last_clust = 0; - - /* Get fsinfo if available */ - if (fmt == FS_FAT32) { - fs->fsi_flag = 0; - fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo); - if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK && - LD_WORD(fs->win+BS_55AA) == 0xAA55 && - LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 && - LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) { - fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free); - fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count); - } - } -#endif - fs->fs_type = fmt; /* FAT sub-type */ - fs->id = ++Fsid; /* File system mount ID */ - fs->winsect = 0; /* Invalidate sector cache */ - fs->wflag = 0; -#if _FS_RPATH - fs->cdir = 0; /* Current directory (root dir) */ -#endif -#if _FS_LOCK /* Clear file lock semaphores */ - clear_lock(fs); -#endif - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Check if the file/dir object is valid or not */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ - void* obj /* Pointer to the object FIL/DIR to check validity */ -) -{ - FIL *fil = (FIL*)obj; /* Assuming offset of fs and id in the FIL/DIR is identical */ - - - if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id) - return FR_INVALID_OBJECT; - - ENTER_FF(fil->fs); /* Lock file system */ - - if (disk_status(fil->fs->drv) & STA_NOINIT) - return FR_NOT_READY; - - return FR_OK; -} - - - - -/*-------------------------------------------------------------------------- - - Public Functions - ---------------------------------------------------------------------------*/ - - - -/*-----------------------------------------------------------------------*/ -/* Mount/Unmount a Logical Drive */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_mount ( - BYTE vol, /* Logical drive number to be mounted/unmounted */ - FATFS *fs /* Pointer to new file system object (NULL for unmount)*/ -) -{ - FATFS *rfs; - - - if (vol >= _VOLUMES) /* Check if the drive number is valid */ - return FR_INVALID_DRIVE; - rfs = FatFs[vol]; /* Get current fs object */ - - if (rfs) { -#if _FS_LOCK - clear_lock(rfs); -#endif -#if _FS_REENTRANT /* Discard sync object of the current volume */ - if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; -#endif - rfs->fs_type = 0; /* Clear old fs object */ - } - - if (fs) { - fs->fs_type = 0; /* Clear new fs object */ -#if _FS_REENTRANT /* Create sync object for the new volume */ - if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; -#endif - } - FatFs[vol] = fs; /* Register new fs object */ - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Open or Create a File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_open ( - FIL *fp, /* Pointer to the blank file object */ - const TCHAR *path, /* Pointer to the file name */ - BYTE mode /* Access mode and file open mode flags */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; - - - if (!fp) return FR_INVALID_OBJECT; - fp->fs = 0; /* Clear file object */ - -#if !_FS_READONLY - mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; - res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ)); -#else - mode &= FA_READ; - res = chk_mounted(&path, &dj.fs, 0); -#endif - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - dir = dj.dir; -#if !_FS_READONLY /* R/W configuration */ - if (res == FR_OK) { - if (!dir) /* Current dir itself */ - res = FR_INVALID_NAME; -#if _FS_LOCK - else - res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); -#endif - } - /* Create or Open a file */ - if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { - DWORD dw, cl; - - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ -#if _FS_LOCK - res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; -#else - res = dir_register(&dj); -#endif - mode |= FA_CREATE_ALWAYS; /* File is created */ - dir = dj.dir; /* New entry */ - } - else { /* Any object is already existing */ - if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; - } else { - if (mode & FA_CREATE_NEW) /* Cannot create as new file */ - res = FR_EXIST; - } - } - if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ - dw = get_fattime(); /* Created time */ - ST_DWORD(dir+DIR_CrtTime, dw); - dir[DIR_Attr] = 0; /* Reset attribute */ - ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ - cl = ld_clust(dj.fs, dir); /* Get start cluster */ - st_clust(dir, 0); /* cluster = 0 */ - dj.fs->wflag = 1; - if (cl) { /* Remove the cluster chain if exist */ - dw = dj.fs->winsect; - res = remove_chain(dj.fs, cl); - if (res == FR_OK) { - dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ - res = move_window(dj.fs, dw); - } - } - } - } - else { /* Open an existing file */ - if (res == FR_OK) { /* Follow succeeded */ - if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ - res = FR_NO_FILE; - } else { - if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ - res = FR_DENIED; - } - } - } - if (res == FR_OK) { - if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ - mode |= FA__WRITTEN; - fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ - fp->dir_ptr = dir; -#if _FS_LOCK - fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); - if (!fp->lockid) res = FR_INT_ERR; -#endif - } - -#else /* R/O configuration */ - if (res == FR_OK) { /* Follow succeeded */ - dir = dj.dir; - if (!dir) { /* Current dir itself */ - res = FR_INVALID_NAME; - } else { - if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ - res = FR_NO_FILE; - } - } -#endif - FREE_BUF(); - - if (res == FR_OK) { - fp->flag = mode; /* File access mode */ - fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */ - fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ - fp->fptr = 0; /* File pointer */ - fp->dsect = 0; -#if _USE_FASTSEEK - fp->cltbl = 0; /* Normal seek mode */ -#endif - fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ - } - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_read ( - FIL *fp, /* Pointer to the file object */ - void *buff, /* Pointer to data buffer */ - UINT btr, /* Number of bytes to read */ - UINT *br /* Pointer to number of bytes read */ -) -{ - FRESULT res; - DWORD clst, sect, remain; - UINT rcnt, cc; - BYTE csect, *rbuff = (BYTE*)buff; - - - *br = 0; /* Clear read byte counter */ - - res = validate(fp); /* Check validity */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Aborted file? */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - remain = fp->fsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ - - for ( ; btr; /* Repeat until all data read */ - rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->sclust; /* Follow from the origin */ - } else { /* Middle or end of the file */ -#if _USE_FASTSEEK - if (fp->cltbl) - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - else -#endif - clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */ - } - if (clst < 2) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - } - sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Read maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; - if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ -#if _FS_TINY - if (fp->fs->wflag && fp->fs->winsect - sect < cc) - mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); -#else - if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) - mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); -#endif -#endif - rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } -#if !_FS_TINY - if (fp->dsect != sect) { /* Load data sector if not in cache */ -#if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */ - ABORT(fp->fs, FR_DISK_ERR); - } -#endif - fp->dsect = sect; - } - rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ - if (rcnt > btr) rcnt = btr; -#if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ -#else - mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ -#endif - } - - LEAVE_FF(fp->fs, FR_OK); -} - - - - -#if !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Write File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_write ( - FIL *fp, /* Pointer to the file object */ - const void *buff, /* Pointer to the data to be written */ - UINT btw, /* Number of bytes to write */ - UINT *bw /* Pointer to number of bytes written */ -) -{ - FRESULT res; - DWORD clst, sect; - UINT wcnt, cc; - const BYTE *wbuff = (const BYTE*)buff; - BYTE csect; - - - *bw = 0; /* Clear write byte counter */ - - res = validate(fp); /* Check validity */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Aborted file? */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; /* File size cannot reach 4GB */ - - for ( ; btw; /* Repeat until all data written */ - wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->sclust; /* Follow from the origin */ - if (clst == 0) /* When no cluster is allocated, */ - fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ - } else { /* Middle or end of the file */ -#if _USE_FASTSEEK - if (fp->cltbl) - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - else -#endif - clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */ - } - if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - } -#if _FS_TINY - if (fp->fs->winsect == fp->dsect && sync_window(fp->fs)) /* Write-back sector cache */ - ABORT(fp->fs, FR_DISK_ERR); -#else - if (fp->flag & FA__DIRTY) { /* Write-back sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Write maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; - if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#if _FS_TINY - if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ - mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->fs->wflag = 0; - } -#else - if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ - mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->flag &= ~FA__DIRTY; - } -#endif - wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } -#if _FS_TINY - if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */ - if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR); - fp->fs->winsect = sect; - } -#else - if (fp->dsect != sect) { /* Fill sector cache with file data */ - if (fp->fptr < fp->fsize && - disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - } -#endif - fp->dsect = sect; - } - wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ - if (wcnt > btw) wcnt = btw; -#if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->fs->wflag = 1; -#else - mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->flag |= FA__DIRTY; -#endif - } - - if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ - fp->flag |= FA__WRITTEN; /* Set file change flag */ - - LEAVE_FF(fp->fs, FR_OK); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Synchronize the File Object */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_sync ( - FIL *fp /* Pointer to the file object */ -) -{ - FRESULT res; - DWORD tm; - BYTE *dir; - - - res = validate(fp); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ -#if !_FS_TINY /* Write-back dirty buffer */ - if (fp->flag & FA__DIRTY) { - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - LEAVE_FF(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - /* Update the directory entry */ - res = move_window(fp->fs, fp->dir_sect); - if (res == FR_OK) { - dir = fp->dir_ptr; - dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ - ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ - st_clust(dir, fp->sclust); /* Update start cluster */ - tm = get_fattime(); /* Update updated time */ - ST_DWORD(dir+DIR_WrtTime, tm); - ST_WORD(dir+DIR_LstAccDate, 0); - fp->flag &= ~FA__WRITTEN; - fp->fs->wflag = 1; - res = sync_fs(fp->fs); - } - } - } - - LEAVE_FF(fp->fs, res); -} - -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Close File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_close ( - FIL *fp /* Pointer to the file object to be closed */ -) -{ - FRESULT res; - - -#if _FS_READONLY - res = validate(fp); - { -#if _FS_REENTRANT - FATFS *fs = fp->fs; -#endif - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - LEAVE_FF(fs, res); - } -#else - res = f_sync(fp); /* Flush cached data */ -#if _FS_LOCK - if (res == FR_OK) { /* Decrement open counter */ -#if _FS_REENTRANT - FATFS *fs = fp->fs;; - res = validate(fp); - if (res == FR_OK) { - res = dec_lock(fp->lockid); - unlock_fs(fs, FR_OK); - } -#else - res = dec_lock(fp->lockid); -#endif - } -#endif - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - return res; -#endif -} - - - - -/*-----------------------------------------------------------------------*/ -/* Current Drive/Directory Handlings */ -/*-----------------------------------------------------------------------*/ - -#if _FS_RPATH >= 1 - -FRESULT f_chdrive ( - BYTE drv /* Drive number */ -) -{ - if (drv >= _VOLUMES) return FR_INVALID_DRIVE; - - CurrVol = drv; - - return FR_OK; -} - -BYTE f_get_current_drive(void) -{ - return CurrVol; -} - -FRESULT f_chdir ( - const TCHAR *path /* Pointer to the directory path */ -) -{ - FRESULT res; - DIR dj; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the path */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (!dj.dir) { - dj.fs->cdir = dj.sclust; /* Start directory itself */ - } else { - if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ - dj.fs->cdir = ld_clust(dj.fs, dj.dir); - else - res = FR_NO_PATH; /* Reached but a file */ - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - } - - LEAVE_FF(dj.fs, res); -} - - -#if _FS_RPATH >= 2 -FRESULT f_getcwd ( - TCHAR *buff, /* Pointer to the directory path */ - UINT len /* Size of path */ -) -{ - FRESULT res; - DIR dj; - UINT i, n; - DWORD ccl; - TCHAR *tp; - FILINFO fno; - DEF_NAMEBUF; - - - *buff = 0; - res = chk_mounted((const TCHAR**)&buff, &dj.fs, 0); /* Get current volume */ - if (res == FR_OK) { - INIT_BUF(dj); - i = len; /* Bottom of buffer (dir stack base) */ - dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ - while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */ - res = dir_sdi(&dj, 1); /* Get parent dir */ - if (res != FR_OK) break; - res = dir_read(&dj, 0); - if (res != FR_OK) break; - dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent dir */ - res = dir_sdi(&dj, 0); - if (res != FR_OK) break; - do { /* Find the entry links to the child dir */ - res = dir_read(&dj, 0); - if (res != FR_OK) break; - if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */ - res = dir_next(&dj, 0); - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ - if (res != FR_OK) break; -#if _USE_LFN - fno.lfname = buff; - fno.lfsize = i; -#endif - get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */ - tp = fno.fname; - if (_USE_LFN && *buff) tp = buff; - for (n = 0; tp[n]; n++) ; - if (i < n + 3) { - res = FR_NOT_ENOUGH_CORE; break; - } - while (n) buff[--i] = tp[--n]; - buff[--i] = '/'; - } - tp = buff; - if (res == FR_OK) { - *tp++ = '0' + CurrVol; /* Put drive number */ - *tp++ = ':'; - if (i == len) { /* Root-dir */ - *tp++ = '/'; - } else { /* Sub-dir */ - do /* Add stacked path str */ - *tp++ = buff[i++]; - while (i < len); - } - } - *tp = 0; - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} -#endif /* _FS_RPATH >= 2 */ -#endif /* _FS_RPATH >= 1 */ - - - -#if _FS_MINIMIZE <= 2 -/*-----------------------------------------------------------------------*/ -/* Seek File R/W Pointer */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_lseek ( - FIL *fp, /* Pointer to the file object */ - DWORD ofs /* File pointer from top of file */ -) -{ - FRESULT res; - - - res = validate(fp); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - -#if _USE_FASTSEEK - if (fp->cltbl) { /* Fast seek */ - DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; - - if (ofs == CREATE_LINKMAP) { /* Create CLMT */ - tbl = fp->cltbl; - tlen = *tbl++; ulen = 2; /* Given table size and required table size */ - cl = fp->sclust; /* Top of the chain */ - if (cl) { - do { - /* Get a fragment */ - tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ - do { - pcl = cl; ncl++; - cl = get_fat(fp->fs, cl); - if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); - if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - } while (cl == pcl + 1); - if (ulen <= tlen) { /* Store the length and top of the fragment */ - *tbl++ = ncl; *tbl++ = tcl; - } - } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */ - } - *fp->cltbl = ulen; /* Number of items used */ - if (ulen <= tlen) - *tbl = 0; /* Terminate table */ - else - res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ - - } else { /* Fast seek */ - if (ofs > fp->fsize) /* Clip offset at the file size */ - ofs = fp->fsize; - fp->fptr = ofs; /* Set file pointer */ - if (ofs) { - fp->clust = clmt_clust(fp, ofs - 1); - dsc = clust2sect(fp->fs, fp->clust); - if (!dsc) ABORT(fp->fs, FR_INT_ERR); - dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1); - if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */ -#if !_FS_TINY -#if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */ - ABORT(fp->fs, FR_DISK_ERR); -#endif - fp->dsect = dsc; - } - } - } - } else -#endif - - /* Normal Seek */ - { - DWORD clst, bcs, nsect, ifptr; - - if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ -#if !_FS_READONLY - && !(fp->flag & FA_WRITE) -#endif - ) ofs = fp->fsize; - - ifptr = fp->fptr; - fp->fptr = nsect = 0; - if (ofs) { - bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ - if (ifptr > 0 && - (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ - fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ - ofs -= fp->fptr; - clst = fp->clust; - } else { /* When seek to back cluster, */ - clst = fp->sclust; /* start from the first cluster */ -#if !_FS_READONLY - if (clst == 0) { /* If no cluster chain, create a new chain */ - clst = create_chain(fp->fs, 0); - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->sclust = clst; - } -#endif - fp->clust = clst; - } - if (clst != 0) { - while (ofs > bcs) { /* Cluster following loop */ -#if !_FS_READONLY - if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ - clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ - if (clst == 0) { /* When disk gets full, clip file size */ - ofs = bcs; break; - } - } else -#endif - clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); - fp->clust = clst; - fp->fptr += bcs; - ofs -= bcs; - } - fp->fptr += ofs; - if (ofs % SS(fp->fs)) { - nsect = clust2sect(fp->fs, clst); /* Current sector */ - if (!nsect) ABORT(fp->fs, FR_INT_ERR); - nsect += ofs / SS(fp->fs); - } - } - } - if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */ -#if !_FS_TINY -#if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */ - ABORT(fp->fs, FR_DISK_ERR); -#endif - fp->dsect = nsect; - } -#if !_FS_READONLY - if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */ - fp->fsize = fp->fptr; - fp->flag |= FA__WRITTEN; - } -#endif - } - - LEAVE_FF(fp->fs, res); -} - - - -#if _FS_MINIMIZE <= 1 -/*-----------------------------------------------------------------------*/ -/* Create a Directory Object */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_opendir ( - DIR *dj, /* Pointer to directory object to create */ - const TCHAR *path /* Pointer to the directory path */ -) -{ - FRESULT res; - FATFS *fs; - DEF_NAMEBUF; - - - if (!dj) return FR_INVALID_OBJECT; - - res = chk_mounted(&path, &dj->fs, 0); - fs = dj->fs; - if (res == FR_OK) { - INIT_BUF(*dj); - res = follow_path(dj, path); /* Follow the path to the directory */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (dj->dir) { /* It is not the root dir */ - if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ - dj->sclust = ld_clust(fs, dj->dir); - } else { /* The object is not a directory */ - res = FR_NO_PATH; - } - } - if (res == FR_OK) { - dj->id = fs->id; - res = dir_sdi(dj, 0); /* Rewind dir */ - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - if (res != FR_OK) dj->fs = 0; /* Invalidate the dir object if function faild */ - } else { - dj->fs = 0; - } - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read Directory Entry in Sequence */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_readdir ( - DIR *dj, /* Pointer to the open directory object */ - FILINFO *fno /* Pointer to file information to return */ -) -{ - FRESULT res; - DEF_NAMEBUF; - - - res = validate(dj); /* Check validity of the object */ - if (res == FR_OK) { - if (!fno) { - res = dir_sdi(dj, 0); /* Rewind the directory object */ - } else { - INIT_BUF(*dj); - res = dir_read(dj, 0); /* Read an item */ - if (res == FR_NO_FILE) { /* Reached end of dir */ - dj->sect = 0; - res = FR_OK; - } - if (res == FR_OK) { /* A valid entry is found */ - get_fileinfo(dj, fno); /* Get the object information */ - res = dir_next(dj, 0); /* Increment index for next */ - if (res == FR_NO_FILE) { - dj->sect = 0; - res = FR_OK; - } - } - FREE_BUF(); - } - } - - LEAVE_FF(dj->fs, res); -} - - - -#if _FS_MINIMIZE == 0 -/*-----------------------------------------------------------------------*/ -/* Get File Status */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_stat ( - const TCHAR *path, /* Pointer to the file path */ - FILINFO *fno /* Pointer to file information to return */ -) -{ - FRESULT res; - DIR dj; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) { /* Follow completed */ - if (dj.dir) /* Found an object */ - get_fileinfo(&dj, fno); - else /* It is root dir */ - res = FR_INVALID_NAME; - } - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} - - - -#if !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Get Number of Free Clusters */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_getfree ( - const TCHAR *path, /* Path name of the logical drive number */ - DWORD *nclst, /* Pointer to a variable to return number of free clusters */ - FATFS **fatfs /* Pointer to return pointer to corresponding file system object */ -) -{ - FRESULT res; - FATFS *fs; - DWORD n, clst, sect, stat; - UINT i; - BYTE fat, *p; - - - /* Get drive number */ - res = chk_mounted(&path, fatfs, 0); - fs = *fatfs; - if (res == FR_OK) { - /* If free_clust is valid, return it without full cluster scan */ - if (fs->free_clust <= fs->n_fatent - 2) { - *nclst = fs->free_clust; - } else { - /* Get number of free clusters */ - fat = fs->fs_type; - n = 0; - if (fat == FS_FAT12) { - clst = 2; - do { - stat = get_fat(fs, clst); - if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } - if (stat == 1) { res = FR_INT_ERR; break; } - if (stat == 0) n++; - } while (++clst < fs->n_fatent); - } else { - clst = fs->n_fatent; - sect = fs->fatbase; - i = 0; p = 0; - do { - if (!i) { - res = move_window(fs, sect++); - if (res != FR_OK) break; - p = fs->win; - i = SS(fs); - } - if (fat == FS_FAT16) { - if (LD_WORD(p) == 0) n++; - p += 2; i -= 2; - } else { - if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; - p += 4; i -= 4; - } - } while (--clst); - } - fs->free_clust = n; - if (fat == FS_FAT32) fs->fsi_flag = 1; - *nclst = n; - } - } - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Truncate File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_truncate ( - FIL *fp /* Pointer to the file object */ -) -{ - FRESULT res; - DWORD ncl; - - - res = validate(fp); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->flag & FA__ERROR) { /* Check abort flag */ - res = FR_INT_ERR; - } else { - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - res = FR_DENIED; - } - } - if (res == FR_OK) { - if (fp->fsize > fp->fptr) { - fp->fsize = fp->fptr; /* Set file size to current R/W point */ - fp->flag |= FA__WRITTEN; - if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ - res = remove_chain(fp->fs, fp->sclust); - fp->sclust = 0; - } else { /* When truncate a part of the file, remove remaining clusters */ - ncl = get_fat(fp->fs, fp->clust); - res = FR_OK; - if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (ncl == 1) res = FR_INT_ERR; - if (res == FR_OK && ncl < fp->fs->n_fatent) { - res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF); - if (res == FR_OK) res = remove_chain(fp->fs, ncl); - } - } - } - if (res != FR_OK) fp->flag |= FA__ERROR; - } - - LEAVE_FF(fp->fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Delete a File or Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_unlink ( - const TCHAR *path /* Pointer to the file or directory path */ -) -{ - FRESULT res; - DIR dj, sdj; - BYTE *dir; - DWORD dclst; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; /* Cannot remove dot entry */ -#if _FS_LOCK - if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ -#endif - if (res == FR_OK) { /* The object is accessible */ - dir = dj.dir; - if (!dir) { - res = FR_INVALID_NAME; /* Cannot remove the start directory */ - } else { - if (dir[DIR_Attr] & AM_RDO) - res = FR_DENIED; /* Cannot remove R/O object */ - } - dclst = ld_clust(dj.fs, dir); - if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ - if (dclst < 2) { - res = FR_INT_ERR; - } else { - mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-dir is empty or not */ - sdj.sclust = dclst; - res = dir_sdi(&sdj, 2); /* Exclude dot entries */ - if (res == FR_OK) { - res = dir_read(&sdj, 0); /* Read an item */ - if (res == FR_OK /* Not empty dir */ -#if _FS_RPATH - || dclst == dj.fs->cdir /* Current dir */ -#endif - ) res = FR_DENIED; - if (res == FR_NO_FILE) res = FR_OK; /* Empty */ - } - } - } - if (res == FR_OK) { - res = dir_remove(&dj); /* Remove the directory entry */ - if (res == FR_OK) { - if (dclst) /* Remove the cluster chain if exist */ - res = remove_chain(dj.fs, dclst); - if (res == FR_OK) res = sync_fs(dj.fs); - } - } - } - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create a Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_mkdir ( - const TCHAR *path /* Pointer to the directory path */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir, n; - DWORD dsc, dcl, pcl, tm = get_fattime(); - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ - if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_NO_FILE) { /* Can create a new directory */ - dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ - res = FR_OK; - if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ - if (dcl == 1) res = FR_INT_ERR; - if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (res == FR_OK) /* Flush FAT */ - res = sync_window(dj.fs); - if (res == FR_OK) { /* Initialize the new directory table */ - dsc = clust2sect(dj.fs, dcl); - dir = dj.fs->win; - mem_set(dir, 0, SS(dj.fs)); - mem_set(dir+DIR_Name, ' ', 11); /* Create "." entry */ - dir[DIR_Name] = '.'; - dir[DIR_Attr] = AM_DIR; - ST_DWORD(dir+DIR_WrtTime, tm); - st_clust(dir, dcl); - mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */ - dir[33] = '.'; pcl = dj.sclust; - if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) - pcl = 0; - st_clust(dir+SZ_DIR, pcl); - for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ - dj.fs->winsect = dsc++; - dj.fs->wflag = 1; - res = sync_window(dj.fs); - if (res != FR_OK) break; - mem_set(dir, 0, SS(dj.fs)); - } - } - if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ - if (res != FR_OK) { - remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ - } else { - dir = dj.dir; - dir[DIR_Attr] = AM_DIR; /* Attribute */ - ST_DWORD(dir+DIR_WrtTime, tm); /* Created time */ - st_clust(dir, dcl); /* Table start cluster */ - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Change Attribute */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_chmod ( - const TCHAR *path, /* Pointer to the file path */ - BYTE value, /* Attribute bits */ - BYTE mask /* Attribute mask to change */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Is it a root directory? */ - res = FR_INVALID_NAME; - } else { /* File or sub directory */ - mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ - dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Change Timestamp */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_utime ( - const TCHAR *path, /* Pointer to the file/directory name */ - const FILINFO *fno /* Pointer to the time stamp to be set */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Root directory */ - res = FR_INVALID_NAME; - } else { /* File or sub-directory */ - ST_WORD(dir+DIR_WrtTime, fno->ftime); - ST_WORD(dir+DIR_WrtDate, fno->fdate); - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Rename File/Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_rename ( - const TCHAR *path_old, /* Pointer to the old name */ - const TCHAR *path_new /* Pointer to the new name */ -) -{ - FRESULT res; - DIR djo, djn; - BYTE buf[21], *dir; - DWORD dw; - DEF_NAMEBUF; - - - res = chk_mounted(&path_old, &djo.fs, 1); - if (res == FR_OK) { - djn.fs = djo.fs; - INIT_BUF(djo); - res = follow_path(&djo, path_old); /* Check old object */ - if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; -#if _FS_LOCK - if (res == FR_OK) res = chk_lock(&djo, 2); -#endif - if (res == FR_OK) { /* Old object is found */ - if (!djo.dir) { /* Is root dir? */ - res = FR_NO_FILE; - } else { - mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ - mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */ - res = follow_path(&djn, path_new); - if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ - if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ -/* Start critical section that any interruption can cause a cross-link */ - res = dir_register(&djn); /* Register the new entry */ - if (res == FR_OK) { - dir = djn.dir; /* Copy object information except for name */ - mem_cpy(dir+13, buf+2, 19); - dir[DIR_Attr] = buf[0] | AM_ARC; - djo.fs->wflag = 1; - if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ - dw = clust2sect(djo.fs, ld_clust(djo.fs, dir)); - if (!dw) { - res = FR_INT_ERR; - } else { - res = move_window(djo.fs, dw); - dir = djo.fs->win+SZ_DIR; /* .. entry */ - if (res == FR_OK && dir[1] == '.') { - dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust; - st_clust(dir, dw); - djo.fs->wflag = 1; - } - } - } - if (res == FR_OK) { - res = dir_remove(&djo); /* Remove old entry */ - if (res == FR_OK) - res = sync_fs(djo.fs); - } - } -/* End critical section */ - } - } - } - FREE_BUF(); - } - - LEAVE_FF(djo.fs, res); -} - -#endif /* !_FS_READONLY */ -#endif /* _FS_MINIMIZE == 0 */ -#endif /* _FS_MINIMIZE <= 1 */ -#endif /* _FS_MINIMIZE <= 2 */ - - - -#if _USE_LABEL -/*-----------------------------------------------------------------------*/ -/* Get volume label */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_getlabel ( - const TCHAR* path, /* Path name of the logical drive number */ - TCHAR* label, /* Pointer to a buffer to return the volume label */ - DWORD* sn /* Pointer to a variable to return the volume serial number */ -) -{ - FRESULT res; - DIR dj; - UINT i, j; - - - /* Get logical drive */ - res = chk_mounted(&path, &dj.fs, 0); - - /* Get volume label */ - if (res == FR_OK && label) { - dj.sclust = 0; /* Open root dir */ - res = dir_sdi(&dj, 0); - if (res == FR_OK) { - res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ - if (res == FR_OK) { /* A volume label is exist */ -#if _LFN_UNICODE - WCHAR w; - i = j = 0; - do { - w = (i < 11) ? dj.dir[i++] : ' '; - if (IsDBCS1(w) && i < 11 && IsDBCS2(dj.dir[i])) - w = (w << 8) | dj.dir[i++]; - label[j++] = ff_convert(w, 1); - } while (j < 11); -#else - mem_cpy(label, dj.dir, 11); -#endif - j = 11; - do { - label[j] = 0; - if (!j) break; - } while (label[--j] == ' '); - } - if (res == FR_NO_FILE) { /* No label, return nul string */ - label[0] = 0; - res = FR_OK; - } - } - } - - /* Get volume serial number */ - if (res == FR_OK && sn) { - res = move_window(dj.fs, dj.fs->volbase); - if (res == FR_OK) { - i = dj.fs->fs_type == FS_FAT32 ? BS_VolID32 : BS_VolID; - *sn = LD_DWORD(&dj.fs->win[i]); - } - } - - LEAVE_FF(dj.fs, res); -} - - - -#if !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Set volume label */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_setlabel ( - const TCHAR* label /* Pointer to the volume label to set */ -) -{ - FRESULT res; - DIR dj; - BYTE vn[11]; - UINT i, j, sl; - WCHAR w; - DWORD tm; - - - /* Get logical drive */ - res = chk_mounted(&label, &dj.fs, 1); - if (res) LEAVE_FF(dj.fs, res); - - /* Create a volume label in directory form */ - vn[0] = 0; - for (sl = 0; label[sl]; sl++) ; /* Get name length */ - for ( ; sl && label[sl-1] == ' '; sl--) ; /* Remove trailing spaces */ - if (sl) { /* Create volume label in directory form */ - i = j = 0; - do { -#if _LFN_UNICODE - w = ff_convert(ff_wtoupper(label[i++]), 0); -#else - w = (BYTE)label[i++]; - if (IsDBCS1(w)) - w = (j < 10 && i < sl && IsDBCS2(label[i])) ? (w << 8) | (BYTE)label[i++] : 0; -#if _USE_LFN - w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0); -#else - if (IsLower(w)) w -= 0x20; /* To upper ASCII chars */ -#ifdef _EXCVT - if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended chars (SBCS cfg) */ -#else - if (!_DF1S && w >= 0x80) w = 0; /* Reject extended chars (ASCII cfg) */ -#endif -#endif -#endif - if (!w || chk_chr("\"*+,.:;<=>\?[]|\x7F", w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) /* Reject invalid chars for volume label */ - LEAVE_FF(dj.fs, FR_INVALID_NAME); - if (w >= 0x100) vn[j++] = (BYTE)(w >> 8); - vn[j++] = (BYTE)w; - } while (i < sl); - while (j < 11) vn[j++] = ' '; - } - - /* Set volume label */ - dj.sclust = 0; /* Open root dir */ - res = dir_sdi(&dj, 0); - if (res == FR_OK) { - res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ - if (res == FR_OK) { /* A volume label is found */ - if (vn[0]) { - mem_cpy(dj.dir, vn, 11); /* Change the volume label name */ - tm = get_fattime(); - ST_DWORD(dj.dir+DIR_WrtTime, tm); - } else { - dj.dir[0] = DDE; /* Remove the volume label */ - } - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } else { /* No volume label is found or error */ - if (res == FR_NO_FILE) { - res = FR_OK; - if (vn[0]) { /* Create volume label as new */ - res = dir_alloc(&dj, 1); /* Allocate an entry for volume label */ - if (res == FR_OK) { - mem_set(dj.dir, 0, SZ_DIR); /* Set volume label */ - mem_cpy(dj.dir, vn, 11); - dj.dir[DIR_Attr] = AM_VOL; - tm = get_fattime(); - ST_DWORD(dj.dir+DIR_WrtTime, tm); - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - } - } - } - - LEAVE_FF(dj.fs, res); -} - -#endif /* !_FS_READONLY */ -#endif /* _USE_LABEL */ - - - -/*-----------------------------------------------------------------------*/ -/* Forward data to the stream directly (available on only tiny cfg) */ -/*-----------------------------------------------------------------------*/ -#if _USE_FORWARD && _FS_TINY - -FRESULT f_forward ( - FIL *fp, /* Pointer to the file object */ - UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ - UINT btf, /* Number of bytes to forward */ - UINT *bf /* Pointer to number of bytes forwarded */ -) -{ - FRESULT res; - DWORD remain, clst, sect; - UINT rcnt; - BYTE csect; - - - *bf = 0; /* Clear transfer byte counter */ - - res = validate(fp); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check error flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - - remain = fp->fsize - fp->fptr; - if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ - - for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ - fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - if (!csect) { /* On the cluster boundary? */ - clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->sclust : get_fat(fp->fs, fp->clust); - if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - } - } - sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - if (move_window(fp->fs, sect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - fp->dsect = sect; - rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ - if (rcnt > btf) rcnt = btf; - rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); - if (!rcnt) ABORT(fp->fs, FR_INT_ERR); - } - - LEAVE_FF(fp->fs, FR_OK); -} -#endif /* _USE_FORWARD */ - - - -#if _USE_MKFS && !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Create File System on the Drive */ -/*-----------------------------------------------------------------------*/ -#define N_ROOTDIR 512 /* Number of root dir entries for FAT12/16 */ -#define N_FATS 1 /* Number of FAT copies (1 or 2) */ - - -FRESULT f_mkfs ( - BYTE vol, /* Logical drive number */ - BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ - UINT au /* Allocation unit size [bytes] */ -) -{ - static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; - static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; - BYTE fmt, md, sys, *tbl, pdrv, part; - DWORD n_clst, vs, n, wsect; - UINT i; - DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ - DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ - FATFS *fs; - DSTATUS stat; - - - /* Check mounted drive and clear work area */ - if (vol >= _VOLUMES) return FR_INVALID_DRIVE; - if (sfd > 1) return FR_INVALID_PARAMETER; - if (au & (au - 1)) return FR_INVALID_PARAMETER; - fs = FatFs[vol]; - if (!fs) return FR_NOT_ENABLED; - fs->fs_type = 0; - pdrv = LD2PD(vol); /* Physical drive */ - part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/ - - /* Get disk statics */ - stat = disk_initialize(pdrv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; -#if _MAX_SS != 512 /* Get disk sector size */ - if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) - return FR_DISK_ERR; -#endif - if (_MULTI_PARTITION && part) { - /* Get partition information from partition table in the MBR */ - if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; - if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; - tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; - if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ - b_vol = LD_DWORD(tbl+8); /* Volume start sector */ - n_vol = LD_DWORD(tbl+12); /* Volume size */ - } else { - /* Create a partition in this function */ - if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) - return FR_DISK_ERR; - b_vol = (sfd) ? 0 : 63; /* Volume start sector */ - n_vol -= b_vol; /* Volume size */ - } - - if (!au) { /* AU auto selection */ - vs = n_vol / (2000 / (SS(fs) / 512)); - for (i = 0; vs < vst[i]; i++) ; - au = cst[i]; - } - au /= SS(fs); /* Number of sectors per cluster */ - if (au == 0) au = 1; - if (au > 128) au = 128; - - /* Pre-compute number of clusters and FAT sub-type */ - n_clst = n_vol / au; - fmt = FS_FAT12; - if (n_clst >= MIN_FAT16) fmt = FS_FAT16; - if (n_clst >= MIN_FAT32) fmt = FS_FAT32; - - /* Determine offset and size of FAT structure */ - if (fmt == FS_FAT32) { - n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); - n_rsv = 32; - n_dir = 0; - } else { - n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; - n_fat = (n_fat + SS(fs) - 1) / SS(fs); - n_rsv = 1; - n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs); - } - b_fat = b_vol + n_rsv; /* FAT area start sector */ - b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ - b_data = b_dir + n_dir; /* Data area start sector */ - if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ - - /* Align data start sector to erase block boundary (for flash memory media) */ - if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; - n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ - n = (n - b_data) / N_FATS; - if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ - n_rsv += n; - b_fat += n; - } else { /* FAT12/16: Expand FAT size */ - n_fat += n; - } - - /* Determine number of clusters and final check of validity of the FAT sub-type */ - n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; - if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) - || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) - return FR_MKFS_ABORTED; - - switch (fmt) { /* Determine system ID for partition table */ - case FS_FAT12: sys = 0x01; break; - case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break; - default: sys = 0x0C; - } - - if (_MULTI_PARTITION && part) { - /* Update system ID in the partition table */ - tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; - tbl[4] = sys; - if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; - md = 0xF8; - } else { - if (sfd) { /* No partition table (SFD) */ - md = 0xF0; - } else { /* Create partition table (FDISK) */ - mem_set(fs->win, 0, SS(fs)); - tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */ - tbl[1] = 1; /* Partition start head */ - tbl[2] = 1; /* Partition start sector */ - tbl[3] = 0; /* Partition start cylinder */ - tbl[4] = sys; /* System type */ - tbl[5] = 254; /* Partition end head */ - n = (b_vol + n_vol) / 63 / 255; - tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */ - tbl[7] = (BYTE)n; /* End cylinder */ - ST_DWORD(tbl+8, 63); /* Partition start in LBA */ - ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ - ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ - if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */ - return FR_DISK_ERR; - md = 0xF8; - } - } - - /* Create BPB in the VBR */ - tbl = fs->win; /* Clear sector */ - mem_set(tbl, 0, SS(fs)); - mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ - i = SS(fs); /* Sector size */ - ST_WORD(tbl+BPB_BytsPerSec, i); - tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ - ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ - tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ - i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ - ST_WORD(tbl+BPB_RootEntCnt, i); - if (n_vol < 0x10000) { /* Number of total sectors */ - ST_WORD(tbl+BPB_TotSec16, n_vol); - } else { - ST_DWORD(tbl+BPB_TotSec32, n_vol); - } - tbl[BPB_Media] = md; /* Media descriptor */ - ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ - ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ - ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ - n = get_fattime(); /* Use current time as VSN */ - if (fmt == FS_FAT32) { - ST_DWORD(tbl+BS_VolID32, n); /* VSN */ - ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ - ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ - ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ - ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ - tbl[BS_DrvNum32] = 0x80; /* Drive number */ - tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ - } else { - ST_DWORD(tbl+BS_VolID, n); /* VSN */ - ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ - tbl[BS_DrvNum] = 0x80; /* Drive number */ - tbl[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ - } - ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ - if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */ - return FR_DISK_ERR; - if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ - disk_write(pdrv, tbl, b_vol + 6, 1); - - /* Initialize FAT area */ - wsect = b_fat; - for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */ - mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ - n = md; /* Media descriptor byte */ - if (fmt != FS_FAT32) { - n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; - ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ - } else { - n |= 0xFFFFFF00; - ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ - ST_DWORD(tbl+4, 0xFFFFFFFF); - ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ - } - if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ - for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ - if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } - } - - /* Initialize root directory */ - i = (fmt == FS_FAT32) ? au : n_dir; - do { - if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } while (--i); - -#if _USE_ERASE /* Erase data area if needed */ - { - DWORD eb[2]; - - eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; - disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb); - } -#endif - - /* Create FSInfo if needed */ - if (fmt == FS_FAT32) { - ST_DWORD(tbl+FSI_LeadSig, 0x41615252); - ST_DWORD(tbl+FSI_StrucSig, 0x61417272); - ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */ - ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */ - ST_WORD(tbl+BS_55AA, 0xAA55); - disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ - disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ - } - - return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; -} - - -#if _MULTI_PARTITION -/*-----------------------------------------------------------------------*/ -/* Divide Physical Drive */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_fdisk ( - BYTE pdrv, /* Physical drive number */ - const DWORD szt[], /* Pointer to the size table for each partitions */ - void* work /* Pointer to the working buffer */ -) -{ - UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; - BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; - DSTATUS stat; - DWORD sz_disk, sz_part, s_part; - - - stat = disk_initialize(pdrv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; - if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; - - /* Determine CHS in the table regardless of the drive geometry */ - for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; - if (n == 256) n--; - e_hd = n - 1; - sz_cyl = 63 * n; - tot_cyl = sz_disk / sz_cyl; - - /* Create partition table */ - mem_set(buf, 0, _MAX_SS); - p = buf + MBR_Table; b_cyl = 0; - for (i = 0; i < 4; i++, p += SZ_PTE) { - p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; - if (!p_cyl) continue; - s_part = (DWORD)sz_cyl * b_cyl; - sz_part = (DWORD)sz_cyl * p_cyl; - if (i == 0) { /* Exclude first track of cylinder 0 */ - s_hd = 1; - s_part += 63; sz_part -= 63; - } else { - s_hd = 0; - } - e_cyl = b_cyl + p_cyl - 1; - if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; - - /* Set partition table */ - p[1] = s_hd; /* Start head */ - p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ - p[3] = (BYTE)b_cyl; /* Start cylinder */ - p[4] = 0x06; /* System type (temporary setting) */ - p[5] = e_hd; /* End head */ - p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ - p[7] = (BYTE)e_cyl; /* End cylinder */ - ST_DWORD(p + 8, s_part); /* Start sector in LBA */ - ST_DWORD(p + 12, sz_part); /* Partition size */ - - /* Next partition */ - b_cyl += p_cyl; - } - ST_WORD(p, 0xAA55); - - /* Write it to the MBR */ - return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK; -} - - -#endif /* _MULTI_PARTITION */ -#endif /* _USE_MKFS && !_FS_READONLY */ - - - - -#if _USE_STRFUNC -/*-----------------------------------------------------------------------*/ -/* Get a string from the file */ -/*-----------------------------------------------------------------------*/ - -TCHAR* f_gets ( - TCHAR* buff, /* Pointer to the string buffer to read */ - int len, /* Size of string buffer (characters) */ - FIL* fp /* Pointer to the file object */ -) -{ - int n = 0; - TCHAR c, *p = buff; - BYTE s[2]; - UINT rc; - - - while (n < len - 1) { /* Read bytes until buffer gets filled */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; /* Break on EOF or error */ - c = s[0]; -#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ - if (c >= 0x80) { - if (c < 0xC0) continue; /* Skip stray trailer */ - if (c < 0xE0) { /* Two-byte sequence */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = ((c & 0x1F) << 6) | (s[0] & 0x3F); - if (c < 0x80) c = '?'; - } else { - if (c < 0xF0) { /* Three-byte sequence */ - f_read(fp, s, 2, &rc); - if (rc != 2) break; - c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F); - if (c < 0x800) c = '?'; - } else { /* Reject four-byte sequence */ - c = '?'; - } - } - } -#endif -#if _USE_STRFUNC >= 2 - if (c == '\r') continue; /* Strip '\r' */ -#endif - *p++ = c; - n++; - if (c == '\n') break; /* Break on EOL */ - } - *p = 0; - return n ? buff : 0; /* When no data read (eof or error), return with error. */ -} - - - -#if !_FS_READONLY -#include -/*-----------------------------------------------------------------------*/ -/* Put a character to the file */ -/*-----------------------------------------------------------------------*/ - -int f_putc ( - TCHAR c, /* A character to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - UINT bw, btw; - BYTE s[3]; - - -#if _USE_STRFUNC >= 2 - if (c == '\n') f_putc ('\r', fp); /* LF -> CRLF conversion */ -#endif - -#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ - if (c < 0x80) { /* 7-bit */ - s[0] = (BYTE)c; - btw = 1; - } else { - if (c < 0x800) { /* 11-bit */ - s[0] = (BYTE)(0xC0 | (c >> 6)); - s[1] = (BYTE)(0x80 | (c & 0x3F)); - btw = 2; - } else { /* 16-bit */ - s[0] = (BYTE)(0xE0 | (c >> 12)); - s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F)); - s[2] = (BYTE)(0x80 | (c & 0x3F)); - btw = 3; - } - } -#else /* Write the character without conversion */ - s[0] = (BYTE)c; - btw = 1; -#endif - f_write(fp, s, btw, &bw); /* Write the char to the file */ - return (bw == btw) ? 1 : EOF; /* Return the result */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a string to the file */ -/*-----------------------------------------------------------------------*/ - -int f_puts ( - const TCHAR* str, /* Pointer to the string to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - int n; - - - for (n = 0; *str; str++, n++) { - if (f_putc(*str, fp) == EOF) return EOF; - } - return n; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a formatted string to the file */ -/*-----------------------------------------------------------------------*/ - -int f_printf ( - FIL* fp, /* Pointer to the file object */ - const TCHAR* str, /* Pointer to the format string */ - ... /* Optional arguments... */ -) -{ - va_list arp; - BYTE f, r; - UINT i, j, w; - ULONG v; - TCHAR c, d, s[16], *p; - int res, chc, cc; - - - va_start(arp, str); - - for (cc = res = 0; cc != EOF; res += cc) { - c = *str++; - if (c == 0) break; /* End of string */ - if (c != '%') { /* Non escape character */ - cc = f_putc(c, fp); - if (cc != EOF) cc = 1; - continue; - } - w = f = 0; - c = *str++; - if (c == '0') { /* Flag: '0' padding */ - f = 1; c = *str++; - } else { - if (c == '-') { /* Flag: left justified */ - f = 2; c = *str++; - } - } - while (IsDigit(c)) { /* Precision */ - w = w * 10 + c - '0'; - c = *str++; - } - if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ - f |= 4; c = *str++; - } - if (!c) break; - d = c; - if (IsLower(d)) d -= 0x20; - switch (d) { /* Type is... */ - case 'S' : /* String */ - p = va_arg(arp, TCHAR*); - for (j = 0; p[j]; j++) ; - chc = 0; - if (!(f & 2)) { - while (j++ < w) chc += (cc = f_putc(' ', fp)); - } - chc += (cc = f_puts(p, fp)); - while (j++ < w) chc += (cc = f_putc(' ', fp)); - if (cc != EOF) cc = chc; - continue; - case 'C' : /* Character */ - cc = f_putc((TCHAR)va_arg(arp, int), fp); continue; - case 'B' : /* Binary */ - r = 2; break; - case 'O' : /* Octal */ - r = 8; break; - case 'D' : /* Signed decimal */ - case 'U' : /* Unsigned decimal */ - r = 10; break; - case 'X' : /* Hexdecimal */ - r = 16; break; - default: /* Unknown type (pass-through) */ - cc = f_putc(c, fp); continue; - } - - /* Get an argument and put it in numeral */ - v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int)); - if (d == 'D' && (v & 0x80000000)) { - v = 0 - v; - f |= 8; - } - i = 0; - do { - d = (TCHAR)(v % r); v /= r; - if (d > 9) d += (c == 'x') ? 0x27 : 0x07; - s[i++] = d + '0'; - } while (v && i < sizeof s / sizeof s[0]); - if (f & 8) s[i++] = '-'; - j = i; d = (f & 1) ? '0' : ' '; - chc = 0; - while (!(f & 2) && j++ < w) chc += (cc = f_putc(d, fp)); - do chc += (cc = f_putc(s[--i], fp)); while(i); - while (j++ < w) chc += (cc = f_putc(' ', fp)); - if (cc != EOF) cc = chc; - } - - va_end(arp); - return (cc == EOF) ? cc : res; -} - -#endif /* !_FS_READONLY */ -#endif /* _USE_STRFUNC */ - -#endif // CFG_TUH_MSC diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h deleted file mode 100644 index 5c2a611ae..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h +++ /dev/null @@ -1,342 +0,0 @@ -/*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module include file R0.09b (C)ChaN, 2013 -/----------------------------------------------------------------------------/ -/ FatFs module is a generic FAT file system module for small embedded systems. -/ This is a free software that opened for education, research and commercial -/ developments under license policy of following terms. -/ -/ Copyright (C) 2013, ChaN, all right reserved. -/ -/ * The FatFs module is a free software and there is NO WARRANTY. -/ * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. -/ * Redistributions of source code must retain the above copyright notice. -/ -/----------------------------------------------------------------------------*/ - -#ifndef _FATFS -#define _FATFS 82786 /* Revision ID */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "integer.h" /* Basic integer types */ -#include "ffconf.h" /* FatFs configuration options */ -#include "tusb_config.h" - -#if _FATFS != _FFCONF -#error Wrong configuration file (ffconf.h). -#endif - - - -/* Definitions of volume management */ - -#if _MULTI_PARTITION /* Multiple partition configuration */ -typedef struct { - BYTE pd; /* Physical drive number */ - BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ -} PARTITION; -extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ -#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ -#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ - -#else /* Single partition configuration */ -#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ -#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */ - -#endif - - - -/* Type of path name strings on FatFs API */ - -#if _LFN_UNICODE /* Unicode string */ -#if !_USE_LFN -#error _LFN_UNICODE must be 0 in non-LFN cfg. -#endif -#ifndef _INC_TCHAR -typedef WCHAR TCHAR; -#define _T(x) L ## x -#define _TEXT(x) L ## x -#endif - -#else /* ANSI/OEM string */ -#ifndef _INC_TCHAR -typedef char TCHAR; -#define _T(x) x -#define _TEXT(x) x -#endif - -#endif - - - -/* File system object structure (FATFS) */ - -typedef struct { - BYTE fs_type; /* FAT sub-type (0:Not mounted) */ - BYTE drv; /* Physical drive number */ - BYTE csize; /* Sectors per cluster (1,2,4...128) */ - BYTE n_fats; /* Number of FAT copies (1,2) */ - BYTE wflag; /* win[] dirty flag (1:must be written back) */ - BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ - WORD id; /* File system mount ID */ - WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ -#if _MAX_SS != 512 - WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ -#endif -#if _FS_REENTRANT - _SYNC_t sobj; /* Identifier of sync object */ -#endif -#if !_FS_READONLY - DWORD last_clust; /* Last allocated cluster */ - DWORD free_clust; /* Number of free clusters */ - DWORD fsi_sector; /* fsinfo sector (FAT32) */ -#endif -#if _FS_RPATH - DWORD cdir; /* Current directory start cluster (0:root) */ -#endif - DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ - DWORD fsize; /* Sectors per FAT */ - DWORD volbase; /* Volume start sector */ - DWORD fatbase; /* FAT start sector */ - DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ - DWORD database; /* Data start sector */ - DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ -} FATFS; - - - -/* File object structure (FIL) */ - -typedef struct { - FATFS* fs; /* Pointer to the related file system object (**do not change order**) */ - WORD id; /* Owner file system mount ID (**do not change order**) */ - BYTE flag; /* File status flags */ - BYTE pad1; - DWORD fptr; /* File read/write pointer (0ed on file open) */ - DWORD fsize; /* File size */ - DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */ - DWORD clust; /* Current cluster of fpter */ - DWORD dsect; /* Current data sector of fpter */ -#if !_FS_READONLY - DWORD dir_sect; /* Sector containing the directory entry */ - BYTE* dir_ptr; /* Pointer to the directory entry in the window */ -#endif -#if _USE_FASTSEEK - DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ -#endif -#if _FS_LOCK - UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ -#endif -#if !_FS_TINY - BYTE buf[_MAX_SS]; /* File data read/write buffer */ -#endif -} FIL; - - - -/* Directory object structure (DIR) */ - -typedef struct { - FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */ - WORD id; /* Owner file system mount ID (**do not change order**) */ - WORD index; /* Current read/write index number */ - DWORD sclust; /* Table start cluster (0:Root dir) */ - DWORD clust; /* Current cluster */ - DWORD sect; /* Current sector */ - BYTE* dir; /* Pointer to the current SFN entry in the win[] */ - BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ -#if _USE_LFN - WCHAR* lfn; /* Pointer to the LFN working buffer */ - WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ -#endif -} DIR; - - - -/* File status structure (FILINFO) */ - -typedef struct { - DWORD fsize; /* File size */ - WORD fdate; /* Last modified date */ - WORD ftime; /* Last modified time */ - BYTE fattrib; /* Attribute */ - TCHAR fname[13]; /* Short file name (8.3 format) */ -#if _USE_LFN - TCHAR* lfname; /* Pointer to the LFN buffer */ - UINT lfsize; /* Size of LFN buffer in TCHAR */ -#endif -} FILINFO; - - - -/* File function return code (FRESULT) */ - -typedef enum { - FR_OK = 0, /* (0) Succeeded */ - FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ - FR_INT_ERR, /* (2) Assertion failed */ - FR_NOT_READY, /* (3) The physical drive cannot work */ - FR_NO_FILE, /* (4) Could not find the file */ - FR_NO_PATH, /* (5) Could not find the path */ - FR_INVALID_NAME, /* (6) The path name format is invalid */ - FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ - FR_EXIST, /* (8) Access denied due to prohibited access */ - FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ - FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ - FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ - FR_NOT_ENABLED, /* (12) The volume has no work area */ - FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ - FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ - FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ - FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ - FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ - FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ - FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ -} FRESULT; - - - -/*--------------------------------------------------------------*/ -/* FatFs module application interface */ - -FRESULT f_mount (BYTE vol, FATFS* fs); /* Mount/Unmount a logical drive */ -FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ -FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */ -FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */ -FRESULT f_close (FIL* fp); /* Close an open file object */ -FRESULT f_opendir (DIR* dj, const TCHAR* path); /* Open an existing directory */ -FRESULT f_readdir (DIR* dj, FILINFO* fno); /* Read a directory item */ -FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ -FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ -FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ -FRESULT f_truncate (FIL* fp); /* Truncate file */ -FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */ -FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ -FRESULT f_mkdir (const TCHAR* path); /* Create a new directory */ -FRESULT f_chmod (const TCHAR* path, BYTE value, BYTE mask); /* Change attribute of the file/dir */ -FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */ -FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ -FRESULT f_chdrive (BYTE drv); /* Change current drive */ -BYTE f_get_current_drive(void); -FRESULT f_chdir (const TCHAR* path); /* Change current directory */ -FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ -FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* sn); /* Get volume label */ -FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ -FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ -FRESULT f_mkfs (BYTE vol, BYTE sfd, UINT au); /* Create a file system on the drive */ -FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */ -int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ -int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ -int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ -TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ - -#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) -#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) -#define f_tell(fp) ((fp)->fptr) -#define f_size(fp) ((fp)->fsize) - -#ifndef EOF -#define EOF (-1) -#endif - - - - -/*--------------------------------------------------------------*/ -/* Additional user defined functions */ - -/* RTC function */ -#if !_FS_READONLY -DWORD get_fattime (void); -#endif - -/* Unicode support functions */ -#if _USE_LFN /* Unicode - OEM code conversion */ -WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ -WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ -#if _USE_LFN == 3 /* Memory functions */ -void* ff_memalloc (UINT msize); /* Allocate memory block */ -void ff_memfree (void* mblock); /* Free memory block */ -#endif -#endif - -/* Sync functions */ -#if _FS_REENTRANT -int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */ -int ff_req_grant (_SYNC_t sobj); /* Lock sync object */ -void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */ -int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ -#endif - - - - -/*--------------------------------------------------------------*/ -/* Flags and offset address */ - - -/* File access control and file status flags (FIL.flag) */ - -#define FA_READ 0x01 -#define FA_OPEN_EXISTING 0x00 -#define FA__ERROR 0x80 - -#if !_FS_READONLY -#define FA_WRITE 0x02 -#define FA_CREATE_NEW 0x04 -#define FA_CREATE_ALWAYS 0x08 -#define FA_OPEN_ALWAYS 0x10 -#define FA__WRITTEN 0x20 -#define FA__DIRTY 0x40 -#endif - - -/* FAT sub type (FATFS.fs_type) */ - -#define FS_FAT12 1 -#define FS_FAT16 2 -#define FS_FAT32 3 - - -/* File attribute bits for directory entry */ - -#define AM_RDO 0x01 /* Read only */ -#define AM_HID 0x02 /* Hidden */ -#define AM_SYS 0x04 /* System */ -#define AM_VOL 0x08 /* Volume label */ -#define AM_LFN 0x0F /* LFN entry */ -#define AM_DIR 0x10 /* Directory */ -#define AM_ARC 0x20 /* Archive */ -#define AM_MASK 0x3F /* Mask of defined bits */ - - -/* Fast seek feature */ -#define CREATE_LINKMAP 0xFFFFFFFF - - - -/*--------------------------------*/ -/* Multi-byte word access macros */ - -#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) -#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) -#else /* Use byte-by-byte access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) -#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _FATFS */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h deleted file mode 100644 index 782057ea4..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h +++ /dev/null @@ -1,193 +0,0 @@ -/*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module configuration file R0.09b (C)ChaN, 2013 -/----------------------------------------------------------------------------/ -/ -/ CAUTION! Do not forget to make clean the project after any changes to -/ the configuration options. -/ -/----------------------------------------------------------------------------*/ -#ifndef _FFCONF -#define _FFCONF 82786 /* Revision ID */ - -#include "tusb_config.h" - -/*---------------------------------------------------------------------------/ -/ Functions and Buffer Configurations -/----------------------------------------------------------------------------*/ - -#define _FS_TINY 0 /* 0:Normal or 1:Tiny */ -/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system -/ object instead of the sector buffer in the individual file object for file -/ data transfer. This reduces memory consumption 512 bytes each file object. */ - - -#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ -/* Setting _FS_READONLY to 1 defines read only configuration. This removes -/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, -/ f_truncate and useless f_getfree. */ - - -#define _FS_MINIMIZE 0 /* 0 to 3 */ -/* The _FS_MINIMIZE option defines minimization level to remove some functions. -/ -/ 0: Full function. -/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename -/ are removed. -/ 2: f_opendir and f_readdir are removed in addition to 1. -/ 3: f_lseek is removed in addition to 2. */ - - -#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ -/* To enable string functions, set _USE_STRFUNC to 1 or 2. */ - - -#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ -/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ - - -#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ -/* To enable fast seek feature, set _USE_FASTSEEK to 1. */ - - -#define _USE_LABEL 1 /* 0:Disable or 1:Enable */ -/* To enable volume label functions, set _USE_LAVEL to 1 */ - - -#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ -/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ - - -/*---------------------------------------------------------------------------/ -/ Locale and Namespace Configurations -/----------------------------------------------------------------------------*/ - -#define _CODE_PAGE 437 -/* The _CODE_PAGE specifies the OEM code page to be used on the target system. -/ Incorrect setting of the code page can cause a file open failure. -/ -/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) -/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) -/ 949 - Korean (DBCS, OEM, Windows) -/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) -/ 1250 - Central Europe (Windows) -/ 1251 - Cyrillic (Windows) -/ 1252 - Latin 1 (Windows) -/ 1253 - Greek (Windows) -/ 1254 - Turkish (Windows) -/ 1255 - Hebrew (Windows) -/ 1256 - Arabic (Windows) -/ 1257 - Baltic (Windows) -/ 1258 - Vietnam (OEM, Windows) -/ 437 - U.S. (OEM) -/ 720 - Arabic (OEM) -/ 737 - Greek (OEM) -/ 775 - Baltic (OEM) -/ 850 - Multilingual Latin 1 (OEM) -/ 858 - Multilingual Latin 1 + Euro (OEM) -/ 852 - Latin 2 (OEM) -/ 855 - Cyrillic (OEM) -/ 866 - Russian (OEM) -/ 857 - Turkish (OEM) -/ 862 - Hebrew (OEM) -/ 874 - Thai (OEM, Windows) -/ 1 - ASCII only (Valid for non LFN cfg.) -*/ - - -#define _USE_LFN 1 /* 0 to 3 */ -#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ -/* The _USE_LFN option switches the LFN support. -/ -/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. -/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant. -/ 2: Enable LFN with dynamic working buffer on the STACK. -/ 3: Enable LFN with dynamic working buffer on the HEAP. -/ -/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN, -/ Unicode handling functions ff_convert() and ff_wtoupper() must be added -/ to the project. When enable to use heap, memory control functions -/ ff_memalloc() and ff_memfree() must be added to the project. */ - - -#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ -/* To switch the character code set on FatFs API to Unicode, -/ enable LFN feature and set _LFN_UNICODE to 1. */ - - -#define _FS_RPATH 2 /* 0 to 2 */ -/* The _FS_RPATH option configures relative path feature. -/ -/ 0: Disable relative path feature and remove related functions. -/ 1: Enable relative path. f_chdrive() and f_chdir() are available. -/ 2: f_getcwd() is available in addition to 1. -/ -/ Note that output of the f_readdir fnction is affected by this option. */ - - -/*---------------------------------------------------------------------------/ -/ Physical Drive Configurations -/----------------------------------------------------------------------------*/ - -#define _VOLUMES CFG_TUH_DEVICE_MAX -/* Number of volumes (logical drives) to be used. */ - - -#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ -/* Maximum sector size to be handled. -/ Always set 512 for memory card and hard disk but a larger value may be -/ required for on-board flash memory, floppy disk and optical disk. -/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size -/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */ - - -#define _MULTI_PARTITION 0 /* 0:Single partition, 1:Enable multiple partition */ -/* When set to 0, each volume is bound to the same physical drive number and -/ it can mount only first primaly partition. When it is set to 1, each volume -/ is tied to the partitions listed in VolToPart[]. */ - - -#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ -/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command -/ should be added to the disk_ioctl functio. */ - - - -/*---------------------------------------------------------------------------/ -/ System Configurations -/----------------------------------------------------------------------------*/ - -#define _WORD_ACCESS 0 /* 0 or 1 */ -/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS -/ option defines which access method is used to the word data on the FAT volume. -/ -/ 0: Byte-by-byte access. -/ 1: Word access. Do not choose this unless following condition is met. -/ -/ When the byte order on the memory is big-endian or address miss-aligned word -/ access results incorrect behavior, the _WORD_ACCESS must be set to 0. -/ If it is not the case, the value can also be set to 1 to improve the -/ performance and code size. -*/ - - -/* A header file that defines sync object types on the O/S, such as -/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */ - -#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ -#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ -#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ - -/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module. -/ -/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. -/ 1: Enable reentrancy. Also user provided synchronization handlers, -/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj -/ function must be added to the project. */ - - -#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */ -/* To enable file lock control feature, set _FS_LOCK to 1 or greater. - The value defines how many files can be opened simultaneously. */ - - -#endif /* _FFCONFIG */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h deleted file mode 100644 index f34f56d92..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-------------------------------------------*/ -/* Integer type definitions for FatFs module */ -/*-------------------------------------------*/ - -#ifndef _INTEGER -#define _INTEGER - -#ifdef _WIN32 /* FatFs development platform */ - -#include -#include - -#else /* Embedded platform */ - -/* These types must be 16-bit, 32-bit or larger integer */ -typedef int INT; -typedef unsigned int UINT; - -/* These types must be 8-bit integer */ -typedef unsigned char UCHAR; -typedef unsigned char BYTE; - -/* These types must be 16-bit integer */ -typedef short SHORT; -typedef unsigned short USHORT; -typedef unsigned short WORD; -typedef unsigned short WCHAR; - -/* These types must be 32-bit integer */ -typedef long LONG; -typedef unsigned long ULONG; -typedef unsigned long DWORD; - -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c deleted file mode 100644 index 590739236..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "dhserver.h" - -/* DHCP message type */ -#define DHCP_DISCOVER 1 -#define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_DECLINE 4 -#define DHCP_ACK 5 -#define DHCP_NAK 6 -#define DHCP_RELEASE 7 -#define DHCP_INFORM 8 - -/* DHCP options */ -enum DHCP_OPTIONS -{ - DHCP_PAD = 0, - DHCP_SUBNETMASK = 1, - DHCP_ROUTER = 3, - DHCP_DNSSERVER = 6, - DHCP_HOSTNAME = 12, - DHCP_DNSDOMAIN = 15, - DHCP_MTU = 26, - DHCP_BROADCAST = 28, - DHCP_PERFORMROUTERDISC = 31, - DHCP_STATICROUTE = 33, - DHCP_NISDOMAIN = 40, - DHCP_NISSERVER = 41, - DHCP_NTPSERVER = 42, - DHCP_VENDOR = 43, - DHCP_IPADDRESS = 50, - DHCP_LEASETIME = 51, - DHCP_OPTIONSOVERLOADED = 52, - DHCP_MESSAGETYPE = 53, - DHCP_SERVERID = 54, - DHCP_PARAMETERREQUESTLIST = 55, - DHCP_MESSAGE = 56, - DHCP_MAXMESSAGESIZE = 57, - DHCP_RENEWALTIME = 58, - DHCP_REBINDTIME = 59, - DHCP_CLASSID = 60, - DHCP_CLIENTID = 61, - DHCP_USERCLASS = 77, /* RFC 3004 */ - DHCP_FQDN = 81, - DHCP_DNSSEARCH = 119, /* RFC 3397 */ - DHCP_CSR = 121, /* RFC 3442 */ - DHCP_MSCSR = 249, /* MS code for RFC 3442 */ - DHCP_END = 255 -}; - -typedef struct -{ - uint8_t dp_op; /* packet opcode type */ - uint8_t dp_htype; /* hardware addr type */ - uint8_t dp_hlen; /* hardware addr length */ - uint8_t dp_hops; /* gateway hops */ - uint32_t dp_xid; /* transaction ID */ - uint16_t dp_secs; /* seconds since boot began */ - uint16_t dp_flags; - uint8_t dp_ciaddr[4]; /* client IP address */ - uint8_t dp_yiaddr[4]; /* 'your' IP address */ - uint8_t dp_siaddr[4]; /* server IP address */ - uint8_t dp_giaddr[4]; /* gateway IP address */ - uint8_t dp_chaddr[16]; /* client hardware address */ - uint8_t dp_legacy[192]; - uint8_t dp_magic[4]; - uint8_t dp_options[275]; /* options area */ -} DHCP_TYPE; - -DHCP_TYPE dhcp_data; -static struct udp_pcb *pcb = NULL; -static const dhcp_config_t *config = NULL; - -char magic_cookie[] = {0x63,0x82,0x53,0x63}; - -static ip4_addr_t get_ip(const uint8_t *pnt) -{ - ip4_addr_t result; - memcpy(&result, pnt, sizeof(result)); - return result; -} - -static void set_ip(uint8_t *pnt, ip4_addr_t value) -{ - memcpy(pnt, &value.addr, sizeof(value.addr)); -} - -static dhcp_entry_t *entry_by_ip(ip4_addr_t ip) -{ - int i; - for (i = 0; i < config->num_entry; i++) - if (config->entries[i].addr.addr == ip.addr) - return &config->entries[i]; - return NULL; -} - -static dhcp_entry_t *entry_by_mac(uint8_t *mac) -{ - int i; - for (i = 0; i < config->num_entry; i++) - if (memcmp(config->entries[i].mac, mac, 6) == 0) - return &config->entries[i]; - return NULL; -} - -static __inline bool is_vacant(dhcp_entry_t *entry) -{ - return memcmp("\0\0\0\0\0", entry->mac, 6) == 0; -} - -static dhcp_entry_t *vacant_address(void) -{ - int i; - for (i = 0; i < config->num_entry; i++) - if (is_vacant(config->entries + i)) - return config->entries + i; - return NULL; -} - -static __inline void free_entry(dhcp_entry_t *entry) -{ - memset(entry->mac, 0, 6); -} - -uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) -{ - int i = 0; - while ((i + 1) < size) - { - int next = i + attrs[i + 1] + 2; - if (next > size) return NULL; - if (attrs[i] == attr) - return attrs + i; - i = next; - } - return NULL; -} - -int fill_options(void *dest, - uint8_t msg_type, - const char *domain, - ip4_addr_t dns, - int lease_time, - ip4_addr_t serverid, - ip4_addr_t router, - ip4_addr_t subnet) -{ - uint8_t *ptr = (uint8_t *)dest; - /* ACK message type */ - *ptr++ = 53; - *ptr++ = 1; - *ptr++ = msg_type; - - /* dhcp server identifier */ - *ptr++ = DHCP_SERVERID; - *ptr++ = 4; - set_ip(ptr, serverid); - ptr += 4; - - /* lease time */ - *ptr++ = DHCP_LEASETIME; - *ptr++ = 4; - *ptr++ = (lease_time >> 24) & 0xFF; - *ptr++ = (lease_time >> 16) & 0xFF; - *ptr++ = (lease_time >> 8) & 0xFF; - *ptr++ = (lease_time >> 0) & 0xFF; - - /* subnet mask */ - *ptr++ = DHCP_SUBNETMASK; - *ptr++ = 4; - set_ip(ptr, subnet); - ptr += 4; - - /* router */ - if (router.addr != 0) - { - *ptr++ = DHCP_ROUTER; - *ptr++ = 4; - set_ip(ptr, router); - ptr += 4; - } - - /* domain name */ - if (domain != NULL) - { - int len = strlen(domain); - *ptr++ = DHCP_DNSDOMAIN; - *ptr++ = len; - memcpy(ptr, domain, len); - ptr += len; - } - - /* domain name server (DNS) */ - if (dns.addr != 0) - { - *ptr++ = DHCP_DNSSERVER; - *ptr++ = 4; - set_ip(ptr, dns); - ptr += 4; - } - - /* end */ - *ptr++ = DHCP_END; - return ptr - (uint8_t *)dest; -} - -static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - uint8_t *ptr; - dhcp_entry_t *entry; - struct pbuf *pp; - struct netif *netif = netif_get_by_index(p->if_idx); - - (void)arg; - (void)addr; - - unsigned n = p->len; - if (n > sizeof(dhcp_data)) n = sizeof(dhcp_data); - memcpy(&dhcp_data, p->payload, n); - switch (dhcp_data.dp_options[2]) - { - case DHCP_DISCOVER: - entry = entry_by_mac(dhcp_data.dp_chaddr); - if (entry == NULL) entry = vacant_address(); - if (entry == NULL) break; - - dhcp_data.dp_op = 2; /* reply */ - dhcp_data.dp_secs = 0; - dhcp_data.dp_flags = 0; - set_ip(dhcp_data.dp_yiaddr, entry->addr); - memcpy(dhcp_data.dp_magic, magic_cookie, 4); - - memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); - - fill_options(dhcp_data.dp_options, - DHCP_OFFER, - config->domain, - config->dns, - entry->lease, - *netif_ip4_addr(netif), - config->router, - *netif_ip4_netmask(netif)); - - pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); - if (pp == NULL) break; - memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); - udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); - pbuf_free(pp); - break; - - case DHCP_REQUEST: - /* 1. find requested ipaddr in option list */ - ptr = find_dhcp_option(dhcp_data.dp_options, sizeof(dhcp_data.dp_options), DHCP_IPADDRESS); - if (ptr == NULL) break; - if (ptr[1] != 4) break; - ptr += 2; - - /* 2. does hw-address registered? */ - entry = entry_by_mac(dhcp_data.dp_chaddr); - if (entry != NULL) free_entry(entry); - - /* 3. find requested ipaddr */ - entry = entry_by_ip(get_ip(ptr)); - if (entry == NULL) break; - if (!is_vacant(entry)) break; - - /* 4. fill struct fields */ - memcpy(dhcp_data.dp_yiaddr, ptr, 4); - dhcp_data.dp_op = 2; /* reply */ - dhcp_data.dp_secs = 0; - dhcp_data.dp_flags = 0; - memcpy(dhcp_data.dp_magic, magic_cookie, 4); - - /* 5. fill options */ - memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); - - fill_options(dhcp_data.dp_options, - DHCP_ACK, - config->domain, - config->dns, - entry->lease, - *netif_ip4_addr(netif), - config->router, - *netif_ip4_netmask(netif)); - - /* 6. send ACK */ - pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); - if (pp == NULL) break; - memcpy(entry->mac, dhcp_data.dp_chaddr, 6); - memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); - udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); - pbuf_free(pp); - break; - - default: - break; - } - pbuf_free(p); -} - -err_t dhserv_init(const dhcp_config_t *c) -{ - err_t err; - udp_init(); - dhserv_free(); - pcb = udp_new(); - if (pcb == NULL) - return ERR_MEM; - err = udp_bind(pcb, IP_ADDR_ANY, c->port); - if (err != ERR_OK) - { - dhserv_free(); - return err; - } - udp_recv(pcb, udp_recv_proc, NULL); - config = c; - return ERR_OK; -} - -void dhserv_free(void) -{ - if (pcb == NULL) return; - udp_remove(pcb); - pcb = NULL; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h deleted file mode 100644 index 2a0b15854..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * version: 1.0 demo (7.02.2015) - * brief: tiny dhcp ipv4 server using lwip (pcb) - * ref: https://lists.gnu.org/archive/html/lwip-users/2012-12/msg00016.html - */ - -#ifndef DHSERVER_H -#define DHSERVER_H - -#include -#include -#include -#include -#include "lwip/err.h" -#include "lwip/udp.h" -#include "netif/etharp.h" - -typedef struct dhcp_entry -{ - uint8_t mac[6]; - ip4_addr_t addr; - uint32_t lease; -} dhcp_entry_t; - -typedef struct dhcp_config -{ - ip4_addr_t router; - uint16_t port; - ip4_addr_t dns; - const char *domain; - int num_entry; - dhcp_entry_t *entries; -} dhcp_config_t; - -err_t dhserv_init(const dhcp_config_t *config); -void dhserv_free(void); - -#endif /* DHSERVER_H */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c deleted file mode 100644 index e4e7c3492..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * version: 1.0 demo (7.02.2015) - * brief: tiny dns ipv4 server using lwip (pcb) - */ - -#include "dnserver.h" - -#define DNS_MAX_HOST_NAME_LEN 128 - -static struct udp_pcb *pcb = NULL; -dns_query_proc_t query_proc = NULL; - -#pragma pack(push, 1) -typedef struct -{ -#if BYTE_ORDER == LITTLE_ENDIAN - uint8_t rd: 1, /* Recursion Desired */ - tc: 1, /* Truncation Flag */ - aa: 1, /* Authoritative Answer Flag */ - opcode: 4, /* Operation code */ - qr: 1; /* Query/Response Flag */ - uint8_t rcode: 4, /* Response Code */ - z: 3, /* Zero */ - ra: 1; /* Recursion Available */ -#else - uint8_t qr: 1, /* Query/Response Flag */ - opcode: 4, /* Operation code */ - aa: 1, /* Authoritative Answer Flag */ - tc: 1, /* Truncation Flag */ - rd: 1; /* Recursion Desired */ - uint8_t ra: 1, /* Recursion Available */ - z: 3, /* Zero */ - rcode: 4; /* Response Code */ -#endif -} dns_header_flags_t; - -typedef struct -{ - uint16_t id; - dns_header_flags_t flags; - uint16_t n_record[4]; -} dns_header_t; - -typedef struct dns_answer -{ - uint16_t name; - uint16_t type; - uint16_t Class; - uint32_t ttl; - uint16_t len; - uint32_t addr; -} dns_answer_t; -#pragma pack(pop) - -typedef struct dns_query -{ - char name[DNS_MAX_HOST_NAME_LEN]; - uint16_t type; - uint16_t Class; -} dns_query_t; - -static uint16_t get_uint16(const uint8_t *pnt) -{ - uint16_t result; - memcpy(&result, pnt, sizeof(result)); - return result; -} - -static int parse_next_query(void *data, int size, dns_query_t *query) -{ - int len; - int lables; - uint8_t *ptr; - - len = 0; - lables = 0; - ptr = (uint8_t *)data; - - while (true) - { - uint8_t lable_len; - if (size <= 0) return -1; - lable_len = *ptr++; - size--; - if (lable_len == 0) break; - if (lables > 0) - { - if (len == DNS_MAX_HOST_NAME_LEN) return -2; - query->name[len++] = '.'; - } - if (lable_len > size) return -1; - if (len + lable_len >= DNS_MAX_HOST_NAME_LEN) return -2; - memcpy(&query->name[len], ptr, lable_len); - len += lable_len; - ptr += lable_len; - size -= lable_len; - lables++; - } - - if (size < 4) return -1; - query->name[len] = 0; - query->type = get_uint16(ptr); - ptr += 2; - query->Class = get_uint16(ptr); - ptr += 2; - return ptr - (uint8_t *)data; -} - -static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - int len; - dns_header_t *header; - static dns_query_t query; - struct pbuf *out; - ip4_addr_t host_addr; - dns_answer_t *answer; - - (void)arg; - - if (p->len <= sizeof(dns_header_t)) goto error; - header = (dns_header_t *)p->payload; - if (header->flags.qr != 0) goto error; - if (ntohs(header->n_record[0]) != 1) goto error; - - len = parse_next_query(header + 1, p->len - sizeof(dns_header_t), &query); - if (len < 0) goto error; - if (!query_proc(query.name, &host_addr)) goto error; - - len += sizeof(dns_header_t); - out = pbuf_alloc(PBUF_TRANSPORT, len + 16, PBUF_POOL); - if (out == NULL) goto error; - - memcpy(out->payload, p->payload, len); - header = (dns_header_t *)out->payload; - header->flags.qr = 1; - header->n_record[1] = htons(1); - answer = (struct dns_answer *)((uint8_t *)out->payload + len); - answer->name = htons(0xC00C); - answer->type = htons(1); - answer->Class = htons(1); - answer->ttl = htonl(32); - answer->len = htons(4); - answer->addr = host_addr.addr; - - udp_sendto(upcb, out, addr, port); - pbuf_free(out); - -error: - pbuf_free(p); -} - -err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t qp) -{ - err_t err; - udp_init(); - dnserv_free(); - pcb = udp_new(); - if (pcb == NULL) - return ERR_MEM; - err = udp_bind(pcb, bind, port); - if (err != ERR_OK) - { - dnserv_free(); - return err; - } - udp_recv(pcb, udp_recv_proc, NULL); - query_proc = qp; - return ERR_OK; -} - -void dnserv_free() -{ - if (pcb == NULL) return; - udp_remove(pcb); - pcb = NULL; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h deleted file mode 100644 index a062e3aa7..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * version: 1.0 demo (7.02.2015) - * brief: tiny dns ipv4 server using lwip (pcb) - */ - -#ifndef DNSERVER -#define DNSERVER - -#include -#include -#include -#include -#include "lwip/def.h" -#include "lwip/err.h" -#include "lwip/udp.h" -#include "netif/etharp.h" - -typedef bool (*dns_query_proc_t)(const char *name, ip4_addr_t *addr); - -err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t query_proc); -void dnserv_free(void); - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h deleted file mode 100644 index 1c737574c..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h +++ /dev/null @@ -1,266 +0,0 @@ -/* This file has been prepared for Doxygen automatic documentation generation.*/ -/*! \file ndis.h *************************************************************** - * - * \brief - * This file contains the possible external configuration of the USB. - * - * \addtogroup usbstick - * - * - ******************************************************************************/ - -/** - \ingroup usbstick - \defgroup RNDIS RNDIS Support - @{ - */ - -/* - * ndis.h - * - * Modified by Colin O'Flynn - * ntddndis.h modified by Benedikt Spranger - * - * Thanks to the cygwin development team, - * espacially to Casper S. Hornstrup - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#ifndef _LINUX_NDIS_H -#define _LINUX_NDIS_H - - -#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 -#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A -#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B - -/* from drivers/net/sk98lin/h/skgepnmi.h */ -#define OID_PNP_CAPABILITIES 0xFD010100 -#define OID_PNP_SET_POWER 0xFD010101 -#define OID_PNP_QUERY_POWER 0xFD010102 -#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 -#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 -#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 - -enum NDIS_DEVICE_POWER_STATE { - NdisDeviceStateUnspecified = 0, - NdisDeviceStateD0, - NdisDeviceStateD1, - NdisDeviceStateD2, - NdisDeviceStateD3, - NdisDeviceStateMaximum -}; - -struct NDIS_PM_WAKE_UP_CAPABILITIES { - enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; - enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; - enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; -}; - -/* NDIS_PNP_CAPABILITIES.Flags constants */ -#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 -#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 -#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 - -/* -struct NDIS_PNP_CAPABILITIES { - __le32 Flags; - struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; -}; - -struct NDIS_PM_PACKET_PATTERN { - __le32 Priority; - __le32 Reserved; - __le32 MaskSize; - __le32 PatternOffset; - __le32 PatternSize; - __le32 PatternFlags; -}; -*/ - -/* Required Object IDs (OIDs) */ -#define OID_GEN_SUPPORTED_LIST 0x00010101 -#define OID_GEN_HARDWARE_STATUS 0x00010102 -#define OID_GEN_MEDIA_SUPPORTED 0x00010103 -#define OID_GEN_MEDIA_IN_USE 0x00010104 -#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 -#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 -#define OID_GEN_LINK_SPEED 0x00010107 -#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 -#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 -#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A -#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B -#define OID_GEN_VENDOR_ID 0x0001010C -#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D -#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E -#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F -#define OID_GEN_DRIVER_VERSION 0x00010110 -#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 -#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 -#define OID_GEN_MAC_OPTIONS 0x00010113 -#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 -#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 -#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 -#define OID_GEN_SUPPORTED_GUIDS 0x00010117 -#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 -#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 -#define OID_GEN_MACHINE_NAME 0x0001021A -#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B -#define OID_GEN_VLAN_ID 0x0001021C - -/* Optional OIDs */ -#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 -#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 - -/* Required statistics OIDs */ -#define OID_GEN_XMIT_OK 0x00020101 -#define OID_GEN_RCV_OK 0x00020102 -#define OID_GEN_XMIT_ERROR 0x00020103 -#define OID_GEN_RCV_ERROR 0x00020104 -#define OID_GEN_RCV_NO_BUFFER 0x00020105 - -/* Optional statistics OIDs */ -#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 -#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 -#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 -#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 -#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 -#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 -#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 -#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 -#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 -#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A -#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B -#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C -#define OID_GEN_RCV_CRC_ERROR 0x0002020D -#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E -#define OID_GEN_GET_TIME_CAPS 0x0002020F -#define OID_GEN_GET_NETCARD_TIME 0x00020210 -#define OID_GEN_NETCARD_LOAD 0x00020211 -#define OID_GEN_DEVICE_PROFILE 0x00020212 -#define OID_GEN_INIT_TIME_MS 0x00020213 -#define OID_GEN_RESET_COUNTS 0x00020214 -#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215 -#define OID_GEN_FRIENDLY_NAME 0x00020216 -#define OID_GEN_MINIPORT_INFO 0x00020217 -#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218 - -/* IEEE 802.3 (Ethernet) OIDs */ -#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 - -#define OID_802_3_PERMANENT_ADDRESS 0x01010101 -#define OID_802_3_CURRENT_ADDRESS 0x01010102 -#define OID_802_3_MULTICAST_LIST 0x01010103 -#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 -#define OID_802_3_MAC_OPTIONS 0x01010105 -#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 -#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 -#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 -#define OID_802_3_XMIT_DEFERRED 0x01020201 -#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 -#define OID_802_3_RCV_OVERRUN 0x01020203 -#define OID_802_3_XMIT_UNDERRUN 0x01020204 -#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 -#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 -#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 - -/* Wireless LAN OIDs */ -/* Mandatory */ -#define OID_802_11_BSSID 0x0D010101 /* Q S */ -#define OID_802_11_SSID 0x0D010102 /* Q S */ -#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */ -#define OID_802_11_RSSI 0x0D010206 /* Q I */ -#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */ -#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */ -#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */ -#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */ -#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */ -#define OID_802_11_ADD_WEP 0x0D010113 /* S */ -#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */ -#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */ -#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */ -#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */ -#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */ - - - -/* OID_GEN_MINIPORT_INFO constants */ -#define NDIS_MINIPORT_BUS_MASTER 0x00000001 -#define NDIS_MINIPORT_WDM_DRIVER 0x00000002 -#define NDIS_MINIPORT_SG_LIST 0x00000004 -#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008 -#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010 -#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020 -#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040 -#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080 -#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100 -#define NDIS_MINIPORT_IS_NDIS_5 0x00000200 -#define NDIS_MINIPORT_IS_CO 0x00000400 -#define NDIS_MINIPORT_DESERIALIZE 0x00000800 -#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000 -#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000 -#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000 -#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000 -#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000 -#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000 -#define NDIS_MINIPORT_HIDDEN 0x00040000 -#define NDIS_MINIPORT_SWENUM 0x00080000 -#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000 -#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000 -#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000 -#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000 -#define NDIS_MINIPORT_64BITS_DMA 0x01000000 - -#define NDIS_MEDIUM_802_3 0x00000000 -#define NDIS_MEDIUM_802_5 0x00000001 -#define NDIS_MEDIUM_FDDI 0x00000002 -#define NDIS_MEDIUM_WAN 0x00000003 -#define NDIS_MEDIUM_LOCAL_TALK 0x00000004 -#define NDIS_MEDIUM_DIX 0x00000005 -#define NDIS_MEDIUM_ARCENT_RAW 0x00000006 -#define NDIS_MEDIUM_ARCENT_878_2 0x00000007 -#define NDIS_MEDIUM_ATM 0x00000008 -#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009 -#define NDIS_MEDIUM_IRDA 0x0000000A -#define NDIS_MEDIUM_BPC 0x0000000B -#define NDIS_MEDIUM_CO_WAN 0x0000000C -#define NDIS_MEDIUM_1394 0x0000000D - -#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 -#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 -#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 -#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 -#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 -#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 -#define NDIS_PACKET_TYPE_SMT 0x00000040 -#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 -#define NDIS_PACKET_TYPE_GROUP 0x00000100 -#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 -#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 -#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 - -#define NDIS_MEDIA_STATE_CONNECTED 0x00000000 -#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001 - -#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 -#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 -#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 -#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 -#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 -#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 -#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 -#define NDIS_MAC_OPTION_RESERVED 0x80000000 - -#endif /* _LINUX_NDIS_H */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h deleted file mode 100644 index b45860eeb..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h +++ /dev/null @@ -1,307 +0,0 @@ -/** - * \file rndis_protocol.h - * RNDIS Defines - * - * \author - * Colin O'Flynn - * - * \addtogroup usbstick - */ - -/* Copyright (c) 2008 Colin O'Flynn - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef _RNDIS_H -#define _RNDIS_H - -/** - \addtogroup RNDIS - @{ - */ - -#include - -#define RNDIS_MAJOR_VERSION 1 -#define RNDIS_MINOR_VERSION 0 - -#define RNDIS_STATUS_SUCCESS 0X00000000 -#define RNDIS_STATUS_FAILURE 0XC0000001 -#define RNDIS_STATUS_INVALID_DATA 0XC0010015 -#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB -#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B -#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C - - -/* Message set for Connectionless (802.3) Devices */ -#define REMOTE_NDIS_PACKET_MSG 0x00000001 -#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002 -#define REMOTE_NDIS_HALT_MSG 0X00000003 -#define REMOTE_NDIS_QUERY_MSG 0X00000004 -#define REMOTE_NDIS_SET_MSG 0X00000005 -#define REMOTE_NDIS_RESET_MSG 0X00000006 -#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007 -#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008 -#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002 -#define REMOTE_NDIS_QUERY_CMPLT 0X80000004 -#define REMOTE_NDIS_SET_CMPLT 0X80000005 -#define REMOTE_NDIS_RESET_CMPLT 0X80000006 -#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008 - -typedef uint32_t rndis_MessageType_t; -typedef uint32_t rndis_MessageLength_t; -typedef uint32_t rndis_RequestId_t; -typedef uint32_t rndis_MajorVersion_t; -typedef uint32_t rndis_MinorVersion_t; -typedef uint32_t rndis_MaxTransferSize_t; -typedef uint32_t rndis_Status_t; - - -/* Device Flags */ -#define RNDIS_DF_CONNECTIONLESS 0x00000001 -#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 -typedef uint32_t rndis_DeviceFlags_t; - -/* Mediums */ -#define RNDIS_MEDIUM_802_3 0x00000000 -typedef uint32_t rndis_Medium_t; - - -typedef uint32_t rndis_MaxPacketsPerTransfer_t; -typedef uint32_t rndis_PacketAlignmentFactor_t; -typedef uint32_t rndis_AfListOffset_t; -typedef uint32_t rndis_AfListSize_t; - -/*** Remote NDIS Generic Message type ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - } rndis_generic_msg_t; - - -/*** Remote NDIS Initialize Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_MajorVersion_t MajorVersion; - rndis_MinorVersion_t MinorVersion; - rndis_MaxTransferSize_t MaxTransferSize; - } rndis_initialize_msg_t; - -/* Response: */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Status_t Status; - rndis_MajorVersion_t MajorVersion; - rndis_MinorVersion_t MinorVersion; - rndis_DeviceFlags_t DeviceFlags; - rndis_Medium_t Medium; - rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer; - rndis_MaxTransferSize_t MaxTransferSize; - rndis_PacketAlignmentFactor_t PacketAlignmentFactor; - rndis_AfListOffset_t AfListOffset; - rndis_AfListSize_t AfListSize; - } rndis_initialize_cmplt_t; - - -/*** Remote NDIS Halt Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - } rndis_halt_msg_t; - -typedef uint32_t rndis_Oid_t; -typedef uint32_t rndis_InformationBufferLength_t; -typedef uint32_t rndis_InformationBufferOffset_t; -typedef uint32_t rndis_DeviceVcHandle_t; - -/*** Remote NDIS Query Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Oid_t Oid; - rndis_InformationBufferLength_t InformationBufferLength; - rndis_InformationBufferOffset_t InformationBufferOffset; - rndis_DeviceVcHandle_t DeviceVcHandle; - } rndis_query_msg_t; - -/* Response: */ - -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Status_t Status; - rndis_InformationBufferLength_t InformationBufferLength; - rndis_InformationBufferOffset_t InformationBufferOffset; - } rndis_query_cmplt_t; - -/*** Remote NDIS Set Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Oid_t Oid; - rndis_InformationBufferLength_t InformationBufferLength; - rndis_InformationBufferOffset_t InformationBufferOffset; - rndis_DeviceVcHandle_t DeviceVcHandle; - } rndis_set_msg_t; - -/* Response */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Status_t Status; - }rndis_set_cmplt_t; - -/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */ -typedef uint32_t rndis_ParameterNameOffset_t; -typedef uint32_t rndis_ParameterNameLength_t; -typedef uint32_t rndis_ParameterType_t; -typedef uint32_t rndis_ParameterValueOffset_t; -typedef uint32_t rndis_ParameterValueLength_t; - -#define PARAMETER_TYPE_STRING 2 -#define PARAMETER_TYPE_NUMERICAL 0 - -typedef struct{ - rndis_ParameterNameOffset_t ParameterNameOffset; - rndis_ParameterNameLength_t ParameterNameLength; - rndis_ParameterType_t ParameterType; - rndis_ParameterValueOffset_t ParameterValueOffset; - rndis_ParameterValueLength_t ParameterValueLength; - }rndis_config_parameter_t; - -typedef uint32_t rndis_Reserved_t; - -/*** Remote NDIS Soft Reset Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_Reserved_t Reserved; - } rndis_reset_msg_t; - -typedef uint32_t rndis_AddressingReset_t; - -/* Response: */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_Status_t Status; - rndis_AddressingReset_t AddressingReset; - } rndis_reset_cmplt_t; - -/*** Remote NDIS Indicate Status Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_Status_t Status; - rndis_Status_t StatusBufferLength; - rndis_Status_t StatusBufferOffset; - } rndis_indicate_status_t; - -typedef uint32_t rndis_DiagStatus_t; -typedef uint32_t rndis_ErrorOffset_t; - -typedef struct { - rndis_DiagStatus_t DiagStatus; - rndis_ErrorOffset_t ErrorOffset; - }rndis_diagnostic_info_t; - -/*** Remote NDIS Keepalive Message */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - }rndis_keepalive_msg_t; - -/* Response: */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Status_t Status; - }rndis_keepalive_cmplt_t; - -/*** Remote NDIS Data Packet ***/ - -typedef uint32_t rndis_DataOffset_t; -typedef uint32_t rndis_DataLength_t; -typedef uint32_t rndis_OOBDataOffset_t; -typedef uint32_t rndis_OOBDataLength_t; -typedef uint32_t rndis_NumOOBDataElements_t; -typedef uint32_t rndis_PerPacketInfoOffset_t; -typedef uint32_t rndis_PerPacketInfoLength_t; - -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_DataOffset_t DataOffset; - rndis_DataLength_t DataLength; - rndis_OOBDataOffset_t OOBDataOffset; - rndis_OOBDataLength_t OOBDataLength; - rndis_NumOOBDataElements_t NumOOBDataElements; - rndis_PerPacketInfoOffset_t PerPacketInfoOffset; - rndis_PerPacketInfoLength_t PerPacketInfoLength; - rndis_DeviceVcHandle_t DeviceVcHandle; - rndis_Reserved_t Reserved; - }rndis_data_packet_t; - -typedef uint32_t rndis_ClassInformationOffset_t; -typedef uint32_t rndis_Size_t; -typedef uint32_t rndis_Type_t; - -typedef struct{ - rndis_Size_t Size; - rndis_Type_t Type; - rndis_ClassInformationOffset_t ClassInformationType; - }rndis_OOB_packet_t; - -#include "ndis.h" - -typedef enum rnids_state_e { - rndis_uninitialized, - rndis_initialized, - rndis_data_initialized - } rndis_state_t; - -typedef struct { - uint32_t txok; - uint32_t rxok; - uint32_t txbad; - uint32_t rxbad; -} usb_eth_stat_t; - -#endif /* _RNDIS_H */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c deleted file mode 100644 index ee611c883..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - The original version of this code was lrndis/usbd_rndis_core.c from https://github.com/fetisov/lrndis - It has since been overhauled to suit this application -*/ - -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "class/net/net_device.h" -#include "rndis_protocol.h" -#include "netif/ethernet.h" - -#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */ -#define RNDIS_VENDOR "TinyUSB" /* NIC vendor name */ - -static const uint8_t *const station_hwaddr = tud_network_mac_address; -static const uint8_t *const permanent_hwaddr = tud_network_mac_address; - -static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 }; -static uint32_t oid_packet_filter = 0x0000000; -static rndis_state_t rndis_state; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t ndis_report[8] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - -static const uint32_t OIDSupportedList[] = -{ - OID_GEN_SUPPORTED_LIST, - OID_GEN_HARDWARE_STATUS, - OID_GEN_MEDIA_SUPPORTED, - OID_GEN_MEDIA_IN_USE, - OID_GEN_MAXIMUM_FRAME_SIZE, - OID_GEN_LINK_SPEED, - OID_GEN_TRANSMIT_BLOCK_SIZE, - OID_GEN_RECEIVE_BLOCK_SIZE, - OID_GEN_VENDOR_ID, - OID_GEN_VENDOR_DESCRIPTION, - OID_GEN_VENDOR_DRIVER_VERSION, - OID_GEN_CURRENT_PACKET_FILTER, - OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_PROTOCOL_OPTIONS, - OID_GEN_MAC_OPTIONS, - OID_GEN_MEDIA_CONNECT_STATUS, - OID_GEN_MAXIMUM_SEND_PACKETS, - OID_802_3_PERMANENT_ADDRESS, - OID_802_3_CURRENT_ADDRESS, - OID_802_3_MULTICAST_LIST, - OID_802_3_MAXIMUM_LIST_SIZE, - OID_802_3_MAC_OPTIONS -}; - -#define OID_LIST_LENGTH TU_ARRAY_SIZE(OIDSupportedList) -#define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32) - -static void *encapsulated_buffer; - -static void rndis_report(void) -{ - netd_report(ndis_report, sizeof(ndis_report)); -} - -static void rndis_query_cmplt32(int status, uint32_t data) -{ - rndis_query_cmplt_t *c; - c = (rndis_query_cmplt_t *)encapsulated_buffer; - c->MessageType = REMOTE_NDIS_QUERY_CMPLT; - c->MessageLength = sizeof(rndis_query_cmplt_t) + 4; - c->InformationBufferLength = 4; - c->InformationBufferOffset = 16; - c->Status = status; - memcpy(c + 1, &data, sizeof(data)); - rndis_report(); -} - -static void rndis_query_cmplt(int status, const void *data, int size) -{ - rndis_query_cmplt_t *c; - c = (rndis_query_cmplt_t *)encapsulated_buffer; - c->MessageType = REMOTE_NDIS_QUERY_CMPLT; - c->MessageLength = sizeof(rndis_query_cmplt_t) + size; - c->InformationBufferLength = size; - c->InformationBufferOffset = 16; - c->Status = status; - memcpy(c + 1, data, size); - rndis_report(); -} - -#define MAC_OPT NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \ - NDIS_MAC_OPTION_RECEIVE_SERIALIZED | \ - NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | \ - NDIS_MAC_OPTION_NO_LOOPBACK - -static const char *rndis_vendor = RNDIS_VENDOR; - -static void rndis_query(void) -{ - switch (((rndis_query_msg_t *)encapsulated_buffer)->Oid) - { - case OID_GEN_SUPPORTED_LIST: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, OIDSupportedList, 4 * OID_LIST_LENGTH); return; - case OID_GEN_VENDOR_DRIVER_VERSION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00001000); return; - case OID_802_3_CURRENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, station_hwaddr, 6); return; - case OID_802_3_PERMANENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, permanent_hwaddr, 6); return; - case OID_GEN_MEDIA_SUPPORTED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; - case OID_GEN_MEDIA_IN_USE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; - case OID_GEN_PHYSICAL_MEDIUM: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; - case OID_GEN_HARDWARE_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_GEN_LINK_SPEED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, RNDIS_LINK_SPEED / 100); return; - case OID_GEN_VENDOR_ID: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00FFFFFF); return; - case OID_GEN_VENDOR_DESCRIPTION: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, rndis_vendor, strlen(rndis_vendor) + 1); return; - case OID_GEN_CURRENT_PACKET_FILTER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, oid_packet_filter); return; - case OID_GEN_MAXIMUM_FRAME_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU - SIZEOF_ETH_HDR); return; - case OID_GEN_MAXIMUM_TOTAL_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; - case OID_GEN_TRANSMIT_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; - case OID_GEN_RECEIVE_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; - case OID_GEN_MEDIA_CONNECT_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIA_STATE_CONNECTED); return; - case OID_GEN_RNDIS_CONFIG_PARAMETER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_802_3_MAXIMUM_LIST_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 1); return; - case OID_802_3_MULTICAST_LIST: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; - case OID_802_3_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; - case OID_GEN_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, /*MAC_OPT*/ 0); return; - case OID_802_3_RCV_ERROR_ALIGNMENT: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_802_3_XMIT_ONE_COLLISION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_802_3_XMIT_MORE_COLLISIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_GEN_XMIT_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txok); return; - case OID_GEN_RCV_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxok); return; - case OID_GEN_RCV_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxbad); return; - case OID_GEN_XMIT_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txbad); return; - case OID_GEN_RCV_NO_BUFFER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - default: rndis_query_cmplt(RNDIS_STATUS_FAILURE, NULL, 0); return; - } -} - -#define INFBUF ((uint8_t *)&(m->RequestId) + m->InformationBufferOffset) - -static void rndis_handle_config_parm(const char *data, int keyoffset, int valoffset, int keylen, int vallen) -{ - (void)data; - (void)keyoffset; - (void)valoffset; - (void)keylen; - (void)vallen; -} - -static void rndis_packetFilter(uint32_t newfilter) -{ - (void)newfilter; -} - -static void rndis_handle_set_msg(void) -{ - rndis_set_cmplt_t *c; - rndis_set_msg_t *m; - rndis_Oid_t oid; - - c = (rndis_set_cmplt_t *)encapsulated_buffer; - m = (rndis_set_msg_t *)encapsulated_buffer; - - oid = m->Oid; - c->MessageType = REMOTE_NDIS_SET_CMPLT; - c->MessageLength = sizeof(rndis_set_cmplt_t); - c->Status = RNDIS_STATUS_SUCCESS; - - switch (oid) - { - /* Parameters set up in 'Advanced' tab */ - case OID_GEN_RNDIS_CONFIG_PARAMETER: - { - rndis_config_parameter_t *p; - char *ptr = (char *)m; - ptr += sizeof(rndis_generic_msg_t); - ptr += m->InformationBufferOffset; - p = (rndis_config_parameter_t *) ((void*) ptr); - rndis_handle_config_parm(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength); - } - break; - - /* Mandatory general OIDs */ - case OID_GEN_CURRENT_PACKET_FILTER: - memcpy(&oid_packet_filter, INFBUF, 4); - if (oid_packet_filter) - { - rndis_packetFilter(oid_packet_filter); - rndis_state = rndis_data_initialized; - } - else - { - rndis_state = rndis_initialized; - } - break; - - case OID_GEN_CURRENT_LOOKAHEAD: - break; - - case OID_GEN_PROTOCOL_OPTIONS: - break; - - /* Mandatory 802_3 OIDs */ - case OID_802_3_MULTICAST_LIST: - break; - - /* Power Managment: fails for now */ - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - case OID_PNP_ENABLE_WAKE_UP: - default: - c->Status = RNDIS_STATUS_FAILURE; - break; - } - - /* c->MessageID is same as before */ - rndis_report(); - return; -} - -void rndis_class_set_handler(uint8_t *data, int size) -{ - encapsulated_buffer = data; - (void)size; - - switch (((rndis_generic_msg_t *)encapsulated_buffer)->MessageType) - { - case REMOTE_NDIS_INITIALIZE_MSG: - { - rndis_initialize_cmplt_t *m; - m = ((rndis_initialize_cmplt_t *)encapsulated_buffer); - /* m->MessageID is same as before */ - m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; - m->MessageLength = sizeof(rndis_initialize_cmplt_t); - m->MajorVersion = RNDIS_MAJOR_VERSION; - m->MinorVersion = RNDIS_MINOR_VERSION; - m->Status = RNDIS_STATUS_SUCCESS; - m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; - m->Medium = RNDIS_MEDIUM_802_3; - m->MaxPacketsPerTransfer = 1; - m->MaxTransferSize = CFG_TUD_NET_MTU + sizeof(rndis_data_packet_t); - m->PacketAlignmentFactor = 0; - m->AfListOffset = 0; - m->AfListSize = 0; - rndis_state = rndis_initialized; - rndis_report(); - } - break; - - case REMOTE_NDIS_QUERY_MSG: - rndis_query(); - break; - - case REMOTE_NDIS_SET_MSG: - rndis_handle_set_msg(); - break; - - case REMOTE_NDIS_RESET_MSG: - { - rndis_reset_cmplt_t * m; - m = ((rndis_reset_cmplt_t *)encapsulated_buffer); - rndis_state = rndis_uninitialized; - m->MessageType = REMOTE_NDIS_RESET_CMPLT; - m->MessageLength = sizeof(rndis_reset_cmplt_t); - m->Status = RNDIS_STATUS_SUCCESS; - m->AddressingReset = 1; /* Make it look like we did something */ - /* m->AddressingReset = 0; - Windows halts if set to 1 for some reason */ - rndis_report(); - } - break; - - case REMOTE_NDIS_KEEPALIVE_MSG: - { - rndis_keepalive_cmplt_t * m; - m = (rndis_keepalive_cmplt_t *)encapsulated_buffer; - m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; - m->MessageLength = sizeof(rndis_keepalive_cmplt_t); - m->Status = RNDIS_STATUS_SUCCESS; - } - /* We have data to send back */ - rndis_report(); - break; - - default: - break; - } -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml deleted file mode 100644 index 331445024..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml +++ /dev/null @@ -1,14 +0,0 @@ -pkg.name: tinyusb -pkg.description: A silly USB stack for embedded -pkg.author: "Ha Thach " -pkg.homepage: "https://github.com/hathach/tinyusb" -pkg.keywords: - - usb - -pkg.type: sdk - -pkg.deps: - - "@apache-mynewt-core/kernel/os" - -pkg.include_dirs: - - src diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml deleted file mode 100644 index 21d092373..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml +++ /dev/null @@ -1,15 +0,0 @@ -repo.name: tinyusb -repo.versions: - "0.0.0": "master" - "0.5.0": "0.5.0" - "0.6.0": "0.6.0" - "0.7.0": "0.7.0" - "0.8.0": "0.8.0" - "0.9.0": "0.9.0" - "0.10.0": "0.10.0" - "0.10.1": "0.10.1" - "0.11.0": "0.11.0" - - "0-dev": "0.0.0" # master - "0-latest": "0.11.0" # latest stable release - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/sbom.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/sbom.yml new file mode 100644 index 000000000..f1e805b9c --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/sbom.yml @@ -0,0 +1,2 @@ +supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' +originator: 'Organization: Espressif Systems (Shanghai) CO LTD' diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename b/examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename deleted file mode 100644 index 6aea8579a..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename +++ /dev/null @@ -1,22 +0,0 @@ -# sdkconfig replacement configurations for deprecated options formatted as -# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION -CONFIG_USB_ENABLED CONFIG_TINYUSB -CONFIG_USB_DO_NOT_CREATE_TASK CONFIG_TINYUSB_NO_DEFAULT_TASK -CONFIG_USB_TASK_PRIORITY CONFIG_TINYUSB_TASK_PRIORITY -CONFIG_USB_DESC_USE_ESPRESSIF_VID CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID -CONFIG_USB_DESC_CUSTOM_VID CONFIG_TINYUSB_DESC_CUSTOM_VID -CONFIG_USB_DESC_USE_DEFAULT_PID CONFIG_TINYUSB_DESC_USE_DEFAULT_PID -CONFIG_USB_DESC_CUSTOM_PID CONFIG_TINYUSB_DESC_CUSTOM_PID -CONFIG_USB_DESC_BCDDEVICE CONFIG_TINYUSB_DESC_BCD_DEVICE -CONFIG_USB_DESC_MANUFACTURER_STRING CONFIG_TINYUSB_DESC_MANUFACTURER_STRING -CONFIG_USB_DESC_PRODUCT_STRING CONFIG_TINYUSB_DESC_PRODUCT_STRING -CONFIG_USB_DESC_SERIAL_STRING CONFIG_TINYUSB_DESC_SERIAL_STRING -CONFIG_USB_DESC_CDC_STRING CONFIG_TINYUSB_DESC_CDC_STRING -CONFIG_USB_DESC_MSC_STRING CONFIG_TINYUSB_DESC_MSC_STRING -CONFIG_USB_DESC_HID_STRING CONFIG_TINYUSB_DESC_HID_STRING -CONFIG_USB_MSC_ENABLED CONFIG_TINYUSB_MSC_ENABLED -CONFIG_USB_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE -CONFIG_USB_CDC_ENABLED CONFIG_TINYUSB_CDC_ENABLED -CONFIG_USB_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE -CONFIG_USB_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE -CONFIG_USB_DEBUG_LEVEL CONFIG_TINYUSB_DEBUG_LEVEL diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h deleted file mode 100644 index 6f9c1a6b5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h +++ /dev/null @@ -1,933 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_Audio Audio - * Currently only MIDI subclass is supported - * @{ */ - -#ifndef _TUSB_AUDIO_H__ -#define _TUSB_AUDIO_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/// Audio Device Class Codes - -/// A.2 - Audio Function Subclass Codes -typedef enum -{ - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, -} audio_function_subclass_type_t; - -/// A.3 - Audio Function Protocol Codes -typedef enum -{ - AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 -} audio_function_protocol_code_t; - -/// A.5 - Audio Interface Subclass Codes -typedef enum -{ - AUDIO_SUBCLASS_UNDEFINED = 0x00, - AUDIO_SUBCLASS_CONTROL , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming -} audio_subclass_type_t; - -/// A.6 - Audio Interface Protocol Codes -typedef enum -{ - AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 -} audio_interface_protocol_code_t; - -/// A.7 - Audio Function Category Codes -typedef enum -{ - AUDIO_FUNC_UNDEF = 0x00, - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C, - AUDIO_FUNC_OTHER = 0xFF, -} audio_function_code_t; - -/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AC_INTERFACE_HEADER = 0x01, - AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, -} audio_cs_ac_interface_subtype_t; - -/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, - AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, - AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, - AUDIO_CS_AS_INTERFACE_DECODER = 0x04, -} audio_cs_as_interface_subtype_t; - -/// A.11 - Effect Unit Effect Types -typedef enum -{ - AUDIO_EFFECT_TYPE_UNDEF = 0x00, - AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, - AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, - AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, - AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, -} audio_effect_unit_effect_type_t; - -/// A.12 - Processing Unit Process Types -typedef enum -{ - AUDIO_PROCESS_TYPE_UNDEF = 0x00, - AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, - AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, - AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, -} audio_processing_unit_process_type_t; - -/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, -} audio_cs_ep_subtype_t; - -/// A.14 - Audio Class-Specific Request Codes -typedef enum -{ - AUDIO_CS_REQ_UNDEF = 0x00, - AUDIO_CS_REQ_CUR = 0x01, - AUDIO_CS_REQ_RANGE = 0x02, - AUDIO_CS_REQ_MEM = 0x03, -} audio_cs_req_t; - -/// A.17 - Control Selector Codes - -/// A.17.1 - Clock Source Control Selectors -typedef enum -{ - AUDIO_CS_CTRL_UNDEF = 0x00, - AUDIO_CS_CTRL_SAM_FREQ = 0x01, - AUDIO_CS_CTRL_CLK_VALID = 0x02, -} audio_clock_src_control_selector_t; - -/// A.17.2 - Clock Selector Control Selectors -typedef enum -{ - AUDIO_CX_CTRL_UNDEF = 0x00, - AUDIO_CX_CTRL_CONTROL = 0x01, -} audio_clock_sel_control_selector_t; - -/// A.17.3 - Clock Multiplier Control Selectors -typedef enum -{ - AUDIO_CM_CTRL_UNDEF = 0x00, - AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, - AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, -} audio_clock_mul_control_selector_t; - -/// A.17.4 - Terminal Control Selectors -typedef enum -{ - AUDIO_TE_CTRL_UNDEF = 0x00, - AUDIO_TE_CTRL_COPY_PROTECT = 0x01, - AUDIO_TE_CTRL_CONNECTOR = 0x02, - AUDIO_TE_CTRL_OVERLOAD = 0x03, - AUDIO_TE_CTRL_CLUSTER = 0x04, - AUDIO_TE_CTRL_UNDERFLOW = 0x05, - AUDIO_TE_CTRL_OVERFLOW = 0x06, - AUDIO_TE_CTRL_LATENCY = 0x07, -} audio_terminal_control_selector_t; - -/// A.17.5 - Mixer Control Selectors -typedef enum -{ - AUDIO_MU_CTRL_UNDEF = 0x00, - AUDIO_MU_CTRL_MIXER = 0x01, - AUDIO_MU_CTRL_CLUSTER = 0x02, - AUDIO_MU_CTRL_UNDERFLOW = 0x03, - AUDIO_MU_CTRL_OVERFLOW = 0x04, - AUDIO_MU_CTRL_LATENCY = 0x05, -} audio_mixer_control_selector_t; - -/// A.17.6 - Selector Control Selectors -typedef enum -{ - AUDIO_SU_CTRL_UNDEF = 0x00, - AUDIO_SU_CTRL_SELECTOR = 0x01, - AUDIO_SU_CTRL_LATENCY = 0x02, -} audio_sel_control_selector_t; - -/// A.17.7 - Feature Unit Control Selectors -typedef enum -{ - AUDIO_FU_CTRL_UNDEF = 0x00, - AUDIO_FU_CTRL_MUTE = 0x01, - AUDIO_FU_CTRL_VOLUME = 0x02, - AUDIO_FU_CTRL_BASS = 0x03, - AUDIO_FU_CTRL_MID = 0x04, - AUDIO_FU_CTRL_TREBLE = 0x05, - AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, - AUDIO_FU_CTRL_AGC = 0x07, - AUDIO_FU_CTRL_DELAY = 0x08, - AUDIO_FU_CTRL_BASS_BOOST = 0x09, - AUDIO_FU_CTRL_LOUDNESS = 0x0A, - AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, - AUDIO_FU_CTRL_GAIN_PAD = 0x0C, - AUDIO_FU_CTRL_INVERTER = 0x0D, - AUDIO_FU_CTRL_UNDERFLOW = 0x0E, - AUDIO_FU_CTRL_OVERVLOW = 0x0F, - AUDIO_FU_CTRL_LATENCY = 0x10, -} audio_feature_unit_control_selector_t; - -/// A.17.8 Effect Unit Control Selectors - -/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors -typedef enum -{ - AUDIO_PE_CTRL_UNDEF = 0x00, - AUDIO_PE_CTRL_ENABLE = 0x01, - AUDIO_PE_CTRL_CENTERFREQ = 0x02, - AUDIO_PE_CTRL_QFACTOR = 0x03, - AUDIO_PE_CTRL_GAIN = 0x04, - AUDIO_PE_CTRL_UNDERFLOW = 0x05, - AUDIO_PE_CTRL_OVERFLOW = 0x06, - AUDIO_PE_CTRL_LATENCY = 0x07, -} audio_parametric_equalizer_control_selector_t; - -/// A.17.8.2 Reverberation Effect Unit Control Selectors -typedef enum -{ - AUDIO_RV_CTRL_UNDEF = 0x00, - AUDIO_RV_CTRL_ENABLE = 0x01, - AUDIO_RV_CTRL_TYPE = 0x02, - AUDIO_RV_CTRL_LEVEL = 0x03, - AUDIO_RV_CTRL_TIME = 0x04, - AUDIO_RV_CTRL_FEEDBACK = 0x05, - AUDIO_RV_CTRL_PREDELAY = 0x06, - AUDIO_RV_CTRL_DENSITY = 0x07, - AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, - AUDIO_RV_CTRL_UNDERFLOW = 0x09, - AUDIO_RV_CTRL_OVERFLOW = 0x0A, - AUDIO_RV_CTRL_LATENCY = 0x0B, -} audio_reverberation_effect_control_selector_t; - -/// A.17.8.3 Modulation Delay Effect Unit Control Selectors -typedef enum -{ - AUDIO_MD_CTRL_UNDEF = 0x00, - AUDIO_MD_CTRL_ENABLE = 0x01, - AUDIO_MD_CTRL_BALANCE = 0x02, - AUDIO_MD_CTRL_RATE = 0x03, - AUDIO_MD_CTRL_DEPTH = 0x04, - AUDIO_MD_CTRL_TIME = 0x05, - AUDIO_MD_CTRL_FEEDBACK = 0x06, - AUDIO_MD_CTRL_UNDERFLOW = 0x07, - AUDIO_MD_CTRL_OVERFLOW = 0x08, - AUDIO_MD_CTRL_LATENCY = 0x09, -} audio_modulation_delay_control_selector_t; - -/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors -typedef enum -{ - AUDIO_DR_CTRL_UNDEF = 0x00, - AUDIO_DR_CTRL_ENABLE = 0x01, - AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, - AUDIO_DR_CTRL_MAXAMPL = 0x03, - AUDIO_DR_CTRL_THRESHOLD = 0x04, - AUDIO_DR_CTRL_ATTACK_TIME = 0x05, - AUDIO_DR_CTRL_RELEASE_TIME = 0x06, - AUDIO_DR_CTRL_UNDERFLOW = 0x07, - AUDIO_DR_CTRL_OVERFLOW = 0x08, - AUDIO_DR_CTRL_LATENCY = 0x09, -} audio_dynamic_range_compression_control_selector_t; - -/// A.17.9 Processing Unit Control Selectors - -/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors -typedef enum -{ - AUDIO_UD_CTRL_UNDEF = 0x00, - AUDIO_UD_CTRL_ENABLE = 0x01, - AUDIO_UD_CTRL_MODE_SELECT = 0x02, - AUDIO_UD_CTRL_CLUSTER = 0x03, - AUDIO_UD_CTRL_UNDERFLOW = 0x04, - AUDIO_UD_CTRL_OVERFLOW = 0x05, - AUDIO_UD_CTRL_LATENCY = 0x06, -} audio_up_down_mix_control_selector_t; - -/// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors -typedef enum -{ - AUDIO_DP_CTRL_UNDEF = 0x00, - AUDIO_DP_CTRL_ENABLE = 0x01, - AUDIO_DP_CTRL_MODE_SELECT = 0x02, - AUDIO_DP_CTRL_CLUSTER = 0x03, - AUDIO_DP_CTRL_UNDERFLOW = 0x04, - AUDIO_DP_CTRL_OVERFLOW = 0x05, - AUDIO_DP_CTRL_LATENCY = 0x06, -} audio_dolby_prologic_control_selector_t; - -/// A.17.9.3 Stereo Extender Processing Unit Control Selectors -typedef enum -{ - AUDIO_ST_EXT_CTRL_UNDEF = 0x00, - AUDIO_ST_EXT_CTRL_ENABLE = 0x01, - AUDIO_ST_EXT_CTRL_WIDTH = 0x02, - AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, - AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, - AUDIO_ST_EXT_CTRL_LATENCY = 0x05, -} audio_stereo_extender_control_selector_t; - -/// A.17.10 Extension Unit Control Selectors -typedef enum -{ - AUDIO_XU_CTRL_UNDEF = 0x00, - AUDIO_XU_CTRL_ENABLE = 0x01, - AUDIO_XU_CTRL_CLUSTER = 0x02, - AUDIO_XU_CTRL_UNDERFLOW = 0x03, - AUDIO_XU_CTRL_OVERFLOW = 0x04, - AUDIO_XU_CTRL_LATENCY = 0x05, -} audio_extension_unit_control_selector_t; - -/// A.17.11 AudioStreaming Interface Control Selectors -typedef enum -{ - AUDIO_AS_CTRL_UNDEF = 0x00, - AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, - AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, - AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, -} audio_audiostreaming_interface_control_selector_t; - -/// A.17.12 Encoder Control Selectors -typedef enum -{ - AUDIO_EN_CTRL_UNDEF = 0x00, - AUDIO_EN_CTRL_BIT_RATE = 0x01, - AUDIO_EN_CTRL_QUALITY = 0x02, - AUDIO_EN_CTRL_VBR = 0x03, - AUDIO_EN_CTRL_TYPE = 0x04, - AUDIO_EN_CTRL_UNDERFLOW = 0x05, - AUDIO_EN_CTRL_OVERFLOW = 0x06, - AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, - AUDIO_EN_CTRL_PARAM1 = 0x08, - AUDIO_EN_CTRL_PARAM2 = 0x09, - AUDIO_EN_CTRL_PARAM3 = 0x0A, - AUDIO_EN_CTRL_PARAM4 = 0x0B, - AUDIO_EN_CTRL_PARAM5 = 0x0C, - AUDIO_EN_CTRL_PARAM6 = 0x0D, - AUDIO_EN_CTRL_PARAM7 = 0x0E, - AUDIO_EN_CTRL_PARAM8 = 0x0F, -} audio_encoder_control_selector_t; - -/// A.17.13 Decoder Control Selectors - -/// A.17.13.1 MPEG Decoder Control Selectors -typedef enum -{ - AUDIO_MPD_CTRL_UNDEF = 0x00, - AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, - AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, - AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, - AUDIO_MPD_CTRL_DYN_RANGE = 0x04, - AUDIO_MPD_CTRL_SCALING = 0x05, - AUDIO_MPD_CTRL_HILO_SCALING = 0x06, - AUDIO_MPD_CTRL_UNDERFLOW = 0x07, - AUDIO_MPD_CTRL_OVERFLOW = 0x08, - AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, -} audio_MPEG_decoder_control_selector_t; - -/// A.17.13.2 AC-3 Decoder Control Selectors -typedef enum -{ - AUDIO_AD_CTRL_UNDEF = 0x00, - AUDIO_AD_CTRL_MODE = 0x01, - AUDIO_AD_CTRL_DYN_RANGE = 0x02, - AUDIO_AD_CTRL_SCALING = 0x03, - AUDIO_AD_CTRL_HILO_SCALING = 0x04, - AUDIO_AD_CTRL_UNDERFLOW = 0x05, - AUDIO_AD_CTRL_OVERFLOW = 0x06, - AUDIO_AD_CTRL_DECODER_ERROR = 0x07, -} audio_AC3_decoder_control_selector_t; - -/// A.17.13.3 WMA Decoder Control Selectors -typedef enum -{ - AUDIO_WD_CTRL_UNDEF = 0x00, - AUDIO_WD_CTRL_UNDERFLOW = 0x01, - AUDIO_WD_CTRL_OVERFLOW = 0x02, - AUDIO_WD_CTRL_DECODER_ERROR = 0x03, -} audio_WMA_decoder_control_selector_t; - -/// A.17.13.4 DTS Decoder Control Selectors -typedef enum -{ - AUDIO_DD_CTRL_UNDEF = 0x00, - AUDIO_DD_CTRL_UNDERFLOW = 0x01, - AUDIO_DD_CTRL_OVERFLOW = 0x02, - AUDIO_DD_CTRL_DECODER_ERROR = 0x03, -} audio_DTS_decoder_control_selector_t; - -/// A.17.14 Endpoint Control Selectors -typedef enum -{ - AUDIO_EP_CTRL_UNDEF = 0x00, - AUDIO_EP_CTRL_PITCH = 0x01, - AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, - AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, -} audio_EP_control_selector_t; - -/// Terminal Types - -/// 2.1 - Audio Class-Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, -} audio_terminal_type_t; - -/// 2.2 - Audio Class-Input Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, -} audio_terminal_input_type_t; - -/// 2.3 - Audio Class-Output Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, -} audio_terminal_output_type_t; - -/// Rest is yet to be implemented - -/// Additional Audio Device Class Codes - Source: Audio Data Formats - -/// A.1 - Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; - -// A.2.1 - Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), - AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), - AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, -} audio_data_format_type_I_t; - -/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification - -/// Audio Class-Control Values UAC2 -typedef enum -{ - AUDIO_CTRL_NONE = 0x00, ///< No Host access - AUDIO_CTRL_R = 0x01, ///< Host read access only - AUDIO_CTRL_RW = 0x03, ///< Host read write access -} audio_control_t; - -/// Audio Class-Specific AC Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, -} audio_cs_ac_interface_control_pos_t; - -/// Audio Class-Specific AS Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, - AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, -} audio_cs_as_interface_control_pos_t; - -/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, - AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, -} audio_cs_as_iso_data_ep_attribute_t; - -/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, -} audio_cs_as_iso_data_ep_control_pos_t; - -/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, -} audio_cs_as_iso_data_ep_lock_delay_unit_t; - -/// Audio Class-Clock Source Attributes UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, - AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, - AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, - AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, - AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, -} audio_clock_source_attribute_t; - -/// Audio Class-Clock Source Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, - AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, -} audio_clock_source_control_pos_t; - -/// Audio Class-Clock Selector Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, -} audio_clock_selector_control_pos_t; - -/// Audio Class-Clock Multiplier Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, - AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, -} audio_clock_multiplier_control_pos_t; - -/// Audio Class-Input Terminal Controls UAC2 -typedef enum -{ - AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, - AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, - AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, -} audio_terminal_input_control_pos_t; - -/// Audio Class-Output Terminal Controls UAC2 -typedef enum -{ - AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, - AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, -} audio_terminal_output_control_pos_t; - -/// Audio Class-Feature Unit Controls UAC2 -typedef enum -{ - AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, - AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, - AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, - AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, - AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, - AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, - AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, - AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, - AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, - AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, - AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, - AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, - AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, -} audio_feature_unit_control_pos_t; - -/// Audio Class-Audio Channel Configuration UAC2 -typedef enum -{ - AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, - AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, - AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, - AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, - AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, - AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, - AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, - AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, - AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, - AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, - AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, - AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, -} audio_channel_config_t; - -/// AUDIO Channel Cluster Descriptor (4.1) -typedef struct TU_ATTR_PACKED { - uint8_t bNrChannels; ///< Number of channels currently connected. - audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. - uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. -} audio_desc_channel_cluster_t; - -/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 9. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. - uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). - uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. - uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. - uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. -} audio_desc_cs_ac_interface_t; - -/// AUDIO Clock Source Descriptor (4.7.2.1) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. - uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. - uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. -} audio_desc_clock_source_t; - -/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. - uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. - uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. -} audio_desc_clock_selector_t; - -/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins -#define audio_desc_clock_selector_n_t(source_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bClockID ; \ - uint8_t bNrInPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID ; \ - } sourceID[source_num] ; \ - uint8_t bmControls ; \ - uint8_t iClockSource ; \ -} - -/// AUDIO Clock Multiplier Descriptor (4.7.2.3) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. - uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. -} audio_desc_clock_multiplier_t; - -/// AUDIO Input Terminal Descriptor(4.7.2.4) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. - uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. - uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. - uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. -} audio_desc_input_terminal_t; - -/// AUDIO Output Terminal Descriptor(4.7.2.5) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. - uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. - uint16_t bmControls ; ///< See: audio_terminal_output_type_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. -} audio_desc_output_terminal_t; - -/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. - uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. - struct TU_ATTR_PACKED { - uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. - } controls[2] ; - uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. -} audio_desc_feature_unit_t; - -/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels -#define audio_desc_feature_unit_n_t(ch_num)\ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; /* 6+(ch_num+1)*4 */\ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bUnitID ; \ - uint8_t bSourceID ; \ - struct TU_ATTR_PACKED { \ - uint32_t bmaControls ; \ - } controls[ch_num+1] ; \ - uint8_t iTerminal ; \ -} - -/// AUDIO Class-Specific AS Interface Descriptor(4.9.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. - uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. - uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. - uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. - uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. -} audio_desc_cs_as_interface_t; - -/// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. - uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. - uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. -} audio_desc_type_I_format_t; - -/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. - uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. - uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. - uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. - uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. -} audio_desc_cs_as_iso_data_ep_t; - -// 5.2.2 Control Request Layout -typedef struct TU_ATTR_PACKED -{ - union - { - struct TU_ATTR_PACKED - { - uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. - uint8_t type : 2; ///< Request type tusb_request_type_t. - uint8_t direction : 1; ///< Direction type. tusb_dir_t - } bmRequestType_bit; - - uint8_t bmRequestType; - }; - - uint8_t bRequest; ///< Request type audio_cs_req_t - uint8_t bChannelNumber; - uint8_t bControlSelector; - union - { - uint8_t bInterface; - uint8_t bEndpoint; - }; - uint8_t bEntityID; - uint16_t wLength; -} audio_control_request_t; - -//// 5.2.3 Control Request Parameter Block Layout - -// 5.2.3.1 1-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_1_t; - -// 5.2.3.2 2-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_2_t; - -// 5.2.3.3 4-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_4_t; - -// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like -// 5.2.3.1 1-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_1_t; - -// 5.2.3.2 2-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_2_t; - -// 5.2.3.3 4-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_4_t; - -// 5.2.3.1 1-byte Control RANGE Parameter Block -#define audio_control_range_1_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ -} - -/// 5.2.3.2 2-byte Control RANGE Parameter Block -#define audio_control_range_2_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} - -// 5.2.3.3 4-byte Control RANGE Parameter Block -#define audio_control_range_4_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c deleted file mode 100644 index d21980060..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c +++ /dev/null @@ -1,2294 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Reinhard Panhuber, Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* - * This driver supports at most one out EP, one in EP, one control EP, and one feedback EP and one alternative interface other than zero. Hence, only one input terminal and one output terminal are support, if you need more adjust the driver! - * It supports multiple TX and RX channels. - * - * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. - * - * There are three data flow structures currently implemented, where at least one SW-FIFO is used to decouple the asynchronous processes MCU vs. host - * - * 1. Input data -> SW-FIFO -> MCU USB - * - * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_xfer_fifo() is available) - * - * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB - * - * In case the target MCU can not handle a SW-FIFO, a linear buffer is used. This uses the default function dcd_edpt_xfer(). In this case more memory is required. - * - * 3. (Input data 1 | Input data 2 | ... | Input data N) -> (SW-FIFO 1 | SW-FIFO 2 | ... | SW-FIFO N) -> Linear buffer -> MCU USB - * - * This case is used if you have more channels which need to be combined into one stream. Every channel has its own SW-FIFO. All data is encoded into an Linear buffer. - * - * The same holds in the RX case. - * - * */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "audio_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Use ring buffer if it's available, some MCUs need extra RAM requirements -#ifndef TUD_AUDIO_PREFER_RING_BUFFER -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX -#define TUD_AUDIO_PREFER_RING_BUFFER 0 -#else -#define TUD_AUDIO_PREFER_RING_BUFFER 1 -#endif -#endif - -// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer -// is available or driver is would need to be changed dramatically - -// Only STM32 synopsys and dcd_transdimension use non-linear buffer for now -// Synopsys detection copied from dcd_synopsys.c (refactor later on) -#if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ - defined (STM32F107xB) || defined (STM32F107xC) -#define STM32F1_SYNOPSYS -#endif - -#if defined (STM32L475xx) || defined (STM32L476xx) || \ - defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ - defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ - defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) -#define STM32L4_SYNOPSYS -#endif - -#if (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ - CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_RX63X || \ - CFG_TUSB_MCU == OPT_MCU_RX65X || \ - CFG_TUSB_MCU == OPT_MCU_RX72N || \ - CFG_TUSB_MCU == OPT_MCU_GD32VF103 || \ - CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_MSP432E4 -#if TUD_AUDIO_PREFER_RING_BUFFER -#define USE_LINEAR_BUFFER 0 -#else -#define USE_LINEAR_BUFFER 1 -#endif -#else -#define USE_LINEAR_BUFFER 1 -#endif - -// Declaration of buffers - -// Check for maximum supported numbers -#if CFG_TUD_AUDIO > 3 -#error Maximum number of audio functions restricted to three! -#endif - -// EP IN software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -// Linear buffer TX in case: -// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - -// EP OUT software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -// Linear buffer RX in case: -// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - -// Control buffers -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; -#if CFG_TUD_AUDIO > 1 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; -#endif -#if CFG_TUD_AUDIO > 2 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; -#endif - -// Active alternate setting of interfaces -uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; -#endif - -// Software encoding/decoding support FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; -tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; -tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; -tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; -tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; -tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; -tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif -#endif - -typedef struct -{ - uint8_t rhport; - uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - uint8_t ep_in; // TX audio data EP. - uint16_t ep_in_sz; // Current size of TX EP - uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - uint8_t ep_out; // Incoming (into uC) audio data EP. - uint16_t ep_out_sz; // Current size of RX EP - uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb; // Feedback EP. -#endif - -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - uint8_t ep_int_ctr; // Audio control interrupt EP. -#endif - - /*------------- From this point, data is not cleared by bus reset -------------*/ - - uint16_t desc_length; // Length of audio function descriptor - - // Buffer for control requests - uint8_t * ctrl_buf; - uint8_t ctrl_buf_sz; - - // Current active alternate settings - uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! - - // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t ep_out_ff; -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t ep_in_ff; -#endif - - // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; -#endif - - // Decoding parameters - parameters are set when alternate AS interface is set by host - // Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - audio_format_type_t format_type_rx; - uint8_t n_channels_rx; - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio_data_format_type_I_t format_type_I_rx; - uint8_t n_bytes_per_sampe_rx; - uint8_t n_channels_per_ff_rx; - uint8_t n_ff_used_rx; -#endif -#endif - - // Encoding parameters - parameters are set when alternate AS interface is set by host -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - audio_format_type_t format_type_tx; - uint8_t n_channels_tx; - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio_data_format_type_I_t format_type_I_tx; - uint8_t n_bytes_per_sampe_tx; - uint8_t n_channels_per_ff_tx; - uint8_t n_ff_used_tx; -#endif -#endif - - // Support FIFOs for software encoding and decoding -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t * rx_supp_ff; - uint8_t n_rx_supp_ff; - uint16_t rx_supp_ff_sz_max; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t * tx_supp_ff; - uint8_t n_tx_supp_ff; - uint16_t tx_supp_ff_sz_max; -#endif - - // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - uint8_t * lin_buf_out; -#define USE_LINEAR_BUFFER_RX 1 -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) - uint8_t * lin_buf_in; -#define USE_LINEAR_BUFFER_TX 1 -#endif - -} audiod_function_t; - -#ifndef USE_LINEAR_BUFFER_TX -#define USE_LINEAR_BUFFER_TX 0 -#endif - -#ifndef USE_LINEAR_BUFFER_RX -#define USE_LINEAR_BUFFER_RX 0 -#endif - -#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); -#endif - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t* audio); -#endif - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio); -#endif - -static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); - -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id); -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); -static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); - -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); - -static inline uint8_t tu_desc_subtype(void const* desc) -{ - return ((uint8_t const*) desc)[2]; -} -#endif - -bool tud_audio_n_mounted(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO); - audiod_function_t* audio = &_audiod_fct[func_id]; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (audio->ep_out == 0) return false; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (audio->ep_in == 0) return false; -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - if (audio->ep_int_ctr == 0) return false; -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->ep_fb == 0) return false; -#endif - - return true; -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -uint16_t tud_audio_n_available(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_count(&_audiod_fct[func_id].ep_out_ff); -} - -uint16_t tud_audio_n_read(uint8_t func_id, void* buffer, uint16_t bufsize) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_read_n(&_audiod_fct[func_id].ep_out_ff, buffer, bufsize); -} - -bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); -} - -tu_fifo_t* tud_audio_n_get_ep_out_ff(uint8_t func_id) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_out_ff; - return NULL; -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -// Delete all content in the support RX FIFOs -bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); -} - -tu_fifo_t* tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff) return &_audiod_fct[func_id].rx_supp_ff[ff_idx]; - return NULL; -} -#endif - -// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_DECODING = 0. - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) -{ - uint8_t idxItf; - uint8_t const *dummy2; - uint8_t idx_audio_fct = 0; - - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); - } - - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - - switch (audio->format_type_rx) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_tx) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); - break; - - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - - // Prepare for next transmission - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); - -#else - -#if USE_LINEAR_BUFFER_RX - // Data currently is in linear buffer, copy into EP OUT FIFO - TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); - - // Schedule for next receive - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); -#else - // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); -#endif - -#endif - - // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - - return true; -} - -#endif //CFG_TUD_AUDIO_ENABLE_EP_OUT - -// The following functions are used in case CFG_TUD_AUDIO_ENABLE_DECODING != 0 -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - -// Decoding according to 2.3.1.5 Audio Streams - -// Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) -{ - - // This function is an optimized version of - // while((uint8_t *)dst < dst_end) - // { - // memcpy(dst, src, nBytesToCopy); - // dst = (uint8_t *)dst + nBytesToCopy; - // src += nBytesToCopy * n_ff_used; - // } - - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - switch (nBytesToCopy) - { - case 1: - while((uint8_t *)dst < dst_end) - { - *(uint8_t *)dst++ = *src; - src += n_ff_used; - } - break; - - case 2: - while((uint8_t *)dst < dst_end) - { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - dst += 2; - src += 2 * n_ff_used; - } - break; - - case 3: - while((uint8_t *)dst < dst_end) - { - // memcpy(dst, src, 3); - // dst = (uint8_t *)dst + 3; - // src += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - - src += 3 * (n_ff_used - 1); - } - break; - - case 4: - while((uint8_t *)dst < dst_end) - { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; - dst += 4; - src += 4 * n_ff_used; - } - break; - } - - return src; -} - -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) -{ - (void) rhport; - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_rx; - uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; - uint8_t cnt_ff; - - // Decode - uint8_t * src; - uint8_t * dst_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) - { - tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) - { - info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); - src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used); - - // Handle wrapped part of FIFO - info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); - if (info.len_wrap != 0) - { - dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used); - } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it - // TU_VERIFY(cnt != n_bytes); - - return true; -} -#endif //CFG_TUD_AUDIO_ENABLE_DECODING - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -/** - * \brief Write data to EP in buffer - * - * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). - * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. - * - * \param[in] func_id: Index of audio function interface - * \param[in] data: Pointer to data array to be copied from - * \param[in] len: # of array elements to copy - * \return Number of bytes actually written - */ -uint16_t tud_audio_n_write(uint8_t func_id, const void * data, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len); -} - -bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Delete all content in the EP IN FIFO -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); -} - -tu_fifo_t* tud_audio_n_get_ep_in_ff(uint8_t func_id) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_in_ff; - return NULL; -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN - -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - audiod_function_t* audio = &_audiod_fct[func_id]; - - uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); - - TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); - - n_bytes_copied -= tu_fifo_count(&audio->tx_supp_ff[0]); - n_bytes_copied = n_bytes_copied*audio->tx_supp_ff[0].item_size; - - return n_bytes_copied; -} - -bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); -} - -tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff) return &_audiod_fct[func_id].tx_supp_ff[ff_idx]; - return NULL; -} - -#endif - - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - -// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user -uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr)); - - // Check length - TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); - - memcpy(_audiod_fct[func_id].ep_int_ctr_buf, buffer, len); - - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr, _audiod_fct[func_id].ep_int_ctr_buf, len)); - - return true; -} - -#endif - - -// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. - -// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) -{ - uint8_t idxItf; - uint8_t const *dummy2; - - uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); - - // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications - if (audio->alt_setting[idxItf] == 0) return false; - - // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or - // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - // Send everything in ISO EP FIFO - uint16_t n_bytes_tx; - - // If support FIFOs are used, encode and schedule transmit -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN - switch (audio->format_type_tx) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_tx) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - - n_bytes_tx = audiod_encode_type_I_pcm(rhport, audio); - break; - - default: - // YOUR ENCODING IS REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - -#else - // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule - - n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO - -#if USE_LINEAR_BUFFER_TX - tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); -#else - // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); -#endif - -#endif - - // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - return true; -} - -#endif //CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -// Take samples from the support buffer and encode them into the IN EP software FIFO -// Returns number of bytes written into linear buffer - -/* 2.3.1.7.1 PCM Format -The PCM (Pulse Coded Modulation) format is the most commonly used audio format to represent audio -data streams. The audio data is not compressed and uses a signed two’s-complement fixed point format. It -is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused -bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the -range [-1, +1) - */ - -/* - * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples - * in the support FIFOs according to 2.3.1.5 Audio Streams. It does not control justification (left or right) and - * does not change the number of bytes per sample. - * */ - -// Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) -{ - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - switch (nBytesToCopy) - { - case 1: - while(src < src_end) - { - *dst = *src++; - dst += n_ff_used; - } - break; - - case 2: - while(src < src_end) - { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - src += 2; - dst += 2 * n_ff_used; - } - break; - - case 3: - while(src < src_end) - { - // memcpy(dst, src, 3); - // src = (uint8_t *)src + 3; - // dst += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - - dst += 3 * (n_ff_used - 1); - } - break; - - case 4: - while(src < src_end) - { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; - src += 4; - dst += 4 * n_ff_used; - } - break; - } - - return dst; -} - -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio) -{ - // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap - // This is ensured within set_interface, where the FIFOs are reconfigured according to this size - - // We encode directly into IN EP's linear buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_tx; - uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; - uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes - uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); - uint8_t cnt_ff; - - for (cnt_ff = 1; cnt_ff < n_ff_used; cnt_ff++) - { - uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); - if (count < nBytesPerFFToSend) - { - nBytesPerFFToSend = count; - } - } - - // Check if there is enough - if (nBytesPerFFToSend == 0) return 0; - - // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); - - // Round to full number of samples (flooring) - nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; - - // Encode - uint8_t * dst; - uint8_t * src_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) - { - dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - - tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) - { - info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length - src_end = (uint8_t *)info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used); - - // Limit up to desired length - info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); - - // Handle wrapped part of FIFO - if (info.len_wrap != 0) - { - src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used); - } - - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - return nBytesPerFFToSend * n_ff_used; -} -#endif //CFG_TUD_AUDIO_ENABLE_ENCODING - -// This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) -{ - return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); -} -#endif - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void audiod_init(void) -{ - tu_memclr(_audiod_fct, sizeof(_audiod_fct)); - - for(uint8_t i=0; ictrl_buf = ctrl_buf_1; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; - break; -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 - case 1: - audio->ctrl_buf = ctrl_buf_2; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 - case 2: - audio->ctrl_buf = ctrl_buf_3; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; - break; -#endif - } - - // Initialize active alternate interface buffers - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 - case 0: - audio->alt_setting = alt_setting_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 - case 1: - audio->alt_setting = alt_setting_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 - case 2: - audio->alt_setting = alt_setting_3; - break; -#endif - } - - // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - case 0: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - case 1: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_2), NULL); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - case 2: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_3), NULL); -#endif - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - - // Initialize linear buffers -#if USE_LINEAR_BUFFER_TX - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 - case 0: - audio->lin_buf_in = lin_buf_in_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 - case 1: - audio->lin_buf_in = lin_buf_in_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 - case 2: - audio->lin_buf_in = lin_buf_in_3; - break; -#endif - } -#endif // USE_LINEAR_BUFFER_TX - - // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - case 0: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_1)); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - case 1: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_2)); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - case 2: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_3)); -#endif - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - - // Initialize linear buffers -#if USE_LINEAR_BUFFER_RX - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 - case 0: - audio->lin_buf_out = lin_buf_out_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 - case 1: - audio->lin_buf_out = lin_buf_out_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 - case 2: - audio->lin_buf_out = lin_buf_out_3; - break; -#endif - } -#endif // USE_LINEAR_BUFFER_TX - - // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->tx_supp_ff = tx_supp_ff_1; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->tx_supp_ff = tx_supp_ff_2; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->tx_supp_ff = tx_supp_ff_3; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX; - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - - // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->rx_supp_ff = rx_supp_ff_1; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->rx_supp_ff = rx_supp_ff_2; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->rx_supp_ff = rx_supp_ff_3; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX; - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - } -} - -void audiod_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; iep_in_ff); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_clear(&audio->ep_out_ff); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } -#endif - } -} - -uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) max_len; - - TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); - - // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); - - // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted - if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed - { - TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); - } - - // Alternate setting MUST be zero - this check can be omitted - TU_VERIFY(itf_desc->bAlternateSetting == 0); - - // Find available audio driver interface - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (!_audiod_fct[i].p_desc) - { - _audiod_fct[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one - _audiod_fct[i].rhport = rhport; - - // Setup descriptor lengths - switch (i) - { - case 0: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_1_DESC_LEN; - break; -#if CFG_TUD_AUDIO > 1 - case 1: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; - break; -#endif -#if CFG_TUD_AUDIO > 2 - case 2: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; - break; -#endif - } - - break; - } - } - - // Verify we found a free one - TU_ASSERT( i < CFG_TUD_AUDIO ); - - // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor - - return drv_len; -} - -static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) -{ - uint8_t const itf = tu_u16_low(p_request->wIndex); - - // Find index of audio streaming interface - uint8_t func_id, idxItf; - uint8_t const *dummy; - - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[func_id].alt_setting[idxItf], 1)); - - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[func_id].alt_setting[idxItf]); - - return true; -} - -static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - // Here we need to do the following: - - // 1. Find the audio driver assigned to the given interface to be set - // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. - // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching - - // 2. Close EPs which are currently open - // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them - - // 3. Open new EP - - uint8_t const itf = tu_u16_low(p_request->wIndex); - uint8_t const alt = tu_u16_low(p_request->wValue); - - TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); - - // Find index of audio streaming interface and index of interface - uint8_t func_id, idxItf; - uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc)); - - audiod_function_t* audio = &_audiod_fct[func_id]; - - // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (audio->ep_in_as_intf_num == itf) - { - audio->ep_in_as_intf_num = 0; - usbd_edpt_close(rhport, audio->ep_in); - - // Clear FIFOs, since data is no longer valid -#if !CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_clear(&audio->ep_in_ff); -#else - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } -#endif - - // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - - audio->ep_in = 0; // Necessary? - - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (audio->ep_out_as_intf_num == itf) - { - audio->ep_out_as_intf_num = 0; - usbd_edpt_close(rhport, audio->ep_out); - - // Clear FIFOs, since data is no longer valid -#if !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_clear(&audio->ep_out_ff); -#else - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } -#endif - - // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - - audio->ep_out = 0; // Necessary? - - // Close corresponding feedback EP -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - usbd_edpt_close(rhport, audio->ep_fb); - audio->ep_fb = 0; // Necessary? -#endif - } -#endif - - // Save current alternative interface setting - audio->alt_setting[idxItf] = alt; - - // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface - // Get pointer at end - uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // p_desc starts at required interface with alternate setting zero - while (p_desc < p_desc_end) - { - // Find correct interface - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) - { -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING - uint8_t const * p_desc_parse_for_params = p_desc; -#endif - // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary - uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; - while (foundEPs < nEps && p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { - tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); - - uint8_t const ep_addr = desc_ep->bEndpointAddress; - - //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! - usbd_edpt_clear_stall(rhport, ep_addr); - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00) // Check if usage is data EP - { - // Save address - audio->ep_in = ep_addr; - audio->ep_in_as_intf_num = itf; - audio->ep_in_sz = tu_edpt_packet_size(desc_ep); - - // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters -#if CFG_TUD_AUDIO_ENABLE_ENCODING - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - const uint16_t active_fifo_depth = (audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx; - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_tx = audio->n_channels_tx / audio->n_channels_per_ff_tx; - TU_ASSERT( audio->n_ff_used_tx <= audio->n_tx_supp_ff ); -#endif - -#endif - // Invoke callback - can be used to trigger data sampling if not already running - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - - // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded - // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary - { - // Save address - audio->ep_out = ep_addr; - audio->ep_out_as_intf_num = itf; - audio->ep_out_sz = tu_edpt_packet_size(desc_ep); - -#if CFG_TUD_AUDIO_ENABLE_DECODING - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sampe_rx) * audio->n_bytes_per_sampe_rx; - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_rx = audio->n_channels_rx / audio->n_channels_per_ff_rx; - TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // In case of asynchronous EP, call Cb after ep_fb is set - if ( !(desc_ep->bmAttributes.sync == 0x01 && audio->ep_fb == 0) ) - { - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - } -#else - // Invoke callback - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); -#endif - // Prepare for incoming data -#if USE_LINEAR_BUFFER_RX - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); -#else - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); -#endif - } - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) // Check if usage is explicit data feedback - { - audio->ep_fb = ep_addr; - - // Invoke callback after ep_out is set - if (audio->ep_out != 0) - { - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - } - } -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - - foundEPs += 1; - } - p_desc = tu_desc_next(p_desc); - } - - TU_VERIFY(foundEPs == nEps); - - // We are done - abort loop - break; - } - - // Moving forward - p_desc = tu_desc_next(p_desc); - } - - tud_control_status(rhport, p_request); - - return true; -} - -// Invoked when class request DATA stage is finished. -// return false to stall control EP (e.g Host send non-sense DATA) -static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) -{ - // Handle audio class specific set requests - if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) - { - uint8_t func_id; - - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - if (entityID != 0) - { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - else - { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - break; - // Unknown/Unsupported recipient - default: TU_BREAKPOINT(); return false; - } - } - return true; -} - -// Handle class control request -// return false to stall control endpoint (e.g unsupported request) -static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - switch (p_request->bRequest) - { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); - - case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); - - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - } - - // Handle class requests - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) - { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t func_id; - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } - } - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } - } - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz)); - return true; - } - - // There went something wrong - unsupported control request type - TU_BREAKPOINT(); - return false; -} - -bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - return audiod_control_request(rhport, request); - } - else if ( stage == CONTROL_STAGE_DATA ) - { - return audiod_control_complete(rhport, request); - } - - return true; -} - -bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) xferred_bytes; - - // Search for interface belonging to given end point address and proceed as required - uint8_t func_id; - for (func_id = 0; func_id < CFG_TUD_AUDIO; func_id++) - { - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - - // Data transmission of control interrupt finished - if (_audiod_fct[func_id].ep_int_ctr == ep_addr) - { - // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) - // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? - // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? - - // I assume here, that things above are handled by PHY - // All transmission is done - what remains to do is to inform job was completed - - if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, (uint16_t) xferred_bytes)); - } - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - - // Data transmission of audio packet finished - if (_audiod_fct[func_id].ep_in == ep_addr && _audiod_fct[func_id].alt_setting != 0) - { - // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." - // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." - // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. - - // Check if there is data to load into EPs buffer - if not load it with ZLP - // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! - // This is the only place where we can fill something into the EPs buffer! - - // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); - - // Transmission of ZLP is done by audiod_tx_done_cb() - return true; - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - - // New audio packet received - if (_audiod_fct[func_id].ep_out == ep_addr) - { - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[func_id], (uint16_t) xferred_bytes)); - return true; - } - - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Transmission of feedback EP finished - if (_audiod_fct[func_id].ep_fb == ep_addr) - { - if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - - // Schedule a transmit with the new value if EP is not busy - if (!usbd_edpt_busy(rhport, _audiod_fct[func_id].ep_fb)) - { - // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_fct[func_id]); - } - } -#endif -#endif - } - - return false; -} - -bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) -{ - // Handles only sending of data not receiving - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; - - // Get corresponding driver index - uint8_t func_id; - uint8_t itf = TU_U16_LOW(p_request->wIndex); - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // Crop length - if (len > _audiod_fct[func_id].ctrl_buf_sz) len = _audiod_fct[func_id].ctrl_buf_sz; - - // Copy into buffer - memcpy((void *)_audiod_fct[func_id].ctrl_buf, data, (size_t)len); - - // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len); -} - -// This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function -// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int) -{ - if (audio->p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // Advance past AC descriptors - uint8_t const *p_desc = tu_desc_next(audio->p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - uint8_t tmp = 0; - while (p_desc < p_desc_end) - { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) - { - if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *pp_desc_int = p_desc; - return true; - } - // Increase index, bytes read, and pointer - tmp++; - } - p_desc = tu_desc_next(p_desc); - } - } - return false; -} - -// This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function -// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int) -{ - // Loop over audio driver interfaces - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) - { - *func_id = i; - return true; - } - } - - return false; -} - -// Verify an entity with the given ID exists and returns also the corresponding driver index -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - // Look for the correct driver by checking if the unique standard AC interface number fits - if (_audiod_fct[i].p_desc && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) - { - // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); // Points to CS AC descriptor - uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; - p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor - - while (p_desc < p_desc_end) - { - if (p_desc[3] == entityID) // Entity IDs are always at offset 3 - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].p_desc) - { - // Get pointer at beginning and end - uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; - - // Advance past AC descriptors - EP we look for are streaming EPs - uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -// p_desc points to the AS interface of alternate setting zero -// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter -// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf) -{ - p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor - - while (p_desc < p_desc_end) - { - // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; - - // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) - { -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently -#endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) break; -#endif -#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) break; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) - { - audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_tx = (audio_format_type_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType); - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio->format_type_I_tx = (audio_data_format_type_I_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats); -#endif - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf == audio->ep_out_as_intf_num) - { - audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; -#endif - } -#endif - } - - // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) - { -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently -#endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) break; -#endif -#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) break; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) - { - audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf == audio->ep_out_as_intf_num) - { - audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; - } -#endif - } -#endif - - // Other format types are not supported yet - - p_desc = tu_desc_next(p_desc); - } -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // Format the feedback value -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION - if ( TUSB_SPEED_FULL == tud_speed_get() ) - { - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - }else -#else - { - // Send value as-is, caller will choose the appropriate format - _audiod_fct[func_id].fb_val = feedback; - } -#endif - - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) - { - return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]); - } - - return true; -} -#endif - -// No security checks here - internal function only which should always succeed -uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) -{ - for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO; cnt++) - { - if (&_audiod_fct[cnt] == audio) return cnt; - } - return 0; -} - -#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h deleted file mode 100644 index f406cf281..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h +++ /dev/null @@ -1,637 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_AUDIO_DEVICE_H_ -#define _TUSB_AUDIO_DEVICE_H_ - -#include "audio.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -// All sizes are in bytes! - -#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif - -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces -#ifndef CFG_TUD_AUDIO_FUNC_1_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#endif - -// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors -#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif - -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif -#endif - -// End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 -#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN -#define CFG_TUD_AUDIO_ENABLE_EP_IN 0 // TX -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT -#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0 // RX -#endif - -// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation -#if CFG_TUD_AUDIO_ENABLE_EP_IN -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - -// Software EP FIFO buffer sizes - must be >= max EP SIZEs! -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif - -#if CFG_TUD_AUDIO > 1 -#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif - -#if CFG_TUD_AUDIO > 1 -#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif -#endif - -// Enable/disable feedback EP (required for asynchronous RX applications) -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 -#endif - -// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set(). -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 -#endif - -// Audio interrupt control EP size - disabled if 0 -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) -#endif - -#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) -#endif - -// Use software encoding/decoding - -// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved -// into a single PCM stream as SAMPLE_1 | SAMPLE_2 | SAMPLE_3 | SAMPLE_4. -// -// Currently, only PCM type I encoding/decoding is supported! -// -// If the coding feature is to be used, support FIFOs need to be configured. Their sizes and numbers are defined below. - -// Encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the -// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using -// - tud_audio_n_write() or -// - tud_audio_n_read(). -// To write/read to/from the support FIFOs use -// - tud_audio_n_write_support_ff() or -// - tud_audio_n_read_support_ff(). -// -// The encoding/decoding format type done is defined below. -// -// The encoding/decoding starts when the private callback functions -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// are invoked. If support FIFOs are used, the corresponding encoding/decoding functions are called from there. -// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// if you want to get informed what happened. -// -// If you don't use the support FIFOs you may use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time. -// -// If you need a different encoding which is not support so far implement it in the -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// functions. - -// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size -// The actual coding parameters of active AS alternate interface is parsed from the descriptors - -// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)! -// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! - -// For PCM encoding/decoding - -#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING -#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_DECODING -#define CFG_TUD_AUDIO_ENABLE_DECODING 0 -#endif - -// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0 -#endif - -// Type I Coding parameters not given within UAC2 descriptors -// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -// Remaining types not support so far - -// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface -#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0 -#endif - -// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO -#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0 -#endif - -//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); - -// Supported types of this driver: -// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup AUDIO_Serial Serial - * @{ - * \defgroup AUDIO_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -// CFG_TUD_AUDIO > 1 -//--------------------------------------------------------------------+ -bool tud_audio_n_mounted (uint8_t func_id); - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available (uint8_t func_id); -uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); -bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO -tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs -uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); -tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); -bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO -tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); -tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len); -#endif - -//--------------------------------------------------------------------+ -// Application API (Interface0) -//--------------------------------------------------------------------+ - -static inline bool tud_audio_mounted (void); - -// RX API - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -static inline uint16_t tud_audio_available (void); -static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO -static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -static inline tu_fifo_t* tud_audio_get_ep_out_ff (void); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); -static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx); -#endif - -// TX API - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_write (const void * data, uint16_t len); -static inline bool tud_audio_clear_ep_in_ff (void); -static inline tu_fifo_t* tud_audio_get_ep_in_ff (void); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_flush_tx_support_ff (void); -static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); -static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx); -#endif - -// INT CTR API - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); -#endif - -// Buffer control EP data and schedule a transmit -// This function is intended to be used if you do not have a persistent buffer or memory location available (e.g. non-local variables) and need to answer onto a -// get request. This function buffers your answer request frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it. -// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such -// available you may directly use 'tud_control_xfer(...)'. In this case data does not need to be copied into an additional buffer and you save some time. -// If the request's wLength is zero, a status packet is sent instead. -bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); - -// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed. -// -// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default, -// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb -// expects 16.16 format and handles the conversion to 10.14 on FS. -// -// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the -// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format. -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); -static inline bool tud_audio_fb_set(uint32_t feedback); -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied); -#endif - -// Invoked when audio set interface request received -TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio set interface request received which closes an EP -TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific set request received for an EP -TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific set request received for an interface -TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific set request received for an entity -TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific get request received for an EP -TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific get request received for an interface -TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific get request received for an entity -TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline bool tud_audio_mounted(void) -{ - return tud_audio_n_mounted(0); -} - -// RX API - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -static inline uint16_t tud_audio_available(void) -{ - return tud_audio_n_available(0); -} - -static inline uint16_t tud_audio_read(void* buffer, uint16_t bufsize) -{ - return tud_audio_n_read(0, buffer, bufsize); -} - -static inline bool tud_audio_clear_ep_out_ff(void) -{ - return tud_audio_n_clear_ep_out_ff(0); -} - -static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) -{ - return tud_audio_n_get_ep_out_ff(0); -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - -static inline bool tud_audio_clear_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_rx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_available_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_available_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, uint16_t bufsize) -{ - return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); -} - -static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_rx_support_ff(0, ff_idx); -} - -#endif - -// TX API - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -static inline uint16_t tud_audio_write(const void * data, uint16_t len) -{ - return tud_audio_n_write(0, data, len); -} - -static inline bool tud_audio_clear_ep_in_ff(void) -{ - return tud_audio_n_clear_ep_in_ff(0); -} - -static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) -{ - return tud_audio_n_get_ep_in_ff(0); -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - -static inline uint16_t tud_audio_flush_tx_support_ff(void) -{ - return tud_audio_n_flush_tx_support_ff(0); -} - -static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_tx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * data, uint16_t len) -{ - return tud_audio_n_write_support_ff(0, ff_idx, data, len); -} - -static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_tx_support_ff(0, ff_idx); -} - -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) -{ - return tud_audio_int_ctr_n_write(0, buffer, len); -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool tud_audio_fb_set(uint32_t feedback) -{ - return tud_audio_n_fb_set(0, feedback); -} -#endif - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_AUDIO_DEVICE_H_ */ - -/** @} */ -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c deleted file mode 100644 index 8ef609622..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_BTH) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "bth_device.h" -#include - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_ev; - uint8_t ep_acl_in; - uint8_t ep_acl_out; - uint8_t ep_voice[2]; // Not used yet - uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE]; - -} btd_interface_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf; - -static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) -{ - // skip if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(TUD_OPT_RHPORT, ep)); - - TU_ASSERT(usbd_edpt_xfer(TUD_OPT_RHPORT, ep, data, len)); - - return true; -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ - - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -bool tud_bt_event_send(void *event, uint16_t event_len) -{ - return bt_tx_data(_btd_itf.ep_ev, event, event_len); -} - -bool tud_bt_acl_data_send(void *event, uint16_t event_len) -{ - return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void btd_init(void) -{ - tu_memclr(&_btd_itf, sizeof(_btd_itf)); -} - -void btd_reset(uint8_t rhport) -{ - (void)rhport; -} - -uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - tusb_desc_endpoint_t const *desc_ep; - uint16_t drv_len = 0; - // Size of single alternative of ISO interface - const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t); - // Size of hci interface - const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); - // Ensure this is BT Primary Controller - TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); - - TU_ASSERT(itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size); - - _btd_itf.itf_num = itf_desc->bInterfaceNumber; - - desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); - _btd_itf.ep_ev = desc_ep->bEndpointAddress; - - // Open endpoint pair - TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, - &_btd_itf.ep_acl_in), 0); - - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(tu_desc_next(desc_ep))); - - // Prepare for incoming data from host - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); - - drv_len = hci_itf_size; - - // Ensure this is still BT Primary Controller - TU_ASSERT(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); - TU_ASSERT(itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size + drv_len); - - uint8_t dir; - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - drv_len += iso_alt_itf_size; - - for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { - // Make sure rest of alternatives matches - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); - if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || - TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || - TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) - { - // Not an Iso interface instance - break; - } - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - drv_len += iso_alt_itf_size; - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) -{ - (void)rhport; - - if ( stage == CONTROL_STAGE_SETUP ) - { - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) - { - // HCI command packet addressing for single function Primary Controllers - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); - } - else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) - { - if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) - { - // TODO: Set interface it would involve changing size of endpoint size - } - else - { - // HCI command packet for Primary Controller function in a composite device - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); - } - } - else return false; - - return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd)); - } - else if ( stage == CONTROL_STAGE_DATA ) - { - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd))); - } - - return true; -} - -bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; - - // received new data from host - if (ep_addr == _btd_itf.ep_acl_out) - { - if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes); - - // prepare for next data - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); - } - else if (ep_addr == _btd_itf.ep_ev) - { - if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); - } - else if (ep_addr == _btd_itf.ep_acl_in) - { - if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h deleted file mode 100644 index 1b90d0915..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_BTH_DEVICE_H_ -#define _TUSB_BTH_DEVICE_H_ - -#include -#include - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ -#ifndef CFG_TUD_BTH_EVENT_EPSIZE -#define CFG_TUD_BTH_EVENT_EPSIZE 16 -#endif -#ifndef CFG_TUD_BTH_DATA_EPSIZE -#define CFG_TUD_BTH_DATA_EPSIZE 64 -#endif - -typedef struct TU_ATTR_PACKED -{ - uint16_t op_code; - uint8_t param_length; - uint8_t param[255]; -} bt_hci_cmd_t; - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when HCI command was received over USB from Bluetooth host. -// Detailed format is described in Bluetooth core specification Vol 2, -// Part E, 5.4.1. -// Length of the command is from 3 bytes (2 bytes for OpCode, -// 1 byte for parameter total length) to 258. -TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); - -// Invoked when ACL data was received over USB from Bluetooth host. -// Detailed format is described in Bluetooth core specification Vol 2, -// Part E, 5.4.2. -// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags -// and 16 bits for data total length) to endpoint size. -TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); - -// Called when event sent with tud_bt_event_send() was delivered to BT stack. -// Controller can release/reuse buffer with Event packet at this point. -TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); - -// Called when ACL data that was sent with tud_bt_acl_data_send() -// was delivered to BT stack. -// Controller can release/reuse buffer with ACL packet at this point. -TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); - -// Bluetooth controller calls this function when it wants to send even packet -// as described in Bluetooth core specification Vol 2, Part E, 5.4.4. -// Event has at least 2 bytes, first is Event code second contains parameter -// total length. Controller can release/reuse event memory after -// tud_bt_event_sent_cb() is called. -bool tud_bt_event_send(void *event, uint16_t event_len); - -// Bluetooth controller calls this to send ACL data packet -// as described in Bluetooth core specification Vol 2, Part E, 5.4.2 -// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags -// and 16 bits for data total length). Upper limit is not limited -// to endpoint size since buffer is allocate by controller -// and must not be reused till tud_bt_acl_data_sent_cb() is called. -bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void btd_init (void); -void btd_reset (uint8_t rhport); -uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request); -bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_BTH_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h deleted file mode 100644 index e345139ea..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_CDC Communication Device Class (CDC) - * Currently only Abstract Control Model subclass is supported - * @{ */ - -#ifndef _TUSB_CDC_H__ -#define _TUSB_CDC_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/** \defgroup ClassDriver_CDC_Common Common Definitions - * @{ */ - -// TODO remove -/// CDC Pipe ID, used to indicate which pipe the API is addressing to (Notification, Out, In) -typedef enum -{ - CDC_PIPE_NOTIFICATION , ///< Notification pipe - CDC_PIPE_DATA_IN , ///< Data in pipe - CDC_PIPE_DATA_OUT , ///< Data out pipe - CDC_PIPE_ERROR , ///< Invalid Pipe ID -}cdc_pipeid_t; - -//--------------------------------------------------------------------+ -// CDC Communication Interface Class -//--------------------------------------------------------------------+ - -/// Communication Interface Subclass Codes -typedef enum -{ - CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 , ///< Direct Line Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL = 0x02 , ///< Abstract Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL = 0x03 , ///< Telephone Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL = 0x04 , ///< Multi-Channel Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL = 0x05 , ///< CAPI Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL = 0x06 , ///< Ethernet Networking Control Model [USBECM1.2] - CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL = 0x07 , ///< ATM Networking Control Model [USBATM1.2] - CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL = 0x08 , ///< Wireless Handset Control Model [USBWMC1.1] - CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT = 0x09 , ///< Device Management [USBWMC1.1] - CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL = 0x0A , ///< Mobile Direct Line Model [USBWMC1.1] - CDC_COMM_SUBCLASS_OBEX = 0x0B , ///< OBEX [USBWMC1.1] - CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL = 0x0C , ///< Ethernet Emulation Model [USBEEM1.0] - CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL = 0x0D ///< Network Control Model [USBNCM1.0] -} cdc_comm_sublcass_type_t; - -/// Communication Interface Protocol Codes -typedef enum -{ - CDC_COMM_PROTOCOL_NONE = 0x00 , ///< No specific protocol - CDC_COMM_PROTOCOL_ATCOMMAND = 0x01 , ///< AT Commands: V.250 etc - CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 = 0x02 , ///< AT Commands defined by PCCA-101 - CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO = 0x03 , ///< AT Commands defined by PCCA-101 & Annex O - CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 = 0x04 , ///< AT Commands defined by GSM 07.07 - CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 = 0x05 , ///< AT Commands defined by 3GPP 27.007 - CDC_COMM_PROTOCOL_ATCOMMAND_CDMA = 0x06 , ///< AT Commands defined by TIA for CDMA - CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL = 0x07 ///< Ethernet Emulation Model -} cdc_comm_protocol_type_t; - -//------------- SubType Descriptor in COMM Functional Descriptor -------------// -/// Communication Interface SubType Descriptor -typedef enum -{ - CDC_FUNC_DESC_HEADER = 0x00 , ///< Header Functional Descriptor, which marks the beginning of the concatenated set of functional descriptors for the interface. - CDC_FUNC_DESC_CALL_MANAGEMENT = 0x01 , ///< Call Management Functional Descriptor. - CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT = 0x02 , ///< Abstract Control Management Functional Descriptor. - CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT = 0x03 , ///< Direct Line Management Functional Descriptor. - CDC_FUNC_DESC_TELEPHONE_RINGER = 0x04 , ///< Telephone Ringer Functional Descriptor. - CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 , ///< Telephone Call and Line State Reporting Capabilities Functional Descriptor. - CDC_FUNC_DESC_UNION = 0x06 , ///< Union Functional Descriptor - CDC_FUNC_DESC_COUNTRY_SELECTION = 0x07 , ///< Country Selection Functional Descriptor - CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES = 0x08 , ///< Telephone Operational ModesFunctional Descriptor - CDC_FUNC_DESC_USB_TERMINAL = 0x09 , ///< USB Terminal Functional Descriptor - CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL = 0x0A , ///< Network Channel Terminal Descriptor - CDC_FUNC_DESC_PROTOCOL_UNIT = 0x0B , ///< Protocol Unit Functional Descriptor - CDC_FUNC_DESC_EXTENSION_UNIT = 0x0C , ///< Extension Unit Functional Descriptor - CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT = 0x0D , ///< Multi-Channel Management Functional Descriptor - CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT = 0x0E , ///< CAPI Control Management Functional Descriptor - CDC_FUNC_DESC_ETHERNET_NETWORKING = 0x0F , ///< Ethernet Networking Functional Descriptor - CDC_FUNC_DESC_ATM_NETWORKING = 0x10 , ///< ATM Networking Functional Descriptor - CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL = 0x11 , ///< Wireless Handset Control Model Functional Descriptor - CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL = 0x12 , ///< Mobile Direct Line Model Functional Descriptor - CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL = 0x13 , ///< MDLM Detail Functional Descriptor - CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL = 0x14 , ///< Device Management Model Functional Descriptor - CDC_FUNC_DESC_OBEX = 0x15 , ///< OBEX Functional Descriptor - CDC_FUNC_DESC_COMMAND_SET = 0x16 , ///< Command Set Functional Descriptor - CDC_FUNC_DESC_COMMAND_SET_DETAIL = 0x17 , ///< Command Set Detail Functional Descriptor - CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL = 0x18 , ///< Telephone Control Model Functional Descriptor - CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19 , ///< OBEX Service Identifier Functional Descriptor - CDC_FUNC_DESC_NCM = 0x1A , ///< NCM Functional Descriptor -}cdc_func_desc_type_t; - -//--------------------------------------------------------------------+ -// CDC Data Interface Class -//--------------------------------------------------------------------+ - -// SUBCLASS code of Data Interface is not used and should/must be zero - -// Data Interface Protocol Codes -typedef enum{ - CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, ///< Physical interface protocol for ISDN BRI - CDC_DATA_PROTOCOL_HDLC = 0x31, ///< HDLC - CDC_DATA_PROTOCOL_TRANSPARENT = 0x32, ///< Transparent - CDC_DATA_PROTOCOL_Q921_MANAGEMENT = 0x50, ///< Management protocol for Q.921 data link protocol - CDC_DATA_PROTOCOL_Q921_DATA_LINK = 0x51, ///< Data link protocol for Q.931 - CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR = 0x52, ///< TEI-multiplexor for Q.921 data link protocol - CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION = 0x90, ///< Data compression procedures - CDC_DATA_PROTOCOL_EURO_ISDN = 0x91, ///< Euro-ISDN protocol control - CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN = 0x92, ///< V.24 rate adaptation to ISDN - CDC_DATA_PROTOCOL_CAPI_COMMAND = 0x93, ///< CAPI Commands - CDC_DATA_PROTOCOL_HOST_BASED_DRIVER = 0xFD, ///< Host based driver. Note: This protocol code should only be used in messages between host and device to identify the host driver portion of a protocol stack. - CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE ///< The protocol(s) are described using a ProtocolUnit Functional Descriptors on Communications Class Interface -}cdc_data_protocol_type_t; - -//--------------------------------------------------------------------+ -// Management Element Request (Control Endpoint) -//--------------------------------------------------------------------+ - -/// Communication Interface Management Element Request Codes -typedef enum -{ - CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface - CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface. - CDC_REQUEST_SET_COMM_FEATURE = 0x02, - CDC_REQUEST_GET_COMM_FEATURE = 0x03, - CDC_REQUEST_CLEAR_COMM_FEATURE = 0x04, - - CDC_REQUEST_SET_AUX_LINE_STATE = 0x10, - CDC_REQUEST_SET_HOOK_STATE = 0x11, - CDC_REQUEST_PULSE_SETUP = 0x12, - CDC_REQUEST_SEND_PULSE = 0x13, - CDC_REQUEST_SET_PULSE_TIME = 0x14, - CDC_REQUEST_RING_AUX_JACK = 0x15, - - CDC_REQUEST_SET_LINE_CODING = 0x20, - CDC_REQUEST_GET_LINE_CODING = 0x21, - CDC_REQUEST_SET_CONTROL_LINE_STATE = 0x22, - CDC_REQUEST_SEND_BREAK = 0x23, - - CDC_REQUEST_SET_RINGER_PARMS = 0x30, - CDC_REQUEST_GET_RINGER_PARMS = 0x31, - CDC_REQUEST_SET_OPERATION_PARMS = 0x32, - CDC_REQUEST_GET_OPERATION_PARMS = 0x33, - CDC_REQUEST_SET_LINE_PARMS = 0x34, - CDC_REQUEST_GET_LINE_PARMS = 0x35, - CDC_REQUEST_DIAL_DIGITS = 0x36, - CDC_REQUEST_SET_UNIT_PARAMETER = 0x37, - CDC_REQUEST_GET_UNIT_PARAMETER = 0x38, - CDC_REQUEST_CLEAR_UNIT_PARAMETER = 0x39, - CDC_REQUEST_GET_PROFILE = 0x3A, - - CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS = 0x40, - CDC_REQUEST_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, - CDC_REQUEST_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, - CDC_REQUEST_SET_ETHERNET_PACKET_FILTER = 0x43, - CDC_REQUEST_GET_ETHERNET_STATISTIC = 0x44, - - CDC_REQUEST_SET_ATM_DATA_FORMAT = 0x50, - CDC_REQUEST_GET_ATM_DEVICE_STATISTICS = 0x51, - CDC_REQUEST_SET_ATM_DEFAULT_VC = 0x52, - CDC_REQUEST_GET_ATM_VC_STATISTICS = 0x53, - - CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60, -}cdc_management_request_t; - -//--------------------------------------------------------------------+ -// Management Elemenent Notification (Notification Endpoint) -//--------------------------------------------------------------------+ - -/// 6.3 Notification Codes -typedef enum -{ - CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status. - CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request. - CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, - CDC_NOTIF_RING_DETECT = 0x09, - CDC_NOTIF_SERIAL_STATE = 0x20, - CDC_NOTIF_CALL_STATE_CHANGE = 0x28, - CDC_NOTIF_LINE_STATE_CHANGE = 0x29, - CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred - CDC_NOTIF_MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40, -}cdc_notification_request_t; - -//--------------------------------------------------------------------+ -// Class Specific Functional Descriptor (Communication Interface) -//--------------------------------------------------------------------+ - -// Start of all packed definitions for compiler without per-type packed -TU_ATTR_PACKED_BEGIN -TU_ATTR_BIT_FIELD_ORDER_BEGIN - -/// Header Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ - uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal -}cdc_desc_func_header_t; - -/// Union Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t bControlInterface ; ///< Interface number of Communication Interface - uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface -}cdc_desc_func_union_t; - -#define cdc_desc_func_union_n_t(no_slave)\ - struct TU_ATTR_PACKED { \ - uint8_t bLength ;\ - uint8_t bDescriptorType ;\ - uint8_t bDescriptorSubType ;\ - uint8_t bControlInterface ;\ - uint8_t bSubordinateInterface[no_slave] ;\ -} - -/// Country Selection Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. - uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. -}cdc_desc_func_country_selection_t; - -#define cdc_desc_func_country_selection_n_t(no_country) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ;\ - uint8_t bDescriptorType ;\ - uint8_t bDescriptorSubType ;\ - uint8_t iCountryCodeRelDate ;\ - uint16_t wCountryCode[no_country] ;\ -} - -//--------------------------------------------------------------------+ -// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS -//--------------------------------------------------------------------+ - -/// \brief Call Management Functional Descriptor -/// \details This functional descriptor describes the processing of calls for the Communications Class interface. -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - - struct { - uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. - uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. - uint8_t TU_RESERVED : 6; - } bmCapabilities; - - uint8_t bDataInterface; -}cdc_desc_func_call_management_t; - -typedef struct TU_ATTR_PACKED -{ - uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. - uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. - uint8_t support_send_break : 1; ///< Device supports the request Send_Break - uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. - uint8_t TU_RESERVED : 4; -}cdc_acm_capability_t; - -TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); - -/// Abstract Control Management Functional Descriptor -/// This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - cdc_acm_capability_t bmCapabilities ; -}cdc_desc_func_acm_t; - -/// \brief Direct Line Management Functional Descriptor -/// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - struct { - uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. - uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. - uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. - uint8_t TU_RESERVED : 5; - } bmCapabilities; -}cdc_desc_func_direct_line_management_t; - -/// \brief Telephone Ringer Functional Descriptor -/// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, -/// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t bRingerVolSteps ; - uint8_t bNumRingerPatterns ; -}cdc_desc_func_telephone_ringer_t; - -/// \brief Telephone Operational Modes Functional Descriptor -/// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by -/// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - struct { - uint8_t simple_mode : 1; - uint8_t standalone_mode : 1; - uint8_t computer_centric_mode : 1; - uint8_t TU_RESERVED : 5; - } bmCapabilities; -}cdc_desc_func_telephone_operational_modes_t; - -/// \brief Telephone Call and Line State Reporting Capabilities Descriptor -/// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a -/// telephone device to report optional call and line states. -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - struct { - uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone - uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. - uint32_t caller_id : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information. - uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns. - uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line. - uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification - uint32_t TU_RESERVED : 26; - } bmCapabilities; -}cdc_desc_func_telephone_call_state_reporting_capabilities_t; - -// TODO remove -static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) -{ - return p_desc[2]; -} - -//--------------------------------------------------------------------+ -// Requests -//--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ - uint32_t bit_rate; - uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits - uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space - uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 -} cdc_line_coding_t; - -TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR. - uint16_t half_duplex_carrier_control : 1; - uint16_t : 14; -} cdc_line_control_state_t; - -TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); - -TU_ATTR_PACKED_END // End of all packed definitions -TU_ATTR_BIT_FIELD_ORDER_END - -#ifdef __cplusplus - } -#endif - -#endif - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c deleted file mode 100644 index 08f2af253..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "cdc_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -enum -{ - BULK_PACKET_SIZE = (TUD_OPT_HIGH_SPEED ? 512 : 64) -}; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) - uint8_t line_state; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - char wanted_char; - cdc_line_coding_t line_coding; - - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; - -}cdcd_interface_t; - -#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; - -static bool _prep_out_transaction (cdcd_interface_t* p_cdc) -{ - uint8_t const rhport = TUD_OPT_RHPORT; - uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= sizeof(p_cdc->epout_buf)); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out)); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_cdc->rx_ff); - - if ( available >= sizeof(p_cdc->epout_buf) ) - { - return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_cdc->ep_out); - - return false; - } -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_cdc_n_connected(uint8_t itf) -{ - // DTR (bit 0) active is considered as connected - return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0); -} - -uint8_t tud_cdc_n_get_line_state (uint8_t itf) -{ - return _cdcd_itf[itf].line_state; -} - -void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding) -{ - (*coding) = _cdcd_itf[itf].line_coding; -} - -void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted) -{ - _cdcd_itf[itf].wanted_char = wanted; -} - - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ -uint32_t tud_cdc_n_available(uint8_t itf) -{ - return tu_fifo_count(&_cdcd_itf[itf].rx_ff); -} - -uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, bufsize); - _prep_out_transaction(p_cdc); - return num_read; -} - -bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) -{ - return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); -} - -void tud_cdc_n_read_flush (uint8_t itf) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - tu_fifo_clear(&p_cdc->rx_ff); - _prep_out_transaction(p_cdc); -} - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ -uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize); - - // flush if queue more than packet size - if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE ) - { - tud_cdc_n_write_flush(itf); - } - - return ret; -} - -uint32_t tud_cdc_n_write_flush (uint8_t itf) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - - // Skip if usb is not ready yet - TU_VERIFY( tud_ready(), 0 ); - - // No data to send - if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; - - uint8_t const rhport = TUD_OPT_RHPORT; - - // Claim the endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); - - // Pull data from FIFO - uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); - - if ( count ) - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); - return count; - }else - { - // Release endpoint since we don't make any transfer - // Note: data is dropped if terminal is not connected - usbd_edpt_release(rhport, p_cdc->ep_in); - return 0; - } -} - -uint32_t tud_cdc_n_write_available (uint8_t itf) -{ - return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); -} - -bool tud_cdc_n_write_clear (uint8_t itf) -{ - return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void cdcd_init(void) -{ - tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); - - for(uint8_t i=0; iwanted_char = (char) -1; - - // default line coding is : stop bit = 1, parity = none, data bits = 8 - p_cdc->line_coding.bit_rate = 115200; - p_cdc->line_coding.stop_bits = 0; - p_cdc->line_coding.parity = 0; - p_cdc->line_coding.data_bits = 8; - - // Config RX fifo - tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); - - // Config TX fifo as overwritable at initialization and will be changed to non-overwritable - // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal. - // In this way, the most current data is prioritized. - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); - -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex)); - tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL); -#endif - } -} - -void cdcd_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&p_cdc->tx_ff); - tu_fifo_set_overwritable(&p_cdc->tx_ff, true); - } -} - -uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // Only support ACM subclass - TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); - - // Find available interface - cdcd_interface_t * p_cdc = NULL; - for(uint8_t cdc_id=0; cdc_iditf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - // notification endpoint - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 ); - p_cdc->ep_notif = desc_ep->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { - // next to endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - } - - // Prepare for incoming data - _prep_out_transaction(p_cdc); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - uint8_t itf = 0; - cdcd_interface_t* p_cdc = _cdcd_itf; - - // Identify which interface to use - for ( ; ; itf++, p_cdc++) - { - if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; - - if ( p_cdc->itf_num == request->wIndex ) break; - } - - switch ( request->bRequest ) - { - case CDC_REQUEST_SET_LINE_CODING: - if (stage == CONTROL_STAGE_SETUP) - { - TU_LOG2(" Set Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); - } - else if ( stage == CONTROL_STAGE_ACK) - { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); - } - break; - - case CDC_REQUEST_GET_LINE_CODING: - if (stage == CONTROL_STAGE_SETUP) - { - TU_LOG2(" Get Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); - } - break; - - case CDC_REQUEST_SET_CONTROL_LINE_STATE: - if (stage == CONTROL_STAGE_SETUP) - { - tud_control_status(rhport, request); - } - else if (stage == CONTROL_STAGE_ACK) - { - // CDC PSTN v1.2 section 6.3.12 - // Bit 0: Indicates if DTE is present or not. - // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) - // Bit 1: Carrier control for half-duplex modems. - // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) - bool const dtr = tu_bit_test(request->wValue, 0); - bool const rts = tu_bit_test(request->wValue, 1); - - p_cdc->line_state = (uint8_t) request->wValue; - - // Disable fifo overwriting if DTR bit is set - tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); - - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); - - // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); - } - break; - case CDC_REQUEST_SEND_BREAK: - if (stage == CONTROL_STAGE_SETUP) - { - tud_control_status(rhport, request); - } - else if (stage == CONTROL_STAGE_ACK) - { - TU_LOG2(" Send Break\r\n"); - if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); - } - break; - - default: return false; // stall unsupported request - } - - return true; -} - -bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t itf; - cdcd_interface_t* p_cdc; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_CDC; itf++) - { - p_cdc = &_cdcd_itf[itf]; - if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break; - } - TU_ASSERT(itf < CFG_TUD_CDC); - - // Received new data - if ( ep_addr == p_cdc->ep_out ) - { - tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); - - // Check for wanted char and invoke callback if needed - if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) - { - for ( uint32_t i = 0; i < xferred_bytes; i++ ) - { - if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) - { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); - } - } - } - - // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); - - // prepare for OUT transaction - _prep_out_transaction(p_cdc); - } - - // Data sent to host, we continue to fetch from tx fifo to send. - // Note: This will cause incorrect baudrate set in line coding. - // Though maybe the baudrate is not really important !!! - if ( ep_addr == p_cdc->ep_in ) - { - // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); - - if ( 0 == tud_cdc_n_write_flush(itf) ) - { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP Packet size and not zero - if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE-1))) ) - { - if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) - { - usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); - } - } - } - } - - // nothing to do with notif endpoint for now - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h deleted file mode 100644 index fbc7162a3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_CDC_DEVICE_H_ -#define _TUSB_CDC_DEVICE_H_ - -#include "common/tusb_common.h" -#include "cdc.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ -#if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE) - #warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE -#endif - -#ifndef CFG_TUD_CDC_EP_BUFSIZE - #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -/** \addtogroup CDC_Serial Serial - * @{ - * \defgroup CDC_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Ports) -// CFG_TUD_CDC > 1 -//--------------------------------------------------------------------+ - -// Check if terminal is connected to this port -bool tud_cdc_n_connected (uint8_t itf); - -// Get current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) -uint8_t tud_cdc_n_get_line_state (uint8_t itf); - -// Get current line encoding: bit rate, stop bits parity etc .. -void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding); - -// Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving -void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); - -// Get the number of bytes available for reading -uint32_t tud_cdc_n_available (uint8_t itf); - -// Read received bytes -uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize); - -// Read a byte, return -1 if there is none -static inline -int32_t tud_cdc_n_read_char (uint8_t itf); - -// Clear the received FIFO -void tud_cdc_n_read_flush (uint8_t itf); - -// Get a byte from FIFO at the specified position without removing it -bool tud_cdc_n_peek (uint8_t itf, uint8_t* ui8); - -// Write bytes to TX FIFO, data may remain in the FIFO for a while -uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); - -// Write a byte -static inline -uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); - -// Write a null-terminated string -static inline -uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); - -// Force sending data if possible, return number of forced bytes -uint32_t tud_cdc_n_write_flush (uint8_t itf); - -// Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. -uint32_t tud_cdc_n_write_available (uint8_t itf); - -// Clear the transmit FIFO -bool tud_cdc_n_write_clear (uint8_t itf); - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_cdc_connected (void); -static inline uint8_t tud_cdc_get_line_state (void); -static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding); -static inline void tud_cdc_set_wanted_char (char wanted); - -static inline uint32_t tud_cdc_available (void); -static inline int32_t tud_cdc_read_char (void); -static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize); -static inline void tud_cdc_read_flush (void); -static inline bool tud_cdc_peek (uint8_t* ui8); - -static inline uint32_t tud_cdc_write_char (char ch); -static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); -static inline uint32_t tud_cdc_write_str (char const* str); -static inline uint32_t tud_cdc_write_flush (void); -static inline uint32_t tud_cdc_write_available (void); -static inline bool tud_cdc_write_clear (void); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received new data -TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); - -// Invoked when received `wanted_char` -TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); - -// Invoked when space becomes available in TX buffer -TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); - -// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE -TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); - -// Invoked when line coding is change via SET_LINE_CODING -TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); - -// Invoked when received send break -TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ -static inline int32_t tud_cdc_n_read_char (uint8_t itf) -{ - uint8_t ch; - return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1; -} - -static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch) -{ - return tud_cdc_n_write(itf, &ch, 1); -} - -static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str) -{ - return tud_cdc_n_write(itf, str, strlen(str)); -} - -static inline bool tud_cdc_connected (void) -{ - return tud_cdc_n_connected(0); -} - -static inline uint8_t tud_cdc_get_line_state (void) -{ - return tud_cdc_n_get_line_state(0); -} - -static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding) -{ - tud_cdc_n_get_line_coding(0, coding); -} - -static inline void tud_cdc_set_wanted_char (char wanted) -{ - tud_cdc_n_set_wanted_char(0, wanted); -} - -static inline uint32_t tud_cdc_available (void) -{ - return tud_cdc_n_available(0); -} - -static inline int32_t tud_cdc_read_char (void) -{ - return tud_cdc_n_read_char(0); -} - -static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize) -{ - return tud_cdc_n_read(0, buffer, bufsize); -} - -static inline void tud_cdc_read_flush (void) -{ - tud_cdc_n_read_flush(0); -} - -static inline bool tud_cdc_peek (uint8_t* ui8) -{ - return tud_cdc_n_peek(0, ui8); -} - -static inline uint32_t tud_cdc_write_char (char ch) -{ - return tud_cdc_n_write_char(0, ch); -} - -static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) -{ - return tud_cdc_n_write(0, buffer, bufsize); -} - -static inline uint32_t tud_cdc_write_str (char const* str) -{ - return tud_cdc_n_write_str(0, str); -} - -static inline uint32_t tud_cdc_write_flush (void) -{ - return tud_cdc_n_write_flush(0); -} - -static inline uint32_t tud_cdc_write_available(void) -{ - return tud_cdc_n_write_available(0); -} - -static inline bool tud_cdc_write_clear(void) -{ - return tud_cdc_n_write_clear(0); -} - -/** @} */ -/** @} */ - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c deleted file mode 100644 index f4fb6c1d6..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC) - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "cdc_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct { - uint8_t itf_num; - uint8_t itf_protocol; - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - cdc_acm_capability_t acm_capability; - -} cdch_data_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static cdch_data_t cdch_data[CFG_TUH_DEVICE_MAX]; - -static inline cdch_data_t* get_itf(uint8_t dev_addr) -{ - return &cdch_data[dev_addr-1]; -} - -bool tuh_cdc_mounted(uint8_t dev_addr) -{ - cdch_data_t* cdc = get_itf(dev_addr); - return cdc->ep_in && cdc->ep_out; -} - -bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) -{ - if ( !tuh_cdc_mounted(dev_addr) ) return false; - - cdch_data_t const * p_cdc = get_itf(dev_addr); - - switch (pipeid) - { - case CDC_PIPE_NOTIFICATION: - return usbh_edpt_busy(dev_addr, p_cdc->ep_notif ); - - case CDC_PIPE_DATA_IN: - return usbh_edpt_busy(dev_addr, p_cdc->ep_in ); - - case CDC_PIPE_DATA_OUT: - return usbh_edpt_busy(dev_addr, p_cdc->ep_out ); - - default: - return false; - } -} - -//--------------------------------------------------------------------+ -// APPLICATION API (parameter validation needed) -//--------------------------------------------------------------------+ -bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) -{ - // TODO consider all AT Command as serial candidate - return tuh_cdc_mounted(dev_addr) && - (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); -} - -bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify) -{ - (void) is_notify; - TU_VERIFY( tuh_cdc_mounted(dev_addr) ); - TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); - - uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; - if ( usbh_edpt_busy(dev_addr, ep_out) ) return false; - - return usbh_edpt_xfer(dev_addr, ep_out, (void*)(uintptr_t) p_data, length); -} - -bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify) -{ - (void) is_notify; - TU_VERIFY( tuh_cdc_mounted(dev_addr) ); - TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); - - uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; - if ( usbh_edpt_busy(dev_addr, ep_in) ) return false; - - return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); -} - -bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb) -{ - cdch_data_t const * p_cdc = get_itf(dev_addr); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0), - .wIndex = p_cdc->itf_num, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, complete_cb) ); - return true; -} - -//--------------------------------------------------------------------+ -// USBH-CLASS DRIVER API -//--------------------------------------------------------------------+ -void cdch_init(void) -{ - tu_memclr(cdch_data, sizeof(cdch_data)); -} - -bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - (void) max_len; - - // Only support ACM subclass - // Protocol 0xFF can be RNDIS device for windows XP - TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0xFF != itf_desc->bInterfaceProtocol); - - cdch_data_t * p_cdc = get_itf(dev_addr); - - p_cdc->itf_num = itf_desc->bInterfaceNumber; - p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; - - //------------- Communication Interface -------------// - uint16_t drv_len = tu_desc_len(itf_desc); - uint8_t const * p_desc = tu_desc_next(itf_desc); - - // Communication Functional Descriptors - while( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) - { - // save ACM bmCapabilities - p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - // notification endpoint - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - p_cdc->ep_notif = desc_ep->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { - // next to endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - // data endpoints expected to be in pairs - for(uint32_t i=0; i<2; i++) - { - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); - - if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) - { - p_cdc->ep_in = desc_ep->bEndpointAddress; - }else - { - p_cdc->ep_out = desc_ep->bEndpointAddress; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next( p_desc ); - } - } - - return true; -} - -bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - (void) dev_addr; (void) itf_num; - return true; -} - -bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - (void) ep_addr; - tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); - return true; -} - -void cdch_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - - cdch_data_t * p_cdc = get_itf(dev_addr); - tu_memclr(p_cdc, sizeof(cdch_data_t)); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h deleted file mode 100644 index 0d435138b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_CDC_HOST_H_ -#define _TUSB_CDC_HOST_H_ - -#include "cdc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// CDC APPLICATION PUBLIC API -//--------------------------------------------------------------------+ -/** \ingroup ClassDriver_CDC Communication Device Class (CDC) - * \addtogroup CDC_Serial Serial - * @{ - * \defgroup CDC_Serial_Host Host - * @{ */ - -bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb); - -static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) -{ - return tuh_cdc_set_control_line_state(dev_addr, true, true, complete_cb); -} - -static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) -{ - return tuh_cdc_set_control_line_state(dev_addr, false, false, complete_cb); -} - -/** \brief Check if device support CDC Serial interface or not - * \param[in] dev_addr device address - * \retval true if device supports - * \retval false if device does not support or is not mounted - */ -bool tuh_cdc_serial_is_mounted(uint8_t dev_addr); - -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \param[in] pipeid value from \ref cdc_pipeid_t to indicate target pipe. - * \retval true if the interface is busy, meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy, meaning the stack successfully transferred data from/to device - * \note This function is used to check if previous transfer is complete (success or error), so that the next transfer - * can be scheduled. User needs to make sure the corresponding interface is mounted - * (by \ref tuh_cdc_serial_is_mounted) before calling this function. - */ -bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid); - -/** \brief Perform USB OUT transfer to device - * \param[in] dev_addr device address - * \param[in] p_data Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] length Number of bytes to be transferred via USB bus - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the - * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION. - */ -bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify); - -/** \brief Perform USB IN transfer to get data from device - * \param[in] dev_addr device address - * \param[in] p_buffer Buffer containing received data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] length Number of bytes to be transferred via USB bus - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the - * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION. - */ -bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify); - -//--------------------------------------------------------------------+ -// CDC APPLICATION CALLBACKS -//--------------------------------------------------------------------+ - -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \param[in] pipe_id value from \ref cdc_pipeid_t indicate the pipe - * \param[in] xferred_bytes Number of bytes transferred via USB bus - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note - */ -void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes); - -/// @} // group CDC_Serial_Host -/// @} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void cdch_init (void); -bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close (uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h deleted file mode 100644 index e0f129fe3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup ClassDriver_CDC Communication Device Class (CDC) - * \defgroup CDC_RNDIS Remote Network Driver Interface Specification (RNDIS) - * @{ - * \defgroup CDC_RNDIS_Common Common Definitions - * @{ */ - -#ifndef _TUSB_CDC_RNDIS_H_ -#define _TUSB_CDC_RNDIS_H_ - -#include "cdc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -#ifdef __CC_ARM -#pragma diag_suppress 66 // Suppress Keil warnings #66-D: enumeration value is out of "int" range -#endif - -/// RNDIS Message Types -typedef enum -{ - RNDIS_MSG_PACKET = 0x00000001UL, ///< The host and device use this to send network data to one another. - - RNDIS_MSG_INITIALIZE = 0x00000002UL, ///< Sent by the host to initialize the device. - RNDIS_MSG_INITIALIZE_CMPLT = 0x80000002UL, ///< Device response to an initialize message. - - RNDIS_MSG_HALT = 0x00000003UL, ///< Sent by the host to halt the device. This does not have a response. It is optional for the device to send this message to the host. - - RNDIS_MSG_QUERY = 0x00000004UL, ///< Sent by the host to send a query OID. - RNDIS_MSG_QUERY_CMPLT = 0x80000004UL, ///< Device response to a query OID. - - RNDIS_MSG_SET = 0x00000005UL, ///< Sent by the host to send a set OID. - RNDIS_MSG_SET_CMPLT = 0x80000005UL, ///< Device response to a set OID. - - RNDIS_MSG_RESET = 0x00000006UL, ///< Sent by the host to perform a soft reset on the device. - RNDIS_MSG_RESET_CMPLT = 0x80000006UL, ///< Device response to reset message. - - RNDIS_MSG_INDICATE_STATUS = 0x00000007UL, ///< Sent by the device to indicate its status or an error when an unrecognized message is received. - - RNDIS_MSG_KEEP_ALIVE = 0x00000008UL, ///< During idle periods, sent every few seconds by the host to check that the device is still responsive. It is optional for the device to send this message to check if the host is active. - RNDIS_MSG_KEEP_ALIVE_CMPLT = 0x80000008UL ///< The device response to a keepalivemessage. The host can respond with this message to a keepalive message from the device when the device implements the optional KeepAliveTimer. -}rndis_msg_type_t; - -/// RNDIS Message Status Values -typedef enum -{ - RNDIS_STATUS_SUCCESS = 0x00000000UL, ///< Success - RNDIS_STATUS_FAILURE = 0xC0000001UL, ///< Unspecified error - RNDIS_STATUS_INVALID_DATA = 0xC0010015UL, ///< Invalid data error - RNDIS_STATUS_NOT_SUPPORTED = 0xC00000BBUL, ///< Unsupported request error - RNDIS_STATUS_MEDIA_CONNECT = 0x4001000BUL, ///< Device is connected to a network medium. - RNDIS_STATUS_MEDIA_DISCONNECT = 0x4001000CUL ///< Device is disconnected from the medium. -}rndis_msg_status_t; - -#ifdef __CC_ARM -#pragma diag_default 66 // return Keil 66 to normal severity -#endif - -//--------------------------------------------------------------------+ -// MESSAGE STRUCTURE -//--------------------------------------------------------------------+ - -//------------- Initialize -------------// -/// \brief Initialize Message -/// \details This message MUST be sent by the host to initialize the device. -typedef struct { - uint32_t type ; ///< Message type, must be \ref RNDIS_MSG_INITIALIZE - uint32_t length ; ///< Message length in bytes, must be 0x18 - uint32_t request_id ; ///< A 32-bit integer value, generated by the host, used to match the host's sent request to the response from the device. - uint32_t major_version ; ///< The major version of the RNDIS Protocol implemented by the host. - uint32_t minor_version ; ///< The minor version of the RNDIS Protocol implemented by the host - uint32_t max_xfer_size ; ///< The maximum size, in bytes, of any single bus data transfer that the host expects to receive from the device. -}rndis_msg_initialize_t; - -/// \brief Initialize Complete Message -/// \details This message MUST be sent by the device in response to an initialize message. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_INITIALIZE_CMPLT - uint32_t length ; ///< Message length in bytes, must be 0x30 - uint32_t request_id ; ///< A 32-bit integer value from \a request_id field of the \ref rndis_msg_initialize_t to which this message is a response. - uint32_t status ; ///< The initialization status of the device, has value from \ref rndis_msg_status_t - uint32_t major_version ; ///< the highest-numbered RNDIS Protocol version supported by the device. - uint32_t minor_version ; ///< the highest-numbered RNDIS Protocol version supported by the device. - uint32_t device_flags ; ///< MUST be set to 0x000000010. Other values are reserved for future use. - uint32_t medium ; ///< is 0x00 for RNDIS_MEDIUM_802_3 - uint32_t max_packet_per_xfer ; ///< The maximum number of concatenated \ref RNDIS_MSG_PACKET messages that the device can handle in a single bus transfer to it. This value MUST be at least 1. - uint32_t max_xfer_size ; ///< The maximum size, in bytes, of any single bus data transfer that the device expects to receive from the host. - uint32_t packet_alignment_factor ; ///< The byte alignment the device expects for each RNDIS message that is part of a multimessage transfer to it. The value is specified as an exponent of 2; for example, the host uses 2{PacketAlignmentFactor} as the alignment value. - uint32_t reserved[2] ; -} rndis_msg_initialize_cmplt_t; - -//------------- Query -------------// -/// \brief Query Message -/// \details This message MUST be sent by the host to query an OID. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_QUERY - uint32_t length ; ///< Message length in bytes, including the header and the \a oid_buffer - uint32_t request_id ; ///< A 32-bit integer value, generated by the host, used to match the host's sent request to the response from the device. - uint32_t oid ; ///< The integer value of the host operating system-defined identifier, for the parameter of the device being queried for. - uint32_t buffer_length ; ///< The length, in bytes, of the input data required for the OID query. This MUST be set to 0 when there is no input data associated with the OID. - uint32_t buffer_offset ; ///< The offset, in bytes, from the beginning of \a request_id field where the input data for the query is located in the message. This value MUST be set to 0 when there is no input data associated with the OID. - uint32_t reserved ; - uint8_t oid_buffer[] ; ///< Flexible array contains the input data supplied by the host, required for the OID query request processing by the device, as per the host NDIS specification. -} rndis_msg_query_t, rndis_msg_set_t; - -TU_VERIFY_STATIC(sizeof(rndis_msg_query_t) == 28, "Make sure flexible array member does not affect layout"); - -/// \brief Query Complete Message -/// \details This message MUST be sent by the device in response to a query OID message. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_QUERY_CMPLT - uint32_t length ; ///< Message length in bytes, including the header and the \a oid_buffer - uint32_t request_id ; ///< A 32-bit integer value from \a request_id field of the \ref rndis_msg_query_t to which this message is a response. - uint32_t status ; ///< The status of processing for the query request, has value from \ref rndis_msg_status_t. - uint32_t buffer_length ; ///< The length, in bytes, of the data in the response to the query. This MUST be set to 0 when there is no OIDInputBuffer. - uint32_t buffer_offset ; ///< The offset, in bytes, from the beginning of \a request_id field where the response data for the query is located in the message. This MUST be set to 0 when there is no \ref oid_buffer. - uint8_t oid_buffer[] ; ///< Flexible array member contains the response data to the OID query request as specified by the host. -} rndis_msg_query_cmplt_t; - -TU_VERIFY_STATIC(sizeof(rndis_msg_query_cmplt_t) == 24, "Make sure flexible array member does not affect layout"); - -//------------- Reset -------------// -/// \brief Reset Message -/// \details This message MUST be sent by the host to perform a soft reset on the device. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_RESET - uint32_t length ; ///< Message length in bytes, MUST be 0x06 - uint32_t reserved ; -} rndis_msg_reset_t; - -/// \brief Reset Complete Message -/// \details This message MUST be sent by the device in response to a reset message. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_RESET_CMPLT - uint32_t length ; ///< Message length in bytes, MUST be 0x10 - uint32_t status ; ///< The status of processing for the \ref rndis_msg_reset_t, has value from \ref rndis_msg_status_t. - uint32_t addressing_reset ; ///< This field indicates whether the addressing information, which is the multicast address list or packet filter, has been lost during the reset operation. This MUST be set to 0x00000001 if the device requires that the host to resend addressing information or MUST be set to zero otherwise. -} rndis_msg_reset_cmplt_t; - -//typedef struct { -// uint32_t type; -// uint32_t length; -// uint32_t status; -// uint32_t buffer_length; -// uint32_t buffer_offset; -// uint32_t diagnostic_status; // optional -// uint32_t diagnostic_error_offset; // optional -// uint32_t status_buffer[0]; // optional -//} rndis_msg_indicate_status_t; - -/// \brief Keep Alive Message -/// \details This message MUST be sent by the host to check that device is still responsive. It is optional for the device to send this message to check if the host is active -typedef struct { - uint32_t type ; ///< Message Type - uint32_t length ; ///< Message length in bytes, MUST be 0x10 - uint32_t request_id ; -} rndis_msg_keep_alive_t, rndis_msg_halt_t; - -/// \brief Set Complete Message -/// \brief This message MUST be sent in response to a the request message -typedef struct { - uint32_t type ; ///< Message Type - uint32_t length ; ///< Message length in bytes, MUST be 0x10 - uint32_t request_id ; ///< must be the same as requesting message - uint32_t status ; ///< The status of processing for the request message request by the device to which this message is the response. -} rndis_msg_set_cmplt_t, rndis_msg_keep_alive_cmplt_t; - -/// \brief Packet Data Message -/// \brief This message MUST be used by the host and the device to send network data to one another. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_PACKET - uint32_t length ; ///< Message length in bytes, The total length of this RNDIS message including the header, payload, and padding. - uint32_t data_offset ; ///< Specifies the offset, in bytes, from the start of this \a data_offset field of this message to the start of the data. This MUST be an integer multiple of 4. - uint32_t data_length ; ///< Specifies the number of bytes in the payload of this message. - uint32_t out_of_band_data_offet ; ///< Specifies the offset, in bytes, of the first out-of-band data record from the start of the DataOffset field in this message. MUST be an integer multiple of 4 when out-of-band data is present or set to 0 otherwise. When there are multiple out-ofband data records, each subsequent record MUST immediately follow the previous out-of-band data record. - uint32_t out_of_band_data_length ; ///< Specifies, in bytes, the total length of the out-of-band data. - uint32_t num_out_of_band_data_elements ; ///< Specifies the number of out-of-band records in this message. - uint32_t per_packet_info_offset ; ///< Specifies the offset, in bytes, of the start of per-packet-info data record from the start of the \a data_offset field in this message. MUST be an integer multiple of 4 when per-packet-info data record is present or MUST be set to 0 otherwise. When there are multiple per-packet-info data records, each subsequent record MUST immediately follow the previous record. - uint32_t per_packet_info_length ; ///< Specifies, in bytes, the total length of per-packetinformation contained in this message. - uint32_t reserved[2] ; - uint32_t payload[0] ; ///< Network data contained in this message. - - // uint8_t padding[0] - // Additional bytes of zeros added at the end of the message to comply with - // the internal and external padding requirements. Internal padding SHOULD be as per the - // specification of the out-of-band data record and per-packet-info data record. The external - //padding size SHOULD be determined based on the PacketAlignmentFactor field specification - //in REMOTE_NDIS_INITIALIZE_CMPLT message by the device, when multiple - //REMOTE_NDIS_PACKET_MSG messages are bundled together in a single bus-native message. - //In this case, all but the very last REMOTE_NDIS_PACKET_MSG MUST respect the - //PacketAlignmentFactor field. - - // rndis_msg_packet_t [0] : (optional) more packet if multiple packet per bus transaction is supported -} rndis_msg_packet_t; - - -typedef struct { - uint32_t size ; ///< Length, in bytes, of this header and appended data and padding. This value MUST be an integer multiple of 4. - uint32_t type ; ///< MUST be as per host operating system specification. - uint32_t offset ; ///< The byte offset from the beginning of this record to the beginning of data. - uint32_t data[0] ; ///< Flexible array contains data -} rndis_msg_out_of_band_data_t, rndis_msg_per_packet_info_t; - -//--------------------------------------------------------------------+ -// NDIS Object ID -//--------------------------------------------------------------------+ - -/// NDIS Object ID -typedef enum -{ - //------------- General Required OIDs -------------// - RNDIS_OID_GEN_SUPPORTED_LIST = 0x00010101, ///< List of supported OIDs - RNDIS_OID_GEN_HARDWARE_STATUS = 0x00010102, ///< Hardware status - RNDIS_OID_GEN_MEDIA_SUPPORTED = 0x00010103, ///< Media types supported (encoded) - RNDIS_OID_GEN_MEDIA_IN_USE = 0x00010104, ///< Media types in use (encoded) - RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD = 0x00010105, ///< - RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE = 0x00010106, ///< Maximum frame size in bytes - RNDIS_OID_GEN_LINK_SPEED = 0x00010107, ///< Link speed in units of 100 bps - RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE = 0x00010108, ///< Transmit buffer space - RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE = 0x00010109, ///< Receive buffer space - RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE = 0x0001010A, ///< Minimum amount of storage, in bytes, that a single packet occupies in the transmit buffer space of the NIC - RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE = 0x0001010B, ///< Amount of storage, in bytes, that a single packet occupies in the receive buffer space of the NIC - RNDIS_OID_GEN_VENDOR_ID = 0x0001010C, ///< Vendor NIC code - RNDIS_OID_GEN_VENDOR_DESCRIPTION = 0x0001010D, ///< Vendor network card description - RNDIS_OID_GEN_CURRENT_PACKET_FILTER = 0x0001010E, ///< Current packet filter (encoded) - RNDIS_OID_GEN_CURRENT_LOOKAHEAD = 0x0001010F, ///< Current lookahead size in bytes - RNDIS_OID_GEN_DRIVER_VERSION = 0x00010110, ///< NDIS version number used by the driver - RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE = 0x00010111, ///< Maximum total packet length in bytes - RNDIS_OID_GEN_PROTOCOL_OPTIONS = 0x00010112, ///< Optional protocol flags (encoded) - RNDIS_OID_GEN_MAC_OPTIONS = 0x00010113, ///< Optional NIC flags (encoded) - RNDIS_OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114, ///< Whether the NIC is connected to the network - RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS = 0x00010115, ///< The maximum number of send packets the driver can accept per call to its MiniportSendPacketsfunction - - //------------- General Optional OIDs -------------// - RNDIS_OID_GEN_VENDOR_DRIVER_VERSION = 0x00010116, ///< Vendor-assigned version number of the driver - RNDIS_OID_GEN_SUPPORTED_GUIDS = 0x00010117, ///< The custom GUIDs (Globally Unique Identifier) supported by the miniport driver - RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES = 0x00010118, ///< List of network-layer addresses associated with the binding between a transport and the driver - RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET = 0x00010119, ///< Size of packets' additional headers - RNDIS_OID_GEN_MEDIA_CAPABILITIES = 0x00010201, ///< - RNDIS_OID_GEN_PHYSICAL_MEDIUM = 0x00010202, ///< Physical media supported by the miniport driver (encoded) - - //------------- 802.3 Objects (Ethernet) -------------// - RNDIS_OID_802_3_PERMANENT_ADDRESS = 0x01010101, ///< Permanent station address - RNDIS_OID_802_3_CURRENT_ADDRESS = 0x01010102, ///< Current station address - RNDIS_OID_802_3_MULTICAST_LIST = 0x01010103, ///< Current multicast address list - RNDIS_OID_802_3_MAXIMUM_LIST_SIZE = 0x01010104, ///< Maximum size of multicast address list -} rndis_oid_type_t; - -/// RNDIS Packet Filter Bits \ref RNDIS_OID_GEN_CURRENT_PACKET_FILTER. -typedef enum -{ - RNDIS_PACKET_TYPE_DIRECTED = 0x00000001, ///< Directed packets. Directed packets contain a destination address equal to the station address of the NIC. - RNDIS_PACKET_TYPE_MULTICAST = 0x00000002, ///< Multicast address packets sent to addresses in the multicast address list. - RNDIS_PACKET_TYPE_ALL_MULTICAST = 0x00000004, ///< All multicast address packets, not just the ones enumerated in the multicast address list. - RNDIS_PACKET_TYPE_BROADCAST = 0x00000008, ///< Broadcast packets. - RNDIS_PACKET_TYPE_SOURCE_ROUTING = 0x00000010, ///< All source routing packets. If the protocol driver sets this bit, the NDIS library attempts to act as a source routing bridge. - RNDIS_PACKET_TYPE_PROMISCUOUS = 0x00000020, ///< Specifies all packets regardless of whether VLAN filtering is enabled or not and whether the VLAN identifier matches or not. - RNDIS_PACKET_TYPE_SMT = 0x00000040, ///< SMT packets that an FDDI NIC receives. - RNDIS_PACKET_TYPE_ALL_LOCAL = 0x00000080, ///< All packets sent by installed protocols and all packets indicated by the NIC that is identified by a given NdisBindingHandle. - RNDIS_PACKET_TYPE_GROUP = 0x00001000, ///< Packets sent to the current group address. - RNDIS_PACKET_TYPE_ALL_FUNCTIONAL = 0x00002000, ///< All functional address packets, not just the ones in the current functional address. - RNDIS_PACKET_TYPE_FUNCTIONAL = 0x00004000, ///< Functional address packets sent to addresses included in the current functional address. - RNDIS_PACKET_TYPE_MAC_FRAME = 0x00008000, ///< NIC driver frames that a Token Ring NIC receives. - RNDIS_PACKET_TYPE_NO_LOCAL = 0x00010000, -} rndis_packet_filter_type_t; - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_RNDIS_H_ */ - -/** @} */ -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c deleted file mode 100644 index cc4ffd1cf..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC && CFG_TUH_CDC_RNDIS) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "cdc_host.h" -#include "cdc_rndis_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -#define RNDIS_MSG_PAYLOAD_MAX (1024*4) - -CFG_TUSB_MEM_SECTION static uint8_t msg_notification[CFG_TUH_DEVICE_MAX][8]; -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX]; - -static rndish_data_t rndish_data[CFG_TUH_DEVICE_MAX]; - -// TODO Microsoft requires message length for any get command must be at least 4096 bytes - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static tusb_error_t rndis_body_subtask(void); -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response ); - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -tusb_error_t tusbh_cdc_rndis_get_mac_addr(uint8_t dev_addr, uint8_t mac_address[6]) -{ - TU_ASSERT( tusbh_cdc_rndis_is_mounted(dev_addr), TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED); - TU_VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); - - memcpy(mac_address, rndish_data[dev_addr-1].mac_address, 6); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ - -// To enable the TASK_ASSERT style (quick return on false condition) in a real RTOS, a task must act as a wrapper -// and is used mainly to call subtasks. Within a subtask return statement can be called freely, the task with -// forever loop cannot have any return at all. -OSAL_TASK_FUNCTION(cdch_rndis_task) (void* param;) -{ - OSAL_TASK_BEGIN - rndis_body_subtask(); - OSAL_TASK_END -} - -static tusb_error_t rndis_body_subtask(void) -{ - static uint8_t relative_addr; - - OSAL_SUBTASK_BEGIN - - for (relative_addr = 0; relative_addr < CFG_TUH_DEVICE_MAX; relative_addr++) - { - - } - - osal_task_delay(100); - - OSAL_SUBTASK_END -} - -//--------------------------------------------------------------------+ -// RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -void rndish_init(void) -{ - tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUH_DEVICE_MAX); - - //------------- Task creation -------------// - - //------------- semaphore creation for notificaiton pipe -------------// - for(uint8_t i=0; itype == RNDIS_MSG_INITIALIZE_CMPLT && p_init_cmpt->status == RNDIS_STATUS_SUCCESS && - p_init_cmpt->max_packet_per_xfer == 1 && p_init_cmpt->max_xfer_size <= RNDIS_MSG_PAYLOAD_MAX); - rndish_data[dev_addr-1].max_xfer_size = p_init_cmpt->max_xfer_size; - - //------------- Message Query 802.3 Permanent Address -------------// - memcpy(msg_payload, &msg_query_permanent_addr, sizeof(rndis_msg_query_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_query_t) + 6, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_query_cmplt_t * const p_query_cmpt = (rndis_msg_query_cmplt_t *) msg_payload; - STASK_ASSERT(p_query_cmpt->type == RNDIS_MSG_QUERY_CMPLT && p_query_cmpt->status == RNDIS_STATUS_SUCCESS); - memcpy(rndish_data[dev_addr-1].mac_address, msg_payload + 8 + p_query_cmpt->buffer_offset, 6); - - //------------- Set OID_GEN_CURRENT_PACKET_FILTER to (DIRECTED | MULTICAST | BROADCAST) -------------// - memcpy(msg_payload, &msg_set_packet_filter, sizeof(rndis_msg_set_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags - ((rndis_msg_set_t*) msg_payload)->oid_buffer[0] = (RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_MULTICAST | RNDIS_PACKET_TYPE_BROADCAST); - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_set_t) + 4, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_set_cmplt_t * const p_set_cmpt = (rndis_msg_set_cmplt_t *) msg_payload; - STASK_ASSERT(p_set_cmpt->type == RNDIS_MSG_SET_CMPLT && p_set_cmpt->status == RNDIS_STATUS_SUCCESS); - - tusbh_cdc_rndis_mounted_cb(dev_addr); - - OSAL_SUBTASK_END -} - -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) -{ - if ( pipehandle_is_equal(pipe_hdl, p_cdc->pipe_notification) ) - { - osal_semaphore_post( rndish_data[pipe_hdl.dev_addr-1].sem_notification_hdl ); - } -} - -//--------------------------------------------------------------------+ -// INTERNAL & HELPER -//--------------------------------------------------------------------+ -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - //------------- Send RNDIS Control Message -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_SEND_ENCAPSULATED_COMMAND, 0, p_cdc->interface_number, - mess_length, p_mess), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - //------------- waiting for Response Available notification -------------// - (void) usbh_edpt_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8); - osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - STASK_ASSERT(msg_notification[dev_addr-1][0] == 1); - - //------------- Get RNDIS Message Initialize Complete -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_GET_ENCAPSULATED_RESPONSE, 0, p_cdc->interface_number, - RNDIS_MSG_PAYLOAD_MAX, p_response), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - OSAL_SUBTASK_END -} - -//static tusb_error_t send_process_msg_initialize_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) -//{ -// tusb_error_t error; -// -// OSAL_SUBTASK_BEGIN -// -// *((rndis_msg_initialize_t*) msg_payload) = (rndis_msg_initialize_t) -// { -// .type = RNDIS_MSG_INITIALIZE, -// .length = sizeof(rndis_msg_initialize_t), -// .request_id = 1, // TODO should use some magic number -// .major_version = 1, -// .minor_version = 0, -// .max_xfer_size = 0x4000 // TODO mimic windows -// }; -// -// -// -// OSAL_SUBTASK_END -//} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h deleted file mode 100644 index 170cb3b0e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup CDC_RNDIS - * \defgroup CDC_RNSID_Host Host - * @{ */ - -#ifndef _TUSB_CDC_RNDIS_HOST_H_ -#define _TUSB_CDC_RNDIS_HOST_H_ - -#include "common/tusb_common.h" -#include "host/usbh.h" -#include "cdc_rndis.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// INTERNAL RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -typedef struct { - OSAL_SEM_DEF(semaphore_notification); - osal_semaphore_handle_t sem_notification_hdl; // used to wait on notification pipe - uint32_t max_xfer_size; // got from device's msg initialize complete - uint8_t mac_address[6]; -}rndish_data_t; - -void rndish_init(void); -tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc); -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); -void rndish_close(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_RNDIS_HOST_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h deleted file mode 100644 index 114c827b8..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_H_ -#define _TUSB_DFU_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Common Definitions -//--------------------------------------------------------------------+ - -// DFU Protocol -typedef enum -{ - DFU_PROTOCOL_RT = 0x01, - DFU_PROTOCOL_DFU = 0x02, -} dfu_protocol_type_t; - -// DFU Descriptor Type -typedef enum -{ - DFU_DESC_FUNCTIONAL = 0x21, -} dfu_descriptor_type_t; - -// DFU Requests -typedef enum { - DFU_REQUEST_DETACH = 0, - DFU_REQUEST_DNLOAD = 1, - DFU_REQUEST_UPLOAD = 2, - DFU_REQUEST_GETSTATUS = 3, - DFU_REQUEST_CLRSTATUS = 4, - DFU_REQUEST_GETSTATE = 5, - DFU_REQUEST_ABORT = 6, -} dfu_requests_t; - -// DFU States -typedef enum { - APP_IDLE = 0, - APP_DETACH = 1, - DFU_IDLE = 2, - DFU_DNLOAD_SYNC = 3, - DFU_DNBUSY = 4, - DFU_DNLOAD_IDLE = 5, - DFU_MANIFEST_SYNC = 6, - DFU_MANIFEST = 7, - DFU_MANIFEST_WAIT_RESET = 8, - DFU_UPLOAD_IDLE = 9, - DFU_ERROR = 10, -} dfu_state_t; - -// DFU Status -typedef enum { - DFU_STATUS_OK = 0x00, - DFU_STATUS_ERR_TARGET = 0x01, - DFU_STATUS_ERR_FILE = 0x02, - DFU_STATUS_ERR_WRITE = 0x03, - DFU_STATUS_ERR_ERASE = 0x04, - DFU_STATUS_ERR_CHECK_ERASED = 0x05, - DFU_STATUS_ERR_PROG = 0x06, - DFU_STATUS_ERR_VERIFY = 0x07, - DFU_STATUS_ERR_ADDRESS = 0x08, - DFU_STATUS_ERR_NOTDONE = 0x09, - DFU_STATUS_ERR_FIRMWARE = 0x0A, - DFU_STATUS_ERR_VENDOR = 0x0B, - DFU_STATUS_ERR_USBR = 0x0C, - DFU_STATUS_ERR_POR = 0x0D, - DFU_STATUS_ERR_UNKNOWN = 0x0E, - DFU_STATUS_ERR_STALLEDPKT = 0x0F, -} dfu_status_t; - -#define DFU_ATTR_CAN_DOWNLOAD (1u << 0) -#define DFU_ATTR_CAN_UPLOAD (1u << 1) -#define DFU_ATTR_MANIFESTATION_TOLERANT (1u << 2) -#define DFU_ATTR_WILL_DETACH (1u << 3) - -// DFU Status Request Payload -typedef struct TU_ATTR_PACKED -{ - uint8_t bStatus; - uint8_t bwPollTimeout[3]; - uint8_t bState; - uint8_t iString; -} dfu_status_response_t; - -TU_VERIFY_STATIC( sizeof(dfu_status_response_t) == 6, "size is not correct"); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c deleted file mode 100644 index ddfa608e4..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "dfu_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t attrs; - uint8_t alt; - - dfu_state_t state; - dfu_status_t status; - - bool flashing_in_progress; - uint16_t block; - uint16_t length; - - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE]; -} dfu_state_ctx_t; - -// Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_ctx; - -static void reset_state(void) -{ - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.flashing_in_progress = false; -} - -static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout); -static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -static tu_lookup_entry_t const _dfu_request_lookup[] = -{ - { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, - { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, - { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, - { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, - { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, - { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, - { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, -}; - -static tu_lookup_table_t const _dfu_request_table = -{ - .count = TU_ARRAY_SIZE(_dfu_request_lookup), - .items = _dfu_request_lookup -}; - -static tu_lookup_entry_t const _dfu_state_lookup[] = -{ - { .key = APP_IDLE , .data = "APP_IDLE" }, - { .key = APP_DETACH , .data = "APP_DETACH" }, - { .key = DFU_IDLE , .data = "IDLE" }, - { .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" }, - { .key = DFU_DNBUSY , .data = "DNBUSY" }, - { .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" }, - { .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" }, - { .key = DFU_MANIFEST , .data = "MANIFEST" }, - { .key = DFU_MANIFEST_WAIT_RESET , .data = "MANIFEST_WAIT_RESET" }, - { .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" }, - { .key = DFU_ERROR , .data = "ERROR" }, -}; - -static tu_lookup_table_t const _dfu_state_table = -{ - .count = TU_ARRAY_SIZE(_dfu_state_lookup), - .items = _dfu_state_lookup -}; - -static tu_lookup_entry_t const _dfu_status_lookup[] = -{ - { .key = DFU_STATUS_OK , .data = "OK" }, - { .key = DFU_STATUS_ERR_TARGET , .data = "errTARGET" }, - { .key = DFU_STATUS_ERR_FILE , .data = "errFILE" }, - { .key = DFU_STATUS_ERR_WRITE , .data = "errWRITE" }, - { .key = DFU_STATUS_ERR_ERASE , .data = "errERASE" }, - { .key = DFU_STATUS_ERR_CHECK_ERASED , .data = "errCHECK_ERASED" }, - { .key = DFU_STATUS_ERR_PROG , .data = "errPROG" }, - { .key = DFU_STATUS_ERR_VERIFY , .data = "errVERIFY" }, - { .key = DFU_STATUS_ERR_ADDRESS , .data = "errADDRESS" }, - { .key = DFU_STATUS_ERR_NOTDONE , .data = "errNOTDONE" }, - { .key = DFU_STATUS_ERR_FIRMWARE , .data = "errFIRMWARE" }, - { .key = DFU_STATUS_ERR_VENDOR , .data = "errVENDOR" }, - { .key = DFU_STATUS_ERR_USBR , .data = "errUSBR" }, - { .key = DFU_STATUS_ERR_POR , .data = "errPOR" }, - { .key = DFU_STATUS_ERR_UNKNOWN , .data = "errUNKNOWN" }, - { .key = DFU_STATUS_ERR_STALLEDPKT , .data = "errSTALLEDPKT" }, -}; - -static tu_lookup_table_t const _dfu_status_table = -{ - .count = TU_ARRAY_SIZE(_dfu_status_lookup), - .items = _dfu_status_lookup -}; - -#endif - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_moded_reset(uint8_t rhport) -{ - (void) rhport; - - _dfu_ctx.attrs = 0; - _dfu_ctx.alt = 0; - - reset_state(); -} - -void dfu_moded_init(void) -{ - dfu_moded_reset(0); -} - -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - - //------------- Interface (with Alt) descriptor -------------// - uint8_t const itf_num = itf_desc->bInterfaceNumber; - uint8_t alt_count = 0; - - uint16_t drv_len = 0; - while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) - { - TU_ASSERT(max_len > drv_len, 0); - - // Alternate must have the same interface number - TU_ASSERT(itf_desc->bInterfaceNumber == itf_num, 0); - - // Alt should increase by one every time - TU_ASSERT(itf_desc->bAlternateSetting == alt_count, 0); - alt_count++; - - drv_len += tu_desc_len(itf_desc); - itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc); - } - - //------------- DFU Functional descriptor -------------// - tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc; - TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0); - drv_len += sizeof(tusb_desc_dfu_functional_t); - - _dfu_ctx.attrs = func_desc->bAttributes; - - // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR - uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t const*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) ); - TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status)); - - if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) - { - // Standard request include GET/SET_INTERFACE - switch ( request->bRequest ) - { - case TUSB_REQ_SET_INTERFACE: - if ( stage == CONTROL_STAGE_SETUP ) - { - // Switch Alt interface and reset state machine - _dfu_ctx.alt = (uint8_t) request->wValue; - reset_state(); - return tud_control_status(rhport, request); - } - break; - - case TUSB_REQ_GET_INTERFACE: - if(stage == CONTROL_STAGE_SETUP) - { - return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1); - } - break; - - // unsupported request - default: return false; - } - } - else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) - { - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - - // Class request - switch ( request->bRequest ) - { - case DFU_REQUEST_DETACH: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( tud_dfu_detach_cb ) tud_dfu_detach_cb(); - } - break; - - case DFU_REQUEST_CLRSTATUS: - if ( stage == CONTROL_STAGE_SETUP ) - { - reset_state(); - tud_control_status(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); - } - break; - - case DFU_REQUEST_ABORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - reset_state(); - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt); - } - break; - - case DFU_REQUEST_UPLOAD: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); - TU_VERIFY(tud_dfu_upload_cb); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); - - uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); - - return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); - } - break; - - case DFU_REQUEST_DNLOAD: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); - TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); - - // set to true for both download and manifest - _dfu_ctx.flashing_in_progress = true; - - // save block and length for flashing - _dfu_ctx.block = request->wValue; - _dfu_ctx.length = request->wLength; - - if ( request->wLength ) - { - // Download with payload -> transition to DOWNLOAD SYNC - _dfu_ctx.state = DFU_DNLOAD_SYNC; - return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); - } - else - { - // Download is complete -> transition to MANIFEST SYNC - _dfu_ctx.state = DFU_MANIFEST_SYNC; - return tud_control_status(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATUS: - switch ( _dfu_ctx.state ) - { - case DFU_DNLOAD_SYNC: - return process_download_get_status(rhport, stage, request); - break; - - case DFU_MANIFEST_SYNC: - return process_manifest_get_status(rhport, stage, request); - break; - - default: - if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0); - break; - } - break; - - default: return false; // stall unsupported request - } - }else - { - return false; // unsupported request - } - - return true; -} - -void tud_dfu_finish_flashing(uint8_t status) -{ - _dfu_ctx.flashing_in_progress = false; - - if ( status == DFU_STATUS_OK ) - { - if (_dfu_ctx.state == DFU_DNBUSY) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - } - else if (_dfu_ctx.state == DFU_MANIFEST) - { - _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) - ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET; - } - } - else - { - // failed while flashing, move to dfuError - _dfu_ctx.state = DFU_ERROR; - _dfu_ctx.status = (dfu_status_t)status; - } -} - -static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - // only transition to next state on CONTROL_STAGE_ACK - dfu_state_t next_state; - uint32_t timeout; - - if ( _dfu_ctx.flashing_in_progress ) - { - next_state = DFU_DNBUSY; - timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state); - } - else - { - next_state = DFU_DNLOAD_IDLE; - timeout = 0; - } - - return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_DNBUSY; - tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length); - }else - { - _dfu_ctx.state = DFU_DNLOAD_IDLE; - } - } - - return true; -} - -static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - // only transition to next state on CONTROL_STAGE_ACK - dfu_state_t next_state; - uint32_t timeout; - - if ( _dfu_ctx.flashing_in_progress ) - { - next_state = DFU_MANIFEST; - timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state); - } - else - { - next_state = DFU_IDLE; - timeout = 0; - } - - return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_MANIFEST; - tud_dfu_manifest_cb(_dfu_ctx.alt); - } - else - { - _dfu_ctx.state = DFU_IDLE; - } - } - - return true; -} - -static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout) -{ - dfu_status_response_t resp; - resp.bStatus = (uint8_t) status; - resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); - resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); - resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); - resp.bState = (uint8_t) state; - resp.iString = 0; - - return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h deleted file mode 100644 index fecf8596f..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_DEVICE_H_ -#define _TUSB_DFU_DEVICE_H_ - -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Default Configure & Validation -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_DFU_XFER_BUFSIZE) - #error "CFG_TUD_DFU_XFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Must be called when the application is done with flashing started by -// tud_dfu_download_cb() and tud_dfu_manifest_cb(). -// status is DFU_STATUS_OK if successful, any other error status will cause state to enter dfuError -void tud_dfu_finish_flashing(uint8_t status); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. - -// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) -// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. -// During this period, USB host won't try to communicate with us. -uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state); - -// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests -// This callback could be returned before flashing op is complete (async). -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_download_cb (uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length); - -// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) -// Application can do checksum, or actual flashing if buffered entire image previously. -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_manifest_cb(uint8_t alt); - -// Invoked when received DFU_UPLOAD request -// Application must populate data with up to length bytes and -// Return the number of written bytes -TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); - -// Invoked when a DFU_DETACH request is received -TU_ATTR_WEAK void tud_dfu_detach_cb(void); - -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_moded_init(void); -void dfu_moded_reset(uint8_t rhport); -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c deleted file mode 100644 index afee2aa1f..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Sylvain Munaut - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "dfu_rt_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_rtd_init(void) -{ -} - -void dfu_rtd_reset(uint8_t rhport) -{ - (void) rhport; -} - -uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - (void) max_len; - - // Ensure this is DFU Runtime - TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT), 0); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA or ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) - { - tud_control_status(rhport, request); - return true; - } - - // Handle class request only from here - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch (request->bRequest) - { - case DFU_REQUEST_DETACH: - { - TU_LOG2(" DFU RT Request: DETACH\r\n"); - tud_control_status(rhport, request); - tud_dfu_runtime_reboot_to_dfu_cb(); - } - break; - - case DFU_REQUEST_GETSTATUS: - { - TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); - dfu_status_response_t resp; - // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 - memset(&resp, 0x00, sizeof(dfu_status_response_t)); - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); - } - break; - - default: - { - TU_LOG2(" DFU RT Unexpected Request: %d\r\n", request->bRequest); - return false; // stall unsupported request - } - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h deleted file mode 100644 index babaa8214..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Sylvain Munaut - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_RT_DEVICE_H_ -#define _TUSB_DFU_RT_DEVICE_H_ - -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -// Invoked when a DFU_DETACH request is received and bitWillDetach is set -void tud_dfu_runtime_reboot_to_dfu_cb(void); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_rtd_init(void); -void dfu_rtd_reset(uint8_t rhport); -uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_RT_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h deleted file mode 100644 index 9265a2ede..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_HID Human Interface Device (HID) - * @{ */ - -#ifndef _TUSB_HID_H_ -#define _TUSB_HID_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Common Definitions -//--------------------------------------------------------------------+ -/** \defgroup ClassDriver_HID_Common Common Definitions - * @{ */ - - /// USB HID Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */ - uint8_t bDescriptorType; /**< Constant name specifying type of HID descriptor. */ - - uint16_t bcdHID; /**< Numeric expression identifying the HID Class Specification release */ - uint8_t bCountryCode; /**< Numeric expression identifying country code of the localized hardware. */ - uint8_t bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */ - - uint8_t bReportType; /**< Type of HID class report. */ - uint16_t wReportLength; /**< the total size of the Report descriptor. */ -} tusb_hid_descriptor_hid_t; - -/// HID Subclass -typedef enum -{ - HID_SUBCLASS_NONE = 0, ///< No Subclass - HID_SUBCLASS_BOOT = 1 ///< Boot Interface Subclass -}hid_subclass_enum_t; - -/// HID Interface Protocol -typedef enum -{ - HID_ITF_PROTOCOL_NONE = 0, ///< None - HID_ITF_PROTOCOL_KEYBOARD = 1, ///< Keyboard - HID_ITF_PROTOCOL_MOUSE = 2 ///< Mouse -}hid_interface_protocol_enum_t; - -/// HID Descriptor Type -typedef enum -{ - HID_DESC_TYPE_HID = 0x21, ///< HID Descriptor - HID_DESC_TYPE_REPORT = 0x22, ///< Report Descriptor - HID_DESC_TYPE_PHYSICAL = 0x23 ///< Physical Descriptor -}hid_descriptor_enum_t; - -/// HID Request Report Type -typedef enum -{ - HID_REPORT_TYPE_INVALID = 0, - HID_REPORT_TYPE_INPUT, ///< Input - HID_REPORT_TYPE_OUTPUT, ///< Output - HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_type_t; - -/// HID Class Specific Control Request -typedef enum -{ - HID_REQ_CONTROL_GET_REPORT = 0x01, ///< Get Report - HID_REQ_CONTROL_GET_IDLE = 0x02, ///< Get Idle - HID_REQ_CONTROL_GET_PROTOCOL = 0x03, ///< Get Protocol - HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report - HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle - HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol -}hid_request_enum_t; - -/// HID Local Code -typedef enum -{ - HID_LOCAL_NotSupported = 0 , ///< NotSupported - HID_LOCAL_Arabic , ///< Arabic - HID_LOCAL_Belgian , ///< Belgian - HID_LOCAL_Canadian_Bilingual , ///< Canadian_Bilingual - HID_LOCAL_Canadian_French , ///< Canadian_French - HID_LOCAL_Czech_Republic , ///< Czech_Republic - HID_LOCAL_Danish , ///< Danish - HID_LOCAL_Finnish , ///< Finnish - HID_LOCAL_French , ///< French - HID_LOCAL_German , ///< German - HID_LOCAL_Greek , ///< Greek - HID_LOCAL_Hebrew , ///< Hebrew - HID_LOCAL_Hungary , ///< Hungary - HID_LOCAL_International , ///< International - HID_LOCAL_Italian , ///< Italian - HID_LOCAL_Japan_Katakana , ///< Japan_Katakana - HID_LOCAL_Korean , ///< Korean - HID_LOCAL_Latin_American , ///< Latin_American - HID_LOCAL_Netherlands_Dutch , ///< Netherlands/Dutch - HID_LOCAL_Norwegian , ///< Norwegian - HID_LOCAL_Persian_Farsi , ///< Persian (Farsi) - HID_LOCAL_Poland , ///< Poland - HID_LOCAL_Portuguese , ///< Portuguese - HID_LOCAL_Russia , ///< Russia - HID_LOCAL_Slovakia , ///< Slovakia - HID_LOCAL_Spanish , ///< Spanish - HID_LOCAL_Swedish , ///< Swedish - HID_LOCAL_Swiss_French , ///< Swiss/French - HID_LOCAL_Swiss_German , ///< Swiss/German - HID_LOCAL_Switzerland , ///< Switzerland - HID_LOCAL_Taiwan , ///< Taiwan - HID_LOCAL_Turkish_Q , ///< Turkish-Q - HID_LOCAL_UK , ///< UK - HID_LOCAL_US , ///< US - HID_LOCAL_Yugoslavia , ///< Yugoslavia - HID_LOCAL_Turkish_F ///< Turkish-F -} hid_local_enum_t; - -// HID protocol value used by GetProtocol / SetProtocol -typedef enum -{ - HID_PROTOCOL_BOOT = 0, - HID_PROTOCOL_REPORT = 1 -} hid_protocol_mode_enum_t; - -/** @} */ - -//--------------------------------------------------------------------+ -// GAMEPAD -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Gamepad Gamepad - * @{ */ - -/* From https://www.kernel.org/doc/html/latest/input/gamepad.html - ____________________________ __ - / [__ZL__] [__ZR__] \ | - / [__ TL __] [__ TR __] \ | Front Triggers - __/________________________________\__ __| - / _ \ | - / /\ __ (N) \ | - / || __ |MO| __ _ _ \ | Main Pad - | <===DP===> |SE| |ST| (W) -|- (E) | | - \ || ___ ___ _ / | - /\ \/ / \ / \ (S) /\ __| - / \________ | LS | ____ | RS | ________/ \ | -| / \ \___/ / \ \___/ / \ | | Control Sticks -| / \_____/ \_____/ \ | __| -| / \ | - \_____/ \_____/ - - |________|______| |______|___________| - D-Pad Left Right Action Pad - Stick Stick - - |_____________| - Menu Pad - - Most gamepads have the following features: - - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST. - - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right. - - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START. - - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also - provide a digital button if you press them. - - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons - are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right. - - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors. - */ - -/// HID Gamepad Protocol Report. -typedef struct TU_ATTR_PACKED -{ - int8_t x; ///< Delta x movement of left analog-stick - int8_t y; ///< Delta y movement of left analog-stick - int8_t z; ///< Delta z movement of right analog-joystick - int8_t rz; ///< Delta Rz movement of right analog-joystick - int8_t rx; ///< Delta Rx movement of analog left trigger - int8_t ry; ///< Delta Ry movement of analog right trigger - uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat - uint32_t buttons; ///< Buttons mask for currently pressed buttons -}hid_gamepad_report_t; - -/// Standard Gamepad Buttons Bitmap -typedef enum -{ - GAMEPAD_BUTTON_0 = TU_BIT(0), - GAMEPAD_BUTTON_1 = TU_BIT(1), - GAMEPAD_BUTTON_2 = TU_BIT(2), - GAMEPAD_BUTTON_3 = TU_BIT(3), - GAMEPAD_BUTTON_4 = TU_BIT(4), - GAMEPAD_BUTTON_5 = TU_BIT(5), - GAMEPAD_BUTTON_6 = TU_BIT(6), - GAMEPAD_BUTTON_7 = TU_BIT(7), - GAMEPAD_BUTTON_8 = TU_BIT(8), - GAMEPAD_BUTTON_9 = TU_BIT(9), - GAMEPAD_BUTTON_10 = TU_BIT(10), - GAMEPAD_BUTTON_11 = TU_BIT(11), - GAMEPAD_BUTTON_12 = TU_BIT(12), - GAMEPAD_BUTTON_13 = TU_BIT(13), - GAMEPAD_BUTTON_14 = TU_BIT(14), - GAMEPAD_BUTTON_15 = TU_BIT(15), - GAMEPAD_BUTTON_16 = TU_BIT(16), - GAMEPAD_BUTTON_17 = TU_BIT(17), - GAMEPAD_BUTTON_18 = TU_BIT(18), - GAMEPAD_BUTTON_19 = TU_BIT(19), - GAMEPAD_BUTTON_20 = TU_BIT(20), - GAMEPAD_BUTTON_21 = TU_BIT(21), - GAMEPAD_BUTTON_22 = TU_BIT(22), - GAMEPAD_BUTTON_23 = TU_BIT(23), - GAMEPAD_BUTTON_24 = TU_BIT(24), - GAMEPAD_BUTTON_25 = TU_BIT(25), - GAMEPAD_BUTTON_26 = TU_BIT(26), - GAMEPAD_BUTTON_27 = TU_BIT(27), - GAMEPAD_BUTTON_28 = TU_BIT(28), - GAMEPAD_BUTTON_29 = TU_BIT(29), - GAMEPAD_BUTTON_30 = TU_BIT(30), - GAMEPAD_BUTTON_31 = TU_BIT(31), -}hid_gamepad_button_bm_t; - -/// Standard Gamepad Buttons Naming from Linux input event codes -/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h -#define GAMEPAD_BUTTON_A GAMEPAD_BUTTON_0 -#define GAMEPAD_BUTTON_SOUTH GAMEPAD_BUTTON_0 - -#define GAMEPAD_BUTTON_B GAMEPAD_BUTTON_1 -#define GAMEPAD_BUTTON_EAST GAMEPAD_BUTTON_1 - -#define GAMEPAD_BUTTON_C GAMEPAD_BUTTON_2 - -#define GAMEPAD_BUTTON_X GAMEPAD_BUTTON_3 -#define GAMEPAD_BUTTON_NORTH GAMEPAD_BUTTON_3 - -#define GAMEPAD_BUTTON_Y GAMEPAD_BUTTON_4 -#define GAMEPAD_BUTTON_WEST GAMEPAD_BUTTON_4 - -#define GAMEPAD_BUTTON_Z GAMEPAD_BUTTON_5 -#define GAMEPAD_BUTTON_TL GAMEPAD_BUTTON_6 -#define GAMEPAD_BUTTON_TR GAMEPAD_BUTTON_7 -#define GAMEPAD_BUTTON_TL2 GAMEPAD_BUTTON_8 -#define GAMEPAD_BUTTON_TR2 GAMEPAD_BUTTON_9 -#define GAMEPAD_BUTTON_SELECT GAMEPAD_BUTTON_10 -#define GAMEPAD_BUTTON_START GAMEPAD_BUTTON_11 -#define GAMEPAD_BUTTON_MODE GAMEPAD_BUTTON_12 -#define GAMEPAD_BUTTON_THUMBL GAMEPAD_BUTTON_13 -#define GAMEPAD_BUTTON_THUMBR GAMEPAD_BUTTON_14 - -/// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) -typedef enum -{ - GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED - GAMEPAD_HAT_UP = 1, ///< DPAD_UP - GAMEPAD_HAT_UP_RIGHT = 2, ///< DPAD_UP_RIGHT - GAMEPAD_HAT_RIGHT = 3, ///< DPAD_RIGHT - GAMEPAD_HAT_DOWN_RIGHT = 4, ///< DPAD_DOWN_RIGHT - GAMEPAD_HAT_DOWN = 5, ///< DPAD_DOWN - GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT - GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT - GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT -}hid_gamepad_hat_t; - -/// @} - -//--------------------------------------------------------------------+ -// MOUSE -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Mouse Mouse - * @{ */ - -/// Standard HID Boot Protocol Mouse Report. -typedef struct TU_ATTR_PACKED -{ - uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */ - int8_t x; /**< Current delta x movement of the mouse. */ - int8_t y; /**< Current delta y movement on the mouse. */ - int8_t wheel; /**< Current delta wheel movement on the mouse. */ - int8_t pan; // using AC Pan -} hid_mouse_report_t; - -/// Standard Mouse Buttons Bitmap -typedef enum -{ - MOUSE_BUTTON_LEFT = TU_BIT(0), ///< Left button - MOUSE_BUTTON_RIGHT = TU_BIT(1), ///< Right button - MOUSE_BUTTON_MIDDLE = TU_BIT(2), ///< Middle button - MOUSE_BUTTON_BACKWARD = TU_BIT(3), ///< Backward button, - MOUSE_BUTTON_FORWARD = TU_BIT(4), ///< Forward button, -}hid_mouse_button_bm_t; - -/// @} - -//--------------------------------------------------------------------+ -// Keyboard -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Keyboard Keyboard - * @{ */ - -/// Standard HID Boot Protocol Keyboard Report. -typedef struct TU_ATTR_PACKED -{ - uint8_t modifier; /**< Keyboard modifier (KEYBOARD_MODIFIER_* masks). */ - uint8_t reserved; /**< Reserved for OEM use, always set to 0. */ - uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */ -} hid_keyboard_report_t; - -/// Keyboard modifier codes bitmap -typedef enum -{ - KEYBOARD_MODIFIER_LEFTCTRL = TU_BIT(0), ///< Left Control - KEYBOARD_MODIFIER_LEFTSHIFT = TU_BIT(1), ///< Left Shift - KEYBOARD_MODIFIER_LEFTALT = TU_BIT(2), ///< Left Alt - KEYBOARD_MODIFIER_LEFTGUI = TU_BIT(3), ///< Left Window - KEYBOARD_MODIFIER_RIGHTCTRL = TU_BIT(4), ///< Right Control - KEYBOARD_MODIFIER_RIGHTSHIFT = TU_BIT(5), ///< Right Shift - KEYBOARD_MODIFIER_RIGHTALT = TU_BIT(6), ///< Right Alt - KEYBOARD_MODIFIER_RIGHTGUI = TU_BIT(7) ///< Right Window -}hid_keyboard_modifier_bm_t; - -typedef enum -{ - KEYBOARD_LED_NUMLOCK = TU_BIT(0), ///< Num Lock LED - KEYBOARD_LED_CAPSLOCK = TU_BIT(1), ///< Caps Lock LED - KEYBOARD_LED_SCROLLLOCK = TU_BIT(2), ///< Scroll Lock LED - KEYBOARD_LED_COMPOSE = TU_BIT(3), ///< Composition Mode - KEYBOARD_LED_KANA = TU_BIT(4) ///< Kana mode -}hid_keyboard_led_bm_t; - -/// @} - -//--------------------------------------------------------------------+ -// HID KEYCODE -//--------------------------------------------------------------------+ -#define HID_KEY_NONE 0x00 -#define HID_KEY_A 0x04 -#define HID_KEY_B 0x05 -#define HID_KEY_C 0x06 -#define HID_KEY_D 0x07 -#define HID_KEY_E 0x08 -#define HID_KEY_F 0x09 -#define HID_KEY_G 0x0A -#define HID_KEY_H 0x0B -#define HID_KEY_I 0x0C -#define HID_KEY_J 0x0D -#define HID_KEY_K 0x0E -#define HID_KEY_L 0x0F -#define HID_KEY_M 0x10 -#define HID_KEY_N 0x11 -#define HID_KEY_O 0x12 -#define HID_KEY_P 0x13 -#define HID_KEY_Q 0x14 -#define HID_KEY_R 0x15 -#define HID_KEY_S 0x16 -#define HID_KEY_T 0x17 -#define HID_KEY_U 0x18 -#define HID_KEY_V 0x19 -#define HID_KEY_W 0x1A -#define HID_KEY_X 0x1B -#define HID_KEY_Y 0x1C -#define HID_KEY_Z 0x1D -#define HID_KEY_1 0x1E -#define HID_KEY_2 0x1F -#define HID_KEY_3 0x20 -#define HID_KEY_4 0x21 -#define HID_KEY_5 0x22 -#define HID_KEY_6 0x23 -#define HID_KEY_7 0x24 -#define HID_KEY_8 0x25 -#define HID_KEY_9 0x26 -#define HID_KEY_0 0x27 -#define HID_KEY_ENTER 0x28 -#define HID_KEY_ESCAPE 0x29 -#define HID_KEY_BACKSPACE 0x2A -#define HID_KEY_TAB 0x2B -#define HID_KEY_SPACE 0x2C -#define HID_KEY_MINUS 0x2D -#define HID_KEY_EQUAL 0x2E -#define HID_KEY_BRACKET_LEFT 0x2F -#define HID_KEY_BRACKET_RIGHT 0x30 -#define HID_KEY_BACKSLASH 0x31 -#define HID_KEY_EUROPE_1 0x32 -#define HID_KEY_SEMICOLON 0x33 -#define HID_KEY_APOSTROPHE 0x34 -#define HID_KEY_GRAVE 0x35 -#define HID_KEY_COMMA 0x36 -#define HID_KEY_PERIOD 0x37 -#define HID_KEY_SLASH 0x38 -#define HID_KEY_CAPS_LOCK 0x39 -#define HID_KEY_F1 0x3A -#define HID_KEY_F2 0x3B -#define HID_KEY_F3 0x3C -#define HID_KEY_F4 0x3D -#define HID_KEY_F5 0x3E -#define HID_KEY_F6 0x3F -#define HID_KEY_F7 0x40 -#define HID_KEY_F8 0x41 -#define HID_KEY_F9 0x42 -#define HID_KEY_F10 0x43 -#define HID_KEY_F11 0x44 -#define HID_KEY_F12 0x45 -#define HID_KEY_PRINT_SCREEN 0x46 -#define HID_KEY_SCROLL_LOCK 0x47 -#define HID_KEY_PAUSE 0x48 -#define HID_KEY_INSERT 0x49 -#define HID_KEY_HOME 0x4A -#define HID_KEY_PAGE_UP 0x4B -#define HID_KEY_DELETE 0x4C -#define HID_KEY_END 0x4D -#define HID_KEY_PAGE_DOWN 0x4E -#define HID_KEY_ARROW_RIGHT 0x4F -#define HID_KEY_ARROW_LEFT 0x50 -#define HID_KEY_ARROW_DOWN 0x51 -#define HID_KEY_ARROW_UP 0x52 -#define HID_KEY_NUM_LOCK 0x53 -#define HID_KEY_KEYPAD_DIVIDE 0x54 -#define HID_KEY_KEYPAD_MULTIPLY 0x55 -#define HID_KEY_KEYPAD_SUBTRACT 0x56 -#define HID_KEY_KEYPAD_ADD 0x57 -#define HID_KEY_KEYPAD_ENTER 0x58 -#define HID_KEY_KEYPAD_1 0x59 -#define HID_KEY_KEYPAD_2 0x5A -#define HID_KEY_KEYPAD_3 0x5B -#define HID_KEY_KEYPAD_4 0x5C -#define HID_KEY_KEYPAD_5 0x5D -#define HID_KEY_KEYPAD_6 0x5E -#define HID_KEY_KEYPAD_7 0x5F -#define HID_KEY_KEYPAD_8 0x60 -#define HID_KEY_KEYPAD_9 0x61 -#define HID_KEY_KEYPAD_0 0x62 -#define HID_KEY_KEYPAD_DECIMAL 0x63 -#define HID_KEY_EUROPE_2 0x64 -#define HID_KEY_APPLICATION 0x65 -#define HID_KEY_POWER 0x66 -#define HID_KEY_KEYPAD_EQUAL 0x67 -#define HID_KEY_F13 0x68 -#define HID_KEY_F14 0x69 -#define HID_KEY_F15 0x6A -#define HID_KEY_F16 0x6B -#define HID_KEY_F17 0x6C -#define HID_KEY_F18 0x6D -#define HID_KEY_F19 0x6E -#define HID_KEY_F20 0x6F -#define HID_KEY_F21 0x70 -#define HID_KEY_F22 0x71 -#define HID_KEY_F23 0x72 -#define HID_KEY_F24 0x73 -#define HID_KEY_EXECUTE 0x74 -#define HID_KEY_HELP 0x75 -#define HID_KEY_MENU 0x76 -#define HID_KEY_SELECT 0x77 -#define HID_KEY_STOP 0x78 -#define HID_KEY_AGAIN 0x79 -#define HID_KEY_UNDO 0x7A -#define HID_KEY_CUT 0x7B -#define HID_KEY_COPY 0x7C -#define HID_KEY_PASTE 0x7D -#define HID_KEY_FIND 0x7E -#define HID_KEY_MUTE 0x7F -#define HID_KEY_VOLUME_UP 0x80 -#define HID_KEY_VOLUME_DOWN 0x81 -#define HID_KEY_LOCKING_CAPS_LOCK 0x82 -#define HID_KEY_LOCKING_NUM_LOCK 0x83 -#define HID_KEY_LOCKING_SCROLL_LOCK 0x84 -#define HID_KEY_KEYPAD_COMMA 0x85 -#define HID_KEY_KEYPAD_EQUAL_SIGN 0x86 -#define HID_KEY_KANJI1 0x87 -#define HID_KEY_KANJI2 0x88 -#define HID_KEY_KANJI3 0x89 -#define HID_KEY_KANJI4 0x8A -#define HID_KEY_KANJI5 0x8B -#define HID_KEY_KANJI6 0x8C -#define HID_KEY_KANJI7 0x8D -#define HID_KEY_KANJI8 0x8E -#define HID_KEY_KANJI9 0x8F -#define HID_KEY_LANG1 0x90 -#define HID_KEY_LANG2 0x91 -#define HID_KEY_LANG3 0x92 -#define HID_KEY_LANG4 0x93 -#define HID_KEY_LANG5 0x94 -#define HID_KEY_LANG6 0x95 -#define HID_KEY_LANG7 0x96 -#define HID_KEY_LANG8 0x97 -#define HID_KEY_LANG9 0x98 -#define HID_KEY_ALTERNATE_ERASE 0x99 -#define HID_KEY_SYSREQ_ATTENTION 0x9A -#define HID_KEY_CANCEL 0x9B -#define HID_KEY_CLEAR 0x9C -#define HID_KEY_PRIOR 0x9D -#define HID_KEY_RETURN 0x9E -#define HID_KEY_SEPARATOR 0x9F -#define HID_KEY_OUT 0xA0 -#define HID_KEY_OPER 0xA1 -#define HID_KEY_CLEAR_AGAIN 0xA2 -#define HID_KEY_CRSEL_PROPS 0xA3 -#define HID_KEY_EXSEL 0xA4 -// RESERVED 0xA5-DF -#define HID_KEY_CONTROL_LEFT 0xE0 -#define HID_KEY_SHIFT_LEFT 0xE1 -#define HID_KEY_ALT_LEFT 0xE2 -#define HID_KEY_GUI_LEFT 0xE3 -#define HID_KEY_CONTROL_RIGHT 0xE4 -#define HID_KEY_SHIFT_RIGHT 0xE5 -#define HID_KEY_ALT_RIGHT 0xE6 -#define HID_KEY_GUI_RIGHT 0xE7 - - -//--------------------------------------------------------------------+ -// REPORT DESCRIPTOR -//--------------------------------------------------------------------+ - -//------------- ITEM & TAG -------------// -#define HID_REPORT_DATA_0(data) -#define HID_REPORT_DATA_1(data) , data -#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data) -#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data) - -#define HID_REPORT_ITEM(data, tag, type, size) \ - (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data) - -// Report Item Types -enum { - RI_TYPE_MAIN = 0, - RI_TYPE_GLOBAL = 1, - RI_TYPE_LOCAL = 2 -}; - -//------------- Main Items - HID 1.11 section 6.2.2.4 -------------// - -// Report Item Main group -enum { - RI_MAIN_INPUT = 8, - RI_MAIN_OUTPUT = 9, - RI_MAIN_COLLECTION = 10, - RI_MAIN_FEATURE = 11, - RI_MAIN_COLLECTION_END = 12 -}; - -#define HID_INPUT(x) HID_REPORT_ITEM(x, RI_MAIN_INPUT , RI_TYPE_MAIN, 1) -#define HID_OUTPUT(x) HID_REPORT_ITEM(x, RI_MAIN_OUTPUT , RI_TYPE_MAIN, 1) -#define HID_COLLECTION(x) HID_REPORT_ITEM(x, RI_MAIN_COLLECTION , RI_TYPE_MAIN, 1) -#define HID_FEATURE(x) HID_REPORT_ITEM(x, RI_MAIN_FEATURE , RI_TYPE_MAIN, 1) -#define HID_COLLECTION_END HID_REPORT_ITEM(x, RI_MAIN_COLLECTION_END, RI_TYPE_MAIN, 0) - -//------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// -#define HID_DATA (0<<0) -#define HID_CONSTANT (1<<0) - -#define HID_ARRAY (0<<1) -#define HID_VARIABLE (1<<1) - -#define HID_ABSOLUTE (0<<2) -#define HID_RELATIVE (1<<2) - -#define HID_WRAP_NO (0<<3) -#define HID_WRAP (1<<3) - -#define HID_LINEAR (0<<4) -#define HID_NONLINEAR (1<<4) - -#define HID_PREFERRED_STATE (0<<5) -#define HID_PREFERRED_NO (1<<5) - -#define HID_NO_NULL_POSITION (0<<6) -#define HID_NULL_STATE (1<<6) - -#define HID_NON_VOLATILE (0<<7) -#define HID_VOLATILE (1<<7) - -#define HID_BITFIELD (0<<8) -#define HID_BUFFERED_BYTES (1<<8) - -//------------- Collection Item - HID 1.11 section 6.2.2.6 -------------// -enum { - HID_COLLECTION_PHYSICAL = 0, - HID_COLLECTION_APPLICATION, - HID_COLLECTION_LOGICAL, - HID_COLLECTION_REPORT, - HID_COLLECTION_NAMED_ARRAY, - HID_COLLECTION_USAGE_SWITCH, - HID_COLLECTION_USAGE_MODIFIER -}; - -//------------- Global Items - HID 1.11 section 6.2.2.7 -------------// - -// Report Item Global group -enum { - RI_GLOBAL_USAGE_PAGE = 0, - RI_GLOBAL_LOGICAL_MIN = 1, - RI_GLOBAL_LOGICAL_MAX = 2, - RI_GLOBAL_PHYSICAL_MIN = 3, - RI_GLOBAL_PHYSICAL_MAX = 4, - RI_GLOBAL_UNIT_EXPONENT = 5, - RI_GLOBAL_UNIT = 6, - RI_GLOBAL_REPORT_SIZE = 7, - RI_GLOBAL_REPORT_ID = 8, - RI_GLOBAL_REPORT_COUNT = 9, - RI_GLOBAL_PUSH = 10, - RI_GLOBAL_POP = 11 -}; - -#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, 1) -#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, n) - -#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, n) - -#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, n) - -#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, n) - -#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, n) - -#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, n) - -#define HID_UNIT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, n) - -#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, n) - -#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, 1), -#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, n), - -#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, n) - -#define HID_PUSH HID_REPORT_ITEM(x, RI_GLOBAL_PUSH, RI_TYPE_GLOBAL, 0) -#define HID_POP HID_REPORT_ITEM(x, RI_GLOBAL_POP, RI_TYPE_GLOBAL, 0) - -//------------- LOCAL ITEMS 6.2.2.8 -------------// - -enum { - RI_LOCAL_USAGE = 0, - RI_LOCAL_USAGE_MIN = 1, - RI_LOCAL_USAGE_MAX = 2, - RI_LOCAL_DESIGNATOR_INDEX = 3, - RI_LOCAL_DESIGNATOR_MIN = 4, - RI_LOCAL_DESIGNATOR_MAX = 5, - // 6 is reserved - RI_LOCAL_STRING_INDEX = 7, - RI_LOCAL_STRING_MIN = 8, - RI_LOCAL_STRING_MAX = 9, - RI_LOCAL_DELIMITER = 10, -}; - -#define HID_USAGE(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, 1) -#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, n) - -#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, n) - -#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, n) - -//--------------------------------------------------------------------+ -// Usage Table -//--------------------------------------------------------------------+ - -/// HID Usage Table - Table 1: Usage Page Summary -enum { - HID_USAGE_PAGE_DESKTOP = 0x01, - HID_USAGE_PAGE_SIMULATE = 0x02, - HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03, - HID_USAGE_PAGE_SPORT = 0x04, - HID_USAGE_PAGE_GAME = 0x05, - HID_USAGE_PAGE_GENERIC_DEVICE = 0x06, - HID_USAGE_PAGE_KEYBOARD = 0x07, - HID_USAGE_PAGE_LED = 0x08, - HID_USAGE_PAGE_BUTTON = 0x09, - HID_USAGE_PAGE_ORDINAL = 0x0a, - HID_USAGE_PAGE_TELEPHONY = 0x0b, - HID_USAGE_PAGE_CONSUMER = 0x0c, - HID_USAGE_PAGE_DIGITIZER = 0x0d, - HID_USAGE_PAGE_PID = 0x0f, - HID_USAGE_PAGE_UNICODE = 0x10, - HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, - HID_USAGE_PAGE_MEDICAL = 0x40, - HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83 - HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 - HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c, - HID_USAGE_PAGE_SCALE = 0x8d, - HID_USAGE_PAGE_MSR = 0x8e, - HID_USAGE_PAGE_CAMERA = 0x90, - HID_USAGE_PAGE_ARCADE = 0x91, - HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF -}; - -/// HID Usage Table - Table 6: Generic Desktop Page -enum { - HID_USAGE_DESKTOP_POINTER = 0x01, - HID_USAGE_DESKTOP_MOUSE = 0x02, - HID_USAGE_DESKTOP_JOYSTICK = 0x04, - HID_USAGE_DESKTOP_GAMEPAD = 0x05, - HID_USAGE_DESKTOP_KEYBOARD = 0x06, - HID_USAGE_DESKTOP_KEYPAD = 0x07, - HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER = 0x08, - HID_USAGE_DESKTOP_TABLET_PC_SYSTEM = 0x09, - HID_USAGE_DESKTOP_X = 0x30, - HID_USAGE_DESKTOP_Y = 0x31, - HID_USAGE_DESKTOP_Z = 0x32, - HID_USAGE_DESKTOP_RX = 0x33, - HID_USAGE_DESKTOP_RY = 0x34, - HID_USAGE_DESKTOP_RZ = 0x35, - HID_USAGE_DESKTOP_SLIDER = 0x36, - HID_USAGE_DESKTOP_DIAL = 0x37, - HID_USAGE_DESKTOP_WHEEL = 0x38, - HID_USAGE_DESKTOP_HAT_SWITCH = 0x39, - HID_USAGE_DESKTOP_COUNTED_BUFFER = 0x3a, - HID_USAGE_DESKTOP_BYTE_COUNT = 0x3b, - HID_USAGE_DESKTOP_MOTION_WAKEUP = 0x3c, - HID_USAGE_DESKTOP_START = 0x3d, - HID_USAGE_DESKTOP_SELECT = 0x3e, - HID_USAGE_DESKTOP_VX = 0x40, - HID_USAGE_DESKTOP_VY = 0x41, - HID_USAGE_DESKTOP_VZ = 0x42, - HID_USAGE_DESKTOP_VBRX = 0x43, - HID_USAGE_DESKTOP_VBRY = 0x44, - HID_USAGE_DESKTOP_VBRZ = 0x45, - HID_USAGE_DESKTOP_VNO = 0x46, - HID_USAGE_DESKTOP_FEATURE_NOTIFICATION = 0x47, - HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER = 0x48, - HID_USAGE_DESKTOP_SYSTEM_CONTROL = 0x80, - HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN = 0x81, - HID_USAGE_DESKTOP_SYSTEM_SLEEP = 0x82, - HID_USAGE_DESKTOP_SYSTEM_WAKE_UP = 0x83, - HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU = 0x84, - HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU = 0x85, - HID_USAGE_DESKTOP_SYSTEM_APP_MENU = 0x86, - HID_USAGE_DESKTOP_SYSTEM_MENU_HELP = 0x87, - HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT = 0x88, - HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT = 0x89, - HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT = 0x8A, - HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT = 0x8B, - HID_USAGE_DESKTOP_SYSTEM_MENU_UP = 0x8C, - HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN = 0x8D, - HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART = 0x8E, - HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART = 0x8F, - HID_USAGE_DESKTOP_DPAD_UP = 0x90, - HID_USAGE_DESKTOP_DPAD_DOWN = 0x91, - HID_USAGE_DESKTOP_DPAD_RIGHT = 0x92, - HID_USAGE_DESKTOP_DPAD_LEFT = 0x93, - HID_USAGE_DESKTOP_SYSTEM_DOCK = 0xA0, - HID_USAGE_DESKTOP_SYSTEM_UNDOCK = 0xA1, - HID_USAGE_DESKTOP_SYSTEM_SETUP = 0xA2, - HID_USAGE_DESKTOP_SYSTEM_BREAK = 0xA3, - HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK = 0xA4, - HID_USAGE_DESKTOP_APPLICATION_BREAK = 0xA5, - HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK = 0xA6, - HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE = 0xA7, - HID_USAGE_DESKTOP_SYSTEM_HIBERNATE = 0xA8, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT = 0xB0, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL = 0xB1, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL = 0xB2, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH = 0xB3, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL = 0xB4, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7 -}; - - -/// HID Usage Table: Consumer Page (0x0C) -/// Only contains controls that supported by Windows (whole list is too long) -enum -{ - // Generic Control - HID_USAGE_CONSUMER_CONTROL = 0x0001, - - // Power Control - HID_USAGE_CONSUMER_POWER = 0x0030, - HID_USAGE_CONSUMER_RESET = 0x0031, - HID_USAGE_CONSUMER_SLEEP = 0x0032, - - // Screen Brightness - HID_USAGE_CONSUMER_BRIGHTNESS_INCREMENT = 0x006F, - HID_USAGE_CONSUMER_BRIGHTNESS_DECREMENT = 0x0070, - - // These HID usages operate only on mobile systems (battery powered) and - // require Windows 8 (build 8302 or greater). - HID_USAGE_CONSUMER_WIRELESS_RADIO_CONTROLS = 0x000C, - HID_USAGE_CONSUMER_WIRELESS_RADIO_BUTTONS = 0x00C6, - HID_USAGE_CONSUMER_WIRELESS_RADIO_LED = 0x00C7, - HID_USAGE_CONSUMER_WIRELESS_RADIO_SLIDER_SWITCH = 0x00C8, - - // Media Control - HID_USAGE_CONSUMER_PLAY_PAUSE = 0x00CD, - HID_USAGE_CONSUMER_SCAN_NEXT = 0x00B5, - HID_USAGE_CONSUMER_SCAN_PREVIOUS = 0x00B6, - HID_USAGE_CONSUMER_STOP = 0x00B7, - HID_USAGE_CONSUMER_VOLUME = 0x00E0, - HID_USAGE_CONSUMER_MUTE = 0x00E2, - HID_USAGE_CONSUMER_BASS = 0x00E3, - HID_USAGE_CONSUMER_TREBLE = 0x00E4, - HID_USAGE_CONSUMER_BASS_BOOST = 0x00E5, - HID_USAGE_CONSUMER_VOLUME_INCREMENT = 0x00E9, - HID_USAGE_CONSUMER_VOLUME_DECREMENT = 0x00EA, - HID_USAGE_CONSUMER_BASS_INCREMENT = 0x0152, - HID_USAGE_CONSUMER_BASS_DECREMENT = 0x0153, - HID_USAGE_CONSUMER_TREBLE_INCREMENT = 0x0154, - HID_USAGE_CONSUMER_TREBLE_DECREMENT = 0x0155, - - // Application Launcher - HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x0183, - HID_USAGE_CONSUMER_AL_EMAIL_READER = 0x018A, - HID_USAGE_CONSUMER_AL_CALCULATOR = 0x0192, - HID_USAGE_CONSUMER_AL_LOCAL_BROWSER = 0x0194, - - // Browser/Explorer Specific - HID_USAGE_CONSUMER_AC_SEARCH = 0x0221, - HID_USAGE_CONSUMER_AC_HOME = 0x0223, - HID_USAGE_CONSUMER_AC_BACK = 0x0224, - HID_USAGE_CONSUMER_AC_FORWARD = 0x0225, - HID_USAGE_CONSUMER_AC_STOP = 0x0226, - HID_USAGE_CONSUMER_AC_REFRESH = 0x0227, - HID_USAGE_CONSUMER_AC_BOOKMARKS = 0x022A, - - // Mouse Horizontal scroll - HID_USAGE_CONSUMER_AC_PAN = 0x0238, -}; - -/*-------------------------------------------------------------------- - * ASCII to KEYCODE Conversion - * Expand to array of [128][2] (shift, keycode) - * - * Usage: example to convert input chr into keyboard report (modifier + keycode) - * - * uint8_t const conv_table[128][2] = { HID_ASCII_TO_KEYCODE }; - * - * uint8_t keycode[6] = { 0 }; - * uint8_t modifier = 0; - * - * if ( conv_table[chr][0] ) modifier = KEYBOARD_MODIFIER_LEFTSHIFT; - * keycode[0] = conv_table[chr][1]; - * tud_hid_keyboard_report(report_id, modifier, keycode); - * - *--------------------------------------------------------------------*/ -#define HID_ASCII_TO_KEYCODE \ - {0, 0 }, /* 0x00 Null */ \ - {0, 0 }, /* 0x01 */ \ - {0, 0 }, /* 0x02 */ \ - {0, 0 }, /* 0x03 */ \ - {0, 0 }, /* 0x04 */ \ - {0, 0 }, /* 0x05 */ \ - {0, 0 }, /* 0x06 */ \ - {0, 0 }, /* 0x07 */ \ - {0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \ - {0, HID_KEY_TAB }, /* 0x09 Tab */ \ - {0, HID_KEY_ENTER }, /* 0x0A Line Feed */ \ - {0, 0 }, /* 0x0B */ \ - {0, 0 }, /* 0x0C */ \ - {0, HID_KEY_ENTER }, /* 0x0D CR */ \ - {0, 0 }, /* 0x0E */ \ - {0, 0 }, /* 0x0F */ \ - {0, 0 }, /* 0x10 */ \ - {0, 0 }, /* 0x11 */ \ - {0, 0 }, /* 0x12 */ \ - {0, 0 }, /* 0x13 */ \ - {0, 0 }, /* 0x14 */ \ - {0, 0 }, /* 0x15 */ \ - {0, 0 }, /* 0x16 */ \ - {0, 0 }, /* 0x17 */ \ - {0, 0 }, /* 0x18 */ \ - {0, 0 }, /* 0x19 */ \ - {0, 0 }, /* 0x1A */ \ - {0, HID_KEY_ESCAPE }, /* 0x1B Escape */ \ - {0, 0 }, /* 0x1C */ \ - {0, 0 }, /* 0x1D */ \ - {0, 0 }, /* 0x1E */ \ - {0, 0 }, /* 0x1F */ \ - \ - {0, HID_KEY_SPACE }, /* 0x20 */ \ - {1, HID_KEY_1 }, /* 0x21 ! */ \ - {1, HID_KEY_APOSTROPHE }, /* 0x22 " */ \ - {1, HID_KEY_3 }, /* 0x23 # */ \ - {1, HID_KEY_4 }, /* 0x24 $ */ \ - {1, HID_KEY_5 }, /* 0x25 % */ \ - {1, HID_KEY_7 }, /* 0x26 & */ \ - {0, HID_KEY_APOSTROPHE }, /* 0x27 ' */ \ - {1, HID_KEY_9 }, /* 0x28 ( */ \ - {1, HID_KEY_0 }, /* 0x29 ) */ \ - {1, HID_KEY_8 }, /* 0x2A * */ \ - {1, HID_KEY_EQUAL }, /* 0x2B + */ \ - {0, HID_KEY_COMMA }, /* 0x2C , */ \ - {0, HID_KEY_MINUS }, /* 0x2D - */ \ - {0, HID_KEY_PERIOD }, /* 0x2E . */ \ - {0, HID_KEY_SLASH }, /* 0x2F / */ \ - {0, HID_KEY_0 }, /* 0x30 0 */ \ - {0, HID_KEY_1 }, /* 0x31 1 */ \ - {0, HID_KEY_2 }, /* 0x32 2 */ \ - {0, HID_KEY_3 }, /* 0x33 3 */ \ - {0, HID_KEY_4 }, /* 0x34 4 */ \ - {0, HID_KEY_5 }, /* 0x35 5 */ \ - {0, HID_KEY_6 }, /* 0x36 6 */ \ - {0, HID_KEY_7 }, /* 0x37 7 */ \ - {0, HID_KEY_8 }, /* 0x38 8 */ \ - {0, HID_KEY_9 }, /* 0x39 9 */ \ - {1, HID_KEY_SEMICOLON }, /* 0x3A : */ \ - {0, HID_KEY_SEMICOLON }, /* 0x3B ; */ \ - {1, HID_KEY_COMMA }, /* 0x3C < */ \ - {0, HID_KEY_EQUAL }, /* 0x3D = */ \ - {1, HID_KEY_PERIOD }, /* 0x3E > */ \ - {1, HID_KEY_SLASH }, /* 0x3F ? */ \ - \ - {1, HID_KEY_2 }, /* 0x40 @ */ \ - {1, HID_KEY_A }, /* 0x41 A */ \ - {1, HID_KEY_B }, /* 0x42 B */ \ - {1, HID_KEY_C }, /* 0x43 C */ \ - {1, HID_KEY_D }, /* 0x44 D */ \ - {1, HID_KEY_E }, /* 0x45 E */ \ - {1, HID_KEY_F }, /* 0x46 F */ \ - {1, HID_KEY_G }, /* 0x47 G */ \ - {1, HID_KEY_H }, /* 0x48 H */ \ - {1, HID_KEY_I }, /* 0x49 I */ \ - {1, HID_KEY_J }, /* 0x4A J */ \ - {1, HID_KEY_K }, /* 0x4B K */ \ - {1, HID_KEY_L }, /* 0x4C L */ \ - {1, HID_KEY_M }, /* 0x4D M */ \ - {1, HID_KEY_N }, /* 0x4E N */ \ - {1, HID_KEY_O }, /* 0x4F O */ \ - {1, HID_KEY_P }, /* 0x50 P */ \ - {1, HID_KEY_Q }, /* 0x51 Q */ \ - {1, HID_KEY_R }, /* 0x52 R */ \ - {1, HID_KEY_S }, /* 0x53 S */ \ - {1, HID_KEY_T }, /* 0x55 T */ \ - {1, HID_KEY_U }, /* 0x55 U */ \ - {1, HID_KEY_V }, /* 0x56 V */ \ - {1, HID_KEY_W }, /* 0x57 W */ \ - {1, HID_KEY_X }, /* 0x58 X */ \ - {1, HID_KEY_Y }, /* 0x59 Y */ \ - {1, HID_KEY_Z }, /* 0x5A Z */ \ - {0, HID_KEY_BRACKET_LEFT }, /* 0x5B [ */ \ - {0, HID_KEY_BACKSLASH }, /* 0x5C '\' */ \ - {0, HID_KEY_BRACKET_RIGHT }, /* 0x5D ] */ \ - {1, HID_KEY_6 }, /* 0x5E ^ */ \ - {1, HID_KEY_MINUS }, /* 0x5F _ */ \ - \ - {0, HID_KEY_GRAVE }, /* 0x60 ` */ \ - {0, HID_KEY_A }, /* 0x61 a */ \ - {0, HID_KEY_B }, /* 0x62 b */ \ - {0, HID_KEY_C }, /* 0x63 c */ \ - {0, HID_KEY_D }, /* 0x66 d */ \ - {0, HID_KEY_E }, /* 0x65 e */ \ - {0, HID_KEY_F }, /* 0x66 f */ \ - {0, HID_KEY_G }, /* 0x67 g */ \ - {0, HID_KEY_H }, /* 0x68 h */ \ - {0, HID_KEY_I }, /* 0x69 i */ \ - {0, HID_KEY_J }, /* 0x6A j */ \ - {0, HID_KEY_K }, /* 0x6B k */ \ - {0, HID_KEY_L }, /* 0x6C l */ \ - {0, HID_KEY_M }, /* 0x6D m */ \ - {0, HID_KEY_N }, /* 0x6E n */ \ - {0, HID_KEY_O }, /* 0x6F o */ \ - {0, HID_KEY_P }, /* 0x70 p */ \ - {0, HID_KEY_Q }, /* 0x71 q */ \ - {0, HID_KEY_R }, /* 0x72 r */ \ - {0, HID_KEY_S }, /* 0x73 s */ \ - {0, HID_KEY_T }, /* 0x75 t */ \ - {0, HID_KEY_U }, /* 0x75 u */ \ - {0, HID_KEY_V }, /* 0x76 v */ \ - {0, HID_KEY_W }, /* 0x77 w */ \ - {0, HID_KEY_X }, /* 0x78 x */ \ - {0, HID_KEY_Y }, /* 0x79 y */ \ - {0, HID_KEY_Z }, /* 0x7A z */ \ - {1, HID_KEY_BRACKET_LEFT }, /* 0x7B { */ \ - {1, HID_KEY_BACKSLASH }, /* 0x7C | */ \ - {1, HID_KEY_BRACKET_RIGHT }, /* 0x7D } */ \ - {1, HID_KEY_GRAVE }, /* 0x7E ~ */ \ - {0, HID_KEY_DELETE } /* 0x7F Delete */ \ - -/*-------------------------------------------------------------------- - * KEYCODE to Ascii Conversion - * Expand to array of [128][2] (ascii without shift, ascii with shift) - * - * Usage: example to convert ascii from keycode (key) and shift modifier (shift). - * Here we assume key < 128 ( printable ) - * - * uint8_t const conv_table[128][2] = { HID_KEYCODE_TO_ASCII }; - * char ch = shift ? conv_table[chr][1] : conv_table[chr][0]; - * - *--------------------------------------------------------------------*/ -#define HID_KEYCODE_TO_ASCII \ - {0 , 0 }, /* 0x00 */ \ - {0 , 0 }, /* 0x01 */ \ - {0 , 0 }, /* 0x02 */ \ - {0 , 0 }, /* 0x03 */ \ - {'a' , 'A' }, /* 0x04 */ \ - {'b' , 'B' }, /* 0x05 */ \ - {'c' , 'C' }, /* 0x06 */ \ - {'d' , 'D' }, /* 0x07 */ \ - {'e' , 'E' }, /* 0x08 */ \ - {'f' , 'F' }, /* 0x09 */ \ - {'g' , 'G' }, /* 0x0a */ \ - {'h' , 'H' }, /* 0x0b */ \ - {'i' , 'I' }, /* 0x0c */ \ - {'j' , 'J' }, /* 0x0d */ \ - {'k' , 'K' }, /* 0x0e */ \ - {'l' , 'L' }, /* 0x0f */ \ - {'m' , 'M' }, /* 0x10 */ \ - {'n' , 'N' }, /* 0x11 */ \ - {'o' , 'O' }, /* 0x12 */ \ - {'p' , 'P' }, /* 0x13 */ \ - {'q' , 'Q' }, /* 0x14 */ \ - {'r' , 'R' }, /* 0x15 */ \ - {'s' , 'S' }, /* 0x16 */ \ - {'t' , 'T' }, /* 0x17 */ \ - {'u' , 'U' }, /* 0x18 */ \ - {'v' , 'V' }, /* 0x19 */ \ - {'w' , 'W' }, /* 0x1a */ \ - {'x' , 'X' }, /* 0x1b */ \ - {'y' , 'Y' }, /* 0x1c */ \ - {'z' , 'Z' }, /* 0x1d */ \ - {'1' , '!' }, /* 0x1e */ \ - {'2' , '@' }, /* 0x1f */ \ - {'3' , '#' }, /* 0x20 */ \ - {'4' , '$' }, /* 0x21 */ \ - {'5' , '%' }, /* 0x22 */ \ - {'6' , '^' }, /* 0x23 */ \ - {'7' , '&' }, /* 0x24 */ \ - {'8' , '*' }, /* 0x25 */ \ - {'9' , '(' }, /* 0x26 */ \ - {'0' , ')' }, /* 0x27 */ \ - {'\r' , '\r' }, /* 0x28 */ \ - {'\x1b', '\x1b' }, /* 0x29 */ \ - {'\b' , '\b' }, /* 0x2a */ \ - {'\t' , '\t' }, /* 0x2b */ \ - {' ' , ' ' }, /* 0x2c */ \ - {'-' , '_' }, /* 0x2d */ \ - {'=' , '+' }, /* 0x2e */ \ - {'[' , '{' }, /* 0x2f */ \ - {']' , '}' }, /* 0x30 */ \ - {'\\' , '|' }, /* 0x31 */ \ - {'#' , '~' }, /* 0x32 */ \ - {';' , ':' }, /* 0x33 */ \ - {'\'' , '\"' }, /* 0x34 */ \ - {'`' , '~' }, /* 0x35 */ \ - {',' , '<' }, /* 0x36 */ \ - {'.' , '>' }, /* 0x37 */ \ - {'/' , '?' }, /* 0x38 */ \ - \ - {0 , 0 }, /* 0x39 */ \ - {0 , 0 }, /* 0x3a */ \ - {0 , 0 }, /* 0x3b */ \ - {0 , 0 }, /* 0x3c */ \ - {0 , 0 }, /* 0x3d */ \ - {0 , 0 }, /* 0x3e */ \ - {0 , 0 }, /* 0x3f */ \ - {0 , 0 }, /* 0x40 */ \ - {0 , 0 }, /* 0x41 */ \ - {0 , 0 }, /* 0x42 */ \ - {0 , 0 }, /* 0x43 */ \ - {0 , 0 }, /* 0x44 */ \ - {0 , 0 }, /* 0x45 */ \ - {0 , 0 }, /* 0x46 */ \ - {0 , 0 }, /* 0x47 */ \ - {0 , 0 }, /* 0x48 */ \ - {0 , 0 }, /* 0x49 */ \ - {0 , 0 }, /* 0x4a */ \ - {0 , 0 }, /* 0x4b */ \ - {0 , 0 }, /* 0x4c */ \ - {0 , 0 }, /* 0x4d */ \ - {0 , 0 }, /* 0x4e */ \ - {0 , 0 }, /* 0x4f */ \ - {0 , 0 }, /* 0x50 */ \ - {0 , 0 }, /* 0x51 */ \ - {0 , 0 }, /* 0x52 */ \ - {0 , 0 }, /* 0x53 */ \ - \ - {'/' , '/' }, /* 0x54 */ \ - {'*' , '*' }, /* 0x55 */ \ - {'-' , '-' }, /* 0x56 */ \ - {'+' , '+' }, /* 0x57 */ \ - {'\r' , '\r' }, /* 0x58 */ \ - {'1' , 0 }, /* 0x59 */ \ - {'2' , 0 }, /* 0x5a */ \ - {'3' , 0 }, /* 0x5b */ \ - {'4' , 0 }, /* 0x5c */ \ - {'5' , '5' }, /* 0x5d */ \ - {'6' , 0 }, /* 0x5e */ \ - {'7' , 0 }, /* 0x5f */ \ - {'8' , 0 }, /* 0x60 */ \ - {'9' , 0 }, /* 0x61 */ \ - {'0' , 0 }, /* 0x62 */ \ - {'0' , 0 }, /* 0x63 */ \ - {'=' , '=' }, /* 0x67 */ \ - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HID_H__ */ - -/// @} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c deleted file mode 100644 index 588b61254..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_HID) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "hid_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; // optional Out endpoint - uint8_t itf_protocol; // Boot mouse or keyboard - - uint8_t protocol_mode; // Boot (0) or Report protocol (1) - uint8_t idle_rate; // up to application to handle idle rate - uint16_t report_desc_len; - - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; - - // TODO save hid descriptor since host can specifically request this after enumeration - // Note: HID descriptor may be not available from application after enumeration - tusb_hid_descriptor_hid_t const * hid_descriptor; -} hidd_interface_t; - -CFG_TUSB_MEM_SECTION static hidd_interface_t _hidd_itf[CFG_TUD_HID]; - -/*------------- Helpers -------------*/ -static inline uint8_t get_index_by_itfnum(uint8_t itf_num) -{ - for (uint8_t i=0; i < CFG_TUD_HID; i++ ) - { - if ( itf_num == _hidd_itf[i].itf_num ) return i; - } - - return 0xFF; -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_hid_n_ready(uint8_t instance) -{ - uint8_t const ep_in = _hidd_itf[instance].ep_in; - return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); -} - -bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len) -{ - uint8_t const rhport = 0; - hidd_interface_t * p_hid = &_hidd_itf[instance]; - - // claim endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); - - // prepare data - if (report_id) - { - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); - - p_hid->epin_buf[0] = report_id; - memcpy(p_hid->epin_buf+1, report, len); - len++; - }else - { - // If report id = 0, skip ID field - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE); - memcpy(p_hid->epin_buf, report, len); - } - - return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len); -} - -uint8_t tud_hid_n_interface_protocol(uint8_t instance) -{ - return _hidd_itf[instance].itf_protocol; -} - -uint8_t tud_hid_n_get_protocol(uint8_t instance) -{ - return _hidd_itf[instance].protocol_mode; -} - -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ - hid_keyboard_report_t report; - - report.modifier = modifier; - report.reserved = 0; - - if ( keycode ) - { - memcpy(report.keycode, keycode, 6); - }else - { - tu_memclr(report.keycode, 6); - } - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, - uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ - hid_mouse_report_t report = - { - .buttons = buttons, - .x = x, - .y = y, - .wheel = vertical, - .pan = horizontal - }; - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, - int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) -{ - hid_gamepad_report_t report = - { - .x = x, - .y = y, - .z = z, - .rz = rz, - .rx = rx, - .ry = ry, - .hat = hat, - .buttons = buttons, - }; - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -//--------------------------------------------------------------------+ -// USBD-CLASS API -//--------------------------------------------------------------------+ -void hidd_init(void) -{ - hidd_reset(TUD_OPT_RHPORT); -} - -void hidd_reset(uint8_t rhport) -{ - (void) rhport; - tu_memclr(_hidd_itf, sizeof(_hidd_itf)); -} - -uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); - - // len = interface + hid + n*endpoints - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_ASSERT(max_len >= drv_len, 0); - - // Find available interface - hidd_interface_t * p_hid = NULL; - uint8_t hid_id; - for(hid_id=0; hid_idhid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc; - - //------------- Endpoint Descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); - - if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; - - p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode - p_hid->itf_num = desc_itf->bInterfaceNumber; - - // Use offsetof to avoid pointer to the odd/misaligned address - p_hid->report_desc_len = tu_unaligned_read16((uint8_t const*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength)); - - // Prepare for output endpoint - if (p_hid->ep_out) - { - if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) ) - { - TU_LOG_FAILED(); - TU_BREAKPOINT(); - } - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - uint8_t const hid_itf = get_index_by_itfnum((uint8_t) request->wIndex); - TU_VERIFY(hid_itf < CFG_TUD_HID); - - hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; - - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - //------------- STD Request -------------// - if ( stage == CONTROL_STAGE_SETUP ) - { - uint8_t const desc_type = tu_u16_high(request->wValue); - //uint8_t const desc_index = tu_u16_low (request->wValue); - - if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) - { - TU_VERIFY(p_hid->hid_descriptor); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); - } - else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) - { - uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); - tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_report, p_hid->report_desc_len); - } - else - { - return false; // stall unsupported request - } - } - } - else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) - { - //------------- Class Specific Request -------------// - switch( request->bRequest ) - { - case HID_REQ_CONTROL_GET_REPORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t* report_buf = p_hid->epin_buf; - uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - uint16_t xferlen = 0; - - // If host request a specific Report ID, add ID to as 1 byte of response - if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) ) - { - *report_buf++ = report_id; - req_len--; - - xferlen++; - } - - xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); - TU_ASSERT( xferlen > 0 ); - - tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); - } - break; - - case HID_REQ_CONTROL_SET_REPORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); - tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t const* report_buf = p_hid->epout_buf; - uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - // If host request a specific Report ID, extract report ID in buffer before invoking callback - if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) - { - report_buf++; - report_len--; - } - - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); - } - break; - - case HID_REQ_CONTROL_SET_IDLE: - if ( stage == CONTROL_STAGE_SETUP ) - { - p_hid->idle_rate = tu_u16_high(request->wValue); - if ( tud_hid_set_idle_cb ) - { - // stall request if callback return false - TU_VERIFY( tud_hid_set_idle_cb( hid_itf, p_hid->idle_rate) ); - } - - tud_control_status(rhport, request); - } - break; - - case HID_REQ_CONTROL_GET_IDLE: - if ( stage == CONTROL_STAGE_SETUP ) - { - // TODO idle rate of report - tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); - } - break; - - case HID_REQ_CONTROL_GET_PROTOCOL: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); - } - break; - - case HID_REQ_CONTROL_SET_PROTOCOL: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - p_hid->protocol_mode = (uint8_t) request->wValue; - if (tud_hid_set_protocol_cb) - { - tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode); - } - } - break; - - default: return false; // stall unsupported request - } - }else - { - return false; // stall unsupported request - } - - return true; -} - -bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t instance = 0; - hidd_interface_t * p_hid = _hidd_itf; - - // Identify which interface to use - for (instance = 0; instance < CFG_TUD_HID; instance++) - { - p_hid = &_hidd_itf[instance]; - if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; - } - TU_ASSERT(instance < CFG_TUD_HID); - - // Sent report successfully - if (ep_addr == p_hid->ep_in) - { - if (tud_hid_report_complete_cb) - { - tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint8_t) xferred_bytes); - } - } - // Received report - else if (ep_addr == p_hid->ep_out) - { - tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); - TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h deleted file mode 100644 index 078b67349..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h +++ /dev/null @@ -1,393 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HID_DEVICE_H_ -#define _TUSB_HID_DEVICE_H_ - -#include "hid.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Default Configure & Validation -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_HID_EP_BUFSIZE) & defined(CFG_TUD_HID_BUFSIZE) - // TODO warn user to use new name later on - // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE -#endif - -#ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 64 -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Instances) -// CFG_TUD_HID > 1 -//--------------------------------------------------------------------+ - -// Check if the interface is ready to use -bool tud_hid_n_ready(uint8_t instance); - -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tud_hid_n_interface_protocol(uint8_t instance); - -// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -uint8_t tud_hid_n_get_protocol(uint8_t instance); - -// Send report to host -bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len); - -// KEYBOARD: convenient helper to send keyboard report if application -// use template layout report as defined by hid_keyboard_report_t -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); - -// MOUSE: convenient helper to send mouse report if application -// use template layout report as defined by hid_mouse_report_t -bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); - -// Gamepad: convenient helper to send gamepad report if application -// use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void); -static inline uint8_t tud_hid_interface_protocol(void); -static inline uint8_t tud_hid_get_protocol(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); - -//--------------------------------------------------------------------+ -// Callbacks (Weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received GET HID REPORT DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance); - -// Invoked when received GET_REPORT control request -// Application must fill buffer report's content and return its length. -// Return zero will cause the stack to STALL request -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); - -// Invoked when received SET_REPORT control request or -// received data on OUT endpoint ( Report ID = 0, Type = 0 ) -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); - -// Invoked when received SET_PROTOCOL request -// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); - -// Invoked when received SET_IDLE request. return false will stall the request -// - Idle Rate = 0 : only send report if there is changes, i.e skip duplication -// - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); - -// Invoked when sent REPORT successfully to host -// Application can use this to send the next report -// Note: For composite reports, report[0] is report ID -TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len); - - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void) -{ - return tud_hid_n_ready(0); -} - -static inline uint8_t tud_hid_interface_protocol(void) -{ - return tud_hid_n_interface_protocol(0); -} - -static inline uint8_t tud_hid_get_protocol(void) -{ - return tud_hid_n_get_protocol(0); -} - -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) -{ - return tud_hid_n_report(0, report_id, report, len); -} - -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ - return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); -} - -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ - return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); -} - -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) -{ - return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); -} - -/* --------------------------------------------------------------------+ - * HID Report Descriptor Template - * - * Convenient for declaring popular HID device (keyboard, mouse, consumer, - * gamepad etc...). Templates take "HID_REPORT_ID(n)" as input, leave - * empty if multiple reports is not used - * - * - Only 1 report: no parameter - * uint8_t const report_desc[] = { TUD_HID_REPORT_DESC_KEYBOARD() }; - * - * - Multiple Reports: "HID_REPORT_ID(ID)" must be passed to template - * uint8_t const report_desc[] = - * { - * TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(1) ) , - * TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(2) ) - * }; - *--------------------------------------------------------------------*/ - -// Keyboard Report Descriptor Template -#define TUD_HID_REPORT_DESC_KEYBOARD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_KEYBOARD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 8 bits Modifier Keys (Shfit, Control, Alt) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ - HID_USAGE_MIN ( 224 ) ,\ - HID_USAGE_MAX ( 231 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 8 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 8 bit reserved */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - /* Output 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_LED ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 5 ) ,\ - HID_REPORT_COUNT ( 5 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* led padding */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 3 ) ,\ - HID_OUTPUT ( HID_CONSTANT ) ,\ - /* 6-byte Keycodes */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ - HID_USAGE_MIN ( 0 ) ,\ - HID_USAGE_MAX_N ( 255, 2 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX_N( 255, 2 ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// Mouse Report Descriptor Template -#define TUD_HID_REPORT_DESC_MOUSE(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\ - HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 5 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - /* Left, Right, Middle, Backward, Forward buttons */ \ - HID_REPORT_COUNT( 5 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 3 bit padding */ \ - HID_REPORT_COUNT( 1 ) ,\ - HID_REPORT_SIZE ( 3 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - /* X, Y position [-127, 127] */ \ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT( 2 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ - /* Verital wheel scroll [-127, 127] */ \ - HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \ - /* Horizontal wheel scroll [-127, 127] */ \ - HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \ - HID_LOGICAL_MIN ( 0x81 ), \ - HID_LOGICAL_MAX ( 0x7f ), \ - HID_REPORT_COUNT( 1 ), \ - HID_REPORT_SIZE ( 8 ), \ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \ - HID_COLLECTION_END , \ - HID_COLLECTION_END \ - -// Consumer Control Report Descriptor Template -#define TUD_HID_REPORT_DESC_CONSUMER(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ) ,\ - HID_USAGE ( HID_USAGE_CONSUMER_CONTROL ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - HID_LOGICAL_MIN ( 0x00 ) ,\ - HID_LOGICAL_MAX_N( 0x03FF, 2 ) ,\ - HID_USAGE_MIN ( 0x00 ) ,\ - HID_USAGE_MAX_N ( 0x03FF, 2 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 16 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -/* System Control Report Descriptor Template - * 0x00 - do nothing - * 0x01 - Power Off - * 0x02 - Standby - * 0x03 - Wake Host - */ -#define TUD_HID_REPORT_DESC_SYSTEM_CONTROL(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_CONTROL ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 2 bit system power control */ \ - HID_LOGICAL_MIN ( 1 ) ,\ - HID_LOGICAL_MAX ( 3 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 2 ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_SLEEP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_WAKE_UP ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - /* 6 bit padding */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 6 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - HID_COLLECTION_END \ - -// Gamepad Report Descriptor Template -// with 32 buttons, 2 joysticks and 1 hat/dpad with following layout -// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (4 bytes) | -#define TUD_HID_REPORT_DESC_GAMEPAD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 8 bit DPad/Hat Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\ - HID_LOGICAL_MIN ( 1 ) ,\ - HID_LOGICAL_MAX ( 8 ) ,\ - HID_PHYSICAL_MIN ( 0 ) ,\ - HID_PHYSICAL_MAX_N ( 315, 2 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 32 bit Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 32 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 32 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// HID Generic Input & Output -// - 1st parameter is report size (mandatory) -// - 2nd parameter is report id HID_REPORT_ID(n) (optional) -#define TUD_HID_REPORT_DESC_GENERIC_INOUT(report_size, ...) \ - HID_USAGE_PAGE_N ( HID_USAGE_PAGE_VENDOR, 2 ),\ - HID_USAGE ( 0x01 ),\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* Input */ \ - HID_USAGE ( 0x02 ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - /* Output */ \ - HID_USAGE ( 0x03 ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - HID_COLLECTION_END \ - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hidd_init (void); -void hidd_reset (uint8_t rhport); -uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HID_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c deleted file mode 100644 index f19f1ba81..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "hid_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t itf_protocol; // None, Keyboard, Mouse - uint8_t protocol_mode; // Boot (0) or Report protocol (1) - - uint8_t report_desc_type; - uint16_t report_desc_len; - - uint16_t epin_size; - uint16_t epout_size; - - uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE]; - uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE]; -} hidh_interface_t; - -typedef struct -{ - uint8_t inst_count; - hidh_interface_t instances[CFG_TUH_HID]; -} hidh_device_t; - -static hidh_device_t _hidh_dev[CFG_TUH_DEVICE_MAX]; - -//------------- Internal prototypes -------------// - -// Get HID device & interface -TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); -static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); -static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); - -//--------------------------------------------------------------------+ -// Interface API -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_instance_count(uint8_t dev_addr) -{ - return get_dev(dev_addr)->inst_count; -} - -bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); -} - -uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->itf_protocol; -} - -//--------------------------------------------------------------------+ -// Control Endpoint API -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->protocol_mode; -} - -static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) request->wValue; - - if (tuh_hid_set_protocol_complete_cb) - { - tuh_hid_set_protocol_complete_cb(dev_addr, instance, hid_itf->protocol_mode); - } - - return true; -} - -bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); - - TU_LOG2("HID Set Protocol = %d\r\n", protocol); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = protocol, - .wIndex = hid_itf->itf_num, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_protocol_complete) ); - return true; -} - -static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_LOG2("HID Set Report complete\r\n"); - - if (tuh_hid_set_report_complete_cb) - { - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? request->wLength : 0); - } - - return true; -} - -bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_REPORT, - .wValue = tu_u16(report_type, report_id), - .wIndex = hid_itf->itf_num, - .wLength = len - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, report, set_report_complete) ); - return true; -} - -//--------------------------------------------------------------------+ -// Interrupt Endpoint API -//--------------------------------------------------------------------+ - -bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // claim endpoint - TU_VERIFY( usbh_edpt_claim(dev_addr, hid_itf->ep_in) ); - - return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); -} - -//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) -//{ -// TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); -// -// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); -// return !usbh_edpt_busy(dev_addr, hid_itf->ep_in); -//} - -//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); - -//--------------------------------------------------------------------+ -// USBH API -//--------------------------------------------------------------------+ -void hidh_init(void) -{ - tu_memclr(_hidh_dev, sizeof(_hidh_dev)); -} - -bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t const dir = tu_edpt_dir(ep_addr); - uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - if ( dir == TUSB_DIR_IN ) - { - TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); - TU_LOG3_MEM(hid_itf->epin_buf, xferred_bytes, 2); - tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); - }else - { - if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(dev_addr, instance, hid_itf->epout_buf, xferred_bytes); - } - - return true; -} - -void hidh_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - - hidh_device_t* hid_dev = get_dev(dev_addr); - - if (tuh_hid_umount_cb) - { - for (uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst); - } - - tu_memclr(hid_dev, sizeof(hidh_device_t)); -} - -//--------------------------------------------------------------------+ -// Enumeration -//--------------------------------------------------------------------+ - -static bool config_set_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); - -static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); - -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ - (void) max_len; - - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); - - TU_LOG2("HID opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); - - // len = interface + hid + n*endpoints - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_ASSERT(max_len >= drv_len); - - uint8_t const *p_desc = (uint8_t const *) desc_itf; - - //------------- HID descriptor -------------// - p_desc = tu_desc_next(p_desc); - tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); - - // not enough interface, try to increase CFG_TUH_HID - // TODO multiple devices - hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0); - - //------------- Endpoint Descriptor -------------// - p_desc = tu_desc_next(p_desc); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - - // first endpoint may be OUT, skip to IN endpoint - // TODO also open endpoint OUT - if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT) - { - p_desc = tu_desc_next(p_desc); - desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - } - - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - - hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); - hid_dev->inst_count++; - - hid_itf->itf_num = desc_itf->bInterfaceNumber; - hid_itf->ep_in = desc_ep->bEndpointAddress; - hid_itf->epin_size = tu_edpt_packet_size(desc_ep); - - // Assume bNumDescriptors = 1 - hid_itf->report_desc_type = desc_hid->bReportType; - hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - - // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config - hid_itf->protocol_mode = HID_PROTOCOL_BOOT; - if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - - return true; -} - -bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // Idle rate = 0 mean only report when there is changes - uint16_t const idle_rate = 0; - - // SET IDLE request, device can stall if not support this request - TU_LOG2("HID Set Idle \r\n"); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = idle_rate, - .wIndex = itf_num, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc) ); - - return true; -} - -// Force device to work in BOOT protocol -static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - // Stall is a valid response for SET_IDLE, therefore we could ignore its result - (void) result; - - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - TU_LOG2("HID Set Protocol to Boot Mode\r\n"); - hid_itf->protocol_mode = HID_PROTOCOL_BOOT; - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = HID_PROTOCOL_BOOT, - .wIndex = hid_itf->itf_num, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); - return true; -} - -static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - // We can be here after SET_IDLE or SET_PROTOCOL (boot device) - // Trigger assert if result is not successful with set protocol - if ( request->bRequest != HID_REQ_CONTROL_SET_IDLE ) - { - TU_ASSERT(result == XFER_RESULT_SUCCESS); - } - - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // Get Report Descriptor if possible - // using usbh enumeration buffer since report descriptor can be very long - if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) - { - TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len); - - // Driver is mounted without report descriptor - config_driver_mount_complete(dev_addr, instance, NULL, 0); - }else - { - TU_LOG2("HID Get Report Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_u16(hid_itf->report_desc_type, 0), - .wIndex = itf_num, - .wLength = hid_itf->report_desc_len - }; - - TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); - } - - return true; -} - -static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - - uint8_t const* desc_report = usbh_get_enum_buf(); - uint16_t const desc_len = request->wLength; - - config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); - - return true; -} - -static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // enumeration is complete - tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num); -} - -//--------------------------------------------------------------------+ -// Report Descriptor Parser -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) -{ - // Report Item 6.2.2.2 USB HID 1.11 - union TU_ATTR_PACKED - { - uint8_t byte; - struct TU_ATTR_PACKED - { - uint8_t size : 2; - uint8_t type : 2; - uint8_t tag : 4; - }; - } header; - - tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t)); - - uint8_t report_num = 0; - tuh_hid_report_info_t* info = report_info_arr; - - // current parsed report count & size from descriptor -// uint8_t ri_report_count = 0; -// uint8_t ri_report_size = 0; - - uint8_t ri_collection_depth = 0; - - while(desc_len && report_num < arr_count) - { - header.byte = *desc_report++; - desc_len--; - - uint8_t const tag = header.tag; - uint8_t const type = header.type; - uint8_t const size = header.size; - - uint8_t const data8 = desc_report[0]; - - TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size); - for(uint32_t i=0; iusage_page, desc_report, size); - break; - - case RI_GLOBAL_LOGICAL_MIN : break; - case RI_GLOBAL_LOGICAL_MAX : break; - case RI_GLOBAL_PHYSICAL_MIN : break; - case RI_GLOBAL_PHYSICAL_MAX : break; - - case RI_GLOBAL_REPORT_ID: - info->report_id = data8; - break; - - case RI_GLOBAL_REPORT_SIZE: -// ri_report_size = data8; - break; - - case RI_GLOBAL_REPORT_COUNT: -// ri_report_count = data8; - break; - - case RI_GLOBAL_UNIT_EXPONENT : break; - case RI_GLOBAL_UNIT : break; - case RI_GLOBAL_PUSH : break; - case RI_GLOBAL_POP : break; - - default: break; - } - break; - - case RI_TYPE_LOCAL: - switch(tag) - { - case RI_LOCAL_USAGE: - // only take in account the "usage" before starting REPORT ID - if ( ri_collection_depth == 0 ) info->usage = data8; - break; - - case RI_LOCAL_USAGE_MIN : break; - case RI_LOCAL_USAGE_MAX : break; - case RI_LOCAL_DESIGNATOR_INDEX : break; - case RI_LOCAL_DESIGNATOR_MIN : break; - case RI_LOCAL_DESIGNATOR_MAX : break; - case RI_LOCAL_STRING_INDEX : break; - case RI_LOCAL_STRING_MIN : break; - case RI_LOCAL_STRING_MAX : break; - case RI_LOCAL_DELIMITER : break; - default: break; - } - break; - - // error - default: break; - } - - desc_report += size; - desc_len -= size; - } - - for ( uint8_t i = 0; i < report_num; i++ ) - { - info = report_info_arr+i; - TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); - } - - return report_num; -} - -//--------------------------------------------------------------------+ -// Helper -//--------------------------------------------------------------------+ - -// Get Device by address -TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) -{ - return &_hidh_dev[dev_addr-1]; -} - -// Get Interface by instance number -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) -{ - return &_hidh_dev[dev_addr-1].instances[instance]; -} - -// Get instance ID by interface number -static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return inst; - } - - return 0xff; -} - -// Get instance ID by endpoint address -static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (ep_addr == hid->ep_in) || ( ep_addr == hid->ep_out) ) return inst; - } - - return 0xff; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h deleted file mode 100644 index fe09b03b2..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HID_HOST_H_ -#define _TUSB_HID_HOST_H_ - -#include "hid.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -// TODO Highspeed interrupt can be up to 512 bytes -#ifndef CFG_TUH_HID_EPIN_BUFSIZE -#define CFG_TUH_HID_EPIN_BUFSIZE 64 -#endif - -#ifndef CFG_TUH_HID_EPOUT_BUFSIZE -#define CFG_TUH_HID_EPOUT_BUFSIZE 64 -#endif - - -typedef struct -{ - uint8_t report_id; - uint8_t usage; - uint16_t usage_page; - - // TODO still use the endpoint size for now -// uint8_t in_len; // length of IN report -// uint8_t out_len; // length of OUT report -} tuh_hid_report_info_t; - -//--------------------------------------------------------------------+ -// Interface API -//--------------------------------------------------------------------+ - -// Get the number of HID instances -uint8_t tuh_hid_instance_count(uint8_t dev_addr); - -// Check if HID instance is mounted -bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); - -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); - -// Parse report descriptor into array of report_info struct and return number of reports. -// For complicated report, application should write its own parser. -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; - -//--------------------------------------------------------------------+ -// Control Endpoint API -//--------------------------------------------------------------------+ - -// Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// Note: Device will be initialized in Boot protocol for simplicity. -// Application can use set_protocol() to switch back to Report protocol. -uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); - -// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) -bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); - -// Set Report using control endpoint -// report_type is either Intput, Output or Feature, (value from hid_report_type_t) -bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); - -//--------------------------------------------------------------------+ -// Interrupt Endpoint API -//--------------------------------------------------------------------+ - -// Check if the interface is ready to use -//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); - -// Try to receive next report on Interrupt Endpoint. Immediately return -// - true If succeeded, tuh_hid_report_received_cb() callback will be invoked when report is available -// - false if failed to queue the transfer e.g endpoint is busy -bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance); - -// Send report using interrupt endpoint -// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. -//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); - -//--------------------------------------------------------------------+ -// Callbacks (Weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when device with hid interface is mounted -// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() -// can be used to parse common/simple enough descriptor. -// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped -// therefore report_desc = NULL, desc_len = 0 -void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); - -// Invoked when device with hid interface is un-mounted -TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); - -// Invoked when received report from device via interrupt endpoint -// Note: if there is report ID (composite), it is 1st byte of report -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); - -// Invoked when sent report to device successfully via interrupt endpoint -TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); - -// Invoked when Sent Report to device via either control endpoint -// len = 0 indicate there is error in the transfer e.g stalled response -TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); - -// Invoked when Set Protocol request is complete -TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hidh_init (void); -bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close (uint8_t dev_addr); - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_HID_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h deleted file mode 100644 index 74dc41749..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_CDC Communication Device Class (CDC) - * Currently only Abstract Control Model subclass is supported - * @{ */ - -#ifndef _TUSB_MIDI_H__ -#define _TUSB_MIDI_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Specific Descriptor -//--------------------------------------------------------------------+ - -typedef enum -{ - MIDI_CS_INTERFACE_HEADER = 0x01, - MIDI_CS_INTERFACE_IN_JACK = 0x02, - MIDI_CS_INTERFACE_OUT_JACK = 0x03, - MIDI_CS_INTERFACE_ELEMENT = 0x04, -} midi_cs_interface_subtype_t; - -typedef enum -{ - MIDI_CS_ENDPOINT_GENERAL = 0x01 -} midi_cs_endpoint_subtype_t; - -typedef enum -{ - MIDI_JACK_EMBEDDED = 0x01, - MIDI_JACK_EXTERNAL = 0x02 -} midi_jack_type_t; - -typedef enum -{ - MIDI_CIN_MISC = 0, - MIDI_CIN_CABLE_EVENT = 1, - MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect - MIDI_CIN_SYSCOM_3BYTE = 3, // 3 byte system common message e.g SPP - MIDI_CIN_SYSEX_START = 4, // SysEx starts or continue - MIDI_CIN_SYSEX_END_1BYTE = 5, // SysEx ends with 1 data, or 1 byte system common message - MIDI_CIN_SYSEX_END_2BYTE = 6, // SysEx ends with 2 data - MIDI_CIN_SYSEX_END_3BYTE = 7, // SysEx ends with 3 data - MIDI_CIN_NOTE_ON = 8, - MIDI_CIN_NOTE_OFF = 9, - MIDI_CIN_POLY_KEYPRESS = 10, - MIDI_CIN_CONTROL_CHANGE = 11, - MIDI_CIN_PROGRAM_CHANGE = 12, - MIDI_CIN_CHANNEL_PRESSURE = 13, - MIDI_CIN_PITCH_BEND_CHANGE = 14, - MIDI_CIN_1BYTE_DATA = 15 -} midi_code_index_number_t; - -// MIDI 1.0 status byte -enum -{ - //------------- System Exclusive -------------// - MIDI_STATUS_SYSEX_START = 0xF0, - MIDI_STATUS_SYSEX_END = 0xF7, - - //------------- System Common -------------// - MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME = 0xF1, - MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER = 0xF2, - MIDI_STATUS_SYSCOM_SONG_SELECT = 0xF3, - // F4, F5 is undefined - MIDI_STATUS_SYSCOM_TUNE_REQUEST = 0xF6, - - //------------- System RealTime -------------// - MIDI_STATUS_SYSREAL_TIMING_CLOCK = 0xF8, - // 0xF9 is undefined - MIDI_STATUS_SYSREAL_START = 0xFA, - MIDI_STATUS_SYSREAL_CONTINUE = 0xFB, - MIDI_STATUS_SYSREAL_STOP = 0xFC, - // 0xFD is undefined - MIDI_STATUS_SYSREAL_ACTIVE_SENSING = 0xFE, - MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, -}; - -/// MIDI Interface Header Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint16_t bcdMSC ; ///< MidiStreaming SubClass release number in Binary-Coded Decimal - uint16_t wTotalLength ; -} midi_desc_header_t; - -/// MIDI In Jack Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t iJack ; ///< string descriptor -} midi_desc_in_jack_t; - - -/// MIDI Out Jack Descriptor with single pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t bNrInputPins; - - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t iJack ; ///< string descriptor -} midi_desc_out_jack_t ; - -/// MIDI Out Jack Descriptor with multiple pins -#define midi_desc_out_jack_n_t(input_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bJackType ; \ - uint8_t bJackID ; \ - uint8_t bNrInputPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID; \ - uint8_t baSourcePin; \ - } pins[input_num]; \ - uint8_t iJack ; \ - } - -/// MIDI Element Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bElementID; - - uint8_t bNrInputPins; - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t bNrOutputPins; - uint8_t bInTerminalLink; - uint8_t bOutTerminalLink; - uint8_t bElCapsSize; - - uint16_t bmElementCaps; - uint8_t iElement; -} midi_desc_element_t; - -/// MIDI Element Descriptor with multiple pins -#define midi_desc_element_n_t(input_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength; \ - uint8_t bDescriptorType; \ - uint8_t bDescriptorSubType; \ - uint8_t bElementID; \ - uint8_t bNrInputPins; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID; \ - uint8_t baSourcePin; \ - } pins[input_num]; \ - uint8_t bNrOutputPins; \ - uint8_t bInTerminalLink; \ - uint8_t bOutTerminalLink; \ - uint8_t bElCapsSize; \ - uint16_t bmElementCaps; \ - uint8_t iElement; \ - } - -/** @} */ - -#ifdef __cplusplus - } -#endif - -#endif - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c deleted file mode 100644 index b08b362f9..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MIDI) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "midi_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef struct -{ - uint8_t buffer[4]; - uint8_t index; - uint8_t total; -}midid_stream_t; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - // For Stream read()/write() API - // Messages are always 4 bytes long, queue them for reading and writing so the - // callers can use the Stream interface with single-byte read/write calls. - midid_stream_t stream_write; - midid_stream_t stream_read; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_MIDI_TX_BUFSIZE]; - - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; - #endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; - -} midid_interface_t; - -#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, rx_ff) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI]; - -bool tud_midi_n_mounted (uint8_t itf) -{ - midid_interface_t* midi = &_midid_itf[itf]; - return midi->ep_in && midi->ep_out; -} - -static void _prep_out_transaction (midid_interface_t* p_midi) -{ - uint8_t const rhport = TUD_OPT_RHPORT; - uint16_t available = tu_fifo_remaining(&p_midi->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= sizeof(p_midi->epout_buf), ); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), ); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_midi->rx_ff); - - if ( available >= sizeof(p_midi->epout_buf) ) { - usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, sizeof(p_midi->epout_buf)); - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_midi->ep_out); - } -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ -uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) -{ - (void) cable_num; - - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t const* stream = &midi->stream_read; - - // when using with packet API stream total & index are both zero - return tu_fifo_count(&midi->rx_ff) + (stream->total - stream->index); -} - -uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) -{ - (void) cable_num; - TU_VERIFY(bufsize, 0); - - uint8_t* buf8 = (uint8_t*) buffer; - - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t* stream = &midi->stream_read; - - uint32_t total_read = 0; - while( bufsize ) - { - // Get new packet from fifo, then set packet expected bytes - if ( stream->total == 0 ) - { - // return if there is no more data from fifo - if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; - - uint8_t const code_index = stream->buffer[0] & 0x0f; - - // MIDI 1.0 Table 4-1: Code Index Number Classifications - switch(code_index) - { - case MIDI_CIN_MISC: - case MIDI_CIN_CABLE_EVENT: - // These are reserved and unused, possibly issue somewhere, skip this packet - return 0; - break; - - case MIDI_CIN_SYSEX_END_1BYTE: - case MIDI_CIN_1BYTE_DATA: - stream->total = 1; - break; - - case MIDI_CIN_SYSCOM_2BYTE : - case MIDI_CIN_SYSEX_END_2BYTE : - case MIDI_CIN_PROGRAM_CHANGE : - case MIDI_CIN_CHANNEL_PRESSURE : - stream->total = 2; - break; - - default: - stream->total = 3; - break; - } - } - - // Copy data up to bufsize - uint32_t const count = tu_min32(stream->total - stream->index, bufsize); - - // Skip the header (1st byte) in the buffer - memcpy(buf8, stream->buffer + 1 + stream->index, count); - - total_read += count; - stream->index += count; - buf8 += count; - bufsize -= count; - - // complete current event packet, reset stream - if ( stream->total == stream->index ) - { - stream->index = 0; - stream->total = 0; - } - } - - return total_read; -} - -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_out); - - uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); - _prep_out_transaction(midi); - return (num_read == 4); -} - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -static uint32_t write_flush(midid_interface_t* midi) -{ - // No data to send - if ( !tu_fifo_count(&midi->tx_ff) ) return 0; - - uint8_t const rhport = TUD_OPT_RHPORT; - - // skip if previous transfer not complete - TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); - - uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); - - if (count) - { - TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); - return count; - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, midi->ep_in); - return 0; - } -} - -uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in, 0); - - midid_stream_t* stream = &midi->stream_write; - - uint32_t i = 0; - while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) - { - uint8_t const data = buffer[i]; - i++; - - if ( stream->index == 0 ) - { - //------------- New event packet -------------// - - uint8_t const msg = data >> 4; - - stream->index = 2; - stream->buffer[1] = data; - - // Check to see if we're still in a SysEx transmit. - if ( stream->buffer[0] == MIDI_CIN_SYSEX_START ) - { - if ( data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; - } - else - { - stream->total = 4; - } - } - else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) - { - // Channel Voice Messages - stream->buffer[0] = (cable_num << 4) | msg; - stream->total = 4; - } - else if ( msg == 0xC || msg == 0xD) - { - // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) - stream->buffer[0] = (cable_num << 4) | msg; - stream->total = 3; - } - else if ( msg == 0xf ) - { - // System message - if ( data == MIDI_STATUS_SYSEX_START ) - { - stream->buffer[0] = MIDI_CIN_SYSEX_START; - stream->total = 4; - } - else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) - { - stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - stream->total = 3; - } - else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) - { - stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - stream->total = 4; - } - else - { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; - } - } - else - { - // Pack individual bytes if we don't support packing them into words. - stream->buffer[0] = cable_num << 4 | 0xf; - stream->buffer[2] = 0; - stream->buffer[3] = 0; - stream->index = 2; - stream->total = 2; - } - } - else - { - //------------- On-going (buffering) packet -------------// - - TU_ASSERT(stream->index < 4, i); - stream->buffer[stream->index] = data; - stream->index++; - - // See if this byte ends a SysEx. - if ( stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); - stream->total = stream->index; - } - } - - // Send out packet - if ( stream->index == stream->total ) - { - // zeroes unused bytes - for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; - - uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); - - // complete current event packet, reset stream - stream->index = stream->total = 0; - - // FIFO overflown, since we already check fifo remaining. It is probably race condition - TU_ASSERT(count == 4, i); - } - } - - write_flush(midi); - - return i; -} - -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in); - - if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; - - tu_fifo_write_n(&midi->tx_ff, packet, 4); - write_flush(midi); - - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void midid_init(void) -{ - tu_memclr(_midid_itf, sizeof(_midid_itf)); - - for(uint8_t i=0; irx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. - - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&midi->rx_ff, NULL, osal_mutex_create(&midi->rx_ff_mutex)); - tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex), NULL); - #endif - } -} - -void midid_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&midi->tx_ff); - } -} - -uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - // 1st Interface is Audio Control v1 - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); - - uint16_t drv_len = tu_desc_len(desc_itf); - uint8_t const * p_desc = tu_desc_next(desc_itf); - - // Skip Class Specific descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // 2nd Interface is MIDI Streaming - TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; - - TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && - AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); - - // Find available interface - midid_interface_t * p_midi = NULL; - for(uint8_t i=0; iitf_num = desc_midi->bInterfaceNumber; - (void) p_midi->itf_num; - - // next descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - // Find and open endpoint descriptors - uint8_t found_endpoints = 0; - while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) - { - p_midi->ep_in = ep_addr; - } else { - p_midi->ep_out = ep_addr; - } - - // Class Specific MIDI Stream endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - found_endpoints += 1; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // Prepare for incoming data - _prep_out_transaction(p_midi); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - (void) rhport; - (void) stage; - (void) request; - - // driver doesn't support any request yet - return false; -} - -bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) rhport; - - uint8_t itf; - midid_interface_t* p_midi; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_MIDI; itf++) - { - p_midi = &_midid_itf[itf]; - if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break; - } - TU_ASSERT(itf < CFG_TUD_MIDI); - - // receive new data - if ( ep_addr == p_midi->ep_out ) - { - tu_fifo_write_n(&p_midi->rx_ff, p_midi->epout_buf, xferred_bytes); - - // invoke receive callback if available - if (tud_midi_rx_cb) tud_midi_rx_cb(itf); - - // prepare for next - // TODO for now ep_out is not used by public API therefore there is no race condition, - // and does not need to claim like ep_in - _prep_out_transaction(p_midi); - } - else if ( ep_addr == p_midi->ep_in ) - { - if (0 == write_flush(p_midi)) - { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) - { - if ( usbd_edpt_claim(rhport, p_midi->ep_in) ) - { - usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); - } - } - } - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h deleted file mode 100644 index 211edc8d1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MIDI_DEVICE_H_ -#define _TUSB_MIDI_DEVICE_H_ - -#include "class/audio/audio.h" -#include "midi.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_MIDI_EP_BUFSIZE) && defined(CFG_TUD_MIDI_EPSIZE) - #warning CFG_TUD_MIDI_EPSIZE is renamed to CFG_TUD_MIDI_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE -#endif - -#ifndef CFG_TUD_MIDI_EP_BUFSIZE - #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -/** \addtogroup MIDI_Serial Serial - * @{ - * \defgroup MIDI_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -// CFG_TUD_MIDI > 1 -//--------------------------------------------------------------------+ - -// Check if midi interface is mounted -bool tud_midi_n_mounted (uint8_t itf); - -// Get the number of bytes available for reading -uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); - -// Read byte stream (legacy) -uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); - -// Write byte Stream (legacy) -uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -// Read event packet (4 bytes) -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); - -// Write event packet (4 bytes) -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); - -//--------------------------------------------------------------------+ -// Application API (Single Interface) -//--------------------------------------------------------------------+ -static inline bool tud_midi_mounted (void); -static inline uint32_t tud_midi_available (void); - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -static inline bool tud_midi_packet_read (uint8_t packet[4]); -static inline bool tud_midi_packet_write (uint8_t const packet[4]); - -//------------- Deprecated API name -------------// -// TODO remove after 0.10.0 release - -TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_stream_read(buffer, bufsize); -} - -TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") -static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_stream_write(cable_num, buffer, bufsize); -} - - -TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") -static inline bool tud_midi_send(uint8_t packet[4]) -{ - return tud_midi_packet_write(packet); -} - -TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") -static inline bool tud_midi_receive(uint8_t packet[4]) -{ - return tud_midi_packet_read(packet); -} - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline bool tud_midi_mounted (void) -{ - return tud_midi_n_mounted(0); -} - -static inline uint32_t tud_midi_available (void) -{ - return tud_midi_n_available(0, 0); -} - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_n_stream_read(0, 0, buffer, bufsize); -} - -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); -} - -static inline bool tud_midi_packet_read (uint8_t packet[4]) -{ - return tud_midi_n_packet_read(0, packet); -} - -static inline bool tud_midi_packet_write (uint8_t const packet[4]) -{ - return tud_midi_n_packet_write(0, packet); -} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void midid_init (void); -void midid_reset (uint8_t rhport); -uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MIDI_DEVICE_H_ */ - -/** @} */ -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h deleted file mode 100644 index 84b6e4d79..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h +++ /dev/null @@ -1,382 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_H_ -#define _TUSB_MSC_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Mass Storage Class Constant -//--------------------------------------------------------------------+ -/// MassStorage Subclass -typedef enum -{ - MSC_SUBCLASS_RBC = 1 , ///< Reduced Block Commands (RBC) T10 Project 1240-D - MSC_SUBCLASS_SFF_MMC , ///< SFF-8020i, MMC-2 (ATAPI). Typically used by a CD/DVD device - MSC_SUBCLASS_QIC , ///< QIC-157. Typically used by a tape device - MSC_SUBCLASS_UFI , ///< UFI. Typically used by Floppy Disk Drive (FDD) device - MSC_SUBCLASS_SFF , ///< SFF-8070i. Can be used by Floppy Disk Drive (FDD) device - MSC_SUBCLASS_SCSI ///< SCSI transparent command set -}msc_subclass_type_t; - -enum { - MSC_CBW_SIGNATURE = 0x43425355, ///< Constant value of 43425355h (little endian) - MSC_CSW_SIGNATURE = 0x53425355 ///< Constant value of 53425355h (little endian) -}; - -/// \brief MassStorage Protocol. -/// \details CBI only approved to use with full-speed floopy disk & should not used with highspeed or device other than floopy -typedef enum -{ - MSC_PROTOCOL_CBI = 0 , ///< Control/Bulk/Interrupt protocol (with command completion interrupt) - MSC_PROTOCOL_CBI_NO_INTERRUPT = 1 , ///< Control/Bulk/Interrupt protocol (without command completion interrupt) - MSC_PROTOCOL_BOT = 0x50 ///< Bulk-Only Transport -}msc_protocol_type_t; - -/// MassStorage Class-Specific Control Request -typedef enum -{ - MSC_REQ_GET_MAX_LUN = 254, ///< The Get Max LUN device request is used to determine the number of logical units supported by the device. Logical Unit Numbers on the device shall be numbered contiguously starting from LUN 0 to a maximum LUN of 15 - MSC_REQ_RESET = 255 ///< This request is used to reset the mass storage device and its associated interface. This class-specific request shall ready the device for the next CBW from the host. -}msc_request_type_t; - -/// \brief Command Block Status Values -/// \details Indicates the success or failure of the command. The device shall set this byte to zero if the command completed -/// successfully. A non-zero value shall indicate a failure during command execution according to the following -typedef enum -{ - MSC_CSW_STATUS_PASSED = 0 , ///< MSC_CSW_STATUS_PASSED - MSC_CSW_STATUS_FAILED , ///< MSC_CSW_STATUS_FAILED - MSC_CSW_STATUS_PHASE_ERROR ///< MSC_CSW_STATUS_PHASE_ERROR -}msc_csw_status_t; - -/// Command Block Wrapper -typedef struct TU_ATTR_PACKED -{ - uint32_t signature; ///< Signature that helps identify this data packet as a CBW. The signature field shall contain the value 43425355h (little endian), indicating a CBW. - uint32_t tag; ///< Tag sent by the host. The device shall echo the contents of this field back to the host in the dCSWTagfield of the associated CSW. The dCSWTagpositively associates a CSW with the corresponding CBW. - uint32_t total_bytes; ///< The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (as indicated by the Direction bit) during the execution of this command. If this field is zero, the device and the host shall transfer no data between the CBW and the associated CSW, and the device shall ignore the value of the Direction bit in bmCBWFlags. - uint8_t dir; ///< Bit 7 of this field define transfer direction \n - 0 : Data-Out from host to the device. \n - 1 : Data-In from the device to the host. - uint8_t lun; ///< The device Logical Unit Number (LUN) to which the command block is being sent. For devices that support multiple LUNs, the host shall place into this field the LUN to which this command block is addressed. Otherwise, the host shall set this field to zero. - uint8_t cmd_len; ///< The valid length of the CBWCBin bytes. This defines the valid length of the command block. The only legal values are 1 through 16 - uint8_t command[16]; ///< The command block to be executed by the device. The device shall interpret the first cmd_len bytes in this field as a command block -}msc_cbw_t; - -TU_VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct"); - -/// Command Status Wrapper -typedef struct TU_ATTR_PACKED -{ - uint32_t signature ; ///< Signature that helps identify this data packet as a CSW. The signature field shall contain the value 53425355h (little endian), indicating CSW. - uint32_t tag ; ///< The device shall set this field to the value received in the dCBWTag of the associated CBW. - uint32_t data_residue ; ///< For Data-Out the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLength, and the actual amount of data processed by the device. For Data-In the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLengthand the actual amount of relevant data sent by the device - uint8_t status ; ///< indicates the success or failure of the command. Values from \ref msc_csw_status_t -}msc_csw_t; - -TU_VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI Constant -//--------------------------------------------------------------------+ - -/// SCSI Command Operation Code -typedef enum -{ - SCSI_CMD_TEST_UNIT_READY = 0x00, ///< The SCSI Test Unit Ready command is used to determine if a device is ready to transfer data (read/write), i.e. if a disk has spun up, if a tape is loaded and ready etc. The device does not perform a self-test operation. - SCSI_CMD_INQUIRY = 0x12, ///< The SCSI Inquiry command is used to obtain basic information from a target device. - SCSI_CMD_MODE_SELECT_6 = 0x15, ///< provides a means for the application client to specify medium, logical unit, or peripheral device parameters to the device server. Device servers that implement the MODE SELECT(6) command shall also implement the MODE SENSE(6) command. Application clients should issue MODE SENSE(6) prior to each MODE SELECT(6) to determine supported mode pages, page lengths, and other parameters. - SCSI_CMD_MODE_SENSE_6 = 0x1A, ///< provides a means for a device server to report parameters to an application client. It is a complementary command to the MODE SELECT(6) command. Device servers that implement the MODE SENSE(6) command shall also implement the MODE SELECT(6) command. - SCSI_CMD_START_STOP_UNIT = 0x1B, - SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E, - SCSI_CMD_READ_CAPACITY_10 = 0x25, ///< The SCSI Read Capacity command is used to obtain data capacity information from a target device. - SCSI_CMD_REQUEST_SENSE = 0x03, ///< The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used to obtain sense data -- status/error information -- from a target device. - SCSI_CMD_READ_FORMAT_CAPACITY = 0x23, ///< The command allows the Host to request a list of the possible format capacities for an installed writable media. This command also has the capability to report the writable capacity for a media when it is installed - SCSI_CMD_READ_10 = 0x28, ///< The READ (10) command requests that the device server read the specified logical block(s) and transfer them to the data-in buffer. - SCSI_CMD_WRITE_10 = 0x2A, ///< The WRITE (10) command requests thatthe device server transfer the specified logical block(s) from the data-out buffer and write them. -}scsi_cmd_type_t; - -/// SCSI Sense Key -typedef enum -{ - SCSI_SENSE_NONE = 0x00, ///< no specific Sense Key. This would be the case for a successful command - SCSI_SENSE_RECOVERED_ERROR = 0x01, ///< ndicates the last command completed successfully with some recovery action performed by the disc drive. - SCSI_SENSE_NOT_READY = 0x02, ///< Indicates the logical unit addressed cannot be accessed. - SCSI_SENSE_MEDIUM_ERROR = 0x03, ///< Indicates the command terminated with a non-recovered error condition. - SCSI_SENSE_HARDWARE_ERROR = 0x04, ///< Indicates the disc drive detected a nonrecoverable hardware failure while performing the command or during a self test. - SCSI_SENSE_ILLEGAL_REQUEST = 0x05, ///< Indicates an illegal parameter in the command descriptor block or in the additional parameters - SCSI_SENSE_UNIT_ATTENTION = 0x06, ///< Indicates the disc drive may have been reset. - SCSI_SENSE_DATA_PROTECT = 0x07, ///< Indicates that a command that reads or writes the medium was attempted on a block that is protected from this operation. The read or write operation is not performed. - SCSI_SENSE_FIRMWARE_ERROR = 0x08, ///< Vendor specific sense key. - SCSI_SENSE_ABORTED_COMMAND = 0x0b, ///< Indicates the disc drive aborted the command. - SCSI_SENSE_EQUAL = 0x0c, ///< Indicates a SEARCH DATA command has satisfied an equal comparison. - SCSI_SENSE_VOLUME_OVERFLOW = 0x0d, ///< Indicates a buffered peripheral device has reached the end of medium partition and data remains in the buffer that has not been written to the medium. - SCSI_SENSE_MISCOMPARE = 0x0e ///< ndicates that the source data did not match the data read from the medium. -}scsi_sense_key_type_t; - -//--------------------------------------------------------------------+ -// SCSI Primary Command (SPC-4) -//--------------------------------------------------------------------+ - -/// SCSI Test Unit Ready Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_TEST_UNIT_READY - uint8_t lun ; ///< Logical Unit - uint8_t reserved[3] ; - uint8_t control ; -} scsi_test_unit_ready_t; - -TU_VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct"); - -/// SCSI Inquiry Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_INQUIRY - uint8_t reserved1 ; - uint8_t page_code ; - uint8_t reserved2 ; - uint8_t alloc_length ; ///< specifies the maximum number of bytes that USB host has allocated in the Data-In Buffer. An allocation length of zero specifies that no data shall be transferred. - uint8_t control ; -} scsi_inquiry_t, scsi_request_sense_t; - -TU_VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct"); - -/// SCSI Inquiry Response Data -typedef struct TU_ATTR_PACKED -{ - uint8_t peripheral_device_type : 5; - uint8_t peripheral_qualifier : 3; - - uint8_t : 7; - uint8_t is_removable : 1; - - uint8_t version; - - uint8_t response_data_format : 4; - uint8_t hierarchical_support : 1; - uint8_t normal_aca : 1; - uint8_t : 2; - - uint8_t additional_length; - - uint8_t protect : 1; - uint8_t : 2; - uint8_t third_party_copy : 1; - uint8_t target_port_group_support : 2; - uint8_t access_control_coordinator : 1; - uint8_t scc_support : 1; - - uint8_t addr16 : 1; - uint8_t : 3; - uint8_t multi_port : 1; - uint8_t : 1; // vendor specific - uint8_t enclosure_service : 1; - uint8_t : 1; - - uint8_t : 1; // vendor specific - uint8_t cmd_que : 1; - uint8_t : 2; - uint8_t sync : 1; - uint8_t wbus16 : 1; - uint8_t : 2; - - uint8_t vendor_id[8] ; ///< 8 bytes of ASCII data identifying the vendor of the product. - uint8_t product_id[16]; ///< 16 bytes of ASCII data defined by the vendor. - uint8_t product_rev[4]; ///< 4 bytes of ASCII data defined by the vendor. -} scsi_inquiry_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct"); - - -typedef struct TU_ATTR_PACKED -{ - uint8_t response_code : 7; ///< 70h - current errors, Fixed Format 71h - deferred errors, Fixed Format - uint8_t valid : 1; - - uint8_t reserved; - - uint8_t sense_key : 4; - uint8_t : 1; - uint8_t ili : 1; ///< Incorrect length indicator - uint8_t end_of_medium : 1; - uint8_t filemark : 1; - - uint32_t information; - uint8_t add_sense_len; - uint32_t command_specific_info; - uint8_t add_sense_code; - uint8_t add_sense_qualifier; - uint8_t field_replaceable_unit_code; - - uint8_t sense_key_specific[3]; ///< sense key specific valid bit is bit 7 of key[0], aka MSB in Big Endian layout - -} scsi_sense_fixed_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_MODE_SENSE_6 - - uint8_t : 3; - uint8_t disable_block_descriptor : 1; - uint8_t : 4; - - uint8_t page_code : 6; - uint8_t page_control : 2; - - uint8_t subpage_code; - uint8_t alloc_length; - uint8_t control; -} scsi_mode_sense6_t; - -TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct"); - -// This is only a Mode parameter header(6). -typedef struct TU_ATTR_PACKED -{ - uint8_t data_len; - uint8_t medium_type; - - uint8_t reserved : 7; - bool write_protected : 1; - - uint8_t block_descriptor_len; -} scsi_mode_sense6_resp_t; - -TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; ///< SCSI OpCode for \ref SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL - uint8_t reserved[3]; - uint8_t prohibit_removal; - uint8_t control; -} scsi_prevent_allow_medium_removal_t; - -TU_VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; - - uint8_t immded : 1; - uint8_t : 7; - - uint8_t TU_RESERVED; - - uint8_t power_condition_mod : 4; - uint8_t : 4; - - uint8_t start : 1; - uint8_t load_eject : 1; - uint8_t no_flush : 1; - uint8_t : 1; - uint8_t power_condition : 4; - - uint8_t control; -} scsi_start_stop_unit_t; - -TU_VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI MMC -//--------------------------------------------------------------------+ -/// SCSI Read Format Capacity: Write Capacity -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; - uint8_t reserved[6]; - uint16_t alloc_length; - uint8_t control; -} scsi_read_format_capacity_t; - -TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct"); - -typedef struct TU_ATTR_PACKED{ - uint8_t reserved[3]; - uint8_t list_length; /// must be 8*n, length in bytes of formattable capacity descriptor followed it. - - uint32_t block_num; /// Number of Logical Blocks - uint8_t descriptor_type; // 00: reserved, 01 unformatted media , 10 Formatted media, 11 No media present - - uint8_t reserved2; - uint16_t block_size_u16; - -} scsi_read_format_capacity_data_t; - -TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI Block Command (SBC-3) -// NOTE: All data in SCSI command are in Big Endian -//--------------------------------------------------------------------+ - -/// SCSI Read Capacity 10 Command: Read Capacity -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_READ_CAPACITY_10 - uint8_t reserved1 ; - uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command - uint16_t reserved2 ; - uint8_t partial_medium_indicator ; - uint8_t control ; -} scsi_read_capacity10_t; - -TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct"); - -/// SCSI Read Capacity 10 Response Data -typedef struct { - uint32_t last_lba ; ///< The last Logical Block Address of the device - uint32_t block_size ; ///< Block size in bytes -} scsi_read_capacity10_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct"); - -/// SCSI Read 10 Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode - uint8_t reserved ; // has LUN according to wiki - uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command - uint8_t reserved2 ; - uint16_t block_count ; ///< Number of Blocks used by this command - uint8_t control ; -} scsi_read10_t, scsi_write10_t; - -TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); -TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c deleted file mode 100644 index 97837b114..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c +++ /dev/null @@ -1,939 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MSC) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" -#include "device/dcd.h" // for faking dcd_event_xfer_complete - -#include "msc_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Can be selectively disabled to reduce logging when troubleshooting other driver -#define MSC_DEBUG 2 - -enum -{ - MSC_STAGE_CMD = 0, - MSC_STAGE_DATA, - MSC_STAGE_STATUS, - MSC_STAGE_STATUS_SENT, - MSC_STAGE_NEED_RESET, -}; - -typedef struct -{ - // TODO optimize alignment - CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; - CFG_TUSB_MEM_ALIGN msc_csw_t csw; - - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - // Bulk Only Transfer (BOT) Protocol - uint8_t stage; - uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw - uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage - - // Sense Response Data - uint8_t sense_key; - uint8_t add_sense_code; - uint8_t add_sense_qualifier; -}mscd_interface_t; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE]; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); - -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes); - -TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) -{ - return tu_bit_test(dir, 7); -} - -static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) -{ - // Data residue is always = host expect - actual transferred - p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; - - p_msc->stage = MSC_STAGE_STATUS_SENT; - return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)); -} - -static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc) -{ - p_msc->stage = MSC_STAGE_CMD; - return usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)); -} - -static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; - - p_csw->status = status; - p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; - p_msc->stage = MSC_STAGE_STATUS; - - // failed but sense key is not set: default to Illegal Request - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); - - // If there is data stage and not yet complete, stall it - if ( p_cbw->total_bytes && p_csw->data_residue ) - { - if ( is_data_in(p_cbw->dir) ) - { - usbd_edpt_stall(rhport, p_msc->ep_in); - } - else - { - usbd_edpt_stall(rhport, p_msc->ep_out); - } - } -} - -static inline uint32_t rdwr10_get_lba(uint8_t const command[]) -{ - // use offsetof to avoid pointer to the odd/unaligned address - uint32_t const lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba)); - - // lba is in Big Endian - return tu_ntohl(lba); -} - -static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) -{ - uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count)); - return tu_ntohs(block_count); -} - -static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) -{ - // first extract block count in the command - uint16_t const block_count = rdwr10_get_blockcount(cbw); - - // invalid block count - if (block_count == 0) return 0; - - return (uint16_t) (cbw->total_bytes / block_count); -} - -uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) -{ - uint8_t status = MSC_CSW_STATUS_PASSED; - uint16_t const block_count = rdwr10_get_blockcount(cbw); - - if ( cbw->total_bytes == 0 ) - { - if ( block_count ) - { - TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - }else - { - // no data transfer, only exist in complaint test suite - } - }else - { - if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) ) - { - TU_LOG(MSC_DEBUG, " SCSI case 10 (Ho <> Di)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) ) - { - TU_LOG(MSC_DEBUG, " SCSI case 8 (Hi <> Do)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - else if ( 0 == block_count ) - { - TU_LOG(MSC_DEBUG, " SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n"); - status = MSC_CSW_STATUS_FAILED; - } - else if ( cbw->total_bytes / block_count == 0 ) - { - TU_LOG(MSC_DEBUG, " Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - } - - return status; -} - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -TU_ATTR_UNUSED static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = -{ - { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, - { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, - { .key = SCSI_CMD_MODE_SELECT_6 , .data = "Mode_Select 6" }, - { .key = SCSI_CMD_MODE_SENSE_6 , .data = "Mode_Sense 6" }, - { .key = SCSI_CMD_START_STOP_UNIT , .data = "Start Stop Unit" }, - { .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent Allow Medium Removal" }, - { .key = SCSI_CMD_READ_CAPACITY_10 , .data = "Read Capacity10" }, - { .key = SCSI_CMD_REQUEST_SENSE , .data = "Request Sense" }, - { .key = SCSI_CMD_READ_FORMAT_CAPACITY , .data = "Read Format Capacity" }, - { .key = SCSI_CMD_READ_10 , .data = "Read10" }, - { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } -}; - -TU_ATTR_UNUSED static tu_lookup_table_t const _msc_scsi_cmd_table = -{ - .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), - .items = _msc_scsi_cmd_lookup -}; - -#endif - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier) -{ - (void) lun; - - _mscd_itf.sense_key = sense_key; - _mscd_itf.add_sense_code = add_sense_code; - _mscd_itf.add_sense_qualifier = add_sense_qualifier; - - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void mscd_init(void) -{ - tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); -} - -void mscd_reset(uint8_t rhport) -{ - (void) rhport; - tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); -} - -uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // only support SCSI's BOT protocol - TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && - MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); - - // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - - // Max length must be at least 1 interface + 2 endpoints - TU_ASSERT(max_len >= drv_len, 0); - - mscd_interface_t * p_msc = &_mscd_itf; - p_msc->itf_num = itf_desc->bInterfaceNumber; - - // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); - - // Prepare for Command Block Wrapper - TU_ASSERT( prepare_cbw(rhport, p_msc), drv_len); - - return drv_len; -} - -static void proc_bot_reset(mscd_interface_t* p_msc) -{ - p_msc->stage = MSC_STAGE_CMD; - p_msc->total_len = 0; - p_msc->xferred_len = 0; - - p_msc->sense_key = 0; - p_msc->add_sense_code = 0; - p_msc->add_sense_qualifier = 0; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA & ACK stage - if (stage != CONTROL_STAGE_SETUP) return true; - - mscd_interface_t* p_msc = &_mscd_itf; - - // Clear Endpoint Feature (stall) for recovery - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_RCPT_ENDPOINT == request->bmRequestType_bit.recipient && - TUSB_REQ_CLEAR_FEATURE == request->bRequest && - TUSB_REQ_FEATURE_EDPT_HALT == request->wValue ) - { - uint8_t const ep_addr = tu_u16_low(request->wIndex); - - if ( p_msc->stage == MSC_STAGE_NEED_RESET ) - { - // reset recovery is required to recover from this stage - // Clear Stall request cannot resolve this -> continue to stall endpoint - usbd_edpt_stall(rhport, ep_addr); - } - else - { - if ( ep_addr == p_msc->ep_in ) - { - if ( p_msc->stage == MSC_STAGE_STATUS ) - { - // resume sending SCSI status if we are in this stage previously before stalled - TU_ASSERT( send_csw(rhport, p_msc) ); - } - } - else if ( ep_addr == p_msc->ep_out ) - { - if ( p_msc->stage == MSC_STAGE_CMD ) - { - // part of reset recovery (probably due to invalid CBW) -> prepare for new command - // Note: skip if already queued previously - if ( usbd_edpt_ready(rhport, p_msc->ep_out) ) - { - TU_ASSERT( prepare_cbw(rhport, p_msc) ); - } - } - } - } - - return true; - } - - // From this point only handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch ( request->bRequest ) - { - case MSC_REQ_RESET: - TU_LOG(MSC_DEBUG, " MSC BOT Reset\r\n"); - TU_VERIFY(request->wValue == 0 && request->wLength == 0); - - // driver state reset - proc_bot_reset(p_msc); - - tud_control_status(rhport, request); - break; - - case MSC_REQ_GET_MAX_LUN: - { - TU_LOG(MSC_DEBUG, " MSC Get Max Lun\r\n"); - TU_VERIFY(request->wValue == 0 && request->wLength == 1); - - uint8_t maxlun = 1; - if (tud_msc_get_maxlun_cb) maxlun = tud_msc_get_maxlun_cb(); - TU_VERIFY(maxlun); - - // MAX LUN is minus 1 by specs - maxlun--; - - tud_control_xfer(rhport, request, &maxlun, 1); - } - break; - - default: return false; // stall unsupported request - } - - return true; -} - -bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - (void) event; - - mscd_interface_t* p_msc = &_mscd_itf; - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; - - switch (p_msc->stage) - { - case MSC_STAGE_CMD: - //------------- new CBW received -------------// - // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it - if(ep_addr != p_msc->ep_out) return true; - - if ( !(xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE) ) - { - TU_LOG(MSC_DEBUG, " SCSI CBW is not valid\r\n"); - - // BOT 6.6.1 If CBW is not valid stall both endpoints until reset recovery - p_msc->stage = MSC_STAGE_NEED_RESET; - - // invalid CBW stall both endpoints - usbd_edpt_stall(rhport, p_msc->ep_in); - usbd_edpt_stall(rhport, p_msc->ep_out); - - return false; - } - - TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); - //TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); - - p_csw->signature = MSC_CSW_SIGNATURE; - p_csw->tag = p_cbw->tag; - p_csw->data_residue = 0; - p_csw->status = MSC_CSW_STATUS_PASSED; - - /*------------- Parse command and prepare DATA -------------*/ - p_msc->stage = MSC_STAGE_DATA; - p_msc->total_len = p_cbw->total_bytes; - p_msc->xferred_len = 0; - - // Read10 or Write10 - if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) ) - { - uint8_t const status = rdwr10_validate_cmd(p_cbw); - - if ( status != MSC_CSW_STATUS_PASSED) - { - fail_scsi_op(rhport, p_msc, status); - }else if ( p_cbw->total_bytes ) - { - if (SCSI_CMD_READ_10 == p_cbw->command[0]) - { - proc_read10_cmd(rhport, p_msc); - }else - { - proc_write10_cmd(rhport, p_msc); - } - }else - { - // no data transfer, only exist in complaint test suite - p_msc->stage = MSC_STAGE_STATUS; - } - } - else - { - // For other SCSI commands - // 1. OUT : queue transfer (invoke app callback after done) - // 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length - if ( (p_cbw->total_bytes > 0 ) && !is_data_in(p_cbw->dir) ) - { - if (p_cbw->total_bytes > sizeof(_mscd_buf)) - { - TU_LOG(MSC_DEBUG, " SCSI reject non READ10/WRITE10 with large data\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // Didn't check for case 9 (Ho > Dn), which requires examining scsi command first - // but it is OK to just receive data then responded with failed status - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) ); - } - }else - { - // First process if it is a built-in commands - int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf)); - - // Invoke user callback if not built-in - if ( (resplen < 0) && (p_msc->sense_key == 0) ) - { - resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len); - } - - if ( resplen < 0 ) - { - // unsupported command - TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - } - else if (resplen == 0) - { - if (p_cbw->total_bytes) - { - // 6.7 The 13 Cases: case 4 (Hi > Dn) - // TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // case 1 Hn = Dn: all good - p_msc->stage = MSC_STAGE_STATUS; - } - } - else - { - if ( p_cbw->total_bytes == 0 ) - { - // 6.7 The 13 Cases: case 2 (Hn < Di) - // TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // cannot return more than host expect - p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes); - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) ); - } - } - } - } - break; - - case MSC_STAGE_DATA: - TU_LOG(MSC_DEBUG, " SCSI Data\r\n"); - //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2); - - if (SCSI_CMD_READ_10 == p_cbw->command[0]) - { - p_msc->xferred_len += xferred_bytes; - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - }else - { - proc_read10_cmd(rhport, p_msc); - } - } - else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) - { - proc_write10_new_data(rhport, p_msc, xferred_bytes); - } - else - { - p_msc->xferred_len += xferred_bytes; - - // OUT transfer, invoke callback if needed - if ( !is_data_in(p_cbw->dir) ) - { - int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len); - - if ( cb_result < 0 ) - { - // unsupported command - TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // TODO haven't implement this scenario any further yet - } - } - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - } - else - { - // This scenario with command that take more than one transfer is already rejected at Command stage - TU_BREAKPOINT(); - } - } - break; - - case MSC_STAGE_STATUS: - // processed immediately after this switch, supposedly to be empty - break; - - case MSC_STAGE_STATUS_SENT: - // Wait for the Status phase to complete - if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) - { - TU_LOG(MSC_DEBUG, " SCSI Status = %u\r\n", p_csw->status); - // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); - - // Invoke complete callback if defined - // Note: There is racing issue with samd51 + qspi flash testing with arduino - // if complete_cb() is invoked after queuing the status. - switch(p_cbw->command[0]) - { - case SCSI_CMD_READ_10: - if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun); - break; - - case SCSI_CMD_WRITE_10: - if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun); - break; - - default: - if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); - break; - } - - TU_ASSERT( prepare_cbw(rhport, p_msc) ); - }else - { - // Any xfer ended here is consider unknown error, ignore it - TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n"); - } - break; - - default : break; - } - - if ( p_msc->stage == MSC_STAGE_STATUS ) - { - // skip status if epin is currently stalled, will do it when received Clear Stall request - if ( !usbd_edpt_stalled(rhport, p_msc->ep_in) ) - { - if ( (p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir) ) - { - // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status - // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); - usbd_edpt_stall(rhport, p_msc->ep_in); - }else - { - TU_ASSERT( send_csw(rhport, p_msc) ); - } - } - - #if TU_CHECK_MCU(OPT_MCU_CXD56) - // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. - // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and - // hope everything will work - if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) - { - usbd_edpt_clear_stall(rhport, p_msc->ep_in); - send_csw(rhport, p_msc); - } - #endif - } - - return true; -} - -/*------------------------------------------------------------------*/ -/* SCSI Command Process - *------------------------------------------------------------------*/ - -// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) -// In case of a failed status, sense key must be set for reason of failure -static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) -{ - (void) bufsize; // TODO refractor later - int32_t resplen; - - mscd_interface_t* p_msc = &_mscd_itf; - - switch ( scsi_cmd[0] ) - { - case SCSI_CMD_TEST_UNIT_READY: - resplen = 0; - if ( !tud_msc_test_unit_ready_cb(lun) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - break; - - case SCSI_CMD_START_STOP_UNIT: - resplen = 0; - - if (tud_msc_start_stop_cb) - { - scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; - if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - } - break; - - case SCSI_CMD_READ_CAPACITY_10: - { - uint32_t block_count; - uint32_t block_size; - uint16_t block_size_u16; - - tud_msc_capacity_cb(lun, &block_count, &block_size_u16); - block_size = (uint32_t) block_size_u16; - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - scsi_read_capacity10_resp_t read_capa10; - - read_capa10.last_lba = tu_htonl(block_count-1); - read_capa10.block_size = tu_htonl(block_size); - - resplen = sizeof(read_capa10); - memcpy(buffer, &read_capa10, resplen); - } - } - break; - - case SCSI_CMD_READ_FORMAT_CAPACITY: - { - scsi_read_format_capacity_data_t read_fmt_capa = - { - .list_length = 8, - .block_num = 0, - .descriptor_type = 2, // formatted media - .block_size_u16 = 0 - }; - - uint32_t block_count; - uint16_t block_size; - - tud_msc_capacity_cb(lun, &block_count, &block_size); - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - read_fmt_capa.block_num = tu_htonl(block_count); - read_fmt_capa.block_size_u16 = tu_htons(block_size); - - resplen = sizeof(read_fmt_capa); - memcpy(buffer, &read_fmt_capa, resplen); - } - } - break; - - case SCSI_CMD_INQUIRY: - { - scsi_inquiry_resp_t inquiry_rsp = - { - .is_removable = 1, - .version = 2, - .response_data_format = 2, - }; - - // vendor_id, product_id, product_rev is space padded string - memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); - memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); - memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); - - tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); - - resplen = sizeof(inquiry_rsp); - memcpy(buffer, &inquiry_rsp, resplen); - } - break; - - case SCSI_CMD_MODE_SENSE_6: - { - scsi_mode_sense6_resp_t mode_resp = - { - .data_len = 3, - .medium_type = 0, - .write_protected = false, - .reserved = 0, - .block_descriptor_len = 0 // no block descriptor are included - }; - - bool writable = true; - if ( tud_msc_is_writable_cb ) - { - writable = tud_msc_is_writable_cb(lun); - } - - mode_resp.write_protected = !writable; - - resplen = sizeof(mode_resp); - memcpy(buffer, &mode_resp, resplen); - } - break; - - case SCSI_CMD_REQUEST_SENSE: - { - scsi_sense_fixed_resp_t sense_rsp = - { - .response_code = 0x70, - .valid = 1 - }; - - sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; - - sense_rsp.sense_key = p_msc->sense_key; - sense_rsp.add_sense_code = p_msc->add_sense_code; - sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier; - - resplen = sizeof(sense_rsp); - memcpy(buffer, &sense_rsp, resplen); - - // Clear sense data after copy - tud_msc_set_sense(lun, 0, 0, 0); - } - break; - - default: resplen = -1; break; - } - - return resplen; -} - -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes - uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); - - // Application can consume smaller bytes - uint32_t const offset = p_msc->xferred_len % block_sz; - nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_buf, (uint32_t) nbytes); - - if ( nbytes < 0 ) - { - // negative means error -> endpoint is stalled & status in CSW set to failed - TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n"); - - // Sense = Flash not ready for access - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00); - - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - } - else if ( nbytes == 0 ) - { - // zero means not ready -> simulate an transfer complete so that this driver callback will fired again - dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); - } - else - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, nbytes), ); - } -} - -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - bool writable = true; - - if ( tud_msc_is_writable_cb ) - { - writable = tud_msc_is_writable_cb(p_cbw->lun); - } - - if ( !writable ) - { - // Not writable, complete this SCSI op with error - // Sense = Write protected - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - return; - } - - // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); - - // Write10 callback will be called later when usb transfer complete - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), ); -} - -// process new data arrived from WRITE10 -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes - uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // Invoke callback to consume new data - uint32_t const offset = p_msc->xferred_len % block_sz; - int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_buf, xferred_bytes); - - if ( nbytes < 0 ) - { - // negative means error -> failed this scsi op - TU_LOG(MSC_DEBUG, " tud_msc_write10_cb() return -1\r\n"); - - // update actual byte before failed - p_msc->xferred_len += xferred_bytes; - - // Sense = Flash not ready for access - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00); - - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // Application consume less than what we got (including zero) - if ( (uint32_t) nbytes < xferred_bytes ) - { - if ( nbytes > 0 ) - { - p_msc->xferred_len += nbytes; - memmove(_mscd_buf, _mscd_buf+nbytes, xferred_bytes-nbytes); - } - - // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter - dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, XFER_RESULT_SUCCESS, false); - } - else - { - // Application consume all bytes in our buffer - p_msc->xferred_len += xferred_bytes; - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - }else - { - // prepare to receive more data from host - proc_write10_cmd(rhport, p_msc); - } - } - } -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h deleted file mode 100644 index d32694340..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_DEVICE_H_ -#define _TUSB_MSC_DEVICE_H_ - -#include "common/tusb_common.h" -#include "msc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_MSC_EP_BUFSIZE) & defined(CFG_TUD_MSC_BUFSIZE) - // TODO warn user to use new name later on - // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MSC_EP_BUFSIZE CFG_TUD_MSC_BUFSIZE -#endif - -#ifndef CFG_TUD_MSC_EP_BUFSIZE - #error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better -#endif - -TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Set SCSI sense response -bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// Invoked when received SCSI READ10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If -// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data. -// -// - read == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. -// -// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); - -// Invoked when received SCSI WRITE10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If -// - write < bufsize : callback invoked again with remaining data later on. -// -// - write == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. -// -// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -// -// TODO change buffer to const uint8_t* -int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); - -// Invoked when received SCSI_CMD_INQUIRY -// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively -void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]); - -// Invoked when received Test Unit Ready command. -// return true allowing host to read/write this LUN e.g SD card inserted -bool tud_msc_test_unit_ready_cb(uint8_t lun); - -// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size -// Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size); - -/** - * Invoked when received an SCSI command not in built-in list below. - * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE - * - READ10 and WRITE10 has their own callbacks - * - * \param[in] lun Logical unit number - * \param[in] scsi_cmd SCSI command contents which application must examine to response accordingly - * \param[out] buffer Buffer for SCSI Data Stage. - * - For INPUT: application must fill this with response. - * - For OUTPUT it holds the Data from host - * \param[in] bufsize Buffer's length. - * - * \return Actual bytes processed, can be zero for no-data command. - * \retval negative Indicate error e.g unsupported command, tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize); - -/*------------- Optional callbacks -------------*/ - -// Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation -TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void); - -// Invoked when received Start Stop Unit command -// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage -// - Start = 1 : active mode, if load_eject = 1 : load disk storage -TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject); - -// Invoked when Read10 command is complete -TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun); - -// Invoke when Write10 command is complete, can be used to flush flash caching -TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun); - -// Invoked when command in tud_msc_scsi_cb is complete -TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]); - -// Invoked to check if device is writable as part of SCSI WRITE10 -TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c deleted file mode 100644 index fa6519956..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "msc_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -enum -{ - MSC_STAGE_IDLE = 0, - MSC_STAGE_CMD, - MSC_STAGE_DATA, - MSC_STAGE_STATUS, -}; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t max_lun; - - volatile bool configured; // Receive SET_CONFIGURE - volatile bool mounted; // Enumeration is complete - - struct { - uint32_t block_size; - uint32_t block_count; - } capacity[CFG_TUH_MSC_MAXLUN]; - - //------------- SCSI -------------// - uint8_t stage; - void* buffer; - tuh_msc_complete_cb_t complete_cb; - - msc_cbw_t cbw; - msc_csw_t csw; -}msch_interface_t; - -CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; - -// buffer used to read scsi information when mounted -// largest response data currently is inquiry TODO Inquiry is not part of enum anymore -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) -static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; - -TU_ATTR_ALWAYS_INLINE -static inline msch_interface_t* get_itf(uint8_t dev_addr) -{ - return &_msch_itf[dev_addr-1]; -} - -//--------------------------------------------------------------------+ -// PUBLIC API -//--------------------------------------------------------------------+ -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->max_lun; -} - -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->capacity[lun].block_count; -} - -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->capacity[lun].block_size; -} - -bool tuh_msc_mounted(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted; -} - -bool tuh_msc_ready(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in); -} - -//--------------------------------------------------------------------+ -// PUBLIC API: SCSI COMMAND -//--------------------------------------------------------------------+ -static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) -{ - tu_memclr(cbw, sizeof(msc_cbw_t)); - cbw->signature = MSC_CBW_SIGNATURE; - cbw->tag = 0x54555342; // TUSB - cbw->lun = lun; -} - -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - // TODO claim endpoint - - p_msc->cbw = *cbw; - p_msc->stage = MSC_STAGE_CMD; - p_msc->buffer = data; - p_msc->complete_cb = complete_cb; - - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))); - - return true; -} - -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read_capacity10_t); - cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); -} - -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = sizeof(scsi_inquiry_resp_t); - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_inquiry_t); - - scsi_inquiry_t const cmd_inquiry = - { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_resp_t) - }; - memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); -} - -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = 0; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_test_unit_ready_t); - cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; - cbw.command[1] = lun; // according to wiki TODO need verification - - return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb); -} - -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb) -{ - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = 18; // TODO sense response - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_request_sense_t); - - scsi_request_sense_t const cmd_request_sense = - { - .cmd_code = SCSI_CMD_REQUEST_SENSE, - .alloc_length = 18 - }; - - memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb); -} - -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read10_t); - - scsi_read10_t const cmd_read10 = - { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_read10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb); -} - -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_write10_t); - - scsi_write10_t const cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_write10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb); -} - -#if 0 -// MSC interface Reset (not used now) -bool tuh_msc_reset(uint8_t dev_addr) -{ - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = MSC_REQ_RESET, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 0 - }; - TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); -} -#endif - -//--------------------------------------------------------------------+ -// CLASS-USBH API -//--------------------------------------------------------------------+ -void msch_init(void) -{ - tu_memclr(_msch_itf, sizeof(_msch_itf)); -} - -void msch_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - - msch_interface_t* p_msc = get_itf(dev_addr); - - // invoke Application Callback - if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); - - tu_memclr(p_msc, sizeof(msch_interface_t)); -} - -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - msc_cbw_t const * cbw = &p_msc->cbw; - msc_csw_t * csw = &p_msc->csw; - - switch (p_msc->stage) - { - case MSC_STAGE_CMD: - // Must be Command Block - TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); - - if ( cbw->total_bytes && p_msc->buffer ) - { - // Data stage if any - p_msc->stage = MSC_STAGE_DATA; - - uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out; - TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, cbw->total_bytes)); - }else - { - // Status stage - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); - } - break; - - case MSC_STAGE_DATA: - // Status stage - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); - break; - - case MSC_STAGE_STATUS: - // SCSI op is complete - p_msc->stage = MSC_STAGE_IDLE; - - if (p_msc->complete_cb) p_msc->complete_cb(dev_addr, cbw, csw); - break; - - // unknown state - default: break; - } - - return true; -} - -//--------------------------------------------------------------------+ -// MSC Enumeration -//--------------------------------------------------------------------+ - -static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); - -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ - TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && - MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); - - // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len); - - msch_interface_t* p_msc = get_itf(dev_addr); - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); - - for(uint32_t i=0; i<2; i++) - { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); - - if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) - { - p_msc->ep_in = ep_desc->bEndpointAddress; - }else - { - p_msc->ep_out = ep_desc->bEndpointAddress; - } - - ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); - } - - p_msc->itf_num = desc_itf->bInterfaceNumber; - - return true; -} - -bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_ASSERT(p_msc->itf_num == itf_num); - - p_msc->configured = true; - - //------------- Get Max Lun -------------// - TU_LOG2("MSC Get Max Lun\r\n"); - tusb_control_request_t request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = itf_num, - .wLength = 1 - }; - TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, config_get_maxlun_complete)); - - return true; -} - -static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - - msch_interface_t* p_msc = get_itf(dev_addr); - - // STALL means zero - p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0; - p_msc->max_lun++; // MAX LUN is minus 1 by specs - - // TODO multiple LUN support - TU_LOG2("SCSI Test Unit Ready\r\n"); - uint8_t const lun = 0; - tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete); - - return true; -} - -static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - if (csw->status == 0) - { - // Unit is ready, read its capacity - TU_LOG2("SCSI Read Capacity\r\n"); - tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete); - }else - { - // Note: During enumeration, some device fails Test Unit Ready and require a few retries - // with Request Sense to start working !! - // TODO limit number of retries - TU_LOG2("SCSI Request Sense\r\n"); - TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete)); - } - - return true; -} - -static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - TU_ASSERT(csw->status == 0); - TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, config_test_unit_ready_complete)); - return true; -} - -static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - TU_ASSERT(csw->status == 0); - - msch_interface_t* p_msc = get_itf(dev_addr); - - // Capacity response field: Block size and Last LBA are both Big-Endian - scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer); - p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; - p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); - - // Mark enumeration is complete - p_msc->mounted = true; - if (tuh_msc_mount_cb) tuh_msc_mount_cb(dev_addr); - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h deleted file mode 100644 index 7718ad4fe..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_HOST_H_ -#define _TUSB_MSC_HOST_H_ - -#include "msc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#ifndef CFG_TUH_MSC_MAXLUN -#define CFG_TUH_MSC_MAXLUN 4 -#endif - -typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Check if device supports MassStorage interface. -// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() -bool tuh_msc_mounted(uint8_t dev_addr); - -// Check if the interface is currently ready or busy transferring data -bool tuh_msc_ready(uint8_t dev_addr); - -// Get Max Lun -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); - -// Get number of block -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun); - -// Get block size in bytes -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); - -// Perform a full SCSI command (cbw, data, csw) in non-blocking manner. -// Complete callback is invoked when SCSI op is complete. -// return true if success, false if there is already pending operation. -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Inquiry command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Test Unit Ready command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Request Sense 10 command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Write 10 command. Write n blocks starting from LBA to device -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Read Capacity 10 command -// Complete callback is invoked when SCSI op is complete. -// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by -// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size() -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); - -//------------- Application Callback -------------// - -// Invoked when a device with MassStorage interface is mounted -TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); - -// Invoked when a device with MassStorage interface is unmounted -TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ - -void msch_init (void); -bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); -void msch_close (uint8_t dev_addr); -bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c deleted file mode 100644 index c6cd388e3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_ECM_RNDIS ) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "net_device.h" -#include "rndis_protocol.h" - -void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface - uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - bool ecm_mode; - - // Endpoint descriptor use to open/close when receving SetInterface - // TODO since configuration descriptor may not be long-lived memory, we should - // keep a copy of endpoint attribute instead - uint8_t const * ecm_desc_epdata; - -} netd_interface_t; - -#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) -#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; - -struct ecm_notify_struct -{ - tusb_control_request_t header; - uint32_t downlink, uplink; -}; - -static const struct ecm_notify_struct ecm_notify_nc = -{ - .header = { - .bmRequestType = 0xA1, - .bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */, - .wValue = 1 /* Connected */, - .wLength = 0, - }, -}; - -static const struct ecm_notify_struct ecm_notify_csc = -{ - .header = { - .bmRequestType = 0xA1, - .bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */, - .wLength = 8, - }, - .downlink = 9728000, - .uplink = 9728000, -}; - -// TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union -{ - uint8_t rndis_buf[120]; - struct ecm_notify_struct ecm_buf; -} notify; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -// TODO remove CFG_TUSB_MEM_SECTION -CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; - -static bool can_xmit; - -void tud_network_recv_renew(void) -{ - usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_out, received, sizeof(received)); -} - -static void do_in_xfer(uint8_t *buf, uint16_t len) -{ - can_xmit = false; - usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_in, buf, len); -} - -void netd_report(uint8_t *buf, uint16_t len) -{ - // skip if previous report not yet acknowledged by host - if ( usbd_edpt_busy(TUD_OPT_RHPORT, _netd_itf.ep_notif) ) return; - usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void netd_init(void) -{ - tu_memclr(&_netd_itf, sizeof(_netd_itf)); -} - -void netd_reset(uint8_t rhport) -{ - (void) rhport; - - netd_init(); -} - -uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && - TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); - - bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0x00 == itf_desc->bInterfaceProtocol); - - TU_VERIFY(is_rndis || is_ecm, 0); - - // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_notif, 0); - - // sanity check the descriptor - _netd_itf.ecm_mode = is_ecm; - - //------------- Management Interface -------------// - _netd_itf.itf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // notification endpoint (if any) - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); - - _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface -------------// - // - RNDIS Data followed immediately by a pair of endpoints - // - CDC-ECM data interface has 2 alternate settings - // - 0 : zero endpoints for inactive (default) - // - 1 : IN & OUT endpoints for active networking - TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - - do - { - tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; - TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len) ); - - // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); - - if ( _netd_itf.ecm_mode ) - { - // ECM by default is in-active, save the endpoint attribute - // to open later when received setInterface - _netd_itf.ecm_desc_epdata = p_desc; - }else - { - // Open endpoint pair for RNDIS - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0 ); - - tud_network_init_cb(); - - // we are ready to transmit a packet - can_xmit = true; - - // prepare for incoming packets - tud_network_recv_renew(); - } - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - - return drv_len; -} - -static void ecm_report(bool nc) -{ - notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; - notify.ecm_buf.header.wIndex = _netd_itf.itf_num; - netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - switch ( request->bmRequestType_bit.type ) - { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); - - tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; - - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); - - // ACM-ECM only: qequest to enable/disable network activities - TU_VERIFY(_netd_itf.ecm_mode); - - _netd_itf.itf_data_alt = req_alt; - - if ( _netd_itf.itf_data_alt ) - { - // TODO since we don't actually close endpoint - // hack here to not re-open it - if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) - { - TU_ASSERT(_netd_itf.ecm_desc_epdata); - TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - - // TODO should be merge with RNDIS's after endpoint opened - // Also should have opposite callback for application to disable network !! - tud_network_init_cb(); - can_xmit = true; // we are ready to transmit a packet - tud_network_recv_renew(); // prepare for incoming packets - } - }else - { - // TODO close the endpoint pair - // For now pretend that we did, this should have no harm since host won't try to - // communicate with the endpoints again - // _netd_itf.ep_in = _netd_itf.ep_out = 0 - } - - tud_control_status(rhport, request); - } - break; - - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (_netd_itf.itf_num == request->wIndex); - - if (_netd_itf.ecm_mode) - { - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) - { - tud_control_xfer(rhport, request, NULL, 0); - ecm_report(true); - } - } - else - { - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); - tud_control_xfer(rhport, request, notify.rndis_buf, msglen); - } - else - { - tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); - } - } - break; - - // unsupported request - default: return false; - } - } - else if ( stage == CONTROL_STAGE_DATA ) - { - // Handle RNDIS class control OUT only - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.direction == TUSB_DIR_OUT && - _netd_itf.itf_num == request->wIndex) - { - if ( !_netd_itf.ecm_mode ) - { - rndis_class_set_handler(notify.rndis_buf, request->wLength); - } - } - } - - return true; -} - -static void handle_incoming_packet(uint32_t len) -{ - uint8_t *pnt = received; - uint32_t size = 0; - - if (_netd_itf.ecm_mode) - { - size = len; - } - else - { - rndis_data_packet_t *r = (rndis_data_packet_t *) ((void*) pnt); - if (len >= sizeof(rndis_data_packet_t)) - if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) - if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) - { - pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; - size = r->DataLength; - } - } - - if (!tud_network_recv_cb(pnt, size)) - { - /* if a buffer was never handled by user code, we must renew on the user's behalf */ - tud_network_recv_renew(); - } -} - -bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - /* new packet received */ - if ( ep_addr == _netd_itf.ep_out ) - { - handle_incoming_packet(xferred_bytes); - } - - /* data transmission finished */ - if ( ep_addr == _netd_itf.ep_in ) - { - /* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */ - - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) ) - { - do_in_xfer(NULL, 0); /* a ZLP is needed */ - } - else - { - /* we're finally finished */ - can_xmit = true; - } - } - - if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) - { - if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); - } - - return true; -} - -bool tud_network_can_xmit(uint16_t size) -{ - (void)size; - - return can_xmit; -} - -void tud_network_xmit(void *ref, uint16_t arg) -{ - uint8_t *data; - uint16_t len; - - if (!can_xmit) - return; - - len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; - data = transmitted + len; - - len += tud_network_xmit_cb(data, ref, arg); - - if (!_netd_itf.ecm_mode) - { - rndis_data_packet_t *hdr = (rndis_data_packet_t *) ((void*) transmitted); - memset(hdr, 0, sizeof(rndis_data_packet_t)); - hdr->MessageType = REMOTE_NDIS_PACKET_MSG; - hdr->MessageLength = len; - hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); - hdr->DataLength = len - sizeof(rndis_data_packet_t); - } - - do_in_xfer(transmitted, len); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h deleted file mode 100644 index 96ba11fbc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef _TUSB_NCM_H_ -#define _TUSB_NCM_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -// Table 4.3 Data Class Interface Protocol Codes -typedef enum -{ - NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK = 0x01 -} ncm_data_interface_protocol_code_t; - - -// Table 6.2 Class-Specific Request Codes for Network Control Model subclass -typedef enum -{ - NCM_SET_ETHERNET_MULTICAST_FILTERS = 0x40, - NCM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, - NCM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, - NCM_SET_ETHERNET_PACKET_FILTER = 0x43, - NCM_GET_ETHERNET_STATISTIC = 0x44, - NCM_GET_NTB_PARAMETERS = 0x80, - NCM_GET_NET_ADDRESS = 0x81, - NCM_SET_NET_ADDRESS = 0x82, - NCM_GET_NTB_FORMAT = 0x83, - NCM_SET_NTB_FORMAT = 0x84, - NCM_GET_NTB_INPUT_SIZE = 0x85, - NCM_SET_NTB_INPUT_SIZE = 0x86, - NCM_GET_MAX_DATAGRAM_SIZE = 0x87, - NCM_SET_MAX_DATAGRAM_SIZE = 0x88, - NCM_GET_CRC_MODE = 0x89, - NCM_SET_CRC_MODE = 0x8A, -} ncm_request_code_t; - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c deleted file mode 100644 index 3e131a85c..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c +++ /dev/null @@ -1,510 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jacob Berg Potter - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NCM ) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" -#include "net_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -#define NTH16_SIGNATURE 0x484D434E -#define NDP16_SIGNATURE_NCM0 0x304D434E -#define NDP16_SIGNATURE_NCM1 0x314D434E - -typedef struct TU_ATTR_PACKED -{ - uint16_t wLength; - uint16_t bmNtbFormatsSupported; - uint32_t dwNtbInMaxSize; - uint16_t wNdbInDivisor; - uint16_t wNdbInPayloadRemainder; - uint16_t wNdbInAlignment; - uint16_t wReserved; - uint32_t dwNtbOutMaxSize; - uint16_t wNdbOutDivisor; - uint16_t wNdbOutPayloadRemainder; - uint16_t wNdbOutAlignment; - uint16_t wNtbOutMaxDatagrams; -} ntb_parameters_t; - -typedef struct TU_ATTR_PACKED -{ - uint32_t dwSignature; - uint16_t wHeaderLength; - uint16_t wSequence; - uint16_t wBlockLength; - uint16_t wNdpIndex; -} nth16_t; - -typedef struct TU_ATTR_PACKED -{ - uint16_t wDatagramIndex; - uint16_t wDatagramLength; -} ndp16_datagram_t; - -typedef struct TU_ATTR_PACKED -{ - uint32_t dwSignature; - uint16_t wLength; - uint16_t wNextNdpIndex; - ndp16_datagram_t datagram[]; -} ndp16_t; - -typedef union TU_ATTR_PACKED { - struct { - nth16_t nth; - ndp16_t ndp; - }; - uint8_t data[CFG_TUD_NCM_IN_NTB_MAX_SIZE]; -} transmit_ntb_t; - -struct ecm_notify_struct -{ - tusb_control_request_t header; - uint32_t downlink, uplink; -}; - -typedef struct -{ - uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface - uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - const ndp16_t *ndp; - uint8_t num_datagrams, current_datagram_index; - - enum { - REPORT_SPEED, - REPORT_CONNECTED, - REPORT_DONE - } report_state; - bool report_pending; - - uint8_t current_ntb; // Index in transmit_ntb[] that is currently being filled with datagrams - uint8_t datagram_count; // Number of datagrams in transmit_ntb[current_ntb] - uint16_t next_datagram_offset; // Offset in transmit_ntb[current_ntb].data to place the next datagram - uint16_t ntb_in_size; // Maximum size of transmitted (IN to host) NTBs; initially CFG_TUD_NCM_IN_NTB_MAX_SIZE - uint8_t max_datagrams_per_ntb; // Maximum number of datagrams per NTB; initially CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB - - uint16_t nth_sequence; // Sequence number counter for transmitted NTBs - - bool transferring; - -} ncm_interface_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static const ntb_parameters_t ntb_parameters = { - .wLength = sizeof(ntb_parameters_t), - .bmNtbFormatsSupported = 0x01, - .dwNtbInMaxSize = CFG_TUD_NCM_IN_NTB_MAX_SIZE, - .wNdbInDivisor = 4, - .wNdbInPayloadRemainder = 0, - .wNdbInAlignment = CFG_TUD_NCM_ALIGNMENT, - .wReserved = 0, - .dwNtbOutMaxSize = CFG_TUD_NCM_OUT_NTB_MAX_SIZE, - .wNdbOutDivisor = 4, - .wNdbOutPayloadRemainder = 0, - .wNdbOutAlignment = CFG_TUD_NCM_ALIGNMENT, - .wNtbOutMaxDatagrams = 0 -}; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static transmit_ntb_t transmit_ntb[2]; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t receive_ntb[CFG_TUD_NCM_OUT_NTB_MAX_SIZE]; - -static ncm_interface_t ncm_interface; - -/* - * Set up the NTB state in ncm_interface to be ready to add datagrams. - */ -static void ncm_prepare_for_tx(void) { - ncm_interface.datagram_count = 0; - // datagrams start after all the headers - ncm_interface.next_datagram_offset = sizeof(nth16_t) + sizeof(ndp16_t) - + ((CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB + 1) * sizeof(ndp16_datagram_t)); -} - -/* - * If not already transmitting, start sending the current NTB to the host and swap buffers - * to start filling the other one with datagrams. - */ -static void ncm_start_tx(void) { - if (ncm_interface.transferring) { - return; - } - - transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; - size_t ntb_length = ncm_interface.next_datagram_offset; - - // Fill in NTB header - ntb->nth.dwSignature = NTH16_SIGNATURE; - ntb->nth.wHeaderLength = sizeof(nth16_t); - ntb->nth.wSequence = ncm_interface.nth_sequence++; - ntb->nth.wBlockLength = ntb_length; - ntb->nth.wNdpIndex = sizeof(nth16_t); - - // Fill in NDP16 header and terminator - ntb->ndp.dwSignature = NDP16_SIGNATURE_NCM0; - ntb->ndp.wLength = sizeof(ndp16_t) + (ncm_interface.datagram_count + 1) * sizeof(ndp16_datagram_t); - ntb->ndp.wNextNdpIndex = 0; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = 0; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = 0; - - // Kick off an endpoint transfer - usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_in, ntb->data, ntb_length); - ncm_interface.transferring = true; - - // Swap to the other NTB and clear it out - ncm_interface.current_ntb = 1 - ncm_interface.current_ntb; - ncm_prepare_for_tx(); -} - -static struct ecm_notify_struct ncm_notify_connected = -{ - .header = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = CDC_NOTIF_NETWORK_CONNECTION, - .wValue = 1 /* Connected */, - .wLength = 0, - }, -}; - -static struct ecm_notify_struct ncm_notify_speed_change = -{ - .header = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE, - .wLength = 8, - }, - .downlink = 10000000, - .uplink = 10000000, -}; - -void tud_network_recv_renew(void) -{ - if (!ncm_interface.num_datagrams) - { - usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_out, receive_ntb, sizeof(receive_ntb)); - return; - } - - const ndp16_t *ndp = ncm_interface.ndp; - const int i = ncm_interface.current_datagram_index; - ncm_interface.current_datagram_index++; - ncm_interface.num_datagrams--; - - tud_network_recv_cb(receive_ntb + ndp->datagram[i].wDatagramIndex, ndp->datagram[i].wDatagramLength); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ - -void netd_init(void) -{ - tu_memclr(&ncm_interface, sizeof(ncm_interface)); - ncm_interface.ntb_in_size = CFG_TUD_NCM_IN_NTB_MAX_SIZE; - ncm_interface.max_datagrams_per_ntb = CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB; - ncm_prepare_for_tx(); -} - -void netd_reset(uint8_t rhport) -{ - (void) rhport; - - netd_init(); -} - -uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // confirm interface hasn't already been allocated - TU_ASSERT(0 == ncm_interface.ep_notif, 0); - - //------------- Management Interface -------------// - ncm_interface.itf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // notification endpoint (if any) - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); - - ncm_interface.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface -------------// - // - CDC-NCM data interface has 2 alternate settings - // - 0 : zero endpoints for inactive (default) - // - 1 : IN & OUT endpoints for transfer of NTBs - TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - - do - { - tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; - TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } while((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len)); - - // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); - - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &ncm_interface.ep_out, &ncm_interface.ep_in) ); - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - - return drv_len; -} - -static void ncm_report(void) -{ - if (ncm_interface.report_state == REPORT_SPEED) { - ncm_notify_speed_change.header.wIndex = ncm_interface.itf_num; - usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_speed_change, sizeof(ncm_notify_speed_change)); - ncm_interface.report_state = REPORT_CONNECTED; - ncm_interface.report_pending = true; - } else if (ncm_interface.report_state == REPORT_CONNECTED) { - ncm_notify_connected.header.wIndex = ncm_interface.itf_num; - usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_connected, sizeof(ncm_notify_connected)); - ncm_interface.report_state = REPORT_DONE; - ncm_interface.report_pending = true; - } -} - -TU_ATTR_WEAK void tud_network_link_state_cb(bool state) -{ - (void)state; -} - -// Handle class control request -// return false to stall control endpoint (e.g unsupported request) -bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage != CONTROL_STAGE_SETUP ) return true; - - switch ( request->bmRequestType_bit.type ) - { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum); - - tud_control_xfer(rhport, request, &ncm_interface.itf_data_alt, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; - - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum && req_alt < 2); - - if (req_alt != ncm_interface.itf_data_alt) { - ncm_interface.itf_data_alt = req_alt; - - if (ncm_interface.itf_data_alt) { - if (!usbd_edpt_busy(rhport, ncm_interface.ep_out)) { - tud_network_recv_renew(); // prepare for incoming datagrams - } - if (!ncm_interface.report_pending) { - ncm_report(); - } - } - - tud_network_link_state_cb(ncm_interface.itf_data_alt); - } - - tud_control_status(rhport, request); - } - break; - - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (ncm_interface.itf_num == request->wIndex); - - if (NCM_GET_NTB_PARAMETERS == request->bRequest) - { - tud_control_xfer(rhport, request, (void*)&ntb_parameters, sizeof(ntb_parameters)); - } - - break; - - // unsupported request - default: return false; - } - - return true; -} - -static void handle_incoming_datagram(uint32_t len) -{ - uint32_t size = len; - - if (len == 0) { - return; - } - - TU_ASSERT(size >= sizeof(nth16_t), ); - - const nth16_t *hdr = (const nth16_t *)receive_ntb; - TU_ASSERT(hdr->dwSignature == NTH16_SIGNATURE, ); - TU_ASSERT(hdr->wNdpIndex >= sizeof(nth16_t) && (hdr->wNdpIndex + sizeof(ndp16_t)) <= len, ); - - const ndp16_t *ndp = (const ndp16_t *)(receive_ntb + hdr->wNdpIndex); - TU_ASSERT(ndp->dwSignature == NDP16_SIGNATURE_NCM0 || ndp->dwSignature == NDP16_SIGNATURE_NCM1, ); - TU_ASSERT(hdr->wNdpIndex + ndp->wLength <= len, ); - - int num_datagrams = (ndp->wLength - 12) / 4; - ncm_interface.current_datagram_index = 0; - ncm_interface.num_datagrams = 0; - ncm_interface.ndp = ndp; - for (int i = 0; i < num_datagrams && ndp->datagram[i].wDatagramIndex && ndp->datagram[i].wDatagramLength; i++) - { - ncm_interface.num_datagrams++; - } - - tud_network_recv_renew(); -} - -bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - /* new datagram receive_ntb */ - if (ep_addr == ncm_interface.ep_out ) - { - handle_incoming_datagram(xferred_bytes); - } - - /* data transmission finished */ - if (ep_addr == ncm_interface.ep_in ) - { - if (ncm_interface.transferring) { - ncm_interface.transferring = false; - } - - // If there are datagrams queued up that we tried to send while this NTB was being emitted, send them now - if (ncm_interface.datagram_count && ncm_interface.itf_data_alt == 1) { - ncm_start_tx(); - } - } - - if (ep_addr == ncm_interface.ep_notif ) - { - ncm_interface.report_pending = false; - ncm_report(); - } - - return true; -} - -// poll network driver for its ability to accept another packet to transmit -bool tud_network_can_xmit(uint16_t size) -{ - TU_VERIFY(ncm_interface.itf_data_alt == 1); - - if (ncm_interface.datagram_count >= ncm_interface.max_datagrams_per_ntb) { - TU_LOG2("NTB full [by count]\r\n"); - return false; - } - - size_t next_datagram_offset = ncm_interface.next_datagram_offset; - if (next_datagram_offset + size > ncm_interface.ntb_in_size) { - TU_LOG2("ntb full [by size]\r\n"); - return false; - } - - return true; -} - -void tud_network_xmit(void *ref, uint16_t arg) -{ - transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; - size_t next_datagram_offset = ncm_interface.next_datagram_offset; - - uint16_t size = tud_network_xmit_cb(ntb->data + next_datagram_offset, ref, arg); - - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = ncm_interface.next_datagram_offset; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = size; - - ncm_interface.datagram_count++; - next_datagram_offset += size; - - // round up so the next datagram is aligned correctly - next_datagram_offset += (CFG_TUD_NCM_ALIGNMENT - 1); - next_datagram_offset -= (next_datagram_offset % CFG_TUD_NCM_ALIGNMENT); - - ncm_interface.next_datagram_offset = next_datagram_offset; - - ncm_start_tx(); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h deleted file mode 100644 index 6e294465b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_NET_DEVICE_H_ -#define _TUSB_NET_DEVICE_H_ - -#include "class/cdc/cdc.h" - -#if CFG_TUD_ECM_RNDIS && CFG_TUD_NCM -#error "Cannot enable both ECM_RNDIS and NCM network drivers" -#endif - -#include "ncm.h" - -/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ -#define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - -/* Maximum Transmission Unit (in bytes) of the network, including Ethernet header */ -#ifndef CFG_TUD_NET_MTU -#define CFG_TUD_NET_MTU 1514 -#endif - -#ifndef CFG_TUD_NCM_IN_NTB_MAX_SIZE -#define CFG_TUD_NCM_IN_NTB_MAX_SIZE 3200 -#endif - -#ifndef CFG_TUD_NCM_OUT_NTB_MAX_SIZE -#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200 -#endif - -#ifndef CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB -#define CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB 8 -#endif - -#ifndef CFG_TUD_NCM_ALIGNMENT -#define CFG_TUD_NCM_ALIGNMENT 4 -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// indicate to network driver that client has finished with the packet provided to network_recv_cb() -void tud_network_recv_renew(void); - -// poll network driver for its ability to accept another packet to transmit -bool tud_network_can_xmit(uint16_t size); - -// if network_can_xmit() returns true, network_xmit() can be called once -void tud_network_xmit(void *ref, uint16_t arg); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// client must provide this: return false if the packet buffer was not accepted -bool tud_network_recv_cb(const uint8_t *src, uint16_t size); - -// client must provide this: copy from network stack packet pointer to dst -uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg); - -//------------- ECM/RNDIS -------------// - -// client must provide this: initialize any network state back to the beginning -void tud_network_init_cb(void); - -// client must provide this: 48-bit MAC address -// TODO removed later since it is not part of tinyusb stack -extern const uint8_t tud_network_mac_address[6]; - -//------------- NCM -------------// - -// callback to client providing optional indication of internal state of network driver -void tud_network_link_state_cb(bool state); - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void netd_init (void); -void netd_reset (uint8_t rhport); -uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void netd_report (uint8_t *buf, uint16_t len); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_NET_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h deleted file mode 100644 index 7d7005c2e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h +++ /dev/null @@ -1,316 +0,0 @@ - -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 N Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBTMC_H__ -#define _TUSB_USBTMC_H__ - -#include "common/tusb_common.h" - - -/* Implements USBTMC Revision 1.0, April 14, 2003 - - String descriptors must have a "LANGID=0x409"/US English string. - Characters must be 0x20 (' ') to 0x7E ('~') ASCII, - But MUST not contain: "/:?\* - Also must not have leading or trailing space (' ') - Device descriptor must state USB version 0x0200 or greater - - If USB488DeviceCapabilites.D2 = 1 (SR1), then there must be a INT endpoint. -*/ - -#define USBTMC_VERSION 0x0100 -#define USBTMC_488_VERSION 0x0100 - -typedef enum { - USBTMC_MSGID_DEV_DEP_MSG_OUT = 1u, - USBTMC_MSGID_DEV_DEP_MSG_IN = 2u, - USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT = 126u, - USBTMC_MSGID_VENDOR_SPECIFIC_IN = 127u, - USBTMC_MSGID_USB488_TRIGGER = 128u, -} usbtmc_msgid_enum; - -/// \brief Message header (For BULK OUT and BULK IN); 4 bytes -typedef struct TU_ATTR_PACKED -{ - uint8_t MsgID ; ///< Message type ID (usbtmc_msgid_enum) - uint8_t bTag ; ///< Transfer ID 1<=bTag<=255 - uint8_t bTagInverse ; ///< Complement of the tag - uint8_t _reserved ; ///< Must be 0x00 -} usbtmc_msg_header_t; - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header; - uint8_t data[8]; -} usbtmc_msg_generic_t; - -/* Uses on the bulk-out endpoint: */ -// Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED { - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - struct TU_ATTR_PACKED - { - unsigned int EOM : 1 ; ///< EOM set on last byte - } bmTransferAttributes; - uint8_t _reserved[3]; -} usbtmc_msg_request_dev_dep_out; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_out) == 12u, "struct wrong length"); - -// Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - struct TU_ATTR_PACKED - { - unsigned int TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar - } bmTransferAttributes; - uint8_t TermChar; - uint8_t _reserved[2]; -} usbtmc_msg_request_dev_dep_in; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_in) == 12u, "struct wrong length"); - -/* Bulk-in headers */ - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header; - uint32_t TransferSize; - struct TU_ATTR_PACKED - { - uint8_t EOM: 1; ///< Last byte of transfer is the end of the message - uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar - } bmTransferAttributes; - uint8_t _reserved[3]; -} usbtmc_msg_dev_dep_msg_in_header_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_dev_dep_msg_in_header_t) == 12u, "struct wrong length"); - -/* Unsupported vendor things.... Are these ever used?*/ - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - uint8_t _reserved[4]; -} usbtmc_msg_request_vendor_specific_out; - - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_out) == 12u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - uint8_t _reserved[4]; -} usbtmc_msg_request_vendor_specific_in; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct wrong length"); - -// Control request type should use tusb_control_request_t - -/* -typedef struct TU_ATTR_PACKED { - struct { - unsigned int Recipient : 5 ; ///< EOM set on last byte - unsigned int Type : 2 ; ///< EOM set on last byte - unsigned int DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN - } bmRequestType; - uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum - uint16_t wValue ; - uint16_t wIndex ; - uint16_t wLength ; // Number of bytes in data stage -} usbtmc_class_specific_control_req; - -*/ -// bulk-in protocol errors -enum { - USBTMC_BULK_IN_ERR_INCOMPLETE_HEADER = 1u, - USBTMC_BULK_IN_ERR_UNSUPPORTED = 2u, - USBTMC_BULK_IN_ERR_BAD_PARAMETER = 3u, - USBTMC_BULK_IN_ERR_DATA_TOO_SHORT = 4u, - USBTMC_BULK_IN_ERR_DATA_TOO_LONG = 5u, -}; -// bult-in halt errors -enum { - USBTMC_BULK_IN_ERR = 1u, ///< receives a USBTMC command message that expects a response while a - /// Bulk-IN transfer is in progress -}; - -typedef enum { - USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT = 1u, - USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS = 2u, - USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN = 3u, - USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS = 4u, - USBTMC_bREQUEST_INITIATE_CLEAR = 5u, - USBTMC_bREQUEST_CHECK_CLEAR_STATUS = 6u, - USBTMC_bREQUEST_GET_CAPABILITIES = 7u, - - USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional - - /****** USBTMC 488 *************/ - USB488_bREQUEST_READ_STATUS_BYTE = 128u, - USB488_bREQUEST_REN_CONTROL = 160u, - USB488_bREQUEST_GO_TO_LOCAL = 161u, - USB488_bREQUEST_LOCAL_LOCKOUT = 162u, - -} usmtmc_request_type_enum; - -typedef enum { - USBTMC_STATUS_SUCCESS = 0x01, - USBTMC_STATUS_PENDING = 0x02, - USBTMC_STATUS_FAILED = 0x80, - USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81, - USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82, - USBTMC_STATUS_SPLIT_IN_PROGRESS = 0x83 -} usbtmc_status_enum; - -/************************************************************ - * Control Responses - */ - -typedef struct TU_ATTR_PACKED { - uint8_t USBTMC_status; ///< usbtmc_status_enum - uint8_t _reserved; - uint16_t bcdUSBTMC; ///< USBTMC_VERSION - - struct TU_ATTR_PACKED - { - unsigned int listenOnly :1; - unsigned int talkOnly :1; - unsigned int supportsIndicatorPulse :1; - } bmIntfcCapabilities; - struct TU_ATTR_PACKED - { - unsigned int canEndBulkInOnTermChar :1; - } bmDevCapabilities; - uint8_t _reserved2[6]; - uint8_t _reserved3[12]; -} usbtmc_response_capabilities_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - struct TU_ATTR_PACKED - { - unsigned int BulkInFifoBytes :1; - } bmClear; -} usbtmc_get_clear_status_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); - -// Used for both abort bulk IN and bulk OUT -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - uint8_t bTag; -} usbtmc_initiate_abort_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); - -// Used for both check_abort_bulk_in_status and check_abort_bulk_out_status -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - struct TU_ATTR_PACKED - { - unsigned int BulkInFifoBytes : 1; ///< Has queued data or a short packet that is queued - } bmAbortBulkIn; - uint8_t _reserved[2]; ///< Must be zero - uint32_t NBYTES_RXD_TXD; -} usbtmc_check_abort_bulk_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_check_abort_bulk_rsp_t) == 8u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; ///< usbtmc_status_enum - uint8_t _reserved; - uint16_t bcdUSBTMC; ///< USBTMC_VERSION - - struct TU_ATTR_PACKED - { - unsigned int listenOnly :1; - unsigned int talkOnly :1; - unsigned int supportsIndicatorPulse :1; - } bmIntfcCapabilities; - - struct TU_ATTR_PACKED - { - unsigned int canEndBulkInOnTermChar :1; - } bmDevCapabilities; - - uint8_t _reserved2[6]; - uint16_t bcdUSB488; - - struct TU_ATTR_PACKED - { - unsigned int is488_2 :1; - unsigned int supportsREN_GTL_LLO :1; - unsigned int supportsTrigger :1; - } bmIntfcCapabilities488; - - struct TU_ATTR_PACKED - { - unsigned int SCPI :1; - unsigned int SR1 :1; - unsigned int RL1 :1; - unsigned int DT1 :1; - } bmDevCapabilities488; - uint8_t _reserved3[8]; -} usbtmc_response_capabilities_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_488_t) == 0x18, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - uint8_t bTag; - uint8_t statusByte; -} usbtmc_read_stb_rsp_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - struct TU_ATTR_PACKED - { - unsigned int bTag : 7; - unsigned int one : 1; - } bNotify1; - uint8_t StatusByte; -} usbtmc_read_stb_interrupt_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); - -#endif - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c deleted file mode 100644 index 26be987cf..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Nathan Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* - * This library is not fully reentrant, though it is reentrant from the view - * of either the application layer or the USB stack. Due to its locking, - * it is not safe to call its functions from interrupts. - * - * The one exception is that its functions may not be called from the application - * until the USB stack is initialized. This should not be a problem since the - * device shouldn't be sending messages until it receives a request from the - * host. - */ - - -/* - * In the case of single-CPU "no OS", this task is never preempted other than by - * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. For "no OS", - * the mutex structure's main effect is to disable the USB interrupts. - * With an OS, this class driver uses the OSAL to perform locking. The code uses a single lock - * and does not call outside of this class with a lock held, so deadlocks won't happen. - */ - -//Limitations: -// "vendor-specific" commands are not handled. -// Dealing with "termchar" must be handled by the application layer, -// though additional error checking is does in this module. -// talkOnly and listenOnly are NOT supported. They're not permitted -// in USB488, anyway. - -/* Supported: - * - * Notification pulse - * Trigger - * Read status byte (both by interrupt endpoint and control message) - * - */ - - -// TODO: -// USBTMC 3.2.2 error conditions not strictly followed -// No local lock-out, REN, or GTL. -// Clear message available status byte at the correct time? (488 4.3.1.3) - - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "usbtmc_device.h" - -#ifdef xDEBUG -#include "uart_util.h" -static char logMsg[150]; -#endif - -/* - * The state machine does not allow simultaneous reading and writing. This is - * consistent with USBTMC. - */ - -typedef enum -{ - STATE_CLOSED, // Endpoints have not yet been opened since USB reset - STATE_NAK, // Bulk-out endpoint is in NAK state. - STATE_IDLE, // Bulk-out endpoint is waiting for CMD. - STATE_RCV, // Bulk-out is receiving DEV_DEP message - STATE_TX_REQUESTED, - STATE_TX_INITIATED, - STATE_TX_SHORTED, - STATE_CLEARING, - STATE_ABORTING_BULK_IN, - STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission - STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been transmitted - STATE_ABORTING_BULK_OUT, - STATE_NUM_STATES -} usbtmcd_state_enum; - -#if (CFG_TUD_USBTMC_ENABLE_488) - typedef usbtmc_response_capabilities_488_t usbtmc_capabilities_specific_t; -#else - typedef usbtmc_response_capabilities_t usbtmc_capabilities_specific_t; -#endif - - -typedef struct -{ - volatile usbtmcd_state_enum state; - - uint8_t itf_id; - uint8_t rhport; - uint8_t ep_bulk_in; - uint8_t ep_bulk_out; - uint8_t ep_int_in; - // IN buffer is only used for first packet, not the remainder - // in order to deal with prepending header - CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE]; - // OUT buffer receives one packet at a time - CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; - uint32_t transfer_size_remaining; // also used for requested length for bulk IN. - uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) - - uint8_t lastBulkOutTag; // used for aborts (mostly) - uint8_t lastBulkInTag; // used for aborts (mostly) - - uint8_t const * devInBuffer; // pointer to application-layer used for transmissions - - usbtmc_capabilities_specific_t const * capabilities; -} usbtmc_interface_state_t; - -CFG_TUSB_MEM_SECTION static usbtmc_interface_state_t usbtmc_state = -{ - .itf_id = 0xFF, -}; - -// We need all headers to fit in a single packet in this implementation. -TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); -TU_VERIFY_STATIC( - (sizeof(usbtmc_state.ep_bulk_in_buf) % USBTMCD_MAX_PACKET_SIZE) == 0, - "packet buffer must be a multiple of the packet size"); - -static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); - -static uint8_t termChar; -static uint8_t termCharRequested = false; - - -osal_mutex_def_t usbtmcLockBuffer; -static osal_mutex_t usbtmcLock; - -// Our own private lock, mostly for the state variable. -#define criticalEnter() do {osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) -#define criticalLeave() do {osal_mutex_unlock(usbtmcLock); } while (0) - -bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState) -{ - bool ret = true; - criticalEnter(); - usbtmcd_state_enum oldState = usbtmc_state.state; - if (oldState == expectedState) - { - usbtmc_state.state = newState; - } - else - { - ret = false; - } - criticalLeave(); - return ret; -} - -// called from app -// We keep a reference to the buffer, so it MUST not change until the app is -// notified that the transfer is complete. -// length of data is specified in the hdr. - -// We can't just send the whole thing at once because we need to concatanate the -// header with the data. -bool tud_usbtmc_transmit_dev_msg_data( - const void * data, size_t len, - bool endOfMessage, - bool usingTermChar) -{ - const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf); - -#ifndef NDEBUG - TU_ASSERT(len > 0u); - TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); - TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); - if(usingTermChar) - { - TU_ASSERT(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t const*)data)[len-1u] == termChar); - } -#endif - - TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); - usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf; - tu_varclr(hdr); - hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; - hdr->header.bTag = usbtmc_state.lastBulkInTag; - hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); - hdr->TransferSize = len; - hdr->bmTransferAttributes.EOM = endOfMessage; - hdr->bmTransferAttributes.UsingTermChar = usingTermChar; - - // Copy in the header - const size_t headerLen = sizeof(*hdr); - const size_t dataLen = ((headerLen + hdr->TransferSize) <= txBufLen) ? - len : (txBufLen - headerLen); - const size_t packetLen = headerLen + dataLen; - - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + headerLen, data, dataLen); - usbtmc_state.transfer_size_remaining = len - dataLen; - usbtmc_state.transfer_size_sent = dataLen; - usbtmc_state.devInBuffer = (uint8_t const*) data + (dataLen); - - bool stateChanged = - atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); - TU_VERIFY(stateChanged); - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); - return true; -} - -void usbtmcd_init_cb(void) -{ - usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); -#ifndef NDEBUG -# if CFG_TUD_USBTMC_ENABLE_488 - if (usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) { - TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); - } - // Per USB488 spec: table 8 - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); -# endif - if (usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) { - TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); - } -#endif - - usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); -} - -uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void)rhport; - - uint16_t drv_len; - uint8_t const * p_desc; - uint8_t found_endpoints = 0; - - TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS , 0); - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS, 0); - -#ifndef NDEBUG - // Only 2 or 3 endpoints are allowed for USBTMC. - TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3), 0); -#endif - - TU_ASSERT(usbtmc_state.state == STATE_CLOSED, 0); - - // Interface - drv_len = 0u; - p_desc = (uint8_t const *) itf_desc; - - usbtmc_state.itf_id = itf_desc->bInterfaceNumber; - usbtmc_state.rhport = rhport; - - while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len) - { - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) - { - tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; - switch(ep_desc->bmAttributes.xfer) { - case TUSB_XFER_BULK: - TU_ASSERT(tu_edpt_packet_size(ep_desc) == USBTMCD_MAX_PACKET_SIZE, 0); - if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) - { - usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; - } else { - usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress; - } - - break; - case TUSB_XFER_INTERRUPT: -#ifndef NDEBUG - TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN, 0); - TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); -#endif - usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; - break; - default: - TU_ASSERT(false, 0); - } - TU_ASSERT( usbd_edpt_open(rhport, ep_desc), 0); - found_endpoints++; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // bulk endpoints are required, but interrupt IN is optional -#ifndef NDEBUG - TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0); - TU_ASSERT(usbtmc_state.ep_bulk_out != 0, 0); - if (itf_desc->bNumEndpoints == 2) - { - TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); - } - else if (itf_desc->bNumEndpoints == 3) - { - TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); - } -#if (CFG_TUD_USBTMC_ENABLE_488) - if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || - usbtmc_state.capabilities->bmDevCapabilities488.SR1) - { - TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); - } -#endif -#endif - atomicChangeState(STATE_CLOSED, STATE_NAK); - tud_usbtmc_open_cb(itf_desc->iInterface); - - return drv_len; -} -// Tell USBTMC class to set its bulk-in EP to ACK so that it can -// receive USBTMC commands. -// Returns false if it was already in an ACK state or is busy -// processing a command (such as a clear). Returns true if it was -// in the NAK state and successfully transitioned to the ACK wait -// state. -bool tud_usbtmc_start_bus_read() -{ - usbtmcd_state_enum oldState = usbtmc_state.state; - switch(oldState) - { - // These may transition to IDLE - case STATE_NAK: - case STATE_ABORTING_BULK_IN_ABORTED: - TU_VERIFY(atomicChangeState(oldState, STATE_IDLE)); - break; - // When receiving, let it remain receiving - case STATE_RCV: - break; - default: - TU_VERIFY(false); - } - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); - return true; -} - -void usbtmcd_reset_cb(uint8_t rhport) -{ - (void)rhport; - usbtmc_capabilities_specific_t const * capabilities = tud_usbtmc_get_capabilities_cb(); - - criticalEnter(); - tu_varclr(&usbtmc_state); - usbtmc_state.capabilities = capabilities; - usbtmc_state.itf_id = 0xFFu; - criticalLeave(); -} - -static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) -{ - (void)rhport; - // return true upon failure, as we can assume error is being handled elsewhere. - TU_VERIFY(atomicChangeState(STATE_IDLE, STATE_RCV), true); - usbtmc_state.transfer_size_sent = 0u; - - // must be a header, should have been confirmed before calling here. - usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(tud_usbtmc_msgBulkOut_start_cb(msg)); - - TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); - usbtmc_state.lastBulkOutTag = msg->header.bTag; - return true; -} - -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) -{ - (void)rhport; - // return true upon failure, as we can assume error is being handled elsewhere. - TU_VERIFY(usbtmc_state.state == STATE_RCV,true); - - bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE); - - // Packet is to be considered complete when we get enough data or at a short packet. - bool atEnd = false; - if(len >= usbtmc_state.transfer_size_remaining || shortPacket) - { - atEnd = true; - TU_VERIFY(atomicChangeState(STATE_RCV, STATE_NAK)); - } - - len = tu_min32(len, usbtmc_state.transfer_size_remaining); - - usbtmc_state.transfer_size_remaining -= len; - usbtmc_state.transfer_size_sent += len; - - // App may (should?) call the wait_for_bus() command at this point - if(!tud_usbtmc_msg_data_cb(data, len, atEnd)) - { - // TODO: Go to an error state upon failure other than just stalling the EP? - return false; - } - - - return true; -} - -static bool handle_devMsgIn(void *data, size_t len) -{ - TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); - usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; - bool stateChanged = atomicChangeState(STATE_IDLE, STATE_TX_REQUESTED); - TU_VERIFY(stateChanged); - usbtmc_state.lastBulkInTag = msg->header.bTag; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - usbtmc_state.transfer_size_sent = 0u; - - termCharRequested = msg->bmTransferAttributes.TermCharEnabled; - termChar = msg->TermChar; - - if(termCharRequested) - TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - - TU_VERIFY(tud_usbtmc_msgBulkIn_request_cb(msg)); - return true; -} - -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - TU_VERIFY(result == XFER_RESULT_SUCCESS); - //uart_tx_str_sync("TMC XFER CB\r\n"); - if(usbtmc_state.state == STATE_CLEARING) { - return true; /* I think we can ignore everything here */ - } - - if(ep_addr == usbtmc_state.ep_bulk_out) - { - usbtmc_msg_generic_t *msg = NULL; - - switch(usbtmc_state.state) - { - case STATE_IDLE: - TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); - msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); - uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); - TU_VERIFY(msg->header.bTag == invInvTag); - TU_VERIFY(msg->header.bTag != 0x00); - - switch(msg->header.MsgID) { - case USBTMC_MSGID_DEV_DEP_MSG_OUT: - if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - TU_VERIFY(false); - } - break; - - case USBTMC_MSGID_DEV_DEP_MSG_IN: - TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); - break; - -#if (CFG_TUD_USBTMC_ENABLE_488) - case USBTMC_MSGID_USB488_TRIGGER: - // Spec says we halt the EP if we didn't declare we support it. - TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg)); - - break; -#endif - case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: - case USBTMC_MSGID_VENDOR_SPECIFIC_IN: - default: - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - TU_VERIFY(false); - return false; - } - return true; - - case STATE_RCV: - if(!handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - TU_VERIFY(false); - } - return true; - - case STATE_ABORTING_BULK_OUT: - TU_VERIFY(false); - return false; // Should be stalled by now, shouldn't have received a packet. - - case STATE_TX_REQUESTED: - case STATE_TX_INITIATED: - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_IN_SHORTED: - case STATE_ABORTING_BULK_IN_ABORTED: - default: - TU_VERIFY(false); - } - } - else if(ep_addr == usbtmc_state.ep_bulk_in) - { - switch(usbtmc_state.state) { - case STATE_TX_SHORTED: - TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); - TU_VERIFY(tud_usbtmc_msgBulkIn_complete_cb()); - break; - - case STATE_TX_INITIATED: - if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) - { - // FIXME! This removes const below! - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, - (void*)(uintptr_t) usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf))); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); - } - else // last packet - { - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen) ); - if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) - { - usbtmc_state.state = STATE_TX_SHORTED; - } - } - return true; - - case STATE_ABORTING_BULK_IN: - // need to send short packet (ZLP?) - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; - return true; - - case STATE_ABORTING_BULK_IN_SHORTED: - /* Done. :)*/ - usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; - return true; - - default: - TU_ASSERT(false); - return false; - } - } - else if (ep_addr == usbtmc_state.ep_int_in) { - // Good? - return true; - } - return false; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA and ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; -#if (CFG_TUD_USBTMC_ENABLE_488) - uint8_t bTag; -#endif - - if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && - (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && - (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && - (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) - { - uint32_t ep_addr = (request->wIndex); - - if(ep_addr == usbtmc_state.ep_bulk_out) - { - criticalEnter(); - usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us - criticalLeave(); - tud_usbtmc_bulkOut_clearFeature_cb(); - } - else if (ep_addr == usbtmc_state.ep_bulk_in) - { - tud_usbtmc_bulkIn_clearFeature_cb(); - } - else - { - return false; - } - return true; - } - - // Otherwise, we only handle class requests. - if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) - { - return false; - } - - // Verification that we own the interface is unneeded since it's been routed to us specifically. - - switch(request->bRequest) - { - // USBTMC required requests - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkOutTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - - // wValue is the requested bTag to abort - if(usbtmc_state.state != STATE_RCV) - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; - } - else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = STATE_ABORTING_BULK_OUT; - criticalLeave(); - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: - { - usbtmc_check_abort_bulk_rsp_t rsp = { - .USBTMC_status = USBTMC_STATUS_SUCCESS, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkInTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); - // wValue is the requested bTag to abort - if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && - usbtmc_state.lastBulkInTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.transfer_size_remaining = 0u; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) == 0) ? - STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; - criticalLeave(); - if(usbtmc_state.transfer_size_sent == 0) - { - // Send short packet, nothing is in the buffer yet - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; - } - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); - } - else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) - { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 8u); - - usbtmc_check_abort_bulk_rsp_t rsp = - { - .USBTMC_status = USBTMC_STATUS_FAILED, - .bmAbortBulkIn = - { - .BulkInFifoBytes = (usbtmc_state.state != STATE_ABORTING_BULK_IN_ABORTED) - }, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, - }; - TU_VERIFY(tud_usbtmc_check_abort_bulk_in_cb(&rsp)); - criticalEnter(); - switch(usbtmc_state.state) - { - case STATE_ABORTING_BULK_IN_ABORTED: - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.state = STATE_IDLE; - break; - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_OUT: - rsp.USBTMC_status = USBTMC_STATUS_PENDING; - break; - default: - break; - } - criticalLeave(); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - - return true; - } - - case USBTMC_bREQUEST_INITIATE_CLEAR: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the - // control endpoint response shown in Table 31, and clear all input buffers and output buffers. - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - usbtmc_state.transfer_size_remaining = 0; - criticalEnter(); - usbtmc_state.state = STATE_CLEARING; - criticalLeave(); - TU_VERIFY(tud_usbtmc_initiate_clear_cb(&tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); - return true; - } - - case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; - TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); - - if(usbd_edpt_busy(rhport, usbtmc_state.ep_bulk_in)) - { - // Stuff stuck in TX buffer? - clearStatusRsp.bmClear.BulkInFifoBytes = 1; - clearStatusRsp.USBTMC_status = USBTMC_STATUS_PENDING; - } - else - { - // Let app check if it's clear - TU_VERIFY(tud_usbtmc_check_clear_cb(&clearStatusRsp)); - } - if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) - { - criticalEnter(); - usbtmc_state.state = STATE_IDLE; - criticalLeave(); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); - return true; - } - - case USBTMC_bREQUEST_GET_CAPABILITIES: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(*(usbtmc_state.capabilities))); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); - return true; - } - // USBTMC Optional Requests - - case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_indicator_pulse_cb(request, &tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); - return true; - } -#if (CFG_TUD_USBTMC_ENABLE_488) - - // USB488 required requests - case USB488_bREQUEST_READ_STATUS_BYTE: - { - usbtmc_read_stb_rsp_488_t rsp; - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface - - bTag = request->wValue & 0x7F; - TU_VERIFY(request->bmRequestType == 0xA1); - TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero - TU_VERIFY(bTag >= 0x02 && bTag <= 127); - TU_VERIFY(request->wIndex == usbtmc_state.itf_id); - TU_VERIFY(request->wLength == 0x0003); - rsp.bTag = (uint8_t)bTag; - if(usbtmc_state.ep_int_in != 0) - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - rsp.statusByte = 0x00; // Use interrupt endpoint, instead. - - usbtmc_read_stb_interrupt_488_t intMsg = - { - .bNotify1 = { - .one = 1, - .bTag = bTag & 0x7Fu, - }, - .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)) - }; - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); - } - else - { - rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); - return true; - } - // USB488 optional requests - case USB488_bREQUEST_REN_CONTROL: - case USB488_bREQUEST_GO_TO_LOCAL: - case USB488_bREQUEST_LOCAL_LOCKOUT: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(false); - return false; - } -#endif - - default: - TU_VERIFY(false); - return false; - } - TU_VERIFY(false); -} - -#endif /* CFG_TUD_TSMC */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h deleted file mode 100644 index 0549a1569..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 N Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef CLASS_USBTMC_USBTMC_DEVICE_H_ -#define CLASS_USBTMC_USBTMC_DEVICE_H_ - -#include "usbtmc.h" - -// Enable 488 mode by default -#if !defined(CFG_TUD_USBTMC_ENABLE_488) -#define CFG_TUD_USBTMC_ENABLE_488 (1) -#endif - -// USB spec says that full-speed must be 8,16,32, or 64. -// However, this driver implementation requires it to be >=32 -#define USBTMCD_MAX_PACKET_SIZE (64u) - -/*********************************************** - * Functions to be implemeted by the class implementation - */ - -// In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: -// * tud_usbtmc_open_cb -// * tud_usbtmc_msg_data_cb -// * tud_usbtmc_msgBulkIn_complete_cb -// * tud_usbtmc_msg_trigger_cb -// * (successful) tud_usbtmc_check_abort_bulk_out_cb -// * (successful) tud_usbtmc_check_abort_bulk_in_cb -// * (successful) tud_usmtmc_bulkOut_clearFeature_cb - -#if (CFG_TUD_USBTMC_ENABLE_488) -usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); -#else -usbtmc_response_capabilities_t const * tud_usbtmc_get_capabilities_cb(void); -#endif - -void tud_usbtmc_open_cb(uint8_t interface_id); - -bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); -// transfer_complete does not imply that a message is complete. -bool tud_usbtmc_msg_data_cb( void *data, size_t len, bool transfer_complete); -void tud_usbtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer - -bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_msgBulkIn_complete_cb(void); -void tud_usbtmc_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer - -bool tud_usbtmc_initiate_abort_bulk_in_cb(uint8_t *tmcResult); -bool tud_usbtmc_initiate_abort_bulk_out_cb(uint8_t *tmcResult); -bool tud_usbtmc_initiate_clear_cb(uint8_t *tmcResult); - -bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); - -// Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); - -#if (CFG_TUD_USBTMC_ENABLE_488) -uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult); -TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg); -//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); -#endif - -/******************************************* - * Called from app - * - * We keep a reference to the buffer, so it MUST not change until the app is - * notified that the transfer is complete. - ******************************************/ - -bool tud_usbtmc_transmit_dev_msg_data( - const void * data, size_t len, - bool endOfMessage, bool usingTermChar); - -bool tud_usbtmc_start_bus_read(void); - - -/* "callbacks" from USB device core */ - -uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -void usbtmcd_reset_cb(uint8_t rhport); -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -void usbtmcd_init_cb(void); - -/************************************************************ - * USBTMC Descriptor Templates - *************************************************************/ - - -#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c deleted file mode 100644 index 8a4ca1d2e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VENDOR) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "vendor_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE]; -} vendord_interface_t; - -CFG_TUSB_MEM_SECTION static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]; - -#define ITF_MEM_RESET_SIZE offsetof(vendord_interface_t, rx_ff) - - -bool tud_vendor_n_mounted (uint8_t itf) -{ - return _vendord_itf[itf].ep_in && _vendord_itf[itf].ep_out; -} - -uint32_t tud_vendor_n_available (uint8_t itf) -{ - return tu_fifo_count(&_vendord_itf[itf].rx_ff); -} - -bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) -{ - return tu_fifo_peek(&_vendord_itf[itf].rx_ff, u8); -} - -//--------------------------------------------------------------------+ -// Read API -//--------------------------------------------------------------------+ -static void _prep_out_transaction (vendord_interface_t* p_itf) -{ - // skip if previous transfer not complete - if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_out) ) return; - - // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t max_read = tu_fifo_remaining(&p_itf->rx_ff); - if ( max_read >= CFG_TUD_VENDOR_EPSIZE ) - { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_out, p_itf->epout_buf, CFG_TUD_VENDOR_EPSIZE); - } -} - -uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_itf->rx_ff, buffer, bufsize); - _prep_out_transaction(p_itf); - return num_read; -} - -void tud_vendor_n_read_flush (uint8_t itf) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - tu_fifo_clear(&p_itf->rx_ff); - _prep_out_transaction(p_itf); -} - -//--------------------------------------------------------------------+ -// Write API -//--------------------------------------------------------------------+ -static bool maybe_transmit(vendord_interface_t* p_itf) -{ - // skip if previous transfer not complete - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_in) ); - - uint16_t count = tu_fifo_read_n(&p_itf->tx_ff, p_itf->epin_buf, CFG_TUD_VENDOR_EPSIZE); - if (count > 0) - { - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_in, p_itf->epin_buf, count) ); - } - return true; -} - -uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - uint16_t ret = tu_fifo_write_n(&p_itf->tx_ff, buffer, bufsize); - maybe_transmit(p_itf); - return ret; -} - -uint32_t tud_vendor_n_write_available (uint8_t itf) -{ - return tu_fifo_remaining(&_vendord_itf[itf].tx_ff); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void vendord_init(void) -{ - tu_memclr(_vendord_itf, sizeof(_vendord_itf)); - - for(uint8_t i=0; irx_ff, p_itf->rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, 1, false); - tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false); - -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_itf->rx_ff, NULL, osal_mutex_create(&p_itf->rx_ff_mutex)); - tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex), NULL); -#endif - } -} - -void vendord_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&p_itf->tx_ff); - } -} - -uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - - uint8_t const * p_desc = tu_desc_next(desc_itf); - uint8_t const * desc_end = p_desc + max_len; - - // Find available interface - vendord_interface_t* p_vendor = NULL; - for(uint8_t i=0; iitf_num = desc_itf->bInterfaceNumber; - if (desc_itf->bNumEndpoints) - { - // skip non-endpoint descriptors - while ( (TUSB_DESC_ENDPOINT != tu_desc_type(p_desc)) && (p_desc < desc_end) ) - { - p_desc = tu_desc_next(p_desc); - } - - // Open endpoint pair with usbd helper - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); - - p_desc += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - - // Prepare for incoming data - if ( p_vendor->ep_out ) - { - TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)), 0); - } - - if ( p_vendor->ep_in ) maybe_transmit(p_vendor); - } - - return (uintptr_t) p_desc - (uintptr_t) desc_itf; -} - -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - uint8_t itf = 0; - vendord_interface_t* p_itf = _vendord_itf; - - for ( ; ; itf++, p_itf++) - { - if (itf >= TU_ARRAY_SIZE(_vendord_itf)) return false; - - if ( ( ep_addr == p_itf->ep_out ) || ( ep_addr == p_itf->ep_in ) ) break; - } - - if ( ep_addr == p_itf->ep_out ) - { - // Receive new data - tu_fifo_write_n(&p_itf->rx_ff, p_itf->epout_buf, xferred_bytes); - - // Invoked callback if any - if (tud_vendor_rx_cb) tud_vendor_rx_cb(itf); - - _prep_out_transaction(p_itf); - } - else if ( ep_addr == p_itf->ep_in ) - { - // Send complete, try to send more if possible - maybe_transmit(p_itf); - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h deleted file mode 100644 index d71c2a3e9..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_VENDOR_DEVICE_H_ -#define _TUSB_VENDOR_DEVICE_H_ - -#include "common/tusb_common.h" - -#ifndef CFG_TUD_VENDOR_EPSIZE -#define CFG_TUD_VENDOR_EPSIZE 64 -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -//--------------------------------------------------------------------+ -bool tud_vendor_n_mounted (uint8_t itf); - -uint32_t tud_vendor_n_available (uint8_t itf); -uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); -bool tud_vendor_n_peek (uint8_t itf, uint8_t* ui8); -void tud_vendor_n_read_flush (uint8_t itf); - -uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); -uint32_t tud_vendor_n_write_available (uint8_t itf); - -static inline -uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_vendor_mounted (void); -static inline uint32_t tud_vendor_available (void); -static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); -static inline bool tud_vendor_peek (uint8_t* ui8); -static inline void tud_vendor_read_flush (void); -static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); -static inline uint32_t tud_vendor_write_str (char const* str); -static inline uint32_t tud_vendor_write_available (void); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received new data -TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str) -{ - return tud_vendor_n_write(itf, str, strlen(str)); -} - -static inline bool tud_vendor_mounted (void) -{ - return tud_vendor_n_mounted(0); -} - -static inline uint32_t tud_vendor_available (void) -{ - return tud_vendor_n_available(0); -} - -static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) -{ - return tud_vendor_n_read(0, buffer, bufsize); -} - -static inline bool tud_vendor_peek (uint8_t* ui8) -{ - return tud_vendor_n_peek(0, ui8); -} - -static inline void tud_vendor_read_flush(void) -{ - tud_vendor_n_read_flush(0); -} - -static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) -{ - return tud_vendor_n_write(0, buffer, bufsize); -} - -static inline uint32_t tud_vendor_write_str (char const* str) -{ - return tud_vendor_n_write_str(0, str); -} - -static inline uint32_t tud_vendor_write_available (void) -{ - return tud_vendor_n_write_available(0); -} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void vendord_init(void); -void vendord_reset(uint8_t rhport); -uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_VENDOR_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c deleted file mode 100644 index 1e28e9af4..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_VENDOR) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "host/usbh.h" -#include "vendor_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -custom_interface_info_t custom_interface[CFG_TUH_DEVICE_MAX]; - -static tusb_error_t cush_validate_paras(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) -{ - if ( !tusbh_custom_is_mounted(dev_addr, vendor_id, product_id) ) - { - return TUSB_ERROR_DEVICE_NOT_READY; - } - - TU_ASSERT( p_buffer != NULL && length != 0, TUSB_ERROR_INVALID_PARA); - - return TUSB_ERROR_NONE; -} -//--------------------------------------------------------------------+ -// APPLICATION API (need to check parameters) -//--------------------------------------------------------------------+ -tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) -{ - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_buffer, length) ); - - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_in) ) - { - return TUSB_ERROR_INTERFACE_IS_BUSY; - } - - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length) -{ - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_data, length) ); - - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_out) ) - { - return TUSB_ERROR_INTERFACE_IS_BUSY; - } - - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// USBH-CLASS API -//--------------------------------------------------------------------+ -void cush_init(void) -{ - tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUH_DEVICE_MAX); -} - -tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) -{ - // FIXME quick hack to test lpc1k custom class with 2 bulk endpoints - uint8_t const *p_desc = (uint8_t const *) p_interface_desc; - p_desc = tu_desc_next(p_desc); - - //------------- Bulk Endpoints Descriptor -------------// - for(uint32_t i=0; i<2; i++) - { - tusb_desc_endpoint_t const *p_endpoint = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint->bDescriptorType, TUSB_ERROR_INVALID_PARA); - - pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? - &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; - *p_pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); - TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); - - p_desc = tu_desc_next(p_desc); - } - - (*p_length) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - return TUSB_ERROR_NONE; -} - -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event) -{ - -} - -void cush_close(uint8_t dev_addr) -{ - tusb_error_t err1, err2; - custom_interface_info_t * p_interface = &custom_interface[dev_addr-1]; - - // TODO re-consider to check pipe valid before calling pipe_close - if( pipehandle_is_valid( p_interface->pipe_in ) ) - { - err1 = hcd_pipe_close( p_interface->pipe_in ); - } - - if ( pipehandle_is_valid( p_interface->pipe_out ) ) - { - err2 = hcd_pipe_close( p_interface->pipe_out ); - } - - tu_memclr(p_interface, sizeof(custom_interface_info_t)); - - TU_ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 ); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h deleted file mode 100644 index 07fa56c61..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_VENDOR_HOST_H_ -#define _TUSB_VENDOR_HOST_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -typedef struct { - pipe_handle_t pipe_in; - pipe_handle_t pipe_out; -}custom_interface_info_t; - -//--------------------------------------------------------------------+ -// USBH-CLASS DRIVER API -//--------------------------------------------------------------------+ -static inline bool tusbh_custom_is_mounted(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id) -{ - (void) vendor_id; // TODO check this later - (void) product_id; -// return (tusbh_device_get_mounted_class_flag(dev_addr) & TU_BIT(TUSB_CLASS_MAPPED_INDEX_END-1) ) != 0; - return false; -} - -tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length); -tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void cush_init(void); -tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event); -void cush_close(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_VENDOR_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h deleted file mode 100644 index 844746546..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h +++ /dev/null @@ -1,480 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Koji KITAYAMA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_VIDEO_H_ -#define TUSB_VIDEO_H_ - -#include "common/tusb_common.h" - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00, - VIDEO_COLOR_PRIMARIES_BT709, // sRGB (default) - VIDEO_COLOR_PRIMARIES_BT470_2M, - VIDEO_COLOR_PRIMARIES_BT470_2BG, - VIDEO_COLOR_PRIMARIES_SMPTE170M, - VIDEO_COLOR_PRIMARIES_SMPTE240M, -} video_color_primaries_t; - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_XFER_CH_UNDEFINED = 0x00, - VIDEO_COLOR_XFER_CH_BT709, // default - VIDEO_COLOR_XFER_CH_BT470_2M, - VIDEO_COLOR_XFER_CH_BT470_2BG, - VIDEO_COLOR_XFER_CH_SMPTE170M, - VIDEO_COLOR_XFER_CH_SMPTE240M, - VIDEO_COLOR_XFER_CH_LINEAR, - VIDEO_COLOR_XFER_CH_SRGB, -} video_color_transfer_characteristics_t; - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_COEF_UNDEFINED = 0x00, - VIDEO_COLOR_COEF_BT709, - VIDEO_COLOR_COEF_FCC, - VIDEO_COLOR_COEF_BT470_2BG, - VIDEO_COLOR_COEF_SMPTE170M, // BT.601 default - VIDEO_COLOR_COEF_SMPTE240M, -} video_color_matrix_coefficients_t; - -/* 4.2.1.2 Request Error Code Control */ -typedef enum { - VIDEO_ERROR_NONE = 0, /* The request succeeded. */ - VIDEO_ERROR_NOT_READY, - VIDEO_ERROR_WRONG_STATE, - VIDEO_ERROR_POWER, - VIDEO_ERROR_OUT_OF_RANGE, - VIDEO_ERROR_INVALID_UNIT, - VIDEO_ERROR_INVALID_CONTROL, - VIDEO_ERROR_INVALID_REQUEST, - VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE, - VIDEO_ERROR_UNKNOWN = 0xFF, -} video_error_code_t; - -/* A.2 Interface Subclass */ -typedef enum { - VIDEO_SUBCLASS_UNDEFINED = 0x00, - VIDEO_SUBCLASS_CONTROL, - VIDEO_SUBCLASS_STREAMING, - VIDEO_SUBCLASS_INTERFACE_COLLECTION, -} video_subclass_type_t; - -/* A.3 Interface Protocol */ -typedef enum { - VIDEO_ITF_PROTOCOL_UNDEFINED = 0x00, - VIDEO_ITF_PROTOCOL_15, -} video_interface_protocol_code_t; - -/* A.5 Class-Specific VideoControl Interface Descriptor Subtypes */ -typedef enum { - VIDEO_CS_ITF_VC_UNDEFINED = 0x00, - VIDEO_CS_ITF_VC_HEADER, - VIDEO_CS_ITF_VC_INPUT_TERMINAL, - VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, - VIDEO_CS_ITF_VC_SELECTOR_UNIT, - VIDEO_CS_ITF_VC_PROCESSING_UNIT, - VIDEO_CS_ITF_VC_EXTENSION_UNIT, - VIDEO_CS_ITF_VC_ENCODING_UNIT, - VIDEO_CS_ITF_VC_MAX, -} video_cs_vc_interface_subtype_t; - -/* A.6 Class-Specific VideoStreaming Interface Descriptor Subtypes */ -typedef enum { - VIDEO_CS_ITF_VS_UNDEFINED = 0x00, - VIDEO_CS_ITF_VS_INPUT_HEADER = 0x01, - VIDEO_CS_ITF_VS_OUTPUT_HEADER = 0x02, - VIDEO_CS_ITF_VS_STILL_IMAGE_FRAME = 0x03, - VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED = 0x04, - VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED = 0x05, - VIDEO_CS_ITF_VS_FORMAT_MJPEG = 0x06, - VIDEO_CS_ITF_VS_FRAME_MJPEG = 0x07, - VIDEO_CS_ITF_VS_FORMAT_MPEG2TS = 0x0A, - VIDEO_CS_ITF_VS_FORMAT_DV = 0x0C, - VIDEO_CS_ITF_VS_COLORFORMAT = 0x0D, - VIDEO_CS_ITF_VS_FORMAT_FRAME_BASED = 0x10, - VIDEO_CS_ITF_VS_FRAME_FRAME_BASED = 0x11, - VIDEO_CS_ITF_VS_FORMAT_STREAM_BASED = 0x12, - VIDEO_CS_ITF_VS_FORMAT_H264 = 0x13, - VIDEO_CS_ITF_VS_FRAME_H264 = 0x14, - VIDEO_CS_ITF_VS_FORMAT_H264_SIMULCAST = 0x15, - VIDEO_CS_ITF_VS_FORMAT_VP8 = 0x16, - VIDEO_CS_ITF_VS_FRAME_VP8 = 0x17, - VIDEO_CS_ITF_VS_FORMAT_VP8_SIMULCAST = 0x18, -} video_cs_vs_interface_subtype_t; - -/* A.7. Class-Specific Endpoint Descriptor Subtypes */ -typedef enum { - VIDEO_CS_EP_UNDEFINED = 0x00, - VIDEO_CS_EP_GENERAL, - VIDEO_CS_EP_ENDPOINT, - VIDEO_CS_EP_INTERRUPT -} video_cs_ep_subtype_t; - -/* A.8 Class-Specific Request Codes */ -typedef enum { - VIDEO_REQUEST_UNDEFINED = 0x00, - VIDEO_REQUEST_SET_CUR = 0x01, - VIDEO_REQUEST_SET_CUR_ALL = 0x11, - VIDEO_REQUEST_GET_CUR = 0x81, - VIDEO_REQUEST_GET_MIN = 0x82, - VIDEO_REQUEST_GET_MAX = 0x83, - VIDEO_REQUEST_GET_RES = 0x84, - VIDEO_REQUEST_GET_LEN = 0x85, - VIDEO_REQUEST_GET_INFO = 0x86, - VIDEO_REQUEST_GET_DEF = 0x87, - VIDEO_REQUEST_GET_CUR_ALL = 0x91, - VIDEO_REQUEST_GET_MIN_ALL = 0x92, - VIDEO_REQUEST_GET_MAX_ALL = 0x93, - VIDEO_REQUEST_GET_RES_ALL = 0x94, - VIDEO_REQUEST_GET_DEF_ALL = 0x97 -} video_control_request_t; - -/* A.9.1 VideoControl Interface Control Selectors */ -typedef enum { - VIDEO_VC_CTL_UNDEFINED = 0x00, - VIDEO_VC_CTL_VIDEO_POWER_MODE, - VIDEO_VC_CTL_REQUEST_ERROR_CODE, -} video_interface_control_selector_t; - -/* A.9.8 VideoStreaming Interface Control Selectors */ -typedef enum { - VIDEO_VS_CTL_UNDEFINED = 0x00, - VIDEO_VS_CTL_PROBE, - VIDEO_VS_CTL_COMMIT, - VIDEO_VS_CTL_STILL_PROBE, - VIDEO_VS_CTL_STILL_COMMIT, - VIDEO_VS_CTL_STILL_IMAGE_TRIGGER, - VIDEO_VS_CTL_STREAM_ERROR_CODE, - VIDEO_VS_CTL_GENERATE_KEY_FRAME, - VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT, - VIDEO_VS_CTL_SYNCH_DELAY_CONTROL, -} video_interface_streaming_selector_t; - -/* B. Terminal Types */ -typedef enum { - // Terminal - VIDEO_TT_VENDOR_SPECIFIC = 0x0100, - VIDEO_TT_STREAMING = 0x0101, - - // Input - VIDEO_ITT_VENDOR_SPECIFIC = 0x0200, - VIDEO_ITT_CAMERA = 0x0201, - VIDEO_ITT_MEDIA_TRANSPORT_INPUT = 0x0202, - - // Output - VIDEO_OTT_VENDOR_SPECIFIC = 0x0300, - VIDEO_OTT_DISPLAY = 0x0301, - VIDEO_OTT_MEDIA_TRANSPORT_OUTPUT = 0x0302, - - // External - VIDEO_ETT_VENDOR_SPEIFIC = 0x0400, - VIDEO_ETT_COMPOSITE_CONNECTOR = 0x0401, - VIDEO_ETT_SVIDEO_CONNECTOR = 0x0402, - VIDEO_ETT_COMPONENT_CONNECTOR = 0x0403, -} video_terminal_type_t; - -//--------------------------------------------------------------------+ -// Descriptors -//--------------------------------------------------------------------+ - -/* 2.3.4.2 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint16_t bcdUVC; - uint16_t wTotalLength; - uint32_t dwClockFrequency; - uint8_t bInCollection; - uint8_t baInterfaceNr[]; -} tusb_desc_cs_video_ctl_itf_hdr_t; - -/* 2.4.3.3 */ -typedef struct TU_ATTR_PACKED { - uint8_t bHeaderLength; - union { - uint8_t bmHeaderInfo; - struct { - uint8_t FrameID: 1; - uint8_t EndOfFrame: 1; - uint8_t PresentationTime: 1; - uint8_t SourceClockReference: 1; - uint8_t PayloadSpecific: 1; - uint8_t StillImage: 1; - uint8_t Error: 1; - uint8_t EndOfHeader: 1; - }; - }; -} tusb_video_payload_header_t; - -/* 3.9.2.1 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; - uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_in_hdr_t; - -/* 3.9.2.2 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bTerminalLink; - uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_out_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - union { - struct { - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; - uint8_t bControlSize; - uint8_t bmaControls[]; - } input; - struct { - uint8_t bEndpointAddress; - uint8_t bTerminalLink; - uint8_t bControlSize; - uint8_t bmaControls[]; - } output; - }; -} tusb_desc_cs_video_stm_itf_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - uint8_t guidFormat[16]; - uint8_t bBitsPerPixel; - uint8_t bDefaultFrameIndex; - uint8_t bAspectRatioX; - uint8_t bAspectRatioY; - uint8_t bmInterlaceFlags; - uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_uncompressed_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - uint32_t dwMinBitRate; - uint32_t dwMaxBitRate; - uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ - uint32_t dwDefaultFrameInterval; - uint8_t bFrameIntervalType; - uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_uncompressed_t; - -//--------------------------------------------------------------------+ -// Requests -//--------------------------------------------------------------------+ - -/* 4.3.1.1 */ -typedef struct TU_ATTR_PACKED { - union { - uint8_t bmHint; - struct TU_ATTR_PACKED { - uint16_t dwFrameInterval: 1; - uint16_t wKeyFrameRatel : 1; - uint16_t wPFrameRate : 1; - uint16_t wCompQuality : 1; - uint16_t wCompWindowSize: 1; - uint16_t : 0; - } Hint; - }; - uint8_t bFormatIndex; - uint8_t bFrameIndex; - uint32_t dwFrameInterval; - uint16_t wKeyFrameRate; - uint16_t wPFrameRate; - uint16_t wCompQuality; - uint16_t wCompWindowSize; - uint16_t wDelay; - uint32_t dwMaxVideoFrameSize; - uint32_t dwMaxPayloadTransferSize; - uint32_t dwClockFrequency; - union { - uint8_t bmFramingInfo; - struct TU_ATTR_PACKED { - uint8_t FrameID : 1; - uint8_t EndOfFrame: 1; - uint8_t EndOfSlice: 1; - uint8_t : 0; - } FramingInfo; - }; - uint8_t bPreferedVersion; - uint8_t bMinVersion; - uint8_t bMaxVersion; - uint8_t bUsage; - uint8_t bBitDepthLuma; - uint8_t bmSettings; - uint8_t bMaxNumberOfRefFramesPlus1; - uint16_t bmRateControlModes; - uint64_t bmLayoutPerStream; -} video_probe_and_commit_control_t; - -TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not correct"); - -#define TUD_VIDEO_DESC_IAD_LEN 8 -#define TUD_VIDEO_DESC_STD_VC_LEN 9 -#define TUD_VIDEO_DESC_CS_VC_LEN 12 -#define TUD_VIDEO_DESC_INPUT_TERM_LEN 8 -#define TUD_VIDEO_DESC_OUTPUT_TERM_LEN 9 -#define TUD_VIDEO_DESC_CAMERA_TERM_LEN 18 -#define TUD_VIDEO_DESC_STD_VS_LEN 9 -#define TUD_VIDEO_DESC_CS_VS_IN_LEN 13 -#define TUD_VIDEO_DESC_CS_VS_OUT_LEN 9 -#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN 27 -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN 38 -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN 26 -#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN 6 - -/* 2.2 compression formats */ -#define TUD_VIDEO_GUID_YUY2 0x59,0x55,0x59,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_NV12 0x4E,0x56,0x31,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_M420 0x4D,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_I420 0x49,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 - -#define TUD_VIDEO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_VIDEO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, \ - _firstitfs, _nitfs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_INTERFACE_COLLECTION, \ - VIDEO_ITF_PROTOCOL_UNDEFINED, _stridx - -#define TUD_VIDEO_DESC_STD_VC(_itfnum, _nEPs, _stridx) \ - TUD_VIDEO_DESC_STD_VC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, \ - _nEPs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_CONTROL, VIDEO_ITF_PROTOCOL_15, _stridx - -/* 3.7.2 */ -#define TUD_VIDEO_DESC_CS_VC(_bcdUVC, _totallen, _clkfreq, ...) \ - TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_HEADER, \ - U16_TO_U8S_LE(_bcdUVC), U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__))), \ - U32_TO_U8S_LE(_clkfreq), TU_ARGS_NUM(__VA_ARGS__), __VA_ARGS__ - -/* 3.7.2.1 */ -#define TUD_VIDEO_DESC_INPUT_TERM(_tid, _tt, _at, _stridx) \ - TUD_VIDEO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(_tt), _at, _stridx - -/* 3.7.2.2 */ -#define TUD_VIDEO_DESC_OUTPUT_TERM(_tid, _tt, _at, _srcid, _stridx) \ - TUD_VIDEO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(_tt), _at, _srcid, _stridx - -/* 3.7.2.3 */ -#define TUD_VIDEO_DESC_CAMERA_TERM(_tid, _at, _stridx, _focal_min, _focal_max, _focal, _ctls) \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(VIDEO_ITT_CAMERA), _at, _stridx, \ - U16_TO_U8S_LE(_focal_min), U16_TO_U8S_LE(_focal_max), U16_TO_U8S_LE(_focal), 3, \ - TU_U32_BYTE0(_ctls), TU_U32_BYTE1(_ctls), TU_U32_BYTE2(_ctls) - -/* 3.9.1 */ -#define TUD_VIDEO_DESC_STD_VS(_itfnum, _alt, _epn, _stridx) \ - TUD_VIDEO_DESC_STD_VS_LEN, TUSB_DESC_INTERFACE, _itfnum, _alt, \ - _epn, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_STREAMING, VIDEO_ITF_PROTOCOL_15, _stridx - -/* 3.9.2.1 */ -#define TUD_VIDEO_DESC_CS_VS_INPUT(_numfmt, _totallen, _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, ...) \ - TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ - VIDEO_CS_ITF_VS_INPUT_HEADER, _numfmt, \ - U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ - _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* 3.9.2.2 */ -#define TUD_VIDEO_DESC_CS_VS_OUTPUT(_numfmt, _totallen, _ep, _inf, _termlnk, ...) \ - TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ - VIDEO_CS_ITF_VS_OUTPUT_HEADER, _numfmt, \ - U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ - _ep, _inf, _termlnk, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* Uncompressed 3.1.1 */ -#define TUD_VIDEO_GUID(_g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15) _g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15 - -#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfrmdesc, \ - _guid, _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp) \ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, \ - _fmtidx, _numfrmdesc, TUD_VIDEO_GUID(_guid), \ - _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp - -/* Uncompressed 3.1.2 Table 3-3 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, _minfrminterval, _maxfrminterval, _frmintervalstep) \ - TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), 0, \ - U32_TO_U8S_LE(_minfrminterval), U32_TO_U8S_LE(_maxfrminterval), U32_TO_U8S_LE(_frmintervalstep) - -/* Uncompressed 3.1.2 Table 3-4 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \ - TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* 3.9.2.6 */ -#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(_color, _trns, _mat) \ - TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_COLORFORMAT, \ - _color, _trns, _mat - -/* 3.10.1.1 */ -#define TUD_VIDEO_DESC_EP_ISO(_ep, _epsize, _ep_interval) \ - 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS,\ - U16_TO_U8S_LE(_epsize), _ep_interval - -/* 3.10.1.2 */ -#define TUD_VIDEO_DESC_EP_BULK(_ep, _epsize, _ep_interval) \ - 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), _ep_interval - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c deleted file mode 100644 index eeb068197..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c +++ /dev/null @@ -1,1149 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Koji KITAYAMA - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VIDEO && CFG_TUD_VIDEO_STREAMING) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "video_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct { - tusb_desc_interface_t std; - tusb_desc_cs_video_ctl_itf_hdr_t ctl; -} tusb_desc_vc_itf_t; - -typedef struct { - tusb_desc_interface_t std; - tusb_desc_cs_video_stm_itf_hdr_t stm; -} tusb_desc_vs_itf_t; - -typedef union { - tusb_desc_cs_video_ctl_itf_hdr_t ctl; - tusb_desc_cs_video_stm_itf_hdr_t stm; -} tusb_desc_video_itf_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bEntityId; -} tusb_desc_cs_video_entity_itf_t; - -/* video streaming interface */ -typedef struct TU_ATTR_PACKED { - uint8_t index_vc; /* index of bound video control interface */ - uint8_t index_vs; /* index from the video control interface */ - struct { - uint16_t beg; /* Offset of the begging of video streaming interface descriptor */ - uint16_t end; /* Offset of the end of video streaming interface descriptor */ - uint16_t cur; /* Offset of the current settings */ - uint16_t ep[2]; /* Offset of endpoint descriptors. 0: streaming, 1: still capture */ - } desc; - uint8_t *buffer; /* frame buffer. assume linear buffer. no support for stride access */ - uint32_t bufsize; /* frame buffer size */ - uint32_t offset; /* offset for the next payload transfer */ - uint32_t max_payload_transfer_size; - uint8_t error_code;/* error code */ - /*------------- From this point, data is not cleared by bus reset -------------*/ - CFG_TUSB_MEM_ALIGN uint8_t ep_buf[CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE]; /* EP transfer buffer for streaming */ -} videod_streaming_interface_t; - -/* video control interface */ -typedef struct TU_ATTR_PACKED { - void const *beg; /* The head of the first video control interface descriptor */ - uint16_t len; /* Byte length of the descriptors */ - uint16_t cur; /* offset for current video control interface */ - uint8_t stm[CFG_TUD_VIDEO_STREAMING]; /* Indices of streaming interface */ - uint8_t error_code; /* error code */ - uint8_t power_mode; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - // CFG_TUSB_MEM_ALIGN uint8_t ctl_buf[64]; /* EP transfer buffer for interrupt transfer */ - -} videod_interface_t; - -#define ITF_STM_MEM_RESET_SIZE offsetof(videod_streaming_interface_t, ep_buf) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static videod_interface_t _videod_itf[CFG_TUD_VIDEO]; -CFG_TUSB_MEM_SECTION static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING]; - -static uint8_t const _cap_get = 0x1u; /* support for GET */ -static uint8_t const _cap_get_set = 0x3u; /* support for GET and SET */ - -/** Get interface number from the interface descriptor - * - * @param[in] desc interface descriptor - * - * @return bInterfaceNumber */ -static inline uint8_t _desc_itfnum(void const *desc) -{ - return ((uint8_t const*)desc)[2]; -} - -/** Get endpoint address from the endpoint descriptor - * - * @param[in] desc endpoint descriptor - * - * @return bEndpointAddress */ -static inline uint8_t _desc_ep_addr(void const *desc) -{ - return ((uint8_t const*)desc)[2]; -} - -/** Get instance of streaming interface - * - * @param[in] ctl_idx instance number of video control - * @param[in] stm_idx index number of streaming interface - * - * @return instance */ -static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - videod_interface_t *ctl = &_videod_itf[ctl_idx]; - if (!ctl->beg) return NULL; - videod_streaming_interface_t *stm = &_videod_streaming_itf[ctl->stm[stm_idx]]; - if (!stm->desc.beg) return NULL; - return stm; -} - -static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self) -{ - return (tusb_desc_vc_itf_t const *)(self->beg + self->cur); -} - -static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self) -{ - if (!self->desc.cur) return NULL; - void const *desc = _videod_itf[self->index_vc].beg; - return (tusb_desc_vs_itf_t const*)(desc + self->desc.cur); -} - -/** Find the first descriptor of a given type - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] desc_type The target descriptor type. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc(void const *beg, void const *end, uint_fast8_t desc_type) -{ - void const *cur = beg; - while ((cur < end) && (desc_type != tu_desc_type(cur))) { - cur = tu_desc_next(cur); - } - return cur; -} - -/** Find the first descriptor specified by the arguments - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] desc_type The target descriptor type - * @param[in] element_0 The target element following the desc_type - * @param[in] element_1 The target element following the element_0 - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc_3(void const *beg, void const *end, - uint_fast8_t desc_type, - uint_fast8_t element_0, - uint_fast8_t element_1) -{ - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, desc_type)) { - uint8_t const *p = (uint8_t const *)cur; - if ((p[2] == element_0) && (p[3] == element_1)) { - return cur; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Return the next interface descriptor which has another interface number. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _next_desc_itf(void const *beg, void const *end) -{ - void const *cur = beg; - uint_fast8_t itfnum = ((tusb_desc_interface_t const*)cur)->bInterfaceNumber; - while ((cur < end) && - (itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) { - cur = _find_desc(tu_desc_next(cur), end, TUSB_DESC_INTERFACE); - } - return cur; -} - -/** Find the first interface descriptor with the specified interface number and alternate setting number. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] itfnum The target interface number. - * @param[in] altnum The target alternate setting number. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static inline void const* _find_desc_itf(void const *beg, void const *end, uint_fast8_t itfnum, uint_fast8_t altnum) -{ - return _find_desc_3(beg, end, TUSB_DESC_INTERFACE, itfnum, altnum); -} - -/** Find the first endpoint descriptor belonging to the current interface descriptor. - * - * The search range is from `beg` to `end` or the next interface descriptor. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * - * @return The pointer for endpoint descriptor. - * @retval end did not found endpoint descriptor */ -static void const* _find_desc_ep(void const *beg, void const *end) -{ - for (void const *cur = beg; cur < end; cur = tu_desc_next(cur)) { - uint_fast8_t desc_type = tu_desc_type(cur); - if (TUSB_DESC_ENDPOINT == desc_type) return cur; - if (TUSB_DESC_INTERFACE == desc_type) break; - } - return end; -} - -/** Find the first entity descriptor with the entity ID - * specified by the argument belonging to the current video control descriptor. - * - * @param[in] desc The video control interface descriptor. - * @param[in] entityid The target entity id. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc_entity(void const *desc, uint_fast8_t entityid) -{ - tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const*)desc; - void const *beg = vc; - void const *end = beg + vc->std.bLength + vc->ctl.wTotalLength; - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { - tusb_desc_cs_video_entity_itf_t const *itf = (tusb_desc_cs_video_entity_itf_t const *)cur; - if ((VIDEO_CS_ITF_VC_INPUT_TERMINAL <= itf->bDescriptorSubtype - && itf->bDescriptorSubtype < VIDEO_CS_ITF_VC_MAX) - && itf->bEntityId == entityid) { - return itf; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Return the end of the video streaming descriptor. */ -static inline void const* _end_of_streaming_descriptor(void const *desc) -{ - tusb_desc_vs_itf_t const *vs = (tusb_desc_vs_itf_t const *)desc; - return desc + vs->std.bLength + vs->stm.wTotalLength; -} - -/** Find the first format descriptor with the specified format number. */ -static inline tusb_desc_cs_video_fmt_uncompressed_t const *_find_desc_format(void const *beg, void const *end, uint_fast8_t fmtnum) -{ - return (tusb_desc_cs_video_fmt_uncompressed_t const*) - _find_desc_3(beg, end, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, fmtnum); -} - -/** Find the first frame descriptor with the specified format number. */ -static inline tusb_desc_cs_video_frm_uncompressed_t const *_find_desc_frame(void const *beg, void const *end, uint_fast8_t frmnum) -{ - return (tusb_desc_cs_video_frm_uncompressed_t const*) - _find_desc_3(beg, end, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, frmnum); -} - -/** Set uniquely determined values to variables that have not been set - * - * @param[in,out] param Target */ -static bool _update_streaming_parameters(videod_streaming_interface_t const *stm, - video_probe_and_commit_control_t *param) -{ - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - uint_fast8_t fmtnum = param->bFormatIndex; - TU_ASSERT(fmtnum <= vs->stm.bNumFormats); - if (!fmtnum) { - if (1 < vs->stm.bNumFormats) return true; /* Need to negotiate all variables. */ - fmtnum = 1; - param->bFormatIndex = 1; - } - - /* Set the parameters determined by the format */ - param->wKeyFrameRate = 1; - param->wPFrameRate = 0; - param->wCompQuality = 1; /* 1 to 10000 */ - param->wCompWindowSize = 1; /* GOP size? */ - param->wDelay = 0; /* milliseconds */ - param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ - param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ - param->bPreferedVersion = 1; - param->bMinVersion = 1; - param->bMaxVersion = 1; - param->bUsage = 0; - param->bBitDepthLuma = 8; - - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - TU_ASSERT(fmt != end); - uint_fast8_t frmnum = param->bFrameIndex; - TU_ASSERT(frmnum <= fmt->bNumFrameDescriptors); - if (!frmnum) { - if (1 < fmt->bNumFrameDescriptors) return true; - frmnum = 1; - param->bFrameIndex = 1; - } - tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - TU_ASSERT(frm != end); - - /* Set the parameters determined by the frame */ - uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - if (!frame_size) { - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->bBitsPerPixel / 8; - param->dwMaxVideoFrameSize = frame_size; - } - - uint_fast32_t interval = param->dwFrameInterval; - if (!interval) { - if ((1 < frm->bFrameIntervalType) || - ((0 == frm->bFrameIntervalType) && (frm->dwFrameInterval[1] != frm->dwFrameInterval[0]))) { - return true; - } - interval = frm->dwFrameInterval[0]; - param->dwFrameInterval = interval; - } - uint_fast32_t interval_ms = interval / 10000; - TU_ASSERT(interval_ms); - uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; - param->dwMaxPayloadTransferSize = payload_size; - return true; -} - -/** Set the minimum, maximum, default values or resolutions to variables which need to negotiate with the host - * - * @param[in] request GET_MAX, GET_MIN, GET_RES or GET_DEF - * @param[in,out] param Target - */ -static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *stm, uint_fast8_t request, - video_probe_and_commit_control_t *param) -{ - uint_fast8_t const fmtnum = param->bFormatIndex; - if (!fmtnum) { - switch (request) { - case VIDEO_REQUEST_GET_MAX: - param->bFormatIndex = _get_desc_vs(stm)->stm.bNumFormats; - break; - case VIDEO_REQUEST_GET_MIN: - case VIDEO_REQUEST_GET_DEF: - param->bFormatIndex = 1; - break; - default: return false; - } - /* Set the parameters determined by the format */ - param->wKeyFrameRate = 1; - param->wPFrameRate = 0; - param->wCompQuality = 1; /* 1 to 10000 */ - param->wCompWindowSize = 1; /* GOP size? */ - param->wDelay = 0; /* milliseconds */ - param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ - param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ - param->bPreferedVersion = 1; - param->bMinVersion = 1; - param->bMaxVersion = 1; - param->bUsage = 0; - param->bBitDepthLuma = 8; - return true; - } - - uint_fast8_t frmnum = param->bFrameIndex; - if (!frmnum) { - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - switch (request) { - case VIDEO_REQUEST_GET_MAX: - frmnum = fmt->bNumFrameDescriptors; - break; - case VIDEO_REQUEST_GET_MIN: - frmnum = 1; - break; - case VIDEO_REQUEST_GET_DEF: - frmnum = fmt->bDefaultFrameIndex; - break; - default: return false; - } - param->bFrameIndex = frmnum; - /* Set the parameters determined by the frame */ - tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - param->dwMaxVideoFrameSize = frm->wWidth * frm->wHeight * fmt->bBitsPerPixel / 8; - return true; - } - - if (!param->dwFrameInterval) { - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - - uint_fast32_t interval, interval_ms; - switch (request) { - case VIDEO_REQUEST_GET_MAX: - { - uint_fast32_t min_interval, max_interval; - uint_fast8_t num_intervals = frm->bFrameIntervalType; - max_interval = num_intervals ? frm->dwFrameInterval[num_intervals - 1]: frm->dwFrameInterval[1]; - min_interval = frm->dwFrameInterval[0]; - interval = max_interval; - interval_ms = min_interval / 10000; - } - break; - case VIDEO_REQUEST_GET_MIN: - { - uint_fast32_t min_interval, max_interval; - uint_fast8_t num_intervals = frm->bFrameIntervalType; - max_interval = num_intervals ? frm->dwFrameInterval[num_intervals - 1]: frm->dwFrameInterval[1]; - min_interval = frm->dwFrameInterval[0]; - interval = min_interval; - interval_ms = max_interval / 10000; - } - break; - case VIDEO_REQUEST_GET_DEF: - interval = frm->dwDefaultFrameInterval; - interval_ms = interval / 10000; - break; - case VIDEO_REQUEST_GET_RES: - { - uint_fast8_t num_intervals = frm->bFrameIntervalType; - if (num_intervals) { - interval = 0; - } else { - interval = frm->dwFrameInterval[2]; - interval_ms = interval / 10000; - } - } - break; - default: return false; - } - param->dwFrameInterval = interval; - if (!interval) { - param->dwMaxPayloadTransferSize = 0; - } else { - uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - if (!interval_ms) { - param->dwMaxPayloadTransferSize = frame_size + 2; - } else { - param->dwMaxPayloadTransferSize = (frame_size + interval_ms - 1) / interval_ms + 2; - } - } - return true; - } - return true; -} - -/** Close current video control interface. - * - * @param[in,out] self Video control interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self) -{ - tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); - /* The next descriptor after the class-specific VC interface header descriptor. */ - void const *cur = (void const*)vc + vc->std.bLength + vc->ctl.bLength; - /* The end of the video control interface descriptor. */ - void const *end = (void const*)vc + vc->std.bLength + vc->ctl.wTotalLength; - if (vc->std.bNumEndpoints) { - /* Find the notification endpoint descriptor. */ - cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); - TU_ASSERT(cur < end); - tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; - usbd_edpt_close(rhport, notif->bEndpointAddress); - } - self->cur = 0; - return true; -} - -/** Set the alternate setting to own video control interface. - * - * @param[in,out] self Video control interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t altnum) -{ - TU_LOG2(" open VC %d\n", altnum); - void const *beg = self->beg; - void const *end = beg + self->len; - /* The first descriptor is a video control interface descriptor. */ - void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); - TU_LOG2(" cur %d\n", cur - beg); - TU_VERIFY(cur < end); - - tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const *)cur; - TU_LOG2(" bInCollection %d\n", vc->ctl.bInCollection); - /* Support for up to 2 streaming interfaces only. */ - TU_ASSERT(vc->ctl.bInCollection <= CFG_TUD_VIDEO_STREAMING); - - /* Update to point the end of the video control interface descriptor. */ - end = cur + vc->std.bLength + vc->ctl.wTotalLength; - /* Advance to the next descriptor after the class-specific VC interface header descriptor. */ - cur += vc->std.bLength + vc->ctl.bLength; - TU_LOG2(" bNumEndpoints %d\n", vc->std.bNumEndpoints); - /* Open the notification endpoint if it exist. */ - if (vc->std.bNumEndpoints) { - /* Support for 1 endpoint only. */ - TU_VERIFY(1 == vc->std.bNumEndpoints); - /* Find the notification endpoint descriptor. */ - cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); - TU_VERIFY(cur < end); - tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; - /* Open the notification endpoint */ - TU_ASSERT(usbd_edpt_open(rhport, notif)); - } - self->cur = (void const*)vc - beg; - return true; -} - -/** Set the alternate setting to own video streaming interface. - * - * @param[in,out] stm Streaming interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint_fast8_t altnum) -{ - uint_fast8_t i; - TU_LOG2(" reopen VS %d\n", altnum); - void const *desc = _videod_itf[stm->index_vc].beg; - - /* Close endpoints of previous settings. */ - for (i = 0; i < TU_ARRAY_SIZE(stm->desc.ep); ++i) { - uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) break; - uint_fast8_t ep_adr = _desc_ep_addr(desc + ofs_ep); - usbd_edpt_close(rhport, ep_adr); - stm->desc.ep[i] = 0; - TU_LOG2(" close EP%02x\n", ep_adr); - } - /* clear transfer management information */ - stm->buffer = NULL; - stm->bufsize = 0; - stm->offset = 0; - - /* Find a alternate interface */ - void const *beg = desc + stm->desc.beg; - void const *end = desc + stm->desc.end; - void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); - TU_VERIFY(cur < end); - uint_fast8_t numeps = ((tusb_desc_interface_t const *)cur)->bNumEndpoints; - TU_ASSERT(numeps <= TU_ARRAY_SIZE(stm->desc.ep)); - stm->desc.cur = cur - desc; /* Save the offset of the new settings */ - if (!altnum) { - /* initialize streaming settings */ - stm->max_payload_transfer_size = 0; - video_probe_and_commit_control_t *param = - (video_probe_and_commit_control_t *)&stm->ep_buf; - tu_memclr(param, sizeof(*param)); - return _update_streaming_parameters(stm, param); - } - /* Open endpoints of the new settings. */ - for (i = 0, cur = tu_desc_next(cur); i < numeps; ++i, cur = tu_desc_next(cur)) { - cur = _find_desc_ep(cur, end); - TU_ASSERT(cur < end); - tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)cur; - if (!stm->max_payload_transfer_size) { - video_probe_and_commit_control_t const *param = (video_probe_and_commit_control_t const*)&stm->ep_buf; - uint_fast32_t max_size = param->dwMaxPayloadTransferSize; - if ((TUSB_XFER_ISOCHRONOUS == ep->bmAttributes.xfer) && - (tu_edpt_packet_size(ep) < max_size)) - { - /* FS must be less than or equal to max packet size */ - return false; - } - /* Set the negotiated value */ - stm->max_payload_transfer_size = max_size; - } - TU_ASSERT(usbd_edpt_open(rhport, ep)); - stm->desc.ep[i] = cur - desc; - TU_LOG2(" open EP%02x\n", _desc_ep_addr(cur)); - } - /* initialize payload header */ - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->bHeaderLength = sizeof(*hdr); - hdr->bmHeaderInfo = 0; - - return true; -} - -/** Prepare the next packet payload. */ -static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm) -{ - uint_fast16_t remaining = stm->bufsize - stm->offset; - uint_fast16_t hdr_len = stm->ep_buf[0]; - uint_fast16_t pkt_len = stm->max_payload_transfer_size; - if (hdr_len + remaining < pkt_len) { - pkt_len = hdr_len + remaining; - } - uint_fast16_t data_len = pkt_len - hdr_len; - memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len); - stm->offset += data_len; - remaining -= data_len; - if (!remaining) { - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->EndOfFrame = 1; - } - return hdr_len + data_len; -} - -/** Handle a standard request to the video control interface. */ -static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - switch (request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - tusb_desc_vc_itf_t const *vc = _get_desc_vc(&_videod_itf[ctl_idx]); - TU_VERIFY(vc, VIDEO_ERROR_UNKNOWN); - - uint8_t alt_num = vc->std.bAlternateSetting; - - TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case TUSB_REQ_SET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(0 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(_close_vc_itf(rhport, &_videod_itf[ctl_idx]), VIDEO_ERROR_UNKNOWN); - TU_VERIFY(_open_vc_itf(rhport, &_videod_itf[ctl_idx], request->wValue), VIDEO_ERROR_UNKNOWN); - tud_control_status(rhport, request); - } - return VIDEO_ERROR_NONE; - - default: /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - videod_interface_t *self = &_videod_itf[ctl_idx]; - - /* 4.2.1 Interface Control Request */ - switch (TU_U16_HIGH(request->wValue)) { - case VIDEO_VC_CTL_VIDEO_POWER_MODE: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_ACK) { - if (tud_video_power_mode_cb) return tud_video_power_mode_cb(ctl_idx, self->power_mode); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VC_CTL_REQUEST_ERROR_CODE: - switch (request->bRequest) { - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - default: break; - } - - /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; -} - -static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - uint_fast8_t entity_id; - switch (request->bmRequestType_bit.type) { - case TUSB_REQ_TYPE_STANDARD: - return handle_video_ctl_std_req(rhport, stage, request, ctl_idx); - - case TUSB_REQ_TYPE_CLASS: - entity_id = TU_U16_HIGH(request->wIndex); - if (!entity_id) { - return handle_video_ctl_cs_req(rhport, stage, request, ctl_idx); - } else { - TU_VERIFY(_find_desc_entity(_get_desc_vc(&_videod_itf[ctl_idx]), entity_id), VIDEO_ERROR_INVALID_REQUEST); - return VIDEO_ERROR_NONE; - } - - default: - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; - switch (request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - tusb_desc_vs_itf_t const *vs = _get_desc_vs(self); - TU_VERIFY(vs, VIDEO_ERROR_UNKNOWN); - uint8_t alt_num = vs->std.bAlternateSetting; - - TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case TUSB_REQ_SET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(_open_vs_itf(rhport, self, request->wValue), VIDEO_ERROR_UNKNOWN); - tud_control_status(rhport, request); - } - return VIDEO_ERROR_NONE; - - default: /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - (void)rhport; - videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; - - /* 4.2.1 Interface Control Request */ - switch (TU_U16_HIGH(request->wValue)) { - case VIDEO_VS_CTL_STREAM_ERROR_CODE: - switch (request->bRequest) { - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - /* TODO */ - TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_PROBE: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(sizeof(video_probe_and_commit_control_t) == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), - VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_ACK) { - TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), - VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_MIN: - case VIDEO_REQUEST_GET_MAX: - case VIDEO_REQUEST_GET_RES: - case VIDEO_REQUEST_GET_DEF: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - video_probe_and_commit_control_t tmp; - tmp = *(video_probe_and_commit_control_t*)&self->ep_buf; - TU_VERIFY(_negotiate_streaming_parameters(self, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_LEN: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); - uint16_t len = sizeof(video_probe_and_commit_control_t); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_COMMIT: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(sizeof(video_probe_and_commit_control_t) == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_ACK) { - TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - if (tud_video_commit_cb) { - return tud_video_commit_cb(self->index_vc, self->index_vs, (video_probe_and_commit_control_t*)self->ep_buf); - } - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_LEN: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); - uint16_t len = sizeof(video_probe_and_commit_control_t); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_STILL_PROBE: - case VIDEO_VS_CTL_STILL_COMMIT: - case VIDEO_VS_CTL_STILL_IMAGE_TRIGGER: - case VIDEO_VS_CTL_GENERATE_KEY_FRAME: - case VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT: - case VIDEO_VS_CTL_SYNCH_DELAY_CONTROL: - /* TODO */ - break; - - default: break; - } - - /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; -} - -static int handle_video_stm_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - switch (request->bmRequestType_bit.type) { - case TUSB_REQ_TYPE_STANDARD: - return handle_video_stm_std_req(rhport, stage, request, stm_idx); - - case TUSB_REQ_TYPE_CLASS: - if (TU_U16_HIGH(request->wIndex)) return VIDEO_ERROR_INVALID_REQUEST; - return handle_video_stm_cs_req(rhport, stage, request, stm_idx); - - default: return VIDEO_ERROR_INVALID_REQUEST; - } - return VIDEO_ERROR_UNKNOWN; -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ - -bool tud_video_n_connected(uint_fast8_t ctl_idx) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, 0); - if (stm) return true; - return false; -} - -bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0]) return false; - return true; -} - -bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - if (!buffer || !bufsize) return false; - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0] || stm->buffer) return false; - - /* Find EP address */ - void const *desc = _videod_itf[stm->index_vc].beg; - uint_fast8_t ep_addr = 0; - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) continue; - ep_addr = _desc_ep_addr(desc + ofs_ep); - break; - } - if (!ep_addr) return false; - - TU_VERIFY( usbd_edpt_claim(0, ep_addr)); - /* update the packet header */ - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->FrameID ^= 1; - hdr->EndOfFrame = 0; - /* update the packet data */ - stm->buffer = (uint8_t*)buffer; - stm->bufsize = bufsize; - uint_fast16_t pkt_len = _prepare_in_payload(stm); - TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm->ep_buf, pkt_len), 0); - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void videod_init(void) -{ - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { - videod_interface_t* ctl = &_videod_itf[i]; - tu_memclr(ctl, sizeof(*ctl)); - } - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; - tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); - } -} - -void videod_reset(uint8_t rhport) -{ - (void) rhport; - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { - videod_interface_t* ctl = &_videod_itf[i]; - tu_memclr(ctl, sizeof(*ctl)); - } - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; - tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); - } -} - -uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - TU_VERIFY((TUSB_CLASS_VIDEO == itf_desc->bInterfaceClass) && - (VIDEO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass) && - (VIDEO_ITF_PROTOCOL_15 == itf_desc->bInterfaceProtocol), 0); - - /* Find available interface */ - videod_interface_t *self = NULL; - uint_fast8_t ctl_idx; - for (ctl_idx = 0; ctl_idx < CFG_TUD_VIDEO; ++ctl_idx) { - if (_videod_itf[ctl_idx].beg) continue; - self = &_videod_itf[ctl_idx]; - break; - } - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO, 0); - - void const *end = (void const*)itf_desc + max_len; - self->beg = itf_desc; - self->len = max_len; - /*------------- Video Control Interface -------------*/ - TU_VERIFY(_open_vc_itf(rhport, self, 0), 0); - tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); - uint_fast8_t bInCollection = vc->ctl.bInCollection; - /* Find the end of the video interface descriptor */ - void const *cur = _next_desc_itf(itf_desc, end); - for (uint_fast8_t stm_idx = 0; stm_idx < bInCollection; ++stm_idx) { - videod_streaming_interface_t *stm = NULL; - /* find free streaming interface handle */ - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - if (_videod_streaming_itf[i].desc.beg) continue; - stm = &_videod_streaming_itf[i]; - self->stm[stm_idx] = i; - break; - } - TU_ASSERT(stm, 0); - stm->index_vc = ctl_idx; - stm->index_vs = stm_idx; - stm->desc.beg = (uintptr_t)cur - (uintptr_t)itf_desc; - cur = _next_desc_itf(cur, end); - stm->desc.end = (uintptr_t)cur - (uintptr_t)itf_desc; - } - self->len = (uintptr_t)cur - (uintptr_t)itf_desc; - return (uintptr_t)cur - (uintptr_t)itf_desc; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - int err; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - uint_fast8_t itfnum = tu_u16_low(request->wIndex); - - /* Identify which control interface to use */ - uint_fast8_t itf; - for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) { - void const *desc = _videod_itf[itf].beg; - if (!desc) continue; - if (itfnum == _desc_itfnum(desc)) break; - } - - if (itf < CFG_TUD_VIDEO) { - err = handle_video_ctl_req(rhport, stage, request, itf); - _videod_itf[itf].error_code = (uint8_t)err; - if (err) return false; - return true; - } - - /* Identify which streaming interface to use */ - for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; - if (!stm->desc.beg) continue; - void const *desc = _videod_itf[stm->index_vc].beg; - if (itfnum == _desc_itfnum(desc + stm->desc.beg)) break; - } - - if (itf < CFG_TUD_VIDEO_STREAMING) { - err = handle_video_stm_req(rhport, stage, request, itf); - _videod_streaming_itf[itf].error_code = (uint8_t)err; - if (err) return false; - return true; - } - return false; -} - -bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; (void)xferred_bytes; - - /* find streaming handle */ - uint_fast8_t itf; - videod_interface_t *ctl; - videod_streaming_interface_t *stm; - for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { - stm = &_videod_streaming_itf[itf]; - uint_fast16_t const ep_ofs = stm->desc.ep[0]; - if (!ep_ofs) continue; - ctl = &_videod_itf[stm->index_vc]; - void const *desc = ctl->beg; - if (ep_addr == _desc_ep_addr(desc + ep_ofs)) break; - } - - TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING); - if (stm->offset < stm->bufsize) { - /* Claim the endpoint */ - TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0); - uint_fast16_t pkt_len = _prepare_in_payload(stm); - TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, pkt_len), 0); - } else { - stm->buffer = NULL; - stm->bufsize = 0; - stm->offset = 0; - if (tud_video_frame_xfer_complete_cb) { - tud_video_frame_xfer_complete_cb(stm->index_vc, stm->index_vs); - } - } - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h deleted file mode 100644 index ee2fcb9d5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2021 Koji KITAYAMA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_VIDEO_DEVICE_H_ -#define TUSB_VIDEO_DEVICE_H_ - -#include "common/tusb_common.h" -#include "video.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Ports) -// CFG_TUD_VIDEO > 1 -//--------------------------------------------------------------------+ - -/** Return true if streaming - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index */ -bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); - -/** Transfer a frame - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @param[in] buffer Frame buffer. The caller must not use this buffer until the operation is completed. - * @param[in] bufsize Byte size of the frame buffer */ -bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize); - -/*------------- Optional callbacks -------------*/ -/** Invoked when compeletion of a frame transfer - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index */ -TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -/** Invoked when SET_POWER_MODE request received - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod); - -/** Invoked when VS_COMMIT_CONTROL(SET_CUR) request received - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @param[in] parameters Video streaming parameters - * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, - video_probe_and_commit_control_t const *parameters); - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void videod_init (void); -void videod_reset (uint8_t rhport); -uint16_t videod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool videod_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h deleted file mode 100644 index 9b9e2b007..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h +++ /dev/null @@ -1,406 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_COMMON_H_ -#define _TUSB_COMMON_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Macros Helper -//--------------------------------------------------------------------+ -#define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) -#define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) -#define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) - -#define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff)) -#define TU_U16_LOW(_u16) ((uint8_t) ((_u16) & 0x00ff)) -#define U16_TO_U8S_BE(_u16) TU_U16_HIGH(_u16), TU_U16_LOW(_u16) -#define U16_TO_U8S_LE(_u16) TU_U16_LOW(_u16), TU_U16_HIGH(_u16) - -#define TU_U32_BYTE3(_u32) ((uint8_t) ((((uint32_t) _u32) >> 24) & 0x000000ff)) // MSB -#define TU_U32_BYTE2(_u32) ((uint8_t) ((((uint32_t) _u32) >> 16) & 0x000000ff)) -#define TU_U32_BYTE1(_u32) ((uint8_t) ((((uint32_t) _u32) >> 8) & 0x000000ff)) -#define TU_U32_BYTE0(_u32) ((uint8_t) (((uint32_t) _u32) & 0x000000ff)) // LSB - -#define U32_TO_U8S_BE(_u32) TU_U32_BYTE3(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE0(_u32) -#define U32_TO_U8S_LE(_u32) TU_U32_BYTE0(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE3(_u32) - -#define TU_BIT(n) (1UL << (n)) -#define TU_GENMASK(h, l) ( (UINT32_MAX << (l)) & (UINT32_MAX >> (31 - (h))) ) - -//--------------------------------------------------------------------+ -// Includes -//--------------------------------------------------------------------+ - -// Standard Headers -#include -#include -#include -#include -#include - -// Tinyusb Common Headers -#include "tusb_option.h" -#include "tusb_compiler.h" -#include "tusb_verify.h" -#include "tusb_types.h" - -#include "tusb_error.h" // TODO remove -#include "tusb_timeout.h" // TODO remove - -//--------------------------------------------------------------------+ -// Internal Helper used by Host and Device Stack -//--------------------------------------------------------------------+ - -// Check if endpoint descriptor is valid per USB specs -bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); - -// Bind all endpoint of a interface descriptor to class driver -void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); - -// Calculate total length of n interfaces (depending on IAD) -uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); - -//--------------------------------------------------------------------+ -// Internal Inline Functions -//--------------------------------------------------------------------+ - -//------------- Mem -------------// -#define tu_memclr(buffer, size) memset((buffer), 0, (size)) -#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) - -//------------- Bytes -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) -{ - return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0; -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) -{ - return (uint16_t) ((((uint16_t) high) << 8) | low); -} - -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte3(uint32_t ui32) { return TU_U32_BYTE3(ui32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t ui32) { return TU_U32_BYTE2(ui32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t ui32) { return TU_U32_BYTE1(ui32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t ui32) { return TU_U32_BYTE0(ui32); } - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_high16(uint32_t ui32) { return (uint16_t) (ui32 >> 16); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_low16 (uint32_t ui32) { return (uint16_t) (ui32 & 0x0000ffffu); } - -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t ui16) { return TU_U16_HIGH(ui16); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t ui16) { return TU_U16_LOW(ui16); } - -//------------- Bits -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); } -TU_ATTR_ALWAYS_INLINE static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value & TU_BIT(pos)) ? true : false; } - -//------------- Min -------------// -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_min8 (uint8_t x, uint8_t y ) { return (x < y) ? x : y; } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_min32 (uint32_t x, uint32_t y) { return (x < y) ? x : y; } - -//------------- Max -------------// -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_max8 (uint8_t x, uint8_t y ) { return (x > y) ? x : y; } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { return (x > y) ? x : y; } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } - -//------------- Align -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment) -{ - return value & ((uint32_t) ~(alignment-1)); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } - -//------------- Mathematics -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return (v + d -1)/d; } - -/// inclusive range checking TODO remove -TU_ATTR_ALWAYS_INLINE static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) -{ - return (lower <= value) && (value <= upper); -} - -// log2 of a value is its MSB's position -// TODO use clz TODO remove -static inline uint8_t tu_log2(uint32_t value) -{ - uint8_t result = 0; - while (value >>= 1) { result++; } - return result; -} - -//------------- Unaligned Access -------------// -#if TUP_ARCH_STRICT_ALIGN - -// Rely on compiler to generate correct code for unaligned access -typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t; -typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t; - -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) -{ - tu_unaligned_uint32_t const* ua32 = (tu_unaligned_uint32_t const*) mem; - return ua32->val; -} - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) -{ - tu_unaligned_uint32_t* ua32 = (tu_unaligned_uint32_t*) mem; - ua32->val = value; -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) -{ - tu_unaligned_uint16_t const* ua16 = (tu_unaligned_uint16_t const*) mem; - return ua16->val; -} - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) -{ - tu_unaligned_uint16_t* ua16 = (tu_unaligned_uint16_t*) mem; - ua16->val = value; -} - -#elif TUP_MCU_STRICT_ALIGN - -// MCU such as LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM although it is ARM M4. -// We have to manually pick up bytes since tu_unaligned_uint32_t will still generate unaligned code -// NOTE: volatile cast to memory to prevent compiler to optimize and generate unaligned code -// TODO Big Endian may need minor changes -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) -{ - volatile uint8_t const* buf8 = (uint8_t const*) mem; - return tu_u32(buf8[3], buf8[2], buf8[1], buf8[0]); -} - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) -{ - volatile uint8_t* buf8 = (uint8_t*) mem; - buf8[0] = tu_u32_byte0(value); - buf8[1] = tu_u32_byte1(value); - buf8[2] = tu_u32_byte2(value); - buf8[3] = tu_u32_byte3(value); -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) -{ - volatile uint8_t const* buf8 = (uint8_t const*) mem; - return tu_u16(buf8[1], buf8[0]); -} - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) -{ - volatile uint8_t* buf8 = (uint8_t*) mem; - buf8[0] = tu_u16_low(value); - buf8[1] = tu_u16_high(value); -} - - -#else - -// MCU that could access unaligned memory natively -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem) { return *((uint32_t const *) mem); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem) { return *((uint16_t const *) mem); } - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32 (void* mem, uint32_t value ) { *((uint32_t*) mem) = value; } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, uint16_t value ) { *((uint16_t*) mem) = value; } - -#endif - -// To be removed -//------------- Binary constant -------------// -#if defined(__GNUC__) && !defined(__CC_ARM) - -#define TU_BIN8(x) ((uint8_t) (0b##x)) -#define TU_BIN16(b1, b2) ((uint16_t) (0b##b1##b2)) -#define TU_BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4)) - -#else - -// internal macro of B8, B16, B32 -#define _B8__(x) (((x&0x0000000FUL)?1:0) \ - +((x&0x000000F0UL)?2:0) \ - +((x&0x00000F00UL)?4:0) \ - +((x&0x0000F000UL)?8:0) \ - +((x&0x000F0000UL)?16:0) \ - +((x&0x00F00000UL)?32:0) \ - +((x&0x0F000000UL)?64:0) \ - +((x&0xF0000000UL)?128:0)) - -#define TU_BIN8(d) ((uint8_t) _B8__(0x##d##UL)) -#define TU_BIN16(dmsb,dlsb) (((uint16_t)TU_BIN8(dmsb)<<8) + TU_BIN8(dlsb)) -#define TU_BIN32(dmsb,db2,db3,dlsb) \ - (((uint32_t)TU_BIN8(dmsb)<<24) \ - + ((uint32_t)TU_BIN8(db2)<<16) \ - + ((uint32_t)TU_BIN8(db3)<<8) \ - + TU_BIN8(dlsb)) -#endif - -//--------------------------------------------------------------------+ -// Debug Function -//--------------------------------------------------------------------+ - -// CFG_TUSB_DEBUG for debugging -// 0 : no debug -// 1 : print error -// 2 : print warning -// 3 : print info -#if CFG_TUSB_DEBUG - -void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); - -#ifdef CFG_TUSB_DEBUG_PRINTF - extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...); - #define tu_printf CFG_TUSB_DEBUG_PRINTF -#else - #define tu_printf printf -#endif - -static inline -void tu_print_var(uint8_t const* buf, uint32_t bufsize) -{ - for(uint32_t i=0; i= 2 - #define TU_LOG2 TU_LOG1 - #define TU_LOG2_MEM TU_LOG1_MEM - #define TU_LOG2_VAR TU_LOG1_VAR - #define TU_LOG2_INT TU_LOG1_INT - #define TU_LOG2_HEX TU_LOG1_HEX -#endif - -// Log Level 3: Info -#if CFG_TUSB_DEBUG >= 3 - #define TU_LOG3 TU_LOG1 - #define TU_LOG3_MEM TU_LOG1_MEM - #define TU_LOG3_VAR TU_LOG1_VAR - #define TU_LOG3_INT TU_LOG1_INT - #define TU_LOG3_HEX TU_LOG1_HEX -#endif - -typedef struct -{ - uint32_t key; - const char* data; -} tu_lookup_entry_t; - -typedef struct -{ - uint16_t count; - tu_lookup_entry_t const* items; -} tu_lookup_table_t; - -static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) -{ - static char not_found[11]; - - for(uint16_t i=0; icount; i++) - { - if (p_table->items[i].key == key) return p_table->items[i].data; - } - - // not found return the key value in hex - sprintf(not_found, "0x%08lX", (unsigned long) key); - - return not_found; -} - -#endif // CFG_TUSB_DEBUG - -#ifndef TU_LOG -#define TU_LOG(n, ...) -#define TU_LOG_MEM(n, ...) -#define TU_LOG_VAR(n, ...) -#define TU_LOG_INT(n, ...) -#define TU_LOG_HEX(n, ...) -#define TU_LOG_LOCATION() -#define TU_LOG_FAILED() -#endif - -// TODO replace all TU_LOGn with TU_LOG(n) - -#define TU_LOG0(...) -#define TU_LOG0_MEM(...) -#define TU_LOG0_VAR(...) -#define TU_LOG0_INT(...) -#define TU_LOG0_HEX(...) - - -#ifndef TU_LOG1 - #define TU_LOG1(...) - #define TU_LOG1_MEM(...) - #define TU_LOG1_VAR(...) - #define TU_LOG1_INT(...) - #define TU_LOG1_HEX(...) -#endif - -#ifndef TU_LOG2 - #define TU_LOG2(...) - #define TU_LOG2_MEM(...) - #define TU_LOG2_VAR(...) - #define TU_LOG2_INT(...) - #define TU_LOG2_HEX(...) -#endif - -#ifndef TU_LOG3 - #define TU_LOG3(...) - #define TU_LOG3_MEM(...) - #define TU_LOG3_VAR(...) - #define TU_LOG3_INT(...) - #define TU_LOG3_HEX(...) -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_COMMON_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h deleted file mode 100644 index d3284c62a..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_Common - * \defgroup Group_Compiler Compiler - * \brief Group_Compiler brief - * @{ */ - -#ifndef _TUSB_COMPILER_H_ -#define _TUSB_COMPILER_H_ - -#define TU_TOKEN(x) x -#define TU_STRING(x) #x ///< stringify without expand -#define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify - -#define TU_STRCAT(a, b) a##b ///< concat without expand -#define TU_STRCAT3(a, b, c) a##b##c ///< concat without expand - -#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat -#define TU_XSTRCAT3(a, b, c) TU_STRCAT3(a, b, c) ///< expand then concat 3 tokens - -#define TU_INCLUDE_PATH(_dir,_file) TU_XSTRING( TU_TOKEN(_dir)TU_TOKEN(_file) ) - -#if defined __COUNTER__ && __COUNTER__ != __COUNTER__ - #define _TU_COUNTER_ __COUNTER__ -#else - #define _TU_COUNTER_ __LINE__ -#endif - -// Compile-time Assert -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define TU_VERIFY_STATIC _Static_assert -#elif defined (__cplusplus) && __cplusplus >= 201103L - #define TU_VERIFY_STATIC static_assert -#elif defined(__CCRX__) - #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0]; -#else - #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } -#endif - -// for declaration of reserved field, make use of _TU_COUNTER_ -#define TU_RESERVED TU_XSTRCAT(reserved, _TU_COUNTER_) - -#define TU_LITTLE_ENDIAN (0x12u) -#define TU_BIG_ENDIAN (0x21u) - -/*------------------------------------------------------------------*/ -/* Count number of arguments of __VA_ARGS__ - * - reference https://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments - * - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) - * - _RSEQ_N() is reverse sequential to N to add padding to have - * Nth position is the same as the number of arguments - * - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma) - *------------------------------------------------------------------*/ -#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N()) - -#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__) -#define _GET_NTH_ARG( \ - _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ - _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ - _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ - _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ - _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ - _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ - _61,_62,_63,N,...) N -#define _RSEQ_N() \ - 62,61,60, \ - 59,58,57,56,55,54,53,52,51,50, \ - 49,48,47,46,45,44,43,42,41,40, \ - 39,38,37,36,35,34,33,32,31,30, \ - 29,28,27,26,25,24,23,22,21,20, \ - 19,18,17,16,15,14,13,12,11,10, \ - 9,8,7,6,5,4,3,2,1,0 - -// Apply an macro X to each of the arguments with an separated of choice -#define TU_ARGS_APPLY(_X, _s, ...) TU_XSTRCAT(_TU_ARGS_APPLY_, TU_ARGS_NUM(__VA_ARGS__))(_X, _s, __VA_ARGS__) - -#define _TU_ARGS_APPLY_1(_X, _s, _a1) _X(_a1) -#define _TU_ARGS_APPLY_2(_X, _s, _a1, _a2) _X(_a1) _s _X(_a2) -#define _TU_ARGS_APPLY_3(_X, _s, _a1, _a2, _a3) _X(_a1) _s _TU_ARGS_APPLY_2(_X, _s, _a2, _a3) -#define _TU_ARGS_APPLY_4(_X, _s, _a1, _a2, _a3, _a4) _X(_a1) _s _TU_ARGS_APPLY_3(_X, _s, _a2, _a3, _a4) -#define _TU_ARGS_APPLY_5(_X, _s, _a1, _a2, _a3, _a4, _a5) _X(_a1) _s _TU_ARGS_APPLY_4(_X, _s, _a2, _a3, _a4, _a5) -#define _TU_ARGS_APPLY_6(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6) _X(_a1) _s _TU_ARGS_APPLY_5(_X, _s, _a2, _a3, _a4, _a5, _a6) -#define _TU_ARGS_APPLY_7(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7) _X(_a1) _s _TU_ARGS_APPLY_6(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7) -#define _TU_ARGS_APPLY_8(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) _X(_a1) _s _TU_ARGS_APPLY_7(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7, _a8) - -//--------------------------------------------------------------------+ -// Compiler porting with Attribute and Endian -//--------------------------------------------------------------------+ - -// TODO refactor since __attribute__ is supported across many compiler -#if defined(__GNUC__) - #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) - #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) - #define TU_ATTR_PACKED __attribute__ ((packed)) - #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) - #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used - #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused - #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used - - #define TU_ATTR_PACKED_BEGIN - #define TU_ATTR_PACKED_END - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN - #define TU_ATTR_BIT_FIELD_ORDER_END - - // Endian conversion use well-known host to network (big endian) naming - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #else - #define TU_BYTE_ORDER TU_BIG_ENDIAN - #endif - - #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) - #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) - - // List of obsolete callback function that is renamed and should not be defined. - // Put it here since only gcc support this pragma - #pragma GCC poison tud_vendor_control_request_cb - -#elif defined(__TI_COMPILER_VERSION__) - #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) - #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) - #define TU_ATTR_PACKED __attribute__ ((packed)) - #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) - #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used - #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused - #define TU_ATTR_USED __attribute__ ((used)) - - #define TU_ATTR_PACKED_BEGIN - #define TU_ATTR_PACKED_END - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN - #define TU_ATTR_BIT_FIELD_ORDER_END - - // __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian) - #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__) - #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #else - #define TU_BYTE_ORDER TU_BIG_ENDIAN - #endif - - #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) - #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) - -#elif defined(__ICCARM__) - #include - #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) - #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) - #define TU_ATTR_PACKED __attribute__ ((packed)) - #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) - #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used - #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused - #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used - - #define TU_ATTR_PACKED_BEGIN - #define TU_ATTR_PACKED_END - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN - #define TU_ATTR_BIT_FIELD_ORDER_END - - // Endian conversion use well-known host to network (big endian) naming - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #else - #define TU_BYTE_ORDER TU_BIG_ENDIAN - #endif - - #define TU_BSWAP16(u16) (__iar_builtin_REV16(u16)) - #define TU_BSWAP32(u32) (__iar_builtin_REV(u32)) - -#elif defined(__CCRX__) - #define TU_ATTR_ALIGNED(Bytes) - #define TU_ATTR_SECTION(sec_name) - #define TU_ATTR_PACKED - #define TU_ATTR_WEAK - #define TU_ATTR_ALWAYS_INLINE - #define TU_ATTR_DEPRECATED(mess) - #define TU_ATTR_UNUSED - #define TU_ATTR_USED - - #define TU_ATTR_PACKED_BEGIN _Pragma("pack") - #define TU_ATTR_PACKED_END _Pragma("packoption") - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") - #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order") - - // Endian conversion use well-known host to network (big endian) naming - #if defined(__LIT) - #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #else - #define TU_BYTE_ORDER TU_BIG_ENDIAN - #endif - - #define TU_BSWAP16(u16) ((unsigned short)_builtin_revw((unsigned long)u16)) - #define TU_BSWAP32(u32) (_builtin_revl(u32)) - -#else - #error "Compiler attribute porting is required" -#endif - -#if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN) - - #define tu_htons(u16) (TU_BSWAP16(u16)) - #define tu_ntohs(u16) (TU_BSWAP16(u16)) - - #define tu_htonl(u32) (TU_BSWAP32(u32)) - #define tu_ntohl(u32) (TU_BSWAP32(u32)) - - #define tu_htole16(u16) (u16) - #define tu_le16toh(u16) (u16) - - #define tu_htole32(u32) (u32) - #define tu_le32toh(u32) (u32) - -#elif (TU_BYTE_ORDER == TU_BIG_ENDIAN) - - #define tu_htons(u16) (u16) - #define tu_ntohs(u16) (u16) - - #define tu_htonl(u32) (u32) - #define tu_ntohl(u32) (u32) - - #define tu_htole16(u16) (TU_BSWAP16(u16)) - #define tu_le16toh(u16) (TU_BSWAP16(u16)) - - #define tu_htole32(u32) (TU_BSWAP32(u32)) - #define tu_le32toh(u32) (TU_BSWAP32(u32)) - -#else - #error Byte order is undefined -#endif - -#endif /* _TUSB_COMPILER_H_ */ - -/// @} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h deleted file mode 100644 index d7ad8c318..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_Common - * \defgroup Group_Error Error Codes - * @{ */ - -#ifndef _TUSB_ERRORS_H_ -#define _TUSB_ERRORS_H_ - -#include "tusb_option.h" - -#ifdef __cplusplus - extern "C" { -#endif - -#define ERROR_ENUM(x) x, -#define ERROR_STRING(x) #x, - -#define ERROR_TABLE(ENTRY) \ - ENTRY(TUSB_ERROR_NONE )\ - ENTRY(TUSB_ERROR_INVALID_PARA )\ - ENTRY(TUSB_ERROR_DEVICE_NOT_READY )\ - ENTRY(TUSB_ERROR_INTERFACE_IS_BUSY )\ - ENTRY(TUSB_ERROR_HCD_OPEN_PIPE_FAILED )\ - ENTRY(TUSB_ERROR_OSAL_TIMEOUT )\ - ENTRY(TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED )\ - ENTRY(TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED )\ - ENTRY(TUSB_ERROR_NOT_SUPPORTED )\ - ENTRY(TUSB_ERROR_NOT_ENOUGH_MEMORY )\ - ENTRY(TUSB_ERROR_FAILED )\ - -/// \brief Error Code returned -/// TODO obsolete and to be remove -typedef enum -{ - ERROR_TABLE(ERROR_ENUM) - TUSB_ERROR_COUNT -}tusb_error_t; - -#if CFG_TUSB_DEBUG -/// Enum to String for debugging purposes. Only available if \ref CFG_TUSB_DEBUG > 0 -extern char const* const tusb_strerr[TUSB_ERROR_COUNT]; -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_ERRORS_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c deleted file mode 100644 index 183c9c6fc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c +++ /dev/null @@ -1,1007 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "osal/osal.h" -#include "tusb_fifo.h" - -// Supress IAR warning -// Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement -#if defined(__ICCARM__) -#pragma diag_suppress = Pa082 -#endif - -// implement mutex lock and unlock -#if CFG_FIFO_MUTEX - -static inline void _ff_lock(tu_fifo_mutex_t mutex) -{ - if (mutex) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); -} - -static inline void _ff_unlock(tu_fifo_mutex_t mutex) -{ - if (mutex) osal_mutex_unlock(mutex); -} - -#else - -#define _ff_lock(_mutex) -#define _ff_unlock(_mutex) - -#endif - -/** \enum tu_fifo_copy_mode_t - * \brief Write modes intended to allow special read and write functions to be able to - * copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others - */ -typedef enum -{ - TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode - TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO -} tu_fifo_copy_mode_t; - -bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) -{ - if (depth > 0x8000) return false; // Maximum depth is 2^15 items - - _ff_lock(f->mutex_wr); - _ff_lock(f->mutex_rd); - - f->buffer = (uint8_t*) buffer; - f->depth = depth; - f->item_size = item_size; - f->overwritable = overwritable; - - // Limit index space to 2*depth - this allows for a fast "modulo" calculation - // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable - // only if overflow happens once (important for unsupervised DMA applications) - f->max_pointer_idx = 2*depth - 1; - f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; - - f->rd_idx = f->wr_idx = 0; - - _ff_unlock(f->mutex_wr); - _ff_unlock(f->mutex_rd); - - return true; -} - -// Static functions are intended to work on local variables -static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) -{ - while ( idx >= depth) idx -= depth; - return idx; -} - -// Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address -// Code adapted from dcd_synopsis.c -// TODO generalize with configurable 1 byte or 4 byte each read -static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t len) -{ - volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; - - // Reading full available 32 bit words from const app address - uint16_t full_words = len >> 2; - while(full_words--) - { - tu_unaligned_write32(ff_buf, *rx_fifo); - ff_buf += 4; - } - - // Read the remaining 1-3 bytes from const app address - uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { - uint32_t tmp32 = *rx_fifo; - memcpy(ff_buf, &tmp32, bytes_rem); - } -} - -// Intended to be used to write to hardware USB FIFO in e.g. STM32 -// where all data is written to a constant address in full word copies -static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t len) -{ - volatile uint32_t * tx_fifo = (volatile uint32_t *) app_buf; - - // Pushing full available 32 bit words to const app address - uint16_t full_words = len >> 2; - while(full_words--) - { - *tx_fifo = tu_unaligned_read32(ff_buf); - ff_buf += 4; - } - - // Write the remaining 1-3 bytes into const app address - uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { - uint32_t tmp32 = 0; - memcpy(&tmp32, ff_buf, bytes_rem); - - *tx_fifo = tmp32; - } -} - -// send one item to FIFO WITHOUT updating write pointer -static inline void _ff_push(tu_fifo_t* f, void const * app_buf, uint16_t rel) -{ - memcpy(f->buffer + (rel * f->item_size), app_buf, f->item_size); -} - -// send n items to FIFO WITHOUT updating write pointer -static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t rel, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t const nLin = f->depth - rel; - uint16_t const nWrap = n - nLin; - - uint16_t nLin_bytes = nLin * f->item_size; - uint16_t nWrap_bytes = nWrap * f->item_size; - - // current buffer of fifo - uint8_t* ff_buf = f->buffer + (rel * f->item_size); - - switch (copy_mode) - { - case TU_FIFO_COPY_INC: - if(n <= nLin) - { - // Linear only - memcpy(ff_buf, app_buf, n*f->item_size); - } - else - { - // Wrap around - - // Write data to linear part of buffer - memcpy(ff_buf, app_buf, nLin_bytes); - - // Write data wrapped around - memcpy(f->buffer, ((uint8_t const*) app_buf) + nLin_bytes, nWrap_bytes); - } - break; - - case TU_FIFO_COPY_CST_FULL_WORDS: - // Intended for hardware buffers from which it can be read word by word only - if(n <= nLin) - { - // Linear only - _ff_push_const_addr(ff_buf, app_buf, n*f->item_size); - } - else - { - // Wrap around case - - // Write full words to linear part of buffer - uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; - _ff_push_const_addr(ff_buf, app_buf, nLin_4n_bytes); - ff_buf += nLin_4n_bytes; - - // There could be odd 1-3 bytes before the wrap-around boundary - volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; - uint8_t rem = nLin_bytes & 0x03; - if (rem > 0) - { - uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); - nWrap_bytes -= remrem; - - uint32_t tmp32 = *rx_fifo; - uint8_t * src_u8 = ((uint8_t *) &tmp32); - - // Write 1-3 bytes before wrapped boundary - while(rem--) *ff_buf++ = *src_u8++; - - // Read more bytes to beginning to complete a word - ff_buf = f->buffer; - while(remrem--) *ff_buf++ = *src_u8++; - } - else - { - ff_buf = f->buffer; // wrap around to beginning - } - - // Write data wrapped part - if (nWrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, nWrap_bytes); - } - break; - } -} - -// get one item from FIFO WITHOUT updating read pointer -static inline void _ff_pull(tu_fifo_t* f, void * app_buf, uint16_t rel) -{ - memcpy(app_buf, f->buffer + (rel * f->item_size), f->item_size); -} - -// get n items from FIFO WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rel, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t const nLin = f->depth - rel; - uint16_t const nWrap = n - nLin; // only used if wrapped - - uint16_t nLin_bytes = nLin * f->item_size; - uint16_t nWrap_bytes = nWrap * f->item_size; - - // current buffer of fifo - uint8_t* ff_buf = f->buffer + (rel * f->item_size); - - switch (copy_mode) - { - case TU_FIFO_COPY_INC: - if ( n <= nLin ) - { - // Linear only - memcpy(app_buf, ff_buf, n*f->item_size); - } - else - { - // Wrap around - - // Read data from linear part of buffer - memcpy(app_buf, ff_buf, nLin_bytes); - - // Read data wrapped part - memcpy((uint8_t*) app_buf + nLin_bytes, f->buffer, nWrap_bytes); - } - break; - - case TU_FIFO_COPY_CST_FULL_WORDS: - if ( n <= nLin ) - { - // Linear only - _ff_pull_const_addr(app_buf, ff_buf, n*f->item_size); - } - else - { - // Wrap around case - - // Read full words from linear part of buffer - uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; - _ff_pull_const_addr(app_buf, ff_buf, nLin_4n_bytes); - ff_buf += nLin_4n_bytes; - - // There could be odd 1-3 bytes before the wrap-around boundary - volatile uint32_t * tx_fifo = (volatile uint32_t *) app_buf; - uint8_t rem = nLin_bytes & 0x03; - if (rem > 0) - { - uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); - nWrap_bytes -= remrem; - - uint32_t tmp32=0; - uint8_t * dst_u8 = (uint8_t *)&tmp32; - - // Read 1-3 bytes before wrapped boundary - while(rem--) *dst_u8++ = *ff_buf++; - - // Read more bytes from beginning to complete a word - ff_buf = f->buffer; - while(remrem--) *dst_u8++ = *ff_buf++; - - *tx_fifo = tmp32; - } - else - { - ff_buf = f->buffer; // wrap around to beginning - } - - // Read data wrapped part - if (nWrap_bytes > 0) _ff_pull_const_addr(app_buf, ff_buf, nWrap_bytes); - } - break; - - default: break; - } -} - -// Advance an absolute pointer -static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) -{ - // We limit the index space of p such that a correct wrap around happens - // Check for a wrap around or if we are in unused index space - This has to be checked first!! - // We are exploiting the wrap around to the correct index - if ((p > (uint16_t)(p + offset)) || ((uint16_t)(p + offset) > f->max_pointer_idx)) - { - p = (p + offset) + f->non_used_index_space; - } - else - { - p += offset; - } - return p; -} - -// Backward an absolute pointer -static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) -{ - // We limit the index space of p such that a correct wrap around happens - // Check for a wrap around or if we are in unused index space - This has to be checked first!! - // We are exploiting the wrap around to the correct index - if ((p < (uint16_t)(p - offset)) || ((uint16_t)(p - offset) > f->max_pointer_idx)) - { - p = (p - offset) - f->non_used_index_space; - } - else - { - p -= offset; - } - return p; -} - -// get relative from absolute pointer -static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p) -{ - return _ff_mod(p, f->depth); -} - -// Works on local copies of w and r - return only the difference and as such can be used to determine an overflow -static inline uint16_t _tu_fifo_count(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) -{ - uint16_t cnt = wAbs-rAbs; - - // In case we have non-power of two depth we need a further modification - if (rAbs > wAbs) cnt -= f->non_used_index_space; - - return cnt; -} - -// Works on local copies of w and r -static inline bool _tu_fifo_empty(uint16_t wAbs, uint16_t rAbs) -{ - return wAbs == rAbs; -} - -// Works on local copies of w and r -static inline bool _tu_fifo_full(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) -{ - return (_tu_fifo_count(f, wAbs, rAbs) == f->depth); -} - -// Works on local copies of w and r -// BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" -// Only one overflow is allowed for this function to work e.g. if depth = 100, you must not -// write more than 2*depth-1 items in one rush without updating write pointer. Otherwise -// write pointer wraps and you pointer states are messed up. This can only happen if you -// use DMAs, write functions do not allow such an error. -static inline bool _tu_fifo_overflowed(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) -{ - return (_tu_fifo_count(f, wAbs, rAbs) > f->depth); -} - -// Works on local copies of w -// For more details see _tu_fifo_overflow()! -static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) -{ - f->rd_idx = backward_pointer(f, wAbs, f->depth); -} - -// Works on local copies of w and r -// Must be protected by mutexes since in case of an overflow read pointer gets modified -static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) -{ - uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); - - // Check overflow and correct if required - if (cnt > f->depth) - { - _tu_fifo_correct_read_pointer(f, wAbs); - cnt = f->depth; - } - - // Skip beginning of buffer - if (cnt == 0) return false; - - uint16_t rRel = get_relative_pointer(f, rAbs); - - // Peek data - _ff_pull(f, p_buffer, rRel); - - return true; -} - -// Works on local copies of w and r -// Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); - - // Check overflow and correct if required - if (cnt > f->depth) - { - _tu_fifo_correct_read_pointer(f, wAbs); - rAbs = f->rd_idx; - cnt = f->depth; - } - - // Skip beginning of buffer - if (cnt == 0) return 0; - - // Check if we can read something at and after offset - if too less is available we read what remains - if (cnt < n) n = cnt; - - uint16_t rRel = get_relative_pointer(f, rAbs); - - // Peek data - _ff_pull_n(f, p_buffer, n, rRel, copy_mode); - - return n; -} - -// Works on local copies of w and r -static inline uint16_t _tu_fifo_remaining(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) -{ - return f->depth - _tu_fifo_count(f, wAbs, rAbs); -} - -static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu_fifo_copy_mode_t copy_mode) -{ - if ( n == 0 ) return 0; - - _ff_lock(f->mutex_wr); - - uint16_t w = f->wr_idx, r = f->rd_idx; - uint8_t const* buf8 = (uint8_t const*) data; - - if (!f->overwritable) - { - // Not overwritable limit up to full - n = tu_min16(n, _tu_fifo_remaining(f, w, r)); - } - else if (n >= f->depth) - { - // Only copy last part - buf8 = buf8 + (n - f->depth) * f->item_size; - n = f->depth; - - // We start writing at the read pointer's position since we fill the complete - // buffer and we do not want to modify the read pointer within a write function! - // This would end up in a race condition with read functions! - w = r; - } - - uint16_t wRel = get_relative_pointer(f, w); - - // Write data - _ff_push_n(f, buf8, n, wRel, copy_mode); - - // Advance pointer - f->wr_idx = advance_pointer(f, w, n); - - _ff_unlock(f->mutex_wr); - - return n; -} - -static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) -{ - _ff_lock(f->mutex_rd); - - // Peek the data - // f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); - - // Advance read pointer - f->rd_idx = advance_pointer(f, f->rd_idx, n); - - _ff_unlock(f->mutex_rd); - return n; -} - -/******************************************************************************/ -/*! - @brief Get number of items in FIFO. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. In case an - overflow occurred, this function return f.depth at maximum. Overflows are - checked and corrected for in the read functions! - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_count(tu_fifo_t* f) -{ - return tu_min16(_tu_fifo_count(f, f->wr_idx, f->rd_idx), f->depth); -} - -/******************************************************************************/ -/*! - @brief Check if FIFO is empty. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -bool tu_fifo_empty(tu_fifo_t* f) -{ - return _tu_fifo_empty(f->wr_idx, f->rd_idx); -} - -/******************************************************************************/ -/*! - @brief Check if FIFO is full. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -bool tu_fifo_full(tu_fifo_t* f) -{ - return _tu_fifo_full(f, f->wr_idx, f->rd_idx); -} - -/******************************************************************************/ -/*! - @brief Get remaining space in FIFO. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_remaining(tu_fifo_t* f) -{ - return _tu_fifo_remaining(f, f->wr_idx, f->rd_idx); -} - -/******************************************************************************/ -/*! - @brief Check if overflow happened. - - BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" - Only one overflow is allowed for this function to work e.g. if depth = 100, you must not - write more than 2*depth-1 items in one rush without updating write pointer. Otherwise - write pointer wraps and your pointer states are messed up. This can only happen if you - use DMAs, write functions do not allow such an error. Avoid such nasty things! - - All reading functions (read, peek) check for overflows and correct read pointer on their own such - that latest items are read. - If required (e.g. for DMA use) you can also correct the read pointer by - tu_fifo_correct_read_pointer(). - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns True if overflow happened - */ -/******************************************************************************/ -bool tu_fifo_overflowed(tu_fifo_t* f) -{ - return _tu_fifo_overflowed(f, f->wr_idx, f->rd_idx); -} - -// Only use in case tu_fifo_overflow() returned true! -void tu_fifo_correct_read_pointer(tu_fifo_t* f) -{ - _ff_lock(f->mutex_rd); - _tu_fifo_correct_read_pointer(f, f->wr_idx); - _ff_unlock(f->mutex_rd); -} - -/******************************************************************************/ -/*! - @brief Read one element out of the buffer. - - This function will return the element located at the array index of the - read pointer, and then increment the read pointer index. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] buffer - Pointer to the place holder for data read from the buffer - - @returns TRUE if the queue is not empty - */ -/******************************************************************************/ -bool tu_fifo_read(tu_fifo_t* f, void * buffer) -{ - _ff_lock(f->mutex_rd); - - // Peek the data - // f->rd_idx might get modified in case of an overflow so we can not use a local variable - bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); - - // Advance pointer - f->rd_idx = advance_pointer(f, f->rd_idx, ret); - - _ff_unlock(f->mutex_rd); - return ret; -} - -/******************************************************************************/ -/*! - @brief This function will read n elements from the array index specified by - the read pointer and increment the read index. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] buffer - The pointer to data location - @param[in] n - Number of element that buffer can afford - - @returns number of items read from the FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) -{ - return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_INC); -} - -uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint16_t n) -{ - return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST_FULL_WORDS); -} - -/******************************************************************************/ -/*! - @brief Read one item without removing it from the FIFO. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] offset - Position to read from in the FIFO buffer with respect to read pointer - @param[in] p_buffer - Pointer to the place holder for data read from the buffer - - @returns TRUE if the queue is not empty - */ -/******************************************************************************/ -bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) -{ - _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek(f, p_buffer, f->wr_idx, f->rd_idx); - _ff_unlock(f->mutex_rd); - return ret; -} - -/******************************************************************************/ -/*! - @brief Read n items without removing it from the FIFO - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] p_buffer - Pointer to the place holder for data read from the buffer - @param[in] n - Number of items to peek - - @returns Number of bytes written to p_buffer - */ -/******************************************************************************/ -uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) -{ - _ff_lock(f->mutex_rd); - uint16_t ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); - _ff_unlock(f->mutex_rd); - return ret; -} - -/******************************************************************************/ -/*! - @brief Write one element into the buffer. - - This function will write one element into the array index specified by - the write pointer and increment the write index. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The byte to add to the FIFO - - @returns TRUE if the data was written to the FIFO (overwrittable - FIFO will always return TRUE) - */ -/******************************************************************************/ -bool tu_fifo_write(tu_fifo_t* f, const void * data) -{ - _ff_lock(f->mutex_wr); - - bool ret; - uint16_t const w = f->wr_idx; - - if ( _tu_fifo_full(f, w, f->rd_idx) && !f->overwritable ) - { - ret = false; - }else - { - uint16_t wRel = get_relative_pointer(f, w); - - // Write data - _ff_push(f, data, wRel); - - // Advance pointer - f->wr_idx = advance_pointer(f, w, 1); - - ret = true; - } - - _ff_unlock(f->mutex_wr); - - return ret; -} - -/******************************************************************************/ -/*! - @brief This function will write n elements into the array index specified by - the write pointer and increment the write index. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The pointer to data to add to the FIFO - @param[in] count - Number of element - @return Number of written elements - */ -/******************************************************************************/ -uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) -{ - return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_INC); -} - -/******************************************************************************/ -/*! - @brief This function will write n elements into the array index specified by - the write pointer and increment the write index. The source address will - not be incremented which is useful for reading from registers. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The pointer to data to add to the FIFO - @param[in] count - Number of element - @return Number of written elements - */ -/******************************************************************************/ -uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t* f, const void * data, uint16_t n) -{ - return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST_FULL_WORDS); -} - -/******************************************************************************/ -/*! - @brief Clear the fifo read and write pointers - - @param[in] f - Pointer to the FIFO buffer to manipulate - */ -/******************************************************************************/ -bool tu_fifo_clear(tu_fifo_t *f) -{ - _ff_lock(f->mutex_wr); - _ff_lock(f->mutex_rd); - - f->rd_idx = f->wr_idx = 0; - f->max_pointer_idx = 2*f->depth-1; - f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; - - _ff_unlock(f->mutex_wr); - _ff_unlock(f->mutex_rd); - return true; -} - -/******************************************************************************/ -/*! - @brief Change the fifo mode to overwritable or not overwritable - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] overwritable - Overwritable mode the fifo is set to - */ -/******************************************************************************/ -bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) -{ - _ff_lock(f->mutex_wr); - _ff_lock(f->mutex_rd); - - f->overwritable = overwritable; - - _ff_unlock(f->mutex_wr); - _ff_unlock(f->mutex_rd); - - return true; -} - -/******************************************************************************/ -/*! - @brief Advance write pointer - intended to be used in combination with DMA. - It is possible to fill the FIFO by use of a DMA in circular mode. Within - DMA ISRs you may update the write pointer to be able to read from the FIFO. - As long as the DMA is the only process writing into the FIFO this is safe - to use. - - USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] n - Number of items the write pointer moves forward - */ -/******************************************************************************/ -void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) -{ - f->wr_idx = advance_pointer(f, f->wr_idx, n); -} - -/******************************************************************************/ -/*! - @brief Advance read pointer - intended to be used in combination with DMA. - It is possible to read from the FIFO by use of a DMA in linear mode. Within - DMA ISRs you may update the read pointer to be able to again write into the - FIFO. As long as the DMA is the only process reading from the FIFO this is - safe to use. - - USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] n - Number of items the read pointer moves forward - */ -/******************************************************************************/ -void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) -{ - f->rd_idx = advance_pointer(f, f->rd_idx, n); -} - -/******************************************************************************/ -/*! - @brief Get read info - - Returns the length and pointer from which bytes can be read in a linear manner. - This is of major interest for DMA transmissions. If returned length is zero the - corresponding pointer is invalid. - The read pointer does NOT get advanced, use tu_fifo_advance_read_pointer() to - do so! - @param[in] f - Pointer to FIFO - @param[out] *info - Pointer to struct which holds the desired infos - */ -/******************************************************************************/ -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) -{ - // Operate on temporary values in case they change in between - uint16_t w = f->wr_idx, r = f->rd_idx; - - uint16_t cnt = _tu_fifo_count(f, w, r); - - // Check overflow and correct if required - may happen in case a DMA wrote too fast - if (cnt > f->depth) - { - _ff_lock(f->mutex_rd); - _tu_fifo_correct_read_pointer(f, w); - _ff_unlock(f->mutex_rd); - r = f->rd_idx; - cnt = f->depth; - } - - // Check if fifo is empty - if (cnt == 0) - { - info->len_lin = 0; - info->len_wrap = 0; - info->ptr_lin = NULL; - info->ptr_wrap = NULL; - return; - } - - // Get relative pointers - w = get_relative_pointer(f, w); - r = get_relative_pointer(f, r); - - // Copy pointer to buffer to start reading from - info->ptr_lin = &f->buffer[r]; - - // Check if there is a wrap around necessary - if (w > r) { - // Non wrapping case - info->len_lin = cnt; - info->len_wrap = 0; - info->ptr_wrap = NULL; - } - else - { - info->len_lin = f->depth - r; // Also the case if FIFO was full - info->len_wrap = cnt - info->len_lin; - info->ptr_wrap = f->buffer; - } -} - -/******************************************************************************/ -/*! - @brief Get linear write info - - Returns the length and pointer to which bytes can be written into FIFO in a linear manner. - This is of major interest for DMA transmissions not using circular mode. If a returned length is zero the - corresponding pointer is invalid. The returned lengths summed up are the currently free space in the FIFO. - The write pointer does NOT get advanced, use tu_fifo_advance_write_pointer() to do so! - TAKE CARE TO NOT OVERFLOW THE BUFFER MORE THAN TWO TIMES THE FIFO DEPTH - IT CAN NOT RECOVERE OTHERWISE! - @param[in] f - Pointer to FIFO - @param[out] *info - Pointer to struct which holds the desired infos - */ -/******************************************************************************/ -void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) -{ - uint16_t w = f->wr_idx, r = f->rd_idx; - uint16_t free = _tu_fifo_remaining(f, w, r); - - if (free == 0) - { - info->len_lin = 0; - info->len_wrap = 0; - info->ptr_lin = NULL; - info->ptr_wrap = NULL; - return; - } - - // Get relative pointers - w = get_relative_pointer(f, w); - r = get_relative_pointer(f, r); - - // Copy pointer to buffer to start writing to - info->ptr_lin = &f->buffer[w]; - - if (w < r) - { - // Non wrapping case - info->len_lin = r-w; - info->len_wrap = 0; - info->ptr_wrap = NULL; - } - else - { - info->len_lin = f->depth - w; - info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth - info->ptr_wrap = f->buffer; // Always start of buffer - } -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h deleted file mode 100644 index 18db289a1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_FIFO_H_ -#define _TUSB_FIFO_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// Due to the use of unmasked pointers, this FIFO does not suffer from loosing -// one item slice. Furthermore, write and read operations are completely -// decoupled as write and read functions do not modify a common state. Henceforth, -// writing or reading from the FIFO within an ISR is safe as long as no other -// process (thread or ISR) interferes. -// Also, this FIFO is ready to be used in combination with a DMA as the write and -// read pointers can be updated from within a DMA ISR. Overflows are detectable -// within a certain number (see tu_fifo_overflow()). - -#include "common/tusb_common.h" - -// mutex is only needed for RTOS -// for OS None, we don't get preempted -#define CFG_FIFO_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) - -#if CFG_FIFO_MUTEX -#include "osal/osal.h" -#define tu_fifo_mutex_t osal_mutex_t -#endif - -typedef struct -{ - uint8_t* buffer ; ///< buffer pointer - uint16_t depth ; ///< max items - uint16_t item_size ; ///< size of each item - bool overwritable ; - - uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length - uint16_t max_pointer_idx ; ///< maximum absolute pointer index - - volatile uint16_t wr_idx ; ///< write pointer - volatile uint16_t rd_idx ; ///< read pointer - -#if CFG_FIFO_MUTEX - tu_fifo_mutex_t mutex_wr; - tu_fifo_mutex_t mutex_rd; -#endif - -} tu_fifo_t; - -typedef struct -{ - uint16_t len_lin ; ///< linear length in item size - uint16_t len_wrap ; ///< wrapped length in item size - void * ptr_lin ; ///< linear part start pointer - void * ptr_wrap ; ///< wrapped part start pointer -} tu_fifo_buffer_info_t; - -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ -{ \ - .buffer = _buffer, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ - .non_used_index_space = UINT16_MAX - (2*(_depth)-1), \ - .max_pointer_idx = 2*(_depth)-1, \ -} - -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) - - -bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); -bool tu_fifo_clear(tu_fifo_t *f); -bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); - -#if CFG_FIFO_MUTEX -TU_ATTR_ALWAYS_INLINE static inline -void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) -{ - f->mutex_wr = write_mutex_hdl; - f->mutex_rd = read_mutex_hdl; -} -#endif - -bool tu_fifo_write (tu_fifo_t* f, void const * p_data); -uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t n); -uint16_t tu_fifo_write_n_const_addr_full_words (tu_fifo_t* f, const void * data, uint16_t n); - -bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); -uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); - -bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n); - -uint16_t tu_fifo_count (tu_fifo_t* f); -uint16_t tu_fifo_remaining (tu_fifo_t* f); -bool tu_fifo_empty (tu_fifo_t* f); -bool tu_fifo_full (tu_fifo_t* f); -bool tu_fifo_overflowed (tu_fifo_t* f); -void tu_fifo_correct_read_pointer (tu_fifo_t* f); - -TU_ATTR_ALWAYS_INLINE static inline -uint16_t tu_fifo_depth(tu_fifo_t* f) -{ - return f->depth; -} - -// Pointer modifications intended to be used in combinations with DMAs. -// USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! -void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n); -void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); - -// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies -// to handle a possible wrapping part. These functions deliver a pointer to start -// reading/writing from/to and a valid linear length along which no wrap occurs. -void tu_fifo_get_read_info (tu_fifo_t *f, tu_fifo_buffer_info_t *info); -void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); - - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_FIFO_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h deleted file mode 100644 index ce53955f0..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_Common Common Files - * \defgroup Group_TimeoutTimer timeout timer - * @{ */ - -#ifndef _TUSB_TIMEOUT_H_ -#define _TUSB_TIMEOUT_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint32_t start; - uint32_t interval; -}tu_timeout_t; - -#if 0 - -extern uint32_t tusb_hal_millis(void); - -static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) -{ - tt->interval = msec; - tt->start = tusb_hal_millis(); -} - -static inline bool tu_timeout_expired(tu_timeout_t* tt) -{ - return ( tusb_hal_millis() - tt->start ) >= tt->interval; -} - -// For used with periodic event to prevent drift -static inline void tu_timeout_reset(tu_timeout_t* tt) -{ - tt->start += tt->interval; -} - -static inline void tu_timeout_restart(tu_timeout_t* tt) -{ - tt->start = tusb_hal_millis(); -} - -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TIMEOUT_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h deleted file mode 100644 index 5b26f5aec..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h +++ /dev/null @@ -1,546 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_usb_definitions - * \defgroup USBDef_Type USB Types - * @{ */ - -#ifndef _TUSB_TYPES_H_ -#define _TUSB_TYPES_H_ - -#include -#include -#include "tusb_compiler.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/*------------------------------------------------------------------*/ -/* CONSTANTS - *------------------------------------------------------------------*/ - -/// defined base on EHCI specs value for Endpoint Speed -typedef enum -{ - TUSB_SPEED_FULL = 0, - TUSB_SPEED_LOW = 1, - TUSB_SPEED_HIGH = 2, - TUSB_SPEED_INVALID = 0xff, -}tusb_speed_t; - -/// defined base on USB Specs Endpoint's bmAttributes -typedef enum -{ - TUSB_XFER_CONTROL = 0 , - TUSB_XFER_ISOCHRONOUS , - TUSB_XFER_BULK , - TUSB_XFER_INTERRUPT -}tusb_xfer_type_t; - -typedef enum -{ - TUSB_DIR_OUT = 0, - TUSB_DIR_IN = 1, - - TUSB_DIR_IN_MASK = 0x80 -}tusb_dir_t; - -/// Isochronous End Point Attributes -typedef enum -{ - TUSB_ISO_EP_ATT_NO_SYNC = 0x00, - TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, - TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, - TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, - TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point - TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback -}tusb_iso_ep_attribute_t; - -/// USB Descriptor Types -typedef enum -{ - TUSB_DESC_DEVICE = 0x01, - TUSB_DESC_CONFIGURATION = 0x02, - TUSB_DESC_STRING = 0x03, - TUSB_DESC_INTERFACE = 0x04, - TUSB_DESC_ENDPOINT = 0x05, - TUSB_DESC_DEVICE_QUALIFIER = 0x06, - TUSB_DESC_OTHER_SPEED_CONFIG = 0x07, - TUSB_DESC_INTERFACE_POWER = 0x08, - TUSB_DESC_OTG = 0x09, - TUSB_DESC_DEBUG = 0x0A, - TUSB_DESC_INTERFACE_ASSOCIATION = 0x0B, - - TUSB_DESC_BOS = 0x0F, - TUSB_DESC_DEVICE_CAPABILITY = 0x10, - - TUSB_DESC_FUNCTIONAL = 0x21, - - // Class Specific Descriptor - TUSB_DESC_CS_DEVICE = 0x21, - TUSB_DESC_CS_CONFIGURATION = 0x22, - TUSB_DESC_CS_STRING = 0x23, - TUSB_DESC_CS_INTERFACE = 0x24, - TUSB_DESC_CS_ENDPOINT = 0x25, - - TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30, - TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31 -}tusb_desc_type_t; - -typedef enum -{ - TUSB_REQ_GET_STATUS = 0 , - TUSB_REQ_CLEAR_FEATURE = 1 , - TUSB_REQ_RESERVED = 2 , - TUSB_REQ_SET_FEATURE = 3 , - TUSB_REQ_RESERVED2 = 4 , - TUSB_REQ_SET_ADDRESS = 5 , - TUSB_REQ_GET_DESCRIPTOR = 6 , - TUSB_REQ_SET_DESCRIPTOR = 7 , - TUSB_REQ_GET_CONFIGURATION = 8 , - TUSB_REQ_SET_CONFIGURATION = 9 , - TUSB_REQ_GET_INTERFACE = 10 , - TUSB_REQ_SET_INTERFACE = 11 , - TUSB_REQ_SYNCH_FRAME = 12 -}tusb_request_code_t; - -typedef enum -{ - TUSB_REQ_FEATURE_EDPT_HALT = 0, - TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1, - TUSB_REQ_FEATURE_TEST_MODE = 2 -}tusb_request_feature_selector_t; - -typedef enum -{ - TUSB_REQ_TYPE_STANDARD = 0, - TUSB_REQ_TYPE_CLASS, - TUSB_REQ_TYPE_VENDOR, - TUSB_REQ_TYPE_INVALID -} tusb_request_type_t; - -typedef enum -{ - TUSB_REQ_RCPT_DEVICE =0, - TUSB_REQ_RCPT_INTERFACE, - TUSB_REQ_RCPT_ENDPOINT, - TUSB_REQ_RCPT_OTHER -} tusb_request_recipient_t; - -// https://www.usb.org/defined-class-codes -typedef enum -{ - TUSB_CLASS_UNSPECIFIED = 0 , - TUSB_CLASS_AUDIO = 1 , - TUSB_CLASS_CDC = 2 , - TUSB_CLASS_HID = 3 , - TUSB_CLASS_RESERVED_4 = 4 , - TUSB_CLASS_PHYSICAL = 5 , - TUSB_CLASS_IMAGE = 6 , - TUSB_CLASS_PRINTER = 7 , - TUSB_CLASS_MSC = 8 , - TUSB_CLASS_HUB = 9 , - TUSB_CLASS_CDC_DATA = 10 , - TUSB_CLASS_SMART_CARD = 11 , - TUSB_CLASS_RESERVED_12 = 12 , - TUSB_CLASS_CONTENT_SECURITY = 13 , - TUSB_CLASS_VIDEO = 14 , - TUSB_CLASS_PERSONAL_HEALTHCARE = 15 , - TUSB_CLASS_AUDIO_VIDEO = 16 , - - TUSB_CLASS_DIAGNOSTIC = 0xDC , - TUSB_CLASS_WIRELESS_CONTROLLER = 0xE0 , - TUSB_CLASS_MISC = 0xEF , - TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE , - TUSB_CLASS_VENDOR_SPECIFIC = 0xFF -}tusb_class_code_t; - -typedef enum -{ - MISC_SUBCLASS_COMMON = 2 -}misc_subclass_type_t; - -typedef enum -{ - MISC_PROTOCOL_IAD = 1 -}misc_protocol_type_t; - -typedef enum -{ - APP_SUBCLASS_USBTMC = 0x03, - APP_SUBCLASS_DFU_RUNTIME = 0x01 -} app_subclass_type_t; - -typedef enum -{ - DEVICE_CAPABILITY_WIRELESS_USB = 0x01, - DEVICE_CAPABILITY_USB20_EXTENSION = 0x02, - DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03, - DEVICE_CAPABILITY_CONTAINER_id = 0x04, - DEVICE_CAPABILITY_PLATFORM = 0x05, - DEVICE_CAPABILITY_POWER_DELIVERY = 0x06, - DEVICE_CAPABILITY_BATTERY_INFO = 0x07, - DEVICE_CAPABILITY_PD_CONSUMER_PORT = 0x08, - DEVICE_CAPABILITY_PD_PROVIDER_PORT = 0x09, - DEVICE_CAPABILITY_SUPERSPEED_PLUS = 0x0A, - DEVICE_CAPABILITY_PRECESION_TIME_MEASUREMENT = 0x0B, - DEVICE_CAPABILITY_WIRELESS_USB_EXT = 0x0C, - DEVICE_CAPABILITY_BILLBOARD = 0x0D, - DEVICE_CAPABILITY_AUTHENTICATION = 0x0E, - DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F, - DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10 -}device_capability_type_t; - -enum { - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5), - TUSB_DESC_CONFIG_ATT_SELF_POWERED = TU_BIT(6), -}; - -#define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) - -/// Device State TODO remove -typedef enum -{ - TUSB_DEVICE_STATE_UNPLUG = 0 , - TUSB_DEVICE_STATE_CONFIGURED , - TUSB_DEVICE_STATE_SUSPENDED , -}tusb_device_state_t; - -typedef enum -{ - XFER_RESULT_SUCCESS, - XFER_RESULT_FAILED, - XFER_RESULT_STALLED, -}xfer_result_t; - -enum // TODO remove -{ - DESC_OFFSET_LEN = 0, - DESC_OFFSET_TYPE = 1 -}; - -enum -{ - INTERFACE_INVALID_NUMBER = 0xff -}; - - -typedef enum -{ - MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, - MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01, - MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02, - MS_OS_20_FEATURE_COMPATBLE_ID = 0x03, - MS_OS_20_FEATURE_REG_PROPERTY = 0x04, - MS_OS_20_FEATURE_MIN_RESUME_TIME = 0x05, - MS_OS_20_FEATURE_MODEL_ID = 0x06, - MS_OS_20_FEATURE_CCGP_DEVICE = 0x07, - MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 -} microsoft_os_20_type_t; - -enum -{ - CONTROL_STAGE_SETUP, - CONTROL_STAGE_DATA, - CONTROL_STAGE_ACK -}; - -//--------------------------------------------------------------------+ -// USB Descriptors -//--------------------------------------------------------------------+ - -// Start of all packed definitions for compiler without per-type packed -TU_ATTR_PACKED_BEGIN -TU_ATTR_BIT_FIELD_ORDER_BEGIN - -/// USB Device Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. - uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant. - - uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). \li If this field is reset to zero, each interface within a configuration specifies its own class information and the various interfaces operate independently. \li If this field is set to a value between 1 and FEH, the device supports different class specifications on different interfaces and the interfaces may not operate independently. This value identifies the class definition used for the aggregate interfaces. \li If this field is set to FFH, the device class is vendor-specific. - uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass field. \li If the bDeviceClass field is reset to zero, this field must also be reset to zero. \li If the bDeviceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. - uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass and the bDeviceSubClass fields. If a device supports class-specific protocols on a device basis as opposed to an interface basis, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use class-specific protocols on a device basis. However, it may use classspecific protocols on an interface basis. \li If this field is set to FFH, the device uses a vendor-specific protocol on a device basis. - uint8_t bMaxPacketSize0 ; ///< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid). For HS devices is fixed to 64. - - uint16_t idVendor ; ///< Vendor ID (assigned by the USB-IF). - uint16_t idProduct ; ///< Product ID (assigned by the manufacturer). - uint16_t bcdDevice ; ///< Device release number in binary-coded decimal. - uint8_t iManufacturer ; ///< Index of string descriptor describing manufacturer. - uint8_t iProduct ; ///< Index of string descriptor describing product. - uint8_t iSerialNumber ; ///< Index of string descriptor describing the device's serial number. - - uint8_t bNumConfigurations ; ///< Number of possible configurations. -} tusb_desc_device_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); - -// USB Binary Device Object Store (BOS) Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes - uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type - uint16_t wTotalLength ; ///< Total length of data returned for this descriptor - uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS -} tusb_desc_bos_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); - -/// USB Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes - uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type - uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration. - - uint8_t bNumInterfaces ; ///< Number of interfaces supported by this configuration - uint8_t bConfigurationValue ; ///< Value to use as an argument to the SetConfiguration() request to select this configuration. - uint8_t iConfiguration ; ///< Index of string descriptor describing this configuration - uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. - uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). -} tusb_desc_configuration_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); - -/// USB Interface Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes - uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type - - uint8_t bInterfaceNumber ; ///< Number of this interface. Zero-based value identifying the index in the array of concurrent interfaces supported by this configuration. - uint8_t bAlternateSetting ; ///< Value used to select this alternate setting for the interface identified in the prior field - uint8_t bNumEndpoints ; ///< Number of endpoints used by this interface (excluding endpoint zero). If this value is zero, this interface only uses the Default Control Pipe. - uint8_t bInterfaceClass ; ///< Class code (assigned by the USB-IF). \li A value of zero is reserved for future standardization. \li If this field is set to FFH, the interface class is vendor-specific. \li All other values are reserved for assignment by the USB-IF. - uint8_t bInterfaceSubClass ; ///< Subclass code (assigned by the USB-IF). \n These codes are qualified by the value of the bInterfaceClass field. \li If the bInterfaceClass field is reset to zero, this field must also be reset to zero. \li If the bInterfaceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. - uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. - uint8_t iInterface ; ///< Index of string descriptor describing this interface -} tusb_desc_interface_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); - -/// USB Endpoint Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; // Size of this descriptor in bytes - uint8_t bDescriptorType ; // ENDPOINT Descriptor Type - - uint8_t bEndpointAddress ; // The address of the endpoint - - struct TU_ATTR_PACKED { - uint8_t xfer : 2; // Control, ISO, Bulk, Interrupt - uint8_t sync : 2; // None, Asynchronous, Adaptive, Synchronous - uint8_t usage : 2; // Data, Feedback, Implicit feedback - uint8_t : 2; - } bmAttributes; - - uint16_t wMaxPacketSize ; // Bit 10..0 : max packet size, bit 12..11 additional transaction per highspeed micro-frame - uint8_t bInterval ; // Polling interval, in frames or microframes depending on the operating speed -} tusb_desc_endpoint_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct"); - -/// USB Other Speed Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of descriptor - uint8_t bDescriptorType ; ///< Other_speed_Configuration Type - uint16_t wTotalLength ; ///< Total length of data returned - - uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration - uint8_t bConfigurationValue ; ///< Value to use to select configuration - uint8_t iConfiguration ; ///< Index of string descriptor - uint8_t bmAttributes ; ///< Same as Configuration descriptor - uint8_t bMaxPower ; ///< Same as Configuration descriptor -} tusb_desc_other_speed_t; - -/// USB Device Qualifier Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of descriptor - uint8_t bDescriptorType ; ///< Device Qualifier Type - uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) - - uint8_t bDeviceClass ; ///< Class Code - uint8_t bDeviceSubClass ; ///< SubClass Code - uint8_t bDeviceProtocol ; ///< Protocol Code - - uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed - uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations - uint8_t bReserved ; ///< Reserved for future use, must be zero -} tusb_desc_device_qualifier_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct"); - -/// USB Interface Association Descriptor (IAD ECN) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of descriptor - uint8_t bDescriptorType ; ///< Other_speed_Configuration Type - - uint8_t bFirstInterface ; ///< Index of the first associated interface. - uint8_t bInterfaceCount ; ///< Total number of associated interfaces. - - uint8_t bFunctionClass ; ///< Interface class ID. - uint8_t bFunctionSubClass ; ///< Interface subclass ID. - uint8_t bFunctionProtocol ; ///< Interface protocol ID. - - uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. -} tusb_desc_interface_assoc_t; - -// USB String Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes - uint8_t bDescriptorType ; ///< Descriptor Type - uint16_t unicode_string[]; -} tusb_desc_string_t; - -// USB Binary Device Object Store (BOS) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; - uint8_t bDescriptorType ; - uint8_t bDevCapabilityType; - uint8_t bReserved; - uint8_t PlatformCapabilityUUID[16]; - uint8_t CapabilityData[]; -} tusb_desc_bos_platform_t; - -// USB WebuSB URL Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bScheme; - char url[]; -} tusb_desc_webusb_url_t; - -// DFU Functional Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; - uint8_t bDescriptorType; - - union { - struct TU_ATTR_PACKED { - uint8_t bitCanDnload : 1; - uint8_t bitCanUpload : 1; - uint8_t bitManifestationTolerant : 1; - uint8_t bitWillDetach : 1; - uint8_t reserved : 4; - } bmAttributes; - - uint8_t bAttributes; - }; - - uint16_t wDetachTimeOut; - uint16_t wTransferSize; - uint16_t bcdDFUVersion; -} tusb_desc_dfu_functional_t; - -/*------------------------------------------------------------------*/ -/* Types - *------------------------------------------------------------------*/ -typedef struct TU_ATTR_PACKED{ - union { - struct TU_ATTR_PACKED { - uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. - uint8_t type : 2; ///< Request type tusb_request_type_t. - uint8_t direction : 1; ///< Direction type. tusb_dir_t - } bmRequestType_bit; - - uint8_t bmRequestType; - }; - - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; -} tusb_control_request_t; - -TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); - - -TU_ATTR_PACKED_END // End of all packed definitions -TU_ATTR_BIT_FIELD_ORDER_END - -//--------------------------------------------------------------------+ -// Endpoint helper -//--------------------------------------------------------------------+ - -// Get direction from Endpoint address -static inline tusb_dir_t tu_edpt_dir(uint8_t addr) -{ - return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; -} - -// Get Endpoint number from address -static inline uint8_t tu_edpt_number(uint8_t addr) -{ - return (uint8_t)(addr & (~TUSB_DIR_IN_MASK)); -} - -static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) -{ - return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); -} - -static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) -{ - return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0); -} - -//--------------------------------------------------------------------+ -// Descriptor helper -//--------------------------------------------------------------------+ -static inline uint8_t const * tu_desc_next(void const* desc) -{ - uint8_t const* desc8 = (uint8_t const*) desc; - return desc8 + desc8[DESC_OFFSET_LEN]; -} - -static inline uint8_t tu_desc_type(void const* desc) -{ - return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; -} - -static inline uint8_t tu_desc_len(void const* desc) -{ - return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TYPES_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h deleted file mode 100644 index 8fef11dc7..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ -#ifndef TUSB_VERIFY_H_ -#define TUSB_VERIFY_H_ - -#include -#include -#include "tusb_option.h" -#include "tusb_compiler.h" - -/*------------------------------------------------------------------*/ -/* This file use an advanced macro technique to mimic the default parameter - * as C++ for the sake of code simplicity. Beware of a headache macro - * manipulation that you are told to stay away. - * - * This contains macros for both VERIFY and ASSERT: - * - * VERIFY: Used when there is an error condition which is not the - * fault of the MCU. For example, bounds checking on data - * sent to the micro over USB should use this function. - * Another example is checking for buffer overflows, where - * returning from the active function causes a NAK. - * - * ASSERT: Used for error conditions that are caused by MCU firmware - * bugs. This is used to discover bugs in the code more - * quickly. One example would be adding assertions in library - * function calls to confirm a function's (untainted) - * parameters are valid. - * - * The difference in behavior is that ASSERT triggers a breakpoint while - * verify does not. - * - * #define TU_VERIFY(cond) if(cond) return false; - * #define TU_VERIFY(cond,ret) if(cond) return ret; - * - * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} - * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} - * - * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} - * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} - * - *------------------------------------------------------------------*/ - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TU_VERIFY Helper -//--------------------------------------------------------------------+ - -#if CFG_TUSB_DEBUG - #include - #define _MESS_ERR(_err) tu_printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) - #define _MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__) -#else - #define _MESS_ERR(_err) do {} while (0) - #define _MESS_FAILED() do {} while (0) -#endif - -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33 -#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) - #define TU_BREAKPOINT() do \ - { \ - volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ - } while(0) - -#elif defined(__riscv) - #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) - -#else - #define TU_BREAKPOINT() do {} while (0) -#endif - -/*------------------------------------------------------------------*/ -/* Macro Generator - *------------------------------------------------------------------*/ - -// Helper to implement optional parameter for TU_VERIFY Macro family -#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 -#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 - -/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/ -#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \ -{ \ - if ( !(_cond) ) { _handler; return _ret; } \ -} while(0) - -/*------------------------------------------------------------------*/ -/* TU_VERIFY - * - TU_VERIFY_1ARGS : return false if failed - * - TU_VERIFY_2ARGS : return provided value if failed - *------------------------------------------------------------------*/ -#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false) -#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret) - -#define TU_VERIFY(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__) - - -/*------------------------------------------------------------------*/ -/* TU_VERIFY WITH HANDLER - * - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed - * - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed - *------------------------------------------------------------------*/ -#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false) -#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret) - -#define TU_VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__) - -/*------------------------------------------------------------------*/ -/* ASSERT - * basically TU_VERIFY with TU_BREAKPOINT() as handler - * - 1 arg : return false if failed - * - 2 arg : return error if failed - *------------------------------------------------------------------*/ -#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false) -#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) - -#ifndef TU_ASSERT -#define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) -#endif - -// TODO remove TU_ASSERT_ERR() later - -/*------------- Generator for TU_VERIFY_ERR and TU_VERIFY_ERR_HDLR -------------*/ -#define TU_VERIFY_ERR_DEF2(_error, _handler) do \ -{ \ - uint32_t _err = (uint32_t)(_error); \ - if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; } \ -} while(0) - -#define TU_VERIFY_ERR_DEF3(_error, _handler, _ret) do \ -{ \ - uint32_t _err = (uint32_t)(_error); \ - if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; } \ -} while(0) - -/*------------------------------------------------------------------*/ -/* ASSERT Error - * basically TU_VERIFY Error with TU_BREAKPOINT() as handler - *------------------------------------------------------------------*/ -#define ASSERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, TU_BREAKPOINT()) -#define ASSERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, TU_BREAKPOINT(), _ret) - -#ifndef TU_ASSERT_ERR -#define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_ERR_2ARGS, ASSERT_ERR_1ARGS,UNUSED)(__VA_ARGS__) -#endif - -/*------------------------------------------------------------------*/ -/* ASSERT HDLR - *------------------------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif /* TUSB_VERIFY_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h deleted file mode 100644 index c042cc708..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DCD_H_ -#define _TUSB_DCD_H_ - -#include "common/tusb_common.h" -#include "osal/osal.h" -#include "common/tusb_fifo.h" -#include "dcd_attr.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Configuration -//--------------------------------------------------------------------+ - -#ifndef CFG_TUD_ENDPPOINT_MAX - #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES -//--------------------------------------------------------------------+ - -typedef enum -{ - DCD_EVENT_INVALID = 0, - DCD_EVENT_BUS_RESET, - DCD_EVENT_UNPLUGGED, - DCD_EVENT_SOF, - DCD_EVENT_SUSPEND, // TODO LPM Sleep L1 support - DCD_EVENT_RESUME, - - DCD_EVENT_SETUP_RECEIVED, - DCD_EVENT_XFER_COMPLETE, - - // Not an DCD event, just a convenient way to defer ISR function - USBD_EVENT_FUNC_CALL, - - DCD_EVENT_COUNT -} dcd_eventid_t; - -typedef struct TU_ATTR_ALIGNED(4) -{ - uint8_t rhport; - uint8_t event_id; - - union - { - // BUS RESET - struct { - tusb_speed_t speed; - } bus_reset; - - // SETUP_RECEIVED - tusb_control_request_t setup_received; - - // XFER_COMPLETE - struct { - uint8_t ep_addr; - uint8_t result; - uint32_t len; - }xfer_complete; - - // FUNC_CALL - struct { - void (*func) (void*); - void* param; - }func_call; - }; -} dcd_event_t; - -//TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); - -//--------------------------------------------------------------------+ -// Controller API -//--------------------------------------------------------------------+ - -// Initialize controller to device mode -void dcd_init (uint8_t rhport); - -// Interrupt Handler -#if __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wredundant-decls" -#endif -void dcd_int_handler(uint8_t rhport); -#if __GNUC__ -#pragma GCC diagnostic pop -#endif - -// Enable device interrupt -void dcd_int_enable (uint8_t rhport); - -// Disable device interrupt -void dcd_int_disable(uint8_t rhport); - -// Receive Set Address request, mcu port must also include status IN response -void dcd_set_address(uint8_t rhport, uint8_t dev_addr); - -// Wake up host -void dcd_remote_wakeup(uint8_t rhport); - -// Connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; - -// Disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; - -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// Invoked when a control transfer's status stage is complete. -// May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; - -// Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); - -// Close all non-control endpoints, cancel all pending transfers if any. -// Invoked when switching from a non-zero Configuration by SET_CONFIGURE therefore -// required for multiple configuration support. -void dcd_edpt_close_all (uint8_t rhport); - -// Close an endpoint. -// Since it is weak, caller must TU_ASSERT this function's existence before calling it. -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; - -// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack -// This API is optional, may be useful for register-based for transferring data. -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; - -// Stall endpoint, any queuing transfer should be removed from endpoint -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); - -// clear stall, data toggle is also reset to DATA0 -// This API never calls with control endpoints, since it is auto cleared when receiving setup packet -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); - -//--------------------------------------------------------------------+ -// Event API (implemented by stack) -//--------------------------------------------------------------------+ - -// Called by DCD to notify device stack -extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); - -// helper to send bus signal event -extern void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr); - -// helper to send bus reset event -extern void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr); - -// helper to send setup received -extern void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr); - -// helper to send transfer complete event -extern void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DCD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h deleted file mode 100644 index b40c2ad07..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_DCD_ATTR_H_ -#define TUSB_DCD_ATTR_H_ - -#include "tusb_option.h" - -// Attribute includes -// - ENDPOINT_MAX: max (logical) number of endpoint -// - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed, -// e.g EP1 OUT & EP1 IN cannot exist together -// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. - -//------------- NXP -------------// -#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) - #define DCD_ATTR_ENDPOINT_MAX 5 - -#elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) - #define DCD_ATTR_ENDPOINT_MAX 16 - -#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) - // TODO USB0 has 6, USB1 has 4 - #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS - #define DCD_ATTR_ENDPOINT_MAX 6 - -#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) - #define DCD_ATTR_ENDPOINT_MAX 5 - -#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) - // TODO USB0 has 5, USB1 has 6 - #define DCD_ATTR_ENDPOINT_MAX 6 - -#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) - // TODO USB0 has 5, USB1 has 6 - #define DCD_ATTR_ENDPOINT_MAX 6 - -#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX) - #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX, OPT_MCU_K32L2BXX) - #define DCD_ATTR_ENDPOINT_MAX 16 - -#elif TU_CHECK_MCU(OPT_MCU_MM32F327X) - #define DCD_ATTR_ENDPOINT_MAX 16 - -//------------- Nordic -------------// -#elif TU_CHECK_MCU(OPT_MCU_NRF5X) - // 8 CBI + 1 ISO - #define DCD_ATTR_ENDPOINT_MAX 9 - -//------------- Microchip -------------// -#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ - TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_SAMG) - #define DCD_ATTR_ENDPOINT_MAX 6 - #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER - -#elif TU_CHECK_MCU(OPT_MCU_SAMX7X) - #define DCD_ATTR_ENDPOINT_MAX 10 - #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER - -#elif TU_CHECK_MCU(OPT_MCU_PIC32MZ) - #define DCD_ATTR_ENDPOINT_MAX 8 - #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER - -//------------- ST -------------// -#elif TU_CHECK_MCU(OPT_MCU_STM32F0) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32F1) - #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ - defined (STM32F107xB) || defined (STM32F107xC) - #define DCD_ATTR_ENDPOINT_MAX 4 - #define DCD_ATTR_DWC2_STM32 - #else - #define DCD_ATTR_ENDPOINT_MAX 8 - #endif - -#elif TU_CHECK_MCU(OPT_MCU_STM32F2) - // FS has 4 ep, HS has 5 ep - #define DCD_ATTR_ENDPOINT_MAX 6 - #define DCD_ATTR_DWC2_STM32 - -#elif TU_CHECK_MCU(OPT_MCU_STM32F3) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32F4) - // For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9 - #define DCD_ATTR_ENDPOINT_MAX 6 - #define DCD_ATTR_DWC2_STM32 - -#elif TU_CHECK_MCU(OPT_MCU_STM32F7) - // FS has 6, HS has 9 - #define DCD_ATTR_ENDPOINT_MAX 9 - #define DCD_ATTR_DWC2_STM32 - -#elif TU_CHECK_MCU(OPT_MCU_STM32H7) - #define DCD_ATTR_ENDPOINT_MAX 9 - #define DCD_ATTR_DWC2_STM32 - -#elif TU_CHECK_MCU(OPT_MCU_STM32G4) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32L4) - #if defined (STM32L475xx) || defined (STM32L476xx) || \ - defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ - defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \ - defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ - defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) - #define DCD_ATTR_ENDPOINT_MAX 6 - #define DCD_ATTR_DWC2_STM32 - #else - #define DCD_ATTR_ENDPOINT_MAX 8 - #endif - -//------------- Sony -------------// -#elif TU_CHECK_MCU(OPT_MCU_CXD56) - #define DCD_ATTR_ENDPOINT_MAX 7 - #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER - -//------------- TI -------------// -#elif TU_CHECK_MCU(OPT_MCU_MSP430x5xx) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) - #define DCD_ATTR_ENDPOINT_MAX 8 - -//------------- ValentyUSB -------------// -#elif TU_CHECK_MCU(OPT_MCU_VALENTYUSB_EPTRI) - #define DCD_ATTR_ENDPOINT_MAX 16 - -//------------- Nuvoton -------------// -#elif TU_CHECK_MCU(OPT_MCU_NUC121, OPT_MCU_NUC126) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_NUC120) - #define DCD_ATTR_ENDPOINT_MAX 6 - -#elif TU_CHECK_MCU(OPT_MCU_NUC505) - #define DCD_ATTR_ENDPOINT_MAX 12 - -//------------- Espressif -------------// -#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - #define DCD_ATTR_ENDPOINT_MAX 6 - -//------------- Dialog -------------// -#elif TU_CHECK_MCU(OPT_MCU_DA1469X) - #define DCD_ATTR_ENDPOINT_MAX 4 - -//------------- Raspberry Pi -------------// -#elif TU_CHECK_MCU(OPT_MCU_RP2040) - #define DCD_ATTR_ENDPOINT_MAX 16 - -//------------- Silabs -------------// -#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) - #define DCD_ATTR_ENDPOINT_MAX 7 - -//------------- Renesas -------------// -#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) - #define DCD_ATTR_ENDPOINT_MAX 10 - -//------------- GigaDevice -------------// -#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) - #define DCD_ATTR_ENDPOINT_MAX 4 - -//------------- Broadcom -------------// -#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) - #define DCD_ATTR_ENDPOINT_MAX 8 - -//------------- Broadcom -------------// -#elif TU_CHECK_MCU(OPT_MCU_XMC4000) - #define DCD_ATTR_ENDPOINT_MAX 8 - -//------------- BridgeTek -------------// -#elif TU_CHECK_MCU(OPT_MCU_FT90X) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_FT93X) - #define DCD_ATTR_ENDPOINT_MAX 16 - -#else - #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" - #define DCD_ATTR_ENDPOINT_MAX 8 -#endif - -// Default to fullspeed if not defined -//#ifndef PORT_HIGHSPEED -// #define DCD_ATTR_PORT_HIGHSPEED 0x00 -//#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c deleted file mode 100644 index 6a5210b34..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c +++ /dev/null @@ -1,1419 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_DEVICE_ENABLED - -#include "tusb.h" -#include "device/usbd.h" -#include "device/usbd_pvt.h" -#include "device/dcd.h" - -//--------------------------------------------------------------------+ -// USBD Configuration -//--------------------------------------------------------------------+ - -// Debug level of USBD -#define USBD_DBG 2 - -#ifndef CFG_TUD_TASK_QUEUE_SZ - #define CFG_TUD_TASK_QUEUE_SZ 16 -#endif - -//--------------------------------------------------------------------+ -// Device Data -//--------------------------------------------------------------------+ - -// Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xFFu }; - -typedef struct -{ - struct TU_ATTR_PACKED - { - volatile uint8_t connected : 1; - volatile uint8_t addressed : 1; - volatile uint8_t suspended : 1; - - uint8_t remote_wakeup_en : 1; // enable/disable by host - uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute - uint8_t self_powered : 1; // configuration descriptor's attribute - }; - - volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) - uint8_t speed; - - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) - - struct TU_ATTR_PACKED - { - volatile bool busy : 1; - volatile bool stalled : 1; - volatile bool claimed : 1; - - // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUD_ENDPPOINT_MAX][2]; - -}usbd_device_t; - -static usbd_device_t _usbd_dev; - -//--------------------------------------------------------------------+ -// Class Driver -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - #define DRIVER_NAME(_name) .name = _name, -#else - #define DRIVER_NAME(_name) -#endif - -// Built-in class drivers -static usbd_class_driver_t const _usbd_driver[] = -{ - #if CFG_TUD_CDC - { - DRIVER_NAME("CDC") - .init = cdcd_init, - .reset = cdcd_reset, - .open = cdcd_open, - .control_xfer_cb = cdcd_control_xfer_cb, - .xfer_cb = cdcd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_MSC - { - DRIVER_NAME("MSC") - .init = mscd_init, - .reset = mscd_reset, - .open = mscd_open, - .control_xfer_cb = mscd_control_xfer_cb, - .xfer_cb = mscd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_HID - { - DRIVER_NAME("HID") - .init = hidd_init, - .reset = hidd_reset, - .open = hidd_open, - .control_xfer_cb = hidd_control_xfer_cb, - .xfer_cb = hidd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_AUDIO - { - DRIVER_NAME("AUDIO") - .init = audiod_init, - .reset = audiod_reset, - .open = audiod_open, - .control_xfer_cb = audiod_control_xfer_cb, - .xfer_cb = audiod_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_VIDEO - { - DRIVER_NAME("VIDEO") - .init = videod_init, - .reset = videod_reset, - .open = videod_open, - .control_xfer_cb = videod_control_xfer_cb, - .xfer_cb = videod_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_MIDI - { - DRIVER_NAME("MIDI") - .init = midid_init, - .open = midid_open, - .reset = midid_reset, - .control_xfer_cb = midid_control_xfer_cb, - .xfer_cb = midid_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_VENDOR - { - DRIVER_NAME("VENDOR") - .init = vendord_init, - .reset = vendord_reset, - .open = vendord_open, - .control_xfer_cb = tud_vendor_control_xfer_cb, - .xfer_cb = vendord_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_USBTMC - { - DRIVER_NAME("TMC") - .init = usbtmcd_init_cb, - .reset = usbtmcd_reset_cb, - .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_xfer_cb, - .xfer_cb = usbtmcd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_DFU_RUNTIME - { - DRIVER_NAME("DFU-RUNTIME") - .init = dfu_rtd_init, - .reset = dfu_rtd_reset, - .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - - #if CFG_TUD_DFU - { - DRIVER_NAME("DFU") - .init = dfu_moded_init, - .reset = dfu_moded_reset, - .open = dfu_moded_open, - .control_xfer_cb = dfu_moded_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - - #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM - { - DRIVER_NAME("NET") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_xfer_cb = netd_control_xfer_cb, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, - #endif - - #if CFG_TUD_BTH - { - DRIVER_NAME("BTH") - .init = btd_init, - .reset = btd_reset, - .open = btd_open, - .control_xfer_cb = btd_control_xfer_cb, - .xfer_cb = btd_xfer_cb, - .sof = NULL - }, - #endif -}; - -enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; - -// Additional class drivers implemented by application -static usbd_class_driver_t const * _app_driver = NULL; -static uint8_t _app_driver_count = 0; - -// virtually joins built-in and application drivers together. -// Application is positioned first to allow overwriting built-in ones. -static inline usbd_class_driver_t const * get_driver(uint8_t drvid) -{ - // Application drivers - if ( usbd_app_driver_get_cb ) - { - if ( drvid < _app_driver_count ) return &_app_driver[drvid]; - drvid -= _app_driver_count; - } - - // Built-in drivers - if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; - - return NULL; -} - -#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) - -//--------------------------------------------------------------------+ -// DCD Event -//--------------------------------------------------------------------+ - -static bool _usbd_initialized = false; - -// Event queue -// OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) -OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); -static osal_queue_t _usbd_q; - -// Mutex for claiming endpoint, only needed when using with preempted RTOS -#if CFG_TUSB_OS != OPT_OS_NONE -static osal_mutex_def_t _ubsd_mutexdef; -static osal_mutex_t _usbd_mutex; -#endif - - -//--------------------------------------------------------------------+ -// Prototypes -//--------------------------------------------------------------------+ -static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); -static bool process_set_config(uint8_t rhport, uint8_t cfg_num); -static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); - -// from usbd_control.c -void usbd_control_reset(void); -void usbd_control_set_request(tusb_control_request_t const *request); -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 -static char const* const _usbd_event_str[DCD_EVENT_COUNT] = -{ - "Invalid" , - "Bus Reset" , - "Unplugged" , - "SOF" , - "Suspend" , - "Resume" , - "Setup Received" , - "Xfer Complete" , - "Func Call" -}; - -static char const* const _tusb_std_request_str[] = -{ - "Get Status" , - "Clear Feature" , - "Reserved" , - "Set Feature" , - "Reserved" , - "Set Address" , - "Get Descriptor" , - "Set Descriptor" , - "Get Configuration" , - "Set Configuration" , - "Get Interface" , - "Set Interface" , - "Synch Frame" -}; - -static char const* const _tusb_speed_str[] = { "Full", "Low", "High" }; - -// for usbd_control to print the name of control complete driver -void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) -{ - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - if ( driver->control_xfer_cb == callback ) - { - TU_LOG2(" %s control complete\r\n", driver->name); - return; - } - } -} - -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ -tusb_speed_t tud_speed_get(void) -{ - return (tusb_speed_t) _usbd_dev.speed; -} - -bool tud_connected(void) -{ - return _usbd_dev.connected; -} - -bool tud_mounted(void) -{ - return _usbd_dev.cfg_num ? true : false; -} - -bool tud_suspended(void) -{ - return _usbd_dev.suspended; -} - -bool tud_remote_wakeup(void) -{ - // only wake up host if this feature is supported and enabled and we are suspended - TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en ); - dcd_remote_wakeup(TUD_OPT_RHPORT); - return true; -} - -bool tud_disconnect(void) -{ - TU_VERIFY(dcd_disconnect); - dcd_disconnect(TUD_OPT_RHPORT); - return true; -} - -bool tud_connect(void) -{ - TU_VERIFY(dcd_connect); - dcd_connect(TUD_OPT_RHPORT); - return true; -} - -//--------------------------------------------------------------------+ -// USBD Task -//--------------------------------------------------------------------+ -bool tud_inited(void) -{ - return _usbd_initialized; -} - -bool tud_init (uint8_t rhport) -{ - // skip if already initialized - if (_usbd_initialized) return _usbd_initialized; - - TU_LOG2("USBD init\r\n"); - - tu_varclr(&_usbd_dev); - -#if CFG_TUSB_OS != OPT_OS_NONE - // Init device mutex - _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef); - TU_ASSERT(_usbd_mutex); -#endif - - // Init device queue & task - _usbd_q = osal_queue_create(&_usbd_qdef); - TU_ASSERT(_usbd_q); - - // Get application driver if available - if ( usbd_app_driver_get_cb ) - { - _app_driver = usbd_app_driver_get_cb(&_app_driver_count); - } - - // Init class drivers - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - TU_LOG2("%s init\r\n", driver->name); - driver->init(); - } - - // Init device controller driver - dcd_init(rhport); - dcd_int_enable(rhport); - - _usbd_initialized = true; - - return true; -} - -static void configuration_reset(uint8_t rhport) -{ - for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) - { - get_driver(i)->reset(rhport); - } - - tu_varclr(&_usbd_dev); - memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping -} - -static void usbd_reset(uint8_t rhport) -{ - configuration_reset(rhport); - usbd_control_reset(); -} - -bool tud_task_event_ready(void) -{ - // Skip if stack is not initialized - if ( !tusb_inited() ) return false; - - return !osal_queue_empty(_usbd_q); -} - -/* USB Device Driver task - * This top level thread manages all device controller event and delegates events to class-specific drivers. - * This should be called periodically within the mainloop or rtos thread. - * - @code - int main(void) - { - application_init(); - tusb_init(); - - while(1) // the mainloop - { - application_code(); - tud_task(); // tinyusb device task - } - } - @endcode - */ -void tud_task (void) -{ - // Skip if stack is not initialized - if ( !tusb_inited() ) return; - - // Loop until there is no more events in the queue - while (1) - { - dcd_event_t event; - - if ( !osal_queue_receive(_usbd_q, &event) ) return; - -#if CFG_TUSB_DEBUG >= 2 - if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG2("\r\n"); // extra line for setup - TU_LOG2("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); -#endif - - switch ( event.event_id ) - { - case DCD_EVENT_BUS_RESET: - TU_LOG2(": %s Speed\r\n", _tusb_speed_str[event.bus_reset.speed]); - usbd_reset(event.rhport); - _usbd_dev.speed = event.bus_reset.speed; - break; - - case DCD_EVENT_UNPLUGGED: - TU_LOG2("\r\n"); - usbd_reset(event.rhport); - - // invoke callback - if (tud_umount_cb) tud_umount_cb(); - break; - - case DCD_EVENT_SETUP_RECEIVED: - TU_LOG2_VAR(&event.setup_received); - TU_LOG2("\r\n"); - - // Mark as connected after receiving 1st setup packet. - // But it is easier to set it every time instead of wasting time to check then set - _usbd_dev.connected = 1; - - // mark both in & out control as free - _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false; - _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0; - _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false; - _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0; - - // Process control request - if ( !process_control_request(event.rhport, &event.setup_received) ) - { - TU_LOG2(" Stall EP0\r\n"); - // Failed -> stall both control endpoint IN and OUT - dcd_edpt_stall(event.rhport, 0); - dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK); - } - break; - - case DCD_EVENT_XFER_COMPLETE: - { - // Invoke the class callback associated with the endpoint address - uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - - _usbd_dev.ep_status[epnum][ep_dir].busy = false; - _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; - - if ( 0 == epnum ) - { - usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); - } - else - { - usbd_class_driver_t const * driver = get_driver( _usbd_dev.ep2drv[epnum][ep_dir] ); - TU_ASSERT(driver, ); - - TU_LOG2(" %s xfer callback\r\n", driver->name); - driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); - } - } - break; - - case DCD_EVENT_SUSPEND: - // NOTE: When plugging/unplugging device, the D+/D- state are unstable and - // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event - // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected - if ( _usbd_dev.connected ) - { - TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); - if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); - }else - { - TU_LOG2(" Skipped\r\n"); - } - break; - - case DCD_EVENT_RESUME: - if ( _usbd_dev.connected ) - { - TU_LOG2("\r\n"); - if (tud_resume_cb) tud_resume_cb(); - }else - { - TU_LOG2(" Skipped\r\n"); - } - break; - - case DCD_EVENT_SOF: - TU_LOG2("\r\n"); - for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) - { - usbd_class_driver_t const * driver = get_driver(i); - if ( driver->sof ) driver->sof(event.rhport); - } - break; - - case USBD_EVENT_FUNC_CALL: - TU_LOG2("\r\n"); - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; - - default: - TU_BREAKPOINT(); - break; - } - } -} - -//--------------------------------------------------------------------+ -// Control Request Parser & Handling -//--------------------------------------------------------------------+ - -// Helper to invoke class driver control request handler -static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) -{ - usbd_control_set_complete_callback(driver->control_xfer_cb); - TU_LOG2(" %s control request\r\n", driver->name); - return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request); -} - -// This handles the actual request and its response. -// return false will cause its caller to stall control endpoint -static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ - usbd_control_set_complete_callback(NULL); - - TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); - - // Vendor request - if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) - { - TU_VERIFY(tud_vendor_control_xfer_cb); - - usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); - return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); - } - -#if CFG_TUSB_DEBUG >= 2 - if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) - { - TU_LOG2(" %s", _tusb_std_request_str[p_request->bRequest]); - if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG2("\r\n"); - } -#endif - - switch ( p_request->bmRequestType_bit.recipient ) - { - //------------- Device Requests e.g in enumeration -------------// - case TUSB_REQ_RCPT_DEVICE: - if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) - { - uint8_t const itf = tu_u16_low(p_request->wIndex); - TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); - - usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]); - TU_VERIFY(driver); - - // forward to class driver: "non-STD request to Interface" - return invoke_class_control(rhport, driver, p_request); - } - - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) - { - // Non standard request is not supported - TU_BREAKPOINT(); - return false; - } - - switch ( p_request->bRequest ) - { - case TUSB_REQ_SET_ADDRESS: - // Depending on mcu, status phase could be sent either before or after changing device address, - // or even require stack to not response with status at all - // Therefore DCD must take full responsibility to response and include zlp status packet if needed. - usbd_control_set_request(p_request); // set request since DCD has no access to tud_control_status() API - dcd_set_address(rhport, (uint8_t) p_request->wValue); - // skip tud_control_status() - _usbd_dev.addressed = 1; - break; - - case TUSB_REQ_GET_CONFIGURATION: - { - uint8_t cfg_num = _usbd_dev.cfg_num; - tud_control_xfer(rhport, p_request, &cfg_num, 1); - } - break; - - case TUSB_REQ_SET_CONFIGURATION: - { - uint8_t const cfg_num = (uint8_t) p_request->wValue; - - // Only process if new configure is different - if (_usbd_dev.cfg_num != cfg_num) - { - if ( _usbd_dev.cfg_num ) - { - // already configured: need to clear all endpoints and driver first - TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); - - // close all non-control endpoints, cancel all pending transfers if any - dcd_edpt_close_all(rhport); - - // close all drivers and current configured state except bus speed - uint8_t const speed = _usbd_dev.speed; - configuration_reset(rhport); - - _usbd_dev.speed = speed; // restore speed - } - - // switch to new configuration if not zero - if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - } - - _usbd_dev.cfg_num = cfg_num; - tud_control_status(rhport, p_request); - } - break; - - case TUSB_REQ_GET_DESCRIPTOR: - TU_VERIFY( process_get_descriptor(rhport, p_request) ); - break; - - case TUSB_REQ_SET_FEATURE: - // Only support remote wakeup for device feature - TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - - TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n"); - - // Host may enable remote wake up before suspending especially HID device - _usbd_dev.remote_wakeup_en = true; - tud_control_status(rhport, p_request); - break; - - case TUSB_REQ_CLEAR_FEATURE: - // Only support remote wakeup for device feature - TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - - TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n"); - - // Host may disable remote wake up after resuming - _usbd_dev.remote_wakeup_en = false; - tud_control_status(rhport, p_request); - break; - - case TUSB_REQ_GET_STATUS: - { - // Device status bit mask - // - Bit 0: Self Powered - // - Bit 1: Remote Wakeup enabled - uint16_t status = (_usbd_dev.self_powered ? 1 : 0) | (_usbd_dev.remote_wakeup_en ? 2 : 0); - tud_control_xfer(rhport, p_request, &status, 2); - } - break; - - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - break; - - //------------- Class/Interface Specific Request -------------// - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t const itf = tu_u16_low(p_request->wIndex); - TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); - - usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]); - TU_VERIFY(driver); - - // all requests to Interface (STD or Class) is forwarded to class driver. - // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - if ( !invoke_class_control(rhport, driver, p_request) ) - { - // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class - // driver doesn't use alternate settings or implement this - TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - - switch(p_request->bRequest) - { - case TUSB_REQ_GET_INTERFACE: - case TUSB_REQ_SET_INTERFACE: - // Clear complete callback if driver set since it can also stall the request. - usbd_control_set_complete_callback(NULL); - - if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) - { - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); - }else - { - tud_control_status(rhport, p_request); - } - break; - - default: return false; - } - } - } - break; - - //------------- Endpoint Request -------------// - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t const ep_addr = tu_u16_low(p_request->wIndex); - uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); - - usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) - { - // Forward class request to its driver - TU_VERIFY(driver); - return invoke_class_control(rhport, driver, p_request); - } - else - { - // Handle STD request to endpoint - switch ( p_request->bRequest ) - { - case TUSB_REQ_GET_STATUS: - { - uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000; - tud_control_xfer(rhport, p_request, &status, 2); - } - break; - - case TUSB_REQ_CLEAR_FEATURE: - case TUSB_REQ_SET_FEATURE: - { - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) - { - usbd_edpt_clear_stall(rhport, ep_addr); - }else - { - usbd_edpt_stall(rhport, ep_addr); - } - } - - if (driver) - { - // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request - // We will also forward std request targeted endpoint to class drivers as well - - // STD request must always be ACKed regardless of driver returned value - // Also clear complete callback if driver set since it can also stall the request. - (void) invoke_class_control(rhport, driver, p_request); - usbd_control_set_complete_callback(NULL); - - // skip ZLP status if driver already did that - if ( !_usbd_dev.ep_status[0][TUSB_DIR_IN].busy ) tud_control_status(rhport, p_request); - } - } - break; - - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - } - } - break; - - // Unknown recipient - default: TU_BREAKPOINT(); return false; - } - - return true; -} - -// Process Set Configure Request -// This function parse configuration descriptor & open drivers accordingly -static bool process_set_config(uint8_t rhport, uint8_t cfg_num) -{ - // index is cfg_num-1 - tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); - TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); - - // Parse configuration descriptor - _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; - _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED ) ? 1 : 0; - - // Parse interface descriptor - uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); - uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); - - while( p_desc < desc_end ) - { - uint8_t assoc_itf_count = 1; - - // Class will always starts with Interface Association (if any) and then Interface descriptor - if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) - { - tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; - assoc_itf_count = desc_iad->bInterfaceCount; - - p_desc = tu_desc_next(p_desc); // next to Interface - - // IAD's first interface number and class should match with opened interface - //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && - // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - } - - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; - - // Find driver for this interface - uint16_t const remaining_len = desc_end-p_desc; - uint8_t drv_id; - for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) - { - usbd_class_driver_t const *driver = get_driver(drv_id); - uint16_t const drv_len = driver->open(rhport, desc_itf, remaining_len); - - if ( (sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len) ) - { - // Open successfully - TU_LOG2(" %s opened\r\n", driver->name); - - // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or - // BTH (even CDC) with class in device descriptor (single interface) - if ( assoc_itf_count == 1) - { - #if CFG_TUD_CDC - if ( driver->open == cdcd_open ) assoc_itf_count = 2; - #endif - - #if CFG_TUD_MIDI - if ( driver->open == midid_open ) assoc_itf_count = 2; - #endif - - #if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT - if ( driver->open == btd_open ) assoc_itf_count = 2; - #endif - } - - // bind (associated) interfaces to found driver - for(uint8_t i=0; ibInterfaceNumber+i; - - // Interface number must not be used already - TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[itf_num]); - _usbd_dev.itf2drv[itf_num] = drv_id; - } - - // bind all endpoints to found driver - tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); - - // next Interface - p_desc += drv_len; - - break; // exit driver find loop - } - } - - // Failed if there is no supported drivers - TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT); - } - - // invoke callback - if (tud_mount_cb) tud_mount_cb(); - - return true; -} - -// return descriptor's buffer and update desc_len -static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request) -{ - tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue); - uint8_t const desc_index = tu_u16_low( p_request->wValue ); - - switch(desc_type) - { - case TUSB_DESC_DEVICE: - { - TU_LOG2(" Device\r\n"); - - void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb(); - - // Only response with exactly 1 Packet if: not addressed and host requested more data than device descriptor has. - // This only happens with the very first get device descriptor and EP0 size = 8 or 16. - if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed && - ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t)) - { - // Hack here: we modify the request length to prevent usbd_control response with zlp - // since we are responding with 1 packet & less data than wLength. - tusb_control_request_t mod_request = *p_request; - mod_request.wLength = CFG_TUD_ENDPOINT0_SIZE; - - return tud_control_xfer(rhport, &mod_request, desc_device, CFG_TUD_ENDPOINT0_SIZE); - }else - { - return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t)); - } - } - break; - - case TUSB_DESC_BOS: - { - TU_LOG2(" BOS\r\n"); - - // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) - if (!tud_descriptor_bos_cb) return false; - - uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb(); - TU_ASSERT(desc_bos); - - // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) ); - - return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); - } - break; - - case TUSB_DESC_CONFIGURATION: - case TUSB_DESC_OTHER_SPEED_CONFIG: - { - uintptr_t desc_config; - - if ( desc_type == TUSB_DESC_CONFIGURATION ) - { - TU_LOG2(" Configuration[%u]\r\n", desc_index); - desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); - }else - { - // Host only request this after getting Device Qualifier descriptor - TU_LOG2(" Other Speed Configuration\r\n"); - TU_VERIFY( tud_descriptor_other_speed_configuration_cb ); - desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); - } - - TU_ASSERT(desc_config); - - // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))) ); - - return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); - } - break; - - case TUSB_DESC_STRING: - { - TU_LOG2(" String[%u]\r\n", desc_index); - - // String Descriptor always uses the desc set from user - uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, tu_le16toh(p_request->wIndex)); - TU_VERIFY(desc_str); - - // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_str, tu_desc_len(desc_str)); - } - break; - - case TUSB_DESC_DEVICE_QUALIFIER: - { - TU_LOG2(" Device Qualifier\r\n"); - - TU_VERIFY( tud_descriptor_device_qualifier_cb ); - - uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); - TU_VERIFY(desc_qualifier); - - // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier)); - } - break; - - default: return false; - } -} - -//--------------------------------------------------------------------+ -// DCD Event Handler -//--------------------------------------------------------------------+ -void dcd_event_handler(dcd_event_t const * event, bool in_isr) -{ - switch (event->event_id) - { - case DCD_EVENT_UNPLUGGED: - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); - break; - - case DCD_EVENT_SUSPEND: - // NOTE: When plugging/unplugging device, the D+/D- state are unstable and - // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). - // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish - // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected - if ( _usbd_dev.connected ) - { - _usbd_dev.suspended = 1; - osal_queue_send(_usbd_q, event, in_isr); - } - break; - - case DCD_EVENT_RESUME: - // skip event if not connected (especially required for SAMD) - if ( _usbd_dev.connected ) - { - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); - } - break; - - case DCD_EVENT_SOF: - // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup - // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational - if ( _usbd_dev.suspended ) - { - _usbd_dev.suspended = 0; - dcd_event_t const event_resume = { .rhport = event->rhport, .event_id = DCD_EVENT_RESUME }; - osal_queue_send(_usbd_q, &event_resume, in_isr); - } - break; - - default: - osal_queue_send(_usbd_q, event, in_isr); - break; - } -} - -void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) -{ - dcd_event_t event = { .rhport = rhport, .event_id = eid }; - dcd_event_handler(&event, in_isr); -} - -void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) -{ - dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET }; - event.bus_reset.speed = speed; - dcd_event_handler(&event, in_isr); -} - -void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) -{ - dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED }; - memcpy(&event.setup_received, setup, 8); - - dcd_event_handler(&event, in_isr); -} - -void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) -{ - dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE }; - - event.xfer_complete.ep_addr = ep_addr; - event.xfer_complete.len = xferred_bytes; - event.xfer_complete.result = result; - - dcd_event_handler(&event, in_isr); -} - -//--------------------------------------------------------------------+ -// USBD API For Class Driver -//--------------------------------------------------------------------+ - -// Parse consecutive endpoint descriptors (IN & OUT) -bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in) -{ - for(int i=0; ibDescriptorType && xfer_type == desc_ep->bmAttributes.xfer); - TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); - - if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) - { - (*ep_in) = desc_ep->bEndpointAddress; - }else - { - (*ep_out) = desc_ep->bEndpointAddress; - } - - p_desc = tu_desc_next(p_desc); - } - - return true; -} - -// Helper to defer an isr function -void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) -{ - dcd_event_t event = - { - .rhport = 0, - .event_id = USBD_EVENT_FUNC_CALL, - }; - - event.func_call.func = func; - event.func_call.param = param; - - dcd_event_handler(&event, in_isr); -} - -//--------------------------------------------------------------------+ -// USBD Endpoint API -//--------------------------------------------------------------------+ - -bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) -{ - TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); - - return dcd_edpt_open(rhport, desc_ep); -} - -bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - // TODO add this check later, also make sure we don't starve an out endpoint while suspending - // TU_VERIFY(tud_ready()); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - -#if CFG_TUSB_OS != OPT_OS_NONE - // pre-check to help reducing mutex lock - TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only claim the endpoint if it is not busy and not claimed yet. - bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); - if (ret) - { - _usbd_dev.ep_status[epnum][dir].claimed = 1; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(_usbd_mutex); -#endif - - return ret; -} - -bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only release the endpoint if it is claimed and not busy - bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); - if (ret) - { - _usbd_dev.ep_status[epnum][dir].claimed = 0; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(_usbd_mutex); -#endif - - return ret; -} - -bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // TODO skip ready() check for now since enumeration also use this API - // TU_VERIFY(tud_ready()); - - TU_LOG2(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() - // could return and USBD task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; - - if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) - { - return true; - }else - { - // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG2("FAILED\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -// The number of bytes has to be given explicitly to allow more flexible control of how many -// bytes should be written and second to keep the return value free to give back a boolean -// success message. If total_bytes is too big, the FIFO will copy only what is available -// into the USB buffer! -bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return - // and usbd task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; - - if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) - { - TU_LOG2("OK\r\n"); - return true; - }else - { - // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - return _usbd_dev.ep_status[epnum][dir].busy; -} - -void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // only stalled if currently cleared - if ( !_usbd_dev.ep_status[epnum][dir].stalled ) - { - TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr); - dcd_edpt_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = true; - _usbd_dev.ep_status[epnum][dir].busy = true; - } -} - -void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // only clear if currently stalled - if ( _usbd_dev.ep_status[epnum][dir].stalled ) - { - TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr); - dcd_edpt_clear_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - } -} - -bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - return _usbd_dev.ep_status[epnum][dir].stalled; -} - -/** - * usbd_edpt_close will disable an endpoint. - * - * In progress transfers on this EP may be delivered after this call. - * - */ -void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - TU_ASSERT(dcd_edpt_close, /**/); - TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - dcd_edpt_close(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = false; - - return; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h deleted file mode 100644 index ec34817fa..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h +++ /dev/null @@ -1,853 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBD_H_ -#define _TUSB_USBD_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Init device stack -bool tud_init (uint8_t rhport); - -// Check if device stack is already initialized -bool tud_inited(void); - -// Task function should be called in main/rtos loop -void tud_task (void); - -// Check if there is pending events need proccessing by tud_task() -bool tud_task_event_ready(void); - -// Interrupt handler, name alias to DCD -extern void dcd_int_handler(uint8_t rhport); -#define tud_int_handler dcd_int_handler - -// Get current bus speed -tusb_speed_t tud_speed_get(void); - -// Check if device is connected (may not mounted/configured yet) -// True if just got out of Bus Reset and received the very first data from host -bool tud_connected(void); - -// Check if device is connected and configured -bool tud_mounted(void); - -// Check if device is suspended -bool tud_suspended(void); - -// Check if device is ready to transfer -TU_ATTR_ALWAYS_INLINE static inline -bool tud_ready(void) -{ - return tud_mounted() && !tud_suspended(); -} - -// Remote wake up host, only if suspended and enabled by host -bool tud_remote_wakeup(void); - -// Enable pull-up resistor on D+ D- -// Return false on unsupported MCUs -bool tud_disconnect(void); - -// Disable pull-up resistor on D+ D- -// Return false on unsupported MCUs -bool tud_connect(void); - -// Carry out Data and Status stage of control transfer -// - If len = 0, it is equivalent to sending status only -// - If len > wLength : it will be truncated -bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len); - -// Send STATUS (zero length) packet -bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// Invoked when received GET DEVICE DESCRIPTOR request -// Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void); - -// Invoked when received GET CONFIGURATION DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index); - -// Invoked when received GET STRING DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); - -// Invoked when received GET BOS DESCRIPTOR request -// Application return pointer to descriptor -TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); - -// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. -// device_qualifier descriptor describes information about a high-speed capable device that would -// change if the device were operating at the other speed. If not highspeed capable stall this request. -TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); - -// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index); - -// Invoked when device is mounted (configured) -TU_ATTR_WEAK void tud_mount_cb(void); - -// Invoked when device is unmounted -TU_ATTR_WEAK void tud_umount_cb(void); - -// Invoked when usb bus is suspended -// Within 7ms, device must draw an average of current less than 2.5 mA from bus -TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); - -// Invoked when usb bus is resumed -TU_ATTR_WEAK void tud_resume_cb(void); - -// Invoked when received control request with VENDOR TYPE -TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Binary Device Object Store (BOS) Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_BOS_DESC_LEN 5 - -// total length, number of device caps -#define TUD_BOS_DESCRIPTOR(_total_len, _caps_num) \ - 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num - -// Device Capability Platform 128-bit UUID + Data -#define TUD_BOS_PLATFORM_DESCRIPTOR(...) \ - 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ - -//------------- WebUSB BOS Platform -------------// - -// Descriptor Length -#define TUD_BOS_WEBUSB_DESC_LEN 24 - -// Vendor Code, iLandingPage -#define TUD_BOS_WEBUSB_DESCRIPTOR(_vendor_code, _ipage) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) - -#define TUD_BOS_WEBUSB_UUID \ - 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ - 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 - -//------------- Microsoft OS 2.0 Platform -------------// -#define TUD_BOS_MICROSOFT_OS_DESC_LEN 28 - -// Total Length of descriptor set, vendor code -#define TUD_BOS_MS_OS_20_DESCRIPTOR(_desc_set_len, _vendor_code) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) - -#define TUD_BOS_MS_OS_20_UUID \ - 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ - 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F - -//--------------------------------------------------------------------+ -// Configuration Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_CONFIG_DESC_LEN (9) - -// Config number, interface count, string index, total length, attribute, power in mA -#define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ - 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 - -//--------------------------------------------------------------------+ -// CDC Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 66 bytes -#define TUD_CDC_DESC_LEN (8+9+5+5+4+5+7+9+7+7) - -// CDC Descriptor Template -// Interface number, string index, EP notification address and size, EP data address (out, in) and size. -#define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ - /* CDC Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC Call */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* CDC ACM: support line request */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//--------------------------------------------------------------------+ -// MSC Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 23 bytes -#define TUD_MSC_DESC_LEN (9 + 7 + 7) - -// Interface number, string index, EP Out & EP In address, EP size -#define TUD_MSC_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - - -//--------------------------------------------------------------------+ -// HID Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 25 bytes -#define TUD_HID_DESC_LEN (9 + 9 + 7) - -// HID Input only descriptor -// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval -#define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval - -// Length of template descriptor: 32 bytes -#define TUD_HID_INOUT_DESC_LEN (9 + 9 + 7 + 7) - -// HID Input & Output descriptor -// Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval -#define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval - -//--------------------------------------------------------------------+ -// MIDI Descriptor Templates -// Note: MIDI v1.0 is based on Audio v1.0 -//--------------------------------------------------------------------+ - -#define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) -#define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ - /* Audio Control (AC) Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ - /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ - /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ - /* MS Header */\ - 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) - -#define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 1) - -#define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 2) - -#define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 3) - -#define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 4) - -#define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) -#define TUD_MIDI_DESC_JACK(_cablenum) \ - /* MS In Jack (Embedded) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ - /* MS In Jack (External) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ - /* MS Out Jack (Embedded), connected to In Jack External */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ - /* MS Out Jack (External), connected to In Jack Embedded */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 - -#define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables)) -#define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint: Note Audio v1.0's endpoint has 9 bytes instead of 7 */\ - 9, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, 0, 0, \ - /* MS Endpoint (connected to embedded jack) */\ - (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables - -// Length of template descriptor (88 bytes) -#define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) - -// MIDI simple descriptor -// - 1 Embedded Jack In connected to 1 External Jack Out -// - 1 Embedded Jack out connected to 1 External Jack In -#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ - TUD_MIDI_DESC_JACK(1),\ - TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ - TUD_MIDI_JACKID_IN_EMB(1),\ - TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ - TUD_MIDI_JACKID_OUT_EMB(1) - -//--------------------------------------------------------------------+ -// Audio v2.0 Descriptor Templates -//--------------------------------------------------------------------+ - -/* Standard Interface Association Descriptor (IAD) */ -#define TUD_AUDIO_DESC_IAD_LEN 8 -#define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx - -/* Standard AC Interface Descriptor(4.7.1) */ -#define TUD_AUDIO_DESC_STD_AC_LEN 9 -#define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ - TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx - -/* Class-Specific AC Interface Header Descriptor(4.7.2) */ -#define TUD_AUDIO_DESC_CS_AC_LEN 9 -#define TUD_AUDIO_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO_DESC_CS_AC_LEN, we already do this here*/ \ - TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl - -/* Clock Source Descriptor(4.7.2.1) */ -#define TUD_AUDIO_DESC_CLK_SRC_LEN 8 -#define TUD_AUDIO_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ - TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx - -/* Input Terminal Descriptor(4.7.2.4) */ -#define TUD_AUDIO_DESC_INPUT_TERM_LEN 17 -#define TUD_AUDIO_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ - TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx - -/* Output Terminal Descriptor(4.7.2.5) */ -#define TUD_AUDIO_DESC_OUTPUT_TERM_LEN 12 -#define TUD_AUDIO_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ - TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx - -/* Feature Unit Descriptor(4.7.2.8) */ -// 1 - Channel -#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN 6+(1+1)*4 -#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx - -// 2 - Channels -#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN (6+(2+1)*4) -#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), _stridx -// 4 - Channels -#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN (6+(4+1)*4) -#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _ctrlch3, _ctrlch4, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), U32_TO_U8S_LE(_ctrlch3), U32_TO_U8S_LE(_ctrlch4), _stridx - -// For more channels, add definitions here - -/* Standard AS Interface Descriptor(4.9.1) */ -#define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 -#define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ - TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx - -/* Class-Specific AS Interface Descriptor(4.9.2) */ -#define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 -#define TUD_AUDIO_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ - TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx - -/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ -#define TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN 6 -#define TUD_AUDIO_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution - -/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ -#define TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN 7 -#define TUD_AUDIO_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval - -/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ -#define TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN 8 -#define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ - TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) - -/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ -#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 -#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval - -// AUDIO simple descriptor (UAC2) for 1 microphone input -// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source - -#define TUD_AUDIO_MIC_ONE_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) - -#define TUD_AUDIO_MIC_ONE_CH_DESC_N_AS_INT 1 // Number of AS interfaces - -#define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) - -// AUDIO simple descriptor (UAC2) for 4 microphone input -// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source - -#define TUD_AUDIO_MIC_FOUR_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) - -#define TUD_AUDIO_MIC_FOUR_CH_DESC_N_AS_INT 1 // Number of AS interfaces - -#define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch3*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch4*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) - -// AUDIO simple descriptor (UAC2) for mono speaker -// - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source - -#define TUD_AUDIO_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) - -#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ - /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ - -// Calculate wMaxPacketSize of Endpoints -#define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ - ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) - - -//--------------------------------------------------------------------+ -// USBTMC/USB488 Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) -#define TUD_USBTMC_APP_SUBCLASS 0x03u - -#define TUD_USBTMC_PROTOCOL_STD 0x00u -#define TUD_USBTMC_PROTOCOL_USB488 0x01u - -// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, -// bulk-in endpoint ID -#define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ - /* Interface */ \ - 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx - -#define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u - -#define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ - /* Endpoint Out */ \ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ - /* Endpoint In */ \ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u - -#define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) - -/* optional interrupt endpoint */ \ -// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? -#define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ - 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 - -#define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) - -//--------------------------------------------------------------------+ -// Vendor Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_VENDOR_DESC_LEN (9+7+7) - -// Interface number, string index, EP Out & IN address, EP size -#define TUD_VENDOR_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//--------------------------------------------------------------------+ -// DFU Runtime Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) -#define TUD_DFU_APP_SUBCLASS (APP_SUBCLASS_DFU_RUNTIME) - -// Length of template descriptr: 18 bytes -#define TUD_DFU_RT_DESC_LEN (9 + 9) - -// DFU runtime descriptor -// Interface number, string index, attributes, detach timeout, transfer size -#define TUD_DFU_RT_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ - /* Function */ \ - 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) - -//--------------------------------------------------------------------+ -// DFU Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 9 bytes + number of alternatives * 9 -#define TUD_DFU_DESC_LEN(_alt_count) (9 + (_alt_count) * 9) - -// Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size -// Note: Alternate count must be numberic or macro, string index is increased by one for each Alt interface -#define TUD_DFU_DESCRIPTOR(_itfnum, _alt_count, _stridx, _attr, _timeout, _xfer_size) \ - TU_XSTRCAT(_TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \ - /* Function */ \ - 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) - -#define _TUD_DFU_ALT(_itfnum, _alt, _stridx) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx - -#define _TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx) - -#define _TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) - -//--------------------------------------------------------------------+ -// CDC-ECM Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 71 bytes -#define TUD_CDC_ECM_DESC_LEN (8+9+5+5+13+7+9+9+7+7) - -// CDC-ECM Descriptor Template -// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. -#define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, _desc_stridx,\ - /* CDC-ECM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC-ECM Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-ECM Functional Descriptor */\ - 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface (default inactive) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* CDC Data Interface (alternative active) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//--------------------------------------------------------------------+ -// RNDIS Descriptor Templates -//--------------------------------------------------------------------+ - -#if 0 -/* Windows XP */ -#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC -#define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL -#define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ -#else -/* Windows 7+ */ -#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER -#define TUD_RNDIS_ITF_SUBCLASS 0x01 -#define TUD_RNDIS_ITF_PROTOCOL 0x03 -#endif - -// Length of template descriptor: 66 bytes -#define TUD_RNDIS_DESC_LEN (8+9+5+5+4+5+7+9+7+7) - -// RNDIS Descriptor Template -// Interface number, string index, EP notification address and size, EP data address (out, in) and size. -#define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ - /* CDC-ACM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC Call Management */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* ACM */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//--------------------------------------------------------------------+ -// Bluetooth Radio Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) -#define TUD_BT_APP_SUBCLASS 0x01 -#define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 -#define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 - -#ifndef CFG_TUD_BTH_ISO_ALT_COUNT -#define CFG_TUD_BTH_ISO_ALT_COUNT 0 -#endif - -// Length of template descriptor: 38 bytes + number of ISO alternatives * 23 -#define TUD_BTH_DESC_LEN (8 + 9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) - -/* Primary Interface */ -#define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, _stridx, \ - /* Endpoint In for events */ \ - 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ - /* Endpoint In for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ - /* Endpoint Out for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 - -#define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ - /* Interface with 2 endpoints */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Isochronous endpoints */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 - -#define _FIRST(a, ...) a -#define _REST(a, ...) __VA_ARGS__ - -#define TUD_BTH_ISO_ITF_0(_itfnum, ...) -#define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) - -#define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ - TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) - -// BT Primary controller descriptor -// Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes -// TODO BTH should also use IAD like CDC for composite device -#define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ - /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0,\ - TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) - -//--------------------------------------------------------------------+ -// CDC-NCM Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor -#define TUD_CDC_NCM_DESC_LEN (8+9+5+5+13+6+7+9+9+7+7) - -// CDC-ECM Descriptor Template -// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. -#define TUD_CDC_NCM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, _desc_stridx,\ - /* CDC-NCM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC-NCM Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-NCM Functional Descriptor */\ - 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0, \ - /* CDC-NCM Functional Descriptor */\ - 6, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_NCM, U16_TO_U8S_LE(0x0100), 0, \ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 50,\ - /* CDC Data Interface (default inactive) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ - /* CDC Data Interface (alternative active) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_USBD_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c deleted file mode 100644 index 7a8244699..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_DEVICE_ENABLED - -#include "tusb.h" -#include "device/usbd_pvt.h" -#include "dcd.h" - -#if CFG_TUSB_DEBUG >= 2 -extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); -#endif - -enum -{ - EDPT_CTRL_OUT = 0x00, - EDPT_CTRL_IN = 0x80 -}; - -typedef struct -{ - tusb_control_request_t request; - - uint8_t* buffer; - uint16_t data_len; - uint16_t total_xferred; - - usbd_control_xfer_cb_t complete_cb; -} usbd_control_xfer_t; - -static usbd_control_xfer_t _ctrl_xfer; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Queue ZLP status transaction -static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) -{ - // Opposite to endpoint in Data Phase - uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); -} - -// Status phase -bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = NULL; - _ctrl_xfer.total_xferred = 0; - _ctrl_xfer.data_len = 0; - - return _status_stage_xact(rhport, request); -} - -// Queue a transaction in Data Stage -// Each transaction has up to Endpoint0's max packet size. -// This function can also transfer an zero-length packet -static bool _data_stage_xact(uint8_t rhport) -{ - uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE); - - uint8_t ep_addr = EDPT_CTRL_OUT; - - if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN ) - { - ep_addr = EDPT_CTRL_IN; - if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); - } - - return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); -} - -// Transmit data to/from the control endpoint. -// If the request's wLength is zero, a status packet is sent instead. -bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = (uint8_t*) buffer; - _ctrl_xfer.total_xferred = 0U; - _ctrl_xfer.data_len = tu_min16(len, request->wLength); - - if (request->wLength > 0U) - { - if(_ctrl_xfer.data_len > 0U) - { - TU_ASSERT(buffer); - } - -// TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len); - - // Data stage - TU_ASSERT( _data_stage_xact(rhport) ); - } - else - { - // Status stage - TU_ASSERT( _status_stage_xact(rhport, request) ); - } - - return true; -} - -//--------------------------------------------------------------------+ -// USBD API -//--------------------------------------------------------------------+ - -void usbd_control_reset(void); -void usbd_control_set_request(tusb_control_request_t const *request); -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -void usbd_control_reset(void) -{ - tu_varclr(&_ctrl_xfer); -} - -// Set complete callback -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) -{ - _ctrl_xfer.complete_cb = fp; -} - -// for dcd_set_address where DCD is responsible for status response -void usbd_control_set_request(tusb_control_request_t const *request) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = NULL; - _ctrl_xfer.total_xferred = 0; - _ctrl_xfer.data_len = 0; -} - -// callback when a transaction complete on -// - DATA stage of control endpoint or -// - Status stage -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - // Endpoint Address is opposite to direction bit, this is Status Stage complete event - if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) - { - TU_ASSERT(0 == xferred_bytes); - - // invoke optional dcd hook if available - if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); - - if (_ctrl_xfer.complete_cb) - { - // TODO refactor with usbd_driver_print_control_complete_name - _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); - } - - return true; - } - - if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT ) - { - TU_VERIFY(_ctrl_xfer.buffer); - memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); - TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); - } - - _ctrl_xfer.total_xferred += xferred_bytes; - _ctrl_xfer.buffer += xferred_bytes; - - // Data Stage is complete when all request's length are transferred or - // a short packet is sent including zero-length packet. - if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE) ) - { - // DATA stage is complete - bool is_ok = true; - - // invoke complete callback if set - // callback can still stall control in status phase e.g out data does not make sense - if ( _ctrl_xfer.complete_cb ) - { - #if CFG_TUSB_DEBUG >= 2 - usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); - #endif - - is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request); - } - - if ( is_ok ) - { - // Send status - TU_ASSERT( _status_stage_xact(rhport, &_ctrl_xfer.request) ); - }else - { - // Stall both IN and OUT control endpoint - dcd_edpt_stall(rhport, EDPT_CTRL_OUT); - dcd_edpt_stall(rhport, EDPT_CTRL_IN); - } - } - else - { - // More data to transfer - TU_ASSERT( _data_stage_xact(rhport) ); - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h deleted file mode 100644 index 7607b9895..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ -#ifndef USBD_PVT_H_ -#define USBD_PVT_H_ - -#include "osal/osal.h" -#include "common/tusb_fifo.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver API -//--------------------------------------------------------------------+ - -typedef struct -{ - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - void (* init ) (void); - void (* reset ) (uint8_t rhport); - uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); - bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); /* optional */ -} usbd_class_driver_t; - -// Invoked when initializing device stack to get additional class drivers. -// Can optionally implemented by application to extend/overwrite class driver support. -// Note: The drivers array must be accessible at all time when stack is active -usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; - -typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// USBD Endpoint API -//--------------------------------------------------------------------+ - -// Open an endpoint -bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); - -// Close an endpoint -void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); - -// Submit a usb transfer -bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); - -// Claim an endpoint before submitting a transfer. -// If caller does not make any transfer, it must release endpoint for others. -bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); - -// Release an endpoint without submitting a transfer -bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr); - -// Check if endpoint is busy transferring -bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); - -// Stall endpoint -void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr); - -// Clear stalled endpoint -void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr); - -// Check if endpoint is stalled -bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr); - -// Check if endpoint is ready (not busy and not stalled) -TU_ATTR_ALWAYS_INLINE static inline -bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) -{ - return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); -} - -/*------------------------------------------------------------------*/ -/* Helper - *------------------------------------------------------------------*/ - -bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); -void usbd_defer_func( osal_task_func_t func, void* param, bool in_isr ); - - -#ifdef __cplusplus - } -#endif - -#endif /* USBD_PVT_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h deleted file mode 100644 index eb53d2e80..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HCD_H_ -#define _TUSB_HCD_H_ - -#include "common/tusb_common.h" -#include "osal/osal.h" -#include "common/tusb_fifo.h" -#include "hcd_attr.h" - -#ifdef __cplusplus - extern "C" { -#endif - - //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef enum -{ - HCD_EVENT_DEVICE_ATTACH, - HCD_EVENT_DEVICE_REMOVE, - HCD_EVENT_XFER_COMPLETE, - - // Not an HCD event, just a convenient way to defer ISR function - USBH_EVENT_FUNC_CALL, - - HCD_EVENT_COUNT -} hcd_eventid_t; - -typedef struct -{ - uint8_t rhport; - uint8_t event_id; - uint8_t dev_addr; - - union - { - // Attach, Remove - struct { - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; - } connection; - - // XFER_COMPLETE - struct { - uint8_t ep_addr; - uint8_t result; - uint32_t len; - } xfer_complete; - - // FUNC_CALL - struct { - void (*func) (void*); - void* param; - }func_call; - }; - -} hcd_event_t; - -#if TUSB_OPT_HOST_ENABLED -// Max number of endpoints per device -enum { - // TODO better computation - HCD_MAX_ENDPOINT = CFG_TUH_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3), - HCD_MAX_XFER = HCD_MAX_ENDPOINT*2, -}; - -//#define HCD_MAX_ENDPOINT 16 -//#define HCD_MAX_XFER 16 - -typedef struct { - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; -} hcd_devtree_info_t; - -#endif - -//--------------------------------------------------------------------+ -// Controller API -//--------------------------------------------------------------------+ - -// Initialize controller to host mode -bool hcd_init(uint8_t rhport); - -// Interrupt Handler -void hcd_int_handler(uint8_t rhport); - -// Enable USB interrupt -void hcd_int_enable (uint8_t rhport); - -// Disable USB interrupt -void hcd_int_disable(uint8_t rhport); - -// Get frame number (1ms) -uint32_t hcd_frame_number(uint8_t rhport); - -//--------------------------------------------------------------------+ -// Port API -//--------------------------------------------------------------------+ - -// Get the current connect status of roothub port -bool hcd_port_connect_status(uint8_t rhport); - -// Reset USB bus on the port -void hcd_port_reset(uint8_t rhport); - -// TODO implement later -void hcd_port_reset_end(uint8_t rhport); - -// Get port link speed -tusb_speed_t hcd_port_speed_get(uint8_t rhport); - -// HCD closes all opened endpoints belong to this device -void hcd_device_close(uint8_t rhport, uint8_t dev_addr); - -//--------------------------------------------------------------------+ -// Endpoints API -//--------------------------------------------------------------------+ - -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); -bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); - -//--------------------------------------------------------------------+ -// USBH implemented API -//--------------------------------------------------------------------+ - -// Get device tree information of a device -// USB device tree can be complicated and manged by USBH, this help HCD to retrieve -// needed topology info to carry out its work -extern void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info); - -//------------- Event API -------------// - -// Called by HCD to notify stack -extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); - -// Helper to send device attach event -extern void hcd_event_device_attach(uint8_t rhport, bool in_isr); - -// Helper to send device removal event -extern void hcd_event_device_remove(uint8_t rhport, bool in_isr); - -// Helper to send USB transfer event -extern void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HCD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h deleted file mode 100644 index 06011c63c..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_HCD_ATTR_H_ -#define TUSB_HCD_ATTR_H_ - -#include "tusb_option.h" - -// Attribute includes -// - ENDPOINT_MAX: max (logical) number of endpoint -// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. - -//------------- NXP -------------// -#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) - #define HCD_ATTR_OHCI - -#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) - #define HCD_ATTR_EHCI_TRANSDIMENSION - -#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) - // #define HCD_ATTR_EHCI_NXP_PTD - -#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) - // #define HCD_ATTR_EHCI_NXP_PTD - -#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX) - #define HCD_ATTR_EHCI_TRANSDIMENSION - -#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX) - -//------------- Microchip -------------// -#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ - TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) - -#elif TU_CHECK_MCU(OPT_MCU_SAMG) - -#elif TU_CHECK_MCU(OPT_MCU_SAMX7X) - -//------------- ST -------------// -#elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1, OPT_MCU_STM32F3) || \ - TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1, OPT_MCU_STM32L4) - -#elif TU_CHECK_MCU(OPT_MCU_STM32F2, OPT_MCU_STM32F3, OPT_MCU_STM32F4) - -#elif TU_CHECK_MCU(OPT_MCU_STM32F7) - -#elif TU_CHECK_MCU(OPT_MCU_STM32H7) - -//------------- Sony -------------// -#elif TU_CHECK_MCU(OPT_MCU_CXD56) - -//------------- Nuvoton -------------// -#elif TU_CHECK_MCU(OPT_MCU_NUC505) - -//------------- Espressif -------------// -#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - -//------------- Raspberry Pi -------------// -#elif TU_CHECK_MCU(OPT_MCU_RP2040) - -//------------- Silabs -------------// -#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) - -//------------- Renesas -------------// -#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) - -//#elif TU_CHECK_MCU(OPT_MCU_MM32F327X) -// #define DCD_ATTR_ENDPOINT_MAX not known yet - -//------------- GigaDevice -------------// -#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) - -#else -// #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" -#endif - -// Default to fullspeed if not defined -//#ifndef PORT_HIGHSPEED -// #define DCD_ATTR_PORT_HIGHSPEED 0x00 -//#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c deleted file mode 100644 index fd4dbd04a..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB) - -#include "usbh.h" -#include "usbh_classdriver.h" -#include "hub.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t port_count; - uint8_t status_change; // data from status change interrupt endpoint - - hub_port_status_response_t port_status; -} hub_interface_t; - -CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB]; -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)]; - -TU_ATTR_ALWAYS_INLINE -static inline hub_interface_t* get_itf(uint8_t dev_addr) -{ - return &hub_data[dev_addr-1-CFG_TUH_DEVICE_MAX]; -} - -#if CFG_TUSB_DEBUG -static char const* const _hub_feature_str[] = -{ - [HUB_FEATURE_PORT_CONNECTION ] = "PORT_CONNECTION", - [HUB_FEATURE_PORT_ENABLE ] = "PORT_ENABLE", - [HUB_FEATURE_PORT_SUSPEND ] = "PORT_SUSPEND", - [HUB_FEATURE_PORT_OVER_CURRENT ] = "PORT_OVER_CURRENT", - [HUB_FEATURE_PORT_RESET ] = "PORT_RESET", - [HUB_FEATURE_PORT_POWER ] = "PORT_POWER", - [HUB_FEATURE_PORT_LOW_SPEED ] = "PORT_LOW_SPEED", - [HUB_FEATURE_PORT_CONNECTION_CHANGE ] = "PORT_CONNECTION_CHANGE", - [HUB_FEATURE_PORT_ENABLE_CHANGE ] = "PORT_ENABLE_CHANGE", - [HUB_FEATURE_PORT_SUSPEND_CHANGE ] = "PORT_SUSPEND_CHANGE", - [HUB_FEATURE_PORT_OVER_CURRENT_CHANGE ] = "PORT_OVER_CURRENT_CHANGE", - [HUB_FEATURE_PORT_RESET_CHANGE ] = "PORT_RESET_CHANGE", - [HUB_FEATURE_PORT_TEST ] = "PORT_TEST", - [HUB_FEATURE_PORT_INDICATOR ] = "PORT_INDICATOR", -}; -#endif - -//--------------------------------------------------------------------+ -// HUB -//--------------------------------------------------------------------+ -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) -{ - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HUB_REQUEST_CLEAR_FEATURE, - .wValue = feature, - .wIndex = hub_port, - .wLength = 0 - }; - - TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); - return true; -} - -bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) -{ - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HUB_REQUEST_SET_FEATURE, - .wValue = feature, - .wIndex = hub_port, - .wLength = 0 - }; - - TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); - return true; -} - -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb) -{ - return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb); -} - -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb) -{ - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = HUB_REQUEST_GET_STATUS, - .wValue = 0, - .wIndex = hub_port, - .wLength = 4 - }; - - TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) ); - return true; -} - -//--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) -//--------------------------------------------------------------------+ -void hub_init(void) -{ - tu_memclr(hub_data, sizeof(hub_data)); -} - -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && - 0 == itf_desc->bInterfaceSubClass); - - // hub driver does not support multiple TT yet - TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); - - // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len); - - //------------- Interrupt Status endpoint -------------// - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && - TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); - - hub_interface_t* p_hub = get_itf(dev_addr); - - p_hub->itf_num = itf_desc->bInterfaceNumber; - p_hub->ep_in = desc_ep->bEndpointAddress; - - return true; -} - -void hub_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr > CFG_TUH_DEVICE_MAX, ); - hub_interface_t* p_hub = get_itf(dev_addr); - - if (p_hub->ep_in) tu_memclr(p_hub, sizeof( hub_interface_t)); -} - -bool hub_status_pipe_queue(uint8_t dev_addr) -{ - hub_interface_t* hub_itf = get_itf(dev_addr); - return usbh_edpt_xfer(dev_addr, hub_itf->ep_in, &hub_itf->status_change, 1); -} - - -//--------------------------------------------------------------------+ -// Set Configure -//--------------------------------------------------------------------+ - -static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); - -bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - hub_interface_t* p_hub = get_itf(dev_addr); - TU_ASSERT(itf_num == p_hub->itf_num); - - // Get Hub Descriptor - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = HUB_REQUEST_GET_DESCRIPTOR, - .wValue = 0, - .wIndex = 0, - .wLength = sizeof(descriptor_hub_desc_t) - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, _hub_buffer, config_set_port_power) ); - - return true; -} - -static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - hub_interface_t* p_hub = get_itf(dev_addr); - - // only use number of ports in hub descriptor - descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; - p_hub->port_count = desc_hub->bNbrPorts; - - // May need to GET_STATUS - - // Set Port Power to be able to detect connection, starting with port 1 - uint8_t const hub_port = 1; - return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); -} - -static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(XFER_RESULT_SUCCESS == result); - hub_interface_t* p_hub = get_itf(dev_addr); - - if (request->wIndex == p_hub->port_count) - { - // All ports are power -> queue notification status endpoint and - // complete the SET CONFIGURATION - TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1) ); - - usbh_driver_set_config_complete(dev_addr, p_hub->itf_num); - }else - { - // power next port - uint8_t const hub_port = (uint8_t) (request->wIndex + 1); - return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); - } - - return true; -} - -//--------------------------------------------------------------------+ -// Connection Changes -//--------------------------------------------------------------------+ - -static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); - -// callback as response of interrupt endpoint polling -bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports - (void) ep_addr; - TU_ASSERT(result == XFER_RESULT_SUCCESS); - - hub_interface_t* p_hub = get_itf(dev_addr); - - TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change); - - // Hub ignore bit0 in status change - for (uint8_t port=1; port <= p_hub->port_count; port++) - { - if ( tu_bit_test(p_hub->status_change, port) ) - { - hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete); - break; - } - } - - // NOTE: next status transfer is queued by usbh.c after handling this request - - return true; -} - -static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(result == XFER_RESULT_SUCCESS); - - hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) request->wIndex; - - // Connection change - if (p_hub->port_status.change.connection) - { - // Port is powered and enabled - //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); - - // Acknowledge Port Connection Change - hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete); - }else - { - // Other changes are: Enable, Suspend, Over Current, Reset, L1 state - // TODO clear change - - // prepare for next hub status - // TODO continue with status_change, or maybe we can do it again with status - hub_status_pipe_queue(dev_addr); - } - - return true; -} - -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(result == XFER_RESULT_SUCCESS); - - hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) request->wIndex; - - if ( p_hub->port_status.status.connection ) - { - // Reset port if attach event - hub_port_reset(dev_addr, port_num, connection_port_reset_complete); - }else - { - // submit detach event - hcd_event_t event = - { - .rhport = usbh_get_rhport(dev_addr), - .event_id = HCD_EVENT_DEVICE_REMOVE, - .connection = - { - .hub_addr = dev_addr, - .hub_port = port_num - } - }; - - hcd_event_handler(&event, false); - } - - return true; -} - -static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(result == XFER_RESULT_SUCCESS); - - // hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) request->wIndex; - - // submit attach event - hcd_event_t event = - { - .rhport = usbh_get_rhport(dev_addr), - .event_id = HCD_EVENT_DEVICE_ATTACH, - .connection = - { - .hub_addr = dev_addr, - .hub_port = port_num - } - }; - - hcd_event_handler(&event, false); - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h deleted file mode 100644 index c4d544193..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_Hub Hub (Host only) - * \details Like most PC's OS, Hub support is completely hidden from Application. In fact, application cannot determine whether - * a device is mounted directly via roothub or via a hub's port. All Hub-related procedures are performed and managed - * by tinyusb stack. Unless you are trying to develop the stack itself, there are nothing else can be used by Application. - * \note Due to my laziness, only 1-level of Hub is supported. In other way, the stack cannot mount a hub via another hub. - * @{ - */ - -#ifndef _TUSB_HUB_H_ -#define _TUSB_HUB_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//D1...D0: Logical Power Switching Mode -//00: Ganged power switching (all ports’power at -//once) -//01: Individual port power switching -//1X: Reserved. Used only on 1.0 compliant hubs -//that implement no power switching -//D2: Identifies a Compound Device -//0: Hub is not part of a compound device. -//1: Hub is part of a compound device. -//D4...D3: Over-current Protection Mode -//00: Global Over-current Protection. The hub -//reports over-current as a summation of all -//ports’current draw, without a breakdown of -//individual port over-current status. -//01: Individual Port Over-current Protection. The -//hub reports over-current on a per-port basis. -//Each port has an over-current status. -//1X: No Over-current Protection. This option is -//allowed only for bus-powered hubs that do not -//implement over-current protection. -// -//D6...D5: TT Think TIme -//00: TT requires at most 8 FS bit times of inter -//transaction gap on a full-/low-speed -//downstream bus. -//01: TT requires at most 16 FS bit times. -//10: TT requires at most 24 FS bit times. -//11: TT requires at most 32 FS bit times. -//D7: Port Indicators Supported -//0: Port Indicators are not supported on its -//downstream facing ports and the -//PORT_INDICATOR request has no effect. -//1: Port Indicators are supported on its -//downstream facing ports and the -//PORT_INDICATOR request controls the -//indicators. See Section 11.5.3. -//D15...D8: Reserved - -typedef struct TU_ATTR_PACKED{ - uint8_t bLength ; ///< Size of descriptor - uint8_t bDescriptorType ; ///< Other_speed_Configuration Type - uint8_t bNbrPorts; - uint16_t wHubCharacteristics; - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; - uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1) - uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff -} descriptor_hub_desc_t; - -TU_VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct"); - -enum { - HUB_REQUEST_GET_STATUS = 0 , - HUB_REQUEST_CLEAR_FEATURE = 1 , - - HUB_REQUEST_SET_FEATURE = 3 , - - HUB_REQUEST_GET_DESCRIPTOR = 6 , - HUB_REQUEST_SET_DESCRIPTOR = 7 , - HUB_REQUEST_CLEAR_TT_BUFFER = 8 , - HUB_REQUEST_RESET_TT = 9 , - HUB_REQUEST_GET_TT_STATE = 10 , - HUB_REQUEST_STOP_TT = 11 -}; - -enum { - HUB_FEATURE_HUB_LOCAL_POWER_CHANGE = 0, - HUB_FEATURE_HUB_OVER_CURRENT_CHANGE -}; - -enum{ - HUB_FEATURE_PORT_CONNECTION = 0, - HUB_FEATURE_PORT_ENABLE = 1, - HUB_FEATURE_PORT_SUSPEND = 2, - HUB_FEATURE_PORT_OVER_CURRENT = 3, - HUB_FEATURE_PORT_RESET = 4, - - HUB_FEATURE_PORT_POWER = 8, - HUB_FEATURE_PORT_LOW_SPEED = 9, - - HUB_FEATURE_PORT_CONNECTION_CHANGE = 16, - HUB_FEATURE_PORT_ENABLE_CHANGE = 17, - HUB_FEATURE_PORT_SUSPEND_CHANGE = 18, - HUB_FEATURE_PORT_OVER_CURRENT_CHANGE = 19, - HUB_FEATURE_PORT_RESET_CHANGE = 20, - HUB_FEATURE_PORT_TEST = 21, - HUB_FEATURE_PORT_INDICATOR = 22 -}; - -// data in response of HUB_REQUEST_GET_STATUS, wIndex = 0 (hub) -typedef struct { - union{ - struct TU_ATTR_PACKED { - uint16_t local_power_source : 1; - uint16_t over_current : 1; - uint16_t : 14; - }; - - uint16_t value; - } status, change; -} hub_status_response_t; - -TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); - -// data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num -typedef struct { - union { - struct TU_ATTR_PACKED { - uint16_t connection : 1; - uint16_t port_enable : 1; - uint16_t suspend : 1; - uint16_t over_current : 1; - uint16_t reset : 1; - - uint16_t : 3; - uint16_t port_power : 1; - uint16_t low_speed : 1; - uint16_t high_speed : 1; - uint16_t port_test_mode : 1; - uint16_t port_indicator_control : 1; - uint16_t TU_RESERVED : 3; - }; - - uint16_t value; - } status, change; -} hub_port_status_response_t; - -TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); - -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); -bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); - -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb); -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb); -bool hub_status_pipe_queue(uint8_t dev_addr); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hub_init (void); -bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void hub_close (uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HUB_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c deleted file mode 100644 index b8439addc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c +++ /dev/null @@ -1,1204 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_HOST_ENABLED - -#include "tusb.h" -#include "host/usbh.h" -#include "host/usbh_classdriver.h" -#include "hub.h" - -//--------------------------------------------------------------------+ -// USBH Configuration -//--------------------------------------------------------------------+ - -// TODO remove,update -#ifndef CFG_TUH_EP_MAX -#define CFG_TUH_EP_MAX 9 -#endif - -#ifndef CFG_TUH_TASK_QUEUE_SZ -#define CFG_TUH_TASK_QUEUE_SZ 16 -#endif - -// Debug level of USBD -#define USBH_DBG_LVL 2 - -//--------------------------------------------------------------------+ -// USBH-HCD common data structure -//--------------------------------------------------------------------+ - -// device0 struct must be strictly a subset of normal device struct -typedef struct -{ - // port - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; - - volatile struct TU_ATTR_PACKED - { - uint8_t connected : 1; - uint8_t addressed : 1; - uint8_t configured : 1; - uint8_t suspended : 1; - }; -} usbh_dev0_t; - -typedef struct { - // port - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; - - volatile struct TU_ATTR_PACKED - { - uint8_t connected : 1; - uint8_t addressed : 1; - uint8_t configured : 1; - uint8_t suspended : 1; - }; - - //------------- device descriptor -------------// - uint16_t vid; - uint16_t pid; - - uint8_t ep0_size; - uint8_t i_manufacturer; - uint8_t i_product; - uint8_t i_serial; - - //------------- configuration descriptor -------------// - // uint8_t interface_count; // bNumInterfaces alias - - //------------- device -------------// - volatile uint8_t state; // device state, value from enum tusbh_device_state_t - - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) - - struct TU_ATTR_PACKED - { - volatile bool busy : 1; - volatile bool stalled : 1; - volatile bool claimed : 1; - - // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUH_EP_MAX][2]; - - // Mutex for claiming endpoint, only needed when using with preempted RTOS -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_def_t mutexdef; - osal_mutex_t mutex; -#endif - -} usbh_device_t; - - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xFFu }; -enum { ADDR_INVALID = 0xFFu }; - -#if CFG_TUSB_DEBUG >= 2 - #define DRIVER_NAME(_name) .name = _name, -#else - #define DRIVER_NAME(_name) -#endif - -static usbh_class_driver_t const usbh_class_drivers[] = -{ - #if CFG_TUH_CDC - { - DRIVER_NAME("CDC") - .init = cdch_init, - .open = cdch_open, - .set_config = cdch_set_config, - .xfer_cb = cdch_xfer_cb, - .close = cdch_close - }, - #endif - - #if CFG_TUH_MSC - { - DRIVER_NAME("MSC") - .init = msch_init, - .open = msch_open, - .set_config = msch_set_config, - .xfer_cb = msch_xfer_cb, - .close = msch_close - }, - #endif - - #if CFG_TUH_HID - { - DRIVER_NAME("HID") - .init = hidh_init, - .open = hidh_open, - .set_config = hidh_set_config, - .xfer_cb = hidh_xfer_cb, - .close = hidh_close - }, - #endif - - #if CFG_TUH_HUB - { - DRIVER_NAME("HUB") - .init = hub_init, - .open = hub_open, - .set_config = hub_set_config, - .xfer_cb = hub_xfer_cb, - .close = hub_close - }, - #endif - - #if CFG_TUH_VENDOR - { - DRIVER_NAME("VENDOR") - .init = cush_init, - .open = cush_open_subtask, - .xfer_cb = cush_isr, - .close = cush_close - } - #endif -}; - -enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; - -enum { RESET_DELAY = 500 }; // 200 USB specs say only 50ms but many devices require much longer - -enum { CONFIG_NUM = 1 }; // default to use configuration 1 - - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -static bool _usbh_initialized = false; - -// Device with address = 0 for enumeration -static usbh_dev0_t _dev0; - -// all devices excluding zero-address -// hub address start from CFG_TUH_DEVICE_MAX+1 -CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB]; - -// Event queue -// role device/host is used by OS NONE for mutex (disable usb isr) -OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); -static osal_queue_t _usbh_q; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; - -//------------- Helper Function -------------// - -TU_ATTR_ALWAYS_INLINE -static inline usbh_device_t* get_device(uint8_t dev_addr) -{ - TU_ASSERT(dev_addr, NULL); - return &_usbh_devices[dev_addr-1]; -} - -static bool enum_new_device(hcd_event_t* event); -static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); -static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); - -// from usbh_control.c -extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - -//--------------------------------------------------------------------+ -// PUBLIC API (Parameter Verification is required) -//--------------------------------------------------------------------+ -bool tuh_mounted(uint8_t dev_addr) -{ - return get_device(dev_addr)->configured; -} - -bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) -{ - *vid = *pid = 0; - - TU_VERIFY(tuh_mounted(dev_addr)); - - usbh_device_t const* dev = get_device(dev_addr); - - *vid = dev->vid; - *pid = dev->pid; - - return true; -} - -tusb_speed_t tuh_speed_get (uint8_t dev_addr) -{ - return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed); -} - -#if CFG_TUSB_OS == OPT_OS_NONE -void osal_task_delay(uint32_t msec) -{ - (void) msec; - - const uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); - while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} -} -#endif - -//--------------------------------------------------------------------+ -// CLASS-USBD API (don't require to verify parameters) -//--------------------------------------------------------------------+ - -bool tuh_inited(void) -{ - return _usbh_initialized; -} - -bool tuh_init(uint8_t rhport) -{ - // skip if already initialized - if (_usbh_initialized) return _usbh_initialized; - - TU_LOG2("USBH init\r\n"); - - tu_memclr(_usbh_devices, sizeof(_usbh_devices)); - tu_memclr(&_dev0, sizeof(_dev0)); - - //------------- Enumeration & Reporter Task init -------------// - _usbh_q = osal_queue_create( &_usbh_qdef ); - TU_ASSERT(_usbh_q != NULL); - - //------------- Semaphore, Mutex for Control Pipe -------------// - for(uint8_t i=0; imutex = osal_mutex_create(&dev->mutexdef); - TU_ASSERT(dev->mutex); -#endif - - memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping - } - - // Class drivers init - for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - TU_LOG2("%s init\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].init(); - } - - TU_ASSERT(hcd_init(rhport)); - hcd_int_enable(rhport); - - _usbh_initialized = true; - return true; -} - -/* USB Host Driver task - * This top level thread manages all host controller event and delegates events to class-specific drivers. - * This should be called periodically within the mainloop or rtos thread. - * - @code - int main(void) - { - application_init(); - tusb_init(); - - while(1) // the mainloop - { - application_code(); - tuh_task(); // tinyusb host task - } - } - @endcode - */ -void tuh_task(void) -{ - // Skip if stack is not initialized - if ( !tusb_inited() ) return; - - // Loop until there is no more events in the queue - while (1) - { - hcd_event_t event; - if ( !osal_queue_receive(_usbh_q, &event) ) return; - - switch (event.event_id) - { - case HCD_EVENT_DEVICE_ATTACH: - // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating - // one device before enumerating another one. - TU_LOG2("USBH DEVICE ATTACH\r\n"); - enum_new_device(&event); - break; - - case HCD_EVENT_DEVICE_REMOVE: - TU_LOG2("USBH DEVICE REMOVED\r\n"); - process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); - - #if CFG_TUH_HUB - // TODO remove - if ( event.connection.hub_addr != 0) - { - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( event.connection.hub_addr ); - } - #endif - break; - - case HCD_EVENT_XFER_COMPLETE: - { - uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - - if (event.dev_addr == 0) - { - // device 0 only has control endpoint - TU_ASSERT(epnum == 0, ); - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - } - else - { - usbh_device_t* dev = get_device(event.dev_addr); - dev->ep_status[epnum][ep_dir].busy = false; - dev->ep_status[epnum][ep_dir].claimed = 0; - - if ( 0 == epnum ) - { - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - }else - { - uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - - TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - } - } - } - break; - - case USBH_EVENT_FUNC_CALL: - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; - - default: break; - } - } -} - -//--------------------------------------------------------------------+ -// USBH API For Class Driver -//--------------------------------------------------------------------+ - -uint8_t usbh_get_rhport(uint8_t dev_addr) -{ - return (dev_addr == 0) ? _dev0.rhport : get_device(dev_addr)->rhport; -} - -uint8_t* usbh_get_enum_buf(void) -{ - return _usbh_ctrl_buf; -} - -//--------------------------------------------------------------------+ -// HCD Event Handler -//--------------------------------------------------------------------+ - -void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) -{ - if (dev_addr) - { - usbh_device_t const* dev = get_device(dev_addr); - - devtree_info->rhport = dev->rhport; - devtree_info->hub_addr = dev->hub_addr; - devtree_info->hub_port = dev->hub_port; - devtree_info->speed = dev->speed; - }else - { - devtree_info->rhport = _dev0.rhport; - devtree_info->hub_addr = _dev0.hub_addr; - devtree_info->hub_port = _dev0.hub_port; - devtree_info->speed = _dev0.speed; - } -} - -void hcd_event_handler(hcd_event_t const* event, bool in_isr) -{ - switch (event->event_id) - { - default: - osal_queue_send(_usbh_q, event, in_isr); - break; - } -} - -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) -{ - hcd_event_t event = - { - .rhport = 0, // TODO correct rhport - .event_id = HCD_EVENT_XFER_COMPLETE, - .dev_addr = dev_addr, - .xfer_complete = - { - .ep_addr = ep_addr, - .result = result, - .len = xferred_bytes - } - }; - - hcd_event_handler(&event, in_isr); -} - -void hcd_event_device_attach(uint8_t rhport, bool in_isr) -{ - hcd_event_t event = - { - .rhport = rhport, - .event_id = HCD_EVENT_DEVICE_ATTACH - }; - - event.connection.hub_addr = 0; - event.connection.hub_port = 0; - - hcd_event_handler(&event, in_isr); -} - -void hcd_event_device_remove(uint8_t hostid, bool in_isr) -{ - hcd_event_t event = - { - .rhport = hostid, - .event_id = HCD_EVENT_DEVICE_REMOVE - }; - - event.connection.hub_addr = 0; - event.connection.hub_port = 0; - - hcd_event_handler(&event, in_isr); -} - - -// a device unplugged on hostid, hub_addr, hub_port -// return true if found and unmounted device, false if cannot find -void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) -{ - //------------- find the all devices (star-network) under port that is unplugged -------------// - // TODO mark as disconnected in ISR, also handle dev0 - for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ ) - { - usbh_device_t* dev = &_usbh_devices[dev_id]; - uint8_t const dev_addr = dev_id+1; - - // TODO Hub multiple level - if (dev->rhport == rhport && - (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub - (hub_port == 0 || dev->hub_port == hub_port) && - dev->state != TUSB_DEVICE_STATE_UNPLUG) - { - // Invoke callback before close driver - if (tuh_umount_cb) tuh_umount_cb(dev_addr); - - // Close class driver - for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - TU_LOG2("%s close\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].close(dev_addr); - } - - hcd_device_close(rhport, dev_addr); - - // release all endpoints associated with the device - memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping - tu_memclr(dev->ep_status, sizeof(dev->ep_status)); - - dev->state = TUSB_DEVICE_STATE_UNPLUG; - } - } -} - -//--------------------------------------------------------------------+ -// INTERNAL HELPER -//--------------------------------------------------------------------+ -static uint8_t get_new_address(bool is_hub) -{ - uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; - uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); - - for (uint8_t i=0; i < count; i++) - { - uint8_t const addr = start + i; - if (get_device(addr)->state == TUSB_DEVICE_STATE_UNPLUG) return addr; - } - return ADDR_INVALID; -} - -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) -{ - usbh_device_t* dev = get_device(dev_addr); - - for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++) - { - // continue with next valid interface - // TODO skip IAD binding interface such as CDCs - uint8_t const drv_id = dev->itf2drv[itf_num]; - if (drv_id != DRVID_INVALID) - { - usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num); - driver->set_config(dev_addr, itf_num); - break; - } - } - - // all interface are configured - if (itf_num == sizeof(dev->itf2drv)) - { - // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(dev_addr); - } -} - -//--------------------------------------------------------------------+ -// Enumeration Process -// is a lengthy process with a seires of control transfer to configure -// newly attached device. Each step is handled by a function in this -// section -// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating -// one device before enumerating another one. -//--------------------------------------------------------------------+ - -static bool enum_request_addr0_device_desc(void); -static bool enum_request_set_addr(void); - -static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_set_address_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_get_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_get_9byte_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_get_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); - -#if CFG_TUH_HUB -static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - enum_request_addr0_device_desc(); - return true; -} - -static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - enum_request_set_addr(); - - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( _dev0.hub_addr ); - - return true; -} - -static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - hub_port_status_response_t port_status; - memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); - - // Acknowledge Port Reset Change if Reset Successful - if (port_status.change.reset) - { - TU_ASSERT( hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); - } - - return true; -} - -static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - hub_port_status_response_t port_status; - memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); - - if ( !port_status.status.connection ) - { - // device unplugged while delaying, nothing else to do, queue hub status - return hub_status_pipe_queue(dev_addr); - } - - _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : - (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; - - // Acknowledge Port Reset Change - if (port_status.change.reset) - { - hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset0_complete); - } - - return true; -} -#endif - -static bool enum_new_device(hcd_event_t* event) -{ - _dev0.rhport = event->rhport; // TODO refractor integrate to device_pool - _dev0.hub_addr = event->connection.hub_addr; - _dev0.hub_port = event->connection.hub_port; - - //------------- connected/disconnected directly with roothub -------------// - if (_dev0.hub_addr == 0) - { - // wait until device is stable TODO non blocking - osal_task_delay(RESET_DELAY); - - // device unplugged while delaying - if ( !hcd_port_connect_status(_dev0.rhport) ) return true; - - _dev0.speed = hcd_port_speed_get(_dev0.rhport ); - - enum_request_addr0_device_desc(); - } -#if CFG_TUH_HUB - //------------- connected/disconnected via hub -------------// - else - { - // wait until device is stable - osal_task_delay(RESET_DELAY); - TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) ); - } -#endif // CFG_TUH_HUB - - return true; -} - -static bool enum_request_addr0_device_desc(void) -{ - // TODO probably doesn't need to open/close each enumeration - uint8_t const addr0 = 0; - TU_ASSERT( usbh_edpt_control_open(addr0, 8) ); - - //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// - TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, - .wIndex = 0, - .wLength = 8 - }; - TU_ASSERT( tuh_control_xfer(addr0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) ); - - return true; -} - -// After Get Device Descriptor of Address 0 -static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(0 == dev_addr); - - if (XFER_RESULT_SUCCESS != result) - { -#if CFG_TUH_HUB - // TODO remove, waiting for next data on status pipe - if (_dev0.hub_addr != 0) hub_status_pipe_queue(_dev0.hub_addr); -#endif - - return false; - } - - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - TU_ASSERT( tu_desc_type(desc_device) == TUSB_DESC_DEVICE ); - - // Reset device again before Set Address - TU_LOG2("Port reset \r\n"); - - if (_dev0.hub_addr == 0) - { - // connected directly to roothub - hcd_port_reset( _dev0.rhport ); // reset port after 8 byte descriptor - osal_task_delay(RESET_DELAY); - - enum_request_set_addr(); - } -#if CFG_TUH_HUB - else - { - // after RESET_DELAY the hub_port_reset() already complete - TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, NULL) ); - osal_task_delay(RESET_DELAY); - - tuh_task(); // FIXME temporarily to clean up port_reset control transfer - - TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); - } -#endif - - return true; -} - -static bool enum_request_set_addr(void) -{ - uint8_t const addr0 = 0; - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - - // Get new address - uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); - TU_ASSERT(new_addr != ADDR_INVALID); - - TU_LOG2("Set Address = %d\r\n", new_addr); - - usbh_device_t* new_dev = get_device(new_addr); - - new_dev->rhport = _dev0.rhport; - new_dev->hub_addr = _dev0.hub_addr; - new_dev->hub_port = _dev0.hub_port; - new_dev->speed = _dev0.speed; - new_dev->connected = 1; - new_dev->ep0_size = desc_device->bMaxPacketSize0; - - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = new_addr, - .wIndex = 0, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(addr0, &new_request, NULL, enum_set_address_complete) ); - - return true; -} - -// After SET_ADDRESS is complete -static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(0 == dev_addr); - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - uint8_t const new_addr = (uint8_t const) request->wValue; - - usbh_device_t* new_dev = get_device(new_addr); - new_dev->addressed = 1; - - // TODO close device 0, may not be needed - hcd_device_close(_dev0.rhport, 0); - - // open control pipe for new address - TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size) ); - - // Get full device descriptor - TU_LOG2("Get Device Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, - .wIndex = 0, - .wLength = sizeof(tusb_desc_device_t) - }; - - TU_ASSERT(tuh_control_xfer(new_addr, &new_request, _usbh_ctrl_buf, enum_get_device_desc_complete)); - - return true; -} - -static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - usbh_device_t* dev = get_device(dev_addr); - - dev->vid = desc_device->idVendor; - dev->pid = desc_device->idProduct; - dev->i_manufacturer = desc_device->iManufacturer; - dev->i_product = desc_device->iProduct; - dev->i_serial = desc_device->iSerialNumber; - -// if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); - - TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), - .wIndex = 0, - .wLength = 9 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_9byte_config_desc_complete) ); - - return true; -} - -static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - // TODO not enough buffer to hold configuration descriptor - uint8_t const * desc_config = _usbh_ctrl_buf; - - // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); - - TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); - - // Get full configuration descriptor - TU_LOG2("Get Configuration Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), - .wIndex = 0, - .wLength = total_len - - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); - - return true; -} - -static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - // Parse configuration & set up drivers - // Driver open aren't allowed to make any usb transfer yet - TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); - - TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_CONFIGURATION, - .wValue = CONFIG_NUM, - .wIndex = 0, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, enum_set_config_complete) ); - - return true; -} - -static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - TU_LOG2("Device configured\r\n"); - usbh_device_t* dev = get_device(dev_addr); - dev->configured = 1; - dev->state = TUSB_DEVICE_STATE_CONFIGURED; - - // Start the Set Configuration process for interfaces (itf = DRVID_INVALID) - // Since driver can perform control transfer within its set_config, this is done asynchronously. - // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() - // TODO use separated API instead of using DRVID_INVALID - usbh_driver_set_config_complete(dev_addr, DRVID_INVALID); - - return true; -} - -static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) -{ - usbh_device_t* dev = get_device(dev_addr); - - uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); - uint8_t const* p_desc = tu_desc_next(desc_cfg); - - // parse each interfaces - while( p_desc < desc_end ) - { - uint8_t assoc_itf_count = 1; - - // Class will always starts with Interface Association (if any) and then Interface descriptor - if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) - { - tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; - assoc_itf_count = desc_iad->bInterfaceCount; - - p_desc = tu_desc_next(p_desc); // next to Interface - - // IAD's first interface number and class should match with opened interface - //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && - // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - } - - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - -#if CFG_TUH_MIDI - // MIDI has 2 interfaces (Audio Control v1 + MIDIStreaming) but does not have IAD - // manually increase the associated count - if (1 == assoc_itf_count && - TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) - { - assoc_itf_count = 2; - } -#endif - - uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, desc_end-p_desc); - TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); - - if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) - { - // TODO Attach hub to Hub is not currently supported - // skip this interface - TU_LOG(USBH_DBG_LVL, "Only 1 level of HUB is supported\r\n"); - } - else - { - // Find driver for this interface - uint8_t drv_id; - for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - - if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) - { - // open successfully - TU_LOG2(" %s opened\r\n", driver->name); - - // bind (associated) interfaces to found driver - for(uint8_t i=0; ibInterfaceNumber+i; - - // Interface number must not be used already - TU_ASSERT( DRVID_INVALID == dev->itf2drv[itf_num] ); - dev->itf2drv[itf_num] = drv_id; - } - - // bind all endpoints to found driver - tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); - - break; // exit driver find loop - } - } - - if( drv_id >= USBH_CLASS_DRIVER_COUNT ) - { - TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", - desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); - } - } - - // next Interface or IAD descriptor - p_desc += drv_len; - } - - return true; -} - -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - -#if CFG_TUSB_OS != OPT_OS_NONE - // pre-check to help reducing mutex lock - TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only claim the endpoint if it is not busy and not claimed yet. - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 1; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only release the endpoint if it is claimed and not busy - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 0; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() - // could return and USBH task can preempt and clear the busy - dev->ep_status[epnum][dir].busy = true; - - if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) - { - TU_LOG2("OK\r\n"); - return true; - }else - { - // HCD error, mark endpoint as ready to allow next transfer - dev->ep_status[epnum][dir].busy = false; - dev->ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) -{ - TU_LOG2("Open EP0 with Size = %u (addr = %u)\r\n", max_packet_size, dev_addr); - - tusb_desc_endpoint_t ep0_desc = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = max_packet_size, - .bInterval = 0 - }; - - return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); -} - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) -{ - usbh_device_t* dev = get_device(dev_addr); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); - - return hcd_edpt_open(rhport, dev_addr, desc_ep); -} - -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - - return dev->ep_status[epnum][dir].busy; -} - - - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h deleted file mode 100644 index 8411cad28..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBH_H_ -#define _TUSB_USBH_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#include "common/tusb_common.h" -#include "hcd.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ - -// Init host stack -bool tuh_init(uint8_t rhport); - -// Check if host stack is already initialized -bool tuh_inited(void); - -// Task function should be called in main/rtos loop -void tuh_task(void); - -// Interrupt handler, name alias to HCD -extern void hcd_int_handler(uint8_t rhport); -#define tuh_int_handler hcd_int_handler - -bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid); -tusb_speed_t tuh_speed_get(uint8_t dev_addr); - -// Check if device is connected and configured -bool tuh_mounted(uint8_t dev_addr); - -// Check if device is suspended -static inline bool tuh_suspended(uint8_t dev_addr) -{ - // TODO implement suspend & resume on host - (void) dev_addr; - return false; -} - -// Check if device is ready to communicate with -TU_ATTR_ALWAYS_INLINE -static inline bool tuh_ready(uint8_t dev_addr) -{ - return tuh_mounted(dev_addr) && !tuh_suspended(dev_addr); -} - -// Carry out control transfer -bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); - -//--------------------------------------------------------------------+ -// APPLICATION CALLBACK -//--------------------------------------------------------------------+ -//TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); - -// Invoked when device is mounted (configured) -TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); - -/// Invoked when device is unmounted (bus reset/unplugged) -TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h deleted file mode 100644 index 8bc2622aa..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBH_CLASSDRIVER_H_ -#define _TUSB_USBH_CLASSDRIVER_H_ - -#include "osal/osal.h" -#include "common/tusb_fifo.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver API -//--------------------------------------------------------------------+ - -typedef struct { - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - void (* const init )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); -} usbh_class_driver_t; - -// Call by class driver to tell USBH that it has complete the enumeration -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); - -//--------------------------------------------------------------------+ -// USBH Endpoint API -//--------------------------------------------------------------------+ - -// Open an endpoint -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); - -// Submit a usb transfer -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Claim an endpoint before submitting a transfer. -// If caller does not make any transfer, it must release endpoint for others. -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); - -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr); - -// Check if endpoint transferring is complete -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c deleted file mode 100644 index 9204576ac..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_HOST_ENABLED - -#include "tusb.h" -#include "usbh_classdriver.h" - -enum -{ - STAGE_SETUP, - STAGE_DATA, - STAGE_ACK -}; - -typedef struct -{ - tusb_control_request_t request TU_ATTR_ALIGNED(4); - - uint8_t stage; - uint8_t* buffer; - tuh_control_complete_cb_t complete_cb; -} usbh_control_xfer_t; - -static usbh_control_xfer_t _ctrl_xfer; - -//CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) -{ - // TODO need to claim the endpoint first - const uint8_t rhport = usbh_get_rhport(dev_addr); - - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = buffer; - _ctrl_xfer.stage = STAGE_SETUP; - _ctrl_xfer.complete_cb = complete_cb; - - TU_LOG2("Control Setup (addr = %u): ", dev_addr); - TU_LOG2_VAR(request); - TU_LOG2("\r\n"); - - // Send setup packet - TU_ASSERT( hcd_setup_send(rhport, dev_addr, (uint8_t const*) &_ctrl_xfer.request) ); - - return true; -} - -static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) -{ - TU_LOG2("\r\n"); - if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); -} - -bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) ep_addr; - (void) xferred_bytes; - - const uint8_t rhport = usbh_get_rhport(dev_addr); - - tusb_control_request_t const * request = &_ctrl_xfer.request; - - if (XFER_RESULT_SUCCESS != result) - { - TU_LOG2("Control failed: result = %d\r\n", result); - - // terminate transfer if any stage failed - _xfer_complete(dev_addr, result); - }else - { - switch(_ctrl_xfer.stage) - { - case STAGE_SETUP: - _ctrl_xfer.stage = STAGE_DATA; - if (request->wLength) - { - // DATA stage: initial data toggle is always 1 - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); - return true; - } - __attribute__((fallthrough)); - - case STAGE_DATA: - _ctrl_xfer.stage = STAGE_ACK; - - if (request->wLength) - { - TU_LOG2("Control data (addr = %u):\r\n", dev_addr); - TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); - } - - // ACK stage: toggle is always 1 - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); - break; - - case STAGE_ACK: - _xfer_complete(dev_addr, result); - break; - - default: return false; - } - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h deleted file mode 100644 index c8131d19d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_H_ -#define _TUSB_OSAL_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -/** \addtogroup group_osal - * @{ */ - -#include "common/tusb_common.h" - -// Return immediately -#define OSAL_TIMEOUT_NOTIMEOUT (0) -// Default timeout -#define OSAL_TIMEOUT_NORMAL (10) -// Wait forever -#define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX) - -#define OSAL_TIMEOUT_CONTROL_XFER OSAL_TIMEOUT_WAIT_FOREVER - -typedef void (*osal_task_func_t)( void * ); - -#if CFG_TUSB_OS == OPT_OS_NONE - #include "osal_none.h" -#elif CFG_TUSB_OS == OPT_OS_FREERTOS - #include "osal_freertos.h" -#elif CFG_TUSB_OS == OPT_OS_MYNEWT - #include "osal_mynewt.h" -#elif CFG_TUSB_OS == OPT_OS_PICO - #include "osal_pico.h" -#elif CFG_TUSB_OS == OPT_OS_RTTHREAD - #include "osal_rtthread.h" -#elif CFG_TUSB_OS == OPT_OS_CUSTOM - #include "tusb_os_custom.h" // implemented by application -#else - #error OS is not supported yet -#endif - -//--------------------------------------------------------------------+ -// OSAL Porting API -//--------------------------------------------------------------------+ - -#if __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wredundant-decls" -#endif -//------------- Semaphore -------------// -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); -static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec); - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed - -//------------- Mutex -------------// -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef); -static inline bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec); -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl); - -//------------- Queue -------------// -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef); -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data); -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); -static inline bool osal_queue_empty(osal_queue_t qhdl); -#if __GNUC__ -#pragma GCC diagnostic pop -#endif - -#if 0 // TODO remove subtask related macros later -// Sub Task -#define OSAL_SUBTASK_BEGIN -#define OSAL_SUBTASK_END return TUSB_ERROR_NONE; - -#define STASK_RETURN(_error) return _error; -#define STASK_INVOKE(_subtask, _status) (_status) = _subtask -#define STASK_ASSERT(_cond) TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) -#endif - -#ifdef __cplusplus - } -#endif - -/** @} */ - -#endif /* _TUSB_OSAL_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h deleted file mode 100644 index 4573e01f5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_FREERTOS_H_ -#define _TUSB_OSAL_FREERTOS_H_ - -// FreeRTOS Headers -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,semphr.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,queue.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,task.h) - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) -{ - vTaskDelay( pdMS_TO_TICKS(msec) ); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef StaticSemaphore_t osal_semaphore_def_t; -typedef SemaphoreHandle_t osal_semaphore_t; - -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - return xSemaphoreCreateBinaryStatic(semdef); -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - if ( !in_isr ) - { - return xSemaphoreGive(sem_hdl) != 0; - } - else - { - BaseType_t xHigherPriorityTaskWoken; - BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - - return res != 0; - } -} - -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(msec); - return xSemaphoreTake(sem_hdl, ticks); -} - -static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) -{ - xQueueReset(sem_hdl); -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef StaticSemaphore_t osal_mutex_def_t; -typedef SemaphoreHandle_t osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - return xSemaphoreCreateMutexStatic(mdef); -} - -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return osal_semaphore_wait(mutex_hdl, msec); -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return xSemaphoreGive(mutex_hdl); -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - static _type _name##_##buf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - void* buf; - - StaticQueue_t sq; -}osal_queue_def_t; - -typedef QueueHandle_t osal_queue_t; - -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) -{ - return xQueueReceive(qhdl, data, portMAX_DELAY); -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - if ( !in_isr ) - { - return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0; - } - else - { - BaseType_t xHigherPriorityTaskWoken; - BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - - return res != 0; - } -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return uxQueueMessagesWaiting(qhdl) == 0; -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OSAL_FREERTOS_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h deleted file mode 100644 index 6882329c1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef OSAL_MYNEWT_H_ -#define OSAL_MYNEWT_H_ - -#include "os/os.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) -{ - os_time_delay( os_time_ms_to_ticks32(msec) ); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef struct os_sem osal_semaphore_def_t; -typedef struct os_sem* osal_semaphore_t; - -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - return (os_sem_init(semdef, 0) == OS_OK) ? (osal_semaphore_t) semdef : NULL; -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - return os_sem_release(sem_hdl) == OS_OK; -} - -static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); - return os_sem_pend(sem_hdl, ticks) == OS_OK; -} - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - // TODO implement later -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef struct os_mutex osal_mutex_def_t; -typedef struct os_mutex* osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - return (os_mutex_init(mdef) == OS_OK) ? (osal_mutex_t) mdef : NULL; -} - -static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); - return os_mutex_pend(mutex_hdl, ticks) == OS_OK; -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return os_mutex_release(mutex_hdl) == OS_OK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - static _type _name##_##buf[_depth];\ - static struct os_event _name##_##evbuf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, .evbuf = _name##_##evbuf};\ - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - void* buf; - void* evbuf; - - struct os_mempool mpool; - struct os_mempool epool; - - struct os_eventq evq; -}osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usbd queue") ) return NULL; - if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usbd evqueue") ) return NULL; - - os_eventq_init(&qdef->evq); - return (osal_queue_t) qdef; -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) -{ - struct os_event* ev; - ev = os_eventq_get(&qhdl->evq); - - memcpy(data, ev->ev_arg, qhdl->item_sz); // copy message - os_memblock_put(&qhdl->mpool, ev->ev_arg); // put back mem block - os_memblock_put(&qhdl->epool, ev); // put back ev block - - return true; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - (void) in_isr; - - // get a block from mem pool for data - void* ptr = os_memblock_get(&qhdl->mpool); - if (!ptr) return false; - memcpy(ptr, data, qhdl->item_sz); - - // get a block from event pool to put into queue - struct os_event* ev = (struct os_event*) os_memblock_get(&qhdl->epool); - if (!ev) - { - os_memblock_put(&qhdl->mpool, ptr); - return false; - } - tu_memclr(ev, sizeof(struct os_event)); - ev->ev_arg = ptr; - - os_eventq_put(&qhdl->evq, ev); - - return true; -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return STAILQ_EMPTY(&qhdl->evq.evq_list); -} - - -#ifdef __cplusplus - } -#endif - -#endif /* OSAL_MYNEWT_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h deleted file mode 100644 index a1f997cf2..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_NONE_H_ -#define _TUSB_OSAL_NONE_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ - - -//--------------------------------------------------------------------+ -// Binary Semaphore API -//--------------------------------------------------------------------+ -typedef struct -{ - volatile uint16_t count; -}osal_semaphore_def_t; - -typedef osal_semaphore_def_t* osal_semaphore_t; - -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - semdef->count = 0; - return semdef; -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - sem_hdl->count++; - return true; -} - -// TODO blocking for now -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ - (void) msec; - - while (sem_hdl->count == 0) { } - sem_hdl->count--; - - return true; -} - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - sem_hdl->count = 0; -} - -//--------------------------------------------------------------------+ -// MUTEX API -// Within tinyusb, mutex is never used in ISR context -//--------------------------------------------------------------------+ -typedef osal_semaphore_def_t osal_mutex_def_t; -typedef osal_semaphore_t osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - mdef->count = 1; - return mdef; -} - -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return osal_semaphore_wait(mutex_hdl, msec); -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return osal_semaphore_post(mutex_hdl, false); -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ -#include "common/tusb_fifo.h" - -// extern to avoid including dcd.h and hcd.h -#if TUSB_OPT_DEVICE_ENABLED -extern void dcd_int_disable(uint8_t rhport); -extern void dcd_int_enable(uint8_t rhport); -#endif - -#if TUSB_OPT_HOST_ENABLED -extern void hcd_int_disable(uint8_t rhport); -extern void hcd_int_enable(uint8_t rhport); -#endif - -typedef struct -{ - uint8_t role; // device or host - tu_fifo_t ff; -}osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .role = _role, \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } - -// lock queue by disable USB interrupt -static inline void _osal_q_lock(osal_queue_t qhdl) -{ - (void) qhdl; - -#if TUSB_OPT_DEVICE_ENABLED - if (qhdl->role == OPT_MODE_DEVICE) dcd_int_disable(TUD_OPT_RHPORT); -#endif - -#if TUSB_OPT_HOST_ENABLED - if (qhdl->role == OPT_MODE_HOST) hcd_int_disable(TUH_OPT_RHPORT); -#endif -} - -// unlock queue -static inline void _osal_q_unlock(osal_queue_t qhdl) -{ - (void) qhdl; - -#if TUSB_OPT_DEVICE_ENABLED - if (qhdl->role == OPT_MODE_DEVICE) dcd_int_enable(TUD_OPT_RHPORT); -#endif - -#if TUSB_OPT_HOST_ENABLED - if (qhdl->role == OPT_MODE_HOST) hcd_int_enable(TUH_OPT_RHPORT); -#endif -} - -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - tu_fifo_clear(&qdef->ff); - return (osal_queue_t) qdef; -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) -{ - _osal_q_lock(qhdl); - bool success = tu_fifo_read(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - return success; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - if (!in_isr) { - _osal_q_lock(qhdl); - } - - bool success = tu_fifo_write(&qhdl->ff, data); - - if (!in_isr) { - _osal_q_unlock(qhdl); - } - - TU_ASSERT(success); - - return success; -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - // Skip queue lock/unlock since this function is primarily called - // with interrupt disabled before going into low power mode - return tu_fifo_empty(&qhdl->ff); -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OSAL_NONE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h deleted file mode 100644 index 1c3366e01..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_PICO_H_ -#define _TUSB_OSAL_PICO_H_ - -#include "pico/time.h" -#include "pico/sem.h" -#include "pico/mutex.h" -#include "pico/critical_section.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) -{ - sleep_ms(msec); -} - -//--------------------------------------------------------------------+ -// Binary Semaphore API -//--------------------------------------------------------------------+ -typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; - -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - sem_init(semdef, 0, 255); - return semdef; -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - sem_release(sem_hdl); - return true; -} - -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ - return sem_acquire_timeout_ms(sem_hdl, msec); -} - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - sem_reset(sem_hdl, 0); -} - -//--------------------------------------------------------------------+ -// MUTEX API -// Within tinyusb, mutex is never used in ISR context -//--------------------------------------------------------------------+ -typedef struct mutex osal_mutex_def_t, *osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - mutex_init(mdef); - return mdef; -} - -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return mutex_enter_timeout_ms(mutex_hdl, msec); -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - mutex_exit(mutex_hdl); - return true; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ -#include "common/tusb_fifo.h" - -#if TUSB_OPT_HOST_ENABLED -extern void hcd_int_disable(uint8_t rhport); -extern void hcd_int_enable(uint8_t rhport); -#endif - -typedef struct -{ - tu_fifo_t ff; - struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section -} osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } - -// lock queue by disable USB interrupt -static inline void _osal_q_lock(osal_queue_t qhdl) -{ - critical_section_enter_blocking(&qhdl->critsec); -} - -// unlock queue -static inline void _osal_q_unlock(osal_queue_t qhdl) -{ - critical_section_exit(&qhdl->critsec); -} - -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - critical_section_init(&qdef->critsec); - tu_fifo_clear(&qdef->ff); - return (osal_queue_t) qdef; -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) -{ - // TODO: revisit... docs say that mutexes are never used from IRQ context, - // however osal_queue_recieve may be. therefore my assumption is that - // the fifo mutex is not populated for queues used from an IRQ context - //assert(!qhdl->ff.mutex); - - _osal_q_lock(qhdl); - bool success = tu_fifo_read(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - return success; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - // TODO: revisit... docs say that mutexes are never used from IRQ context, - // however osal_queue_recieve may be. therefore my assumption is that - // the fifo mutex is not populated for queues used from an IRQ context - //assert(!qhdl->ff.mutex); - (void) in_isr; - - _osal_q_lock(qhdl); - bool success = tu_fifo_write(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - TU_ASSERT(success); - - return success; -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - // TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single - // volatile read. - - // Skip queue lock/unlock since this function is primarily called - // with interrupt disabled before going into low power mode - return tu_fifo_empty(&qhdl->ff); -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OSAL_PICO_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h deleted file mode 100644 index d5c062ac1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 tfx2001 (2479727366@qq.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_RTTHREAD_H_ -#define _TUSB_OSAL_RTTHREAD_H_ - -// RT-Thread Headers -#include "rtthread.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) { - rt_thread_mdelay(msec); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef struct rt_semaphore osal_semaphore_def_t; -typedef rt_sem_t osal_semaphore_t; - -static inline osal_semaphore_t -osal_semaphore_create(osal_semaphore_def_t *semdef) { - rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_FIFO); - return semdef; -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - (void) in_isr; - return rt_sem_release(sem_hdl) == RT_EOK; -} - -static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { - return rt_sem_take(sem_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; -} - -static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { - // TODO: implement -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef struct rt_mutex osal_mutex_def_t; -typedef rt_mutex_t osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { - rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_FIFO); - return mdef; -} - -static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { - return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { - return rt_mutex_release(mutex_hdl) == RT_EOK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - static _type _name##_##buf[_depth]; \ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; - -typedef struct { - uint16_t depth; - uint16_t item_sz; - void *buf; - - struct rt_messagequeue sq; -} osal_queue_def_t; - -typedef rt_mq_t osal_queue_t; - -static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { - rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz, - qdef->item_sz * qdef->depth, RT_IPC_FLAG_FIFO); - return &(qdef->sq); -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void *data) { - return rt_mq_recv(qhdl, data, qhdl->msg_size, RT_WAITING_FOREVER) == RT_EOK; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { - (void) in_isr; - return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK; -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) { - return (qhdl->entry) == 0; -} - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_OSAL_RTTHREAD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c deleted file mode 100644 index a9c311324..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ /dev/null @@ -1,854 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && TUSB_OPT_DEVICE_ENABLED) - -// Espressif -#include "freertos/xtensa_api.h" -#include "esp_intr_alloc.h" -#include "esp_log.h" -#include "driver/gpio.h" -#include "soc/dport_reg.h" -#include "soc/gpio_sig_map.h" -#include "soc/usb_periph.h" -#include "soc/periph_defs.h" // for interrupt source - -#include "device/dcd.h" - -// Max number of bi-directional endpoints including EP0 -// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 -// We should probably prohibit enabling Endpoint IN > 4 (not done yet) -#define EP_MAX USB_OUT_EP_NUM - -// FIFO size in bytes -#define EP_FIFO_SIZE 1024 - -// Max number of IN EP FIFOs -#define EP_FIFO_NUM 5 - -typedef struct { - uint8_t *buffer; - // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API - uint16_t total_len; - uint16_t queued_len; - uint16_t max_size; - bool short_packet; -} xfer_ctl_t; - -static const char *TAG = "TUSB:DCD"; -static intr_handle_t usb_ih; - - -static uint32_t _setup_packet[2]; - -#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] -static xfer_ctl_t xfer_status[EP_MAX][2]; - -// Keep count of how many FIFOs are in use -static uint8_t _allocated_fifos = 1; //FIFO0 is always in use - -// Will either return an unused FIFO number, or 0 if all are used. -static uint8_t get_free_fifo(void) -{ - if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; - return 0; -} - -// Setup the control endpoint 0. -static void bus_reset(void) -{ - for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { - USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // clear device address - USB0.dcfg &= ~USB_DEVADDR_M; - - USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; - USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK; - USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; - - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): - // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN - // - // - All EP OUT shared a unique OUT FIFO which uses - // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). - // * 2 locations for OUT endpoint control words. - // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) - // * 1 location for global NAK (not required/used here). - // * It is recommended to allocate 2 times the largest packet size, therefore - // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 - USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, - USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo - USB0.grxfsiz = 52; - - // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); - - // Ready to receive SETUP packet - USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; - - USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; -} - -static void enum_done_processing(void) -{ - ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); - // On current silicon on the Full Speed core, speed is fixed to Full Speed. - // However, keep for debugging and in case Low Speed is ever supported. - uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); - - // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL - if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) - USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } else { - USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } -} - - -/*------------------------------------------------------------------*/ -/* Controller API - *------------------------------------------------------------------*/ -void dcd_init(uint8_t rhport) -{ - ESP_LOGV(TAG, "DCD init - Start"); - - // A. Disconnect - ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); - USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect - - // B. Programming DCFG - /* If USB host misbehaves during status portion of control xfer - (non zero-length packet), send STALL back and discard. Full speed. */ - USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL - (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) - - USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON - USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode - USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides - - // C. Setting SNAKs, then connect - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // D. Interruption masking - USB0.gintmsk = 0; //mask all - USB0.gotgint = ~0U; //clear OTG ints - USB0.gintsts = ~0U; //clear pending ints - USB0.gintmsk = USB_OTGINTMSK_M | - USB_MODEMISMSK_M | - USB_RXFLVIMSK_M | - USB_ERLYSUSPMSK_M | - USB_USBSUSPMSK_M | - USB_USBRSTMSK_M | - USB_ENUMDONEMSK_M | - USB_RESETDETMSK_M | - USB_DISCONNINTMSK_M; // host most only - - dcd_connect(rhport); -} - -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void)rhport; - ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); - USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); - // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} - -void dcd_remote_wakeup(uint8_t rhport) -{ - (void)rhport; - - // set remote wakeup - USB0.dctl |= USB_RMTWKUPSIG_M; - - // enable SOF to detect bus resume - USB0.gintsts = USB_SOF_M; - USB0.gintmsk |= USB_SOFMSK_M; - - // Per specs: remote wakeup signal bit must be clear within 1-15ms - vTaskDelay(pdMS_TO_TICKS(1)); - - USB0.dctl &= ~USB_RMTWKUPSIG_M; -} - -// connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - USB0.dctl &= ~USB_SFTDISCON_M; -} - -// disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - USB0.dctl |= USB_SFTDISCON_M; -} - -/*------------------------------------------------------------------*/ -/* DCD Endpoint port - *------------------------------------------------------------------*/ - -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) -{ - ESP_LOGV(TAG, "DCD endpoint opened"); - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - TU_ASSERT(epnum < EP_MAX); - - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = tu_edpt_packet_size(desc_edpt); - - if (dir == TUSB_DIR_OUT) { - out_ep[epnum].doepctl |= USB_USBACTEP1_M | - desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) | - xfer->max_size << USB_MPS1_S; - USB0.daintmsk |= (1 << (16 + epnum)); - } else { - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints - // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) - // - Offset: GRXFSIZ + 16 + Size*(epnum-1) - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - - uint8_t fifo_num = get_free_fifo(); - TU_ASSERT(fifo_num != 0); - - in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); - in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | - fifo_num << USB_D_TXFNUM1_S | - desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | - xfer->max_size << 0; - - USB0.daintmsk |= (1 << (0 + epnum)); - - // Both TXFD and TXSA are in unit of 32-bit words. - // IN FIFO 0 was configured during enumeration, hence the "+ 16". - uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); - uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); - - // DIEPTXF starts at FIFO #1. - USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; - } - return true; -} - -void dcd_edpt_close_all(uint8_t rhport) -{ - (void) rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - // Disable non-control interrupt - USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; - - for(uint8_t n = 1; n < EP_MAX; n++) - { - // disable OUT endpoint - out_ep[n].doepctl = 0; - xfer_status[n][TUSB_DIR_OUT].max_size = 0; - - // disable IN endpoint - in_ep[n].diepctl = 0; - xfer_status[n][TUSB_DIR_IN].max_size = 0; - } - - _allocated_fifos = 1; -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) -{ - (void)rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; - - uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } - - ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", - epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), - num_packets, total_bytes); - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. - if (dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; - USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) { - USB0.dtknqr4_fifoemptymsk |= (1 << epnum); - } - } else { - // Each complete packet for OUT xfers triggers XFRC. - USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - return true; -} - -#if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - (void)rhport; -} -#endif - -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); - } else { - // Stop transmitting packets and NAK IN xfers. - in_ep[epnum].diepctl |= USB_DI_SNAK1_M; - while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ; - - // Disable the endpoint. Note that both SNAK and STALL are set here. - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M); - while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ; - in_ep[epnum].diepint = USB_D_EPDISBLD0_M; - } - - // Flush the FIFO, and wait until we have confirmed it cleared. - uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V); - USB0.grstctl |= (fifo_num << USB_TXFNUM_S); - USB0.grstctl |= USB_TXFFLSH_M; - while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; - } else { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { - out_ep[epnum].doepctl |= USB_STALL0_M; - } else { - // Asserting GONAK is required to STALL an OUT endpoint. - // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt - // anyway, and it can't be cleared by user code. If this while loop never - // finishes, we have bigger problems than just the stack. - USB0.dctl |= USB_SGOUTNAK_M; - while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ; - - // Ditto here- disable the endpoint. Note that only STALL and not SNAK - // is set here. - out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); - while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ; - out_ep[epnum].doepint = USB_EPDISBLD0_M; - - // Allow other OUT endpoints to keep receiving. - USB0.dctl |= USB_CGOUTNAK_M; - } - } -} - -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - in_ep[epnum].diepctl &= ~USB_D_STALL1_M; - - uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; - } - } else { - out_ep[epnum].doepctl &= ~USB_STALL1_M; - - uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; - } - } -} - -/*------------------------------------------------------------------*/ - -static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) -{ - ESP_EARLY_LOGV(TAG, "USB - receive_packet"); - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // See above TODO - // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; - // xfer->queued_len = xfer->total_len - remaining; - - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - if (remaining <= xfer->max_size) { - // Avoid buffer overflow. - to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; - } else { - // Room for full packet, choose recv_size based on what the microcontroller - // claims. - to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; - } - - // Common buffer read -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - // Ring buffer - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); - } - else -#endif - { - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - // Do not assume xfer buffer is aligned. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if (to_recv_size >= 4) { - for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (*rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; - } - } - - // Do not read invalid bytes from RX FIFO. - if (to_recv_rem != 0) { - uint32_t tmp = (*rx_fifo); - uint8_t *last_32b_bound = base + to_recv_size_aligned; - - last_32b_bound[0] = tmp & 0x000000FF; - if (to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; - } - if (to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; - } - } - } - - xfer->queued_len += xfer_size; - - // Per USB spec, a short OUT packet (including length 0) is always - // indicative of the end of a transfer (at least for ctl, bulk, int). - xfer->short_packet = (xfer_size < xfer->max_size); -} - -static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) -{ - ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); - volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; - - uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; - xfer->queued_len = xfer->total_len - remaining; - - uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); - } - else -#endif - { - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - - // Buffer might not be aligned to 32b, so we need to force alignment - // by copying to a temp var. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to send off. - if (to_xfer_size >= 4) { - for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { - uint32_t tmp = base[i] | (base[i + 1] << 8) | - (base[i + 2] << 16) | (base[i + 3] << 24); - (*tx_fifo) = tmp; - } - } - - // Do not read beyond end of buffer if not divisible by 4. - if (to_xfer_rem != 0) { - uint32_t tmp = 0; - uint8_t *last_32b_bound = base + to_xfer_size_aligned; - - tmp |= last_32b_bound[0]; - if (to_xfer_rem > 1) { - tmp |= (last_32b_bound[1] << 8); - } - if (to_xfer_rem > 2) { - tmp |= (last_32b_bound[2] << 16); - } - - (*tx_fifo) = tmp; - } - } -} - -static void read_rx_fifo(void) -{ - // Pop control word off FIFO (completed xfers will have 2 control words, - // we only pop one ctl word each interrupt). - uint32_t const ctl_word = USB0.grxstsp; - uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; - uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; - uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; - - switch (pktsts) { - case 0x01: // Global OUT NAK (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); - break; - - case 0x02: { // Out packet recvd - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(xfer, bcnt); - } - break; - - case 0x03: // Out packet done (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); - break; - - case 0x04: // Step 2: Setup transaction completed (Interrupt) - // After this event, OEPINT interrupt will occur with SETUP bit set - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); - USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; - break; - - case 0x06: { // Step1: Setup data packet received - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // We can receive up to three setup packets in succession, but - // only the last one is valid. Therefore we just overwrite it - _setup_packet[0] = (*rx_fifo); - _setup_packet[1] = (*rx_fifo); - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); - } - break; - - default: // Invalid, do something here, like breakpoint? - TU_BREAKPOINT(); - break; - } -} - -static void handle_epout_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DOEPINTx is cleared. - // DOEPINT will be cleared when DAINT's out bits are cleared. - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); - - if (USB0.daint & (1 << (16 + n))) { - // SETUP packet Setup Phase done. - if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { - USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear - dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); - } - - // OUT XFER complete (single packet).q - if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); - USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; - - // Transfer complete if short packet or total len is transferred - if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { - xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - // Schedule another packet to be received. - USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - } - } - } -} - -static void handle_epin_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DIEPINTx is cleared. - // IEPINT will be cleared when DAINT's out bits are cleared. - for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { - xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; - - if (USB0.daint & (1 << (0 + n))) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); - // IN XFER complete (entire xfer). - if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); - USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - - // XFER FIFO empty - if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); - USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; - transmit_packet(xfer, &USB0.in_ep_reg[n], n); - - // Turn off TXFE if all bytes are written. - if (xfer->queued_len == xfer->total_len) - { - USB0.dtknqr4_fifoemptymsk &= ~(1 << n); - } - } - - // XFER Timeout - if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) { - // Clear interrupt or enpoint will hang. - USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M; - // Maybe retry? - } - } - } -} - - -static void _dcd_int_handler(void* arg) -{ - (void) arg; - uint8_t const rhport = 0; - - const uint32_t int_msk = USB0.gintmsk; - const uint32_t int_status = USB0.gintsts & int_msk; - - if (int_status & USB_USBRST_M) { - // start of reset - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); - USB0.gintsts = USB_USBRST_M; - // FIFOs will be reassigned when the endpoints are reopen - _allocated_fifos = 1; - bus_reset(); - } - - if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); - USB0.gintsts = USB_RESETDET_M; - bus_reset(); - } - - if (int_status & USB_ENUMDONE_M) { - // ENUMDNE detects speed of the link. For full-speed, we - // always expect the same value. This interrupt is considered - // the end of reset. - USB0.gintsts = USB_ENUMDONE_M; - enum_done_processing(); - dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); - } - - if(int_status & USB_USBSUSP_M) - { - USB0.gintsts = USB_USBSUSP_M; - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); - } - - if(int_status & USB_WKUPINT_M) - { - USB0.gintsts = USB_WKUPINT_M; - dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - } - - if (int_status & USB_OTGINT_M) - { - // OTG INT bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); - - uint32_t const otg_int = USB0.gotgint; - - if (otg_int & USB_SESENDDET_M) - { - dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); - } - - USB0.gotgint = otg_int; - } - - if (int_status & USB_SOF_M) { - USB0.gintsts = USB_SOF_M; - - // Disable SOF interrupt since currently only used for remote wakeup detection - USB0.gintmsk &= ~USB_SOFMSK_M; - - dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); - } - - - if (int_status & USB_RXFLVI_M) { - // RXFLVL bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); - - // Mask out RXFLVL while reading data from FIFO - USB0.gintmsk &= ~USB_RXFLVIMSK_M; - read_rx_fifo(); - USB0.gintmsk |= USB_RXFLVIMSK_M; - } - - // OUT endpoint interrupt handling. - if (int_status & USB_OEPINT_M) { - // OEPINT is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); - handle_epout_ints(); - } - - // IN endpoint interrupt handling. - if (int_status & USB_IEPINT_M) { - // IEPINT bit read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); - handle_epin_ints(); - } - - // Without handling - USB0.gintsts |= USB_CURMOD_INT_M | - USB_MODEMIS_M | - USB_OTGINT_M | - USB_NPTXFEMP_M | - USB_GINNAKEFF_M | - USB_GOUTNAKEFF | - USB_ERLYSUSP_M | - USB_USBSUSP_M | - USB_ISOOUTDROP_M | - USB_EOPF_M | - USB_EPMIS_M | - USB_INCOMPISOIN_M | - USB_INCOMPIP_M | - USB_FETSUSP_M | - USB_PTXFEMP_M; -} - -void dcd_int_enable (uint8_t rhport) -{ - (void) rhport; - esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih); -} - -void dcd_int_disable (uint8_t rhport) -{ - (void) rhport; - esp_intr_free(usb_ih); -} - -#endif // #if OPT_MCU_ESP32S2 || OPT_MCU_ESP32S3 - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c deleted file mode 100644 index 9583f509d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_HOST_ENABLED || TUSB_OPT_DEVICE_ENABLED - -#include "tusb.h" - -// TODO clean up -#if TUSB_OPT_DEVICE_ENABLED -#include "device/usbd_pvt.h" -#endif - -bool tusb_init(void) -{ -#if TUSB_OPT_DEVICE_ENABLED - TU_ASSERT ( tud_init(TUD_OPT_RHPORT) ); // init device stack -#endif - -#if TUSB_OPT_HOST_ENABLED - TU_ASSERT( tuh_init(TUH_OPT_RHPORT) ); // init host stack -#endif - - return true; -} - -bool tusb_inited(void) -{ - bool ret = false; - -#if TUSB_OPT_DEVICE_ENABLED - ret = ret || tud_inited(); -#endif - -#if TUSB_OPT_HOST_ENABLED - ret = ret || tuh_inited(); -#endif - - return ret; -} - -//--------------------------------------------------------------------+ -// Internal Helper for both Host and Device stack -//--------------------------------------------------------------------+ - -bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) -{ - uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); - - switch (desc_ep->bmAttributes.xfer) - { - case TUSB_XFER_ISOCHRONOUS: - { - uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - case TUSB_XFER_BULK: - if (speed == TUSB_SPEED_HIGH) - { - // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(max_packet_size == 512); - }else - { - // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(max_packet_size <= 64); - } - break; - - case TUSB_XFER_INTERRUPT: - { - uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - default: return false; - } - - return true; -} - -void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) -{ - uint8_t const* p_desc = (uint8_t const*) desc_itf; - uint8_t const* desc_end = p_desc + desc_len; - - while( p_desc < desc_end ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id); - ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; - } - - p_desc = tu_desc_next(p_desc); - } -} - -uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) -{ - uint8_t const* p_desc = (uint8_t const*) desc_itf; - uint16_t len = 0; - - while (itf_count--) - { - // Next on interface desc - len += tu_desc_len(desc_itf); - p_desc = tu_desc_next(p_desc); - - while (len < max_len) - { - // return on IAD regardless of itf count - if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; - - if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && - ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) - { - break; - } - - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - } - - return len; -} - -/*------------------------------------------------------------------*/ -/* Debug - *------------------------------------------------------------------*/ -#if CFG_TUSB_DEBUG -#include - -char const* const tusb_strerr[TUSB_ERROR_COUNT] = { ERROR_TABLE(ERROR_STRING) }; - -static void dump_str_line(uint8_t const* buf, uint16_t count) -{ - tu_printf(" |"); - - // each line is 16 bytes - for(uint16_t i=0; i= 0 ) - -// Which roothub port is configured as device -#define TUD_OPT_RHPORT ( ((CFG_TUSB_RHPORT0_MODE) & OPT_MODE_DEVICE) ? 0 : (((CFG_TUSB_RHPORT1_MODE) & OPT_MODE_DEVICE) ? 1 : -1) ) - -#if TUD_OPT_RHPORT == 0 -#define TUD_OPT_HIGH_SPEED ( (CFG_TUSB_RHPORT0_MODE) & OPT_MODE_HIGH_SPEED ) -#else -#define TUD_OPT_HIGH_SPEED ( (CFG_TUSB_RHPORT1_MODE) & OPT_MODE_HIGH_SPEED ) -#endif - -#define TUSB_OPT_DEVICE_ENABLED ( TUD_OPT_RHPORT >= 0 ) - -//--------------------------------------------------------------------+ -// COMMON OPTIONS -//--------------------------------------------------------------------+ - -// Debug enable to print out error message -#ifndef CFG_TUSB_DEBUG - #define CFG_TUSB_DEBUG 0 -#endif - -// place data in accessible RAM for usb controller -#ifndef CFG_TUSB_MEM_SECTION - #define CFG_TUSB_MEM_SECTION -#endif - -// alignment requirement of buffer used for endpoint transferring -#ifndef CFG_TUSB_MEM_ALIGN - #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) -#endif - -// OS selection -#ifndef CFG_TUSB_OS - #define CFG_TUSB_OS OPT_OS_NONE -#endif - -#ifndef CFG_TUSB_OS_INC_PATH - #define CFG_TUSB_OS_INC_PATH -#endif - -//-------------------------------------------------------------------- -// DEVICE OPTIONS -//-------------------------------------------------------------------- - -#ifndef CFG_TUD_ENDPOINT0_SIZE - #define CFG_TUD_ENDPOINT0_SIZE 64 -#endif - -#ifndef CFG_TUD_CDC - #define CFG_TUD_CDC 0 -#endif - -#ifndef CFG_TUD_MSC - #define CFG_TUD_MSC 0 -#endif - -#ifndef CFG_TUD_HID - #define CFG_TUD_HID 0 -#endif - -#ifndef CFG_TUD_AUDIO - #define CFG_TUD_AUDIO 0 -#endif - -#ifndef CFG_TUD_VIDEO - #define CFG_TUD_VIDEO 0 -#endif - -#ifndef CFG_TUD_MIDI - #define CFG_TUD_MIDI 0 -#endif - -#ifndef CFG_TUD_VENDOR - #define CFG_TUD_VENDOR 0 -#endif - -#ifndef CFG_TUD_USBTMC - #define CFG_TUD_USBTMC 0 -#endif - -#ifndef CFG_TUD_DFU_RUNTIME - #define CFG_TUD_DFU_RUNTIME 0 -#endif - -#ifndef CFG_TUD_DFU - #define CFG_TUD_DFU 0 -#endif - -#ifndef CFG_TUD_BTH - #define CFG_TUD_BTH 0 -#endif - -#ifndef CFG_TUD_ECM_RNDIS - #ifdef CFG_TUD_NET - #warning "CFG_TUD_NET is renamed to CFG_TUD_ECM_RNDIS" - #define CFG_TUD_ECM_RNDIS CFG_TUD_NET - #else - #define CFG_TUD_ECM_RNDIS 0 - #endif -#endif - -#ifndef CFG_TUD_NCM - #define CFG_TUD_NCM 0 -#endif - -//-------------------------------------------------------------------- -// HOST OPTIONS -//-------------------------------------------------------------------- -#if TUSB_OPT_HOST_ENABLED - #ifndef CFG_TUH_DEVICE_MAX - #define CFG_TUH_DEVICE_MAX 1 - #endif - - #ifndef CFG_TUH_ENUMERATION_BUFSIZE - #define CFG_TUH_ENUMERATION_BUFSIZE 256 - #endif -#endif // TUSB_OPT_HOST_ENABLED - -//------------- CLASS -------------// - -#ifndef CFG_TUH_HUB -#define CFG_TUH_HUB 0 -#endif - -#ifndef CFG_TUH_CDC -#define CFG_TUH_CDC 0 -#endif - -#ifndef CFG_TUH_HID -#define CFG_TUH_HID 0 -#endif - -#ifndef CFG_TUH_MIDI -#define CFG_TUH_MIDI 0 -#endif - -#ifndef CFG_TUH_MSC -#define CFG_TUH_MSC 0 -#endif - -#ifndef CFG_TUH_VENDOR -#define CFG_TUH_VENDOR 0 -#endif - -//--------------------------------------------------------------------+ -// Port Specific -// TUP stand for TinyUSB Port (can be renamed) -//--------------------------------------------------------------------+ - -//------------- Unaligned Memory -------------// - -// ARMv7+ (M3-M7, M23-M33) can access unaligned memory -#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) - #define TUP_ARCH_STRICT_ALIGN 0 -#else - #define TUP_ARCH_STRICT_ALIGN 1 -#endif - -// TUP_MCU_STRICT_ALIGN will overwrite TUP_ARCH_STRICT_ALIGN. -// In case TUP_MCU_STRICT_ALIGN = 1 and TUP_ARCH_STRICT_ALIGN =0, we will not reply on compiler -// to generate unaligned access code. -// LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM -#if TUD_OPT_HIGH_SPEED && (CFG_TUSB_MCU == OPT_MCU_LPC54XXX || CFG_TUSB_MCU == OPT_MCU_LPC55XX) - #define TUP_MCU_STRICT_ALIGN 1 -#else - #define TUP_MCU_STRICT_ALIGN 0 -#endif - - -//------------------------------------------------------------------ -// Configuration Validation -//------------------------------------------------------------------ -#if CFG_TUD_ENDPOINT0_SIZE > 64 - #error Control Endpoint Max Packet Size cannot be larger than 64 -#endif - -#endif /* _TUSB_OPTION_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/CMakeLists.txt new file mode 100644 index 000000000..637991e7c --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.22) +project(libusb_test + LANGUAGES C +) + +add_executable(libusb_test libusb_test.c) +target_link_libraries(libusb_test -lusb-1.0) + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/libusb_test.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/libusb_test.c new file mode 100644 index 000000000..3c86f44e0 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/libusb_test.c @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define TINYUSB_VENDOR 0x303A +#define TINYUSB_PRODUCT 0x4002 + +#define DESC_TYPE_DEVICE_QUALIFIER 0x06 +#define DESC_TYOE_OTHER_SPEED_CONFIG 0x07 + +// Buffer for descriptor data +unsigned char buffer[512] = { 0 }; + +// USB Other Speed Configuration Descriptor +typedef struct __attribute__ ((packed)) +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + uint16_t wTotalLength ; ///< Total length of data returned + + uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration + uint8_t bConfigurationValue ; ///< Value to use to select configuration + uint8_t iConfiguration ; ///< Index of string descriptor + uint8_t bmAttributes ; ///< Same as Configuration descriptor + uint8_t bMaxPower ; ///< Same as Configuration descriptor +} desc_other_speed_t; + +// USB Device Qualifier Descriptor +typedef struct __attribute__ ((packed)) +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Device Qualifier Type + uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) + + uint8_t bDeviceClass ; ///< Class Code + uint8_t bDeviceSubClass ; ///< SubClass Code + uint8_t bDeviceProtocol ; ///< Protocol Code + + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed + uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations + uint8_t bReserved ; ///< Reserved for future use, must be zero +} desc_device_qualifier_t; + +// printf helpers +static void _print_device_qulifier_desc(unsigned char *buffer, int length); +static void _print_other_speed_desc(unsigned char *buffer, int length); + +// +// MAIN +// +int main() +{ + libusb_context *context = NULL; + int rc = 0; + + rc = libusb_init(&context); + assert(rc == 0); + libusb_device_handle *dev_handle = libusb_open_device_with_vid_pid(context, + TINYUSB_VENDOR, + TINYUSB_PRODUCT); + + if (dev_handle != NULL) { + printf("TinyUSB Device has been found\n"); + + // Test Qualifier Descriprtor + // 1. Get Qualifier Descriptor + // 2. print descriptor data + rc = libusb_get_descriptor(dev_handle, DESC_TYPE_DEVICE_QUALIFIER, 0, buffer, 512); + _print_device_qulifier_desc(buffer, rc); + + // Test Other Speed Descriptor + // 1. Get Other Speed Descriptor + // 2. print descriptor data + rc = libusb_get_descriptor(dev_handle, DESC_TYOE_OTHER_SPEED_CONFIG, 0, buffer, 512); + _print_other_speed_desc(buffer, rc); + + libusb_close(dev_handle); + } else { + printf("TinyUSB Device has NOT been found\n"); + } + + libusb_exit(context); +} + + +// ============================================================================= +static void _print_device_qulifier_desc(unsigned char *buffer, int length) +{ + assert(buffer); + desc_device_qualifier_t *qualifier_desc = (desc_device_qualifier_t *) buffer; + printf("========= Device Qualifier ========== \n"); + printf("\t bLength: %d \n", qualifier_desc->bLength); + printf("\t bDescriptorType: %d (%#x)\n", qualifier_desc->bDescriptorType, qualifier_desc->bDescriptorType); + printf("\t bcdUSB: %d (%#x) \n", qualifier_desc->bcdUSB, qualifier_desc->bcdUSB); + printf("\t bDeviceClass: %d (%#x) \n", qualifier_desc->bDeviceClass, qualifier_desc->bDeviceClass); + printf("\t bDeviceSubClass: %d \n", qualifier_desc->bDeviceSubClass); + printf("\t bDeviceProtocol: %d \n", qualifier_desc->bDeviceProtocol); + printf("\t bMaxPacketSize0: %d \n", qualifier_desc->bMaxPacketSize0); + printf("\t bNumConfigurations: %d \n", qualifier_desc->bNumConfigurations); +} + +static void _print_other_speed_desc(unsigned char *buffer, int length) +{ + assert(buffer); + desc_other_speed_t *other_speed = (desc_other_speed_t *) buffer; + printf("============ Other Speed ============ \n"); + printf("\t bLength: %d \n", other_speed->bLength); + printf("\t bDescriptorType: %d (%#x) \n", other_speed->bDescriptorType, other_speed->bDescriptorType); + printf("\t wTotalLength: %d \n", other_speed->wTotalLength); + printf("\t bNumInterfaces: %d \n", other_speed->bNumInterfaces); + printf("\t bConfigurationValue: %d \n", other_speed->bConfigurationValue); + printf("\t iConfiguration: %d \n", other_speed->iConfiguration); + printf("\t bmAttributes: %d (%#x) \n", other_speed->bmAttributes, other_speed->bmAttributes); + printf("\t bMaxPower: %d (%#x) \n", other_speed->bMaxPower, other_speed->bMaxPower); +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/CMakeLists.txt new file mode 100644 index 000000000..9298e904a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/CMakeLists.txt @@ -0,0 +1,11 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +# Set the components to include the tests for. +set(EXTRA_COMPONENT_DIRS + ../ + ) + +project(test_app_usb_device_esp_tinyusb) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/README.md b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/README.md new file mode 100644 index 000000000..c3b5e9e95 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/README.md @@ -0,0 +1,4 @@ +| Supported Targets | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | + +# USB: esp_tinyusb test application \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/CMakeLists.txt new file mode 100644 index 000000000..3cb6ad50a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/CMakeLists.txt @@ -0,0 +1,6 @@ +include($ENV{IDF_PATH}/tools/cmake/version.cmake) + +idf_component_register(SRC_DIRS . + INCLUDE_DIRS . + REQUIRES unity esp_tinyusb + WHOLE_ARCHIVE) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/idf_component.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/idf_component.yml new file mode 100644 index 000000000..43ab3419f --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/idf_component.yml @@ -0,0 +1,7 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/esp_tinyusb: + version: "*" + override_path: "../../" + rules: + - if: "idf_version >= 5.0" \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_app_main.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_app_main.c new file mode 100644 index 000000000..b25c8df7e --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_app_main.c @@ -0,0 +1,57 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "unity.h" +#include "esp_heap_caps.h" + +static size_t before_free_8bit; +static size_t before_free_32bit; + +#define TEST_MEMORY_LEAK_THRESHOLD (-530) +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + ssize_t delta = after_free - before_free; + printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); + TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak"); +} + +void app_main(void) +{ + // ____ ___ ___________________ __ __ + // | | \/ _____/\______ \ _/ |_ ____ _______/ |_ + // | | /\_____ \ | | _/ \ __\/ __ \ / ___/\ __\. + // | | / / \ | | \ | | \ ___/ \___ \ | | + // |______/ /_______ / |______ / |__| \___ >____ > |__| + // \/ \/ \/ \/ + printf(" ____ ___ ___________________ __ __ \r\n"); + printf("| | \\/ _____/\\______ \\ _/ |_ ____ _______/ |_ \r\n"); + printf("| | /\\_____ \\ | | _/ \\ __\\/ __ \\ / ___/\\ __\\\r\n"); + printf("| | / / \\ | | \\ | | \\ ___/ \\___ \\ | | \r\n"); + printf("|______/ /_______ / |______ / |__| \\___ >____ > |__| \r\n"); + printf(" \\/ \\/ \\/ \\/ \r\n"); + + UNITY_BEGIN(); + unity_run_menu(); + UNITY_END(); +} + +/* setUp runs before every test */ +void setUp(void) +{ + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +/* tearDown runs after every test */ +void tearDown(void) +{ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.c new file mode 100644 index 000000000..b596564f7 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.c @@ -0,0 +1,103 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" + +#if SOC_USB_OTG_SUPPORTED + +#include +#include +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_err.h" +#include "driver/gpio.h" +#include "esp_rom_gpio.h" +#include "soc/gpio_sig_map.h" +#include "unity.h" +#include "tinyusb.h" +#include "tusb_tasks.h" + +#define DEVICE_DETACH_TEST_ROUNDS 10 +#define DEVICE_DETACH_ROUND_DELAY_MS 1000 + +#if (CONFIG_IDF_TARGET_ESP32P4) +#define USB_SRP_BVALID_IN_IDX USB_SRP_BVALID_PAD_IN_IDX +#endif // CONFIG_IDF_TARGET_ESP32P4 + +/* TinyUSB descriptors + ********************************************************************* */ +#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN) + +static unsigned int dev_mounted = 0; +static unsigned int dev_umounted = 0; + +static uint8_t const test_configuration_descriptor[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), +}; + +static const tusb_desc_device_t test_device_descriptor = { + .bLength = sizeof(test_device_descriptor), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = 0x303A, // This is Espressif VID. This needs to be changed according to Users / Customers + .idProduct = 0x4002, + .bcdDevice = 0x100, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + .bNumConfigurations = 0x01 +}; + +void test_bvalid_sig_mount_cb(void) +{ + dev_mounted++; +} + +void test_bvalid_sig_umount_cb(void) +{ + dev_umounted++; +} + +TEST_CASE("bvalid_signal", "[esp_tinyusb][usb_device]") +{ + unsigned int rounds = DEVICE_DETACH_TEST_ROUNDS; + + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = test_configuration_descriptor, + }; + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + + dev_mounted = 0; + dev_umounted = 0; + + while (rounds--) { + // LOW to emulate disconnect USB device + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_SRP_BVALID_IN_IDX, false); + vTaskDelay(pdMS_TO_TICKS(DEVICE_DETACH_ROUND_DELAY_MS)); + // HIGH to emulate connect USB device + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, false); + vTaskDelay(pdMS_TO_TICKS(DEVICE_DETACH_ROUND_DELAY_MS)); + } + + // Verify + TEST_ASSERT_EQUAL(dev_umounted, dev_mounted); + TEST_ASSERT_EQUAL(DEVICE_DETACH_TEST_ROUNDS, dev_mounted); + + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); +} +#endif // SOC_USB_OTG_SUPPORTED diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.h new file mode 100644 index 000000000..82dd31b90 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test_bvalid_sig_mount_cb(void); +void test_bvalid_sig_umount_cb(void); + +#ifdef __cplusplus +} +#endif //__cplusplus diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.c new file mode 100644 index 000000000..2b92b5151 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.c @@ -0,0 +1,235 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" + +#if SOC_USB_OTG_SUPPORTED + +#include +#include +#include "esp_system.h" +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_log.h" +#include "esp_err.h" +#include "driver/gpio.h" +#include "esp_rom_gpio.h" +#include "soc/gpio_sig_map.h" +#include "unity.h" +#include "tinyusb.h" +#include "tusb_tasks.h" + +#define DEVICE_MOUNT_TIMEOUT_MS 5000 + +// ========================= TinyUSB descriptors =============================== +#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN) + +static uint8_t const test_fs_configuration_descriptor[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), +}; + +#if (TUD_OPT_HIGH_SPEED) +static uint8_t const test_hs_configuration_descriptor[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), +}; +#endif // TUD_OPT_HIGH_SPEED + +static const tusb_desc_device_t test_device_descriptor = { + .bLength = sizeof(test_device_descriptor), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = 0x303A, // This is Espressif VID. This needs to be changed according to Users / Customers + .idProduct = 0x4002, + .bcdDevice = 0x100, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + .bNumConfigurations = 0x01 +}; + +// ========================== Private logic ==================================== +SemaphoreHandle_t desc_config_device_mounted = NULL; + +static bool __test_prep(void) +{ + desc_config_device_mounted = xSemaphoreCreateBinary(); + return (desc_config_device_mounted != NULL); +} + +static esp_err_t __test_wait_conn(void) +{ + if (!desc_config_device_mounted) { + return ESP_ERR_INVALID_STATE; + } + + return ( xSemaphoreTake(desc_config_device_mounted, pdMS_TO_TICKS(DEVICE_MOUNT_TIMEOUT_MS)) + ? ESP_OK + : ESP_ERR_TIMEOUT ); +} + +static void __test_conn(void) +{ + if (desc_config_device_mounted) { + xSemaphoreGive(desc_config_device_mounted); + } +} + +static void __test_free(void) +{ + if (desc_config_device_mounted) { + vSemaphoreDelete(desc_config_device_mounted); + } +} + +// ========================== Callbacks ======================================== +// Invoked when device is mounted +void test_descriptors_config_mount_cb(void) +{ + __test_conn(); +} + +void test_descriptors_config_umount_cb(void) +{ + +} + +TEST_CASE("descriptors_config_all_default", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = NULL, + .configuration_descriptor = NULL, +#if (TUD_OPT_HIGH_SPEED) + .hs_configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_device", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = NULL, +#if (TUD_OPT_HIGH_SPEED) + .hs_configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_device_and_config", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = test_fs_configuration_descriptor, +#if (TUD_OPT_HIGH_SPEED) + .hs_configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +#if (TUD_OPT_HIGH_SPEED) +TEST_CASE("descriptors_config_device_and_fs_config_only", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = test_fs_configuration_descriptor, + .hs_configuration_descriptor = NULL, + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_device_and_hs_config_only", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = NULL, + .hs_configuration_descriptor = test_hs_configuration_descriptor, + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_all_configured", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .fs_configuration_descriptor = test_fs_configuration_descriptor, + .hs_configuration_descriptor = test_hs_configuration_descriptor, + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} +#endif // TUD_OPT_HIGH_SPEED + +#endif // SOC_USB_OTG_SUPPORTED diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.h new file mode 100644 index 000000000..6bdd77b7a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test_descriptors_config_mount_cb(void); +void test_descriptors_config_umount_cb(void); + +#ifdef __cplusplus +} +#endif //__cplusplus diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_esp_tinyusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_esp_tinyusb.c new file mode 100644 index 000000000..b71d48702 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_esp_tinyusb.c @@ -0,0 +1,132 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" +#if SOC_USB_OTG_SUPPORTED + +#include +#include +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_err.h" + +#include "unity.h" +#include "tinyusb.h" +#include "tusb_cdc_acm.h" +#include "vfs_tinyusb.h" + +#define VFS_PATH "/dev/usb-cdc1" + +// idf_component_register(WHOLE_ARCHIVE) backward compatibility to IDF_v4.4 +void linker_hook(void) {}; + +static const tusb_desc_device_t cdc_device_descriptor = { + .bLength = sizeof(cdc_device_descriptor), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = USB_ESPRESSIF_VID, + .idProduct = 0x4002, + .bcdDevice = 0x0100, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + .bNumConfigurations = 0x01 +}; + +static const uint16_t cdc_desc_config_len = TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN; +static const uint8_t cdc_desc_configuration[] = { + TUD_CONFIG_DESCRIPTOR(1, 4, 0, cdc_desc_config_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + TUD_CDC_DESCRIPTOR(0, 4, 0x81, 8, 0x02, 0x82, 64), + TUD_CDC_DESCRIPTOR(2, 4, 0x83, 8, 0x04, 0x84, 64), +}; + +static void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event) +{ +} + +/** + * @brief TinyUSB CDC testcase + * + * This is not a 'standard' testcase, as it never exits. The testcase runs in a loop where it echoes back all the data received. + * + * - Init TinyUSB with standard CDC device and configuration descriptors + * - Init 2 CDC-ACM interfaces + * - Map CDC1 to Virtual File System + * - In a loop: Read data from CDC0 and CDC1. Echo received data back + * + * Note: CDC0 appends 'novfs' to echoed data, so the host (test runner) can easily determine which port is which. + */ +TEST_CASE("tinyusb_cdc", "[esp_tinyusb]") +{ + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &cdc_device_descriptor, + .configuration_descriptor = cdc_desc_configuration + }; + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + + tinyusb_config_cdcacm_t acm_cfg = { + .usb_dev = TINYUSB_USBDEV_0, + .cdc_port = TINYUSB_CDC_ACM_0, + .rx_unread_buf_sz = 64, + .callback_rx = &tinyusb_cdc_rx_callback, + .callback_rx_wanted_char = NULL, + .callback_line_state_changed = NULL, + .callback_line_coding_changed = NULL + }; + + // Init CDC 0 + TEST_ASSERT_FALSE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_0)); + TEST_ASSERT_EQUAL(ESP_OK, tusb_cdc_acm_init(&acm_cfg)); + TEST_ASSERT_TRUE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_0)); + + // Init CDC 1 + acm_cfg.cdc_port = TINYUSB_CDC_ACM_1; + acm_cfg.callback_rx = NULL; + TEST_ASSERT_FALSE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_1)); + TEST_ASSERT_EQUAL(ESP_OK, tusb_cdc_acm_init(&acm_cfg)); + TEST_ASSERT_TRUE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_1)); + + // Install VFS to CDC 1 + TEST_ASSERT_EQUAL(ESP_OK, esp_vfs_tusb_cdc_register(TINYUSB_CDC_ACM_1, VFS_PATH)); + esp_vfs_tusb_cdc_set_rx_line_endings(ESP_LINE_ENDINGS_CRLF); + esp_vfs_tusb_cdc_set_tx_line_endings(ESP_LINE_ENDINGS_LF); + FILE *cdc = fopen(VFS_PATH, "r+"); + TEST_ASSERT_NOT_NULL(cdc); + + uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1]; + while (true) { + size_t b = fread(buf, 1, sizeof(buf), cdc); + if (b > 0) { + printf("Intf VFS, RX %d bytes\n", b); + //ESP_LOG_BUFFER_HEXDUMP("test", buf, b, ESP_LOG_INFO); + fwrite(buf, 1, b, cdc); + } + vTaskDelay(1); + + size_t rx_size = 0; + int itf = 0; + ESP_ERROR_CHECK(tinyusb_cdcacm_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size)); + if (rx_size > 0) { + printf("Intf %d, RX %d bytes\n", itf, rx_size); + + // Add 'novfs' to reply so the host can identify the port + strcpy((char *)&buf[rx_size - 2], "novfs\r\n"); + tinyusb_cdcacm_write_queue(itf, buf, rx_size + sizeof("novfs") - 1); + + tinyusb_cdcacm_write_flush(itf, 0); + } + } +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_tud_cb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_tud_cb.c new file mode 100644 index 000000000..37d0a3338 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_tud_cb.c @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "tinyusb.h" +#include "tusb_tasks.h" +#include "test_bvalid_sig.h" +#include "test_descriptors_config.h" + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + printf("%s\n", __FUNCTION__); + test_bvalid_sig_mount_cb(); + test_descriptors_config_mount_cb(); +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + printf("%s\n", __FUNCTION__); + test_bvalid_sig_umount_cb(); + test_descriptors_config_umount_cb(); +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_cdc.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_cdc.py new file mode 100644 index 000000000..1b48438a2 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_cdc.py @@ -0,0 +1,73 @@ +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import pytest +from pytest_embedded_idf.dut import IdfDut +from time import sleep +from serial import Serial +from serial.tools.list_ports import comports + + +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.usb_device +def test_usb_device_cdc(dut) -> None: + ''' + Running the test locally: + 1. Build the testa app for your DUT (ESP32-S2 or S3) + 2. Connect you DUT to your test runner (local machine) with USB port and flashing port + 3. Run `pytest --target esp32s3` + + Test procedure: + 1. Run the test on the DUT + 2. Expect 2 Virtual COM Ports in the system + 3. Open both comports and send some data. Expect echoed data + ''' + dut.expect_exact('Press ENTER to see the list of tests.') + dut.write('[esp_tinyusb]') + dut.expect_exact('TinyUSB: TinyUSB Driver installed') + sleep(2) # Some time for the OS to enumerate our USB device + + # Find devices with Espressif TinyUSB VID/PID + s = [] + ports = comports() + for port, _, hwid in ports: + if '303A:4002' in hwid: + s.append(port) + + if len(s) != 2: + raise Exception('TinyUSB COM port not found') + + with Serial(s[0]) as cdc0: + with Serial(s[1]) as cdc1: + # Write dummy string and check for echo + cdc0.write('text\r\n'.encode()) + res = cdc0.readline() + assert b'text' in res + if b'novfs' in res: + novfs_cdc = cdc0 + vfs_cdc = cdc1 + + cdc1.write('text\r\n'.encode()) + res = cdc1.readline() + assert b'text' in res + if b'novfs' in res: + novfs_cdc = cdc1 + vfs_cdc = cdc0 + + # Write more than MPS, check that the transfer is not divided + novfs_cdc.write(bytes(100)) + dut.expect_exact("Intf 0, RX 100 bytes") + + # Write more than RX buffer, check correct reception + novfs_cdc.write(bytes(600)) + transfer_len1 = int(dut.expect(r'Intf 0, RX (\d+) bytes')[1].decode()) + transfer_len2 = int(dut.expect(r'Intf 0, RX (\d+) bytes')[1].decode()) + assert transfer_len1 + transfer_len2 == 600 + + # The VFS is setup for CRLF RX and LF TX + vfs_cdc.write('text\r\n'.encode()) + res = vfs_cdc.readline() + assert b'text\n' in res + + return diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_esp_tinyusb.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_esp_tinyusb.py new file mode 100644 index 000000000..78765bcbb --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_esp_tinyusb.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import pytest +from pytest_embedded_idf.dut import IdfDut + + +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.usb_device +def test_usb_device_esp_tinyusb(dut: IdfDut) -> None: + dut.run_all_single_board_cases(group='usb_device') diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/sdkconfig.defaults b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/sdkconfig.defaults new file mode 100644 index 000000000..e68b6cd87 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/sdkconfig.defaults @@ -0,0 +1,19 @@ +# Configure TinyUSB, it will be used to mock USB devices +CONFIG_TINYUSB=y +CONFIG_TINYUSB_MSC_ENABLED=n +CONFIG_TINYUSB_CDC_ENABLED=y +CONFIG_TINYUSB_CDC_COUNT=2 +CONFIG_TINYUSB_HID_COUNT=0 + +# Disable watchdogs, they'd get triggered during unity interactive menu +CONFIG_ESP_INT_WDT=n +CONFIG_ESP_TASK_WDT=n + +# Run-time checks of Heap and Stack +CONFIG_HEAP_POISONING_COMPREHENSIVE=y +CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y +CONFIG_COMPILER_STACK_CHECK=y + +CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y + +CONFIG_COMPILER_CXX_EXCEPTIONS=y diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb.c similarity index 53% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb.c index a081030c3..52bc2aebc 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,7 +13,6 @@ #include "soc/usb_pins.h" #include "tinyusb.h" #include "descriptors_control.h" -#include "usb_descriptors.h" #include "tusb.h" #include "tusb_tasks.h" @@ -22,10 +21,7 @@ static usb_phy_handle_t phy_hdl; esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) { - const tusb_desc_device_t *dev_descriptor; - const char **string_descriptor; - const uint8_t *cfg_descriptor; - ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "Config can't be NULL"); // Configure USB PHY usb_phy_config_t phy_conf = { @@ -56,38 +52,22 @@ esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) } ESP_RETURN_ON_ERROR(usb_new_phy(&phy_conf, &phy_hdl), TAG, "Install USB PHY failed"); - if (config->configuration_descriptor) { - cfg_descriptor = config->configuration_descriptor; - } else { -#if (CONFIG_TINYUSB_HID_COUNT > 0 || CONFIG_TINYUSB_MIDI_COUNT > 0) - // For HID device, configuration descriptor must be provided - ESP_RETURN_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for this device"); -#else - cfg_descriptor = descriptor_cfg_kconfig; - ESP_LOGW(TAG, "The device's configuration descriptor is not provided by user, using default."); -#endif - } - - if (config->string_descriptor) { - string_descriptor = config->string_descriptor; - } else { - string_descriptor = descriptor_str_kconfig; - ESP_LOGW(TAG, "The device's string descriptor is not provided by user, using default."); - } - - if (config->device_descriptor) { - dev_descriptor = config->device_descriptor; - } else { - dev_descriptor = &descriptor_dev_kconfig; - ESP_LOGW(TAG, "The device's device descriptor is not provided by user, using default."); - } - - tusb_set_descriptor(dev_descriptor, string_descriptor, cfg_descriptor); + // Descriptors config + ESP_RETURN_ON_ERROR(tinyusb_set_descriptors(config), TAG, "Descriptors config failed"); + // Init +#if !CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK ESP_RETURN_ON_FALSE(tusb_init(), ESP_FAIL, TAG, "Init TinyUSB stack failed"); +#endif #if !CONFIG_TINYUSB_NO_DEFAULT_TASK ESP_RETURN_ON_ERROR(tusb_run_task(), TAG, "Run TinyUSB task failed"); #endif ESP_LOGI(TAG, "TinyUSB Driver installed"); return ESP_OK; } + +esp_err_t tinyusb_driver_uninstall() +{ + tinyusb_free_descriptors(); + return usb_del_phy(phy_hdl); +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb_net.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb_net.c new file mode 100644 index 000000000..f7390d763 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb_net.c @@ -0,0 +1,174 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "tinyusb_net.h" +#include "descriptors_control.h" +#include "usb_descriptors.h" +#include "device/usbd_pvt.h" +#include "esp_check.h" + +#define MAC_ADDR_LEN 6 + +typedef struct packet { + void *buffer; + void *buff_free_arg; + uint16_t len; + esp_err_t result; +} packet_t; + +struct tinyusb_net_handle { + bool initialized; + SemaphoreHandle_t buffer_sema; + EventGroupHandle_t tx_flags; + tusb_net_rx_cb_t rx_cb; + tusb_net_free_tx_cb_t tx_buff_free_cb; + tusb_net_init_cb_t init_cb; + char mac_str[2 * MAC_ADDR_LEN + 1]; + void *ctx; + packet_t *packet_to_send; +}; + +const static int TX_FINISHED_BIT = BIT0; +static struct tinyusb_net_handle s_net_obj = { }; +static const char *TAG = "tusb_net"; + +static void do_send_sync(void *ctx) +{ + (void) ctx; + if (xSemaphoreTake(s_net_obj.buffer_sema, 0) != pdTRUE || s_net_obj.packet_to_send == NULL) { + return; + } + + packet_t *packet = s_net_obj.packet_to_send; + if (tud_network_can_xmit(packet->len)) { + tud_network_xmit(packet, packet->len); + packet->result = ESP_OK; + } else { + packet->result = ESP_FAIL; + } + xSemaphoreGive(s_net_obj.buffer_sema); + xEventGroupSetBits(s_net_obj.tx_flags, TX_FINISHED_BIT); +} + +static void do_send_async(void *ctx) +{ + packet_t *packet = ctx; + if (tud_network_can_xmit(packet->len)) { + tud_network_xmit(packet, packet->len); + } else if (s_net_obj.tx_buff_free_cb) { + ESP_LOGW(TAG, "Packet cannot be accepted on USB interface, dropping"); + s_net_obj.tx_buff_free_cb(packet->buff_free_arg, s_net_obj.ctx); + } + free(packet); +} + +esp_err_t tinyusb_net_send_async(void *buffer, uint16_t len, void *buff_free_arg) +{ + if (!tud_ready()) { + return ESP_ERR_INVALID_STATE; + } + + packet_t *packet = calloc(1, sizeof(packet_t)); + packet->len = len; + packet->buffer = buffer; + packet->buff_free_arg = buff_free_arg; + ESP_RETURN_ON_FALSE(packet, ESP_ERR_NO_MEM, TAG, "Failed to allocate packet to send"); + usbd_defer_func(do_send_async, packet, false); + return ESP_OK; +} + +esp_err_t tinyusb_net_send_sync(void *buffer, uint16_t len, void *buff_free_arg, TickType_t timeout) +{ + if (!tud_ready()) { + return ESP_ERR_INVALID_STATE; + } + + // Lazy init the flags and semaphores, as they might not be needed (if async approach is used) + if (!s_net_obj.tx_flags) { + s_net_obj.tx_flags = xEventGroupCreate(); + ESP_RETURN_ON_FALSE(s_net_obj.tx_flags, ESP_ERR_NO_MEM, TAG, "Failed to allocate event flags"); + } + if (!s_net_obj.buffer_sema) { + s_net_obj.buffer_sema = xSemaphoreCreateBinary(); + ESP_RETURN_ON_FALSE(s_net_obj.buffer_sema, ESP_ERR_NO_MEM, TAG, "Failed to allocate buffer semaphore"); + } + + packet_t packet = { + .buffer = buffer, + .len = len, + .buff_free_arg = buff_free_arg + }; + s_net_obj.packet_to_send = &packet; + xSemaphoreGive(s_net_obj.buffer_sema); // now the packet is ready, let's mark it available to tusb send + + // to execute the send function in tinyUSB task context + usbd_defer_func(do_send_sync, NULL, false); // arg=NULL -> sync send, we keep the packet inside the object + + // wait wor completion with defined timeout + EventBits_t bits = xEventGroupWaitBits(s_net_obj.tx_flags, TX_FINISHED_BIT, pdTRUE, pdTRUE, timeout); + xSemaphoreTake(s_net_obj.buffer_sema, portMAX_DELAY); // if tusb sending already started, we have wait before ditching the packet + s_net_obj.packet_to_send = NULL; // invalidate the argument + if (bits & TX_FINISHED_BIT) { // If transaction finished, return error code + return packet.result; + } + return ESP_ERR_TIMEOUT; +} + +esp_err_t tinyusb_net_init(tinyusb_usbdev_t usb_dev, const tinyusb_net_config_t *cfg) +{ + (void) usb_dev; + + ESP_RETURN_ON_FALSE(s_net_obj.initialized == false, ESP_ERR_INVALID_STATE, TAG, "TinyUSB Net class is already initialized"); + + // the semaphore and event flags are initialized only if needed + s_net_obj.rx_cb = cfg->on_recv_callback; + s_net_obj.init_cb = cfg->on_init_callback; + s_net_obj.tx_buff_free_cb = cfg->free_tx_buffer; + s_net_obj.ctx = cfg->user_context; + + const uint8_t *mac = &cfg->mac_addr[0]; + snprintf(s_net_obj.mac_str, sizeof(s_net_obj.mac_str), "%02X%02X%02X%02X%02X%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + uint8_t mac_id = tusb_get_mac_string_id(); + // Pass it to Descriptor control module + tinyusb_set_str_descriptor(s_net_obj.mac_str, mac_id); + + s_net_obj.initialized = true; + + return ESP_OK; +} + +//--------------------------------------------------------------------+ +// tinyusb callbacks +//--------------------------------------------------------------------+ +bool tud_network_recv_cb(const uint8_t *src, uint16_t size) +{ + if (s_net_obj.rx_cb) { + s_net_obj.rx_cb((void *)src, size, s_net_obj.ctx); + } + tud_network_recv_renew(); + return true; +} + +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) +{ + packet_t *packet = ref; + uint16_t len = arg; + + memcpy(dst, packet->buffer, packet->len); + if (s_net_obj.tx_buff_free_cb) { + s_net_obj.tx_buff_free_cb(packet->buff_free_arg, s_net_obj.ctx); + } + return len; +} + +void tud_network_init_cb(void) +{ + if (s_net_obj.init_cb) { + s_net_obj.init_cb(s_net_obj.ctx); + } +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py deleted file mode 100644 index b2a80c680..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py +++ /dev/null @@ -1,100 +0,0 @@ -import os -import glob -import sys -import subprocess -import time - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -success_count = 0 -fail_count = 0 -skip_count = 0 -exit_status = 0 - -total_time = time.monotonic() - -build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |' -build_separator = '-' * 106 - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - -# If examples are not specified in arguments, build all -all_examples = [] -for entry in os.scandir("examples/device"): - if entry.is_dir(): - all_examples.append("device/" + entry.name) -for entry in os.scandir("examples/host"): - if entry.is_dir(): - all_examples.append("host/" + entry.name) -filter_with_input(all_examples) -all_examples.sort() - -# If boards are not specified in arguments, build all -all_boards = [] -for entry in os.scandir("hw/bsp"): - if entry.is_dir() and os.path.exists(entry.path + "/board.mk"): - all_boards.append(entry.name) -filter_with_input(all_boards) -all_boards.sort() - -def build_board(example, board): - global success_count, fail_count, skip_count, exit_status - start_time = time.monotonic() - flash_size = "-" - sram_size = "-" - - # Check if board is skipped - if build_utils.skip_example(example, board): - success = SKIPPED - skip_count += 1 - print(build_format.format(example, board, success, '-', flash_size, sram_size)) - else: - subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - if build_result.returncode == 0: - success = SUCCEEDED - success_count += 1 - (flash_size, sram_size) = build_size(example, board) - else: - exit_status = build_result.returncode - success = FAILED - fail_count += 1 - - build_duration = time.monotonic() - start_time - print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) - - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) - -def build_size(example, board): - #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) - elf_file = 'examples/{}/_build/{}/*.elf'.format(example, board) - size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") - size_list = size_output.split('\n')[1].split('\t') - flash_size = int(size_list[0]) - sram_size = int(size_list[1]) + int(size_list[2]) - return (flash_size, sram_size) - -print(build_separator) -print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) - -for example in all_examples: - print(build_separator) - for board in all_boards: - build_board(example, board) - -total_time = time.monotonic() - total_time -print(build_separator) -print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) -print(build_separator) - -sys.exit(exit_status) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py deleted file mode 100644 index 2947a0a6b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py +++ /dev/null @@ -1,101 +0,0 @@ -import os -import glob -import sys -import subprocess -import time - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -success_count = 0 -fail_count = 0 -skip_count = 0 -exit_status = 0 - -total_time = time.monotonic() - -build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |' -build_separator = '-' * 100 - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - -# Build all examples if not specified -all_examples = [] -for entry in os.scandir("examples/device"): - # Only includes example with CMakeLists.txt for esp32s, and skip board_test to speed up ci - if entry.is_dir() and os.path.exists(entry.path + "/sdkconfig.defaults") and entry.name != 'board_test': - all_examples.append(entry.name) -filter_with_input(all_examples) -all_examples.sort() - -# Build all boards if not specified -all_boards = [] -for entry in os.scandir("hw/bsp/esp32s2/boards"): - if entry.is_dir(): - all_boards.append(entry.name) -for entry in os.scandir("hw/bsp/esp32s3/boards"): - if entry.is_dir(): - all_boards.append(entry.name) -filter_with_input(all_boards) -all_boards.sort() - -def build_board(example, board): - global success_count, fail_count, skip_count, exit_status - start_time = time.monotonic() - flash_size = "-" - sram_size = "-" - - # Check if board is skipped - if build_utils.skip_example(example, board): - success = SKIPPED - skip_count += 1 - print(build_format.format(example, board, success, '-', flash_size, sram_size)) - else: - subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - build_result = subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - if build_result.returncode == 0: - success = SUCCEEDED - success_count += 1 - (flash_size, sram_size) = build_size(example, board) - else: - exit_status = build_result.returncode - success = FAILED - fail_count += 1 - - build_duration = time.monotonic() - start_time - print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) - - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) - -def build_size(example, board): - #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) - elf_file = 'examples/device/{}/_build/{}/*.elf'.format(example, board) - size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") - size_list = size_output.split('\n')[1].split('\t') - flash_size = int(size_list[0]) - sram_size = int(size_list[1]) + int(size_list[2]) - return (flash_size, sram_size) - -print(build_separator) -print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) -print(build_separator) - -for example in all_examples: - for board in all_boards: - build_board(example, board) - -total_time = time.monotonic() - total_time -print(build_separator) -print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) -print(build_separator) - -sys.exit(exit_status) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py deleted file mode 100644 index 4094d07db..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py +++ /dev/null @@ -1,113 +0,0 @@ -import os -import glob -import sys -import subprocess -import time - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -success_count = 0 -fail_count = 0 -skip_count = 0 -exit_status = 0 - -total_time = time.monotonic() - -build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |' -build_separator = '-' * 106 - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - -# If examples are not specified in arguments, build all -all_examples = [] -for entry in os.scandir("examples/device"): - if entry.is_dir(): - all_examples.append("device/" + entry.name) -for entry in os.scandir("examples/host"): - if entry.is_dir(): - all_examples.append("host/" + entry.name) -filter_with_input(all_examples) -all_examples.sort() - -# If family are not specified in arguments, build all -all_families = [] -for entry in os.scandir("hw/bsp"): - if entry.is_dir() and os.path.isdir(entry.path + "/boards") and entry.name not in ("esp32s2", "esp32s3"): - all_families.append(entry.name) - -filter_with_input(all_families) -all_families.sort() - -def build_family(example, family): - all_boards = [] - for entry in os.scandir("hw/bsp/{}/boards".format(family)): - if entry.is_dir(): - all_boards.append(entry.name) - filter_with_input(all_boards) - all_boards.sort() - - for board in all_boards: - build_board(example, board) - -def build_board(example, board): - global success_count, fail_count, skip_count, exit_status - start_time = time.monotonic() - flash_size = "-" - sram_size = "-" - - # Check if board is skipped - if build_utils.skip_example(example, board): - success = SKIPPED - skip_count += 1 - print(build_format.format(example, board, success, '-', flash_size, sram_size)) - else: - #subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - if build_result.returncode == 0: - success = SUCCEEDED - success_count += 1 - (flash_size, sram_size) = build_size(example, board) - subprocess.run("make -j -C examples/{} BOARD={} copy-artifact".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - else: - exit_status = build_result.returncode - success = FAILED - fail_count += 1 - - build_duration = time.monotonic() - start_time - print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) - - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) - -def build_size(example, board): - #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) - elf_file = 'examples/{}/_build/{}/*.elf'.format(example, board) - size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") - size_list = size_output.split('\n')[1].split('\t') - flash_size = int(size_list[0]) - sram_size = int(size_list[1]) + int(size_list[2]) - return (flash_size, sram_size) - -print(build_separator) -print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) - -for example in all_examples: - print(build_separator) - for family in all_families: - build_family(example, family) - -total_time = time.monotonic() - total_time -print(build_separator) -print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) -print(build_separator) - -sys.exit(exit_status) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py deleted file mode 100644 index 299fffa4d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py +++ /dev/null @@ -1,61 +0,0 @@ -import pathlib - -def skip_example(example, board): - ex_dir = pathlib.Path('examples/') / example - bsp = pathlib.Path("hw/bsp") - - board_dir = list(bsp.glob("*/boards/" + board)) - if not board_dir: - # Skip unknown boards - return True - - board_dir = list(board_dir)[0] - - family_dir = board_dir.parent.parent - family = family_dir.name - - # family CMake - family_mk = family_dir / "family.cmake" - - # family.mk - if not family_mk.exists(): - family_mk = family_dir / "family.mk" - - mk_contents = family_mk.read_text() - - # Find the mcu - if "CFG_TUSB_MCU=OPT_MCU_" not in mk_contents: - board_mk = board_dir / "board.cmake" - if not board_mk.exists(): - board_mk = board_dir / "board.mk" - - mk_contents = board_mk.read_text() - - for token in mk_contents.split(): - if "CFG_TUSB_MCU=OPT_MCU_" in token: - # Strip " because cmake files has them. - token = token.strip("\"") - _, opt_mcu = token.split("=") - mcu = opt_mcu[len("OPT_MCU_"):] - - # Skip all OPT_MCU_NONE these are WIP port - if mcu == "NONE": - return True - - skip_file = ex_dir / "skip.txt" - only_file = ex_dir / "only.txt" - - if skip_file.exists() and only_file.exists(): - raise RuntimeError("Only have a skip or only file. Not both.") - elif skip_file.exists(): - skips = skip_file.read_text().split() - return ("mcu:" + mcu in skips or - "board:" + board in skips or - "family:" + family in skips) - elif only_file.exists(): - onlys = only_file.read_text().split() - return not ("mcu:" + mcu in onlys or - "board:" + board in onlys or - "family:" + family in onlys) - - return False diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py deleted file mode 100644 index 73c8b29fc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python3 - -import os -import xml.dom.minidom as XML - -# Read base configuration -base = "" -with open("iar_template.ipcf") as f: - base = f.read() - -# Enumerate all device/host examples -dir_1 = os.listdir("../examples") -for dir_2 in dir_1: - if os.path.isdir("../examples/{}".format(dir_2)): - print(dir_2) - examples = os.listdir("../examples/{}".format(dir_2)) - for example in examples: - if os.path.isdir("../examples/{}/{}".format(dir_2, example)): - print("../examples/{}/{}".format(dir_2, example)) - conf = XML.parseString(base) - files = conf.getElementsByTagName("files")[0] - inc = conf.getElementsByTagName("includePath")[0] - # Add bsp inc - path = conf.createElement('path') - path_txt = conf.createTextNode("$TUSB_DIR$/hw") - path.appendChild(path_txt) - inc.appendChild(path) - # Add board.c/.h - grp = conf.createElement('group') - grp.setAttribute("name", "bsp") - path = conf.createElement('path') - path_txt = conf.createTextNode("$TUSB_DIR$/hw/bsp/board.c") - path.appendChild(path_txt) - grp.appendChild(path) - files.appendChild(grp) - # Add example's .c/.h - grp = conf.createElement('group') - grp.setAttribute("name", "example") - for file in os.listdir("../examples/{}/{}/src".format(dir_2, example)): - if file.endswith(".c") or file.endswith(".h"): - path = conf.createElement('path') - path.setAttribute("copyTo", "$PROJ_DIR$/{}".format(file)) - path_txt = conf.createTextNode("$TUSB_DIR$/examples/{0}/{1}/src/{2}".format(dir_2, example, file)) - path.appendChild(path_txt) - grp.appendChild(path) - files.appendChild(grp) - cfg_str = conf.toprettyxml() - cfg_str = '\n'.join([s for s in cfg_str.splitlines() if s.strip()]) - #print(cfg_str) - with open("../examples/{0}/{1}/iar_{1}.ipcf".format(dir_2, example), 'w') as f: - f.write(cfg_str) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf deleted file mode 100644 index ba54fe057..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf +++ /dev/null @@ -1,145 +0,0 @@ - - - - - $TUSB_DIR$/src - $TUSB_DIR$/lib/SEGGER_RTT/RTT - $PROJ_DIR$ - - - - $TUSB_DIR$/src/device/usbd.c - $TUSB_DIR$/src/device/usbd_control.c - - - $TUSB_DIR$/src/common/tusb_fifo.c - - - $TUSB_DIR$/src/class/audio/audio_device.c - - - $TUSB_DIR$/src/class/bth/bth_device.c - - - $TUSB_DIR$/src/class/cdc/cdc_device.c - $TUSB_DIR$/src/class/cdc/cdc_host.c - $TUSB_DIR$/src/class/cdc/cdc_rndis_host.c - - - $TUSB_DIR$/src/class/dfu/dfu_device.c - $TUSB_DIR$/src/class/dfu/dfu_rt_device.c - - - $TUSB_DIR$/src/class/hid/hid_device.c - $TUSB_DIR$/src/class/hid/hid_host.c - - - $TUSB_DIR$/src/class/midi/midi_device.c - - - $TUSB_DIR$/src/class/msc/msc_device.c - $TUSB_DIR$/src/class/msc/msc_host.c - - - $TUSB_DIR$/src/class/net/ecm_rndis_device.c - $TUSB_DIR$/src/class/net/ncm_device.c - - - $TUSB_DIR$/src/class/usbtmc/usbtmc_device.c - - - $TUSB_DIR$/src/class/vendor/vendor_device.c - $TUSB_DIR$/src/class/vendor/vendor_host.c - - - $TUSB_DIR$/src/tusb.c - - - $TUSB_DIR$/src/host/hub.c - $TUSB_DIR$/src/host/usbh.c - $TUSB_DIR$/src/host/usbh_control.c - - - $TUSB_DIR$/src/portable/synopsys/dwc2/dcd_dwc2.c - - - $TUSB_DIR$/src/portable/dialog/da146xx/dcd_da146xx.c - - - $TUSB_DIR$/src/portable/ehci/ehci.c - - - $TUSB_DIR$/src/portable/espressif/esp32sx/dcd_esp32sx.c - - - $TUSB_DIR$/src/portable/mentor/musb/dcd_musb.c - - - $TUSB_DIR$/src/portable/microchip/samd/dcd_samd.c - - - $TUSB_DIR$/src/portable/microchip/samg/dcd_samg.c - - - $TUSB_DIR$/src/portable/microchip/samx7x/dcd_samx7x.c - - - $TUSB_DIR$/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c - - - $TUSB_DIR$/src/portable/nordic/nrf5x/dcd_nrf5x.c - - - $TUSB_DIR$/src/portable/nuvoton/nuc120/dcd_nuc120.c - - - $TUSB_DIR$/src/portable/nuvoton/nuc121/dcd_nuc121.c - - - $TUSB_DIR$/src/portable/nuvoton/nuc505/dcd_nuc505.c - - - $TUSB_DIR$/src/portable/nxp/khci/dcd_khci.c - - - $TUSB_DIR$/src/portable/nxp/lpc17_40/dcd_lpc17_40.c - $TUSB_DIR$/src/portable/nxp/lpc17_40/hcd_lpc17_40.c - - - $TUSB_DIR$/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c - - - $TUSB_DIR$/src/portable/nxp/transdimension/dcd_transdimension.c - $TUSB_DIR$/src/portable/nxp/transdimension/hcd_transdimension.c - - - $TUSB_DIR$/src/portable/ohci/ohci.c - - - $TUSB_DIR$/src/portable/raspberrypi/rp2040/dcd_rp2040.c - $TUSB_DIR$/src/portable/raspberrypi/rp2040/hcd_rp2040.c - $TUSB_DIR$/src/portable/raspberrypi/rp2040/rp2040_usb.c - - - $TUSB_DIR$/src/portable/renesas/usba/dcd_usba.c - - - $TUSB_DIR$/src/portable/sony/cxd56/dcd_cxd56.c - - - $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - - - $TUSB_DIR$/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c - - - $TUSB_DIR$/src/portable/valentyusb/eptri/dcd_eptri.c - - - $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT.c - $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c - $TUSB_DIR$/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c - - - - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk deleted file mode 100644 index 84523a557..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk +++ /dev/null @@ -1,30 +0,0 @@ -ifneq ($(lastword a b),b) -$(error This Makefile require make 3.81 or newer) -endif - -# Detect whether shell style is windows or not -# https://stackoverflow.com/questions/714100/os-detecting-makefile/52062069#52062069 -ifeq '$(findstring ;,$(PATH))' ';' -CMDEXE := 1 -endif - -# Set TOP to be the path to get from the current directory (where make was -# invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns -# the name of this makefile relative to where make was invoked. - -THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -TOP := $(patsubst %/tools/top.mk,%,$(THIS_MAKEFILE)) - -ifeq ($(CMDEXE),1) -TOP := $(subst \,/,$(shell for %%i in ( $(TOP) ) do echo %%~fi)) -else -TOP := $(shell realpath $(TOP)) -endif -#$(info Top directory is $(TOP)) - -ifeq ($(CMDEXE),1) -CURRENT_PATH := $(subst $(TOP)/,,$(subst \,/,$(shell echo %CD%))) -else -CURRENT_PATH := $(shell realpath --relative-to=$(TOP) `pwd`) -endif -#$(info Path from top is $(CURRENT_PATH)) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf deleted file mode 100644 index e7f7a9b22..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf +++ /dev/null @@ -1,108 +0,0 @@ -;************************************************************ -; Windows USB CDC ACM Setup File -; Copyright (c) 2000 Microsoft Corporation - - -[Version] -Signature="$Windows NT$" -Class=Ports -ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} -Provider=%MFGNAME% -LayoutFile=layout.inf -CatalogFile=%MFGFILENAME%.cat -DriverVer=11/15/2007,5.1.2600.0 -DriverPackageDisplayName=%DESCRIPTION% - -[Manufacturer] -%MFGNAME%=DeviceList, NTamd64 - -[DestinationDirs] -DefaultDestDir=12 - - -;------------------------------------------------------------------------------ -; Windows 2000/XP/Vista-32bit Sections -;------------------------------------------------------------------------------ - -[DriverInstall.nt] -include=mdmcpq.inf -CopyFiles=DriverCopyFiles.nt -AddReg=DriverInstall.nt.AddReg - -[DriverCopyFiles.nt] -usbser.sys,,,0x20 - -[DriverInstall.nt.AddReg] -HKR,,DevLoader,,*ntkern -HKR,,NTMPDriver,,%DRIVERFILENAME%.sys -HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" - -[DriverInstall.nt.Services] -AddService=usbser, 0x00000002, DriverService.nt - -[DriverService.nt] -DisplayName=%SERVICE% -ServiceType=1 -StartType=3 -ErrorControl=1 -ServiceBinary=%12%\%DRIVERFILENAME%.sys - -;------------------------------------------------------------------------------ -; Vista-64bit Sections -;------------------------------------------------------------------------------ - -[DriverInstall.NTamd64] -include=mdmcpq.inf -CopyFiles=DriverCopyFiles.NTamd64 -AddReg=DriverInstall.NTamd64.AddReg - -[DriverCopyFiles.NTamd64] -%DRIVERFILENAME%.sys,,,0x20 - -[DriverInstall.NTamd64.AddReg] -HKR,,DevLoader,,*ntkern -HKR,,NTMPDriver,,%DRIVERFILENAME%.sys -HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" - -[DriverInstall.NTamd64.Services] -AddService=usbser, 0x00000002, DriverService.NTamd64 - -[DriverService.NTamd64] -DisplayName=%SERVICE% -ServiceType=1 -StartType=3 -ErrorControl=1 -ServiceBinary=%12%\%DRIVERFILENAME%.sys - - -;------------------------------------------------------------------------------ -; Vendor and Product ID Definitions -;------------------------------------------------------------------------------ -; When developing your USB device, the VID and PID used in the PC side -; application program and the firmware on the microcontroller must match. -; Modify the below line to use your VID and PID. Use the format as shown below. -; Note: One INF file can be used for multiple devices with different VID and PIDs. -; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line. -;------------------------------------------------------------------------------ -[SourceDisksFiles] -[SourceDisksNames] -[DeviceList] - -%DESCRIPTION%=DriverInstall, USB\VID_CAFE&PID_4001&MI_00, USB\VID_CAFE&PID_4003&MI_00, USB\VID_CAFE&PID_4005&MI_00, USB\VID_CAFE&PID_4007&MI_00, USB\VID_CAFE&PID_4009&MI_00, USB\VID_CAFE&PID_400b&MI_00, USB\VID_CAFE&PID_400d&MI_00, USB\VID_CAFE&PID_400f&MI_00, USB\VID_CAFE&PID_4011&MI_00, USB\VID_CAFE&PID_4013&MI_00, USB\VID_CAFE&PID_4015&MI_00, USB\VID_CAFE&PID_4017&MI_00, USB\VID_CAFE&PID_4019&MI_00, USB\VID_CAFE&PID_401b&MI_00, USB\VID_CAFE&PID_401d&MI_00, USB\VID_CAFE&PID_401f&MI_00, USB\VID_CAFE&PID_4021&MI_00, USB\VID_CAFE&PID_4023&MI_00, USB\VID_CAFE&PID_4025&MI_00, USB\VID_CAFE&PID_4027&MI_00, USB\VID_CAFE&PID_4029&MI_00, USB\VID_CAFE&PID_402b&MI_00, USB\VID_CAFE&PID_402d&MI_00, USB\VID_CAFE&PID_402f&MI_00, USB\VID_CAFE&PID_4031&MI_00, USB\VID_CAFE&PID_4033&MI_00, USB\VID_CAFE&PID_4035&MI_00, USB\VID_CAFE&PID_4037&MI_00, USB\VID_CAFE&PID_4039&MI_00, USB\VID_CAFE&PID_403b&MI_00, USB\VID_CAFE&PID_403d&MI_00, USB\VID_CAFE&PID_403f&MI_00 - - -[DeviceList.NTamd64] -%DESCRIPTION%=DriverInstall, USB\VID_CAFE&PID_4001&MI_00, USB\VID_CAFE&PID_4003&MI_00, USB\VID_CAFE&PID_4005&MI_00, USB\VID_CAFE&PID_4007&MI_00, USB\VID_CAFE&PID_4009&MI_00, USB\VID_CAFE&PID_400b&MI_00, USB\VID_CAFE&PID_400d&MI_00, USB\VID_CAFE&PID_400f&MI_00, USB\VID_CAFE&PID_4011&MI_00, USB\VID_CAFE&PID_4013&MI_00, USB\VID_CAFE&PID_4015&MI_00, USB\VID_CAFE&PID_4017&MI_00, USB\VID_CAFE&PID_4019&MI_00, USB\VID_CAFE&PID_401b&MI_00, USB\VID_CAFE&PID_401d&MI_00, USB\VID_CAFE&PID_401f&MI_00, USB\VID_CAFE&PID_4021&MI_00, USB\VID_CAFE&PID_4023&MI_00, USB\VID_CAFE&PID_4025&MI_00, USB\VID_CAFE&PID_4027&MI_00, USB\VID_CAFE&PID_4029&MI_00, USB\VID_CAFE&PID_402b&MI_00, USB\VID_CAFE&PID_402d&MI_00, USB\VID_CAFE&PID_402f&MI_00, USB\VID_CAFE&PID_4031&MI_00, USB\VID_CAFE&PID_4033&MI_00, USB\VID_CAFE&PID_4035&MI_00, USB\VID_CAFE&PID_4037&MI_00, USB\VID_CAFE&PID_4039&MI_00, USB\VID_CAFE&PID_403b&MI_00, USB\VID_CAFE&PID_403d&MI_00, USB\VID_CAFE&PID_403f&MI_00 - -;------------------------------------------------------------------------------ -; String Definitions -;------------------------------------------------------------------------------ -;Modify these strings to customize your device -;------------------------------------------------------------------------------ -[Strings] -MFGFILENAME="tinyusb_usbser" -DRIVERFILENAME ="usbser" -MFGNAME="tinyusb.org" -INSTDISK="tinyusb CDC Driver" -DESCRIPTION="tinyusb Serial" -SERVICE="USB RS-232 Emulation Driver" \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_cdc_acm.c similarity index 65% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_cdc_acm.c index 725426ead..a69ba6e2a 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_cdc_acm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,22 +10,21 @@ #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/ringbuf.h" #include "tusb.h" #include "tusb_cdc_acm.h" #include "cdc.h" #include "sdkconfig.h" -#define RX_UNREADBUF_SZ_DEFAULT 64 // buffer storing all unread RX data +#ifndef MIN #define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif +// CDC-ACM spinlock +static portMUX_TYPE cdc_acm_lock = portMUX_INITIALIZER_UNLOCKED; +#define CDC_ACM_ENTER_CRITICAL() portENTER_CRITICAL(&cdc_acm_lock) +#define CDC_ACM_EXIT_CRITICAL() portEXIT_CRITICAL(&cdc_acm_lock) typedef struct { - bool initialized; - size_t rx_unread_buf_sz; - RingbufHandle_t rx_unread_buf; - SemaphoreHandle_t ringbuf_read_mux; - uint8_t *rx_tfbuf; tusb_cdcacm_callback_t callback_rx; tusb_cdcacm_callback_t callback_rx_wanted_char; tusb_cdcacm_callback_t callback_line_state_changed; @@ -66,7 +65,9 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) } } if (acm) { + CDC_ACM_ENTER_CRITICAL(); tusb_cdcacm_callback_t cb = acm->callback_line_state_changed; + CDC_ACM_EXIT_CRITICAL(); if (cb) { cdcacm_event_t event = { .type = CDC_EVENT_LINE_STATE_CHANGED, @@ -85,29 +86,9 @@ void tud_cdc_rx_cb(uint8_t itf) { esp_tusb_cdcacm_t *acm = get_acm(itf); if (acm) { - if (!acm->rx_unread_buf) { - ESP_LOGE(TAG, "There is no RX buffer created"); - abort(); - } - } else { - tud_cdc_n_read_flush(itf); // we have no place to store data, so just drop it - return; - } - while (tud_cdc_n_available(itf)) { - int read_res = tud_cdc_n_read( itf, - acm->rx_tfbuf, - CONFIG_TINYUSB_CDC_RX_BUFSIZE ); - int res = xRingbufferSend(acm->rx_unread_buf, - acm->rx_tfbuf, - read_res, 0); - if (res != pdTRUE) { - ESP_LOGW(TAG, "The unread buffer is too small, the data has been lost"); - } else { - ESP_LOGV(TAG, "Sent %d bytes to the buffer", read_res); - } - } - if (acm) { + CDC_ACM_ENTER_CRITICAL(); tusb_cdcacm_callback_t cb = acm->callback_rx; + CDC_ACM_EXIT_CRITICAL(); if (cb) { cdcacm_event_t event = { .type = CDC_EVENT_RX @@ -122,7 +103,9 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) { esp_tusb_cdcacm_t *acm = get_acm(itf); if (acm) { + CDC_ACM_ENTER_CRITICAL(); tusb_cdcacm_callback_t cb = acm->callback_line_coding_changed; + CDC_ACM_EXIT_CRITICAL(); if (cb) { cdcacm_event_t event = { .type = CDC_EVENT_LINE_CODING_CHANGED, @@ -132,8 +115,6 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) }; cb(itf, &event); } - } else { - return; } } @@ -142,7 +123,9 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { esp_tusb_cdcacm_t *acm = get_acm(itf); if (acm) { + CDC_ACM_ENTER_CRITICAL(); tusb_cdcacm_callback_t cb = acm->callback_rx_wanted_char; + CDC_ACM_EXIT_CRITICAL(); if (cb) { cdcacm_event_t event = { .type = CDC_EVENT_RX_WANTED_CHAR, @@ -152,8 +135,6 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) }; cb(itf, &event); } - } else { - return; } } @@ -165,16 +146,24 @@ esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, if (acm) { switch (event_type) { case CDC_EVENT_RX: + CDC_ACM_ENTER_CRITICAL(); acm->callback_rx = callback; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_RX_WANTED_CHAR: + CDC_ACM_ENTER_CRITICAL(); acm->callback_rx_wanted_char = callback; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_LINE_STATE_CHANGED: + CDC_ACM_ENTER_CRITICAL(); acm->callback_line_state_changed = callback; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_LINE_CODING_CHANGED: + CDC_ACM_ENTER_CRITICAL(); acm->callback_line_coding_changed = callback; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; default: ESP_LOGE(TAG, "Wrong event type"); @@ -196,16 +185,24 @@ esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, } switch (event_type) { case CDC_EVENT_RX: + CDC_ACM_ENTER_CRITICAL(); acm->callback_rx = NULL; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_RX_WANTED_CHAR: + CDC_ACM_ENTER_CRITICAL(); acm->callback_rx_wanted_char = NULL; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_LINE_STATE_CHANGED: + CDC_ACM_ENTER_CRITICAL(); acm->callback_line_state_changed = NULL; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_LINE_CODING_CHANGED: + CDC_ACM_ENTER_CRITICAL(); acm->callback_line_coding_changed = NULL; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; default: ESP_LOGE(TAG, "Wrong event type"); @@ -217,56 +214,16 @@ esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, /* CDC-ACM ********************************************************************* */ -static esp_err_t read_from_rx_unread_to_buffer(esp_tusb_cdcacm_t *acm, uint8_t *out_buf, size_t req_bytes, size_t *read_bytes) -{ - uint8_t *buf = xRingbufferReceiveUpTo(acm->rx_unread_buf, read_bytes, 0, req_bytes); - if (buf) { - memcpy(out_buf, buf, *read_bytes); - vRingbufferReturnItem(acm->rx_unread_buf, (void *)(buf)); - return ESP_OK; - } else { - return ESP_ERR_NO_MEM; - } -} - -static esp_err_t ringbuf_mux_take(esp_tusb_cdcacm_t *acm) -{ - if (xSemaphoreTake(acm->ringbuf_read_mux, 0) != pdTRUE) { - ESP_LOGW(TAG, "Read error: ACM is busy"); - return ESP_ERR_INVALID_STATE; - } - return ESP_OK; -} - -static esp_err_t ringbuf_mux_give(esp_tusb_cdcacm_t *acm) -{ - BaseType_t ret = xSemaphoreGive(acm->ringbuf_read_mux); - assert(ret == pdTRUE); - return ESP_OK; -} - esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size) { esp_tusb_cdcacm_t *acm = get_acm(itf); ESP_RETURN_ON_FALSE(acm, ESP_ERR_INVALID_STATE, TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization"); - size_t read_sz; - - /* Take a mutex to proceed two uninterrupted read operations */ - ESP_RETURN_ON_ERROR(ringbuf_mux_take(acm), TAG, "ringbuf_mux_take failed"); - - esp_err_t res = read_from_rx_unread_to_buffer(acm, out_buf, out_buf_sz, &read_sz); - if (res != ESP_OK) { - ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed"); - return res; - } - *rx_data_size = read_sz; - /* Buffer's data can be wrapped, at that situations we should make another retrievement */ - if (read_from_rx_unread_to_buffer(acm, out_buf + read_sz, out_buf_sz - read_sz, &read_sz) == ESP_OK) { - *rx_data_size += read_sz; + if (tud_cdc_n_available(itf) == 0) { + *rx_data_size = 0; + } else { + *rx_data_size = tud_cdc_n_read(itf, out_buf, out_buf_sz); } - - ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed"); return ESP_OK; } @@ -299,27 +256,21 @@ esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ } if (!timeout_ticks) { // if no timeout - nonblocking mode - int res = tud_cdc_n_write_flush(itf); - if (!res) { - ESP_LOGW(TAG, "flush failed (res: %d)", res); - return ESP_FAIL; - } else { - if (tud_cdc_n_write_occupied(itf)) { - ESP_LOGW(TAG, "remained data to flush!"); - return ESP_FAIL; - } + // It might take some time until TinyUSB flushes the endpoint + // Since this call is non-blocking, we don't wait for flush finished, + // We only inform the user by returning ESP_ERR_NOT_FINISHED + tud_cdc_n_write_flush(itf); + if (tud_cdc_n_write_occupied(itf)) { + return ESP_ERR_NOT_FINISHED; } - return ESP_ERR_TIMEOUT; } else { // trying during the timeout uint32_t ticks_start = xTaskGetTickCount(); uint32_t ticks_now = ticks_start; while (1) { // loop until success or until the time runs out ticks_now = xTaskGetTickCount(); - if (!tud_cdc_n_write_occupied(itf)) { // if nothing to write - nothing to flush - break; - } - if (tud_cdc_n_write_flush(itf)) { // Success - break; + tud_cdc_n_write_flush(itf); + if (tud_cdc_n_write_occupied(itf) == 0) { + break; // All data flushed } if ( (ticks_now - ticks_start) > timeout_ticks ) { // Time is up ESP_LOGW(TAG, "Flush failed"); @@ -327,30 +278,26 @@ esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ } vTaskDelay(1); } - return ESP_OK; } + return ESP_OK; } static esp_err_t alloc_obj(tinyusb_cdcacm_itf_t itf) { esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf); + if (cdc_inst == NULL) { + return ESP_FAIL; + } cdc_inst->subclass_obj = calloc(1, sizeof(esp_tusb_cdcacm_t)); - if (!cdc_inst->subclass_obj) { + if (cdc_inst->subclass_obj == NULL) { return ESP_FAIL; - } else { - return ESP_OK; } -} - -static void free_obj(tinyusb_cdcacm_itf_t itf) -{ - esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf); - free(cdc_inst->subclass_obj); - cdc_inst->subclass_obj = NULL; + return ESP_OK; } esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg) { + esp_err_t ret = ESP_OK; int itf = (int)cfg->cdc_port; /* Creating a CDC object */ const tinyusb_config_cdc_t cdc_cfg = { @@ -358,10 +305,10 @@ esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg) .cdc_class = TUSB_CLASS_CDC, .cdc_subclass.comm_subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL }; + ESP_RETURN_ON_ERROR(tinyusb_cdc_init(itf, &cdc_cfg), TAG, "tinyusb_cdc_init failed"); - ESP_RETURN_ON_ERROR(alloc_obj(itf), TAG, "alloc_obj failed"); + ESP_GOTO_ON_ERROR(alloc_obj(itf), fail, TAG, "alloc_obj failed"); - esp_tusb_cdcacm_t *acm = get_acm(itf); /* Callbacks setting up*/ if (cfg->callback_rx) { tinyusb_cdcacm_register_callback(itf, CDC_EVENT_RX, cfg->callback_rx); @@ -376,31 +323,15 @@ esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg) tinyusb_cdcacm_register_callback( itf, CDC_EVENT_LINE_CODING_CHANGED, cfg->callback_line_coding_changed); } - /* Buffers */ - - acm->ringbuf_read_mux = xSemaphoreCreateMutex(); - if (acm->ringbuf_read_mux == NULL) { - ESP_LOGE(TAG, "Creation of a ringbuf mutex failed"); - free_obj(itf); - return ESP_ERR_NO_MEM; - } + return ESP_OK; +fail: + tinyusb_cdc_deinit(itf); + return ret; +} - acm->rx_tfbuf = malloc(CONFIG_TINYUSB_CDC_RX_BUFSIZE); - if (!acm->rx_tfbuf) { - ESP_LOGE(TAG, "Creation buffer error"); - free_obj(itf); - return ESP_ERR_NO_MEM; - } - acm->rx_unread_buf_sz = cfg->rx_unread_buf_sz == 0 ? RX_UNREADBUF_SZ_DEFAULT : cfg->rx_unread_buf_sz; - acm->rx_unread_buf = xRingbufferCreate(acm->rx_unread_buf_sz, RINGBUF_TYPE_BYTEBUF); - if (acm->rx_unread_buf == NULL) { - ESP_LOGE(TAG, "Creation buffer error"); - free_obj(itf); - return ESP_ERR_NO_MEM; - } else { - ESP_LOGD(TAG, "Comm Initialized buff:%d bytes", cfg->rx_unread_buf_sz); - return ESP_OK; - } +esp_err_t tusb_cdc_acm_deinit(int itf) +{ + return tinyusb_cdc_deinit(itf); } bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_console.c similarity index 97% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_console.c index 97c3e256d..692f64f7b 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_console.c @@ -103,7 +103,7 @@ esp_err_t esp_tusb_init_console(int cdc_intf) { /* Registering TUSB at VFS */ ESP_RETURN_ON_ERROR(esp_vfs_tusb_cdc_register(cdc_intf, NULL), TAG, ""); - ESP_RETURN_ON_ERROR(redirect_std_streams_to(&con.in, &con.out, &con.err, "/dev/tusb_cdc"), TAG, "Failed to redirect STD streams"); + ESP_RETURN_ON_ERROR(redirect_std_streams_to(&con.in, &con.out, &con.err, VFS_TUSB_PATH_DEFAULT), TAG, "Failed to redirect STD streams"); return ESP_OK; } diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_msc_storage.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_msc_storage.c new file mode 100644 index 000000000..356ad2c28 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_msc_storage.c @@ -0,0 +1,640 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_log.h" +#include "esp_err.h" +#include "esp_check.h" +#include "esp_vfs_fat.h" +#include "diskio_impl.h" +#include "diskio_wl.h" +#include "wear_levelling.h" +#include "esp_partition.h" +#include "vfs_fat_internal.h" +#include "tinyusb.h" +#include "class/msc/msc_device.h" +#include "tusb_msc_storage.h" +#include "esp_vfs_fat.h" +#if SOC_SDMMC_HOST_SUPPORTED +#include "diskio_sdmmc.h" +#endif + +static const char *TAG = "tinyusb_msc_storage"; + +typedef struct { + bool is_fat_mounted; + const char *base_path; + union { + wl_handle_t wl_handle; +#if SOC_SDMMC_HOST_SUPPORTED + sdmmc_card_t *card; +#endif + }; + esp_err_t (*mount)(BYTE pdrv); + esp_err_t (*unmount)(void); + uint32_t (*sector_count)(void); + uint32_t (*sector_size)(void); + esp_err_t (*read)(size_t sector_size, uint32_t lba, uint32_t offset, size_t size, void *dest); + esp_err_t (*write)(size_t sector_size, size_t addr, uint32_t lba, uint32_t offset, size_t size, const void *src); + tusb_msc_callback_t callback_mount_changed; + tusb_msc_callback_t callback_premount_changed; + int max_files; +} tinyusb_msc_storage_handle_s; /*!< MSC object */ + +/* handle of tinyusb driver connected to application */ +static tinyusb_msc_storage_handle_s *s_storage_handle; + +static esp_err_t _mount_spiflash(BYTE pdrv) +{ + return ff_diskio_register_wl_partition(pdrv, s_storage_handle->wl_handle); +} + +static esp_err_t _unmount_spiflash(void) +{ + BYTE pdrv; + pdrv = ff_diskio_get_pdrv_wl(s_storage_handle->wl_handle); + if (pdrv == 0xff) { + ESP_LOGE(TAG, "Invalid state"); + return ESP_ERR_INVALID_STATE; + } + ff_diskio_clear_pdrv_wl(s_storage_handle->wl_handle); + + char drv[3] = {(char)('0' + pdrv), ':', 0}; + f_mount(0, drv, 0); + ff_diskio_unregister(pdrv); + + return ESP_OK; +} + +static uint32_t _get_sector_count_spiflash(void) +{ + uint32_t result = 0; + assert(s_storage_handle->wl_handle != WL_INVALID_HANDLE); + size_t size = wl_sector_size(s_storage_handle->wl_handle); + if (size == 0) { + ESP_LOGW(TAG, "WL Sector size is zero !!!"); + result = 0; + } else { + result = (uint32_t)(wl_size(s_storage_handle->wl_handle) / size); + } + return result; +} + +static uint32_t _get_sector_size_spiflash(void) +{ + assert(s_storage_handle->wl_handle != WL_INVALID_HANDLE); + return (uint32_t)wl_sector_size(s_storage_handle->wl_handle); +} + +static esp_err_t _read_sector_spiflash(size_t sector_size, + uint32_t lba, + uint32_t offset, + size_t size, + void *dest) +{ + size_t temp = 0; + size_t addr = 0; // Address of the data to be read, relative to the beginning of the partition. + ESP_RETURN_ON_FALSE(!__builtin_umul_overflow(lba, sector_size, &temp), ESP_ERR_INVALID_SIZE, TAG, "overflow lba %lu sector_size %u", lba, sector_size); + ESP_RETURN_ON_FALSE(!__builtin_uadd_overflow(temp, offset, &addr), ESP_ERR_INVALID_SIZE, TAG, "overflow addr %u offset %lu", temp, offset); + return wl_read(s_storage_handle->wl_handle, addr, dest, size); +} + +static esp_err_t _write_sector_spiflash(size_t sector_size, + size_t addr, + uint32_t lba, + uint32_t offset, + size_t size, + const void *src) +{ + ESP_RETURN_ON_ERROR(wl_erase_range(s_storage_handle->wl_handle, addr, size), + TAG, "Failed to erase"); + return wl_write(s_storage_handle->wl_handle, addr, src, size); +} + +#if SOC_SDMMC_HOST_SUPPORTED +static esp_err_t _mount_sdmmc(BYTE pdrv) +{ + ff_diskio_register_sdmmc(pdrv, s_storage_handle->card); + ff_sdmmc_set_disk_status_check(pdrv, false); + return ESP_OK; +} + +static esp_err_t _unmount_sdmmc(void) +{ + BYTE pdrv; + pdrv = ff_diskio_get_pdrv_card(s_storage_handle->card); + if (pdrv == 0xff) { + ESP_LOGE(TAG, "Invalid state"); + return ESP_ERR_INVALID_STATE; + } + + char drv[3] = {(char)('0' + pdrv), ':', 0}; + f_mount(0, drv, 0); + ff_diskio_unregister(pdrv); + + return ESP_OK; +} + +static uint32_t _get_sector_count_sdmmc(void) +{ + assert(s_storage_handle->card); + return (uint32_t)s_storage_handle->card->csd.capacity; +} + +static uint32_t _get_sector_size_sdmmc(void) +{ + assert(s_storage_handle->card); + return (uint32_t)s_storage_handle->card->csd.sector_size; +} + +static esp_err_t _read_sector_sdmmc(size_t sector_size, + uint32_t lba, + uint32_t offset, + size_t size, + void *dest) +{ + return sdmmc_read_sectors(s_storage_handle->card, dest, lba, size / sector_size); +} + +static esp_err_t _write_sector_sdmmc(size_t sector_size, + size_t addr, + uint32_t lba, + uint32_t offset, + size_t size, + const void *src) +{ + return sdmmc_write_sectors(s_storage_handle->card, src, lba, size / sector_size); +} +#endif + +static esp_err_t msc_storage_read_sector(uint32_t lba, + uint32_t offset, + size_t size, + void *dest) +{ + assert(s_storage_handle); + size_t sector_size = tinyusb_msc_storage_get_sector_size(); + return (s_storage_handle->read)(sector_size, lba, offset, size, dest); +} + +static esp_err_t msc_storage_write_sector(uint32_t lba, + uint32_t offset, + size_t size, + const void *src) +{ + assert(s_storage_handle); + if (s_storage_handle->is_fat_mounted) { + ESP_LOGE(TAG, "can't write, FAT mounted"); + return ESP_ERR_INVALID_STATE; + } + size_t sector_size = tinyusb_msc_storage_get_sector_size(); + size_t temp = 0; + size_t addr = 0; // Address of the data to be read, relative to the beginning of the partition. + ESP_RETURN_ON_FALSE(!__builtin_umul_overflow(lba, sector_size, &temp), ESP_ERR_INVALID_SIZE, TAG, "overflow lba %lu sector_size %u", lba, sector_size); + ESP_RETURN_ON_FALSE(!__builtin_uadd_overflow(temp, offset, &addr), ESP_ERR_INVALID_SIZE, TAG, "overflow addr %u offset %lu", temp, offset); + + if (addr % sector_size != 0 || size % sector_size != 0) { + ESP_LOGE(TAG, "Invalid Argument lba(%lu) offset(%lu) size(%u) sector_size(%u)", lba, offset, size, sector_size); + return ESP_ERR_INVALID_ARG; + } + return (s_storage_handle->write)(sector_size, addr, lba, offset, size, src); +} + +static esp_err_t _mount(char *drv, FATFS *fs) +{ + void *workbuf = NULL; + const size_t workbuf_size = 4096; + esp_err_t ret; + // Try to mount partition + FRESULT fresult = f_mount(fs, drv, 1); + if (fresult != FR_OK) { + ESP_LOGW(TAG, "f_mount failed (%d)", fresult); + if (!((fresult == FR_NO_FILESYSTEM || fresult == FR_INT_ERR))) { + ret = ESP_FAIL; + goto fail; + } + workbuf = ff_memalloc(workbuf_size); + if (workbuf == NULL) { + ret = ESP_ERR_NO_MEM; + goto fail; + } + size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size( + CONFIG_WL_SECTOR_SIZE, + 4096); + ESP_LOGW(TAG, "formatting card, allocation unit size=%d", alloc_unit_size); + const MKFS_PARM opt = {(BYTE)FM_FAT, 0, 0, 0, alloc_unit_size}; + fresult = f_mkfs("", &opt, workbuf, workbuf_size); // Use default volume + if (fresult != FR_OK) { + ret = ESP_FAIL; + ESP_LOGE(TAG, "f_mkfs failed (%d)", fresult); + goto fail; + } + free(workbuf); + workbuf = NULL; + fresult = f_mount(fs, drv, 0); + if (fresult != FR_OK) { + ret = ESP_FAIL; + ESP_LOGE(TAG, "f_mount failed after formatting (%d)", fresult); + goto fail; + } + } + return ESP_OK; +fail: + if (workbuf) { + free(workbuf); + } + return ret; +} + +esp_err_t tinyusb_msc_storage_mount(const char *base_path) +{ + esp_err_t ret = ESP_OK; + assert(s_storage_handle); + + if (s_storage_handle->is_fat_mounted) { + return ESP_OK; + } + + tusb_msc_callback_t cb = s_storage_handle->callback_premount_changed; + if (cb) { + tinyusb_msc_event_t event = { + .type = TINYUSB_MSC_EVENT_PREMOUNT_CHANGED, + .mount_changed_data = { + .is_mounted = s_storage_handle->is_fat_mounted + } + }; + cb(&event); + } + + if (!base_path) { + base_path = CONFIG_TINYUSB_MSC_MOUNT_PATH; + } + + // connect driver to FATFS + BYTE pdrv = 0xFF; + ESP_RETURN_ON_ERROR(ff_diskio_get_drive(&pdrv), TAG, + "The maximum count of volumes is already mounted"); + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + ESP_GOTO_ON_ERROR((s_storage_handle->mount)(pdrv), fail, TAG, "Failed pdrv=%d", pdrv); + + FATFS *fs = NULL; + ret = esp_vfs_fat_register(base_path, drv, s_storage_handle->max_files, &fs); + if (ret == ESP_ERR_INVALID_STATE) { + ESP_LOGD(TAG, "it's okay, already registered with VFS"); + } else if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_vfs_fat_register failed (0x%x)", ret); + goto fail; + } + + ESP_GOTO_ON_ERROR(_mount(drv, fs), fail, TAG, "Failed _mount"); + + s_storage_handle->is_fat_mounted = true; + s_storage_handle->base_path = base_path; + + cb = s_storage_handle->callback_mount_changed; + if (cb) { + tinyusb_msc_event_t event = { + .type = TINYUSB_MSC_EVENT_MOUNT_CHANGED, + .mount_changed_data = { + .is_mounted = s_storage_handle->is_fat_mounted + } + }; + cb(&event); + } + + return ret; + +fail: + if (fs) { + esp_vfs_fat_unregister_path(base_path); + } + ff_diskio_unregister(pdrv); + s_storage_handle->is_fat_mounted = false; + ESP_LOGW(TAG, "Failed to mount storage (0x%x)", ret); + return ret; +} + +esp_err_t tinyusb_msc_storage_unmount(void) +{ + if (!s_storage_handle) { + return ESP_FAIL; + } + + if (!s_storage_handle->is_fat_mounted) { + return ESP_OK; + } + + tusb_msc_callback_t cb = s_storage_handle->callback_premount_changed; + if (cb) { + tinyusb_msc_event_t event = { + .type = TINYUSB_MSC_EVENT_PREMOUNT_CHANGED, + .mount_changed_data = { + .is_mounted = s_storage_handle->is_fat_mounted + } + }; + cb(&event); + } + + esp_err_t err = (s_storage_handle->unmount)(); + if (err) { + return err; + } + err = esp_vfs_fat_unregister_path(s_storage_handle->base_path); + s_storage_handle->base_path = NULL; + s_storage_handle->is_fat_mounted = false; + + cb = s_storage_handle->callback_mount_changed; + if (cb) { + tinyusb_msc_event_t event = { + .type = TINYUSB_MSC_EVENT_MOUNT_CHANGED, + .mount_changed_data = { + .is_mounted = s_storage_handle->is_fat_mounted + } + }; + cb(&event); + } + + return err; +} + +uint32_t tinyusb_msc_storage_get_sector_count(void) +{ + assert(s_storage_handle); + return (s_storage_handle->sector_count)(); +} + +uint32_t tinyusb_msc_storage_get_sector_size(void) +{ + assert(s_storage_handle); + return (s_storage_handle->sector_size)(); +} + +esp_err_t tinyusb_msc_storage_init_spiflash(const tinyusb_msc_spiflash_config_t *config) +{ + assert(!s_storage_handle); + s_storage_handle = (tinyusb_msc_storage_handle_s *)malloc(sizeof(tinyusb_msc_storage_handle_s)); + ESP_RETURN_ON_FALSE(s_storage_handle, ESP_ERR_NO_MEM, TAG, "could not allocate new handle for storage"); + s_storage_handle->mount = &_mount_spiflash; + s_storage_handle->unmount = &_unmount_spiflash; + s_storage_handle->sector_count = &_get_sector_count_spiflash; + s_storage_handle->sector_size = &_get_sector_size_spiflash; + s_storage_handle->read = &_read_sector_spiflash; + s_storage_handle->write = &_write_sector_spiflash; + s_storage_handle->is_fat_mounted = false; + s_storage_handle->base_path = NULL; + s_storage_handle->wl_handle = config->wl_handle; + // In case the user does not set mount_config.max_files + // and for backward compatibility with versions <1.4.2 + // max_files is set to 2 + const int max_files = config->mount_config.max_files; + s_storage_handle->max_files = max_files > 0 ? max_files : 2; + + /* Callbacks setting up*/ + if (config->callback_mount_changed) { + tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED, config->callback_mount_changed); + } else { + tinyusb_msc_unregister_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED); + } + if (config->callback_premount_changed) { + tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_PREMOUNT_CHANGED, config->callback_premount_changed); + } else { + tinyusb_msc_unregister_callback(TINYUSB_MSC_EVENT_PREMOUNT_CHANGED); + } + + return ESP_OK; +} + +#if SOC_SDMMC_HOST_SUPPORTED +esp_err_t tinyusb_msc_storage_init_sdmmc(const tinyusb_msc_sdmmc_config_t *config) +{ + assert(!s_storage_handle); + s_storage_handle = (tinyusb_msc_storage_handle_s *)malloc(sizeof(tinyusb_msc_storage_handle_s)); + ESP_RETURN_ON_FALSE(s_storage_handle, ESP_ERR_NO_MEM, TAG, "could not allocate new handle for storage"); + s_storage_handle->mount = &_mount_sdmmc; + s_storage_handle->unmount = &_unmount_sdmmc; + s_storage_handle->sector_count = &_get_sector_count_sdmmc; + s_storage_handle->sector_size = &_get_sector_size_sdmmc; + s_storage_handle->read = &_read_sector_sdmmc; + s_storage_handle->write = &_write_sector_sdmmc; + s_storage_handle->is_fat_mounted = false; + s_storage_handle->base_path = NULL; + s_storage_handle->card = config->card; + // In case the user does not set mount_config.max_files + // and for backward compatibility with versions <1.4.2 + // max_files is set to 2 + const int max_files = config->mount_config.max_files; + s_storage_handle->max_files = max_files > 0 ? max_files : 2; + + /* Callbacks setting up*/ + if (config->callback_mount_changed) { + tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED, config->callback_mount_changed); + } else { + tinyusb_msc_unregister_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED); + } + if (config->callback_premount_changed) { + tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_PREMOUNT_CHANGED, config->callback_premount_changed); + } else { + tinyusb_msc_unregister_callback(TINYUSB_MSC_EVENT_PREMOUNT_CHANGED); + } + + return ESP_OK; +} +#endif + +void tinyusb_msc_storage_deinit(void) +{ + assert(s_storage_handle); + free(s_storage_handle); + s_storage_handle = NULL; +} + +esp_err_t tinyusb_msc_register_callback(tinyusb_msc_event_type_t event_type, + tusb_msc_callback_t callback) +{ + assert(s_storage_handle); + switch (event_type) { + case TINYUSB_MSC_EVENT_MOUNT_CHANGED: + s_storage_handle->callback_mount_changed = callback; + return ESP_OK; + case TINYUSB_MSC_EVENT_PREMOUNT_CHANGED: + s_storage_handle->callback_premount_changed = callback; + return ESP_OK; + default: + ESP_LOGE(TAG, "Wrong event type"); + return ESP_ERR_INVALID_ARG; + } +} + +esp_err_t tinyusb_msc_unregister_callback(tinyusb_msc_event_type_t event_type) +{ + assert(s_storage_handle); + switch (event_type) { + case TINYUSB_MSC_EVENT_MOUNT_CHANGED: + s_storage_handle->callback_mount_changed = NULL; + return ESP_OK; + case TINYUSB_MSC_EVENT_PREMOUNT_CHANGED: + s_storage_handle->callback_premount_changed = NULL; + return ESP_OK; + default: + ESP_LOGE(TAG, "Wrong event type"); + return ESP_ERR_INVALID_ARG; + } +} + +bool tinyusb_msc_storage_in_use_by_usb_host(void) +{ + assert(s_storage_handle); + return !s_storage_handle->is_fat_mounted; +} + + +/* TinyUSB MSC callbacks + ********************************************************************* */ + +/** SCSI ASC/ASCQ codes. **/ +/** User can add and use more codes as per the need of the application **/ +#define SCSI_CODE_ASC_MEDIUM_NOT_PRESENT 0x3A /** SCSI ASC code for 'MEDIUM NOT PRESENT' **/ +#define SCSI_CODE_ASC_INVALID_COMMAND_OPERATION_CODE 0x20 /** SCSI ASC code for 'INVALID COMMAND OPERATION CODE' **/ +#define SCSI_CODE_ASCQ 0x00 + +// Invoked when received SCSI_CMD_INQUIRY +// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) +{ + (void) lun; + const char vid[] = "TinyUSB"; + const char pid[] = "Flash Storage"; + const char rev[] = "0.1"; + + memcpy(vendor_id, vid, strlen(vid)); + memcpy(product_id, pid, strlen(pid)); + memcpy(product_rev, rev, strlen(rev)); +} + +// Invoked when received Test Unit Ready command. +// return true allowing host to read/write this LUN e.g SD card inserted +bool tud_msc_test_unit_ready_cb(uint8_t lun) +{ + (void) lun; + bool result = false; + + if (s_storage_handle->is_fat_mounted) { + tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, SCSI_CODE_ASC_MEDIUM_NOT_PRESENT, SCSI_CODE_ASCQ); + result = false; + } else { + if (tinyusb_msc_storage_unmount() != ESP_OK) { + ESP_LOGW(TAG, "tud_msc_test_unit_ready_cb() unmount Fails"); + } + result = true; + } + return result; +} + +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size +void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) +{ + (void) lun; + + uint32_t sec_count = tinyusb_msc_storage_get_sector_count(); + uint32_t sec_size = tinyusb_msc_storage_get_sector_size(); + *block_count = sec_count; + *block_size = (uint16_t)sec_size; +} + +// Invoked when received Start Stop Unit command +// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage +// - Start = 1 : active mode, if load_eject = 1 : load disk storage +bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) +{ + (void) lun; + (void) power_condition; + + if (load_eject && !start) { + if (tinyusb_msc_storage_mount(s_storage_handle->base_path) != ESP_OK) { + ESP_LOGW(TAG, "tud_msc_start_stop_cb() mount Fails"); + } + } + return true; +} + +// Invoked when received SCSI READ10 command +// - Address = lba * BLOCK_SIZE + offset +// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) +{ + esp_err_t err = msc_storage_read_sector(lba, offset, bufsize, buffer); + if (err != ESP_OK) { + ESP_LOGE(TAG, "msc_storage_read_sector failed: 0x%x", err); + return 0; + } + return bufsize; +} + +// Invoked when received SCSI WRITE10 command +// - Address = lba * BLOCK_SIZE + offset +// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) +{ + esp_err_t err = msc_storage_write_sector(lba, offset, bufsize, buffer); + if (err != ESP_OK) { + ESP_LOGE(TAG, "msc_storage_write_sector failed: 0x%x", err); + return 0; + } + return bufsize; +} + +/** + * Invoked when received an SCSI command not in built-in list below. + * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE + * - READ10 and WRITE10 has their own callbacks + * + * \param[in] lun Logical unit number + * \param[in] scsi_cmd SCSI command contents which application must examine to response accordingly + * \param[out] buffer Buffer for SCSI Data Stage. + * - For INPUT: application must fill this with response. + * - For OUTPUT it holds the Data from host + * \param[in] bufsize Buffer's length. + * + * \return Actual bytes processed, can be zero for no-data command. + * \retval negative Indicate error e.g unsupported command, tinyusb will \b STALL the corresponding + * endpoint and return failed status in command status wrapper phase. + */ +int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) +{ + int32_t ret; + + switch (scsi_cmd[0]) { + case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + /* SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL is the Prevent/Allow Medium Removal + command (1Eh) that requests the library to enable or disable user access to + the storage media/partition. */ + ret = 0; + break; + default: + ESP_LOGW(TAG, "tud_msc_scsi_cb() invoked: %d", scsi_cmd[0]); + tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_CODE_ASC_INVALID_COMMAND_OPERATION_CODE, SCSI_CODE_ASCQ); + ret = -1; + break; + } + return ret; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + if (tinyusb_msc_storage_mount(s_storage_handle->base_path) != ESP_OK) { + ESP_LOGW(TAG, "tud_umount_cb() mount Fails"); + } +} + +// Invoked when device is mounted (configured) +void tud_mount_cb(void) +{ + tinyusb_msc_storage_unmount(); +} +/*********************************************************************** TinyUSB MSC callbacks*/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_tasks.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_tasks.c new file mode 100644 index 000000000..cd4add4e1 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_tasks.c @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_log.h" +#include "esp_check.h" +#include "tinyusb.h" +#include "tusb_tasks.h" + +const static char *TAG = "tusb_tsk"; +static TaskHandle_t s_tusb_tskh; + +#if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK +const static int INIT_OK = BIT0; +const static int INIT_FAILED = BIT1; +#endif + +/** + * @brief This top level thread processes all usb events and invokes callbacks + */ +static void tusb_device_task(void *arg) +{ + ESP_LOGD(TAG, "tinyusb task started"); +#if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK + EventGroupHandle_t *init_flags = arg; + if (!tusb_init()) { + ESP_LOGI(TAG, "Init TinyUSB stack failed"); + xEventGroupSetBits(*init_flags, INIT_FAILED); + vTaskDelete(NULL); + } + ESP_LOGD(TAG, "tinyusb task has been initialized"); + xEventGroupSetBits(*init_flags, INIT_OK); +#endif // CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK + while (1) { // RTOS forever loop + tud_task(); + } +} + +esp_err_t tusb_run_task(void) +{ + // This function is not guaranteed to be thread safe, if invoked multiple times without calling `tusb_stop_task`, will cause memory leak + // doing a sanity check anyway + ESP_RETURN_ON_FALSE(!s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task already started"); + + void *task_arg = NULL; +#if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK + // need to synchronize to potentially report issue if init failed + EventGroupHandle_t init_flags = xEventGroupCreate(); + ESP_RETURN_ON_FALSE(init_flags, ESP_ERR_NO_MEM, TAG, "Failed to allocate task sync flags"); + task_arg = &init_flags; +#endif + // Create a task for tinyusb device stack: + xTaskCreatePinnedToCore(tusb_device_task, "TinyUSB", CONFIG_TINYUSB_TASK_STACK_SIZE, task_arg, CONFIG_TINYUSB_TASK_PRIORITY, &s_tusb_tskh, CONFIG_TINYUSB_TASK_AFFINITY); + ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed"); +#if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK + // wait until tusb initialization has completed + EventBits_t bits = xEventGroupWaitBits(init_flags, INIT_OK | INIT_FAILED, pdFALSE, pdFALSE, portMAX_DELAY); + vEventGroupDelete(init_flags); + ESP_RETURN_ON_FALSE(bits & INIT_OK, ESP_FAIL, TAG, "Init TinyUSB stack failed"); +#endif + + return ESP_OK; +} + +esp_err_t tusb_stop_task(void) +{ + ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task not started yet"); + vTaskDelete(s_tusb_tskh); + s_tusb_tskh = NULL; + return ESP_OK; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/usb_descriptors.c similarity index 50% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/usb_descriptors.c index d4d3004e7..891091336 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/usb_descriptors.c @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "usb_descriptors.h" #include "sdkconfig.h" +#include "tinyusb_types.h" /* * A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. @@ -14,12 +15,15 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ +#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #define USB_TUSB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ _PID_MAP(MIDI, 3) ) //| _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) -/**** TinyUSB default ****/ -tusb_desc_device_t descriptor_tinyusb = { - .bLength = sizeof(descriptor_tinyusb), +/**** Kconfig driven Descriptor ****/ + +//------------- Device Descriptor -------------// +const tusb_desc_device_t descriptor_dev_default = { + .bLength = sizeof(descriptor_dev_default), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, @@ -37,9 +41,19 @@ tusb_desc_device_t descriptor_tinyusb = { .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, +#if CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID + .idVendor = USB_ESPRESSIF_VID, +#else + .idVendor = CONFIG_TINYUSB_DESC_CUSTOM_VID, +#endif + +#if CONFIG_TINYUSB_DESC_USE_DEFAULT_PID .idProduct = USB_TUSB_PID, - .bcdDevice = 0x0100, +#else + .idProduct = CONFIG_TINYUSB_DESC_CUSTOM_PID, +#endif + + .bcdDevice = CONFIG_TINYUSB_DESC_BCD_DEVICE, .iManufacturer = 0x01, .iProduct = 0x02, @@ -48,19 +62,10 @@ tusb_desc_device_t descriptor_tinyusb = { .bNumConfigurations = 0x01 }; -tusb_desc_strarray_device_t descriptor_str_tinyusb = { - // array of pointer to string descriptors - (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - "123456", // 3: Serials, should use chip ID -}; -/* End of TinyUSB default */ - -/**** Kconfig driven Descriptor ****/ -const tusb_desc_device_t descriptor_dev_kconfig = { - .bLength = sizeof(descriptor_dev_kconfig), - .bDescriptorType = TUSB_DESC_DEVICE, +#if (TUD_OPT_HIGH_SPEED) +const tusb_desc_device_qualifier_t descriptor_qualifier_default = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, .bcdUSB = 0x0200, #if CFG_TUD_CDC @@ -76,29 +81,13 @@ const tusb_desc_device_t descriptor_dev_kconfig = { #endif .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - -#if CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID - .idVendor = USB_ESPRESSIF_VID, -#else - .idVendor = CONFIG_TINYUSB_DESC_CUSTOM_VID, -#endif - -#if CONFIG_TINYUSB_DESC_USE_DEFAULT_PID - .idProduct = USB_TUSB_PID, -#else - .idProduct = CONFIG_TINYUSB_DESC_CUSTOM_PID, -#endif - - .bcdDevice = CONFIG_TINYUSB_DESC_BCD_DEVICE, - - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - - .bNumConfigurations = 0x01 + .bNumConfigurations = 0x01, + .bReserved = 0 }; +#endif // TUD_OPT_HIGH_SPEED -tusb_desc_strarray_device_t descriptor_str_kconfig = { +//------------- Array of String Descriptors -------------// +const char *descriptor_str_default[] = { // array of pointer to string descriptors (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) CONFIG_TINYUSB_DESC_MANUFACTURER_STRING, // 1: Manufacturer @@ -117,9 +106,14 @@ tusb_desc_strarray_device_t descriptor_str_kconfig = { "", #endif +#if CONFIG_TINYUSB_NET_MODE_ECM_RNDIS || CONFIG_TINYUSB_NET_MODE_NCM + "USB net", // 6. NET Interface + "", // 7. MAC +#endif + NULL // NULL: Must be last. Indicates end of array }; -//------------- Configuration Descriptor -------------// +//------------- Interfaces enumeration -------------// enum { #if CFG_TUD_CDC ITF_NUM_CDC = 0, @@ -135,13 +129,19 @@ enum { ITF_NUM_MSC, #endif +#if CFG_TUD_NCM + ITF_NUM_NET, + ITF_NUM_NET_DATA, +#endif + ITF_NUM_TOTAL }; enum { TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN + - CFG_TUD_CDC * TUD_CDC_DESC_LEN + - CFG_TUD_MSC * TUD_MSC_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN + + CFG_TUD_MSC * TUD_MSC_DESC_LEN + + CFG_TUD_NCM * TUD_CDC_NCM_DESC_LEN }; //------------- USB Endpoint numbers -------------// @@ -161,26 +161,91 @@ enum { #if CFG_TUD_MSC EPNUM_MSC, #endif + +#if CFG_TUD_NCM + EPNUM_NET_NOTIF, + EPNUM_NET_DATA, +#endif +}; + +//------------- STRID -------------// +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, +#if CFG_TUD_CDC + STRID_CDC_INTERFACE, +#endif + +#if CFG_TUD_MSC + STRID_MSC_INTERFACE, +#endif + +#if CFG_TUD_NCM + STRID_NET_INTERFACE, + STRID_MAC, +#endif + }; -uint8_t const descriptor_cfg_kconfig[] = { +//------------- Configuration Descriptor -------------// +uint8_t const descriptor_fs_cfg_default[] = { // Configuration number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), #if CFG_TUD_CDC // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, CFG_TUD_CDC_EP_BUFSIZE), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, STRID_CDC_INTERFACE, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, 64), #endif #if CFG_TUD_CDC > 1 // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, CFG_TUD_CDC_EP_BUFSIZE), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, STRID_CDC_INTERFACE, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, 64), #endif #if CFG_TUD_MSC // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512 + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC_INTERFACE, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), +#endif + +#if CFG_TUD_NCM + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_NET, STRID_NET_INTERFACE, STRID_MAC, (0x80 | EPNUM_NET_NOTIF), 64, EPNUM_NET_DATA, (0x80 | EPNUM_NET_DATA), 64, CFG_TUD_NET_MTU), #endif }; +#if (TUD_OPT_HIGH_SPEED) +uint8_t const descriptor_hs_cfg_default[] = { + // Configuration number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + +#if CFG_TUD_CDC + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, STRID_CDC_INTERFACE, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, 512), +#endif + +#if CFG_TUD_CDC > 1 + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, STRID_CDC_INTERFACE, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, 512), +#endif + +#if CFG_TUD_MSC + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC_INTERFACE, EPNUM_MSC, 0x80 | EPNUM_MSC, 512), +#endif + +#if CFG_TUD_NCM + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_NET, STRID_NET_INTERFACE, STRID_MAC, (0x80 | EPNUM_NET_NOTIF), 64, EPNUM_NET_DATA, (0x80 | EPNUM_NET_DATA), 512, CFG_TUD_NET_MTU), +#endif +}; +#endif // TUD_OPT_HIGH_SPEED + +#if CFG_TUD_NCM +uint8_t tusb_get_mac_string_id(void) +{ + return STRID_MAC; +} +#endif /* End of Kconfig driven Descriptor */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml deleted file mode 100644 index db103d80e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml +++ /dev/null @@ -1,3 +0,0 @@ -# Newt uses this file to determine the version of a checked out repo. -# This should always be 0.0.0 in the master branch. -repo.version: 0.0.0 diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/vfs_tinyusb.c similarity index 66% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/vfs_tinyusb.c index fdf31e6a9..8b8cea9ee 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/vfs_tinyusb.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,8 +23,6 @@ #include "sdkconfig.h" const static char *TAG = "tusb_vfs"; -#define VFS_TUSB_MAX_PATH 16 -#define VFS_TUSB_PATH_DEFAULT "/dev/tusb_cdc" // Token signifying that no character is available #define NONE -1 @@ -69,19 +67,17 @@ static vfs_tinyusb_t s_vfstusb; static esp_err_t apply_path(char const *path) { - if (path != NULL) { - size_t path_len = strlen(path) + 1; - if (path_len > VFS_TUSB_MAX_PATH) { - ESP_LOGE(TAG, "The path is too long; maximum is %d characters", VFS_TUSB_MAX_PATH); - return ESP_ERR_INVALID_ARG; - } - strncpy(s_vfstusb.vfs_path, path, (VFS_TUSB_MAX_PATH - 1)); - } else { - strncpy(s_vfstusb.vfs_path, - VFS_TUSB_PATH_DEFAULT, - (VFS_TUSB_MAX_PATH - 1)); + if (path == NULL) { + path = VFS_TUSB_PATH_DEFAULT; } - ESP_LOGV(TAG, "Path is set to `%s`", s_vfstusb.vfs_path); + + size_t path_len = strlen(path) + 1; + if (path_len > VFS_TUSB_MAX_PATH) { + ESP_LOGE(TAG, "The path is too long; maximum is %d characters", VFS_TUSB_MAX_PATH); + return ESP_ERR_INVALID_ARG; + } + strncpy(s_vfstusb.vfs_path, path, (VFS_TUSB_MAX_PATH - 1)); + ESP_LOGV(TAG, "Path is set to `%s`", path); return ESP_OK; } @@ -109,7 +105,6 @@ static void vfstusb_deinit(void) memset(&s_vfstusb, 0, sizeof(s_vfstusb)); } - static int tusb_open(const char *path, int flags, int mode) { (void) mode; @@ -126,24 +121,25 @@ static ssize_t tusb_write(int fd, const void *data, size_t size) _lock_acquire(&(s_vfstusb.write_lock)); for (size_t i = 0; i < size; i++) { int c = data_c[i]; - /* handling the EOL */ - if (c == '\n' && s_vfstusb.tx_mode != ESP_LINE_ENDINGS_LF) { - if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, '\r')) { - written_sz++; - } else { + if (c != '\n') { + if (!tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, c)) { break; // can't write anymore } - if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CR) { - continue; - } - } - /* write a char */ - if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, c)) { - written_sz++; } else { - break; // can't write anymore + if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CRLF || s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CR) { + char cr = '\r'; + if (!tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, cr)) { + break; // can't write anymore + } + } + if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CRLF || s_vfstusb.tx_mode == ESP_LINE_ENDINGS_LF) { + char lf = '\n'; + if (!tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, lf)) { + break; // can't write anymore + } + } } - + written_sz++; } tud_cdc_n_write_flush(s_vfstusb.cdc_intf); _lock_release(&(s_vfstusb.write_lock)); @@ -162,31 +158,40 @@ static ssize_t tusb_read(int fd, void *data, size_t size) char *data_c = (char *) data; size_t received = 0; _lock_acquire(&(s_vfstusb.read_lock)); - int cm1 = NONE; - int c = NONE; + if (tud_cdc_n_available(s_vfstusb.cdc_intf) == 0) { + goto finish; + } while (received < size) { - cm1 = c; // store the old char - int c = tud_cdc_n_read_char(0); // get a new one + int c = tud_cdc_n_read_char(s_vfstusb.cdc_intf); + if ( c == NONE) { // if data ends + break; + } + + // Handle line endings. From configured mode -> LF mode if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) { + // Change CRs to newlines if (c == '\r') { c = '\n'; } - } else if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) { - if ((c == '\n') & (cm1 == '\r')) { - --received; // step back - c = '\n'; + } else if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CRLF) { + if (c == '\r') { + uint8_t next_char = NONE; + // Check if next char is newline. If yes, we got CRLF sequence + tud_cdc_n_peek(s_vfstusb.cdc_intf, &next_char); + if (next_char == '\n') { + c = tud_cdc_n_read_char(s_vfstusb.cdc_intf); // Remove '\n' from the fifo + } } } - if ( c == NONE) { // if data ends - break; - } + data_c[received] = (char) c; ++received; if (c == '\n') { break; } } +finish: _lock_release(&(s_vfstusb.read_lock)); if (received > 0) { return received; @@ -195,7 +200,6 @@ static ssize_t tusb_read(int fd, void *data, size_t size) return -1; } - static int tusb_fstat(int fd, struct stat *st) { FD_CHECK(fd, -1); @@ -225,39 +229,33 @@ static int tusb_fcntl(int fd, int cmd, int arg) esp_err_t esp_vfs_tusb_cdc_unregister(char const *path) { - ESP_LOGD(TAG, "Unregistering TinyUSB driver"); + ESP_LOGD(TAG, "Unregistering CDC-VFS driver"); int res; if (path == NULL) { // NULL means using the default path for unregistering: VFS_TUSB_PATH_DEFAULT - res = strcmp(s_vfstusb.vfs_path, VFS_TUSB_PATH_DEFAULT); - } else { - res = strcmp(s_vfstusb.vfs_path, path); + path = VFS_TUSB_PATH_DEFAULT; } + res = strcmp(s_vfstusb.vfs_path, path); if (res) { res = ESP_ERR_INVALID_ARG; - ESP_LOGE(TAG, "There is no TinyUSB driver registerred to the path '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); + ESP_LOGE(TAG, "There is no CDC-VFS driver registered to path '%s' (err: 0x%x)", path, res); return res; } - - res = esp_vfs_unregister(s_vfstusb.vfs_path); if (res != ESP_OK) { - ESP_LOGE(TAG, "Can't unregister TinyUSB driver from '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); + ESP_LOGE(TAG, "Can't unregister CDC-VFS driver from '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); } else { - ESP_LOGD(TAG, "Unregistered TinyUSB driver"); + ESP_LOGD(TAG, "Unregistered CDC-VFS driver"); vfstusb_deinit(); } return res; } - - - esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path) { - ESP_LOGD(TAG, "Registering TinyUSB CDC driver"); + ESP_LOGD(TAG, "Registering CDC-VFS driver"); int res; if (!tusb_cdc_acm_initialized(cdc_intf)) { ESP_LOGE(TAG, "TinyUSB CDC#%d is not initialized", cdc_intf); @@ -281,9 +279,23 @@ esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path) res = esp_vfs_register(s_vfstusb.vfs_path, &vfs, NULL); if (res != ESP_OK) { - ESP_LOGE(TAG, "Can't register TinyUSB driver (err: %x)", res); + ESP_LOGE(TAG, "Can't register CDC-VFS driver (err: %x)", res); } else { - ESP_LOGD(TAG, "TinyUSB CDC registered (%s)", s_vfstusb.vfs_path); + ESP_LOGD(TAG, "CDC-VFS registered (%s)", s_vfstusb.vfs_path); } return res; } + +void esp_vfs_tusb_cdc_set_rx_line_endings(esp_line_endings_t mode) +{ + _lock_acquire(&(s_vfstusb.read_lock)); + s_vfstusb.rx_mode = mode; + _lock_release(&(s_vfstusb.read_lock)); +} + +void esp_vfs_tusb_cdc_set_tx_line_endings(esp_line_endings_t mode) +{ + _lock_acquire(&(s_vfstusb.write_lock)); + s_vfstusb.tx_mode = mode; + _lock_release(&(s_vfstusb.write_lock)); +} diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index 5a646e838..d0f4a39b3 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -32,8 +32,9 @@ class Esp32ExceptionDecoder(DeviceMonitorFilterBase): NAME = "esp32_exception_decoder" - BACKTRACE_PATTERN = re.compile(r"^Backtrace:(((\s?0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8}))+)") - BACKTRACE_ADDRESS_PATTERN = re.compile(r'0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8}') + ADDR_PATTERN = re.compile(r"((?:0x[0-9a-fA-F]{8}[: ]?)+)\s?$") + ADDR_SPLIT = re.compile(r"[ :]") + PREFIX_RE = re.compile(r"^ *") def __call__(self): self.buffer = "" @@ -56,7 +57,8 @@ def __call__(self): def setup_paths(self): self.project_dir = os.path.abspath(self.project_dir) try: - data = load_build_metadata(self.project_dir, self.environment) + data = load_build_metadata(self.project_dir, self.environment, cache=True) + self.firmware_path = data["prog_path"] if not os.path.isfile(self.firmware_path): sys.stderr.write( @@ -100,38 +102,65 @@ def rx(self, text): self.buffer = "" last = idx + 1 - m = self.BACKTRACE_PATTERN.match(line) + m = self.ADDR_PATTERN.search(line) if m is None: continue - trace = self.get_backtrace(m) - if len(trace) != "": + trace = self.build_backtrace(line, m.group(1)) + if trace: text = text[: idx + 1] + trace + text[idx + 1 :] last += len(trace) return text - def get_backtrace(self, match): - trace = "\n" + def is_address_ignored(self, address): + return address in ("", "0x00000000") + + def filter_addresses(self, adresses_str): + addresses = self.ADDR_SPLIT.split(adresses_str) + size = len(addresses) + while size > 1 and self.is_address_ignored(addresses[size-1]): + size -= 1 + return addresses[:size] + + def build_backtrace(self, line, address_match): + addresses = self.filter_addresses(address_match) + if not addresses: + return "" + + prefix_match = self.PREFIX_RE.match(line) + prefix = prefix_match.group(0) if prefix_match is not None else "" + + trace = "" enc = "mbcs" if IS_WINDOWS else "utf-8" args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path] try: - for i, addr in enumerate(self.BACKTRACE_ADDRESS_PATTERN.findall(match.group(1))): + i = 0 + for addr in addresses: output = ( subprocess.check_output(args + [addr]) .decode(enc) .strip() ) + + # newlines happen with inlined methods output = output.replace( "\n", "\n " - ) # newlines happen with inlined methods + ) + + # throw out addresses not from ELF + if output == "?? ??:0": + continue + output = self.strip_project_dir(output) - trace += " #%-2d %s in %s\n" % (i, addr, output) + trace += "%s #%-2d %s in %s\n" % (prefix, i, addr, output) + i += 1 except subprocess.CalledProcessError as e: sys.stderr.write( "%s: failed to call %s: %s\n" % (self.__class__.__name__, self.addr2line_path, e) ) - return trace + + return trace + "\n" if trace else "" def strip_project_dir(self, trace): while True: diff --git a/platform.json b/platform.json index 5bf959b7b..ee0745b68 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/platformio/platform-espressif32.git" }, - "version": "6.4.0", + "version": "6.9.0", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -33,35 +33,38 @@ "toolchain-xtensa-esp32": { "type": "toolchain", "owner": "espressif", - "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["12.2.0+20230208"] + "version": "8.4.0+2021r2-patch5" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["12.2.0+20230208"] + "version": "8.4.0+2021r2-patch5" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["12.2.0+20230208"] + "version": "8.4.0+2021r2-patch5" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["12.2.0+20230208"] + "optionalVersions": ["13.2.0+20240530"] + }, + "toolchain-xtensa-esp-elf": { + "type": "toolchain", + "optional": true, + "owner": "platformio", + "version": "13.2.0+20240530" }, "toolchain-esp32ulp": { "type": "toolchain", "optional": true, "owner": "platformio", - "version": "~1.23500.0" + "version": "~1.23800.0" }, "tool-xtensa-esp-elf-gdb": { "type": "debugger", @@ -79,31 +82,20 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.20011.0" - }, - "framework-arduino-mbcwb": { - "type": "framework", - "optional": true, - "owner": "meteca", - "version": ">=2.1.1" + "version": "~3.20017.0" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.50101.0", - "optionalVersions": ["~3.40405.0"] + "version": "~3.50301.0", + "optionalVersions": ["~3.40407.0"] }, "tool-esptoolpy": { "type": "uploader", "owner": "platformio", "version": "~1.40501.0" }, - "tool-mbctool": { - "optional": true, - "owner": "meteca", - "version": ">=2.0.0" - }, "tool-dfuutil-arduino": { "type": "uploader", "optional": true, diff --git a/platform.py b/platform.py index 834384a7b..895948e06 100644 --- a/platform.py +++ b/platform.py @@ -113,55 +113,47 @@ def configure_default_packages(self, variables, targets): if "arduino" in frameworks: # Downgrade the IDF version for mixed Arduino+IDF projects - self.packages["framework-espidf"]["version"] = "~3.40405.0" + self.packages["framework-espidf"]["version"] = "~3.40407.0" + # Delete the latest toolchain packages from config + self.packages.pop("toolchain-xtensa-esp-elf", None) else: - # Use the latest toolchains available for IDF v5.0 + # Disable old toolchain packages and use the latest + # available for IDF v5.0 for target in ( "xtensa-esp32", "xtensa-esp32s2", "xtensa-esp32s3", - "riscv32-esp" ): - self.packages["toolchain-%s" % target]["version"] = "12.2.0+20230208" + self.packages.pop("toolchain-%s" % target, None) + + if mcu in ("esp32c3", "esp32c6"): + self.packages.pop("toolchain-xtensa-esp-elf", None) + else: + self.packages["toolchain-xtensa-esp-elf"][ + "optional" + ] = False + + # Pull the latest RISC-V toolchain from PlatformIO organization + self.packages["toolchain-riscv32-esp"]["owner"] = "platformio" + self.packages["toolchain-riscv32-esp"][ + "version" + ] = "13.2.0+20240530" if "arduino" in frameworks: # Disable standalone GDB packages for Arduino and Arduino/IDF projects for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): self.packages.pop(gdb_package, None) - for available_mcu in ("esp32", "esp32s2", "esp32s3"): - if available_mcu == mcu: - self.packages["toolchain-xtensa-%s" % mcu]["optional"] = False - else: - self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) + for available_mcu in ("esp32", "esp32s2", "esp32s3"): + if available_mcu == mcu: + self.packages["toolchain-xtensa-%s" % mcu]["optional"] = False + else: + self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) if mcu in ("esp32s2", "esp32s3", "esp32c3", "esp32c6"): # RISC-V based toolchain for ESP32C3, ESP32C6 ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp"]["optional"] = False - if build_core == "mbcwb": - # Remove the main toolchains from PATH - for toolchain in ( - "toolchain-xtensa-esp32", - "toolchain-xtensa-esp32s2", - "toolchain-xtensa-esp32s3", - "toolchain-riscv32-esp", - ): - self.packages.pop(toolchain, None) - - # Add legacy toolchain with specific version - self.packages["toolchain-xtensa32"] = { - "type": "toolchain", - "owner": "platformio", - "version": "~2.50200.0" - } - - if build_core == "mbcwb": - self.packages["framework-arduinoespressif32"]["optional"] = True - self.packages["framework-arduino-mbcwb"]["optional"] = False - self.packages["tool-mbctool"]["type"] = "uploader" - self.packages["tool-mbctool"]["optional"] = False - return super().configure_default_packages(variables, targets) def get_boards(self, id_=None): @@ -184,7 +176,7 @@ def _add_dynamic_options(self, board): # debug tools debug = board.manifest.get("debug", {}) - non_debug_protocols = ["esptool", "espota", "mbctool"] + non_debug_protocols = ["esptool", "espota"] supported_debug_tools = [ "cmsis-dap", "esp-prog",