Skip to content

Commit 9699ea6

Browse files
committed
stmhal: Fix USB MSC so that it unmounts correctly on Mac OS X.
Mac OS X sends a SCSI command to remove the medium when it unmounts a drive. If this command is not honoured, then OS X will automatically remount the drive, making it impossible to eject. This patch disables the USB MSC when the right SCSI command is sent.
1 parent 4d7f4eb commit 9699ea6

File tree

4 files changed

+71
-3
lines changed

4 files changed

+71
-3
lines changed

stmhal/usbd_msc_storage.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
#include "diskio.h"
3636
#include "sdcard.h"
3737

38+
// These are needed to support removal of the medium, so that the USB drive
39+
// can be unmounted, and won't be remounted automatically.
40+
static uint8_t flash_removed = 0;
41+
static uint8_t sdcard_removed = 0;
42+
3843
/******************************************************************************/
3944
// Callback functions for when the internal flash is the mass storage device
4045

@@ -83,6 +88,9 @@ int8_t FLASH_STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *blo
8388
* @retval Status
8489
*/
8590
int8_t FLASH_STORAGE_IsReady(uint8_t lun) {
91+
if (flash_removed) {
92+
return -1;
93+
}
8694
return 0;
8795
}
8896

@@ -95,6 +103,12 @@ int8_t FLASH_STORAGE_IsWriteProtected(uint8_t lun) {
95103
return 0;
96104
}
97105

106+
// Remove the lun
107+
int8_t FLASH_STORAGE_StopUnit(uint8_t lun) {
108+
flash_removed = 1;
109+
return 0;
110+
}
111+
98112
/**
99113
* @brief Read data from the medium
100114
* @param lun : logical unit number
@@ -150,6 +164,7 @@ const USBD_StorageTypeDef USBD_FLASH_STORAGE_fops = {
150164
FLASH_STORAGE_GetCapacity,
151165
FLASH_STORAGE_IsReady,
152166
FLASH_STORAGE_IsWriteProtected,
167+
FLASH_STORAGE_StopUnit,
153168
FLASH_STORAGE_Read,
154169
FLASH_STORAGE_Write,
155170
FLASH_STORAGE_GetMaxLun,
@@ -236,6 +251,9 @@ int8_t SDCARD_STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *bl
236251
* @retval Status
237252
*/
238253
int8_t SDCARD_STORAGE_IsReady(uint8_t lun) {
254+
if (sdcard_removed) {
255+
return -1;
256+
}
239257
/*
240258
#ifndef USE_STM3210C_EVAL
241259
@@ -271,6 +289,12 @@ int8_t SDCARD_STORAGE_IsWriteProtected(uint8_t lun) {
271289
return 0;
272290
}
273291

292+
// Remove the lun
293+
int8_t SDCARD_STORAGE_StopUnit(uint8_t lun) {
294+
sdcard_removed = 1;
295+
return 0;
296+
}
297+
274298
/**
275299
* @brief Read data from the medium
276300
* @param lun : logical unit number
@@ -315,6 +339,7 @@ const USBD_StorageTypeDef USBD_SDCARD_STORAGE_fops = {
315339
SDCARD_STORAGE_GetCapacity,
316340
SDCARD_STORAGE_IsReady,
317341
SDCARD_STORAGE_IsWriteProtected,
342+
SDCARD_STORAGE_StopUnit,
318343
SDCARD_STORAGE_Read,
319344
SDCARD_STORAGE_Write,
320345
SDCARD_STORAGE_GetMaxLun,

stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ typedef struct _USBD_STORAGE {
5353
int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint16_t *block_size);
5454
int8_t (* IsReady) (uint8_t lun);
5555
int8_t (* IsWriteProtected) (uint8_t lun);
56+
int8_t (* StopUnit)(uint8_t lun);
5657
int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
5758
int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
5859
int8_t (* GetMaxLun)(void);

stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,11 +583,18 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
583583

584584
/*
585585
printf("SU: %x %x %x %x\n", req->bmRequest, req->bRequest, req->wValue, req->wIndex);
586+
586587
This is what we get when MSC is IFACE=0 and CDC is IFACE=1,2:
587588
SU: 21 22 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE
588589
SU: 21 20 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_LINE_CODING
589590
SU: a1 fe 0 0 -- 0x80 | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; BOT_GET_MAX_LUN; 0; 0
590591
SU: 21 22 3 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE
592+
593+
On a Mac OS X, with MSC then CDC:
594+
SU: a1 fe 0 0
595+
SU: 21 22 2 1
596+
SU: 21 22 3 1
597+
SU: 21 20 0 1
591598
*/
592599

593600
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
@@ -723,6 +730,11 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
723730
return USBD_OK;
724731
}
725732

733+
/* unused
734+
static uint8_t EP0_TxSent(USBD_HandleTypeDef *pdev) {
735+
}
736+
*/
737+
726738
static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) {
727739
if((CDC_fops != NULL) && (CDC_ClassData.CmdOpCode != 0xFF)) {
728740
CDC_fops->Control(CDC_ClassData.CmdOpCode, (uint8_t *)CDC_ClassData.data, CDC_ClassData.CmdLength);
@@ -902,8 +914,8 @@ USBD_ClassTypeDef USBD_CDC_MSC_HID = {
902914
USBD_CDC_MSC_HID_DataIn,
903915
USBD_CDC_MSC_HID_DataOut,
904916
NULL, // SOF
905-
NULL,
906-
NULL,
917+
NULL, // IsoINIncomplete
918+
NULL, // IsoOUTIncomplete
907919
USBD_CDC_MSC_HID_GetCfgDesc,
908920
USBD_CDC_MSC_HID_GetCfgDesc,
909921
USBD_CDC_MSC_HID_GetCfgDesc,

stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, ui
8686
static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
8787
static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
8888
static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
89+
static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
8990
static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
9091
static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
9192
static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
@@ -122,6 +123,11 @@ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
122123
uint8_t lun,
123124
uint8_t *params)
124125
{
126+
/*
127+
if (params[0] != SCSI_READ10 && params[0] != SCSI_WRITE10) {
128+
printf("SCSI_ProcessCmd(lun=%d, params=%x, %x)\n", lun, params[0], params[1]);
129+
}
130+
*/
125131

126132
switch (params[0])
127133
{
@@ -137,7 +143,7 @@ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
137143
return SCSI_StartStopUnit(pdev, lun, params);
138144

139145
case SCSI_ALLOW_MEDIUM_REMOVAL:
140-
return SCSI_StartStopUnit(pdev, lun, params);
146+
return SCSI_AllowMediumRemoval(pdev, lun, params);
141147

142148
case SCSI_MODE_SENSE6:
143149
return SCSI_ModeSense6 (pdev, lun, params);
@@ -439,6 +445,30 @@ void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_
439445
* @retval status
440446
*/
441447
static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
448+
{
449+
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
450+
hmsc->bot_data_length = 0;
451+
452+
// On Mac OS X, when the device is ejected a SCSI_START_STOP_UNIT command is sent.
453+
// params[1]==0 means stop, param[1]==1 seems to be something else (happens after the
454+
// device is plugged in and mounted for some time, probably a keep alive).
455+
// If we get a stop, we must really stop the device so that the Mac does not
456+
// automatically remount it.
457+
if (params[1] == 0) {
458+
((USBD_StorageTypeDef *)pdev->pUserData)->StopUnit(lun);
459+
}
460+
461+
return 0;
462+
}
463+
464+
/**
465+
* @brief SCSI_AllowMediumRemoval
466+
* Process Allow Medium Removal command
467+
* @param lun: Logical unit number
468+
* @param params: Command parameters
469+
* @retval status
470+
*/
471+
static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
442472
{
443473
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
444474
hmsc->bot_data_length = 0;

0 commit comments

Comments
 (0)