⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disk.c

📁 WIN CE 下storage 存储外设的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
UsbDiskAttach(
    HANDLE  UsbTransport,
    LPCWSTR pHardwareKey,
    DWORD   dwLun,
    UCHAR   bInterfaceSubClass
    )
{
    BOOL bRc = TRUE;
    DWORD dwErr = ERROR_SUCCESS;
    PSCSI_DEVICE pDevice = NULL;
    REG_VALUE_DESCR rdTimeouts[] = {
        MEDIA_POLL_SZ,     REG_DWORD, sizeof(DWORD),  (PUCHAR)(NULL),
        READ_SECTOR_SZ,    REG_DWORD, sizeof(DWORD),  (PUCHAR)(NULL),
        WRITE_SECTOR_SZ,   REG_DWORD, sizeof(DWORD),  (PUCHAR)(NULL),
        SCSI_COMMAND_SZ,   REG_DWORD, sizeof(DWORD),  (PUCHAR)(NULL),
        UNIT_ATTENTION_SZ, REG_DWORD, sizeof(DWORD),  (PUCHAR)(NULL),
        NULL, 0, 0, NULL
    };

    DEBUGMSG(ZONE_INIT, (TEXT("USBDISK6>DiskAttach\n")));

    if (!UsbTransport || !pHardwareKey) {
        SetLastError(ERROR_INVALID_PARAMETER);
        DEBUGMSG( ZONE_ERR, (TEXT("Invalid Parameter\n")));
        return NULL;
    }

    // try to accept all disks, probe the device, then unload if we can't controll it.
    if ( !((bInterfaceSubClass >= USBMSC_SUBCLASS_RBC) && (bInterfaceSubClass <= USBMSC_SUBCLASS_SCSI)) ) {
        DEBUGMSG( ZONE_ERR, (TEXT("Unsupported Disk bInterfaceSubClass:0x%x\n"), bInterfaceSubClass));
        return NULL;
    }

    do {
        //
        // alloc at least 1 disk device context
        //
        pDevice = (PSCSI_DEVICE)LocalAlloc( LPTR, sizeof(SCSI_DEVICE) );
        if ( !pDevice ) {
            DEBUGMSG( ZONE_ERR, (TEXT("LocalAlloc error:%d\n"), GetLastError() ));
            bRc = FALSE;
            break;
        }

        // create sterile I/O request
        pDevice->pSterileIoRequest = (PSG_REQ)LocalAlloc(
            LPTR,
            (sizeof(SG_REQ) + ((MAX_SG_BUF - 1) * sizeof(SG_BUF)))
            );
        if (NULL == pDevice->pSterileIoRequest) {
            bRc = FALSE;
            break;
        }

        pDevice->Sig = USBSCSI_SIG;

        pDevice->hUsbTransport = UsbTransport;

        pDevice->ActivePath = LocalAlloc(LPTR, wcslen(pHardwareKey)*sizeof(WCHAR)+sizeof(WCHAR));
        if (!pDevice->ActivePath) {
            DEBUGMSG( ZONE_ERR, (TEXT("LocalAlloc ERROR:%d\n"), GetLastError()));
            bRc = FALSE;
            break;
        }
        wcscpy(pDevice->ActivePath, pHardwareKey);
        DEBUGMSG(ZONE_INIT, (TEXT("ActivePath:%s\n"), pDevice->ActivePath));

        pDevice->DiskSubClass = bInterfaceSubClass;

        InitializeCriticalSection( &pDevice->Lock );

        if ( !InitializeRemoveLock( &pDevice->RemoveLock) ) {
            DEBUGMSG( ZONE_ERR, (TEXT("InitializeRemoveLock failed\n")));
            bRc = FALSE;
            break;
        }

        //
        // Grab the RemoveLock, which balances
        // the ReleaseRemoveLockAndWait on UsbDiskDetach
        //
        AcquireRemoveLock(&pDevice->RemoveLock,NULL);

        //
        // set state flags
        //
        pDevice->MediumType = SCSI_MEDIUM_UNKNOWN;
        pDevice->DeviceType = SCSI_DEVICE_UNKNOWN;
        pDevice->Flags.MediumPresent = FALSE;
        pDevice->Flags.MediumChanged = TRUE;
        pDevice->Flags.DeviceRemoved = FALSE;
        pDevice->Flags.PoweredDown   = FALSE;

        pDevice->Lun    = (UCHAR)dwLun;

        //
        // Check registry for timeout values
        //
        rdTimeouts[0].Data = (PUCHAR)(&pDevice->Timeouts.MediaPollInterval);
        rdTimeouts[1].Data = (PUCHAR)(&pDevice->Timeouts.ReadSector);
        rdTimeouts[2].Data = (PUCHAR)(&pDevice->Timeouts.WriteSector);
        rdTimeouts[3].Data = (PUCHAR)(&pDevice->Timeouts.ScsiCommandTimeout);
        rdTimeouts[4].Data = (PUCHAR)(&pDevice->Timeouts.UnitAttnRepeat);

        if ( !GetSetKeyValues(pHardwareKey,
                                  &rdTimeouts[0],
                                  GET,
                                  FALSE) ) {
            //
            // use defaults
            //
            pDevice->Timeouts.MediaPollInterval  = SCSI_MEDIA_POLL_INTERVAL;
            pDevice->Timeouts.ReadSector         = SCSI_READ_SECTOR_TIMEOUT;
            pDevice->Timeouts.WriteSector        = SCSI_WRITE_SECTOR_TIMEOUT;
            pDevice->Timeouts.ScsiCommandTimeout = SCSI_COMMAND_TIMEOUT;
            pDevice->Timeouts.UnitAttnRepeat     = UNIT_ATTENTION_REPEAT;

            // stuff defaults back in reg for tuning
            if ( !GetSetKeyValues(pHardwareKey,
                                  &rdTimeouts[0],
                                  SET,
                                  TRUE) ) {

                DEBUGMSG(ZONE_ERR, (TEXT("GetSetKeyValues ERROR:%d\n"), GetLastError() ));
            }
        }

        // let the user try a zero value, but complain in the debugger
        ASSERT(pDevice->Timeouts.MediaPollInterval);
        ASSERT(pDevice->Timeouts.ReadSector);
        ASSERT(pDevice->Timeouts.WriteSector);
        ASSERT(pDevice->Timeouts.ScsiCommandTimeout);
        ASSERT(pDevice->Timeouts.UnitAttnRepeat);


        // TODO: alloc additional disk instances and activate their interface...

        //
        // Activate the Streams Interface.
        // This call invokes our DSK_Init.
        //
        pDevice->hStreamDevice = ActivateDevice(pDevice->ActivePath,
                                                (DWORD)pDevice );


        if ( !pDevice->hStreamDevice ) {
            bRc = FALSE;
            DEBUGMSG(ZONE_ERR, (TEXT("ActivateDevice ERROR:%d\n"), GetLastError() ));
            TEST_TRAP();
            break;
        }


        //
        // Finally, if we discovered the device type and it has the removable media bit set
        // (via the SCSI_INQUIRY command) then setup the media polling thread.
        // Special case: CD-ROM must load UDFS, which has it's owm polling mechanism.
        //

        //
        // We call need to ScsiInquiry() explicit because if a unit is not ready we do
        //  not know the DeviceType.
        //
        ScsiInquiry(pDevice, pDevice->Lun);

        Sleep(500);

        if ( SCSI_DEVICE_UNKNOWN != pDevice->DeviceType && pDevice->Flags.RMB &&
             SCSI_DEVICE_CDROM != pDevice->DeviceType )
        {
            pDevice->hMediaChangedEvent = CreateEvent( NULL, AUTO_RESET_EVENT, FALSE, NULL);
            if ( !pDevice->hMediaChangedEvent ) {
                DEBUGMSG( ZONE_ERR, (TEXT("CreateEvent error:%d\n"), GetLastError() ));
                bRc = FALSE;
                break;
            }

            __try {
                pDevice->hMediaPollThread = CreateThread( NULL, 0,
                                                          MediaChangeThread,
                                                          pDevice,
                                                          0, NULL );

                if ( !pDevice->hMediaPollThread ) {
                    DEBUGMSG( ZONE_ERR, (TEXT("CreateThread error:%d\n"), GetLastError() ));
                    bRc = FALSE;
                    break;
                }
            } __except (EXCEPTION_EXECUTE_HANDLER) {
                dwErr = GetExceptionCode();
                DEBUGMSG(ZONE_ERR,(TEXT("USBDISK6::UsbDiskAttach:EXCEPTION:0x%x\n"), dwErr));
                TEST_TRAP();
            }
        }

    } while (0);

    if (!bRc) {
        //
        // If error then clean up
        //
        TEST_TRAP();

        if (pDevice) {
            ReleaseRemoveLock(&pDevice->RemoveLock,NULL);
            RemoveDeviceContext( pDevice );
        }
    }

    DEBUGMSG(ZONE_INIT, (TEXT("USBDISK6<DiskAttach:%d\n"), bRc));

    return (bRc ? pDevice : NULL);
}


//
// The USB Mass Storage Class driver is removing this disk instance.
// Delete our context & streams interface.
//
BOOL
UsbDiskDetach(
    PSCSI_DEVICE pDevice // Context
    )
{
    BOOL bRc = TRUE;
    DWORD dwWait = 0;

    DEBUGMSG(ZONE_INIT, (TEXT("USBDISK6>DiskDetach:%p\n"), pDevice));

    if ( !VALID_CONTEXT( pDevice ) ) {
        DEBUGMSG( ZONE_ERR, (TEXT("Invalid Context!\n")));
        return FALSE;
    }

    //
    // set Remove Pending state
    //
    EnterCriticalSection( &pDevice->Lock );

    pDevice->Flags.DeviceRemoved = TRUE;

    LeaveCriticalSection( &pDevice->Lock );

    //
    // wait for the polling thread to terminate
    //
    if (pDevice->hMediaChangedEvent && pDevice->hMediaPollThread) {

        SetEvent(pDevice->hMediaChangedEvent);

        WaitForSingleObject(pDevice->hMediaPollThread, INFINITE);

    } else if ( pDevice->hStreamDevice ) {
        //
        // The device has no polling thread, so dismount the disk
        //
        DismountUpperDriver(pDevice);

    } else {
        TEST_TRAP();
    }

    //
    // wait for the remove lock
    //
    DEBUGMSG(ZONE_INIT, (TEXT("ReleaseRemoveLockAndWait...\n")));
    ReleaseRemoveLockAndWait( &pDevice->RemoveLock, NULL );
    DEBUGMSG(ZONE_INIT, (TEXT("...ReleaseRemoveLockAndWait\n")));

    //
    // remove this device instance
    //
    RemoveDeviceContext( pDevice );

    DEBUGMSG(ZONE_INIT, (TEXT("USBDISK6<DiskDetach:%d\n"), bRc));

    return bRc;
}


//
// Mount the File System Driver named in the registry on top of our Device.
//
DWORD
MountUpperDriver(
    IN PSCSI_DEVICE pDevice,
    IN PPOST_INIT_BUF pInBuf
    )
{
    DWORD dwErr = ERROR_SUCCESS;
    WCHAR sFsd[MAX_DLL_LEN] = DEFAULT_FSD_SZ;
    REG_VALUE_DESCR RegVal[] = {
        FSD_SZ, REG_SZ, MAX_DLL_LEN, (PUCHAR)(sFsd),
        NULL,   0, 0, NULL
    };
    HANDLE h;

    DEBUGMSG(ZONE_TRACE, (TEXT("USBDISK6>MountUpperDriver\n")));

    if ( !VALID_CONTEXT( pDevice ) ) {
        DEBUGMSG( ZONE_ERR, (TEXT("MountUpperDriver: Invalid Context!\n")));
        return ERROR_INVALID_PARAMETER;
    }

    EnterCriticalSection(&pDevice->Lock);

    do {

        if (!pInBuf)
            h = pDevice->hStreamDevice;
        else
            h = pInBuf->p_hDevice;

        if ( !pDevice->ActivePath || !h ) {
            dwErr = ERROR_INVALID_PARAMETER;
            DEBUGMSG(ZONE_ERR, (TEXT("MountUpperDriver: ERROR_INVALID_PARAMETER\n")));
            break;
        }

        if ( !GetSetKeyValues(pDevice->ActivePath,
                              RegVal,
                              GET,
                              FALSE ) ) {
            dwErr = GetLastError();
            DEBUGMSG(ZONE_ERR, (TEXT("GetSetKeyValues ERRROR:%d\n"), dwErr));
            TEST_TRAP();
            break;
        }

        //
        // Special case: CD-ROM must load UDFS
        //
        if (pDevice->DeviceType == SCSI_DEVICE_CDROM &&
            wcscmp(sFsd, TEXT("UDFS.DLL")) != 0 )
        {
            DEBUGMSG(ZONE_WARN, (TEXT("LoadFSD:%s OVERRIDE to:%s\n"), sFsd, TEXT("UDFS.DLL")));
            memset(sFsd, 0, MAX_DLL_LEN);
            wcscpy(sFsd, TEXT("UDFS.DLL"));
        }

        //
        // This will cause the named FSD to open our device, query via Ioctl,
        // then close our device. We can not assume that the FSD is loaded until
        // we successfully complete the IOCTL_DISK_GETINFO Ioctl.
        //
        __try {
            if ( !LoadFSDEx(h, sFsd, LOADFSD_SYNCH) ) {
                dwErr = GetLastError();
                DEBUGMSG(ZONE_ERR, (TEXT("LoadFSD error:%d\n"), dwErr ));
                TEST_TRAP();
                break;
            }
        } __except (EXCEPTION_EXECUTE_HANDLER) {
            dwErr = GetExceptionCode();
            DEBUGMSG(ZONE_ERR,(TEXT("USBDISK6::MountUpperDriver:EXCEPTION:0x%x\n"), dwErr));
        }

        // pDevice->Flags.FSDMounted = TRUE; // Set in IOCTL_DISK_GETINFO

    } while(0);

    LeaveCriticalSection(&pDevice->Lock);

    DEBUGMSG(ZONE_TRACE, (TEXT("USBDISK6<MountUpperDriver:%d\n"), dwErr));

    return dwErr;
}


/* ++

This function forces the FSD to dismount by unloading the streams interface.
This invokes our DSK_Deinit.
This deletes the active key in the registry, sends a WM_DEVICECHANGE
message, and triggers a NOTIFICATION_EVENT_DEVICE_CHANGE.

-- */
DWORD
DismountUpperDriver(
    IN PSCSI_DEVICE pDevice
    )
{
    DWORD dwErr = ERROR_SUCCESS;

    DEBUGMSG(ZONE_TRACE, (TEXT("USBDISK6>DismountUpperDriver\n")));

    if ( !pDevice || !pDevice->hStreamDevice ) {

        dwErr = ERROR_INVALID_PARAMETER;

    } else {
        EnterCriticalSection(&p

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -