I have an application that detects when digital cameras are connected and
copies file from them. Currently it works with plug in play cameras that
use USB storage and I am now working on a Still Image version. I have the
Still Image handler code working and I can detect what USB port the camera
is on, but I am unable to read from that port. Basically what I want to do
is use windows.CreateFile passing the USB port in the format of //./Usbscan
and then query and read from this location. Below is a sample application
that uses CreateFile and then attempts to get pipe information from the file
handle using DeviceIOControl. The CreateFile call works without issue, but
I am getting an error, 87 - Parameter incorrect, on the DeviceIOControl
call. I have tried all combination of params I can think of to no avail.
Hopefully someone out there has done something similar... Here is the code:
unit Demo;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
{ start USBSCAN.h translation }
const
FILE_DEVICE_USB_SCAN = $8000;
IOCTL_INDEX = $0800;
METHOD_BUFFERED = 0;
FILE_ANY_ACCESS = 0;
MAX_NUM_PIPES = 8;
IOCTL_GET_PIPE_CONFIGURATION =
(FILE_DEVICE_USB_SCAN SHL 16) OR
(FILE_ANY_ACCESS SHL 14) OR
((IOCTL_INDEX + 10) SHL 2) or METHOD_BUFFERED;
//CTL_CODE(FILE_DEVICE_USB_SCAN, IOCTL_INDEX +
10,METHOD_BUFFERED,FILE_ANY_ACCESS);
type
_RAW_PIPE_TYPE = (
USBSCAN_PIPE_CONTROL,
USBSCAN_PIPE_ISOCHRONOUS,
USBSCAN_PIPE_BULK,
USBSCAN_PIPE_INTERRUPT );
_USBSCAN_PIPE_INFORMATION = record
MaximumPacketSize: Word;
EndpointAddress: UCHAR;
Interval: UCHAR;
PipeType: _RAW_PIPE_TYPE;
end {_USBSCAN_PIPE_INFORMATION};
USBSCAN_PIPE_INFORMATION = _USBSCAN_PIPE_INFORMATION;
PUSBSCAN_PIPE_INFORMATION = ^_USBSCAN_PIPE_INFORMATION;
_USBSCAN_PIPE_CONFIGURATION = record
NumberOfPipes: ULONG;
PipeInfo: Array[0..MAX_NUM_PIPES-1] of USBSCAN_PIPE_INFORMATION;
end {_USBSCAN_PIPE_CONFIGURATION};
USBSCAN_PIPE_CONFIGURATION = _USBSCAN_PIPE_CONFIGURATION;
PUSBSCAN_PIPE_CONFIGURATION = ^_USBSCAN_PIPE_CONFIGURATION;
{ end USBSCAN.h translation }
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
hres: HRESULT;
srcHandle: THandle;
usbScanPipeInfo : USBSCAN_PIPE_CONFIGURATION;
overlapped : TOverlapped;
bytesReturned: DWORD;
b : boolean;
pt : _RAW_PIPE_TYPE;
begin
memo1.lines.clear();
memo1.lines.Add(format('USBSCAN_PIPE_CONFIGURATION
size:%s',[inttostr(sizeof(USBSCAN_PIPE_CONFIGURATION))]));
memo1.lines.Add(format('USBSCAN_PIPE_INFORMATION
size:%s',[inttostr(sizeof(USBSCAN_PIPE_INFORMATION))]));
// Initialize Overlapped structure
FillChar(overlapped, SizeOf(overlapped), #0);
overlapped.hEvent := CreateEvent(nil, True, False, nil);
srcHandle := CreateFile(
PChar(edit1.text), // format = //./Usbscanx
GENERIC_READ,
FILE_SHARE_READ,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL {OR FILE_FLAG_OVERLAPPED},
0
);
memo1.lines.Add(format('CreateFile LastError
size:%s',[inttostr(getlasterror ())]));
b := DeviceIoControl(
srcHandle,
DWORD(IOCTL_GET_PIPE_CONFIGURATION),
nil,
0,
@usbScanPipeInfo,
sizeof(USBSCAN_PIPE_CONFIGURATION),
bytesReturned,
//@overlapped // if FLAG FILE_FLAG_OVERLAPPED set in CreateFile
nil
);
memo1.lines.Add(format('DeviceIoControl LastError
size:%s',[inttostr(getlasterror ())]));
CloseHandle(srcHandle);
SetEvent(overlapped.hEvent);
CloseHandle(overlapped.hEvent);
end;
end.