From 2df324bd60d4b0bb27404fd70b1c089b467f0e09 Mon Sep 17 00:00:00 2001 From: slimih Date: Wed, 8 Apr 2026 11:44:17 +0100 Subject: [PATCH] Release v2.11.6 --- Class/CDC_RNDIS/Src/usbd_cdc_rndis.c | 9 +- Class/CustomHID/Src/usbd_customhid.c | 5 + Class/HID/Src/usbd_hid.c | 5 + Class/MSC/Inc/usbd_msc.h | 2 +- Class/MSC/Src/usbd_msc_bot.c | 2 +- Class/MSC/Src/usbd_msc_data.c | 2 +- Class/MSC/Src/usbd_msc_scsi.c | 288 ++++- Class/MTP/Src/usbd_mtp.c | 2 +- Class/MTP/Src/usbd_mtp_opt.c | 182 +-- Class/MTP/Src/usbd_mtp_storage.c | 9 + Class/Template/Src/usbd_template.c | 3 - Class/VIDEO/Src/usbd_video.c | 11 +- Core/Inc/usbd_conf_template.h | 2 - Core/Inc/usbd_core.h | 4 - Core/Inc/usbd_ctlreq.h | 3 - Core/Inc/usbd_def.h | 1 - Core/Inc/usbd_ioreq.h | 4 +- Core/Src/usbd_core.c | 9 +- Core/Src/usbd_ctlreq.c | 12 +- README.md | 50 +- Release_Notes.html | 1279 ++++++++++---------- SECURITY.md | 31 - SW_Security_Level.html | 138 +++ SW_Security_Level.md | 47 + _htmresc/Add_button.svg | 2 + _htmresc/Update.svg | 2 + _htmresc/{mini-st.css => mini-st_2020.css} | 12 +- 27 files changed, 1297 insertions(+), 819 deletions(-) delete mode 100644 SECURITY.md create mode 100644 SW_Security_Level.html create mode 100644 SW_Security_Level.md create mode 100644 _htmresc/Add_button.svg create mode 100644 _htmresc/Update.svg rename _htmresc/{mini-st.css => mini-st_2020.css} (99%) diff --git a/Class/CDC_RNDIS/Src/usbd_cdc_rndis.c b/Class/CDC_RNDIS/Src/usbd_cdc_rndis.c index 21bb18e..af56ca5 100644 --- a/Class/CDC_RNDIS/Src/usbd_cdc_rndis.c +++ b/Class/CDC_RNDIS/Src/usbd_cdc_rndis.c @@ -1414,7 +1414,7 @@ static uint8_t USBD_CDC_RNDIS_ProcessQueryMsg(USBD_HandleTypeDef *pdev, case OID_GEN_VENDOR_DESCRIPTION: QueryResponse->InfoBufLength = (strlen(USBD_CDC_RNDIS_VENDOR_DESC) + 1U); (void)USBD_memcpy(QueryResponse->InfoBuf, USBD_CDC_RNDIS_VENDOR_DESC, - strlen(USBD_CDC_RNDIS_VENDOR_DESC)); + strlen(USBD_CDC_RNDIS_VENDOR_DESC) + 1U); QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; break; @@ -1641,6 +1641,13 @@ static uint8_t USBD_CDC_RNDIS_ProcessPacketMsg(USBD_HandleTypeDef *pdev, /* Use temporary storage variables to comply with MISRA-C 2012 rule of (+) operand allowed types */ tmp1 = (uint32_t)PacketMsg; tmp2 = (uint32_t)(PacketMsg->DataOffset); + + /* Validate DataOffset and DataLength against the received MsgLength */ + if ((tmp2 + CDC_RNDIS_PCKTMSG_DATAOFFSET_OFFSET + PacketMsg->DataLength) > PacketMsg->MsgLength) + { + return (uint8_t)USBD_FAIL; + } + hcdc->RxBuffer = (uint8_t *)(tmp1 + tmp2 + CDC_RNDIS_PCKTMSG_DATAOFFSET_OFFSET); hcdc->RxLength = PacketMsg->DataLength; diff --git a/Class/CustomHID/Src/usbd_customhid.c b/Class/CustomHID/Src/usbd_customhid.c index 25768b8..7ca8464 100644 --- a/Class/CustomHID/Src/usbd_customhid.c +++ b/Class/CustomHID/Src/usbd_customhid.c @@ -691,6 +691,11 @@ static uint8_t USBD_CUSTOM_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) /* Ensure that the FIFO is empty before a new transfer, this condition could be caused by a new transfer before the end of the previous transfer */ + if (pdev->pClassDataCmsit[pdev->classId] == NULL) + { + return (uint8_t)USBD_FAIL; + } + ((USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = CUSTOM_HID_IDLE; return (uint8_t)USBD_OK; diff --git a/Class/HID/Src/usbd_hid.c b/Class/HID/Src/usbd_hid.c index f0d3b87..f226b0b 100644 --- a/Class/HID/Src/usbd_hid.c +++ b/Class/HID/Src/usbd_hid.c @@ -618,6 +618,11 @@ static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) UNUSED(epnum); /* Ensure that the FIFO is empty before a new transfer, this condition could be caused by a new transfer before the end of the previous transfer */ + if (pdev->pClassDataCmsit[pdev->classId] == NULL) + { + return (uint8_t)USBD_FAIL; + } + ((USBD_HID_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId])->state = USBD_HID_IDLE; return (uint8_t)USBD_OK; diff --git a/Class/MSC/Inc/usbd_msc.h b/Class/MSC/Inc/usbd_msc.h index c9c26cb..1f1ad10 100644 --- a/Class/MSC/Inc/usbd_msc.h +++ b/Class/MSC/Inc/usbd_msc.h @@ -110,7 +110,7 @@ typedef struct uint8_t scsi_sense_tail; uint8_t scsi_medium_state; - USBD_MSC_BOT_LUN_TypeDef scsi_blk[MSC_BOT_MAX_LUN]; + USBD_MSC_BOT_LUN_TypeDef scsi_blk[MSC_BOT_MAX_LUN + 1U]; } USBD_MSC_BOT_HandleTypeDef; /* Structure for MSC process */ diff --git a/Class/MSC/Src/usbd_msc_bot.c b/Class/MSC/Src/usbd_msc_bot.c index e1cb63c..4dab4c8 100644 --- a/Class/MSC/Src/usbd_msc_bot.c +++ b/Class/MSC/Src/usbd_msc_bot.c @@ -346,7 +346,7 @@ static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint32_t length = MIN(hmsc->cbw.dDataLength, len); - hmsc->csw.dDataResidue -= len; + hmsc->csw.dDataResidue -= length; hmsc->csw.bStatus = USBD_CSW_CMD_PASSED; hmsc->bot_state = USBD_BOT_SEND_DATA; diff --git a/Class/MSC/Src/usbd_msc_data.c b/Class/MSC/Src/usbd_msc_data.c index 333a87a..b7acde3 100644 --- a/Class/MSC/Src/usbd_msc_data.c +++ b/Class/MSC/Src/usbd_msc_data.c @@ -81,7 +81,7 @@ uint8_t MSC_Page80_Inquiry_Data[LENGTH_INQUIRY_PAGE80] = 0x00, 0x80, 0x00, - LENGTH_INQUIRY_PAGE80, + (LENGTH_INQUIRY_PAGE80 - 4U), 0x20, /* Put Product Serial number */ 0x20, 0x20, diff --git a/Class/MSC/Src/usbd_msc_scsi.c b/Class/MSC/Src/usbd_msc_scsi.c index 25f9423..3ca57a5 100644 --- a/Class/MSC/Src/usbd_msc_scsi.c +++ b/Class/MSC/Src/usbd_msc_scsi.c @@ -85,6 +85,10 @@ static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t static int8_t SCSI_RequestSense(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_AllowPreventRemovable(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ProcessModeSelect(USBD_HandleTypeDef *pdev, uint8_t lun, + uint32_t param_list_length); +static int8_t SCSI_ModeSelect6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ModeSelect10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); @@ -152,6 +156,14 @@ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd) ret = SCSI_AllowPreventRemovable(pdev, lun, cmd); break; + case SCSI_MODE_SELECT6: + ret = SCSI_ModeSelect6(pdev, lun, cmd); + break; + + case SCSI_MODE_SELECT10: + ret = SCSI_ModeSelect10(pdev, lun, cmd); + break; + case SCSI_MODE_SENSE6: ret = SCSI_ModeSense6(pdev, lun, cmd); break; @@ -202,6 +214,7 @@ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd) default: SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB); + hmsc->bot_state = USBD_BOT_NO_DATA; ret = -1; break; } @@ -328,13 +341,15 @@ static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t UNUSED(params); int8_t ret; USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; if (hmsc == NULL) { return -1; } + p_scsi_blk = &hmsc->scsi_blk[lun]; + ret = ((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->GetCapacity(lun, &p_scsi_blk->nbr, &p_scsi_blk->size); @@ -369,17 +384,19 @@ static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t */ static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { - UNUSED(params); uint32_t idx; + uint32_t alloc_len; int8_t ret; USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; if (hmsc == NULL) { return -1; } + p_scsi_blk = &hmsc->scsi_blk[lun]; + ret = ((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->GetCapacity(lun, &p_scsi_blk->nbr, &p_scsi_blk->size); @@ -389,12 +406,8 @@ static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t return -1; } - hmsc->bot_data_length = ((uint32_t)params[10] << 24) | - ((uint32_t)params[11] << 16) | - ((uint32_t)params[12] << 8) | - (uint32_t)params[13]; - - for (idx = 0U; idx < hmsc->bot_data_length; idx++) + /* READ CAPACITY(16) response is 32 bytes per SBC-3 */ + for (idx = 0U; idx < 32U; idx++) { hmsc->bot_data[idx] = 0U; } @@ -409,10 +422,13 @@ static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t hmsc->bot_data[10] = (uint8_t)(p_scsi_blk->size >> 8); hmsc->bot_data[11] = (uint8_t)(p_scsi_blk->size); - hmsc->bot_data_length = ((uint32_t)params[10] << 24) | - ((uint32_t)params[11] << 16) | - ((uint32_t)params[12] << 8) | - (uint32_t)params[13]; + /* Clamp transfer length to actual response size (32 bytes) */ + alloc_len = ((uint32_t)params[10] << 24) | + ((uint32_t)params[11] << 16) | + ((uint32_t)params[12] << 8) | + (uint32_t)params[13]; + + hmsc->bot_data_length = MIN(alloc_len, 32U); return 0; } @@ -427,8 +443,8 @@ static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t */ static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { - UNUSED(params); uint16_t blk_size; + uint16_t alloc_len; uint32_t blk_nbr; uint16_t i; int8_t ret; @@ -463,12 +479,116 @@ static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uin hmsc->bot_data[10] = (uint8_t)(blk_size >> 8); hmsc->bot_data[11] = (uint8_t)(blk_size); - hmsc->bot_data_length = 12U; + alloc_len = ((uint16_t)params[7] << 8) | (uint16_t)params[8]; + hmsc->bot_data_length = MIN(alloc_len, READ_FORMAT_CAPACITY_DATA_LEN); return 0; } +/** + * @brief SCSI_ProcessModeSelect + * Drain MODE SELECT parameter data without applying mode pages + * @param lun: Logical unit number + * @param param_list_length: Mode parameter list length from the CDB + * @retval status + */ +static int8_t SCSI_ProcessModeSelect(USBD_HandleTypeDef *pdev, uint8_t lun, + uint32_t param_list_length) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; + uint32_t packet_length; + uint32_t rx_length; + + UNUSED(param_list_length); + + if (hmsc == NULL) + { + return -1; + } + + p_scsi_blk = &hmsc->scsi_blk[lun]; + +#ifdef USE_USBD_COMPOSITE + /* Get the Endpoints addresses allocated for this class instance */ + MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId); +#endif /* USE_USBD_COMPOSITE */ + + if (hmsc->bot_state == USBD_BOT_IDLE) + { + if ((hmsc->cbw.bmFlags & 0x80U) == 0x80U) + { + hmsc->bot_state = USBD_BOT_NO_DATA; + hmsc->bot_data_length = 0U; + return 0; + } + + if (hmsc->cbw.dDataLength == 0U) + { + hmsc->bot_data_length = 0U; + return 0; + } + + p_scsi_blk->len = hmsc->cbw.dDataLength; + hmsc->bot_state = USBD_BOT_DATA_OUT; + + packet_length = MIN(p_scsi_blk->len, MSC_MEDIA_PACKET); + (void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, hmsc->bot_data, packet_length); + + return 0; + } + + rx_length = USBD_LL_GetRxDataSize(pdev, MSCOutEpAdd); + + if (rx_length >= p_scsi_blk->len) + { + hmsc->csw.dDataResidue -= p_scsi_blk->len; + p_scsi_blk->len = 0U; + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED); + } + else + { + p_scsi_blk->len -= rx_length; + hmsc->csw.dDataResidue -= rx_length; + packet_length = MIN(p_scsi_blk->len, MSC_MEDIA_PACKET); + (void)USBD_LL_PrepareReceive(pdev, MSCOutEpAdd, hmsc->bot_data, packet_length); + } + + return 0; +} + + +/** + * @brief SCSI_ModeSelect6 + * Process Mode Select6 command + * @param lun: Logical unit number + * @param params: Command parameters + * @retval status + */ +static int8_t SCSI_ModeSelect6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + return SCSI_ProcessModeSelect(pdev, lun, params[4]); +} + + +/** + * @brief SCSI_ModeSelect10 + * Process Mode Select10 command + * @param lun: Logical unit number + * @param params: Command parameters + * @retval status + */ +static int8_t SCSI_ModeSelect10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + uint32_t param_list_length; + + param_list_length = ((uint32_t)params[7] << 8) | (uint32_t)params[8]; + + return SCSI_ProcessModeSelect(pdev, lun, param_list_length); +} + + /** * @brief SCSI_ModeSense6 * Process Mode Sense6 command @@ -478,7 +598,6 @@ static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uin */ static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { - UNUSED(lun); USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint16_t len = MODE_SENSE6_LEN; @@ -494,7 +613,7 @@ static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *pa } else { - MSC_Mode_Sense10_data[2] &= ~(0x1U << 7); /* Clear the WP (write protection) bit */ + MSC_Mode_Sense6_data[2] &= ~(0x1U << 7); /* Clear the WP (write protection) bit */ } if (params[4] <= len) @@ -517,9 +636,9 @@ static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *pa */ static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { - UNUSED(lun); USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint16_t len = MODE_SENSE10_LEN; + uint16_t alloc_len; if (hmsc == NULL) { @@ -536,9 +655,12 @@ static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *p MSC_Mode_Sense10_data[3] &= ~(0x1U << 7); /* Clear the WP (write protection) bit */ } - if (params[8] <= len) + /* Allocation length is a 16-bit field: CDB bytes 7-8 */ + alloc_len = ((uint16_t)params[7] << 8) | (uint16_t)params[8]; + + if (alloc_len < len) { - len = params[8]; + len = alloc_len; } (void)SCSI_UpdateBotData(hmsc, MSC_Mode_Sense10_data, len); @@ -631,6 +753,16 @@ void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t { hmsc->scsi_sense_tail = 0U; } + + if (hmsc->scsi_sense_tail == hmsc->scsi_sense_head) + { + hmsc->scsi_sense_head++; + + if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH) + { + hmsc->scsi_sense_head = 0U; + } + } } @@ -722,13 +854,15 @@ static int8_t SCSI_AllowPreventRemovable(USBD_HandleTypeDef *pdev, uint8_t lun, static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; if (hmsc == NULL) { return -1; } + p_scsi_blk = &hmsc->scsi_blk[lun]; + if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ { /* case 10 : Ho <> Di */ @@ -788,13 +922,15 @@ static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params static int8_t SCSI_Read12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; if (hmsc == NULL) { return -1; } + p_scsi_blk = &hmsc->scsi_blk[lun]; + if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ { /* case 10 : Ho <> Di */ @@ -856,7 +992,7 @@ static int8_t SCSI_Read12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; uint32_t len; if (hmsc == NULL) @@ -864,6 +1000,8 @@ static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *param return -1; } + p_scsi_blk = &hmsc->scsi_blk[lun]; + #ifdef USE_USBD_COMPOSITE /* Get the Endpoints addresses allocated for this class instance */ MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId); @@ -884,10 +1022,18 @@ static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *param return -1; } + if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED) + { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + hmsc->bot_state = USBD_BOT_NO_DATA; + return -1; + } + /* Check whether Media is ready */ if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsReady(lun) != 0) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + hmsc->bot_state = USBD_BOT_NO_DATA; return -1; } @@ -895,6 +1041,7 @@ static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *param if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsWriteProtected(lun) != 0) { SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED); + hmsc->bot_state = USBD_BOT_NO_DATA; return -1; } @@ -946,13 +1093,16 @@ static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *param static int8_t SCSI_Write12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; uint32_t len; if (hmsc == NULL) { return -1; } + + p_scsi_blk = &hmsc->scsi_blk[lun]; + #ifdef USE_USBD_COMPOSITE /* Get the Endpoints addresses allocated for this class instance */ MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId); @@ -973,6 +1123,13 @@ static int8_t SCSI_Write12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *param return -1; } + if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED) + { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + hmsc->bot_state = USBD_BOT_NO_DATA; + return -1; + } + /* Check whether Media is ready */ if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsReady(lun) != 0) { @@ -1039,20 +1196,51 @@ static int8_t SCSI_Write12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *param static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + uint32_t blk_offset; + uint32_t blk_nbr; if (hmsc == NULL) { return -1; } + if (hmsc->cbw.dDataLength != 0U) + { + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB); + hmsc->bot_state = USBD_BOT_NO_DATA; + return -1; + } + + if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED) + { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + hmsc->bot_state = USBD_BOT_NO_DATA; + return -1; + } + + if (((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->IsReady(lun) != 0) + { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + hmsc->bot_state = USBD_BOT_NO_DATA; + return -1; + } + if ((params[1] & 0x02U) == 0x02U) { SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_FIELD_IN_COMMAND); + hmsc->bot_state = USBD_BOT_NO_DATA; return -1; /* Error, Verify Mode Not supported*/ } - if (SCSI_CheckAddressRange(pdev, lun, p_scsi_blk->addr, p_scsi_blk->len) < 0) + /* Decode LBA and verification length from current CDB */ + blk_offset = ((uint32_t)params[2] << 24) | + ((uint32_t)params[3] << 16) | + ((uint32_t)params[4] << 8) | + (uint32_t)params[5]; + + blk_nbr = ((uint32_t)params[7] << 8) | (uint32_t)params[8]; + + if (SCSI_CheckAddressRange(pdev, lun, blk_offset, blk_nbr) < 0) { return -1; /* error */ } @@ -1070,15 +1258,16 @@ static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *para static int8_t SCSI_ReportLuns(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc; + uint32_t report_idx; uint32_t lun_list_length; uint32_t total_length; + uint32_t alloc_len; uint8_t lun_idx; UNUSED(lun); - UNUSED(params); - /* Define the report LUNs buffer Each LUN entry is 8 bytes */ - static uint8_t lun_report[8U * (MSC_BOT_MAX_LUN + 1U)]; + /* Define the report LUNs buffer: 8-byte header + 8 bytes per LUN entry */ + static uint8_t lun_report[8U + (8U * (MSC_BOT_MAX_LUN + 1U))]; hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; @@ -1088,7 +1277,10 @@ static int8_t SCSI_ReportLuns(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *pa } /* Initialize the report LUNs buffer */ - (void)USBD_memset(lun_report, 0, sizeof(lun_report)); + for (report_idx = 0U; report_idx < sizeof(lun_report); report_idx++) + { + lun_report[report_idx] = 0U; + } /* Set the LUN list length in the first 4 bytes */ lun_list_length = 8U * (hmsc->max_lun + 1U); @@ -1107,6 +1299,17 @@ static int8_t SCSI_ReportLuns(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *pa /* Calculate the total length of the report LUNs buffer */ total_length = lun_list_length + 8U; + /* Clamp to allocation length from CDB bytes 6-9 */ + alloc_len = ((uint32_t)params[6] << 24) | + ((uint32_t)params[7] << 16) | + ((uint32_t)params[8] << 8) | + (uint32_t)params[9]; + + if (alloc_len < total_length) + { + total_length = alloc_len; + } + /* Update the BOT data with the report LUNs buffer */ (void)SCSI_UpdateBotData(hmsc, lun_report, (uint16_t)total_length); @@ -1126,11 +1329,17 @@ static int8_t SCSI_ReceiveDiagnosticResults(USBD_HandleTypeDef *pdev, uint8_t lu USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint16_t allocation_length; + if (hmsc == NULL) + { + return -1; + } + /* Extract the allocation length from the CDB */ allocation_length = (((uint16_t)params[3] << 8) | (uint16_t)params[4]); if (allocation_length == 0U) { + hmsc->bot_data_length = 0U; return 0; } @@ -1158,14 +1367,21 @@ static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun, uint32_t blk_offset, uint32_t blk_nbr) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; if (hmsc == NULL) { return -1; } - if ((blk_offset + blk_nbr) > p_scsi_blk->nbr) + p_scsi_blk = &hmsc->scsi_blk[lun]; + + /* Refresh cached capacity for this LUN so multi-LUN configs + with different sizes use the correct block count. */ + (void)((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->GetCapacity(lun, &p_scsi_blk->nbr, + &p_scsi_blk->size); + + if ((blk_nbr > p_scsi_blk->nbr) || (blk_offset > (p_scsi_blk->nbr - blk_nbr))) { SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); return -1; @@ -1183,7 +1399,7 @@ static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun, static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; uint32_t len; if (hmsc == NULL) @@ -1191,6 +1407,8 @@ static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun) return -1; } + p_scsi_blk = &hmsc->scsi_blk[lun]; + len = p_scsi_blk->len * p_scsi_blk->size; #ifdef USE_USBD_COMPOSITE @@ -1233,7 +1451,7 @@ static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun) static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk = &hmsc->scsi_blk[lun]; + USBD_MSC_BOT_LUN_TypeDef *p_scsi_blk; uint32_t len; if (hmsc == NULL) @@ -1241,6 +1459,8 @@ static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun) return -1; } + p_scsi_blk = &hmsc->scsi_blk[lun]; + len = p_scsi_blk->len * p_scsi_blk->size; #ifdef USE_USBD_COMPOSITE diff --git a/Class/MTP/Src/usbd_mtp.c b/Class/MTP/Src/usbd_mtp.c index 449791a..adf8e0a 100644 --- a/Class/MTP/Src/usbd_mtp.c +++ b/Class/MTP/Src/usbd_mtp.c @@ -487,7 +487,7 @@ static uint8_t USBD_MTP_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) /* prepare to receive next operation */ len = MIN(hmtp->MaxPcktLen, pdev->request.wLength); - (void)USBD_LL_PrepareReceive(pdev, MTPInEpAdd, (uint8_t *)&hmtp->rx_buff, len); + (void)USBD_LL_PrepareReceive(pdev, MTPOutEpAdd, (uint8_t *)&hmtp->rx_buff, len); break; case MTP_PHASE_IDLE : diff --git a/Class/MTP/Src/usbd_mtp_opt.c b/Class/MTP/Src/usbd_mtp_opt.c index fd2025f..df154ae 100644 --- a/Class/MTP/Src/usbd_mtp_opt.c +++ b/Class/MTP/Src/usbd_mtp_opt.c @@ -23,7 +23,7 @@ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ -static uint8_t ObjInfo_buff[255]; +static uint8_t ObjInfo_buff[576]; static uint32_t objhandle; static uint16_t obj_format; static uint32_t storage_id; @@ -385,7 +385,6 @@ void USBD_MTP_OPT_SendObject(USBD_HandleTypeDef *pdev, uint8_t *buff, uint32_t { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; USBD_MTP_ItfTypeDef *hmtpif = (USBD_MTP_ItfTypeDef *)pdev->pUserData[pdev->classId]; - static uint32_t tmp = 0U; switch (hmtp->RECEIVE_DATA_STATUS) { @@ -410,8 +409,7 @@ void USBD_MTP_OPT_SendObject(USBD_HandleTypeDef *pdev, uint8_t *buff, uint32_t { hmtp->RECEIVE_DATA_STATUS = RECEIVE_REST_OF_DATA; } - tmp = (uint32_t)buff; - hmtpif->WriteData(len, (uint8_t *)(tmp + 12U)); + hmtpif->WriteData(len, (buff + 12U)); break; case RECEIVE_REST_OF_DATA: @@ -474,21 +472,26 @@ void USBD_MTP_OPT_SendObjectInfo(USBD_HandleTypeDef *pdev, uint8_t *buff, uint3 tmp = buff; (void)USBD_memcpy(ObjInfo_buff, tmp + 12U, - (uint16_t)(hmtp->MaxPcktLen - MTP_CONT_HEADER_SIZE)); + (uint16_t)MIN(hmtp->MaxPcktLen - MTP_CONT_HEADER_SIZE, + sizeof(ObjInfo_buff))); hmtp->RECEIVE_DATA_STATUS = RECEIVE_REST_OF_DATA; break; case RECEIVE_REST_OF_DATA: - - (void)USBD_memcpy(ObjInfo_buff + len, buff, hmtp->MaxPcktLen); - + if (len < (uint32_t)sizeof(ObjInfo_buff)) + { + (void)USBD_memcpy(ObjInfo_buff + len, buff, + (uint16_t)MIN(hmtp->MaxPcktLen, + sizeof(ObjInfo_buff) - len)); + } break; case SEND_RESPONSE: (void)USBD_memcpy((uint8_t *)&ObjectInfo, ObjInfo_buff, dataLength); (void)USBD_memcpy((uint8_t *)&ObjectInfo.Filename, (ObjInfo_buff + dataLength), - ((uint32_t)(ObjectInfo.Filename_len) * 2U)); + MIN((uint32_t)(ObjectInfo.Filename_len) * 2U, + (uint32_t)(sizeof(ObjInfo_buff) - dataLength))); obj_format = ObjectInfo.ObjectFormat; @@ -560,7 +563,8 @@ static void MTP_Get_PayloadContent(USBD_HandleTypeDef *pdev) case MTP_OP_GET_OBJECT_HANDLES: (void)MTP_Get_ObjectHandle(pdev); - (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_ObjectHandle, hmtp->ResponseLength); + (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&MTP_ObjectHandle, + MIN(hmtp->ResponseLength, MTP_MEDIA_PACKET)); break; case MTP_OP_GET_OBJECT_INFO: @@ -588,7 +592,8 @@ static void MTP_Get_PayloadContent(USBD_HandleTypeDef *pdev) case MTP_OP_GET_OBJECT_PROP_VALUE: buffer = MTP_Get_ObjectPropValue(pdev); - (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)buffer, hmtp->ResponseLength); + (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)buffer, + MIN(hmtp->ResponseLength, MTP_MEDIA_PACKET)); break; case MTP_OP_GET_DEVICE_PROP_DESC: @@ -882,9 +887,12 @@ static uint8_t *MTP_Get_ObjectPropValue(USBD_HandleTypeDef *pdev) case MTP_OB_PROP_OBJ_FILE_NAME: MTP_FileName.FileName_len = hmtpif->GetObjectName_len(hmtp->OperationsContainer.Param1); hmtpif->GetObjectName(hmtp->OperationsContainer.Param1, MTP_FileName.FileName_len, (uint16_t *)buf); - (void)USBD_memcpy(MTP_FileName.FileName, (uint16_t *)buf, ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U); + (void)USBD_memcpy(MTP_FileName.FileName, (uint16_t *)buf, + MIN(((uint32_t)MTP_FileName.FileName_len * 2U) + 1U, + sizeof(MTP_FileName.FileName))); - hmtp->ResponseLength = ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U; + hmtp->ResponseLength = MIN(((uint32_t)MTP_FileName.FileName_len * 2U) + 1U, + sizeof(MTP_FileName.FileName)); break; case MTP_OB_PROP_PARENT_OBJECT : @@ -955,7 +963,9 @@ static void MTP_Get_ObjectPropList(USBD_HandleTypeDef *pdev) /* MTP_FileName.FileName_len value shall be set before USBD_MTP_FS_GetObjectName */ MTP_FileName.FileName_len = hmtpif->GetObjectName_len(hmtp->OperationsContainer.Param1); hmtpif->GetObjectName(hmtp->OperationsContainer.Param1, MTP_FileName.FileName_len, filename); - (void)USBD_memcpy(MTP_FileName.FileName, filename, ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U); + (void)USBD_memcpy(MTP_FileName.FileName, filename, + MIN(((uint32_t)MTP_FileName.FileName_len * 2U) + 1U, + sizeof(MTP_FileName.FileName))); MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)&MTP_FileName; break; @@ -979,7 +989,9 @@ static void MTP_Get_ObjectPropList(USBD_HandleTypeDef *pdev) /* MTP_FileName.FileName_len value shall be set before USBD_MTP_FS_GetObjectName */ MTP_FileName.FileName_len = hmtpif->GetObjectName_len(hmtp->OperationsContainer.Param1); hmtpif->GetObjectName(hmtp->OperationsContainer.Param1, MTP_FileName.FileName_len, filename); - (void)USBD_memcpy(MTP_FileName.FileName, filename, ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U); + (void)USBD_memcpy(MTP_FileName.FileName, filename, + MIN(((uint32_t)MTP_FileName.FileName_len * 2U) + 1U, + sizeof(MTP_FileName.FileName))); MTP_PropertiesList.MTP_Properties[i].propval = (uint8_t *)&MTP_FileName; break; @@ -1067,7 +1079,9 @@ static void MTP_Get_ObjectInfo(USBD_HandleTypeDef *pdev) /* we have to get this value before MTP_ObjectInfo.Filename */ MTP_ObjectInfo.Filename_len = hmtpif->GetObjectName_len(hmtp->OperationsContainer.Param1); hmtpif->GetObjectName(hmtp->OperationsContainer.Param1, MTP_ObjectInfo.Filename_len, filename); - (void)USBD_memcpy(MTP_ObjectInfo.Filename, filename, ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U); + (void)USBD_memcpy(MTP_ObjectInfo.Filename, filename, + MIN(((uint32_t)MTP_ObjectInfo.Filename_len * 2U) + 1U, + sizeof(MTP_ObjectInfo.Filename))); MTP_ObjectInfo.CaptureDate = 0U; MTP_ObjectInfo.ModificationDate = 0U; @@ -1096,42 +1110,55 @@ static void MTP_Get_StorageIDS(void) static uint32_t MTP_build_data_propdesc(USBD_HandleTypeDef *pdev, MTP_ObjectPropDescTypeDef def) { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; - uint8_t DefValue_size = (MTP_FileName.FileName_len * 2U) + 1U; + uint32_t DefValue_size; uint32_t dataLength = offsetof(MTP_ObjectPropDescTypeDef, DefValue); + uint32_t totalLength; - (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&def, dataLength); - + /* Determine DefValue size based on data type */ switch (def.DataType) { case MTP_DATATYPE_UINT16: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, sizeof(uint16_t)); - dataLength += sizeof(uint16_t); + DefValue_size = sizeof(uint16_t); break; case MTP_DATATYPE_UINT32: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, sizeof(uint32_t)); - dataLength += sizeof(uint32_t); + DefValue_size = sizeof(uint32_t); break; case MTP_DATATYPE_UINT64: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, sizeof(uint64_t)); - dataLength += sizeof(uint64_t); + DefValue_size = sizeof(uint64_t); break; case MTP_DATATYPE_STR: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, DefValue_size); - dataLength += DefValue_size; + DefValue_size = ((uint32_t)MTP_FileName.FileName_len * 2U) + 1U; break; case MTP_DATATYPE_UINT128: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, (sizeof(uint64_t) * 2U)); - dataLength += (sizeof(uint64_t) * 2U); + DefValue_size = (sizeof(uint64_t) * 2U); break; default: + DefValue_size = 0U; break; } + /* Check if there is enough room in GenericContainer.data */ + totalLength = dataLength + DefValue_size + sizeof(MTP_ObjectPropDesc.GroupCode) + + sizeof(MTP_ObjectPropDesc.FormFlag); + + if (totalLength > MTP_MEDIA_PACKET) + { + return 0U; + } + + (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&def, dataLength); + + if ((DefValue_size > 0U) && (def.DefValue != NULL)) + { + (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, def.DefValue, DefValue_size); + dataLength += DefValue_size; + } + (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, (const uint8_t *)&MTP_ObjectPropDesc.GroupCode, sizeof(MTP_ObjectPropDesc.GroupCode)); @@ -1156,55 +1183,56 @@ static uint32_t MTP_build_data_proplist(USBD_HandleTypeDef *pdev, { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint8_t *propval = proplist.MTP_Properties[idx].propval; - uint8_t propval_size = (propval[0] * 2U) + 1U; uint32_t dataLength; + uint32_t payloadSize; dataLength = offsetof(MTP_PropertiesTypedef, propval); + /* Determine the payload size based on data type */ + switch (proplist.MTP_Properties[idx].Datatype) + { + case MTP_DATATYPE_UINT16: + payloadSize = sizeof(uint16_t); + break; + + case MTP_DATATYPE_UINT32: + payloadSize = sizeof(uint32_t); + break; + + case MTP_DATATYPE_STR: + payloadSize = ((uint32_t)propval[0] * 2U) + 1U; + break; + + case MTP_DATATYPE_UINT64: + payloadSize = sizeof(uint64_t); + break; + + case MTP_DATATYPE_UINT128: + payloadSize = (sizeof(uint64_t) * 2U); + break; + + default: + payloadSize = 0U; + break; + } + + /* Check if there is enough room in GenericContainer.data for header + payload */ + if ((hmtp->ResponseLength + dataLength + payloadSize) > MTP_MEDIA_PACKET) + { + return hmtp->ResponseLength; + } + (void)USBD_memcpy(hmtp->GenericContainer.data + hmtp->ResponseLength, (const uint8_t *)&proplist.MTP_Properties[idx], dataLength); dataLength += hmtp->ResponseLength; - switch (proplist.MTP_Properties[idx].Datatype) + if (payloadSize > 0U) { - case MTP_DATATYPE_UINT16: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, - proplist.MTP_Properties[idx].propval, sizeof(uint16_t)); + (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, + proplist.MTP_Properties[idx].propval, payloadSize); - dataLength += sizeof(uint16_t); - break; - - case MTP_DATATYPE_UINT32: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, - proplist.MTP_Properties[idx].propval, sizeof(uint32_t)); - - dataLength += sizeof(uint32_t); - break; - - case MTP_DATATYPE_STR: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, - proplist.MTP_Properties[idx].propval, propval_size); - - dataLength += propval_size; - break; - - case MTP_DATATYPE_UINT64: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, - proplist.MTP_Properties[idx].propval, sizeof(uint64_t)); - - dataLength += sizeof(uint64_t); - break; - - case MTP_DATATYPE_UINT128: - (void)USBD_memcpy(hmtp->GenericContainer.data + dataLength, - proplist.MTP_Properties[idx].propval, (sizeof(uint64_t) * 2U)); - - dataLength += (sizeof(uint64_t) * 2U); - break; - - default: - break; + dataLength += payloadSize; } return dataLength; @@ -1220,17 +1248,25 @@ static uint32_t MTP_build_data_ObjInfo(USBD_HandleTypeDef *pdev, MTP_ObjectInfoT { USBD_MTP_HandleTypeDef *hmtp = (USBD_MTP_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId]; uint32_t ObjInfo_len = offsetof(MTP_ObjectInfoTypeDef, Filename); + uint32_t fname_size; (void)USBD_memcpy(hmtp->GenericContainer.data, (const uint8_t *)&objinfo, ObjInfo_len); - (void)USBD_memcpy(hmtp->GenericContainer.data + ObjInfo_len, - (const uint8_t *)&objinfo.Filename, objinfo.Filename_len * sizeof(uint16_t)); - ObjInfo_len = ObjInfo_len + (objinfo.Filename_len * sizeof(uint16_t)); + fname_size = MIN((uint32_t)objinfo.Filename_len * sizeof(uint16_t), + (uint32_t)(MTP_MEDIA_PACKET - ObjInfo_len)); - (void)USBD_memcpy(hmtp->GenericContainer.data + ObjInfo_len, - (const uint8_t *)&objinfo.CaptureDate, sizeof(objinfo.CaptureDate)); + (void)USBD_memcpy(hmtp->GenericContainer.data + ObjInfo_len, + (const uint8_t *)&objinfo.Filename, fname_size); - ObjInfo_len = ObjInfo_len + sizeof(objinfo.CaptureDate); + ObjInfo_len = ObjInfo_len + fname_size; + + if ((ObjInfo_len + sizeof(objinfo.CaptureDate)) <= MTP_MEDIA_PACKET) + { + (void)USBD_memcpy(hmtp->GenericContainer.data + ObjInfo_len, + (const uint8_t *)&objinfo.CaptureDate, sizeof(objinfo.CaptureDate)); + + ObjInfo_len = ObjInfo_len + sizeof(objinfo.CaptureDate); + } return ObjInfo_len; } diff --git a/Class/MTP/Src/usbd_mtp_storage.c b/Class/MTP/Src/usbd_mtp_storage.c index bd3fe08..b1f4bbf 100644 --- a/Class/MTP/Src/usbd_mtp_storage.c +++ b/Class/MTP/Src/usbd_mtp_storage.c @@ -454,6 +454,15 @@ static uint8_t USBD_MTP_STORAGE_ReceiveContainer(USBD_HandleTypeDef *pdev, return (uint8_t)USBD_FAIL; } + /* Convert byte count to uint32_t element count */ + len = len / sizeof(uint32_t); + + /* Clamp copy length to the size of OperationsContainer */ + if (len > (sizeof(MTP_OperationsTypeDef) / sizeof(uint32_t))) + { + len = (sizeof(MTP_OperationsTypeDef) / sizeof(uint32_t)); + } + for (Counter = 0U; Counter < len; Counter++) { *pdst = (hmtp->rx_buff[Counter]); diff --git a/Class/Template/Src/usbd_template.c b/Class/Template/Src/usbd_template.c index 947ae91..cd08a0a 100644 --- a/Class/Template/Src/usbd_template.c +++ b/Class/Template/Src/usbd_template.c @@ -76,13 +76,10 @@ */ - - /** @defgroup USBD_TEMPLATE_Private_FunctionPrototypes * @{ */ - static uint8_t USBD_TEMPLATE_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); static uint8_t USBD_TEMPLATE_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); static uint8_t USBD_TEMPLATE_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); diff --git a/Class/VIDEO/Src/usbd_video.c b/Class/VIDEO/Src/usbd_video.c index 6c3faba..c4aef9a 100644 --- a/Class/VIDEO/Src/usbd_video.c +++ b/Class/VIDEO/Src/usbd_video.c @@ -318,7 +318,7 @@ __ALIGN_BEGIN static uint8_t USBD_VIDEO_CfgDesc[] __ALIGN_END = UVC_IN_EP, /* bEndpointAddress */ 0x05, /* bmAttributes: ISO transfer */ LOBYTE(UVC_ISO_FS_MPS), /* wMaxPacketSize */ - LOBYTE(UVC_ISO_FS_MPS), + HIBYTE(UVC_ISO_FS_MPS), 0x01, /* bInterval: 1 frame interval */ }; @@ -691,8 +691,11 @@ static uint8_t USBD_VIDEO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) } else { - (void)USBD_memcpy((packet + ((DataOffset + 0U) * i) + 2U), - Pcktdata + ((DataOffset - 2U) * i), (RemainData - 2U)); + if (RemainData > 2U) + { + (void)USBD_memcpy((packet + ((DataOffset + 0U) * i) + 2U), + Pcktdata + ((DataOffset - 2U) * i), (RemainData - 2U)); + } RemainData = 0U; } @@ -726,7 +729,7 @@ static uint8_t USBD_VIDEO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) static uint8_t USBD_VIDEO_SOF(USBD_HandleTypeDef *pdev) { USBD_VIDEO_HandleTypeDef *hVIDEO = (USBD_VIDEO_HandleTypeDef *) pdev->pClassDataCmsit[pdev->classId]; - uint8_t payload[2] = {0x02U, 0x00U}; + static uint8_t payload[2] = {0x02U, 0x00U}; #ifdef USE_USBD_COMPOSITE /* Get the Endpoints addresses allocated for this class instance */ diff --git a/Core/Inc/usbd_conf_template.h b/Core/Inc/usbd_conf_template.h index 1ff66bc..73d4f3d 100644 --- a/Core/Inc/usbd_conf_template.h +++ b/Core/Inc/usbd_conf_template.h @@ -177,8 +177,6 @@ extern "C" { * @} */ - - /** * @} */ diff --git a/Core/Inc/usbd_core.h b/Core/Inc/usbd_core.h index 4672921..8388e32 100644 --- a/Core/Inc/usbd_core.h +++ b/Core/Inc/usbd_core.h @@ -55,13 +55,11 @@ extern "C" { * @{ */ - /** * @} */ - /** @defgroup USBD_CORE_Exported_Macros * @{ */ @@ -171,5 +169,3 @@ USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr); /** * @} */ - - diff --git a/Core/Inc/usbd_ctlreq.h b/Core/Inc/usbd_ctlreq.h index 6c45d6c..efb78a7 100644 --- a/Core/Inc/usbd_ctlreq.h +++ b/Core/Inc/usbd_ctlreq.h @@ -53,7 +53,6 @@ extern "C" { */ - /** @defgroup USBD_REQ_Exported_Macros * @{ */ @@ -97,5 +96,3 @@ void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len); /** * @} */ - - diff --git a/Core/Inc/usbd_def.h b/Core/Inc/usbd_def.h index 5b2394e..7025f69 100644 --- a/Core/Inc/usbd_def.h +++ b/Core/Inc/usbd_def.h @@ -418,7 +418,6 @@ typedef enum */ - /** @defgroup USBD_DEF_Exported_Macros * @{ */ diff --git a/Core/Inc/usbd_ioreq.h b/Core/Inc/usbd_ioreq.h index 15197b9..1a574b8 100644 --- a/Core/Inc/usbd_ioreq.h +++ b/Core/Inc/usbd_ioreq.h @@ -40,6 +40,7 @@ extern "C" { /** @defgroup USBD_IOREQ_Exported_Defines * @{ */ + /** * @} */ @@ -49,13 +50,11 @@ extern "C" { * @{ */ - /** * @} */ - /** @defgroup USBD_IOREQ_Exported_Macros * @{ */ @@ -110,4 +109,3 @@ uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr); /** * @} */ - diff --git a/Core/Src/usbd_core.c b/Core/Src/usbd_core.c index bcf571e..3b664a9 100644 --- a/Core/Src/usbd_core.c +++ b/Core/Src/usbd_core.c @@ -105,21 +105,22 @@ USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, #ifdef USE_USBD_COMPOSITE /* Parse the table of classes in use */ - for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++) + for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++) { /* Unlink previous class*/ pdev->pClass[i] = NULL; pdev->pUserData[i] = NULL; /* Set class as inactive */ - pdev->tclasslist[i].Active = 0; - pdev->NumClasses = 0; - pdev->classId = 0; + pdev->tclasslist[i].Active = 0U; + pdev->NumClasses = 0U; + pdev->classId = 0U; } #else /* Unlink previous class*/ pdev->pClass[0] = NULL; pdev->pUserData[0] = NULL; + pdev->NumClasses = 0U; #endif /* USE_USBD_COMPOSITE */ pdev->pConfDesc = NULL; diff --git a/Core/Src/usbd_ctlreq.c b/Core/Src/usbd_ctlreq.c index 814b810..584a8cb 100644 --- a/Core/Src/usbd_ctlreq.c +++ b/Core/Src/usbd_ctlreq.c @@ -361,6 +361,12 @@ USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef break; case USBD_STATE_CONFIGURED: + if ((ep_addr & 0x7FU) > 0x0FU) + { + USBD_CtlError(pdev, req); + break; + } + if ((ep_addr & 0x80U) == 0x80U) { if (pdev->ep_in[ep_addr & 0xFU].is_used == 0U) @@ -378,8 +384,8 @@ USBD_StatusTypeDef USBD_StdEPReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef } } - pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0x7FU] : \ - &pdev->ep_out[ep_addr & 0x7FU]; + pep = ((ep_addr & 0x80U) == 0x80U) ? &pdev->ep_in[ep_addr & 0xFU] : \ + &pdev->ep_out[ep_addr & 0xFU]; if ((ep_addr == 0x00U) || (ep_addr == 0x80U)) { @@ -1011,7 +1017,7 @@ void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len) unicode[idx] = USB_DESC_TYPE_STRING; idx++; - while (*pdesc != (uint8_t)'\0') + while ((*pdesc != (uint8_t)'\0') && (idx < *len)) { unicode[idx] = *pdesc; pdesc++; diff --git a/README.md b/README.md index 570f7c5..c25a919 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,36 @@ -# USB Device Middleware Library MCU Software Component +# Middleware USB Device MCU Component -![latest tag](https://img.shields.io/github/v/tag/STMicroelectronics/stm32-mw-usb-device.svg?color=brightgreen) +![latest tag](https://img.shields.io/github/v/tag/STMicroelectronics/stm32_mw_usb_device.svg?color=brightgreen) -## Overview of the STM32Cube MCU offer on GitHub +## Overview -**STM32Cube** is an original initiative by STMicroelectronics to **simplify** prototyping and development by **reducing** effort, time, and cost. It supports the entire ARM™ Cortex-based STM32 microcontroller portfolio and provides a **comprehensive** software solution including: - * The CMSIS Core and Device interfaces enabling access to processor core features and device-specific peripherals of STM32 microcontrollers. - * The STM32 HAL-LL drivers, an abstraction layer offering a set of APIs ensuring maximized portability across the STM32 portfolio. - * The BSP drivers enabling access to peripherals on the STM32 development boards, external to the microcontroller itself. - * A consistent set of middleware libraries offering standardized, high-level functionalities — such as USB, TCP/IP, file systems, and graphics. - * A full set of software projects (basic examples, applications, and demonstrations) that showcase specific functionalities or use cases, and provided with support for multiple IDEs. +**STM32Cube** is an STMicroelectronics original initiative to ease developers' life by reducing efforts, time and cost. -The **STM32Cube embedded software** is available in two flavors: - * The **MCU Firmware** _monolithic_ offer, where **all** software components (Drivers, Middleware, Projects, Utilities) are included in a **single** repository for each STM32 series. - * The **MCU Software Components** _modular_ offer, where **each** software component (mainly Drivers and Middleware) is provided in a **dedicated** repository, allowing users to **select** only the components they need. +**STM32Cube** covers the overall STM32 products portfolio. It includes a comprehensive embedded software platform delivered for each STM32 series. + * The CMSIS modules (core and device) corresponding to the ARM(tm) core implemented in this STM32 product. + * The STM32 HAL-LL drivers, an abstraction layer offering a set of APIs ensuring maximized portability across the STM32 portfolio. + * The BSP drivers of each evaluation, demonstration or nucleo board provided for this STM32 series. + * A consistent set of middleware libraries such as RTOS, USB, FatFS, graphics, touch sensing library... + * A full set of software projects (basic examples, applications, and demonstrations) for each board provided for this STM32 series. -The complete list of repositories is available [here](https://github.com/STMicroelectronics/STM32Cube_MCU_Overall_Offer/blob/master/README.md#content). +Two models of publication are proposed for the STM32Cube embedded software: + * The monolithic **MCU Package**: all STM32Cube software modules of one STM32 series are present (Drivers, Middleware, Projects, Utilities) in the repository (usual name **STM32Cubexx**, xx corresponding to the STM32 series). + * The **MCU component**: each STM32Cube software module being part of the STM32Cube MCU Package, is delivered as an individual repository, allowing the user to select and get only the required software functions. -## Repository content +## Description -This repository provides the STM32Cube **USB Device** Middleware Library, **common to every** STM32Cube MCU firmware that supports it. +This **stm32_mw_usb_device** MCU component repository is one element **common to all** STM32Cube MCU embedded software packages, providing the **USB Device MCU Middleware** part. -This represents STMicroelectronics’ offering to support the USB Device role on STM32 MCUs. It includes two main modules: - -- **Core**: provides USB Device standard peripheral control APIs implementing the USB 2.0 standard code for a USB device. These APIs are called in every USB Device application, regardless of the desired functionality. - -- **Class**: provides APIs for commonly supported USB Device classes complying with USB 2.0 standard and their respective class specifications. These APIs are called in USB Device applications based on the desired functionality. +It represents ST offer to ensure the support of USB Devices on STM32 MCUs. +It includes two main modules: + * **Core** module for the USB device standard peripheral control APIs. It includes the files ensuring USB 2.0 standard code implementation for an USB device. +These files’ APIs will be called within every USB device application regardless of the desired functionality. + * **Class** module for the commonly supported classes APIs. it includes the files including different USB device classes. All STM32 USB classes are implemented according to the USB 2.0 and every class’s specifications. These files’ APIs will be called within USB device applications according to the desired functionality. ## Release note -Details about the content of this release are available in the release note [here](https://htmlpreview.github.io/?https://github.com/STMicroelectronics/stm32-mw-usb-device/blob/master/Release_Notes.html). +Details about the content of this release are available in the release note [here](https://htmlpreview.github.io/?https://github.com/STMicroelectronics/stm32_mw_usb_device/blob/master/Release_Notes.html). -## Compatibility information +## Troubleshooting -Please refer to the **release note** in the firmware repository for the STM32 series you are using ([list](https://github.com/STMicroelectronics/STM32Cube_MCU_Overall_Offer/blob/master/README.md#stm32cube-mcu-packages)). It is **important** to use a **consistent set** of software component versions (i.e., CMSIS, HAL-LL, BSP, MW) as specified in the release note. - -## Feedback and contributions - -Please refer to the [CONTRIBUTING.md](CONTRIBUTING.md) guide. +Please refer to the [CONTRIBUTING.md](CONTRIBUTING.md) guide. \ No newline at end of file diff --git a/Release_Notes.html b/Release_Notes.html index 2364f64..622f1ec 100644 --- a/Release_Notes.html +++ b/Release_Notes.html @@ -6,19 +6,23 @@ Release Notes for STM32Cube USB Device Library - - - +code{white-space: pre-wrap;} +span.smallcaps{font-variant: small-caps;} +div.columns{display: flex; gap: min(4vw, 1.5em);} +div.column{flex: auto; overflow-x: auto;} +div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} + +ul.task-list[class]{list-style: none;} +ul.task-list li input[type="checkbox"] { +font-size: inherit; +width: 0.8em; +margin: 0 0.8em 0.2em -1.6em; +vertical-align: middle; +} +.display.math{display: block; text-align: center; margin: 0.5rem auto;} + + +
@@ -28,12 +32,11 @@ for STM32Cube USB Device Library

Copyright © 2015 STMicroelectronics

- +

Purpose

The USB device library comes on top of the STM32Cube™ USB device HAL -driver and offers all the APIs required to develop an USB device +driver and offers all the APIs required to develop a USB device application.

The main USB device library features are:

Here is the list of references to user documents:

+