How to enumerate MTP and PTP devices - delphi

This answer explains how to use WMI to find attached USB mass storage devices by drive letter but I am trying to find the names of (or UNC paths to) attached MTP or PTP devices, such as attached cameras or mobile devices which are mounted without a drive letter, so that I can crawl their directories to search for images. How can I do this?

First of all, you need to understand that having MTP device name will not allow you to crawl it directories or search for images with methods you use for simple PC filesystems. It's only simplified view from Windows Explorer, not really state of things.
I don't know how exeactly do it with Delphi, but there is a Windows Portable Devices API and it all uses COM, so I beleave there is a way to get it works even on Delphi.
Another way you may try, is using libmtp it's a plain C library, you definetely can call it's dll methods from Delphi with some helper code.
If you want just names, you can find names of attached WPD devices (Windows Portable Devices, they are using MTP and PTP protocols) using SetupDiGetDeviceRegistryProperty WinApi function.
First you need to call SetupDiGetClassDevs with GUID_DEVINTERFACE_WPD (it is defined in PortableDevice.h but you can find it easy in google
{6AC27878-A6FA-4155-BA85-F98F491D4F33} )
Then iterate on devices using SetupDiEnumDeviceInfo, get id of each device from WPD cathegory with CM_Get_Device_ID function call and pass it to SetupDiGetDeviceRegistryProperty with SPDRP_FRIENDLYNAME (or SPDRP_DEVICEDESC, maybe you should try different parameters)
There are a lot of samples of using this functions, for example this one:
SetupDiGetDeviceProperty usage example

Related

How to write a library for multiple devices with similar versions of an API

I am trying to develop a library of shared code for my company.
We are developing on a technology by SICK called AppSpace, which is designed for machine vision. AppSpace is a stand alone eco-system, beneath which there comes a variety of SICK programmable devices (e.g. programmable cameras, LiDAR sensors), and an IDE with which these can be programmed. Programs are written in Lua, using HTML/CSS for the front end.
AppSpace provides a Lua API for these devices.
In my company, a few of us write applications and it is therefore important that we create a library of shared code to avoid redundancy / rewritten code.
However, each firmware version of each device has a corresponding API version. That is to say, that on a given device the API can change between firmware versions, and also that API versions differ across devices. Two devices will have two different sets of API functions available to them. Functions they share in common may also have slightly different implementations.
I am at a loss as to how such a situation can be properly managed.
I suppose the most "manual" route would be for each device to have its own partial copy of the library, and to manually update each device's library to have the same behavior each time a change is made, ensuring that each device conforms to its API. This seems like bad practice as it is very error prone - the libraries would inevitably become out of sync.
Another option might be to have a master library, and to scrape the API documentation for each device. Then build a library manager which parses the Lua code from the library and identifies missing functions for each device. This seems completely impractical and also error prone, probably.
What would be the best way to develop and maintain a library of shared code which can be run on multiple devices, if it is even possible?
I would like to answer this and review some of the topics discussed.
First and foremost; functions that are shared in common between devices will be implemented differently by means of the compiled code on the respective device (i.e. PC, 2d camera, 3d camera, LIDAR, etc) while the functionality maintains the same between them all. This way the code can be readily ported from one device to another. That is the principle of the SICK AppEngine that is running on all SICK AppSpace devices as well as 3rd party hardware with AppEngine installed.
The APIs embedded into the devices are called a CROWN (Common Reusable Objects Wired by Name) component and can be tested against nil to determine if they are exposed APIs. Here's an example of an CROWN called 'IMAGE'. If it exists than you could run this code when it does.
if IMAGE then
--do code
end
SICK also has a AppPool that you can upload your source code to and it will test all the required CROWNs and return a list of all SICK devices that can run properly.

Reading and identifying multiple USB keyboards

I'm in charge of technology at my local camera club, a not-for-profit charity in Malvern UK. We have a database-centric competition management system which is home-brewed by me in Delphi 6 and now we wish to add a scoring system to it. This entails attaching 5 x cheap-and-standard USB numeric keypads to a PC (using a USB hub) and being able to programmatically read the keystrokes from each keyboard as they are entered by the 5 judges. Of course, they will hit their keys in a completely parallel and asynchronous way, so I need to identify which key has been struck by which judge, so as to assemble the scores (i.e. possible multiple keystrokes each) they have entered individually.
From what I can gather, Windows grabs the attention of keyboard devices and looks after the characer strings they produce, simply squirting the chars into the normal keyboard queue (and I have confirmed that by experiment!). This won't do for my needs, as I really must collect the 5 sets of (possibly multiple) key-presses and allocate the received characters as 5 separate variables for the scoring system to manipulate thereafter.
Can anyone (a) suggest a method for doing this in Delphi and (b) offer some guide to the code that might be needed? Whilst I am pretty Delphi-aware, I have no experience of accessing USB devices, or capturing their data.
Any help or guidance would be most gratefully received!
Windows provides a Raw Input API, which can be used for this purpose. In the reference at the link provided, one of the advantages is listed as:
An application can distinguish the source of the input even if it is
from the same type of device. For example, two mouse devices.
While this is more work than regular Windows input messages, it is a lot easier than writing USB device drivers.
One example of its use (while not written in Delphi) demonstrates what it can do, and provides some information on using it:
Using Raw Input from C# to handle multiple keyboards.

Possible to create a zeroconf service with Delphi XE5?

Working on an appliance and would like to support zero configuration feature. That way users can look for the device on the network and simply double click an icon to access the web interface without having to configure it or know its ip address.
Tried to use UPNPLib_TLB but functions seem to be read-only; am I right? I can create a device using CoUPnPDevice.Create but can't set a FriendlyName or a URL.
Tried to use Deltics Bonjour service but it crashes on create (ACCESS_VIOLATION). The demo code uses a custom test unit which complicates experimentation.
After much research it does not look like there is a component available for this and would appreciate some pointers. Has anyone successfully created a zeroconf broadcast either via UPnP or Bonjour with Delphi XE2/5.. I can go back to Delphi 7 if required. Target = Windows 7.
NOTE: To be clear, I can find existing devices on the network and don't want to enumerate existing devices but what I want is to broadcast my service so that my box behaves like a network printer for example. The only service I need to expose is the URL so that users can access an embedded web server.
Appreciate the help!
EDIT
With the tips provided I did some research and getting this done the RAD way is not possible.
Using MS APIs directly is time consuming and requires a level of understanding of C that I don't have. Porting the Delphi 5/Indy 7 component to XE2/5 will require a good amount of work and debugging.
I discovered UPnP developer tools from Intel now open source here: Developer Tools for UPnP. This tools makes it really simply to create a server in 10-15 lines of code. Intel provides a DLL that I can call from VS Express as follows and it works great:
device = UPnPDevice.CreateRootDevice();
device.FriendlyName = 'My name';
device.PresentationURL = 'URLToEmbeddedServer";
..
I tried to use headconv7 tool to convert the .h file Intel's UPNP.DLL to a pascal file and call the external functions within the DLL directly from Delphi but there were too many problems with the conversion.
It's too bad because the Intel library makes it really simple to create UPnP stacks and the approach would apply itself very well to a component but for now its quicker to use .NET and VS Express to get the job done.
When using UPNPLib_TLB, you are not supposed to create a UPnPDevice object directly. UPnpDevice describes a known device on the network, which is why its properties are read-only.
Read the documentation:
Control Point API
Finding Devices
You are supposed to create an instance of the UPnPDeviceFinder class instead. Its search methods will give you a UPnDevice object for each device that is found.

How to generate unique serial number of machine in Delphi?

I have question how to generate unique serial number of machine in Delphi? I tried to do this using the ID the motherboard or processor, but unfortunately it's unfortunately supported. Partition serial numbers, etc. fall off, because it is changing after the formatted. I'm looking for something that doesn't change after the formatted. Has anyone any idea?
Inside JCL library, there are several functions very usefull for this topic:
function CPUID: TCpuInfo;
function GetMacAddresses(const Machine: string; const Addresses: TStrings): Integer;
function GetVolumeSerialNumber(const Drive: string): string;
function GetBIOSName: string;
What you're after is actually some sort of "hardware fingerprint", not an "serial number". The problem with this approach is that it's not 100% reliable. Proof: Microsoft didn't manage to find a way to properly limit OEM software to any single computer, you can actually re-install a OEM license on a new computer after a while! Once you agree there can't be a perfect solution you may look at your options and try getting something that's good enough.
For my applications I'm creating a fingerprint based on info returned by GetSystemInfo, GetVolumeInformation and (for the 'C:' partition) and a selection of registry keys from HKLM\HARDWARE (lots of registry keys actually, everything but usb, keyboard and mouse stuff). I'm reading hardware information from the registry because a Windows application can't really access hardware directly (DOS-style approaches can't work), and because I don't have time to figure out ways to determine hardware-related information for many different devices.
My approach has the following disadvantages:
Uses the partition serial number, as set up by Format. An format would clearly change the fingerprint.
Uses information about the installed drivers. Updating an driver might actually change the fingerprint! Moving a card from one PCI port to an other might change the fingerprint.
None the less, even with all of this changing information taken into account, I get collisions: Something like 1/1000 computers! There are several factors at work here:
Big OEM build many computers using the same hardware. They also clone HDD's in order to speed up software installation so different PC's might get the same partition serial number.
I'm building a very short hash from all that information, short enough so people can read it to me on the phone without too many mistakes.
This system works for me, but it will not work for you if you expect to re-identify computers once they're reinstalled.
You can test GLibWMI that extract information of several components on Windows.
It's free and source included. You can find it on my Web or in Sourceforge.
alt text http://img175.imageshack.us/img175/1250/imagen344.png
Include components for BIOSInfo, DiskInfo, ProcessorInfo,...
With this three components you can obtain information like this:
alt text http://img690.imageshack.us/img690/6006/imagen349.png
You can find the BIN/EXE of GenericDemo (all components) here; You can test all information that you can retrive with this components.
I had a similar problem back in the good old DOS days. I found out that the ROM of the installed hardware ie. video card, disk controllers seriel ports etc. was accessible directly, since they are memory-mapped. This means that I was able to create a list of installed hardware, and use it to generate a "serial number", that uniquely identified each computer (until the hardware setup was changed). I'm sure something similar is possible today as well.
Check out http://duartes.org/gustavo/blog/post/motherboard-chipsets-memory-map, if you want to use this approach.
Regards
Frank
Often the MAC address of the (a) network card is used, there are several ways to query the mac address (in Delphi) but the easiest/cleanest way is probably to use the GetAdaptersInfo API.
Here is a simple solution
Generate a GUID
Save the Guid value in the registry
Use the value of the guid as the serial number
If you a worried about security use a
hash over the ( Guid + some secret data)
I tend to agree with the "it can't be done" camp. At least not 100%, but it can probably be done "good enough" to keep the average user in line.
And if it can be done then it probably has been done. Did you check Torry's Delpi300, etc (maybe even sourceforge, although you might have to translate into Delphi).
http://www.google.com.sg/search?hl=en&source=hp&q=How+to+generate+unique+serial+number+of+machine+in+Delphi actually looks promising

How to write virtual audio device driver for WinXP

How to write simpliest audio virtual device driver in WinXP? I know that one way is to write a WDM driver but I suppose it is not an easyly task. I need to implement some audio filtering for a Flash based application. Unfortunatelly it seems that it is the only way to do it - outside a Flash, by a device driver, then a Flash app can attach to my virtual device.
I was wondering if I can write a device driver using some high level API (higher that WDM), maybe UMDF as virtual usb audio device(?) or maybe only some dll which will register a virtual device. As I can see Google Talk plugin contain googleadapter.dll which provfides virtual webcams, I wonder how they wrote it.
Thanks in advance,
ternyk
For WinXP it is enough to write Installable Driver which is a simple user-mode dll. However it will not work under Vista or higher because they have different audio model.
What API? First thing i'd worry about is learning how the app(s) interface with Windows and the best way to do this is to actually learn how to code an application with audio using the same interface. So, if it uses DirectSound audio, learn how to code an application which uses DirectSound.
The reason i say this is that once you know how your code works you will also know what API need to be hooked. Then it goes from there, code the loader/dll injector so that it performs what you're after.
Finally, don't forget to use Google to do as much research on your own first:
[quote]Give a man a fish, he'll eat for a day... Teach a man to fish and he'll never go hungry again...[/quote]

Resources