这次介绍的是在 Arduino 1.8.16 + ESP32 2.0.1 下实现假U盘的例子。特别强调:ESP32 Arduino 环境必须是 2.0.1, 更高的版本反倒有兼容问题。
实现的方法和之前的相同【参考1】: 1. 首先在本机做一个虚拟的256MB硬盘,然后在上面放置一个 200MB 的内容为全0x00的文件(太大的话,处理起来非常麻烦); 2. 将这个硬盘使用HXD做成镜像文件,然后使用工具扫描这个文件,将所有的不为0的内容写入.h文件中(这就是256MBDisk.bin.h文件的来源); 3. 这个文件中0x804到 0x8CC扇区内容,和0x902到 0x9CA扇区内容相同,因此在数组中删除后者内容,当有到这个扇区的请求时,用前者的内容替代,这样可以大大缩减编译后文件的体积; 4. 在代码中响应 onRead(),如果请求的LBA在.h文件中,就进行Buffer的填充; 5. 插入过程 Windows 有写入操作,因此必须响应 onWrite
完整代码如下:
- #include "USB.h"
- #include "USBMSC.h"
- #include "256MBDisk.h"
- #if ARDUINO_USB_CDC_ON_BOOT
- #define HWSerial Serial0
- #define USBSerial Serial
- #else
- #define HWSerial Serial
- //USBCDC USBSerial;
- #endif
- USBMSC MSC;
- uint32_t findLBA(uint32_t LBA) {
- for (uint32_t i=0; i<415;i++) {
- if (Index[i]==LBA) {
- if (i>=205) {i=i-205+4;}
- return i;
- }
- }
- return 0xFFFFFF;
- }
- static const uint32_t DISK_SECTOR_COUNT = 520192;
- static int32_t onRead(uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize){
- //HWSerial.printf("MSC READ: lba: %u, offset: %u, bufsize: %u\n", lba, offset, bufsize);
- uint32_t getLBA=0;
- uint8_t *p;
- p=(uint8_t *)buffer;
- //HWSerial.printf("Buffer1 %X\n", buffer);
- for (uint32_t i=0;i<bufsize/DISK_SECTOR_SIZE;i++) {
- //HWSerial.printf("Check %u\n", lba+i);
- getLBA=findLBA(lba+i);
- //HWSerial.printf("getLBA %u %u\n", getLBA,lba+i);
- if (getLBA!=0xFFFFFF) { //如果找到了
- memcpy((void *)&p[i*DISK_SECTOR_SIZE], &msc_disk[getLBA][0], DISK_SECTOR_SIZE);
- //HWSerial.printf("%u %u %u %u\n", msc_disk[getLBA][0],msc_disk[getLBA][1],msc_disk[getLBA][2],msc_disk[getLBA][3]);
- //HWSerial.printf("Send %u\n", getLBA);
- //HWSerial.printf("Buffer2 %X\n", (void *)&p[i*DISK_SECTOR_SIZE]);
- } else {
- //HWSerial.printf("Send all zero to %u\n", getLBA);
- for (uint16_t j=0;j<DISK_SECTOR_SIZE;j++) {
- p[i*DISK_SECTOR_SIZE+j]=0;
- }
-
- }
- }
- return bufsize;
- }
- static bool onStartStop(uint8_t power_condition, bool start, bool load_eject){
- HWSerial.printf("MSC START/STOP: power: %u, start: %u, eject: %u\n", power_condition, start, load_eject);
- return true;
- }
- static void usbEventCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
- if(event_base == ARDUINO_USB_EVENTS){
- arduino_usb_event_data_t * data = (arduino_usb_event_data_t*)event_data;
- switch (event_id){
- case ARDUINO_USB_STARTED_EVENT:
- HWSerial.println("USB PLUGGED");
- break;
- case ARDUINO_USB_STOPPED_EVENT:
- HWSerial.println("USB UNPLUGGED");
- break;
- case ARDUINO_USB_SUSPEND_EVENT:
- HWSerial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en);
- break;
- case ARDUINO_USB_RESUME_EVENT:
- HWSerial.println("USB RESUMED");
- break;
-
- default:
- break;
- }
- }
- }
- static int32_t onWrite(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize){
- HWSerial.printf("MSC WRITE: lba: %u, offset: %u, bufsize: %u\n", lba, offset, bufsize);
- return bufsize;
- }
- void setup() {
- HWSerial.begin(115200);
- HWSerial.setDebugOutput(true);
- USB.onEvent(usbEventCallback);
- MSC.vendorID("ESP32");//max 8 chars
- MSC.productID("USB_MSC");//max 16 chars
- MSC.productRevision("1.02");//max 4 chars
- MSC.onStartStop(onStartStop);
- MSC.onRead(onRead);
- MSC.onWrite(onWrite);
- MSC.mediaPresent(true);
- MSC.begin(DISK_SECTOR_COUNT, DISK_SECTOR_SIZE);
- //USBSerial.begin();
- USB.begin();
- }
- void loop() {
- // put your main code here, to run repeatedly:
- }
复制代码
参考:
|