Hi!

Am Freitag, den 09.08.2019, 08:08 -0400 schrieb James Richters:
> Hi Hansi,
> Thanks for the explanation.
>
> Here's the python code I’m trying to port over to FPC:
> https://github.com/wolfmanjm/kivy-smoothie-host/blob/master/modules/hb04.py
>
> it uses functions like hid.open, hid.close, hid.read, hid.write, and
> hid.send_feature_report   I'm trying to figure out how to somehow get
> similar functions to those in FPC.   Some example of how to perform
> those kinds of functions would be extremely helpful!

These hid.open, hid.close, ... functions are all methods of the object
"hid", which was previously assigned to from devices[0] (line 68),
which itself was returned from en.find(), where en is an object of
Enumeration() from the package easyhid.

To communicate with USB HID devices, please peek into the outdated
branch “master” of pas-libust (for legacy libusb-0.1) and open file
src/usb.pas. This is the old analogous to the new libusboop.pas.

It has the class TUSBPseudoHIDInterface which implements basic
communication with USB HID devices.

I've used that for a project with a barcode scanner. Please find
attached the two files snapi.pas (implementing the "standard" SNAPI for
barcode scanners, which is based on USB HID), and
barcodescannersymbolms4407.pas (implementing a few more specific
methods for a Symbol MS4407 barcode scanner). The latter file uses
several units of my project, therefore it will not compile on your
host. It is just to see how to use the SNAPI devices. I release these
files with the same license as libusboop.pas.

Please excuse that these files are still based on the outdated pas-
libusb for the old libusb-0.1. Therefore they would need translation
for the newer libusb-1.0 stuff. Unfortunately I've never head time to
transition the project. Actually you could copy the class
TUSBPseudoHIDInterface (plus the types THIDReport and TIntrReportFunc)
from usb.pas to libusboop.pas and change everything necessary.

At least one difference is that all names change from TUSB* to
TLibUsb*. I'm sure there are more, but I don't know by heart.

Please also excuse that I can’t recall why its just “PseudoHID” and not
a fully-fledged HID. Probably I didn’t implement all HID functions, or
the SNAPI HID interface just isn't registered with descriptor type $21.

This brings me to the second topic, where you got the message
  Unknown descriptor type $21 with length 9
from test2controlsync. That's a HID descriptor (see LIBUSB_DT_HID). It
is just not decoded in test2controlsync.

And finally, the third point regarding the bug with PortPath index.
I've fixed that now and pushed to Github. Thanks for pointing this out!

Thanks
  Hansi

> -----Original Message-----
> From: fpc-pascal <fpc-pascal-boun...@lists.freepascal.org> On Behalf
> Of Johann Glaser
> Sent: Friday, August 9, 2019 7:17 AM
> To: fpc-pascal@lists.freepascal.org
> Subject: Re: [fpc-pascal] USB Human Interface Devices
>
> Hi!
>
> Just a quick reply while at work, I'll reply to all EMails in the
> evening.
>
> First of all: Thanks for finding the bug with the index variable I
> vs. J. I'll fix that in the evening.
>
> Secondly: You are correct, the "EZ-USB" is a specific chip family by
> Cypress, e.g., AN2131, without Flash/ROM but with SRAM for the
> firmware. I built a few devices with that chip, therefore I also
> implemented the Pascal "driver" to download the firmware into the
> "naked" device. There are also many (old) devices on the marked which
> use that chip, e.g., the Keil uLink (1st generation).
>
> To understand how USB actually works (endpoints, in and out
> transfers, control/bulk/interrupt/isochronous transfers, ...), I have
> learned a lot from the Technical Reference Manual (TRM) of the EZ-
> USB. Just search for it, there are plenty of sources. Chapter 1 is
> the interesting one. If you directly search at the Cypress page, they
> will redirect you to the successor product FX2, but its chapter 1 is
> nearly identical to that of EZ-USB.
>
> The EZ-USB firmware download is performed with control transfers to
> EP0. So you can find examples for control transfers in ezusb.pas.
>
> You can find example code for bulk and interrupt endpoints e.g., in
> https://github.com/hansiglaser/pas-gpib/blob/master/usb/usbtmc.pas.
>
> I can provide more examples in the evening.
>
> Bye
>   Hansi
>
> > Gesendet: Freitag, 09. August 2019 um 12:09 Uhr
> > Von: "James Richters" <ja...@productionautomation.net>
> > An: "'FPC-Pascal users discussions'" <
> > fpc-pascal@lists.freepascal.org>
> > Betreff: Re: [fpc-pascal] USB Human Interface Devices
> >
> > Maybe I am going down the wrong path trying to get
> > test_arduino_with_bmp280.pas to work with my device...  I think I
> > am confusing easyusb with easyhid which is what is used to
> > communicate with the device in the python code I am trying to
> > use.  It looks like easyusb is to send firmware to a specific usb
> > device that has no rom in it... and that's not exactly what I'm
> > trying to do...
> >
> > I'm trying to figure out how to open the device and read data and
> > write data to this device.  Is there an example of how to do that
> > with pas-libusb?
> >
> > Sorry I am so confused by all this.  I feel like I'm almost to
> > where I will understand things again but I'm just missing
> > something.
> >
> > James
> > _______________________________________________
> > fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
> > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
> >
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Unit BarcodeScannerSymbolMS4407;

{$mode objfpc}{$H+}
{$INTERFACES CORBA}

Interface

Uses
  Classes, SysUtils,List,
  Callback,DevOperator,CharBuf,BarcodeScanner,USB,SNAPI;


Type
  { CSNAPIBarcodeScanner }

  CSNAPIBarcodeScanner = class(TSNAPIDevice,IBarcodeScanner,IPollable)
  private
    { callbacks }
    BarcodeCallback   : CCallback;
    { local variables }
    Active            : Boolean;
    { callback variable for my installed cbRecv }
    RecvCallback      : CCallback;
    { callbacks }
    Procedure   NotifyCallback(aBarcode:String);
  public
    Constructor Create(idVendor,idProduct:LongInt;AConfig,AInterface,AAltInterface:LongInt); overload;
    Destructor  Destroy; override;
    (** Interface IBarcodeScanner ********************************************)
    { callback admin methods }
    Function    AddBarcodeCallback(aCallBack:cbCallback;aData:Pointer) : CCallback;
    Function    DelBarcodeCallback(aCallback:CCallback):LongInt;
    { top level methods }
    Procedure Activate;      virtual;
    Procedure Deactivate;    virtual;
    Procedure NotifySuccess; virtual;
    Procedure NotifyProblem; virtual;
    Procedure Operate;
  End;

  { CBarcodeScannerSymbolMS4407 }

  CBarcodeScannerSymbolMS4407 = class(CSNAPIBarcodeScanner)
  public
    Constructor Create;
    Destructor  Destroy; override;
  End;

Implementation

Constructor CSNAPIBarcodeScanner.Create(idVendor,idProduct:LongInt;AConfig,AInterface,AAltInterface:LongInt);
Begin
  inherited Create(idVendor,idProduct,AConfig,AInterface,AAltInterface);
  { set local variables }
  Active := false;
  OnBarcode := @NotifyCallback;
  TheDevOperator.Add(Self);
End;

Destructor CSNAPIBarcodeScanner.Destroy;
Begin
  try
    TheDevOperator.Del(Self);
  Except
    On E : Exception do
      ;  // ignore, this most proably happend because we are called due to an exception in the constructor
  End;
  Deactivate;
  Inherited Destroy;
End;

Procedure CSNAPIBarcodeScanner.Activate;
Begin
  Active := True;
  { switch on barcode scanner's read function }
  ScanEnable;
  PullTrigger;
End;

Procedure CSNAPIBarcodeScanner.Deactivate;
Begin
  if Active = False then Exit;
  Active := False;
  { switch off barcode scanner's read function }
  ReleaseTrigger;
  ScanDisable;
End;

Procedure CSNAPIBarcodeScanner.NotifySuccess;
Begin
  Beep(bcOneShortHi);
End;

Procedure CSNAPIBarcodeScanner.NotifyProblem;
Begin
  Beep(bcFastHiLoHiLo);
End;

Procedure CSNAPIBarcodeScanner.Operate;
Begin
  Listen;
End;

Procedure CSNAPIBarcodeScanner.NotifyCallback(aBarcode:String);
Var BarcodeEvent : TBarcodeEvent;
Begin
  BarcodeEvent.Barcode := aBarcode;
  if Assigned(BarcodeCallback) then
    BarcodeCallback.Execute(@BarcodeEvent);
End;

Function  CSNAPIBarcodeScanner.AddBarcodeCallback(aCallBack:cbCallback;aData:Pointer) : CCallback;
Begin
  Result := CCallback.Create(@BarcodeCallback,aCallback,aData);
End;
Function CSNAPIBarcodeScanner.DelBarcodeCallback(aCallback:CCallback):LongInt;
Begin
  { pricipially we only need to destroy the aCallback class instance }
  { But for security we search it in our UARTRecvCallbacks that we   }
  { don't delete foreigh callbacks. }
  Result := 0;
  if aCallback.InList(BarcodeCallback) then
    Begin
      aCallback.Free;
      Exit;
    End;
  raise Exception.Create('INTERNAL ERROR: CSNAPIBarcodeScanner.DelBarcodeCallback was called with a wrong callback');
  Result := -1;  { not necessary, because we will not reach this point }
End;

Const USBVend : LongInt = $05E0;
      USBProd : LongInt = $1900;

{ CBarcodeScannerSymbolMS4407 }

Constructor CBarcodeScannerSymbolMS4407.Create;
Begin
  try
    inherited Create(USBVend,USBProd,1,0,0);
  Except
    on E : Exception do
      Begin
        WriteLn('Couldn''t instantiate a Symbol MS4407 Barcode Scanner.');
        raise;
      End;
  End;
End;

Destructor CBarcodeScannerSymbolMS4407.Destroy;
Begin
  Inherited Destroy;
End;

End.

Unit SNAPI;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils, TypInfo,
  LibUSB, USB;

{$PACKENUM 1}
Type
  TSNAPIBeepCode = (bcOneShortHi,bcTwoShortHi,bcThreeShortHi,bcFourShortHi,bcFiveShortHi,
                    bcOneShortLo,bcTwoShortLo,bcThreeShortLo,bcFourShortLo,bcFiveShortLo,
                    bcOneLongHi,bcTwoLongHi,bcThreeLongHi,bcFourLongHi,bcFiveLongHi,
                    bcOneLongLo,bcTwoLongLo,bcThreeLongLo,bcFourLongLo,bcFiveLongLo,
                    bcFastHiLoHiLo,bcSlowHiLoHiLo,bcHiLo,bcLoHi,bcHiLoHi,bcLoHiLo);

  TSNAPICodeType = (ctCode39=1,ctCodabar,ctCode128,ctDiscrete2of5,ctIATA,ctInterleaved2of5,
                    ctCode93,ctUPCA,ctUPCE0,ctEAN8,ctEAN13,ctCode11,ctCode49,ctMSI,ctEAN128,
                    ctUPCE1,ctPDF417,ctCode16K,ctCode39FullASCII,ctUPCD,ctCode39Trioptic,
                    ctBookland,ctCouponCode,ctNW7,ctISBT128,ctMicroPDF,ctDataMatrix,ctQRCode,
                    ctMicroPDFCCA,ctPostNetUS,ctPlanenCode,ctCod32,ctISBT128Con,ctJapanPostal,
                    ctAustralianPostal,ctDutchPostal,ctMaxiCode,ctCanadianPostal,ctUKPostal,
                    ctMacroPDF,
                    ctRSS14=48,ctRSSLimited,ctRSSExpanded,
                    ctScanlet=55,
                    ctUPCA2=72,ctUPCE02,ctEAN82,ctEAN132,
                    ctUPCE12=80,ctCCAEAN128,ctCCAEAN13,ctCCAEAN8,ctCCARSSExpanded,
                    ctCCARSSLimited,ctCCARSS14,ctCCAUPCA,ctCCAUPCE,ctCCCEAN128,ctTLC39,
                    ctCCBEAN128=97,ctCCBEAN13,ctCCBEAN8,ctCCBRSSExpanded,ctCCBRSSLimited,
                    ctCCBRSS14,ctCCBUPCA,ctCCBUPCE,ctSignatureCapture,
                    ctMatris2of5=113,ctChinese2of5,
                    ctUPCA5=136,ctUPCE05,ctEAN85,ctEAN135,ctUPCE15=144,ctMacroMicroPDF=154);

  TSNAPIError = (seOk=0,seNoACK=-1,seCommandNotSupported=-2);

Type
  PReportStatus = ^TReportStatus;
  TReportStatus = record  // total size: 4 Bytes
    ReportID   : Byte;
    PrevReport : Byte;
    Status     : Byte;
    Unknown    : Byte;
  End;
  PReportBarcode = ^TReportBarcode;
  TReportBarcode = packed record  // total size: 32 Bytes
    ReportID   : Byte;
    Packets    : Byte;  // total number of packets
    PacketNum  : Byte;  // number of this packet
    Length     : Byte;  // length of this packet
    CodeType   : TSNAPICodeType;
    Unknown3   : Byte;
    Barcode    : Array[0..25] of Byte;
  End;

  ESNAPIError               = class(Exception);
  ESNAPINoACK               = class(ESNAPIError);
  ESNAPICommandNotSupported = class(ESNAPIError);
  ESNAPIUSBError            = class(ESNAPIError);

  { TSNAPIDevice }

  TOnBarcodeFunc = Procedure(Barcode:String) of object;

  TSNAPIDevice = class(TUSBDevice)
  private
    FSNAPICommandInterface : TUSBPseudoHIDInterface;
    FFragmentedBarcode : Array of TReportBarcode;
    FOnBarcode : TOnBarcodeFunc;
    Procedure SendACK(ReportID: Byte);
    Function WaitForACK(ReportID:Byte): TSNAPIError;
    Procedure SetOutputReport(ReportID:Byte;Data:Byte);
    Function IntrReport(Report:PHIDReport) : Boolean;
  public
    Constructor Create(idVendor,idProduct:LongInt;AConfig,AInterface,AAltInterface:LongInt); overload;
    Destructor Destroy; override;
    Procedure AbortMacroPdf;
    Procedure AimOff;
    Procedure AimOn;
    //Procedure Connect;
    //Procedure Disconnect;
    Procedure EnterLowPwrMode;
    Procedure FlushMacroPdf;
    Function  GetSerialNumber : String;
    //Procedure Init;
    Procedure LedOff(LEDs:Byte);
    Procedure LedOn(LEDs:Byte);
    Procedure PullTrigger;
    Procedure ReleaseTrigger;
    //Procedure RequestAllParameters;
    Procedure RequestParameters(Parameters : Array of Word);
    Procedure RequestScannerCapabilities;
    //Procedure ReturnDLLVersion;
    Procedure ScanDisable;
    Procedure ScanEnable;
    //Procedure SetCapabilitiesBuffer;  // replaced by OnXyz
    //Procedure SetDecodeBuffer;  // replaced by OnXyz
    //Procedure SetImageBuffer;
    Procedure SetParamPersistance(Persistent:Boolean);
    //Procedure SetParameterBuffer;
    Procedure SetParameterDefaults;
    Procedure SetParameters(Parameters : Array of Word);  // number/value alternating, maximum 7x
    //Procedure SetVersionBuffer; // beongs to TransmitVersion
    //Procedure SetVideoBuffer;
    Procedure SnapShot;        // will call OnSnapshot when an image is there
    Procedure TransmitVersion;
    Procedure TransmitVideo;

    Procedure Beep(Code:TSNAPIBeepCode);
    Procedure Listen;
    property OnBarcode : TOnBarcodeFunc read FOnBarcode write FOnBarcode;
  End;

Const
  SNAPI_PARAM_IMAGE_FORMAT      = $0130;
  SNAPI_PARAM_VIDEO_VIEW_FINDER = $0144;           // $0000: disable, $0001: enable

  SNAPI_IMAGE_FORMAT_JPEG = $0001;
  SNAPI_IMAGE_FORMAT_BMP  = $0003;
  SNAPI_IMAGE_FORMAT_TIFF = $0004;

Implementation

Const
  SNAPI_FEATURE_REPORT_SOFTWARE_REVISION = $31; //  -> NBRPVAAM
  SNAPI_FEATURE_REPORT_BOARD_TYPE = $32; // ???  -> Hardware Revision
  SNAPI_FEATURE_REPORT_ENGINE_CODE = $33; // ??? -> Engine Code
  SNAPI_FEATURE_REPORT_CLASS_INFO = $34; // ??? -> Class Code
  SNAPI_FEATURE_REPORT_UNKNOWN_1  = $3; //5 -> :D:C:V:b

  SNAPI_OUTPUT_REPORT_UNKNOWN_2 = $0c; // ->  01 01 00 30 01 , dann das selbe als HID_SET_REPORT, beides nur noch mit $20 Bytes
  SNAPI_OUTPUT_REPORT_STATUS = $21; // -> (oder so, kommt nach jedem SET_REPORT OUTPUT)  Report ID, Status, $00
  SNAPI_OUTPUT_REPORT_BARCODE = $22; //
  SNAPI_OUTPUT_REPORT_PARAM_STORED = $24; //    (data = 03 = Event Data Received???)
  SNAPI_OUTPUT_REPORT_UNKNOWN_3 = $25; //

  SNAPI_OUTPUT_REPORT_ACK = $01; // -> (nach jedem Strichcode?)

   SNAPI_OUTPUT_REPORT_AIM = $02; //
   SNAPI_OUTPUT_REPORT_LED = $05; //
   SNAPI_OUTPUT_REPORT_SCANNING = $06; //
   SNAPI_OUTPUT_REPORT_TRIGGER = $0A; //
   SNAPI_OUTPUT_REPORT_BEEP = $04; //
   SNAPI_OUTPUT_REPORT_MACRO_PDF = $08; //
   SNAPI_OUTPUT_REPORT_LOW_POWER = $07; //
   SNAPI_OUTPUT_REPORT_SET_DEFAULTS = $09; //    (data = 00)
  SNAPI_OUTPUT_REPORT_SET_IMAGE_FORMAT = $0b; // ($20 bytes data)
  SNAPI_OUTPUT_REPORT_GET_PARAMETER = $0c; //

  SNAPI_STATUS_OK = $01;
  SNAPI_STATUS_COMMAND_NOT_SUPPORTED = $03;


{ TSNAPIDevice }

Constructor TSNAPIDevice.Create(idVendor, idProduct: LongInt; AConfig, AInterface, AAltInterface: LongInt);
Var Intf : PUSBInterfaceDescriptor;
Begin
  inherited Create(idVendor,idProduct,AConfig);
  { create USB interface }
  Intf := USBFindInterface(AInterface,AAltInterface,FDevice); { better: search for iInterface = "SNAPI Command Interface" }
  FSNAPICommandInterface := TUSBPseudoHIDInterface.Create(Self,Intf);
  FSNAPICommandInterface.OnIntrReport := @IntrReport;
End;

Destructor TSNAPIDevice.Destroy;
Begin
  if (Self <> Nil) and (FSNAPICommandInterface <> Nil) then
    Begin
      ReleaseTrigger;
      ScanDisable;
    End;
  FSNAPICommandInterface.Free;
  inherited Destroy;
End;

Function TSNAPIDevice.WaitForACK(ReportID : Byte): TSNAPIError;
Const BufSize = 64;
Var Buf : Array[0..BufSize-1] of Byte;
    Len : Integer;
    Status : PHIDReport;
Begin
  Len := FSNAPICommandInterface.InterruptRead;
  if Len < 0 then
    Begin
      WriteLn('No Interrupt In!');
      Exit(seNoACK);  // ERROR
    End;
  Status := FSNAPICommandInterface.HasReport(SNAPI_OUTPUT_REPORT_STATUS);
  if Status = Nil then
    Begin
      WriteLn('No Status Report!');
      Exit(seNoACK);  // ERROR
    End;
  if Status^.Data[0] = ReportID then
    Begin
      FSNAPICommandInterface.EatReport(Status);
      Case Status^.Data[1] of
        SNAPI_STATUS_OK : Begin
          //WriteLn('Ok');
          FreeMem(Status);
          Exit(seOk);
        End;
        SNAPI_STATUS_COMMAND_NOT_SUPPORTED : Begin
          WriteLn('Command not supported');
          FreeMem(Status);
          Exit(seCommandNotSupported)
        End;
      else
        WriteLn('Unknown SNAPI Status: $',IntToHex(Status^.Data[1],2));
        FreeMem(Status);
      End;
    End;
End;

Procedure TSNAPIDevice.SetOutputReport(ReportID:Byte;Data:Byte);
Var Ret : TSNAPIError;
Begin
  FSNAPICommandInterface.SetOutputReport(ReportID, Data, 1);
  Ret := WaitForAck(ReportID);
  Case Ret of
    seOk                  : ;
    seNoACK               : raise ESNAPINoAck.Create('No Ack');
    seCommandNotSupported : raise ESNAPICommandNotSupported.Create('Command not Supported');
    else
      raise ESNAPIError.CreateFmt('Unknown error %d',[Ord(Ret)]);
  End;
End;

Procedure TSNAPIDevice.SendACK(ReportID : Byte);
Var ACK : Array[0..2] of Byte;
Begin
  ACK[0] := ReportID;
  ACK[1] := SNAPI_STATUS_OK;
  ACK[2] := 0;
  FSNAPICommandInterface.SetOutputReport(SNAPI_OUTPUT_REPORT_ACK, ACK, 3);
End;

Function TSNAPIDevice.IntrReport(Report: PHIDReport): Boolean;
Var St : String;
    I  : Integer;
    Len : Integer;
    Pos : Integer;
Begin
  Result := False;
  Case Report^.ReportID of
    SNAPI_OUTPUT_REPORT_BARCODE : Begin
      // every single report has to be acknowledged, even if one barcode is split into multiple reports
      SendACK(SNAPI_OUTPUT_REPORT_BARCODE);
      if PReportBarcode(Report)^.Length > 26 then
        Begin
          WriteLn('Error: Invalid length of barcode: ',PReportBarcode(Report)^.Length);
          Exit(True);
        End;
      if PReportBarcode(Report)^.Packets > 1 then
        Begin
          //WriteLn('Received packet ',PReportBarcode(Report)^.PacketNum,' of ',PReportBarcode(Report)^.Packets);
          // first fragment? create array
          if Length(FFragmentedBarcode) = 0 then
            SetLength(FFragmentedBarcode,PReportBarcode(Report)^.Packets);
          // check if this report belongs to us
          if PReportBarcode(Report)^.Packets <> Length(FFragmentedBarcode) then    // correct number of reports?
            Begin
              WriteLn('Error: Fragment with different total number of packets');
              SetLength(FFragmentedBarcode,0);
              Exit(True);
            End;
          if FFragmentedBarcode[PReportBarcode(Report)^.PacketNum].Packets <> 0 then  // not already received?
            Begin
              WriteLn('Error: Fragment with same number already received');
              SetLength(FFragmentedBarcode,0);
              Exit(True);
            End;
          // store report
          FFragmentedBarcode[PReportBarcode(Report)^.PacketNum] := PReportBarcode(Report)^;
          FreeMem(Report);
          // check if all reports have arrived
          For I := 0 to Length(FFragmentedBarcode)-1 do
            if FFragmentedBarcode[I].Packets = 0 then
              Exit(True);   // this entry was not yet set, i.e. we are not yet finished
          // all fragments have arrived
          Len := 0;
          For I := 0 to Length(FFragmentedBarcode)-1 do
            Len := Len + FFragmentedBarcode[I].Length;
          SetLength(St,Len);
          Pos := 1;
          For I := 0 to Length(FFragmentedBarcode)-1 do
            Begin
              Move(FFragmentedBarcode[I].Barcode,St[Pos],FFragmentedBarcode[I].Length);
              Pos := Pos + FFragmentedBarcode[I].Length;
            End;
          // Debug
          WriteLn('Barcode: ',St,' Packets: ',Length(FFragmentedBarcode));
          // remove array
          SetLength(FFragmentedBarcode,0);
        End
      else
        Begin
          SetLength(St,PReportBarcode(Report)^.Length);
          Move(PReportBarcode(Report)^.Barcode,St[1],PReportBarcode(Report)^.Length);
          With PReportBarcode(Report)^ do
            WriteLn('Barcode: ',St,' Packets: ',Packets,' # ',PacketNum,' Code Type: ',Ord(CodeType){doesn't work with holes:,'=',GetEnumName(TypeInfo(TSNAPICodeType),Ord(CodeType))},' U3: ',Unknown3);
          FreeMem(Report);
        End;

      if FOnBarcode <> Nil then
        FOnBarcode(St);
      Result := True;
    End;
  else
  End;
End;

Procedure TSNAPIDevice.AbortMacroPdf;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_MACRO_PDF,$01);
End;

Procedure TSNAPIDevice.FlushMacroPdf;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_MACRO_PDF,$00);
End;

Procedure TSNAPIDevice.AimOff;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_AIM,$00);
End;

Procedure TSNAPIDevice.AimOn;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_AIM,$01);
End;

Procedure TSNAPIDevice.Beep(Code: TSNAPIBeepCode);
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_BEEP,Byte(Code));
End;

Procedure TSNAPIDevice.EnterLowPwrMode;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_LOW_POWER,$01);
End;

function TSNAPIDevice.GetSerialNumber: String;
Begin

End;

Procedure TSNAPIDevice.LedOff(LEDs: Byte);
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_AIM,$00);  // TODO: but how to set the LEDs?
End;

Procedure TSNAPIDevice.LedOn(LEDs: Byte);
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_AIM,$01);
End;

Procedure TSNAPIDevice.PullTrigger;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_TRIGGER,$01);
End;

Procedure TSNAPIDevice.ReleaseTrigger;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_TRIGGER,$00);
End;

Procedure TSNAPIDevice.RequestParameters(Parameters: array of Word);
Begin

End;

Procedure TSNAPIDevice.RequestScannerCapabilities;
Begin

End;

Procedure TSNAPIDevice.ScanDisable;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_SCANNING,$00);
End;

Procedure TSNAPIDevice.ScanEnable;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_SCANNING,$01);
End;

Procedure TSNAPIDevice.SetParamPersistance(Persistent: Boolean);
Begin

End;

Procedure TSNAPIDevice.SetParameterDefaults;
Begin
  SetOutputReport(SNAPI_OUTPUT_REPORT_SET_DEFAULTS,$00);
  // this is followed by a Param Stored Event
End;

Procedure TSNAPIDevice.SetParameters(Parameters: array of Word);
Begin

End;

Procedure TSNAPIDevice.SnapShot;
Begin

End;

Procedure TSNAPIDevice.TransmitVersion;
Begin

End;

Procedure TSNAPIDevice.TransmitVideo;
Begin

End;

Procedure TSNAPIDevice.Listen;
Var Len : Integer;
Begin
  Len := FSNAPICommandInterface.InterruptRead;
  // negative values are pre-filtered, i.e. ESysETIMEDOUT is returned as 0
  if Len < 0 then
    raise USBException('TSNAPIDevice.Listen',Len);
End;

End.

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to