Discussion:
Delphi 5 and USB?
(too old to reply)
Dunny
2009-08-01 23:25:54 UTC
Permalink
Hi all -

I have an idea that I'd like to write an app that can detect a certain USB
device which presents two drives to the system. They normally show up at J:
and K:, but occaisonally they get different letters depending upon which
other devices I have attached.

Currently I'm making my app /ask/ the user for the correct drive
assignments, but I'd like to do it automatically if possible. ie, look
through the list of devices and then, when the device has been found,
determine which two drives that are attached belong to it.

I've never worked with USB before, so have no idea where to start. Can
anyone point me either to some example code or some documentation?

Cheers,

D.
Jamie
2009-08-02 01:02:18 UTC
Permalink
Post by Dunny
Hi all -
I have an idea that I'd like to write an app that can detect a certain
USB device which presents two drives to the system. They normally show
up at J: and K:, but occaisonally they get different letters depending
upon which other devices I have attached.
Currently I'm making my app /ask/ the user for the correct drive
assignments, but I'd like to do it automatically if possible. ie, look
through the list of devices and then, when the device has been found,
determine which two drives that are attached belong to it.
I've never worked with USB before, so have no idea where to start. Can
anyone point me either to some example code or some documentation?
Cheers,
D.
I think if you get the volume drive label and associated it with your
app at some point, you can then scan all the drives looking for that
volume.. Or, you can place special hidden files you can use to ID the
drives.
If you loop using "GetDriveType". You can search for removable drives,
then, look at each one you find and use the "GetVolumeInformation"

Etc.
Dunny
2009-08-02 13:42:52 UTC
Permalink
Post by Dunny
I have an idea that I'd like to write an app that can detect a certain
USB device which presents two drives to the system. They normally show up
at J: and K:, but occaisonally they get different letters depending upon
which other devices I have attached.
I think if you get the volume drive label and associated it with your app
at some point, you can then scan all the drives looking for that volume..
Or, you can place special hidden files you can use to ID the
drives.
I think that's what I might do. It will require that the user specifies the
drive letter at least once though, which is what I want to avoid.
Enumerating USB busses and the devices attached would be nice, if it's at
all possible in Delphi - I have no idea if it is, or how to do it :)

I've tried looking through the registry at
HKEY_LOCAL_MACHINE/SYSTEM/MountedDevices, but although that lists the
devices and drives, it lists them even when they're not connected - and I've
noticed that the same device is listed under three different drives due to
drive letters having changed at some point which makes it difficult to tell
which one is the one I want.
If you loop using "GetDriveType". You can search for removable drives,
then, look at each one you find and use the "GetVolumeInformation"
That's what I'm currently doing, to provide a list of devices the user can
choose from. It's the automation of that which I would like to do now.

Thanks,

D.
a***@aol.com
2009-08-02 18:34:48 UTC
Permalink
<snip>
Post by Dunny
Enumerating USB busses and the devices attached would be nice, if it's at
all possible in Delphi - I have no idea if it is, or how to do it :)
<snip>

You could ask the user to (re-)insert the USB device & catch the
DBT_DEVICEARRIVAL message & find out which drive it's connected to, In
the mesage handler (snippet from my code) . . .

begin
inherited;
if (Msg.lParam <> 0)
and (PDevBroadcastHdr(Msg.lParam)^.dbcd_DeviceType =
DBT_DEVTYP_VOLUME) then
case Msg.wParam of
DBT_DEVICEARRIVAL:
begin
if (PDevBroadcastVolume(Msg.lParam).dbcv_Flags = DBTF_NET)
then
Exit;
ADrive := GetDrive(PDevBroadcastVolume(Msg.lParam)); //
drive == 'X:'

. . . and GetDrive is . . .

function TDSSFoldersForm.GetDrive(pDBVol: PDevBroadcastVolume):
string;
type
TBit = ( Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7,
Bit8, Bit9, Bit10, Bit11, Bit12, Bit13, Bit14, Bit15,
Bit16, Bit17, Bit18, Bit19, Bit20, Bit21, Bit22, Bit23,
Bit24, Bit25, Bit26, Bit27, Bit28, Bit29, Bit30, Bit31);
TBits = set of TBit;
var
I: TBit;
Mask: DWORD;
const
DriveStr : array[TBit] of string =
('A:', 'B:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:',
'I:', 'J:', 'K:', 'L:', 'M:', 'N:', 'O:', 'P:',
'Q:', 'R:', 'S:', 'T:', 'U:', 'V:', 'W:', 'X:',
'Y:', 'Z:', ' ', ' ', ' ', ' ', ' ', ' ');
begin
Mask := pDBVol^.dbcv_UnitMask;
for I := Bit0 to Bit25 do
if I in TBits(Mask) then begin
Result := DriveStr[I];
Break;
end;
{end;}
end;

Look up the messages & records structure in MS Developers Network.

Alan Lloyd
Dunny
2009-08-02 20:31:05 UTC
Permalink
Post by a***@aol.com
<snip>
Post by Dunny
Enumerating USB busses and the devices attached would be nice, if it's at
all possible in Delphi - I have no idea if it is, or how to do it :)
<snip>
You could ask the user to (re-)insert the USB device & catch the
DBT_DEVICEARRIVAL message & find out which drive it's connected to, In
the mesage handler (snippet from my code) . . .
I could, but that would be counter-intuitive - the device could take up to 5
minutes to become ready and visible to the PC due to housekeeping routines
that occur on disconnect.

I'd much rather be able to walk through the USB devices system and find the
drives - Explorer has no problem with it, so I'd have thought it was
possible in Delphi?

Thanks for the code though - I can use some of your ideas to catch the
device if the user hasn't yet plugged it in :)

Cheers,

D.
Jamie
2009-08-02 21:04:56 UTC
Permalink
Post by Dunny
Post by a***@aol.com
<snip>
Post by Dunny
Enumerating USB busses and the devices attached would be nice, if it's at
all possible in Delphi - I have no idea if it is, or how to do it :)
<snip>
You could ask the user to (re-)insert the USB device & catch the
DBT_DEVICEARRIVAL message & find out which drive it's connected to, In
the mesage handler (snippet from my code) . . .
I could, but that would be counter-intuitive - the device could take up
to 5 minutes to become ready and visible to the PC due to housekeeping
routines that occur on disconnect.
I'd much rather be able to walk through the USB devices system and find
the drives - Explorer has no problem with it, so I'd have thought it was
possible in Delphi?
Thanks for the code though - I can use some of your ideas to catch the
device if the user hasn't yet plugged it in :)
Cheers,
D.
If you simply do a drive scan looking for any removable devices that are
not marked as read only . I think you'll be fine.

Personally, you shouldn't be looking for USB specific devices, just
removable one's. Unless there is some devious scheme on your part?
Peter
2009-08-02 21:42:38 UTC
Permalink
Post by Dunny
I have an idea that I'd like to write an app that can detect a certain USB
device which presents two drives to the system.
How exactly does one detect the right one? I mean even manually? Does
the user click open every drive and then somehow (how?) recognize that
_this_ is the drive I was looking for?
Post by Dunny
ie, look
through the list of devices and then, when the device has been found,
determine which two drives that are attached belong to it.
Belong to "it"? What exactly is that "it" in here, is it your app? How
exactly does your app mark some drives owned or "belonged" to it?

Let's say you have one SanDisk stick and you plug it to a USB port.
Windows will create two drive letters for it. The first looks like CD
and you can not read/write to it. The second is the actual USB drive
there you can read/write.
Then you plug two more SanDisk sticks in, you system gets 4 more drive
letters and then you have totally 6 of those USB related drives.

Now, what ecaxtly should your app do at this phase? Which of those
drives and by which means should your app recognize?
Post by Dunny
I'd much rather be able to walk through the USB devices system and find the
drives - Explorer has no problem with it, so I'd have thought it was
possible in Delphi?
Hmm, IE-Explorer.

We developers consider IE to be no more than an errand boy. It's one
tool among other tools that we kick and command every day. Even the
whole Windows is just a tool we bend to do things to our customers.

So what exactly do you need IE or to do to solve your problem?

I do not think we will need Explorer it in the first place. But you can
freely use Explorer to better describe the recognizing algorithm you are
after here.
Peter
Dunny
2009-08-02 22:24:56 UTC
Permalink
Post by Peter
How exactly does one detect the right one? I mean even manually? Does
the user click open every drive and then somehow (how?) recognize that
_this_ is the drive I was looking for?
It's not so much the user, but...

Here's what I want to do - I want to be able to recognise my mp3 player. It
has expandable memory, hence two drives (internal and micro-sd slot). It has
a firmware updater which detects the drives when it's plugged in - so it can
be done.

The Internal memory appears as a named device (it has registry strings with
the vendor associated with it in HKEY_LOCAL_MACHINE\SYSTEM\MOUNTEDDEVICES)
but the drive appears as a generic flash drive. Microsoft's tool, USBView,
detects the player correctly, and the micro-sd drive as a regular USB drive.

The only way to detect the micro-sd slot appears to be by finding the
player, and then searching the USB hub that it is attached to - there would
be another drive on that hub.

The problem is that I know next to f-all about USB devices, and need to know
where I go to learn.

D.
Jamie
2009-08-03 00:43:35 UTC
Permalink
Post by Dunny
Post by Peter
How exactly does one detect the right one? I mean even manually? Does
the user click open every drive and then somehow (how?) recognize that
_this_ is the drive I was looking for?
It's not so much the user, but...
Here's what I want to do - I want to be able to recognise my mp3 player.
It has expandable memory, hence two drives (internal and micro-sd slot).
It has a firmware updater which detects the drives when it's plugged in
- so it can be done.
The Internal memory appears as a named device (it has registry strings
with the vendor associated with it in
HKEY_LOCAL_MACHINE\SYSTEM\MOUNTEDDEVICES) but the drive appears as a
generic flash drive. Microsoft's tool, USBView, detects the player
correctly, and the micro-sd drive as a regular USB drive.
The only way to detect the micro-sd slot appears to be by finding the
player, and then searching the USB hub that it is attached to - there
would be another drive on that hub.
The problem is that I know next to f-all about USB devices, and need to
know where I go to learn.
D.
I think you'll find there is a file on the player/drive that is
associated with the OS. The OS simply fires off a application for that
file. Also, there could be a auto run file.
You need to look at these things.. Also, hidden files exist!..
Dunny
2009-08-03 14:48:05 UTC
Permalink
I think you'll find there is a file on the player/drive that is associated
with the OS. The OS simply fires off a application for that
file. Also, there could be a auto run file.
You need to look at these things.. Also, hidden files exist!..
That is true for the main internal drive, but the micro-sd slot can be
formatted with no files on it... So that one can't be detected that way -
believe me, I've looked into that one :)
As another poster has already suggested, why not simply enumerate the
logical drives on the system and examine the ones marked removable to see
if they are the ones you are looking for. There are a number of ways of
doing this but GetLogicalDriveStrings may be the simplest. Subsequent
GetDriveType calls will get you the types of drives.
This is what I'm currently doing, though it's to generate a list of drives
for the user to choose from. Yes, the micro-sd drive will be marked
"removable" but there's no way to tell it apart from other removable drives
on the system if the user has formatted it :(
Post by Dunny
The only way to detect the micro-sd slot appears to be by finding the
player, and then searching the USB hub that it is attached to - there would
be another drive on that hub.
If you know, and if you have decided that this is the only way that will
satisfactory solve your problem then you have two choices.
1. Start digging the internet with keywords like "delphi enumerate USB
devices" and check what kind of code snippets there are.
2. Start digging your pockets, and check if any of the ready made
USB-components will do what you need.
http://www.torry.net/authorsmore.php?id=6335
The first option you suggest has had me hunting around for the last few
days - my frustration has led me here, as people have been very helpful
previously with other problems that have crept up... The answer appears to
be the JVCL/JCL libs, but I can't find any handy documentation for them
other than MSDN, which can at best be quite cryptic.

I'll look at other components too - I was hoping to roll my own, but this
might be beyond my abilities :(

Cheers,

D.
a***@aol.com
2009-08-04 21:14:07 UTC
Permalink
On 3 Aug, 15:48, "Dunny" <***@virgin.net> wrote:
<snip>
Post by Dunny
The answer appears to
be the JVCL/JCL libs, but I can't find any handy documentation for them
other than MSDN, which can at best be quite cryptic.
Have you looked up URB (USB Request Blocks) in MSDN to send a
URB_CONTROL_DESCRIPTOR_REQUEST which looks as though it returns a
string descibing the USB device. I guess if the removable device is
NOT a USB device if fails the request. You can also get vendor &
product ids. But as you say it appears a bit cryptic.

Could you ask the user to 'initialize' the device by plugging it in,
then having received the device arrival message, write an identifying
file on the device.

Alan Lloyd
Dunny
2009-08-05 15:32:45 UTC
Permalink
Post by a***@aol.com
Have you looked up URB (USB Request Blocks) in MSDN to send a
URB_CONTROL_DESCRIPTOR_REQUEST which looks as though it returns a
string descibing the USB device. I guess if the removable device is
NOT a USB device if fails the request. You can also get vendor &
product ids. But as you say it appears a bit cryptic.
I've managed to solve the problem :)

Thanks for all the advice, folks - what I did in the end was to query, for
each drive's mointpoint, the deviceID for that drive. This returns a rather
garbled string which contains vendor and product, enough for an
identification. As it turns out, the micro-sd slot can be quite easily
distinguished from the internal memory!

Only one problem remained, and that was the difference in the strings
returned between Vista and XP - the strings issued for the drive in Vista
are only issue for the parent of that drive in XP. That caused some
head-scratching. Anyhow, I now enumerate all strings for all drives and all
their parents/grandparents, and search for the vendor/prodcut strings
therein.

Works a treat! Cheers for all the help,

D.
Nicholas Ring
2009-08-18 20:53:10 UTC
Permalink
Hi Dunny,
...
Post by Dunny
Only one problem remained, and that was the difference in the strings
returned between Vista and XP - the strings issued for the drive in
Vista are only issue for the parent of that drive in XP. That caused
some head-scratching. Anyhow, I now enumerate all strings for all
drives and all their parents/grandparents, and search for the
vendor/prodcut strings therein.
Would you consider sharing the code that does this? I am interested to
see how it is done.

Cheers,
Nick

BRoberts
2009-08-03 00:31:58 UTC
Permalink
Post by Dunny
Post by Peter
How exactly does one detect the right one? I mean even manually? Does
the user click open every drive and then somehow (how?) recognize that
_this_ is the drive I was looking for?
It's not so much the user, but...
Here's what I want to do - I want to be able to recognise my mp3 player.
It has expandable memory, hence two drives (internal and micro-sd slot).
It has a firmware updater which detects the drives when it's plugged in -
so it can be done.
The Internal memory appears as a named device (it has registry strings
with the vendor associated with it in
HKEY_LOCAL_MACHINE\SYSTEM\MOUNTEDDEVICES) but the drive appears as a
generic flash drive. Microsoft's tool, USBView, detects the player
correctly, and the micro-sd drive as a regular USB drive.
The only way to detect the micro-sd slot appears to be by finding the
player, and then searching the USB hub that it is attached to - there
would be another drive on that hub.
The problem is that I know next to f-all about USB devices, and need to
know where I go to learn.
As another poster has already suggested, why not simply enumerate the
logical drives on the system and examine the ones marked removable to see if
they are the ones you are looking for. There are a number of ways of doing
this but GetLogicalDriveStrings may be the simplest. Subsequent GetDriveType
calls will get you the types of drives.
Peter
2009-08-03 09:47:43 UTC
Permalink
Post by Dunny
but the drive appears as a generic flash drive. Microsoft's tool, USBView,
detects the player correctly, and the micro-sd drive as a regular USB drive.
The only way to detect the micro-sd slot appears to be by finding the
player, and then searching the USB hub that it is attached to - there would
be another drive on that hub.
If you know, and if you have decided that this is the only way that will
satisfactory solve your problem then you have two choices.

1. Start digging the internet with keywords like "delphi enumerate USB
devices" and check what kind of code snippets there are.

2. Start digging your pockets, and check if any of the ready made
USB-components will do what you need.
http://www.torry.net/authorsmore.php?id=6335
Peter
Peter
2009-08-03 09:48:22 UTC
Permalink
Post by Dunny
but the drive appears as a generic flash drive. Microsoft's tool, USBView,
detects the player correctly, and the micro-sd drive as a regular USB drive.
The only way to detect the micro-sd slot appears to be by finding the
player, and then searching the USB hub that it is attached to - there would
be another drive on that hub.
If you know, and if you have decided that this is the only way that will
satisfactory solve your problem then you have two choices.

1. Start digging the internet with keywords like "delphi enumerate USB
devices" and check what kind of code snippets there are.

2. Start digging your pockets, and check if any of the ready made
USB-components will do what you need.
http://www.torry.net/authorsmore.php?id=6335
Peter
Continue reading on narkive:
Loading...