Announcement

Collapse
No announcement yet.

SD card or USB stick

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • SD card or USB stick

    Is there a way to determine if a storage device is a USB stick/drive or an SD card? (both return USB as interface)
    I need to present a list with only SD cards in it, from which user can pick one to install on.
    (must be an SD card, and no other removable media)

    Reading the CID or CSD from the card would give info, but how to do that?
    Regards,
    Peter

  • #2
    Peter, I found a USB digger tool written by Pierre located at
    http://pages.videotron.com/lyra/Powe...ameCode=GotCha



    that might be of help as it can list out all the USB devices and their parameters
    For the codes, you need to click on option button Usb digger Windows

    Comment


    • #3
      That only gives information about the USB connection of the card reader, not the cards itself...
      Regards,
      Peter

      Comment


      • #4
        Yep, the card itself is not a USB device.

        Comment


        • #5
          I got a go, no time for now, still...
          Not precisely what you want.
          I think it could help...
          You may look at SHChangeNotifyRegister & SHCNE_DISKEVENTS and WM_DEVICECHANGE & SHCNE_DISKEVENTS

          Focus on SHCNE_MEDIAINSERTED & SHCNE_MEDIAREMOVED messages.

          Comment


          • #6
            Must it be a specific type of SD card out of the multitude of different types?
            https://gizmodo.com/giz-explains-an-...d-memo-5057252

            Are you looking for the built in SD card slot or something connected through something like this:
            Click image for larger version

Name:	80in1.jpg
Views:	241
Size:	20.0 KB
ID:	784350

            Comment


            • #7
              The application is shipped to customers, so there's no saying what they use as card reader.
              The SD cards are for configuring stand-alone hardware devices with a microcontroller.
              Configuring is done on PC for ease of use.

              I need to identify if a SD card is connected for the program to be able to write it.
              Of course I can ask 'Which drive is a SD card?" but that's not very user friendly...

              It's strange that there are no easy means to determine if or what kind of memorycards are connected...
              The oldest drives you can identify (I think there are some 20+ different floppy types), and nothing with memory cards...
              Regards,
              Peter

              Comment


              • #8
                OK, so they are more than likely to be using an external card reader plugged into a USB slot. In that case, you are "pushing s*** up hill" trying to identify what is on the other end. What if they have "your SD card", an SD card from a digital camera and a microSD card from a phone all plugged into the same USB connected card reader?

                No matter what you come up with, some user will have a configuration that you haven't thought of and unless you ask for confirmation of the destination, you are heading for trouble.

                Just get them to identify the correct drive.

                Comment


                • #9
                  Peter,
                  It's easy to generate a disk Volume name and a volume serial number.
                  Doing this, you could use GetLogicalDriveStrings to get Drives
                  and GetVolumeInformation to scan them and get Volume name, volume serial number.
                  So, your drive will be easy to find...
                  Ex: Vol = "PeterVol", S/N = "1234-ABCD"

                  Comment


                  • #10
                    The cards belong to the customer, so I don't know what they are called or what's on it regrettably...
                    I always found SD cards (technically spoken) a bit of a kludge...
                    (they have registers with all information, but those aren't accessible in an OS...)
                    Regards,
                    Peter

                    Comment


                    • #11
                      Peter
                      Try this program which can detect the Harddisk's bus type I don't have a SD to test but this will work
                      https://forum.powerbasic.com/forum/u...436#post570436



                      At the PBMain() function just iterate zPath and enumerate all the HDD from "\\.\PhysicalDrive0" to "\\.\PhysicalDrive4"
                      etc to get their drive properties. Perhaps you need add in a loop to do this

                      Code:
                          zPath = "\\.\PhysicalDrive1"

                      Comment


                      • #12
                        Modified Pierre's codes to make a loop to enumerate all the physical drives
                        Have tested this program with my sata drive and USB drives, but please test it out with your SD drive
                        which I do not have any.

                        Please also response if this is doable for SD drives?

                        Code:
                        ' Detect HDD type.bas
                        ' https://forum.powerbasic.com/forum/user-to-user-discussions/programming/48577-determine-if-fixed-drive-is-usb?p=570436#post570436
                        'Return: Drive bus type:USB, ATA, SCSI...
                        'Return: Vendor and model and, sadly, inconsistant serial number
                        
                        #COMPILE EXE
                        #DIM ALL
                        #INCLUDE "Win32Api.inc"
                        
                        
                        %StorageDeviceProperty        = 0
                        %PropertyStandardQuery        = 0
                        %IOCTL_STORAGE_QUERY_PROPERTY = &H002D1400???
                        
                        TYPE STORAGE_PROPERTY_QUERY DWORD 'Size = 12 bytes (Thank to Pépé)
                          PropertyId              AS LONG 'STORAGE_PROPERTY_ID, ID of the property being retrieved
                          QueryType               AS LONG 'STORAGE_QUERY_TYPE, Flags indicating the type of query being performed
                          AdditionalParameters(0) AS BYTE 'Variable-length array, Space for additional parameters if necessary
                        END TYPE
                        
                        TYPE STORAGE_DESCRIPTOR_HEADER DWORD 'Size = 8 bytes
                          Version AS DWORD
                          SIZE    AS DWORD
                        END TYPE
                        
                        TYPE STORAGE_DEVICE_DESCRIPTOR DWORD FILL 'Size = 40 bytes
                          Version                AS DWORD 'Sizeof(STORAGE_DEVICE_DESCRIPTOR)
                          SIZE                   AS DWORD 'Total size of the descriptor, including the space for additional data and id strings
                          DeviceType             AS BYTE  'The SCSI-2 device type
                          DeviceTypeModifier     AS BYTE  'The SCSI-2 device type modifier (if any) - this may be zero
                          RemovableMedia         AS BYTE  'Flag indicating whether the device's media (if any) is removable.  This field should be ignored for media-less devices
                          CommandQueueing        AS BYTE  'Flag indicating whether the device can support mulitple outstanding commands.  The actual synchronization in this case is the responsibility of the port driver.
                          VendorIdOffset         AS DWORD 'Byte offset to the zero-terminated ascii string containing the device's vendor id string.  For devices with no such ID this will be zero
                          ProductIdOffset        AS DWORD 'Byte offset to the zero-terminated ascii string containing the device's product id string.  For devices with no such ID this will be zero
                          ProductRevisionOffset  AS DWORD 'Byte offset to the zero-terminated ascii string containing the device's product revision string.  For devices with no such string this will be zero
                          SerialNumberOffset     AS DWORD 'Byte offset to the zero-terminated ascii string containing the device's serial number.  For devices with no serial number this will be zero
                          BusType                AS LONG  'Contains the bus type (as defined above) of the device.  It should be used to interpret the raw device properties at the end of this structure (if any)
                          RawPropertiesLength    AS DWORD 'The number of bytes of bus-specific data which have been appended to this descriptor
                          RawDeviceProperties(0) AS BYTE  'Place holder for the first byte of the bus specific property data
                          alignment__(2)         AS BYTE
                        END TYPE
                        '______________________________________________________________________________
                        
                        'FUNCTION CtlCCode(BYVAL dwDeviceType AS DWORD, BYVAL dwFunction AS DWORD, _ 'Thank to Erwin van de Wiel
                        '                  BYVAL dwMethod AS DWORD, BYVAL dwAccess AS DWORD) AS DWORD
                        ' '%IOCTL_STORAGE_QUERY_PROPERTY = &H002D1400???
                        ' 'or
                        ' 'CTL_CODE(%IOCTL_STORAGE_BASE, &H0500, %METHOD_BUFFERED, %FILE_ANY_ACCESS)
                        
                        ' SHIFT LEFT dwDeviceType, 16
                        ' SHIFT LEFT dwAccess, 14
                        ' SHIFT LEFT dwFunction, 2
                        ' FUNCTION = dwDeviceType OR dwAccess OR dwFunction OR dwMethod
                        '
                        'END FUNCTION
                        '______________________________________________________________________________
                        
                        FUNCTION PBMAIN() AS LONG
                         LOCAL pDesc       AS STORAGE_DEVICE_DESCRIPTOR POINTER
                         LOCAL pHeader     AS STORAGE_DESCRIPTOR_HEADER POINTER
                         LOCAL Query       AS STORAGE_PROPERTY_QUERY
                         LOCAL zPath       AS ASCIIZ * %MAX_PATH
                         LOCAL pZ          AS ASCIIZ POINTER
                         LOCAL OutBuf      AS STRING
                         LOCAL sBuf        AS STRING
                         LOCAL hDevice     AS DWORD
                         LOCAL dwOutBytes  AS DWORD
                         LOCAL LRes  , jdriv       AS LONG
                        
                         DIM BusType(0 TO 16) AS STRING
                         BusType(00) = "Unknown"               '&H00
                         BusType(01) = "Scsi"                  '&H01
                         BusType(02) = "Atapi"                 '&H02
                         BusType(03) = "Ata"                   '&H03
                         BusType(04) = "1394"                  '&H04
                         BusType(05) = "Ssa"                   '&H05
                         BusType(06) = "Fibre"                 '&H06
                         BusType(07) = "Usb"                   '&H07
                         BusType(08) = "RAID"                  '&H08
                         BusType(09) = "iScsi"                 '&H09
                         BusType(10) = "Sas"                   '&H0A
                         BusType(11) = "Sata"                  '&H0B
                         BusType(12) = "Sd"                    '&H0C
                         BusType(13) = "Mmc"                   '&H0D
                         BusType(14) = "Virtual"               '&H0E
                        'BusType(15) = "FileBackedVirtual"     '&H0F
                        'BusType(15) = "Max"                   '&H0F
                         BusType(15) = "Max/FileBackedVirtual" '&H0F
                         BusType(16) = "MaxReserved"           '&H7F
                        
                         'Valid format: \\.\C:
                         'Valid format: \\\?\Volume{433619ed-c6ea-11d9-a3b2-806d6172696f}
                         'Valid format: \\.\PhysicalDrive0
                        
                          '  At the PBMain()  function  just iterate zPath  and enumerate all
                          '  the HDD  from "\\.\PhysicalDrive0"  to "\\.\PhysicalDrive4"    to get their drive properties
                          '  perhaps you need add a loop to do this
                        
                        
                         ' Iterates for all the physical drives
                         FOR jdriv = 0 TO 4
                        
                             'Select drive here
                             zPath = "\\.\PhysicalDrive" + TRIM$(STR$(jdriv))
                        
                             hDevice = CreateFile(zPath, 0, %FILE_SHARE_READ OR %FILE_SHARE_WRITE, _
                                              BYVAL %NULL, %OPEN_EXISTING, 0, %NULL)
                        
                         IF hDevice <> %INVALID_HANDLE_VALUE THEN
                        
                           Query.PropertyId = %StorageDeviceProperty
                           Query.QueryType = %PropertyStandardQuery
                           OutBuf = NUL$(1024)
                        
                           LRes = DeviceIoControl(hDevice,                                 _ 'Device handle
                                                 %IOCTL_STORAGE_QUERY_PROPERTY,           _ 'Info of device property
                                                 Query, SIZEOF(STORAGE_PROPERTY_QUERY),   _ 'Input data buffer
                                                 BYVAL STRPTR(OutBuf), BYVAL LEN(OutBuf), _ 'Output data buffer
                                                 dwOutBytes,                              _ 'Out's length
                                                 BYVAL %NULL)
                           CloseHandle(hDevice)
                           IF LRes THEN
                             OutBuf = LEFT$(OutBuf, dwOutBytes)
                             pHeader = STRPTR(OutBuf)
                             IF @pHeader.Version = 40 THEN
                               pDesc = pHeader
                               sBuf = "******* Physical drive : " + STR$(jdriv) & $CRLF & $CRLF
                               sBuf = sBuf & "Storage_Query version:" & $TAB & FORMAT$(@pDesc.Version) & $CRLF
                               sBuf = sBuf & "Query size:"            & $TAB & $TAB & FORMAT$(@pDesc.Size) & $CRLF
                               sBuf = sBuf & "DataLen:"               & $TAB & $TAB & $TAB  & FORMAT$(dwOutBytes) & $CRLF
                               sBuf = sBuf & "DeviceType:"            & $TAB & $TAB & FORMAT$(@pDesc.DeviceType) & $CRLF
                               sBuf = sBuf & "DeviceTypeModifier:"    & $TAB & $TAB & FORMAT$(@pDesc.DeviceTypeModifier) & $CRLF
                               sBuf = sBuf & "RemovableMedia:"        & $TAB & $TAB & FORMAT$(@pDesc.RemovableMedia) & $CRLF
                               sBuf = sBuf & "CommandQueueing:"       & $TAB & FORMAT$(@pDesc.CommandQueueing) & $CRLF
                        
                               sBuf = sBuf & "VendorIdOffset:"        & $TAB & $TAB & FORMAT$(@pDesc.VendorIdOffset) & $CRLF
                               IF @pDesc.VendorIdOffset THEN
                                 pZ = pDesc + @pDesc.VendorIdOffset
                                 sBuf = sBuf & "VendorId:"            & $TAB & $TAB & @pZ & $CRLF
                               END IF
                        
                               sBuf = sBuf & "ProductIdOffset:"       & $TAB & $TAB & FORMAT$(@pDesc.ProductIdOffset) & $CRLF
                               IF @pDesc.ProductIdOffset THEN
                                 pZ = pDesc + @pDesc.ProductIdOffset
                                 sBuf = sBuf & "ProductId:"           & $TAB & $TAB & $TAB & @pZ & $CRLF
                               END IF
                        
                               sBuf = sBuf & "ProductRevisionOffset:" & $TAB & FORMAT$(@pDesc.ProductRevisionOffset) & $CRLF
                               IF @pDesc.ProductRevisionOffset THEN
                                 pZ = pDesc + @pDesc.ProductRevisionOffset
                                 sBuf = sBuf & "ProductRevision:"     & $TAB & $TAB & @pZ & $CRLF
                               END IF
                        
                               sBuf = sBuf & "SerialNumberOffset:"    & $TAB & $TAB & FORMAT$(@pDesc.SerialNumberOffset) & $CRLF
                        
                               sBuf = sBuf & "SerialNumber:"          & $TAB & $TAB
                               IF (@pDesc.SerialNumberOffset = &HFFFFFFFF) THEN
                                 sBuf = sBuf & "None" & $CRLF
                               ELSE
                                 IF (@pDesc.SerialNumberOffset) THEN
                                   pZ = pDesc + @pDesc.SerialNumberOffset
                                   IF LEN(@pZ) THEN
                                     sBuf = sBuf & @pZ & $CRLF
                                   ELSE
                                     sBuf = sBuf & "none" & $CRLF
                                   END IF
                                 ELSE
                                   sBuf = sBuf & "NONE" & $CRLF
                                 END IF
                               END IF
                               sBuf = sBuf & "(SerialNumber often inconsistant !)" & $CRLF
                        
                               IF @pDesc.BusType = &H7F THEN @pDesc.BusType = 16
                               IF @pDesc.BusType > 16   THEN @pDesc.BusType = 0
                               sBuf = sBuf & "BusType:"               & $TAB & $TAB & $TAB & BusType(@pDesc.BusType) & $CRLF
                               sBuf = sBuf & "RawPropertiesLength:"   & $TAB & FORMAT$(@pDesc.RawPropertiesLength) & $CRLF
                        
                             END IF
                        
                           ELSE
                             sBuf = "No go..."
                           END IF
                        
                           MessageBox(%HWND_DESKTOP, BYCOPY sBuf, "IOCTL_STORAGE_QUERY_PROPERTY", %MB_ICONINFORMATION OR %MB_OK)
                        
                            ' reinititalize the string buffer for the next physical drive
                             sBuf =""
                         END IF
                        
                         NEXT jdriv
                        
                        END FUNCTION

                        Comment


                        • #13
                          Pierre's program does look like it can do for all the known bustypes : Raid, SATA , USB , SD and more ....

                          Code:
                          BusType(00) = "Unknown"               '&H00
                           BusType(01) = "Scsi"                  '&H01
                           BusType(02) = "Atapi"                 '&H02
                           BusType(03) = "Ata"                   '&H03
                           BusType(04) = "1394"                  '&H04
                           BusType(05) = "Ssa"                   '&H05
                           BusType(06) = "Fibre"                 '&H06
                           BusType(07) = "Usb"                   '&H07
                           BusType(08) = "RAID"                  '&H08
                           BusType(09) = "iScsi"                 '&H09
                           BusType(10) = "Sas"                   '&H0A
                           BusType(11) = "Sata"                  '&H0B
                           BusType(12) = "Sd"                    '&H0C
                           BusType(13) = "Mmc"                   '&H0D
                           BusType(14) = "Virtual"               '&H0E
                          'BusType(15) = "FileBackedVirtual"     '&H0F
                          'BusType(15) = "Max"                   '&H0F
                           BusType(15) = "Max/FileBackedVirtual" '&H0F
                           BusType(16) = "MaxReserved"           '&H7F

                          Comment


                          • #14
                            But Peter is not looking for the bus type. The SD card could appear as either USB or SD. He could be dealing with for a flash drive plugged into an internal SD port (likely on a laptop) or one plugged into an external USB port via a card reader (on most desktops). In the latter case, there doesn't appear to be any way to reliably differentiate between flash/thumb drive and SD card.

                            Comment


                            • #15
                              Would the wrong SD card be just as wrong as a flash drive? How about Volume Label?
                              Dale

                              Comment


                              • #16
                                Any SD will do. Data is stored outside the partition(s) on the physical drive.
                                I only need to be sure it's an SD card. (else it won't fit in the standalone hardware device)

                                There are description strings, but I don't know how to retrieve those. Like:
                                Code:
                                Drive -> Properties -> Hardware -> Details -> Hardware ID's
                                Settings -> Device magager -> Disk drives
                                Regards,
                                Peter

                                Comment


                                • #17
                                  Well, Windows Mobile have FindFirstFlashCard() and FindNextFlashCard() for dedicated SD card slot. No good for us.

                                  I think that I read somewhere that you can send some SD-Card command when a PCMCIA bus is used, still no good for us.

                                  Seems that the reader does most, if not all, the interfacing job, so the OS work only with the given disk infos, like geometry, etc.
                                  Maybe it could be accesses via the driver, I did not find anything in this regard.
                                  Linux looks to have some little control over SD-Card.

                                  Using SetupDiEnumDeviceInfo with wpd device give a description
                                  as "Flash Reader" on one pc, "SD/MMC" on another one,
                                  so, with no standard naming, this is not not a viable way.

                                  This is a tough question..

                                  Comment


                                  • #18
                                    As I said, memorycards are a crappy invention (strange it hasn't been improved much through the years)
                                    They at least should have made the information registers available to applications.
                                    (by addressing them outside the normal memory area as normal memory cells)
                                    Regards,
                                    Peter

                                    Comment


                                    • #19
                                      All,
                                      I found this about reading the Card Identification (CID) Register...
                                      "One way to read the CID is to use a laptop with an SD card slot. Card readers in laptops are usually connected directly through the PCI bus (or IDE bus). This will not work through a USB card reader because the command to retrieve the card information is intercepted and not understood by card readers. Not all computers with built-in card slots will work, some internal card readers are connected through a USB bus."

                                      All attributes are read-only.

                                      cid..................Card Identification Register
                                      csd..................Card Specific Data Register
                                      scr..................SD Card Configuration Register (SD only)
                                      date.................Manufacturing Date (from CID Register)
                                      fwrev................Firmware/Product Revision (from CID Register) (SD and MMCv1 only)
                                      hwrev................Hardware/Product Revision (from CID Register) (SD and MMCv1 only)
                                      manfid...............Manufacturer ID (from CID Register)
                                      name.................Product Name (from CID Register)
                                      oemid................OEM/Application ID (from CID Register)
                                      prv..................Product Revision (from CID Register) (SD and MMCv4 only)
                                      serial...............Product Serial Number (from CID Register)
                                      erase_size...........Erase group size
                                      preferred_erase_size.Preferred erase size
                                      raw_rpmb_size_mult...RPMB partition size
                                      rel_sectors..........Reliable write sector count
                                      ocr..................Operation Conditions Register
                                      dsr..................Driver Stage Register
                                      cmdq_en..............Command Queue enabled: 1 => enabled, 0 => not enabled


                                      -->"I need to identify if a SD card is connected for the program to be able to write it. Of course I can ask 'Which drive is a SD card?" but that's not very user friendly..."

                                      Perhaps the User could store a text ID on the card so that your program just has to look for that. (Should be a simpler method to find the correct card.)

                                      Something like this PL001.txt

                                      You could also have the User insert the card at the appropriate moment and as Pierre suggested just respond to an arrival event.

                                      "Please insert your SD Card Now."

                                      "Ok I detected your card. Drive Z: Correct? (Y/N)" or "I am sorry. The drive you inserted does not appear to be a 16GB SD card. Please try again."

                                      NOTE:
                                      Anne's app works well to document the SD Card when it is inserted directly into the laptop:
                                      DeviceType = 0
                                      DeviceTypeModifier = 13
                                      RemovableMedia = 1
                                      VendorIdOffset = 72
                                      VendorID = Generic-

                                      ProductID = Multi-Card
                                      SerialNumber = Same every time
                                      BusType = USB

                                      That was for a SanDisk adapter card with a SanDisk Ultra Plus 16 GB microSD in it.

                                      My multi-card reader SanDisk ImageMate 12 in 1 had some issues reporting data. No updated drivers for it so I could not even see the SD card. The interfaces were there which were reported as 4 Generic Storage Devices USB Device but that was it.
                                      Last edited by Jim Fritts; 28 Aug 2019, 11:29 AM.

                                      Comment


                                      • #20
                                        One thing intrigues me, if you use this nice utility, USB Disk Ejector
                                        It seems to detect SD-Card in a viable way.
                                        The source code is available. The answer may be in this Delphi code...


                                        Click image for larger version  Name:	USB Disk Ejector.png Views:	1 Size:	46.0 KB ID:	784396
                                        Last edited by Pierre Bellisle; 28 Aug 2019, 10:53 PM.

                                        Comment

                                        Working...
                                        X