test_usb_mock_msc.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <inttypes.h>
  7. #include <stdbool.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "usb/usb_types_ch9.h"
  11. #include "test_usb_mock_msc.h"
  12. // ---------------------------------------------------- MSC SCSI -------------------------------------------------------
  13. const char *MSC_CLIENT_TAG = "MSC Client";
  14. const usb_device_desc_t mock_msc_scsi_dev_desc = {
  15. .bLength = USB_DEVICE_DESC_SIZE,
  16. .bDescriptorType = USB_B_DESCRIPTOR_TYPE_DEVICE,
  17. .bcdUSB = MOCK_MSC_SCSI_USB_VERSION,
  18. .bDeviceClass = USB_CLASS_PER_INTERFACE,
  19. .bDeviceSubClass = 0,
  20. .bDeviceProtocol = 0,
  21. .bMaxPacketSize0 = MOCK_MSC_SCSI_DEV_DFLT_EP_MPS,
  22. .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR,
  23. .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT,
  24. .bcdDevice = MOCK_MSC_SCSI_DEV_VERSION,
  25. .iManufacturer = 1,
  26. .iProduct = 2,
  27. .iSerialNumber = 3,
  28. .bNumConfigurations = 1,
  29. };
  30. #define MOCK_MSC_SCSI_WTOTALLENGTH (USB_CONFIG_DESC_SIZE + USB_INTF_DESC_SIZE + 2*USB_EP_DESC_SIZE)
  31. static const usb_config_desc_t mock_msc_config_desc = {
  32. .bLength = USB_CONFIG_DESC_SIZE,
  33. .bDescriptorType = USB_B_DESCRIPTOR_TYPE_CONFIGURATION,
  34. .wTotalLength = MOCK_MSC_SCSI_WTOTALLENGTH,
  35. .bNumInterfaces = 1,
  36. .bConfigurationValue = 1,
  37. .iConfiguration = 0,
  38. .bmAttributes = 0x80,
  39. .bMaxPower = 0x70, //224mA
  40. };
  41. static const usb_intf_desc_t mock_msc_intf_desc = {
  42. .bLength = USB_INTF_DESC_SIZE,
  43. .bDescriptorType = USB_B_DESCRIPTOR_TYPE_INTERFACE,
  44. .bInterfaceNumber = MOCK_MSC_SCSI_INTF_NUMBER,
  45. .bAlternateSetting = MOCK_MSC_SCSI_INTF_ALT_SETTING,
  46. .bNumEndpoints = 2,
  47. .bInterfaceClass = USB_CLASS_MASS_STORAGE,
  48. .bInterfaceSubClass = 0x06, //SCSI
  49. .bInterfaceProtocol = 0x50, //Bulk only
  50. .iInterface = 0,
  51. };
  52. uint8_t mock_msc_scsi_config_desc[255];
  53. uint16_t mock_msc_scsi_str_desc_manu[128];
  54. uint16_t mock_msc_scsi_str_desc_prod[128];
  55. uint16_t mock_msc_scsi_str_desc_ser_num[128];
  56. const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc = {
  57. .bLength = sizeof(usb_ep_desc_t),
  58. .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
  59. .bEndpointAddress = MOCK_MSC_SCSI_BULK_OUT_EP_ADDR, //EP 1 OUT
  60. .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK,
  61. .wMaxPacketSize = MOCK_MSC_SCSI_BULK_EP_MPS, //MPS of 64 bytes
  62. .bInterval = 0,
  63. };
  64. const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc = {
  65. .bLength = sizeof(usb_ep_desc_t),
  66. .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
  67. .bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR,
  68. .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK,
  69. .wMaxPacketSize = MOCK_MSC_SCSI_BULK_EP_MPS, //MPS of 64 bytes
  70. .bInterval = 0,
  71. };
  72. void mock_msc_scsi_init_cbw(mock_msc_bulk_cbw_t *cbw, bool is_read, int offset, int num_sectors, uint32_t tag)
  73. {
  74. cbw->dCBWSignature = 0x43425355; //Fixed value
  75. cbw->dCBWTag = tag; //Random value that is echoed back
  76. cbw->dCBWDataTransferLength = num_sectors * MOCK_MSC_SCSI_SECTOR_SIZE;
  77. cbw->bmCBWFlags = (is_read) ? (1 << 7) : 0; //If this is a read, set the direction flag
  78. cbw->bCBWLUN = MOCK_MSC_SCSI_LUN;
  79. cbw->bCBWCBLength = 10; //The length of the SCSI command
  80. //Initialize SCSI CMD as READ10 or WRITE 10
  81. cbw->CBWCB.opcode = (is_read) ? 0x28 : 0x2A; //SCSI CMD READ10 or WRITE10
  82. cbw->CBWCB.flags = 0;
  83. cbw->CBWCB.lba_3 = (offset >> 24);
  84. cbw->CBWCB.lba_2 = (offset >> 16);
  85. cbw->CBWCB.lba_1 = (offset >> 8);
  86. cbw->CBWCB.lba_0 = (offset >> 0);
  87. cbw->CBWCB.group = 0;
  88. cbw->CBWCB.len_1 = (num_sectors >> 8);
  89. cbw->CBWCB.len_0 = (num_sectors >> 0);
  90. cbw->CBWCB.control = 0;
  91. }
  92. bool mock_msc_scsi_check_csw(mock_msc_bulk_csw_t *csw, uint32_t tag_expect)
  93. {
  94. bool no_issues = true;
  95. if (csw->dCSWSignature != 0x53425355) {
  96. no_issues = false;
  97. printf("Warning: csw signature corrupt (0x%"PRIX32")\n", csw->dCSWSignature);
  98. }
  99. if (csw->dCSWTag != tag_expect) {
  100. no_issues = false;
  101. printf("Warning: csw tag unexpected! Expected %"PRIu32" got %"PRIu32"\n", tag_expect, csw->dCSWTag);
  102. }
  103. if (csw->dCSWDataResidue) {
  104. no_issues = false;
  105. printf("Warning: csw indicates data residue of %"PRIu32" bytes!\n", csw->dCSWDataResidue);
  106. }
  107. if (csw->bCSWStatus) {
  108. no_issues = false;
  109. printf("Warning: csw indicates non-good status %d!\n", csw->bCSWStatus);
  110. }
  111. return no_issues;
  112. }
  113. void mock_msc_scsi_init_reference_descriptors(void)
  114. {
  115. // Configuration descriptor
  116. uint8_t *dest_ptr = mock_msc_scsi_config_desc;
  117. memcpy(dest_ptr, (void*)&mock_msc_config_desc, sizeof(mock_msc_config_desc));
  118. dest_ptr += USB_CONFIG_DESC_SIZE;
  119. memcpy(dest_ptr, (void*)&mock_msc_intf_desc, sizeof(mock_msc_intf_desc));
  120. dest_ptr += USB_INTF_DESC_SIZE;
  121. memcpy(dest_ptr, (void*)&mock_msc_scsi_bulk_in_ep_desc, sizeof(mock_msc_scsi_bulk_in_ep_desc));
  122. dest_ptr += USB_EP_DESC_SIZE;
  123. memcpy(dest_ptr, (void*)&mock_msc_scsi_bulk_out_ep_desc, sizeof(mock_msc_scsi_bulk_out_ep_desc));
  124. // String descriptors
  125. const char *str = MOCK_MSC_SCSI_STRING_1;
  126. uint8_t chr_count = strlen(str);
  127. mock_msc_scsi_str_desc_manu[0] = (USB_B_DESCRIPTOR_TYPE_STRING << 8 ) | (2 * chr_count + 2); // first byte is length (including header), second byte is string type
  128. for (uint8_t i = 0; i < chr_count; i++) {
  129. mock_msc_scsi_str_desc_manu[1 + i] = str[i];
  130. }
  131. str = MOCK_MSC_SCSI_STRING_2;
  132. chr_count = strlen(str);
  133. mock_msc_scsi_str_desc_prod[0] = (USB_B_DESCRIPTOR_TYPE_STRING << 8 ) | (2 * chr_count + 2); // first byte is length (including header), second byte is string type
  134. for (uint8_t i = 0; i < chr_count; i++) {
  135. mock_msc_scsi_str_desc_prod[1 + i] = str[i];
  136. }
  137. str = MOCK_MSC_SCSI_STRING_3;
  138. chr_count = strlen(str);
  139. mock_msc_scsi_str_desc_ser_num[0] = (USB_B_DESCRIPTOR_TYPE_STRING << 8 ) | (2 * chr_count + 2); // first byte is length (including header), second byte is string type
  140. for (uint8_t i = 0; i < chr_count; i++) {
  141. mock_msc_scsi_str_desc_ser_num[1 + i] = str[i];
  142. }
  143. }