├── Project2.dproj.local ├── Project2.res ├── README.md ├── device_filter.xml ├── Project2.dpr ├── Project2.identcache ├── .gitignore ├── UnitUSBTestJNI.fmx ├── AndroidManifest.template.xml ├── AndroidHeaders ├── Androidapi.JNI.Toast.pas └── android.app.PendingIntent.pas ├── AndroidUSBHeaders ├── android.hardware.usb.UsbInterface.pas ├── android.hardware.usb.UsbEndpoint.pas ├── android.hardware.usb.UsbAccessory.pas ├── android.hardware.usb.UsbDevice.pas ├── android.hardware.usb.UsbManager.pas ├── __history │ └── android.hardware.usb.UsbManager.pas.~1~ ├── android.hardware.usb.UsbDeviceConnection.pas └── android.hardware.usb.UsbConstants.pas ├── UnitUSBTestJNI.pas ├── USB2.pas ├── LICENSE ├── android.hardware.usb.HID.pas └── Project2.dproj /Project2.dproj.local: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Project2.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LongDirtyAnimAlf/Delphi-Android-USB-HID/HEAD/Project2.res -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Delphi-Android-USB-HID 2 | This is a simple clone of the Jedi JVCL library to access Hid devices on Android with Delphi. 3 | Not all functions fom the original JVCL library are available. 4 | But this simple clone will allow you to control most HID devices. 5 | It is designed to control Microchip MCUs with USB and the HID firmware. 6 | But other applications can be made to function. 7 | -------------------------------------------------------------------------------- /device_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | // Microchip USB HID 18 | 19 | -------------------------------------------------------------------------------- /Project2.dpr: -------------------------------------------------------------------------------- 1 | program Project2; 2 | 3 | uses 4 | //System.SysUtils, 5 | System.StartUpCopy, 6 | FMX.Forms, 7 | UnitUSBTestJNI in 'UnitUSBTestJNI.pas' {Form1}, 8 | android.hardware.usb.UsbDeviceConnection in '.\AndroidUSBHeaders\android.hardware.usb.UsbDeviceConnection.pas', 9 | android.hardware.usb.UsbEndpoint in '.\AndroidUSBHeaders\android.hardware.usb.UsbEndpoint.pas', 10 | android.hardware.usb.UsbManager in '.\AndroidUSBHeaders\android.hardware.usb.UsbManager.pas', 11 | android.hardware.usb.UsbDevice in '.\AndroidUSBHeaders\android.hardware.usb.UsbDevice.pas', 12 | android.hardware.usb.UsbInterface in '.\AndroidUSBHeaders\android.hardware.usb.UsbInterface.pas', 13 | android.hardware.usb.UsbConstants in '.\AndroidUSBHeaders\android.hardware.usb.UsbConstants.pas', 14 | android.app.PendingIntent in '.\AndroidHeaders\android.app.PendingIntent.pas', 15 | Androidapi.JNI.Toast in '.\AndroidHeaders\Androidapi.JNI.Toast.pas', 16 | USB2 in 'USB2.pas', 17 | android.hardware.usb.HID in 'android.hardware.usb.HID.pas'; 18 | 19 | {$R *.res} 20 | 21 | begin 22 | Application.Initialize; 23 | Application.CreateForm(TForm1, Form1); 24 | Application.Run; 25 | //FreeAndNil(Application); 26 | end. 27 | -------------------------------------------------------------------------------- /Project2.identcache: -------------------------------------------------------------------------------- 1 | @C:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\USB2.pasJC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\UnitUSBTestJNI.pas_C:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\AndroidHeaders\Androidapi.JNI.Toast.paslC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\AndroidUSBHeaders\android.hardware.usb.UsbDevice.pasnC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\AndroidUSBHeaders\android.hardware.usb.UsbEndpoint.pasdC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\AndroidHeaders\android.app.PendingIntent.pasoC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\AndroidUSBHeaders\android.hardware.usb.UsbConstants.pasmC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\AndroidUSBHeaders\android.hardware.usb.UsbManager.pasTC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\android.hardware.usb.HID.pasoC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\AndroidUSBHeaders\android.hardware.usb.UsbInterface.pasDC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\Project2.dprvC:\Users\Alfred\Documents\GitHub\Delphi-Android-USB-HID\AndroidUSBHeaders\android.hardware.usb.UsbDeviceConnection.pas -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | 25 | # Delphi compiler-generated binaries (safe to delete) 26 | *.exe 27 | *.dll 28 | *.bpl 29 | *.bpi 30 | *.dcp 31 | *.so 32 | *.apk 33 | *.drc 34 | *.map 35 | *.dres 36 | *.rsm 37 | *.tds 38 | *.dcu 39 | *.lib 40 | 41 | # Delphi autogenerated files (duplicated info) 42 | *.cfg 43 | *Resource.rc 44 | 45 | # Delphi local files (user-specific info) 46 | *.local 47 | *.identcache 48 | *.projdata 49 | *.tvsconfig 50 | *.dsk 51 | 52 | # Delphi history and backups 53 | __history/ 54 | *.~* 55 | 56 | # Delphi build directories 57 | Android/ 58 | Win32/ 59 | Win64/ 60 | OSX32/ 61 | OSX64/ 62 | 63 | # Castalia statistics file 64 | *.stat -------------------------------------------------------------------------------- /UnitUSBTestJNI.fmx: -------------------------------------------------------------------------------- 1 | object Form1: TForm1 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form2' 5 | ClientHeight = 518 6 | ClientWidth = 308 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object Memo1: TMemo 12 | Touch.InteractiveGestures = [Pan, LongTap, DoubleTap] 13 | Align = Client 14 | Size.Width = 308.000000000000000000 15 | Size.Height = 328.000000000000000000 16 | Size.PlatformDefault = False 17 | TabOrder = 0 18 | TextSettings.WordWrap = True 19 | end 20 | object btnHIDCreate: TButton 21 | Align = Bottom 22 | Position.Y = 328.000000000000000000 23 | Size.Width = 308.000000000000000000 24 | Size.Height = 56.000000000000000000 25 | Size.PlatformDefault = False 26 | TabOrder = 2 27 | Text = 'Create HID controller' 28 | OnClick = btnHIDCreateClick 29 | end 30 | object btnHIDEnable: TButton 31 | Align = Bottom 32 | Enabled = False 33 | Position.Y = 384.000000000000000000 34 | Size.Width = 308.000000000000000000 35 | Size.Height = 48.000000000000000000 36 | Size.PlatformDefault = False 37 | TabOrder = 4 38 | Text = 'Enable HID controller' 39 | OnClick = btnHIDEnableClick 40 | end 41 | object btnGetSerial: TButton 42 | Align = Bottom 43 | Enabled = False 44 | Position.Y = 432.000000000000000000 45 | Size.Width = 308.000000000000000000 46 | Size.Height = 48.000000000000000000 47 | Size.PlatformDefault = False 48 | TabOrder = 6 49 | Text = 'Get serial of first HID device' 50 | OnClick = btnGetSerialClick 51 | end 52 | object btnInfo: TButton 53 | Align = Bottom 54 | Enabled = False 55 | Position.Y = 480.000000000000000000 56 | Size.Width = 308.000000000000000000 57 | Size.Height = 38.000000000000000000 58 | Size.PlatformDefault = False 59 | TabOrder = 7 60 | Text = 'USB info' 61 | OnClick = btnInfoClick 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /AndroidManifest.template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | <%uses-permission%> 16 | 25 | 27 | 31 | 32 | 34 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <%activity%> 43 | 44 | <%receivers%> 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /AndroidHeaders/Androidapi.JNI.Toast.pas: -------------------------------------------------------------------------------- 1 | unit Androidapi.JNI.Toast; 2 | 3 | //Java bridge class imported by hand by Brian Long (http://blong.com) 4 | 5 | interface 6 | 7 | uses 8 | Androidapi.JNIBridge, 9 | Androidapi.JNI.JavaTypes, 10 | Androidapi.JNI.GraphicsContentViewText; 11 | 12 | type 13 | TToastLength = (LongToast, ShortToast); 14 | 15 | JToast = interface; 16 | 17 | JToastClass = interface(JObjectClass) 18 | ['{69E2D233-B9D3-4F3E-B882-474C8E1D50E9}'] 19 | {Property methods} 20 | function _GetLENGTH_LONG: Integer; cdecl; 21 | function _GetLENGTH_SHORT: Integer; cdecl; 22 | {Methods} 23 | function init(context: JContext): JToast; cdecl; overload; 24 | function makeText(context: JContext; text: JCharSequence; duration: Integer): JToast; cdecl; 25 | {Properties} 26 | property LENGTH_LONG: Integer read _GetLENGTH_LONG; 27 | property LENGTH_SHORT: Integer read _GetLENGTH_SHORT; 28 | end; 29 | 30 | [JavaSignature('android/widget/Toast')] 31 | JToast = interface(JObject) 32 | ['{FD81CC32-BFBC-4838-8893-9DD01DE47B00}'] 33 | {Methods} 34 | procedure cancel; cdecl; 35 | function getDuration: Integer; cdecl; 36 | function getGravity: Integer; cdecl; 37 | function getHorizontalMargin: Single; cdecl; 38 | function getVerticalMargin: Single; cdecl; 39 | function getView: JView; cdecl; 40 | function getXOffset: Integer; cdecl; 41 | function getYOffset: Integer; cdecl; 42 | procedure setDuration(value: Integer); cdecl; 43 | procedure setGravity(gravity, xOffset, yOffset: Integer); cdecl; 44 | procedure setMargin(horizontalMargin, verticalMargin: Single); cdecl; 45 | procedure setText(s: JCharSequence); cdecl; 46 | procedure setView(view: JView); cdecl; 47 | procedure show; cdecl; 48 | end; 49 | TJToast = class(TJavaGenericImport) end; 50 | 51 | procedure Toast(const Msg: string; Duration: TToastLength = ShortToast); 52 | 53 | implementation 54 | 55 | uses 56 | FMX.Helpers.Android, 57 | Androidapi.Helpers; 58 | 59 | procedure Toast(const Msg: string; Duration: TToastLength); 60 | var 61 | ToastLength: Integer; 62 | begin 63 | if Duration = ShortToast then 64 | ToastLength := TJToast.JavaClass.LENGTH_SHORT 65 | else 66 | ToastLength := TJToast.JavaClass.LENGTH_LONG; 67 | CallInUiThread(procedure 68 | begin 69 | TJToast.JavaClass.makeText(SharedActivityContext, StrToJCharSequence(msg), 70 | ToastLength).show 71 | end); 72 | end; 73 | 74 | end. 75 | -------------------------------------------------------------------------------- /AndroidUSBHeaders/android.hardware.usb.UsbInterface.pas: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by JavaToPas v1.5 20140918 - 093132 3 | //////////////////////////////////////////////////////////////////////////////// 4 | unit android.hardware.usb.UsbInterface; 5 | 6 | interface 7 | 8 | uses 9 | AndroidAPI.JNIBridge, 10 | Androidapi.JNI.JavaTypes, 11 | Androidapi.JNI.os, 12 | android.hardware.usb.UsbEndpoint; 13 | 14 | type 15 | JUsbInterface = interface; 16 | 17 | JUsbInterfaceClass = interface(JObjectClass) 18 | ['{C6568D6C-A70D-49E7-B387-76B8D78336DE}'] 19 | function _GetCREATOR : JParcelable_Creator; cdecl; // A: $19 20 | function describeContents : Integer; cdecl; // ()I A: $1 21 | function getEndpoint(&index : Integer) : JUsbEndpoint; cdecl; // (I)Landroid/hardware/usb/UsbEndpoint; A: $1 22 | function getEndpointCount : Integer; cdecl; // ()I A: $1 23 | function getId : Integer; cdecl; // ()I A: $1 24 | function getInterfaceClass : Integer; cdecl; // ()I A: $1 25 | function getInterfaceProtocol : Integer; cdecl; // ()I A: $1 26 | function getInterfaceSubclass : Integer; cdecl; // ()I A: $1 27 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 28 | procedure writeToParcel(parcel : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 29 | property CREATOR : JParcelable_Creator read _GetCREATOR; // Landroid/os/Parcelable$Creator; A: $19 30 | end; 31 | 32 | [JavaSignature('android/hardware/usb/UsbInterface')] 33 | JUsbInterface = interface(JObject) 34 | ['{86ABB4C3-A129-49E1-88BE-890EF6C31E04}'] 35 | function describeContents : Integer; cdecl; // ()I A: $1 36 | function getEndpoint(&index : Integer) : JUsbEndpoint; cdecl; // (I)Landroid/hardware/usb/UsbEndpoint; A: $1 37 | function getEndpointCount : Integer; cdecl; // ()I A: $1 38 | function getId : Integer; cdecl; // ()I A: $1 39 | function getInterfaceClass : Integer; cdecl; // ()I A: $1 40 | function getInterfaceProtocol : Integer; cdecl; // ()I A: $1 41 | function getInterfaceSubclass : Integer; cdecl; // ()I A: $1 42 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 43 | procedure writeToParcel(parcel : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 44 | end; 45 | 46 | TJUsbInterface = class(TJavaGenericImport) 47 | end; 48 | 49 | implementation 50 | 51 | end. 52 | -------------------------------------------------------------------------------- /AndroidUSBHeaders/android.hardware.usb.UsbEndpoint.pas: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by JavaToPas v1.5 20140918 - 093132 3 | //////////////////////////////////////////////////////////////////////////////// 4 | unit android.hardware.usb.UsbEndpoint; 5 | 6 | interface 7 | 8 | uses 9 | AndroidAPI.JNIBridge, 10 | Androidapi.JNI.JavaTypes, 11 | Androidapi.JNI.os; 12 | 13 | type 14 | JUsbEndpoint = interface; 15 | 16 | JUsbEndpointClass = interface(JObjectClass) 17 | ['{F87F238E-1166-4AF4-B345-CCB61DBD770E}'] 18 | function _GetCREATOR : JParcelable_Creator; cdecl; // A: $19 19 | function describeContents : Integer; cdecl; // ()I A: $1 20 | function getAddress : Integer; cdecl; // ()I A: $1 21 | function getAttributes : Integer; cdecl; // ()I A: $1 22 | function getDirection : Integer; cdecl; // ()I A: $1 23 | function getEndpointNumber : Integer; cdecl; // ()I A: $1 24 | function getInterval : Integer; cdecl; // ()I A: $1 25 | function getMaxPacketSize : Integer; cdecl; // ()I A: $1 26 | function getType : Integer; cdecl; // ()I A: $1 27 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 28 | procedure writeToParcel(parcel : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 29 | property CREATOR : JParcelable_Creator read _GetCREATOR; // Landroid/os/Parcelable$Creator; A: $19 30 | end; 31 | 32 | [JavaSignature('android/hardware/usb/UsbEndpoint')] 33 | JUsbEndpoint = interface(JObject) 34 | ['{7FDFAEF0-F8DC-4F5C-933D-81A1BE691B6B}'] 35 | function describeContents : Integer; cdecl; // ()I A: $1 36 | function getAddress : Integer; cdecl; // ()I A: $1 37 | function getAttributes : Integer; cdecl; // ()I A: $1 38 | function getDirection : Integer; cdecl; // ()I A: $1 39 | function getEndpointNumber : Integer; cdecl; // ()I A: $1 40 | function getInterval : Integer; cdecl; // ()I A: $1 41 | function getMaxPacketSize : Integer; cdecl; // ()I A: $1 42 | function getType : Integer; cdecl; // ()I A: $1 43 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 44 | procedure writeToParcel(parcel : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 45 | end; 46 | 47 | TJUsbEndpoint = class(TJavaGenericImport) 48 | end; 49 | 50 | implementation 51 | 52 | end. 53 | -------------------------------------------------------------------------------- /AndroidUSBHeaders/android.hardware.usb.UsbAccessory.pas: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by JavaToPas v1.5 20140918 - 093132 3 | //////////////////////////////////////////////////////////////////////////////// 4 | unit android.hardware.usb.UsbAccessory; 5 | 6 | interface 7 | 8 | uses 9 | AndroidAPI.JNIBridge, 10 | Androidapi.JNI.JavaTypes, 11 | Androidapi.JNI.os; 12 | 13 | type 14 | JUsbAccessory = interface; 15 | 16 | JUsbAccessoryClass = interface(JObjectClass) 17 | ['{BB18CBC1-4FED-41BB-A2F1-8D95E772C4F0}'] 18 | function _GetCREATOR : JParcelable_Creator; cdecl; // A: $19 19 | function describeContents : Integer; cdecl; // ()I A: $1 20 | function equals(obj : JObject) : boolean; cdecl; // (Ljava/lang/Object;)Z A: $1 21 | function getDescription : JString; cdecl; // ()Ljava/lang/String; A: $1 22 | function getManufacturer : JString; cdecl; // ()Ljava/lang/String; A: $1 23 | function getModel : JString; cdecl; // ()Ljava/lang/String; A: $1 24 | function getSerial : JString; cdecl; // ()Ljava/lang/String; A: $1 25 | function getUri : JString; cdecl; // ()Ljava/lang/String; A: $1 26 | function getVersion : JString; cdecl; // ()Ljava/lang/String; A: $1 27 | function hashCode : Integer; cdecl; // ()I A: $1 28 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 29 | procedure writeToParcel(parcel : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 30 | property CREATOR : JParcelable_Creator read _GetCREATOR; // Landroid/os/Parcelable$Creator; A: $19 31 | end; 32 | 33 | [JavaSignature('android/hardware/usb/UsbAccessory')] 34 | JUsbAccessory = interface(JObject) 35 | ['{E85D9F43-BAD7-4074-B692-9FFE45206EBC}'] 36 | function describeContents : Integer; cdecl; // ()I A: $1 37 | function equals(obj : JObject) : boolean; cdecl; // (Ljava/lang/Object;)Z A: $1 38 | function getDescription : JString; cdecl; // ()Ljava/lang/String; A: $1 39 | function getManufacturer : JString; cdecl; // ()Ljava/lang/String; A: $1 40 | function getModel : JString; cdecl; // ()Ljava/lang/String; A: $1 41 | function getSerial : JString; cdecl; // ()Ljava/lang/String; A: $1 42 | function getUri : JString; cdecl; // ()Ljava/lang/String; A: $1 43 | function getVersion : JString; cdecl; // ()Ljava/lang/String; A: $1 44 | function hashCode : Integer; cdecl; // ()I A: $1 45 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 46 | procedure writeToParcel(parcel : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 47 | end; 48 | 49 | TJUsbAccessory = class(TJavaGenericImport) 50 | end; 51 | 52 | implementation 53 | 54 | end. 55 | -------------------------------------------------------------------------------- /UnitUSBTestJNI.pas: -------------------------------------------------------------------------------- 1 | unit UnitUSBTestJNI; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, 8 | FMX.Layouts, FMX.Memo, FMX.StdCtrls, FMX.Grid, 9 | usb2, System.Rtti; 10 | 11 | type 12 | TForm1 = class(TForm) 13 | Memo1: TMemo; 14 | btnHIDCreate: TButton; 15 | btnHIDEnable: TButton; 16 | btnGetSerial: TButton; 17 | btnInfo: TButton; 18 | procedure btnHIDCreateClick(Sender: TObject); 19 | procedure btnHIDEnableClick(Sender: TObject); 20 | procedure btnGetSerialClick(Sender: TObject); 21 | procedure btnInfoClick(Sender: TObject); 22 | private 23 | { Private declarations } 24 | NewUSB:TUSB; 25 | procedure UpdateUSBDevice(Sender: TObject;datacarrier:integer); 26 | public 27 | end; 28 | 29 | var 30 | Form1: TForm1; 31 | 32 | implementation 33 | 34 | uses 35 | StrUtils, 36 | System.IOUtils, 37 | Androidapi.JNI.Toast; 38 | 39 | {$R *.fmx} 40 | 41 | const 42 | Numtypes=2; 43 | Numsamples=7; 44 | 45 | {Form1} 46 | 47 | procedure TForm1.btnInfoClick(Sender: TObject); 48 | var 49 | S:string; 50 | begin 51 | S:=NewUSB.Info; 52 | if Length(S)>0 then 53 | begin 54 | Memo1.Lines.Append('INFO:'); 55 | Memo1.Lines.Append(S); 56 | end else Memo1.Lines.Append('No new USB info.'); 57 | end; 58 | 59 | procedure TForm1.btnHIDCreateClick(Sender: TObject); 60 | var 61 | S:string; 62 | begin 63 | TButton(Sender).Enabled:=False; 64 | Memo1.Lines.Append('HID Created.'); 65 | NewUSB:=TUSB.Create; 66 | NewUSB.OnUSBDeviceChange:=UpdateUSBDevice; 67 | Memo1.Lines.Append('Ready.'); 68 | S:=NewUSB.Info; 69 | if Length(S)>0 then 70 | begin 71 | Memo1.Lines.Append('INFO:'); 72 | Memo1.Lines.Append(S); 73 | end; 74 | S:=NewUSB.Errors; 75 | if Length(S)>0 then 76 | begin 77 | Memo1.Lines.Append('ERRORS:'); 78 | Memo1.Lines.Append(S); 79 | end; 80 | btnHIDEnable.Enabled:=True; 81 | btnInfo.Enabled:=True; 82 | end; 83 | 84 | procedure TForm1.btnHIDEnableClick(Sender: TObject); 85 | var 86 | S:string; 87 | begin 88 | TButton(Sender).Enabled:=False; 89 | Memo1.Lines.Append('HID Enabled.'); 90 | NewUSB.Enabled:=True; 91 | Memo1.Lines.Append('Ready.'); 92 | S:=NewUSB.Info; 93 | if Length(S)>0 then 94 | begin 95 | Memo1.Lines.Append('INFO:'); 96 | Memo1.Lines.Append(S); 97 | end; 98 | S:=NewUSB.Errors; 99 | if Length(S)>0 then 100 | begin 101 | Memo1.Lines.Append('ERRORS:'); 102 | Memo1.Lines.Append(S); 103 | end; 104 | btnGetSerial.Enabled:=True; 105 | end; 106 | 107 | procedure TForm1.btnGetSerialClick(Sender: TObject); 108 | var 109 | S:string; 110 | begin 111 | Memo1.Lines.Append('Get HID serial:'); 112 | Memo1.Lines.Append(NewUSB.GetSerial[0]); 113 | Memo1.Lines.Append('Ready.'); 114 | S:=NewUSB.Info; 115 | if Length(S)>0 then 116 | begin 117 | Memo1.Lines.Append('INFO:'); 118 | Memo1.Lines.Append(S); 119 | end; 120 | S:=NewUSB.Errors; 121 | if Length(S)>0 then 122 | begin 123 | Memo1.Lines.Append('ERRORS:'); 124 | Memo1.Lines.Append(S); 125 | end; 126 | end; 127 | 128 | 129 | procedure TForm1.UpdateUSBDevice(Sender: TObject;datacarrier:integer); 130 | var 131 | S:string; 132 | begin 133 | Memo1.Lines.Append('Measuremain board: '+InttoStr(datacarrier)); 134 | S:=NewUSB.Info; 135 | if Length(S)>0 then 136 | begin 137 | Memo1.Lines.Append('INFO:'); 138 | Memo1.Lines.Append(S); 139 | end; 140 | S:=NewUSB.Errors; 141 | if Length(S)>0 then 142 | begin 143 | Memo1.Lines.Append('ERRORS:'); 144 | Memo1.Lines.Append(S); 145 | end; 146 | end; 147 | 148 | end. 149 | -------------------------------------------------------------------------------- /AndroidUSBHeaders/android.hardware.usb.UsbDevice.pas: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by JavaToPas v1.5 20140918 - 093132 3 | //////////////////////////////////////////////////////////////////////////////// 4 | unit android.hardware.usb.UsbDevice; 5 | 6 | interface 7 | 8 | uses 9 | AndroidAPI.JNIBridge, 10 | Androidapi.JNI.JavaTypes, 11 | Androidapi.JNI.os, 12 | android.hardware.usb.UsbInterface; 13 | 14 | type 15 | JUsbDevice = interface; 16 | 17 | JUsbDeviceClass = interface(JObjectClass) 18 | ['{64CFC6B3-EB8E-444D-BC35-45F39730D3E8}'] 19 | function _GetCREATOR : JParcelable_Creator; cdecl; // A: $19 20 | function describeContents : Integer; cdecl; // ()I A: $1 21 | function equals(o : JObject) : boolean; cdecl; // (Ljava/lang/Object;)Z A: $1 22 | function getDeviceClass : Integer; cdecl; // ()I A: $1 23 | function getDeviceId : Integer; cdecl; overload; // ()I A: $1 24 | function getDeviceId(&name : JString) : Integer; cdecl; overload; // (Ljava/lang/String;)I A: $9 25 | function getDeviceName : JString; cdecl; overload; // ()Ljava/lang/String; A: $1 26 | function getDeviceName(id : Integer) : JString; cdecl; overload; // (I)Ljava/lang/String; A: $9 27 | function getManufacturerName : JString; cdecl; overload; // ()Ljava/lang/String; A: $1 28 | function getManufacturerName(id : Integer) : JString; cdecl; overload; // (I)Ljava/lang/String; A: $9 29 | function getDeviceProtocol : Integer; cdecl; // ()I A: $1 30 | function getDeviceSubclass : Integer; cdecl; // ()I A: $1 31 | function getInterface(&index : Integer) : JUsbInterface; cdecl; // (I)Landroid/hardware/usb/UsbInterface; A: $1 32 | function getInterfaceCount : Integer; cdecl; // ()I A: $1 33 | function getProductId : Integer; cdecl; // ()I A: $1 34 | function getVendorId : Integer; cdecl; // ()I A: $1 35 | function hashCode : Integer; cdecl; // ()I A: $1 36 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 37 | procedure writeToParcel(parcel : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 38 | property CREATOR : JParcelable_Creator read _GetCREATOR; // Landroid/os/Parcelable$Creator; A: $19 39 | end; 40 | 41 | [JavaSignature('android/hardware/usb/UsbDevice')] 42 | JUsbDevice = interface(JObject) 43 | ['{9B3E938C-94B1-49CE-BA19-9DFEF9A96972}'] 44 | function describeContents : Integer; cdecl; // ()I A: $1 45 | function equals(o : JObject) : boolean; cdecl; // (Ljava/lang/Object;)Z A: $1 46 | function getDeviceClass : Integer; cdecl; // ()I A: $1 47 | function getDeviceId : Integer; cdecl; overload; // ()I A: $1 48 | function getDeviceName : JString; cdecl; overload; // ()Ljava/lang/String; A: $1 49 | function getManufacturerName : JString; cdecl; overload; // ()Ljava/lang/String; A: $1 50 | function getDeviceProtocol : Integer; cdecl; // ()I A: $1 51 | function getDeviceSubclass : Integer; cdecl; // ()I A: $1 52 | function getInterface(&index : Integer) : JUsbInterface; cdecl; // (I)Landroid/hardware/usb/UsbInterface; A: $1 53 | function getInterfaceCount : Integer; cdecl; // ()I A: $1 54 | function getProductId : Integer; cdecl; // ()I A: $1 55 | function getVendorId : Integer; cdecl; // ()I A: $1 56 | function hashCode : Integer; cdecl; // ()I A: $1 57 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 58 | procedure writeToParcel(parcel : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 59 | end; 60 | 61 | TJUsbDevice = class(TJavaGenericImport) 62 | end; 63 | 64 | implementation 65 | 66 | end. 67 | -------------------------------------------------------------------------------- /AndroidUSBHeaders/android.hardware.usb.UsbManager.pas: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by JavaToPas v1.5 20140918 - 093132 3 | //////////////////////////////////////////////////////////////////////////////// 4 | unit android.hardware.usb.UsbManager; 5 | 6 | interface 7 | 8 | uses 9 | AndroidAPI.JNIBridge, 10 | Androidapi.JNI.JavaTypes, 11 | android.hardware.usb.UsbDeviceConnection, 12 | android.hardware.usb.UsbDevice, 13 | android.hardware.usb.UsbAccessory, 14 | Androidapi.JNI.os, 15 | Androidapi.JNI.App; 16 | // android.app.PendingIntent; 17 | 18 | type 19 | JUsbManager = interface; 20 | 21 | JUsbManagerClass = interface(JObjectClass) 22 | ['{4FC84AA6-1E8D-46D2-B850-828F4E897D3F}'] 23 | function _GetACTION_USB_ACCESSORY_ATTACHED : JString; cdecl; // A: $19 24 | function _GetACTION_USB_ACCESSORY_DETACHED : JString; cdecl; // A: $19 25 | function _GetACTION_USB_DEVICE_ATTACHED : JString; cdecl; // A: $19 26 | function _GetACTION_USB_DEVICE_DETACHED : JString; cdecl; // A: $19 27 | function _GetEXTRA_ACCESSORY : JString; cdecl; // A: $19 28 | function _GetEXTRA_DEVICE : JString; cdecl; // A: $19 29 | function _GetEXTRA_PERMISSION_GRANTED : JString; cdecl; // A: $19 30 | function getAccessoryList : TJavaArray; cdecl; // ()[Landroid/hardware/usb/UsbAccessory; A: $1 31 | function getDeviceList : JHashMap; cdecl; // ()Ljava/util/HashMap; A: $1 32 | function hasPermission(accessory : JUsbAccessory) : boolean; cdecl; overload;// (Landroid/hardware/usb/UsbAccessory;)Z A: $1 33 | function hasPermission(device : JUsbDevice) : boolean; cdecl; overload; // (Landroid/hardware/usb/UsbDevice;)Z A: $1 34 | function openAccessory(accessory : JUsbAccessory) : JParcelFileDescriptor; cdecl;// (Landroid/hardware/usb/UsbAccessory;)Landroid/os/ParcelFileDescriptor; A: $1 35 | function openDevice(device : JUsbDevice) : JUsbDeviceConnection; cdecl; // (Landroid/hardware/usb/UsbDevice;)Landroid/hardware/usb/UsbDeviceConnection; A: $1 36 | procedure requestPermission(accessory : JUsbAccessory; pi : JPendingIntent) ; cdecl; overload;// (Landroid/hardware/usb/UsbAccessory;Landroid/app/PendingIntent;)V A: $1 37 | procedure requestPermission(device : JUsbDevice; pi : JPendingIntent) ; cdecl; overload;// (Landroid/hardware/usb/UsbDevice;Landroid/app/PendingIntent;)V A: $1 38 | property ACTION_USB_ACCESSORY_ATTACHED : JString read _GetACTION_USB_ACCESSORY_ATTACHED;// Ljava/lang/String; A: $19 39 | property ACTION_USB_ACCESSORY_DETACHED : JString read _GetACTION_USB_ACCESSORY_DETACHED;// Ljava/lang/String; A: $19 40 | property ACTION_USB_DEVICE_ATTACHED : JString read _GetACTION_USB_DEVICE_ATTACHED;// Ljava/lang/String; A: $19 41 | property ACTION_USB_DEVICE_DETACHED : JString read _GetACTION_USB_DEVICE_DETACHED;// Ljava/lang/String; A: $19 42 | property EXTRA_ACCESSORY : JString read _GetEXTRA_ACCESSORY; // Ljava/lang/String; A: $19 43 | property EXTRA_DEVICE : JString read _GetEXTRA_DEVICE; // Ljava/lang/String; A: $19 44 | property EXTRA_PERMISSION_GRANTED : JString read _GetEXTRA_PERMISSION_GRANTED;// Ljava/lang/String; A: $19 45 | end; 46 | 47 | [JavaSignature('android/hardware/usb/UsbManager')] 48 | JUsbManager = interface(JObject) 49 | ['{A5A85A3D-0B47-4A49-82CC-F90E8A2E16C6}'] 50 | function getAccessoryList : TJavaArray; cdecl; // ()[Landroid/hardware/usb/UsbAccessory; A: $1 51 | function getDeviceList : JHashMap; cdecl; // ()Ljava/util/HashMap; A: $1 52 | function hasPermission(accessory : JUsbAccessory) : boolean; cdecl; overload;// (Landroid/hardware/usb/UsbAccessory;)Z A: $1 53 | function hasPermission(device : JUsbDevice) : boolean; cdecl; overload; // (Landroid/hardware/usb/UsbDevice;)Z A: $1 54 | function openAccessory(accessory : JUsbAccessory) : JParcelFileDescriptor; cdecl;// (Landroid/hardware/usb/UsbAccessory;)Landroid/os/ParcelFileDescriptor; A: $1 55 | function openDevice(device : JUsbDevice) : JUsbDeviceConnection; cdecl; // (Landroid/hardware/usb/UsbDevice;)Landroid/hardware/usb/UsbDeviceConnection; A: $1 56 | procedure requestPermission(accessory : JUsbAccessory; pi : JPendingIntent) ; cdecl; overload;// (Landroid/hardware/usb/UsbAccessory;Landroid/app/PendingIntent;)V A: $1 57 | procedure requestPermission(device : JUsbDevice; pi : JPendingIntent) ; cdecl; overload;// (Landroid/hardware/usb/UsbDevice;Landroid/app/PendingIntent;)V A: $1 58 | end; 59 | 60 | TJUsbManager = class(TJavaGenericImport) 61 | end; 62 | 63 | const 64 | TJUsbManagerACTION_USB_DEVICE_ATTACHED = 'android.hardware.usb.action.USB_DEVICE_ATTACHED'; 65 | TJUsbManagerACTION_USB_DEVICE_DETACHED = 'android.hardware.usb.action.USB_DEVICE_DETACHED'; 66 | TJUsbManagerACTION_USB_ACCESSORY_ATTACHED = 'android.hardware.usb.action.USB_ACCESSORY_ATTACHED'; 67 | TJUsbManagerACTION_USB_ACCESSORY_DETACHED = 'android.hardware.usb.action.USB_ACCESSORY_DETACHED'; 68 | TJUsbManagerEXTRA_DEVICE = 'device'; 69 | TJUsbManagerEXTRA_ACCESSORY = 'accessory'; 70 | TJUsbManagerEXTRA_PERMISSION_GRANTED = 'permission'; 71 | 72 | implementation 73 | 74 | end. 75 | -------------------------------------------------------------------------------- /AndroidUSBHeaders/__history/android.hardware.usb.UsbManager.pas.~1~: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by JavaToPas v1.5 20140918 - 093132 3 | //////////////////////////////////////////////////////////////////////////////// 4 | unit android.hardware.usb.UsbManager; 5 | 6 | interface 7 | 8 | uses 9 | AndroidAPI.JNIBridge, 10 | Androidapi.JNI.JavaTypes, 11 | android.hardware.usb.UsbDeviceConnection, 12 | android.hardware.usb.UsbDevice, 13 | android.hardware.usb.UsbAccessory, 14 | Androidapi.JNI.os, 15 | Androidapi.JNI.App; 16 | // android.app.PendingIntent; 17 | 18 | 19 | type 20 | JUsbManager = interface; 21 | 22 | JUsbManagerClass = interface(JObjectClass) 23 | ['{4FC84AA6-1E8D-46D2-B850-828F4E897D3F}'] 24 | function _GetACTION_USB_ACCESSORY_ATTACHED : JString; cdecl; // A: $19 25 | function _GetACTION_USB_ACCESSORY_DETACHED : JString; cdecl; // A: $19 26 | function _GetACTION_USB_DEVICE_ATTACHED : JString; cdecl; // A: $19 27 | function _GetACTION_USB_DEVICE_DETACHED : JString; cdecl; // A: $19 28 | function _GetEXTRA_ACCESSORY : JString; cdecl; // A: $19 29 | function _GetEXTRA_DEVICE : JString; cdecl; // A: $19 30 | function _GetEXTRA_PERMISSION_GRANTED : JString; cdecl; // A: $19 31 | function getAccessoryList : TJavaArray; cdecl; // ()[Landroid/hardware/usb/UsbAccessory; A: $1 32 | function getDeviceList : JHashMap; cdecl; // ()Ljava/util/HashMap; A: $1 33 | function hasPermission(accessory : JUsbAccessory) : boolean; cdecl; overload;// (Landroid/hardware/usb/UsbAccessory;)Z A: $1 34 | function hasPermission(device : JUsbDevice) : boolean; cdecl; overload; // (Landroid/hardware/usb/UsbDevice;)Z A: $1 35 | function openAccessory(accessory : JUsbAccessory) : JParcelFileDescriptor; cdecl;// (Landroid/hardware/usb/UsbAccessory;)Landroid/os/ParcelFileDescriptor; A: $1 36 | function openDevice(device : JUsbDevice) : JUsbDeviceConnection; cdecl; // (Landroid/hardware/usb/UsbDevice;)Landroid/hardware/usb/UsbDeviceConnection; A: $1 37 | procedure requestPermission(accessory : JUsbAccessory; pi : JPendingIntent) ; cdecl; overload;// (Landroid/hardware/usb/UsbAccessory;Landroid/app/PendingIntent;)V A: $1 38 | procedure requestPermission(device : JUsbDevice; pi : JPendingIntent) ; cdecl; overload;// (Landroid/hardware/usb/UsbDevice;Landroid/app/PendingIntent;)V A: $1 39 | property ACTION_USB_ACCESSORY_ATTACHED : JString read _GetACTION_USB_ACCESSORY_ATTACHED;// Ljava/lang/String; A: $19 40 | property ACTION_USB_ACCESSORY_DETACHED : JString read _GetACTION_USB_ACCESSORY_DETACHED;// Ljava/lang/String; A: $19 41 | property ACTION_USB_DEVICE_ATTACHED : JString read _GetACTION_USB_DEVICE_ATTACHED;// Ljava/lang/String; A: $19 42 | property ACTION_USB_DEVICE_DETACHED : JString read _GetACTION_USB_DEVICE_DETACHED;// Ljava/lang/String; A: $19 43 | property EXTRA_ACCESSORY : JString read _GetEXTRA_ACCESSORY; // Ljava/lang/String; A: $19 44 | property EXTRA_DEVICE : JString read _GetEXTRA_DEVICE; // Ljava/lang/String; A: $19 45 | property EXTRA_PERMISSION_GRANTED : JString read _GetEXTRA_PERMISSION_GRANTED;// Ljava/lang/String; A: $19 46 | end; 47 | 48 | [JavaSignature('android/hardware/usb/UsbManager')] 49 | JUsbManager = interface(JObject) 50 | ['{A5A85A3D-0B47-4A49-82CC-F90E8A2E16C6}'] 51 | function getAccessoryList : TJavaArray; cdecl; // ()[Landroid/hardware/usb/UsbAccessory; A: $1 52 | function getDeviceList : JHashMap; cdecl; // ()Ljava/util/HashMap; A: $1 53 | function hasPermission(accessory : JUsbAccessory) : boolean; cdecl; overload;// (Landroid/hardware/usb/UsbAccessory;)Z A: $1 54 | function hasPermission(device : JUsbDevice) : boolean; cdecl; overload; // (Landroid/hardware/usb/UsbDevice;)Z A: $1 55 | function openAccessory(accessory : JUsbAccessory) : JParcelFileDescriptor; cdecl;// (Landroid/hardware/usb/UsbAccessory;)Landroid/os/ParcelFileDescriptor; A: $1 56 | function openDevice(device : JUsbDevice) : JUsbDeviceConnection; cdecl; // (Landroid/hardware/usb/UsbDevice;)Landroid/hardware/usb/UsbDeviceConnection; A: $1 57 | procedure requestPermission(accessory : JUsbAccessory; pi : JPendingIntent) ; cdecl; overload;// (Landroid/hardware/usb/UsbAccessory;Landroid/app/PendingIntent;)V A: $1 58 | procedure requestPermission(device : JUsbDevice; pi : JPendingIntent) ; cdecl; overload;// (Landroid/hardware/usb/UsbDevice;Landroid/app/PendingIntent;)V A: $1 59 | end; 60 | 61 | TJUsbManager = class(TJavaGenericImport) 62 | end; 63 | 64 | const 65 | TJUsbManagerACTION_USB_DEVICE_ATTACHED = 'android.hardware.usb.action.USB_DEVICE_ATTACHED'; 66 | TJUsbManagerACTION_USB_DEVICE_DETACHED = 'android.hardware.usb.action.USB_DEVICE_DETACHED'; 67 | TJUsbManagerACTION_USB_ACCESSORY_ATTACHED = 'android.hardware.usb.action.USB_ACCESSORY_ATTACHED'; 68 | TJUsbManagerACTION_USB_ACCESSORY_DETACHED = 'android.hardware.usb.action.USB_ACCESSORY_DETACHED'; 69 | TJUsbManagerEXTRA_DEVICE = 'device'; 70 | TJUsbManagerEXTRA_ACCESSORY = 'accessory'; 71 | TJUsbManagerEXTRA_PERMISSION_GRANTED = 'permission'; 72 | 73 | implementation 74 | 75 | end. 76 | -------------------------------------------------------------------------------- /AndroidUSBHeaders/android.hardware.usb.UsbDeviceConnection.pas: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by JavaToPas v1.5 20140918 - 093132 3 | //////////////////////////////////////////////////////////////////////////////// 4 | unit android.hardware.usb.UsbDeviceConnection; 5 | 6 | interface 7 | 8 | uses 9 | AndroidAPI.JNIBridge, 10 | Androidapi.JNI.JavaTypes, 11 | android.hardware.usb.UsbInterface, 12 | android.hardware.usb.UsbEndpoint; 13 | 14 | type 15 | JUsbRequest = interface; // merged 16 | JUsbDeviceConnection = interface; 17 | 18 | JUsbDeviceConnectionClass = interface(JObjectClass) 19 | ['{74BC41F4-07BC-431C-BC50-22DE40E287A9}'] 20 | function bulkTransfer(endpoint : JUsbEndpoint; buffer : TJavaArray; length : Integer; timeout : Integer) : Integer; cdecl; overload;// (Landroid/hardware/usb/UsbEndpoint;[BII)I A: $1 21 | function bulkTransfer(endpoint : JUsbEndpoint; buffer : TJavaArray; offset : Integer; length : Integer; timeout : Integer) : Integer; cdecl; overload;// (Landroid/hardware/usb/UsbEndpoint;[BIII)I A: $1 22 | function claimInterface(intf : JUsbInterface; force : boolean) : boolean; cdecl;// (Landroid/hardware/usb/UsbInterface;Z)Z A: $1 23 | function controlTransfer(requestType : Integer; request : Integer; value : Integer; &index : Integer; buffer : TJavaArray; length : Integer; timeout : Integer) : Integer; cdecl; overload;// (IIII[BII)I A: $1 24 | function controlTransfer(requestType : Integer; request : Integer; value : Integer; &index : Integer; buffer : TJavaArray; offset : Integer; length : Integer; timeout : Integer) : Integer; cdecl; overload;// (IIII[BIII)I A: $1 25 | function getFileDescriptor : Integer; cdecl; // ()I A: $1 26 | function getRawDescriptors : TJavaArray; cdecl; // ()[B A: $1 27 | function getSerial : JString; cdecl; // ()Ljava/lang/String; A: $1 28 | function releaseInterface(intf : JUsbInterface) : boolean; cdecl; // (Landroid/hardware/usb/UsbInterface;)Z A: $1 29 | function requestWait : JUsbRequest; cdecl; // ()Landroid/hardware/usb/UsbRequest; A: $1 30 | procedure close ; cdecl; // ()V A: $1 31 | end; 32 | 33 | [JavaSignature('android/hardware/usb/UsbDeviceConnection')] 34 | JUsbDeviceConnection = interface(JObject) 35 | ['{8E5EFAEF-10A2-482F-8862-F8056786D1B9}'] 36 | function bulkTransfer(endpoint : JUsbEndpoint; buffer : TJavaArray; length : Integer; timeout : Integer) : Integer; cdecl; overload;// (Landroid/hardware/usb/UsbEndpoint;[BII)I A: $1 37 | function bulkTransfer(endpoint : JUsbEndpoint; buffer : TJavaArray; offset : Integer; length : Integer; timeout : Integer) : Integer; cdecl; overload;// (Landroid/hardware/usb/UsbEndpoint;[BIII)I A: $1 38 | function claimInterface(intf : JUsbInterface; force : boolean) : boolean; cdecl;// (Landroid/hardware/usb/UsbInterface;Z)Z A: $1 39 | function controlTransfer(requestType : Integer; request : Integer; value : Integer; &index : Integer; buffer : TJavaArray; length : Integer; timeout : Integer) : Integer; cdecl; overload;// (IIII[BII)I A: $1 40 | function controlTransfer(requestType : Integer; request : Integer; value : Integer; &index : Integer; buffer : TJavaArray; offset : Integer; length : Integer; timeout : Integer) : Integer; cdecl; overload;// (IIII[BIII)I A: $1 41 | function getFileDescriptor : Integer; cdecl; // ()I A: $1 42 | function getRawDescriptors : TJavaArray; cdecl; // ()[B A: $1 43 | function getSerial : JString; cdecl; // ()Ljava/lang/String; A: $1 44 | function releaseInterface(intf : JUsbInterface) : boolean; cdecl; // (Landroid/hardware/usb/UsbInterface;)Z A: $1 45 | function requestWait : JUsbRequest; cdecl; // ()Landroid/hardware/usb/UsbRequest; A: $1 46 | procedure close ; cdecl; // ()V A: $1 47 | end; 48 | 49 | TJUsbDeviceConnection = class(TJavaGenericImport) 50 | end; 51 | 52 | // Merged from: .\android-19\android.hardware.usb.UsbRequest.pas 53 | JUsbRequestClass = interface(JObjectClass) 54 | ['{2D0D4B19-E476-417D-B7E1-C209650DD3BB}'] 55 | function cancel : boolean; cdecl; // ()Z A: $1 56 | function getClientData : JObject; cdecl; // ()Ljava/lang/Object; A: $1 57 | function getEndpoint : JUsbEndpoint; cdecl; // ()Landroid/hardware/usb/UsbEndpoint; A: $1 58 | function init : JUsbRequest; cdecl; // ()V A: $1 59 | function initialize(connection : JUsbDeviceConnection; endpoint : JUsbEndpoint) : boolean; cdecl;// (Landroid/hardware/usb/UsbDeviceConnection;Landroid/hardware/usb/UsbEndpoint;)Z A: $1 60 | function queue(buffer : JByteBuffer; length : Integer) : boolean; cdecl; // (Ljava/nio/ByteBuffer;I)Z A: $1 61 | procedure close ; cdecl; // ()V A: $1 62 | procedure setClientData(data : JObject) ; cdecl; // (Ljava/lang/Object;)V A: $1 63 | end; 64 | 65 | [JavaSignature('android/hardware/usb/UsbRequest')] 66 | JUsbRequest = interface(JObject) 67 | ['{BBCFD8A0-6F88-48AE-B012-B4EB489C2E4A}'] 68 | function cancel : boolean; cdecl; // ()Z A: $1 69 | function getClientData : JObject; cdecl; // ()Ljava/lang/Object; A: $1 70 | function getEndpoint : JUsbEndpoint; cdecl; // ()Landroid/hardware/usb/UsbEndpoint; A: $1 71 | function initialize(connection : JUsbDeviceConnection; endpoint : JUsbEndpoint) : boolean; cdecl;// (Landroid/hardware/usb/UsbDeviceConnection;Landroid/hardware/usb/UsbEndpoint;)Z A: $1 72 | function queue(buffer : JByteBuffer; length : Integer) : boolean; cdecl; // (Ljava/nio/ByteBuffer;I)Z A: $1 73 | procedure close ; cdecl; // ()V A: $1 74 | procedure setClientData(data : JObject) ; cdecl; // (Ljava/lang/Object;)V A: $1 75 | end; 76 | 77 | TJUsbRequest = class(TJavaGenericImport) 78 | end; 79 | 80 | 81 | implementation 82 | 83 | end. 84 | -------------------------------------------------------------------------------- /AndroidUSBHeaders/android.hardware.usb.UsbConstants.pas: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by JavaToPas v1.5 20140918 - 093132 3 | //////////////////////////////////////////////////////////////////////////////// 4 | unit android.hardware.usb.UsbConstants; 5 | 6 | interface 7 | 8 | uses 9 | AndroidAPI.JNIBridge, 10 | Androidapi.JNI.JavaTypes; 11 | 12 | type 13 | JUsbConstants = interface; 14 | 15 | JUsbConstantsClass = interface(JObjectClass) 16 | ['{248A5772-6972-487D-B445-5DBFD7845E56}'] 17 | function _GetUSB_CLASS_APP_SPEC : Integer; cdecl; // A: $19 18 | function _GetUSB_CLASS_AUDIO : Integer; cdecl; // A: $19 19 | function _GetUSB_CLASS_CDC_DATA : Integer; cdecl; // A: $19 20 | function _GetUSB_CLASS_COMM : Integer; cdecl; // A: $19 21 | function _GetUSB_CLASS_CONTENT_SEC : Integer; cdecl; // A: $19 22 | function _GetUSB_CLASS_CSCID : Integer; cdecl; // A: $19 23 | function _GetUSB_CLASS_HID : Integer; cdecl; // A: $19 24 | function _GetUSB_CLASS_HUB : Integer; cdecl; // A: $19 25 | function _GetUSB_CLASS_MASS_STORAGE : Integer; cdecl; // A: $19 26 | function _GetUSB_CLASS_MISC : Integer; cdecl; // A: $19 27 | function _GetUSB_CLASS_PER_INTERFACE : Integer; cdecl; // A: $19 28 | function _GetUSB_CLASS_PHYSICA : Integer; cdecl; // A: $19 29 | function _GetUSB_CLASS_PRINTER : Integer; cdecl; // A: $19 30 | function _GetUSB_CLASS_STILL_IMAGE : Integer; cdecl; // A: $19 31 | function _GetUSB_CLASS_VENDOR_SPEC : Integer; cdecl; // A: $19 32 | function _GetUSB_CLASS_VIDEO : Integer; cdecl; // A: $19 33 | function _GetUSB_CLASS_WIRELESS_CONTROLLER : Integer; cdecl; // A: $19 34 | function _GetUSB_DIR_IN : Integer; cdecl; // A: $19 35 | function _GetUSB_DIR_OUT : Integer; cdecl; // A: $19 36 | function _GetUSB_ENDPOINT_DIR_MASK : Integer; cdecl; // A: $19 37 | function _GetUSB_ENDPOINT_NUMBER_MASK : Integer; cdecl; // A: $19 38 | function _GetUSB_ENDPOINT_XFERTYPE_MASK : Integer; cdecl; // A: $19 39 | function _GetUSB_ENDPOINT_XFER_BULK : Integer; cdecl; // A: $19 40 | function _GetUSB_ENDPOINT_XFER_CONTROL : Integer; cdecl; // A: $19 41 | function _GetUSB_ENDPOINT_XFER_INT : Integer; cdecl; // A: $19 42 | function _GetUSB_ENDPOINT_XFER_ISOC : Integer; cdecl; // A: $19 43 | function _GetUSB_INTERFACE_SUBCLASS_BOOT : Integer; cdecl; // A: $19 44 | function _GetUSB_SUBCLASS_VENDOR_SPEC : Integer; cdecl; // A: $19 45 | function _GetUSB_TYPE_CLASS : Integer; cdecl; // A: $19 46 | function _GetUSB_TYPE_MASK : Integer; cdecl; // A: $19 47 | function _GetUSB_TYPE_RESERVED : Integer; cdecl; // A: $19 48 | function _GetUSB_TYPE_STANDARD : Integer; cdecl; // A: $19 49 | function _GetUSB_TYPE_VENDOR : Integer; cdecl; // A: $19 50 | function init : JUsbConstants; cdecl; // ()V A: $1 51 | property USB_CLASS_APP_SPEC : Integer read _GetUSB_CLASS_APP_SPEC; // I A: $19 52 | property USB_CLASS_AUDIO : Integer read _GetUSB_CLASS_AUDIO; // I A: $19 53 | property USB_CLASS_CDC_DATA : Integer read _GetUSB_CLASS_CDC_DATA; // I A: $19 54 | property USB_CLASS_COMM : Integer read _GetUSB_CLASS_COMM; // I A: $19 55 | property USB_CLASS_CONTENT_SEC : Integer read _GetUSB_CLASS_CONTENT_SEC; // I A: $19 56 | property USB_CLASS_CSCID : Integer read _GetUSB_CLASS_CSCID; // I A: $19 57 | property USB_CLASS_HID : Integer read _GetUSB_CLASS_HID; // I A: $19 58 | property USB_CLASS_HUB : Integer read _GetUSB_CLASS_HUB; // I A: $19 59 | property USB_CLASS_MASS_STORAGE : Integer read _GetUSB_CLASS_MASS_STORAGE; // I A: $19 60 | property USB_CLASS_MISC : Integer read _GetUSB_CLASS_MISC; // I A: $19 61 | property USB_CLASS_PER_INTERFACE : Integer read _GetUSB_CLASS_PER_INTERFACE;// I A: $19 62 | property USB_CLASS_PHYSICA : Integer read _GetUSB_CLASS_PHYSICA; // I A: $19 63 | property USB_CLASS_PRINTER : Integer read _GetUSB_CLASS_PRINTER; // I A: $19 64 | property USB_CLASS_STILL_IMAGE : Integer read _GetUSB_CLASS_STILL_IMAGE; // I A: $19 65 | property USB_CLASS_VENDOR_SPEC : Integer read _GetUSB_CLASS_VENDOR_SPEC; // I A: $19 66 | property USB_CLASS_VIDEO : Integer read _GetUSB_CLASS_VIDEO; // I A: $19 67 | property USB_CLASS_WIRELESS_CONTROLLER : Integer read _GetUSB_CLASS_WIRELESS_CONTROLLER;// I A: $19 68 | property USB_DIR_IN : Integer read _GetUSB_DIR_IN; // I A: $19 69 | property USB_DIR_OUT : Integer read _GetUSB_DIR_OUT; // I A: $19 70 | property USB_ENDPOINT_DIR_MASK : Integer read _GetUSB_ENDPOINT_DIR_MASK; // I A: $19 71 | property USB_ENDPOINT_NUMBER_MASK : Integer read _GetUSB_ENDPOINT_NUMBER_MASK;// I A: $19 72 | property USB_ENDPOINT_XFERTYPE_MASK : Integer read _GetUSB_ENDPOINT_XFERTYPE_MASK;// I A: $19 73 | property USB_ENDPOINT_XFER_BULK : Integer read _GetUSB_ENDPOINT_XFER_BULK; // I A: $19 74 | property USB_ENDPOINT_XFER_CONTROL : Integer read _GetUSB_ENDPOINT_XFER_CONTROL;// I A: $19 75 | property USB_ENDPOINT_XFER_INT : Integer read _GetUSB_ENDPOINT_XFER_INT; // I A: $19 76 | property USB_ENDPOINT_XFER_ISOC : Integer read _GetUSB_ENDPOINT_XFER_ISOC; // I A: $19 77 | property USB_INTERFACE_SUBCLASS_BOOT : Integer read _GetUSB_INTERFACE_SUBCLASS_BOOT;// I A: $19 78 | property USB_SUBCLASS_VENDOR_SPEC : Integer read _GetUSB_SUBCLASS_VENDOR_SPEC;// I A: $19 79 | property USB_TYPE_CLASS : Integer read _GetUSB_TYPE_CLASS; // I A: $19 80 | property USB_TYPE_MASK : Integer read _GetUSB_TYPE_MASK; // I A: $19 81 | property USB_TYPE_RESERVED : Integer read _GetUSB_TYPE_RESERVED; // I A: $19 82 | property USB_TYPE_STANDARD : Integer read _GetUSB_TYPE_STANDARD; // I A: $19 83 | property USB_TYPE_VENDOR : Integer read _GetUSB_TYPE_VENDOR; // I A: $19 84 | end; 85 | 86 | [JavaSignature('android/hardware/usb/UsbConstants')] 87 | JUsbConstants = interface(JObject) 88 | ['{FD72DE34-694B-4F95-A348-34D893AA5F4C}'] 89 | end; 90 | 91 | TJUsbConstants = class(TJavaGenericImport) 92 | end; 93 | 94 | const 95 | TJUsbConstantsUSB_ENDPOINT_DIR_MASK = 128; 96 | TJUsbConstantsUSB_DIR_OUT = 0; 97 | TJUsbConstantsUSB_DIR_IN = 128; 98 | TJUsbConstantsUSB_ENDPOINT_NUMBER_MASK = 15; 99 | TJUsbConstantsUSB_ENDPOINT_XFERTYPE_MASK = 3; 100 | TJUsbConstantsUSB_ENDPOINT_XFER_CONTROL = 0; 101 | TJUsbConstantsUSB_ENDPOINT_XFER_ISOC = 1; 102 | TJUsbConstantsUSB_ENDPOINT_XFER_BULK = 2; 103 | TJUsbConstantsUSB_ENDPOINT_XFER_INT = 3; 104 | TJUsbConstantsUSB_TYPE_MASK = 96; 105 | TJUsbConstantsUSB_TYPE_STANDARD = 0; 106 | TJUsbConstantsUSB_TYPE_CLASS = 32; 107 | TJUsbConstantsUSB_TYPE_VENDOR = 64; 108 | TJUsbConstantsUSB_TYPE_RESERVED = 96; 109 | TJUsbConstantsUSB_CLASS_PER_INTERFACE = 0; 110 | TJUsbConstantsUSB_CLASS_AUDIO = 1; 111 | TJUsbConstantsUSB_CLASS_COMM = 2; 112 | TJUsbConstantsUSB_CLASS_HID = 3; 113 | TJUsbConstantsUSB_CLASS_PHYSICA = 5; 114 | TJUsbConstantsUSB_CLASS_STILL_IMAGE = 6; 115 | TJUsbConstantsUSB_CLASS_PRINTER = 7; 116 | TJUsbConstantsUSB_CLASS_MASS_STORAGE = 8; 117 | TJUsbConstantsUSB_CLASS_HUB = 9; 118 | TJUsbConstantsUSB_CLASS_CDC_DATA = 10; 119 | TJUsbConstantsUSB_CLASS_CSCID = 11; 120 | TJUsbConstantsUSB_CLASS_CONTENT_SEC = 13; 121 | TJUsbConstantsUSB_CLASS_VIDEO = 14; 122 | TJUsbConstantsUSB_CLASS_WIRELESS_CONTROLLER = 224; 123 | TJUsbConstantsUSB_CLASS_MISC = 239; 124 | TJUsbConstantsUSB_CLASS_APP_SPEC = 254; 125 | TJUsbConstantsUSB_CLASS_VENDOR_SPEC = 255; 126 | TJUsbConstantsUSB_INTERFACE_SUBCLASS_BOOT = 1; 127 | TJUsbConstantsUSB_SUBCLASS_VENDOR_SPEC = 255; 128 | 129 | implementation 130 | 131 | end. 132 | -------------------------------------------------------------------------------- /AndroidHeaders/android.app.PendingIntent.pas: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by JavaToPas v1.5 20140918 - 093101 3 | //////////////////////////////////////////////////////////////////////////////// 4 | unit android.app.PendingIntent; 5 | 6 | interface 7 | 8 | uses 9 | AndroidAPI.JNIBridge, 10 | Androidapi.JNI.JavaTypes, 11 | Androidapi.JNI.os, 12 | Androidapi.JNI.GraphicsContentViewText; 13 | //android.content.ClipData, 14 | //android.content.IntentSender; 15 | 16 | type 17 | JPendingIntent_OnFinished = interface; // merged 18 | JPendingIntent = interface; 19 | 20 | JPendingIntentClass = interface(JObjectClass) 21 | ['{840B8629-44C8-41FC-B5D2-41894DE3E596}'] 22 | function _GetCREATOR : JParcelable_Creator; cdecl; // A: $19 23 | function _GetFLAG_CANCEL_CURRENT : Integer; cdecl; // A: $19 24 | function _GetFLAG_NO_CREATE : Integer; cdecl; // A: $19 25 | function _GetFLAG_ONE_SHOT : Integer; cdecl; // A: $19 26 | function _GetFLAG_UPDATE_CURRENT : Integer; cdecl; // A: $19 27 | function describeContents : Integer; cdecl; // ()I A: $1 28 | function equals(otherObj : JObject) : boolean; cdecl; // (Ljava/lang/Object;)Z A: $1 29 | function getActivities(context : JContext; requestCode : Integer; intents : TJavaArray; flags : Integer) : JPendingIntent; cdecl; overload;// (Landroid/content/Context;I[Landroid/content/Intent;I)Landroid/app/PendingIntent; A: $9 30 | function getActivities(context : JContext; requestCode : Integer; intents : TJavaArray; flags : Integer; options : JBundle) : JPendingIntent; cdecl; overload;// (Landroid/content/Context;I[Landroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/PendingIntent; A: $9 31 | function getActivity(context : JContext; requestCode : Integer; intent : JIntent; flags : Integer) : JPendingIntent; cdecl; overload;// (Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent; A: $9 32 | function getActivity(context : JContext; requestCode : Integer; intent : JIntent; flags : Integer; options : JBundle) : JPendingIntent; cdecl; overload;// (Landroid/content/Context;ILandroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/PendingIntent; A: $9 33 | function getBroadcast(context : JContext; requestCode : Integer; intent : JIntent; flags : Integer) : JPendingIntent; cdecl;// (Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent; A: $9 34 | function getCreatorPackage : JString; cdecl; // ()Ljava/lang/String; A: $1 35 | function getCreatorUid : Integer; cdecl; // ()I A: $1 36 | function getCreatorUserHandle : JUserHandle; cdecl; // ()Landroid/os/UserHandle; A: $1 37 | function getIntentSender : JIntentSender; cdecl; // ()Landroid/content/IntentSender; A: $1 38 | function getService(context : JContext; requestCode : Integer; intent : JIntent; flags : Integer) : JPendingIntent; cdecl;// (Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent; A: $9 39 | function getTargetPackage : JString; deprecated; cdecl; // ()Ljava/lang/String; A: $1 40 | function hashCode : Integer; cdecl; // ()I A: $1 41 | function readPendingIntentOrNullFromParcel(&in : JParcel) : JPendingIntent; cdecl;// (Landroid/os/Parcel;)Landroid/app/PendingIntent; A: $9 42 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 43 | procedure cancel ; cdecl; // ()V A: $1 44 | procedure send ; cdecl; overload; // ()V A: $1 45 | procedure send(code : Integer) ; cdecl; overload; // (I)V A: $1 46 | procedure send(code : Integer; onFinished : JPendingIntent_OnFinished; handler : JHandler) ; cdecl; overload;// (ILandroid/app/PendingIntent$OnFinished;Landroid/os/Handler;)V A: $1 47 | procedure send(context : JContext; code : Integer; intent : JIntent) ; cdecl; overload;// (Landroid/content/Context;ILandroid/content/Intent;)V A: $1 48 | procedure send(context : JContext; code : Integer; intent : JIntent; onFinished : JPendingIntent_OnFinished; handler : JHandler) ; cdecl; overload;// (Landroid/content/Context;ILandroid/content/Intent;Landroid/app/PendingIntent$OnFinished;Landroid/os/Handler;)V A: $1 49 | procedure send(context : JContext; code : Integer; intent : JIntent; onFinished : JPendingIntent_OnFinished; handler : JHandler; requiredPermission : JString) ; cdecl; overload;// (Landroid/content/Context;ILandroid/content/Intent;Landroid/app/PendingIntent$OnFinished;Landroid/os/Handler;Ljava/lang/String;)V A: $1 50 | procedure writePendingIntentOrNullToParcel(sender : JPendingIntent; &out : JParcel) ; cdecl;// (Landroid/app/PendingIntent;Landroid/os/Parcel;)V A: $9 51 | procedure writeToParcel(&out : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 52 | property CREATOR : JParcelable_Creator read _GetCREATOR; // Landroid/os/Parcelable$Creator; A: $19 53 | property FLAG_CANCEL_CURRENT : Integer read _GetFLAG_CANCEL_CURRENT; // I A: $19 54 | property FLAG_NO_CREATE : Integer read _GetFLAG_NO_CREATE; // I A: $19 55 | property FLAG_ONE_SHOT : Integer read _GetFLAG_ONE_SHOT; // I A: $19 56 | property FLAG_UPDATE_CURRENT : Integer read _GetFLAG_UPDATE_CURRENT; // I A: $19 57 | end; 58 | 59 | [JavaSignature('android/app/PendingIntent$OnFinished')] 60 | JPendingIntent = interface(JObject) 61 | ['{3B0E7CA4-4C68-4003-AE0A-E5ABDE85C8B4}'] 62 | function describeContents : Integer; cdecl; // ()I A: $1 63 | function equals(otherObj : JObject) : boolean; cdecl; // (Ljava/lang/Object;)Z A: $1 64 | function getCreatorPackage : JString; cdecl; // ()Ljava/lang/String; A: $1 65 | function getCreatorUid : Integer; cdecl; // ()I A: $1 66 | function getCreatorUserHandle : JUserHandle; cdecl; // ()Landroid/os/UserHandle; A: $1 67 | function getIntentSender : JIntentSender; cdecl; // ()Landroid/content/IntentSender; A: $1 68 | function getTargetPackage : JString; deprecated; cdecl; // ()Ljava/lang/String; A: $1 69 | function hashCode : Integer; cdecl; // ()I A: $1 70 | function toString : JString; cdecl; // ()Ljava/lang/String; A: $1 71 | procedure cancel ; cdecl; // ()V A: $1 72 | procedure send ; cdecl; overload; // ()V A: $1 73 | procedure send(code : Integer) ; cdecl; overload; // (I)V A: $1 74 | procedure send(code : Integer; onFinished : JPendingIntent_OnFinished; handler : JHandler) ; cdecl; overload;// (ILandroid/app/PendingIntent$OnFinished;Landroid/os/Handler;)V A: $1 75 | procedure send(context : JContext; code : Integer; intent : JIntent) ; cdecl; overload;// (Landroid/content/Context;ILandroid/content/Intent;)V A: $1 76 | procedure send(context : JContext; code : Integer; intent : JIntent; onFinished : JPendingIntent_OnFinished; handler : JHandler) ; cdecl; overload;// (Landroid/content/Context;ILandroid/content/Intent;Landroid/app/PendingIntent$OnFinished;Landroid/os/Handler;)V A: $1 77 | procedure send(context : JContext; code : Integer; intent : JIntent; onFinished : JPendingIntent_OnFinished; handler : JHandler; requiredPermission : JString) ; cdecl; overload;// (Landroid/content/Context;ILandroid/content/Intent;Landroid/app/PendingIntent$OnFinished;Landroid/os/Handler;Ljava/lang/String;)V A: $1 78 | procedure writeToParcel(&out : JParcel; flags : Integer) ; cdecl; // (Landroid/os/Parcel;I)V A: $1 79 | end; 80 | 81 | TJPendingIntent = class(TJavaGenericImport) 82 | end; 83 | 84 | // Merged from: .\android-19\android.app.PendingIntent_OnFinished.pas 85 | JPendingIntent_OnFinishedClass = interface(JObjectClass) 86 | ['{EED42D9E-090A-48BE-9F8D-F9272589BE00}'] 87 | procedure onSendFinished(JPendingIntentparam0 : JPendingIntent; JIntentparam1 : JIntent; Integerparam2 : Integer; JStringparam3 : JString; JBundleparam4 : JBundle) ; cdecl;// (Landroid/app/PendingIntent;Landroid/content/Intent;ILjava/lang/String;Landroid/os/Bundle;)V A: $401 88 | end; 89 | 90 | [JavaSignature('android/app/PendingIntent_OnFinished')] 91 | JPendingIntent_OnFinished = interface(JObject) 92 | ['{471C0779-A0D7-4453-9C9B-C2A81FE6499B}'] 93 | procedure onSendFinished(JPendingIntentparam0 : JPendingIntent; JIntentparam1 : JIntent; Integerparam2 : Integer; JStringparam3 : JString; JBundleparam4 : JBundle) ; cdecl;// (Landroid/app/PendingIntent;Landroid/content/Intent;ILjava/lang/String;Landroid/os/Bundle;)V A: $401 94 | end; 95 | 96 | TJPendingIntent_OnFinished = class(TJavaGenericImport) 97 | end; 98 | 99 | 100 | const 101 | TJPendingIntentFLAG_ONE_SHOT = 1073741824; 102 | TJPendingIntentFLAG_NO_CREATE = 536870912; 103 | TJPendingIntentFLAG_CANCEL_CURRENT = 268435456; 104 | TJPendingIntentFLAG_UPDATE_CURRENT = 134217728; 105 | 106 | implementation 107 | 108 | end. 109 | -------------------------------------------------------------------------------- /USB2.pas: -------------------------------------------------------------------------------- 1 | unit USB2; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Classes,System.SyncObjs,Generics.Collections,System.DateUtils,System.Types, 7 | {$IFDEF ANDROID} 8 | android.hardware.usb.HID 9 | {$ENDIF} 10 | ; 11 | 12 | const 13 | INIFILENAME = 'settings.ini'; 14 | 15 | type 16 | TReport = packed record 17 | ReportID: byte; 18 | Data: array [0..15] of byte; 19 | //Data: array of byte; 20 | end; 21 | 22 | TUSBController = class(TObject) 23 | HidCtrl : TJvHidDevice; 24 | FaultCounter : word; 25 | Serial : string; 26 | LocalDataTimer: TEvent; 27 | LocalData : TReport; 28 | public 29 | constructor Create(HidDev: TJvHidDevice); 30 | destructor Destroy; 31 | procedure ShowRead(HidDev: TJvHidDevice; ReportID: Byte;const Data: Pointer; Size: Word); 32 | end; 33 | 34 | TUSBList = TObjectList; 35 | 36 | TUSBEvent = procedure(Sender: TObject;datacarrier:integer) of object; 37 | 38 | TUSB=class 39 | private 40 | HidCtl:TJvHidDeviceController; 41 | 42 | AUSBList : TUSBList; 43 | 44 | FErrors:TStringList; 45 | FInfo:TStringList; 46 | FEmulation:boolean; 47 | 48 | FEnabled: Boolean; 49 | 50 | MaxErrors:word; 51 | 52 | FOnUSBDeviceChange: TUSBEvent; 53 | 54 | FIniFileFullPath:string; 55 | 56 | MaxPositions:word; 57 | 58 | procedure AddErrors(data:string); 59 | function GetErrors:String; 60 | procedure AddInfo(data:string); 61 | function GetInfo:String; 62 | procedure SetEnabled(Value: Boolean); 63 | 64 | function HidReadWrite(Ctrl: TUSBController; ReadOnly:boolean):boolean; 65 | 66 | procedure DeviceArrival(HidDev: TJvHidDevice); 67 | procedure DeviceRemoval(HidDev: TJvHidDevice); 68 | procedure DeviceChange(Sender:TObject); 69 | 70 | function CheckAddressNewer(Ctrl: TUSBController):integer; 71 | function CheckParameters(board:word):boolean;overload; 72 | 73 | function ReadSerial(Ctrl: TUSBController):string; 74 | 75 | procedure HandleCRCError(HidCtrl: TJvHidDevice);overload; 76 | 77 | function FGetSerial(board:word):string; 78 | public 79 | constructor Create; 80 | destructor Destroy;override; 81 | 82 | property Emulation:boolean read FEmulation; 83 | 84 | property Errors:String read GetErrors; 85 | property Info:String read GetInfo; 86 | 87 | property Enabled: Boolean read FEnabled write SetEnabled; 88 | 89 | property OnUSBDeviceChange: TUSBEvent read FOnUSBDeviceChange write FOnUSBDeviceChange; 90 | 91 | property GetSerial[board: word]: string read FGetSerial; 92 | 93 | property Controller:TJvHidDeviceController read HidCtl; 94 | end; 95 | 96 | 97 | implementation 98 | 99 | uses 100 | System.IOUtils, 101 | IniFiles, 102 | StrUtils; 103 | 104 | type 105 | TCommands = ( 106 | CMD_get_serial=100, 107 | CMD_set_serial=101 108 | ); 109 | 110 | const 111 | Vendor = $04D8; 112 | Product = $003F; 113 | 114 | ErrorDelay = 100; 115 | USBTimeout = 2000; 116 | 117 | constructor TUSBController.Create(HidDev: TJvHidDevice); 118 | begin 119 | Inherited Create; 120 | HidCtrl:=HidDev; 121 | LocalDataTimer:=TEvent.Create(nil, true, false, ''); 122 | LocalDataTimer.ResetEvent; 123 | if HidCtrl<>nil then 124 | begin 125 | //disable for now on Android !! 126 | HidCtrl.OnData:=nil; 127 | //HidCtrl.OnData:=ShowRead; 128 | end; 129 | end; 130 | 131 | destructor TUSBController.Destroy; 132 | begin 133 | HidCtrl.OnData:=nil; 134 | LocalDataTimer.Free; 135 | Inherited Destroy; 136 | end; 137 | 138 | procedure TUSBController.ShowRead(HidDev: TJvHidDevice; ReportID: Byte;const Data: Pointer; Size: Word); 139 | var 140 | x: Integer; 141 | begin 142 | LocalData.ReportID:=ReportID; 143 | for x := Low(LocalData.Data) to High(LocalData.Data) do 144 | begin 145 | LocalData.Data[x]:=byte(PByte(Data)[x]); 146 | end; 147 | LocalDataTimer.SetEvent; 148 | end; 149 | 150 | constructor TUSB.Create; 151 | var 152 | Ini: TIniFile; 153 | x:integer; 154 | begin 155 | inherited Create; 156 | 157 | //System.IOUtils.tpath.GetDocumentsPath - /data/data/com.myapp.app1/files 158 | //System.IOUtils.tpath.GetSharedDocumentsPath - /storage/emulated/0/Android/data/com.myapp.app1/files 159 | //System.IOUtils.tpath.GetPublicPath - /storage/emulated/0/Android/data/com.myapp.app1/files 160 | //System.IOUtils.tpath.GetHomePath - /data/data/com.myapp.app1/files 161 | FIniFileFullPath:=System.IOUtils.TPath.Combine(System.IOUtils.tpath.GetHomePath,INIFILENAME); 162 | 163 | FErrors:=TStringList.Create; 164 | FInfo:=TStringList.Create; 165 | 166 | AUSBList := TUSBList.Create(false); 167 | 168 | FEmulation := True; 169 | 170 | MaxErrors := 1; 171 | 172 | Ini := TIniFile.Create(FIniFileFullPath); 173 | try 174 | MaxErrors := Ini.ReadInteger( 'General', 'NumError', MaxErrors ); 175 | finally 176 | Ini.Free; 177 | end; 178 | 179 | HidCtl:=TJvHidDeviceController.Create(nil); 180 | {$IFDEF ANDROID} 181 | HidCtl.OnDeviceChange:=DeviceChange; 182 | {$ELSE} 183 | HidCtl.OnArrival:= DeviceArrival; 184 | HidCtl.OnRemoval:= DeviceRemoval; 185 | {$ENDIF} 186 | end; 187 | 188 | destructor TUSB.Destroy; 189 | var 190 | board:word; 191 | begin 192 | if AUSBList.Count>0 then 193 | begin 194 | for board:=Pred(AUSBList.Count) downto 0 do 195 | begin 196 | if Assigned(AUSBList.Items[board].HidCtrl) then HidCtl.CheckIn(AUSBList.Items[board].HidCtrl); 197 | AUSBList.Items[board].Destroy; 198 | end; 199 | end; 200 | AUSBList.Free; 201 | 202 | HidCtl.Free; 203 | FErrors.Free; 204 | FInfo.Free; 205 | inherited Destroy; 206 | end; 207 | 208 | procedure TUSB.SetEnabled(Value: Boolean); 209 | begin 210 | if Value <> FEnabled then 211 | begin 212 | FEnabled := Value; 213 | HidCtl.Enabled:=FEnabled; 214 | end; 215 | end; 216 | 217 | function TUSB.HidReadWrite(Ctrl: TUSBController; ReadOnly:boolean):boolean; 218 | var 219 | error:boolean; 220 | Written:DWORD; 221 | x:integer; 222 | Err:DWORD; 223 | begin 224 | error:=False; 225 | 226 | if NOT Assigned(Ctrl.HidCtrl) then 227 | begin 228 | result:=False; 229 | exit; 230 | end; 231 | 232 | if Assigned(Ctrl.HidCtrl) then 233 | begin 234 | Ctrl.HidCtrl.FlushQueue; 235 | if (NOT ReadOnly) then 236 | begin 237 | if Assigned(Ctrl.HidCtrl.OnData) then Ctrl.LocalDataTimer.ResetEvent; 238 | end; 239 | error:=(NOT Ctrl.HidCtrl.WriteFile(Ctrl.LocalData, Ctrl.HidCtrl.Caps.OutputReportByteLength, Written)); 240 | if (error) then 241 | begin 242 | Err := GetLastError; 243 | AddErrors(Format('USB normal write error: %s (%x)', [SysErrorMessage(Err), Err])); 244 | end; 245 | if (NOT error) AND (NOT ReadOnly) then 246 | begin 247 | error:=True; 248 | if Assigned(Ctrl.HidCtrl.OnData) then 249 | begin 250 | if Ctrl.LocalDataTimer.WaitFor(USBTimeout) = wrSignaled 251 | then error:=False 252 | else 253 | begin 254 | FillChar(Ctrl.LocalData, SizeOf(Ctrl.LocalData), 0); 255 | AddErrors('USB thread read timeout !!'); 256 | end; 257 | end 258 | else 259 | begin 260 | error:=(NOT Ctrl.HidCtrl.ReadFile(Ctrl.LocalData, Ctrl.HidCtrl.Caps.InputReportByteLength, Written)); 261 | if error then 262 | begin 263 | FillChar(Ctrl.LocalData, SizeOf(Ctrl.LocalData), 0); 264 | Err := GetLastError; 265 | AddErrors(Format('USB normal read error: %s (%x)', [SysErrorMessage(Err), Err])); 266 | end; 267 | end; 268 | end; 269 | end; 270 | 271 | result:=error; 272 | 273 | end; 274 | 275 | 276 | procedure TUSB.DeviceRemoval(HidDev: TJvHidDevice); 277 | var 278 | board:integer; 279 | begin 280 | AddInfo('Device removal. VID: '+InttoStr(HidDev.Attributes.VendorID)+'. PID: '+InttoStr(HidDev.Attributes.ProductID)+'.'); 281 | if ((HidDev.Attributes.VendorID = Vendor) AND 282 | (HidDev.Attributes.ProductID = Product) ) then 283 | begin 284 | for board:=0 to AUSBList.Count-1 do 285 | begin 286 | if ((Assigned(AUSBList.Items[board].HidCtrl)) and (NOT AUSBList.Items[board].HidCtrl.IsPluggedIn)) then 287 | begin 288 | if Assigned(FOnUSBDeviceChange) then 289 | begin 290 | FOnUSBDeviceChange(Self,-1*board); 291 | end; 292 | AUSBList.Items[board].HidCtrl.FlushQueue; 293 | HidCtl.CheckIn(AUSBList.Items[board].HidCtrl); 294 | break; 295 | end; 296 | end; 297 | if HidCtl.NumCheckedOutDevices=0 then FEmulation:=True; 298 | end; 299 | end; 300 | 301 | procedure TUSB.DeviceArrival(HidDev: TJvHidDevice); 302 | var 303 | newboard:integer; 304 | NewUSBController : TUSBController; 305 | begin 306 | 307 | AddInfo('Device arrival. VID: '+InttoStr(HidDev.Attributes.VendorID)+'. PID: '+InttoStr(HidDev.Attributes.ProductID)+'.'); 308 | 309 | if ( (HidDev.Attributes.VendorID = Vendor) AND 310 | (HidDev.Attributes.ProductID = Product) ) then 311 | begin 312 | 313 | if HidDev.CheckOut then 314 | begin 315 | 316 | FEmulation:=False; 317 | 318 | AddInfo('I1: '+HidDev.DeviceStrings[1]); 319 | AddInfo('I2: '+HidDev.DeviceStrings[2]); 320 | AddInfo('I3: '+HidDev.DeviceStrings[3]); 321 | AddInfo('I4: '+HidDev.DeviceStrings[4]); 322 | 323 | NewUSBController := TUSBController.Create(HidDev); 324 | 325 | Sleep(200); 326 | //Setlength(NewUSBController.LocalData.Data,HidDev.Caps.InputReportByteLength); 327 | 328 | with NewUSBController do 329 | begin 330 | Serial:=''; 331 | FaultCounter:=0; 332 | end; 333 | 334 | Sleep(200); 335 | 336 | with NewUSBController do 337 | begin 338 | if HidCtrl.DeviceStrings[4]<>HidCtrl.DeviceStrings[1] then 339 | begin 340 | Serial:=HidCtrl.DeviceStrings[4]; 341 | end; 342 | end; 343 | if NewUSBController.Serial='' then ReadSerial(NewUSBController); 344 | 345 | if NewUSBController.Serial='' then 346 | begin 347 | AddInfo('Severe error while receiving serial number of controller !!!!'); 348 | exit; 349 | end; 350 | 351 | newboard:=CheckAddressNewer(NewUSBController); 352 | 353 | AddInfo('S/N of board '+InttoStr(newboard)+': '+NewUSBController.Serial); 354 | 355 | while AUSBList.Count<(newboard+1) do 356 | begin 357 | AUSBList.Add(TUSBController.Create(nil)); 358 | end; 359 | 360 | AUSBList.Items[newboard]:=NewUSBController; 361 | 362 | if Assigned(FOnUSBDeviceChange) then 363 | begin 364 | FOnUSBDeviceChange(Self,newboard); 365 | end; 366 | end; 367 | end; 368 | end; 369 | 370 | procedure TUSB.DeviceChange(Sender:TObject); 371 | var 372 | board:integer; 373 | i:integer; 374 | HidDev:TJvHidDevice; 375 | begin 376 | AddInfo('Devices change !!'); 377 | for i:=0 to HidCtl.HidDevices.Count-1 do 378 | begin 379 | HidDev:=HidCtl.HidDevices[i]; 380 | AddInfo('HID-device#'+InttoStr(i)+'. VID: '+InttoStr(HidDev.Attributes.VendorID)+'. PID: '+InttoStr(HidDev.Attributes.ProductID)+'.'); 381 | if ( (HidDev.Attributes.VendorID = Vendor) AND 382 | (HidDev.Attributes.ProductID = Product) ) then 383 | begin 384 | if HidDev.IsPluggedIn AND NOT HidDev.IsCheckedOut then 385 | begin 386 | AddInfo('New device that has not been checked out.'); 387 | DeviceArrival(HidDev); 388 | end; 389 | if NOT HidDev.IsPluggedIn AND HidDev.IsCheckedOut then 390 | begin 391 | AddInfo('Checkedout device that has been unplugged.'); 392 | DeviceRemoval(HidDev); 393 | end; 394 | end; 395 | end; 396 | end; 397 | 398 | function TUSB.CheckAddressNewer(Ctrl: TUSBController):integer; 399 | var 400 | x,y: integer; 401 | newboardnumber:word; 402 | found:boolean; 403 | 404 | RegValueNames: TStringList; 405 | 406 | dataline:string; 407 | error:boolean; 408 | ErrorCounter:word; 409 | 410 | Ini: TIniFile; 411 | begin 412 | 413 | result:=0; 414 | 415 | error:=False; 416 | 417 | if (NOT error) then 418 | begin 419 | if (Ctrl.Serial='0-0-0-0-0-0') 420 | OR 421 | (Ctrl.Serial='0000-0000-0000-0000-0000-0000') 422 | OR 423 | (Ctrl.Serial='65535-65535-65535-65535-65535-65535') 424 | OR 425 | (Ctrl.Serial='FFFF-FFFF-FFFF-FFFF-FFFF-FFFF') 426 | OR 427 | (RightStr(Ctrl.Serial,4)='FFFF') 428 | then 429 | begin 430 | ErrorCounter:=1; 431 | 432 | repeat 433 | 434 | with Ctrl do 435 | begin 436 | FillChar(LocalData, SizeOf(LocalData), 0); 437 | 438 | LocalData.Data[0] := byte(CMD_set_serial); 439 | LocalData.Data[1] := Random($FF); 440 | LocalData.Data[2] := Random($FF); 441 | LocalData.Data[3] := Random($FF); 442 | LocalData.Data[4] := Random($FF); 443 | LocalData.Data[5] := Random($FF); 444 | LocalData.Data[6] := Random($FF); 445 | LocalData.Data[7] := Random($FF); 446 | LocalData.Data[8] := Random($FF); 447 | LocalData.Data[9] := Random($FF); 448 | LocalData.Data[10] := Random($FF); 449 | LocalData.Data[11] := Random($FF); 450 | LocalData.Data[12] := Random($FF); 451 | end; 452 | error:=HidReadWrite(Ctrl,True); 453 | 454 | if (NOT error) then with Ctrl.LocalData do 455 | begin 456 | if (data[0]=byte(CMD_set_serial)) then 457 | begin 458 | Ctrl.Serial:= 459 | InttoHex(WORD(data[1]+data[2]*256),4)+'-'+ 460 | InttoHex(WORD(data[3]+data[4]*256),4)+'-'+ 461 | InttoHex(WORD(data[5]+data[6]*256),4)+'-'+ 462 | InttoHex(WORD(data[7]+data[8]*256),4)+'-'+ 463 | InttoHex(WORD(data[9]+data[10]*256),4)+'-'+ 464 | InttoHex(WORD(data[11]+data[12]*256),4); 465 | end 466 | else 467 | begin 468 | error:=True; 469 | end; 470 | end; 471 | if ( (error) AND (ErrorCounterMaxErrors) ); 474 | if error then AddErrors('Controller set serial number error'); 475 | end; 476 | end; 477 | 478 | if (NOT error) then 479 | begin 480 | found:=false; 481 | 482 | newboardnumber:=0; 483 | 484 | Ini := TIniFile.Create(FIniFileFullPath); 485 | 486 | RegValueNames:=TStringList.Create; 487 | try 488 | ini.ReadSection('USBLocations',RegValueNames); 489 | if RegValueNames.Count>0 then 490 | begin 491 | for x:=1 to RegValueNames.Count do 492 | begin 493 | If Pos('Controller',RegValueNames.Strings[x-1])>-1 then 494 | begin 495 | y:=StrToIntDef(RightStr(RegValueNames.Strings[x-1],2),0); 496 | dataline:=ini.ReadString('USBLocations',RegValueNames.Strings[x-1],''); 497 | if (dataline=Ctrl.Serial) AND (y>0) then 498 | begin 499 | found:=true; 500 | newboardnumber:=y; 501 | break; 502 | end; 503 | end; 504 | end; 505 | end; 506 | if (NOT found) then 507 | begin 508 | y:=1; 509 | while ini.ValueExists('USBLocations','Controller '+InttoStr(y)) do Inc(y); 510 | ini.WriteString('USBLocations','Controller '+InttoStr(y),Ctrl.Serial); 511 | newboardnumber:=y; 512 | end; 513 | finally 514 | RegValueNames.Free; 515 | Ini.UpdateFile; 516 | Ini.Free; 517 | end; 518 | 519 | result:=newboardnumber; 520 | end; 521 | 522 | end; 523 | 524 | procedure TUSB.HandleCRCError(HidCtrl: TJvHidDevice); 525 | begin 526 | begin 527 | //if Assigned(HidCtrl) then HidCtrl.FlushQueue; 528 | //if Assigned(HidCtrl) then HidCtrl.CloseFileEx(omhRead); 529 | //if Assigned(HidCtrl) then HidCtrl.CloseFileEx(omhWrite); 530 | end; 531 | end; 532 | 533 | function TUSB.CheckParameters(board:word):boolean; 534 | begin 535 | result:=true; 536 | if FEmulation then exit; 537 | result:=NOT ( (board0 then 543 | begin 544 | result:=FErrors.Text; 545 | FErrors.Clear; 546 | end else result:=''; 547 | end; 548 | 549 | procedure TUSB.AddInfo(data:string); 550 | begin 551 | if Length(data)>0 then 552 | begin 553 | while FInfo.Count>1000 do FInfo.Delete(0); 554 | FInfo.Append(data); 555 | end; 556 | end; 557 | 558 | function TUSB.GetInfo:String; 559 | begin 560 | if FInfo.Count>0 then 561 | begin 562 | result:=FInfo.Text; 563 | FInfo.Clear; 564 | end else result:=''; 565 | end; 566 | 567 | procedure TUSB.AddErrors(data:string); 568 | begin 569 | if length(data)>0 then 570 | begin 571 | while FErrors.Count>1000 do FErrors.Delete(0); 572 | FErrors.Append(DateTimeToStr(Now)+': '+data); 573 | end; 574 | end; 575 | 576 | function TUSB.ReadSerial(Ctrl: TUSBController):string; 577 | var 578 | error:boolean; 579 | ErrorCounter:word; 580 | begin 581 | Result:=''; 582 | 583 | ErrorCounter:=1; 584 | 585 | repeat 586 | FillChar(Ctrl.LocalData, SizeOf(Ctrl.LocalData), 0); 587 | Ctrl.LocalData.Data[0] := Integer(CMD_get_serial); 588 | 589 | error:=HidReadWrite(Ctrl,False); 590 | 591 | if (NOT error) then with Ctrl.LocalData do 592 | begin 593 | if ( data[0]=byte(CMD_get_serial) ) then 594 | begin 595 | result:= 596 | InttoHex(WORD(data[1]+data[2]*256),4)+'-'+ 597 | InttoHex(WORD(data[3]+data[4]*256),4)+'-'+ 598 | InttoHex(WORD(data[5]+data[6]*256),4)+'-'+ 599 | InttoHex(WORD(data[7]+data[8]*256),4)+'-'+ 600 | InttoHex(WORD(data[9]+data[10]*256),4)+'-'+ 601 | InttoHex(WORD(data[11]+data[12]*256),4); 602 | Ctrl.Serial:=Result; 603 | end else error:=True; 604 | end; 605 | 606 | if ( (error) AND (ErrorCounterMaxErrors) ); 610 | if error then AddErrors('Controller read serial number error'); 611 | end; 612 | 613 | function TUSB.FGetSerial(board:word):string; 614 | begin 615 | result:=''; 616 | if FEmulation then exit; 617 | if AUSBList.Count=0 then exit; 618 | if board>AUSBList.Count then exit; 619 | result:=AUSBList.Items[board].Serial; 620 | end; 621 | 622 | end. 623 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /android.hardware.usb.HID.pas: -------------------------------------------------------------------------------- 1 | unit android.hardware.usb.HID; 2 | 3 | interface 4 | 5 | {.$define WITHPERMISSION} 6 | 7 | uses 8 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Generics.Collections, 9 | 10 | Androidapi.JNI.Toast, 11 | 12 | android.hardware.usb.UsbDeviceConnection, 13 | android.hardware.usb.UsbEndpoint, 14 | android.hardware.usb.UsbManager, 15 | android.hardware.usb.UsbDevice, 16 | android.hardware.usb.UsbInterface, 17 | Androidapi.JNI.App, 18 | Androidapi.JNIBridge, 19 | Androidapi.JNI.JavaTypes, 20 | Androidapi.JNI.Embarcadero, 21 | Androidapi.JNI.GraphicsContentViewText 22 | ; 23 | 24 | type 25 | TJvHidDeviceController = class; 26 | TJvHidDevice = class; 27 | 28 | TBroadcastReceiverListener = class(TJavaLocal, JFMXBroadcastReceiverListener) 29 | private 30 | FHidDC:TJvHidDeviceController; 31 | public 32 | constructor Create(aOwner:TJvHidDeviceController); 33 | procedure onReceive(context: JContext; intent: JIntent); cdecl; 34 | property HidDC:TJvHidDeviceController read FHidDC; 35 | end; 36 | 37 | 38 | TJvHidPnPInfo = class(TObject) 39 | private 40 | FUSBDevice:JUSBDevice; 41 | FDeviceID: DWORD; 42 | FFriendlyName: string; 43 | FProductId: DWORD; 44 | FVendorId: DWORD; 45 | FDeviceClass: DWORD; 46 | FDeviceProtocol: DWORD; 47 | FDeviceSubclass: DWORD; 48 | public 49 | property DeviceID: DWORD read FDeviceID write FDeviceID; 50 | property FriendlyName: string read FFriendlyName; 51 | constructor Create(ADevice:JUSBDevice); 52 | destructor Destroy; override; 53 | end; 54 | 55 | 56 | TJvHidDeviceReadThread = class(TThread) 57 | private 58 | procedure DoData; 59 | procedure DoDataError; 60 | constructor CtlCreate(const aDevice: TJvHidDevice); 61 | protected 62 | procedure Execute; override; 63 | public 64 | Device:TJvHidDevice; 65 | NumBytesRead: word; 66 | Report: array of Byte; 67 | constructor Create(CreateSuspended: Boolean); 68 | end; 69 | 70 | TJvHidPlugEvent = procedure(HidDev: TJvHidDevice) of object; 71 | TJvHidUnplugEvent = TJvHidPlugEvent; 72 | 73 | TJvHidDataEvent = procedure(HidDev: TJvHidDevice; ReportID: Byte; 74 | const Data: Pointer; Size: Word) of object; 75 | 76 | TJvHidDataErrorEvent = procedure(HidDev: TJvHidDevice; Error: DWORD) of object; 77 | TJvHidDeviceCreateError = procedure(Controller: TJvHidDeviceController; PnPInfo: TJvHidPnPInfo; var Handled: Boolean; var RetryCreate: Boolean) of object; 78 | 79 | 80 | // check out test function 81 | TJvHidCheckCallback = function(HidDev: TJvHidDevice): Boolean; stdcall; 82 | 83 | THIDPCAPS = record 84 | InputReportByteLength: Word; 85 | OutputReportByteLength: Word; 86 | FeatureReportByteLength: Word; 87 | end; 88 | 89 | THIDDAttributes = record 90 | VendorID: Word; 91 | ProductID: Word; 92 | VersionNumber: Word; 93 | end; 94 | 95 | TJvHidDevice = class(TObject) 96 | private 97 | FMyController: TJvHidDeviceController; 98 | 99 | FUsbDevice : JUSBDevice; 100 | FUsbDeviceConnection : JUSBDeviceConnection; 101 | FUsbInterface : JUSBInterface; 102 | FEpOut,FEpIn : JUSBEndPoint; 103 | 104 | FIsPluggedIn: Boolean; 105 | FIsCheckedOut: Boolean; 106 | FIsEnumerated: Boolean; 107 | FData: TJvHidDataEvent; 108 | FUnplug: TJvHidUnplugEvent; 109 | FDataThread: TJvHidDeviceReadThread; 110 | fCaps:THIDPCaps; 111 | FAttributes: THIDDAttributes; 112 | FPnPInfo: TJvHidPnPInfo; 113 | FVendorName: String; 114 | FProductName: String; 115 | FSerialNumber: String; 116 | FLanguageStrings : TStringList; 117 | FThreadSleepTime: Integer; 118 | FDebugInfo : TStringList; 119 | function GetCaps: THIDPCaps; 120 | function GetAttributes: boolean; 121 | function GetVendorName: String; 122 | function GetProductName: String; 123 | function GetSerialNumber: String; 124 | function GetDeviceString(Idx: Byte): string; 125 | function GetFeatureReport: string; 126 | procedure SetDataEvent(const DataEvent: TJvHidDataEvent); 127 | procedure SetThreadSleepTime(const SleepTime: Integer); 128 | procedure StartThread; 129 | procedure StopThread; 130 | constructor CtlCreate(const APnPInfo: TJvHidPnPInfo; const LocalController: TJvHidDeviceController); 131 | protected 132 | // internal event implementor 133 | procedure DoUnplug; 134 | public 135 | // dummy constructor 136 | constructor Create; 137 | destructor Destroy; override; 138 | function OpenFile:boolean; 139 | procedure CloseFile; 140 | procedure FlushQueue; 141 | function ReadFile(var Report; ToRead: DWord; var BytesRead: DWord): Boolean; 142 | function WriteFile(var Report; ToWrite: Dword; var BytesWritten: DWord): Boolean; 143 | function CheckOut: Boolean; 144 | property Caps: THIDPCaps read GetCaps; 145 | //property Attributes: THIDDAttributes read GetAttributes; 146 | property Attributes: THIDDAttributes read FAttributes; 147 | property IsCheckedOut: Boolean read FIsCheckedOut; 148 | property IsPluggedIn: Boolean read FIsPluggedIn; 149 | property PnPInfo: TJvHidPnPInfo read FPnPInfo; 150 | property VendorName: String read GetVendorName; 151 | property ProductName: String read GetProductName; 152 | property SerialNumber: String read GetSerialNumber; 153 | property ThreadSleepTime: Integer read FThreadSleepTime write SetThreadSleepTime; 154 | property DeviceStrings[Idx: Byte]: string read GetDeviceString; 155 | property Connection:JUSBDeviceConnection read FUsbDeviceConnection; 156 | property EpIn:JUSBEndPoint read FEpIn; 157 | property EpOut:JUSBEndPoint read FEpOut; 158 | property OnData: TJvHidDataEvent read FData write SetDataEvent; 159 | property OnUnplug: TJvHidUnplugEvent read FUnplug write FUnplug; 160 | end; 161 | 162 | //THidDevList = TObjectList; 163 | THidDevList = TList; 164 | //THidDevList = TList; 165 | 166 | TJvHidDeviceController = class(TComponent) 167 | private 168 | FArrivalEvent: TJvHidPlugEvent; 169 | FDeviceChangeEvent: TNotifyEvent; 170 | FDevUnplugEvent: TJvHidUnplugEvent; 171 | FRemovalEvent: TJvHidUnplugEvent; 172 | FOnDeviceCreateError: TJvHidDeviceCreateError; 173 | FDevThreadSleepTime: Integer; 174 | FContinue: Boolean; 175 | FRunning: Boolean; 176 | FEnabled: Boolean; 177 | FUsbManager : JUSBManager; 178 | FBroadcastReceiverListener: JFMXBroadcastReceiverListener; 179 | FReceiver: JFMXBroadcastReceiver; 180 | {$ifdef WITHPERMISSION} 181 | FPermissionIntent : JPendingIntent; 182 | {$endif} 183 | FDevDataEvent: TJvHidDataEvent; 184 | FList:THidDevList; 185 | FNumCheckedInDevices: Integer; 186 | FNumCheckedOutDevices: Integer; 187 | FNumUnpluggedDevices: Integer; 188 | FInDeviceChange: Boolean; 189 | function CheckThisOut(var HidDev: TJvHidDevice; Idx: Integer; Check: Boolean): Boolean; 190 | procedure SetEnabled(Value: Boolean); 191 | procedure SetDevThreadSleepTime(const DevTime: Integer); 192 | procedure SetDevData(const DataEvent: TJvHidDataEvent); 193 | procedure SetDeviceChangeEvent(const Notifier: TNotifyEvent); 194 | procedure SetDevUnplug(const Unplugger: TJvHidUnplugEvent); 195 | protected 196 | procedure DoArrival(HidDev: TJvHidDevice); 197 | procedure DoRemoval(HidDev: TJvHidDevice); 198 | procedure DoDeviceChange; 199 | //procedure StartControllerThread; 200 | //procedure StopControllerThread; 201 | property Continue: Boolean read FContinue write FContinue; 202 | public 203 | constructor Create(AOwner: TComponent); override; 204 | destructor Destroy; override; 205 | procedure CheckIn(var HidDev: TJvHidDevice); 206 | function CheckOut(var HidDev: TJvHidDevice): Boolean; 207 | function CheckOutByID(var HidDev: TJvHidDevice; const Vid, Pid: Integer): Boolean; 208 | function CheckOutByIndex(var HidDev: TJvHidDevice; const Idx: Integer): Boolean; 209 | function CheckOutByProductName(var HidDev: TJvHidDevice; const ProductName: String): Boolean; 210 | function CheckOutByVendorName(var HidDev: TJvHidDevice; const VendorName: String): Boolean; 211 | function CheckOutByCallback(var HidDev: TJvHidDevice; Check: TJvHidCheckCallback): Boolean; 212 | // methods to count HID device objects 213 | function CountByID(const Vid, Pid: Integer): Integer; 214 | function CountByProductName(const ProductName: String): Integer; 215 | function CountByVendorName(const VendorName: String): Integer; 216 | function CountByCallback(Check: TJvHidCheckCallback): Integer; 217 | //property DebugInfo: String read GetDebugInfo write SetDebugInfo; 218 | property HidDevices:THidDevList read FList; 219 | property NumCheckedInDevices: Integer read FNumCheckedInDevices; 220 | property NumCheckedOutDevices: Integer read FNumCheckedOutDevices; 221 | property NumUnpluggedDevices: Integer read FNumUnpluggedDevices; 222 | property USBManager:JUSBManager read FUSBManager; 223 | {$ifdef WITHPERMISSION} 224 | property PermissionIntent: JPendingIntent read FPermissionIntent; 225 | {$endif} 226 | property InDeviceChange: Boolean read FInDeviceChange write FInDeviceChange; 227 | published 228 | property Enabled: Boolean read FEnabled write SetEnabled; 229 | property DevThreadSleepTime: Integer read FDevThreadSleepTime write SetDevThreadSleepTime default 100; 230 | property OnDeviceData: TJvHidDataEvent read FDevDataEvent write SetDevData; 231 | property OnArrival: TJvHidPlugEvent read FArrivalEvent write FArrivalEvent; 232 | property OnDeviceChange: TNotifyEvent read FDeviceChangeEvent write SetDeviceChangeEvent; 233 | property OnDeviceCreateError: TJvHidDeviceCreateError read FOnDeviceCreateError write FOnDeviceCreateError; 234 | property OnDeviceUnplug: TJvHidUnplugEvent read FDevUnplugEvent write SetDevUnplug; 235 | property OnRemoval: TJvHidUnplugEvent read FRemovalEvent write FRemovalEvent; 236 | procedure DeviceChange; 237 | end; 238 | 239 | implementation 240 | 241 | uses 242 | FMX.Platform.Android, 243 | android.hardware.usb.UsbConstants, 244 | Androidapi.JNI, 245 | Androidapi.Helpers; 246 | 247 | type 248 | EControllerError = class(Exception); 249 | EHidClientError = class(Exception); 250 | 251 | resourcestring 252 | RsEDirectThreadCreationNotAllowed = 'Direct creation of a TJvDeviceReadThread object is not allowed'; 253 | RsEDirectHidDeviceCreationNotAllowed = 'Direct creation of a TJvHidDevice object is not allowed'; 254 | RsEDeviceCannotBeIdentified = 'Device cannot be identified'; 255 | RsEDeviceCannotBeOpened = 'Device cannot be opened'; 256 | RsEOnlyOneControllerPerProgram = 'Only one TJvHidDeviceController allowed per program'; 257 | 258 | const 259 | ACTION_USB_PERMISSION='com.android.example.USB_PERMISSION'; 260 | USBTIMEOUT = 250; 261 | 262 | function translateDeviceClass(deviceClass:integer):string; 263 | begin 264 | case deviceClass of 265 | TJUsbConstantsUSB_CLASS_APP_SPEC:result:='Application specific USB class'; 266 | TJUsbConstantsUSB_CLASS_AUDIO:result:='USB class for audio devices'; 267 | TJUsbConstantsUSB_CLASS_CDC_DATA:result:='USB class for CDC devices (communications device class)'; 268 | TJUsbConstantsUSB_CLASS_COMM: result:='USB class for communication devices'; 269 | TJUsbConstantsUSB_CLASS_CONTENT_SEC: result:='USB class for content security devices'; 270 | TJUsbConstantsUSB_CLASS_CSCID: result:='USB class for content smart card devices'; 271 | TJUsbConstantsUSB_CLASS_HID: result:='USB class for human interface devices (for example, mice and keyboards)'; 272 | TJUsbConstantsUSB_CLASS_HUB: result:='USB class for USB hubs'; 273 | TJUsbConstantsUSB_CLASS_MASS_STORAGE: result:='USB class for mass storage devices'; 274 | TJUsbConstantsUSB_CLASS_MISC: result:='USB class for wireless miscellaneous devices'; 275 | TJUsbConstantsUSB_CLASS_PER_INTERFACE: result:='USB class indicating that the class is determined on a per-interface basis'; 276 | TJUsbConstantsUSB_CLASS_PHYSICA: result:='USB class for physical devices'; 277 | TJUsbConstantsUSB_CLASS_PRINTER: result:='USB class for printers'; 278 | TJUsbConstantsUSB_CLASS_STILL_IMAGE: result:='USB class for still image devices (digital cameras)'; 279 | TJUsbConstantsUSB_CLASS_VENDOR_SPEC: result:='Vendor specific USB class'; 280 | TJUsbConstantsUSB_CLASS_VIDEO: result:='USB class for video devices'; 281 | TJUsbConstantsUSB_CLASS_WIRELESS_CONTROLLER: result:='USB class for wireless controller devices'; 282 | else 283 | result:='Unknown USB class!'; 284 | end; 285 | end; 286 | 287 | constructor TJvHidPnPInfo.Create(ADevice:JUSBDevice); 288 | begin 289 | inherited Create; 290 | FUSBDevice:=ADevice; 291 | FFriendlyName := JStringToString(FUSBDevice.getDeviceName); 292 | FDeviceID := FUSBDevice.getDeviceId; 293 | FProductId:= FUSBDevice.getProductId; 294 | FVendorId:= FUSBDevice.getVendorId; 295 | FDeviceClass:= FUSBDevice.getDeviceClass; 296 | FDeviceProtocol:= FUSBDevice.getDeviceProtocol; 297 | FDeviceSubclass:= FUSBDevice.getDeviceSubclass; 298 | end; 299 | 300 | destructor TJvHidPnPInfo.Destroy; 301 | begin 302 | inherited Destroy; 303 | end; 304 | 305 | 306 | constructor TJvHidDeviceReadThread.CtlCreate(const aDevice: TJvHidDevice); 307 | begin 308 | inherited Create(True); 309 | FreeOnTerminate:=False; 310 | Device:=aDevice; 311 | NumBytesRead := 0; 312 | Finalize(Report); 313 | SetLength(Report, Device.EpIn.getMaxPacketSize); 314 | Start; 315 | end; 316 | 317 | constructor TJvHidDeviceReadThread.Create(CreateSuspended: Boolean); 318 | begin 319 | // direct creation of thread not allowed !! 320 | raise EControllerError.CreateRes(@RsEDirectThreadCreationNotAllowed); 321 | end; 322 | 323 | procedure TJvHidDeviceReadThread.DoData; 324 | begin 325 | Device.OnData(Device, Report[0], @Report[1], NumBytesRead); 326 | end; 327 | 328 | procedure TJvHidDeviceReadThread.DoDataError; 329 | begin 330 | //if Assigned(Device.FDataError) then 331 | // Device.FDataError(Device, FErr); 332 | end; 333 | 334 | 335 | procedure TJvHidDeviceReadThread.Execute; 336 | var 337 | i,FBytesRead:integer; 338 | FIBuffer : TJavaArray; 339 | begin 340 | if NOT Assigned(Device.Connection) then exit; 341 | FIBuffer := TJavaArray.Create(Device.EPIn.getMaxPacketSize); 342 | while not Terminated do 343 | begin 344 | while assigned(Device.Connection) and (not Terminated) do 345 | begin 346 | FBytesRead := Device.Connection.bulkTransfer(Device.EPIn, FIBuffer, FIBuffer.Length, 0); 347 | if FBytesRead > 0 then 348 | begin 349 | for i := 0 to (FBytesRead-1) do Report[i+1]:=FIBuffer.Items[i]; 350 | if not Terminated then DoData; 351 | //if not Terminated then Synchronize(DoData); 352 | end; 353 | end; 354 | Sleep(10); 355 | end; 356 | FIBuffer.Free; 357 | end; 358 | 359 | procedure TJvHidDevice.StartThread; 360 | begin 361 | if Assigned(FData) and Assigned(EpIn) and IsPluggedIn and IsCheckedOut and 362 | not Assigned(FDataThread) then 363 | begin 364 | FDataThread := TJvHidDeviceReadThread.CtlCreate(Self); 365 | end; 366 | end; 367 | 368 | procedure TJvHidDevice.StopThread; 369 | begin 370 | if Assigned(FDataThread) then 371 | begin 372 | FDataThread.Terminate; 373 | FDataThread.WaitFor; 374 | FDataThread.Free; 375 | FDataThread := nil; 376 | end; 377 | end; 378 | 379 | procedure TJvHidDevice.SetThreadSleepTime(const SleepTime: Integer); 380 | begin 381 | // limit to 10 msec .. 10 sec 382 | if (SleepTime >= 10) and (SleepTime <= 10000) then 383 | FThreadSleepTime := SleepTime; 384 | end; 385 | 386 | 387 | procedure TJvHidDevice.SetDataEvent(const DataEvent: TJvHidDataEvent); 388 | begin 389 | if not Assigned(DataEvent) then StopThread; 390 | FData := DataEvent; 391 | StartThread; 392 | end; 393 | 394 | procedure TJvHidDevice.CloseFile; 395 | begin 396 | if Assigned(FUsbDeviceConnection) then 397 | begin 398 | if Assigned(FUsbInterface) then FUsbDeviceConnection.releaseInterface(FUsbInterface); 399 | FUsbDeviceConnection.close; 400 | end; 401 | FUsbDeviceConnection:=nil; 402 | FUsbInterface:=nil; 403 | FEpOut := nil; 404 | FEpIn := nil; 405 | end; 406 | 407 | 408 | function TJvHidDevice.OpenFile:boolean; 409 | var 410 | FUsbEP:JUSBEndPoint; 411 | error:boolean; 412 | begin 413 | 414 | if NOT Assigned(FUsbDeviceConnection) then 415 | begin 416 | 417 | try 418 | 419 | if NOT FMyController.UsbManager.hasPermission(FUsbDevice) then 420 | begin 421 | //raise Exception.Create('No permission to access USB device.'); 422 | error:=True; 423 | {$ifdef WITHPERMISSION} 424 | FMyController.UsbManager.requestPermission(FUsbDevice,FMyController.PermissionIntent); 425 | {$endif} 426 | exit; 427 | end; 428 | 429 | error:=false; 430 | 431 | FUsbInterface := FUsbDevice.getInterface(0); 432 | 433 | FEpOut:=nil; 434 | FEpIn:=nil; 435 | 436 | // Get HID endpoint 0 437 | if FUsbInterface.getEndpointCount>0 then 438 | begin 439 | FUsbEP := FUsbInterface.getEndpoint(0); 440 | if FUsbEP.getType=TJUsbConstantsUSB_ENDPOINT_XFER_INT then 441 | begin 442 | if FUsbEP.getDirection = TJUsbConstantsUSB_DIR_OUT then 443 | begin 444 | FEpOut := FUsbEP; 445 | end 446 | else if FUsbEP.getDirection = TJUsbConstantsUSB_DIR_IN then 447 | begin 448 | FEpIn := FUsbEP; 449 | end; 450 | end; 451 | end; 452 | 453 | // Get HID endpoint 1 454 | if FUsbInterface.getEndpointCount>1 then 455 | begin 456 | FUsbEP := FUsbInterface.getEndpoint(1); 457 | if FUsbEP.getType=TJUsbConstantsUSB_ENDPOINT_XFER_INT then 458 | begin 459 | if FUsbEP.getDirection = TJUsbConstantsUSB_DIR_OUT then 460 | begin 461 | FEpOut := FUsbEP; 462 | end 463 | else if FUsbEP.getDirection = TJUsbConstantsUSB_DIR_IN then 464 | begin 465 | FEpIn := FUsbEP; 466 | end; 467 | end; 468 | end; 469 | 470 | if (EpIn=nil) AND (EpOut=nil) then 471 | begin 472 | //raise Exception.Create('Not endpoints found !!.'); 473 | error:=True; 474 | exit; 475 | end; 476 | 477 | // Open device 478 | FUsbDeviceConnection := FMyController.UsbManager.openDevice(FUsbDevice); 479 | if not assigned( FUsbDeviceConnection) then 480 | begin 481 | //raise Exception.Create('Failed to open device.'); 482 | error:=True; 483 | exit; 484 | end; 485 | 486 | if not FUsbDeviceConnection.claimInterface(FUsbInterface, True) then 487 | begin 488 | //raise Exception.Create('Failed to claim interface.'); 489 | error:=True; 490 | exit; 491 | end; 492 | 493 | finally 494 | if error then 495 | begin 496 | result:=False; 497 | CloseFile; 498 | //raise Exception.Create('Failed to open USB device.'); 499 | end; 500 | end; 501 | 502 | end; 503 | 504 | result:=Assigned(FUsbDeviceConnection); 505 | 506 | end; 507 | 508 | 509 | procedure TJvHidDevice.FlushQueue; 510 | begin 511 | // not implemented 512 | end; 513 | 514 | function TJvHidDevice.ReadFile(var Report; ToRead: DWORD; var BytesRead: DWORD): Boolean; 515 | var 516 | bufferMaxLength:integer; 517 | i : Word; 518 | Buffer2 : JByteBuffer; 519 | Buffer : TJavaArray; 520 | retval: integer; 521 | inrequest: JUSbRequest; 522 | returnrequest: JUSbRequest; 523 | //retval: boolean; 524 | readBufferByte: array[0..64] of byte; 525 | begin 526 | 527 | BytesRead:=0; 528 | 529 | if OpenFile then 530 | begin 531 | 532 | if Assigned(EpIn) then 533 | begin 534 | 535 | FillChar(readBufferByte, SizeOf(readBufferByte), 0); 536 | 537 | bufferMaxLength:=EpIn.getMaxPacketSize; 538 | 539 | Buffer := TJavaArray.Create(bufferMaxLength); 540 | 541 | repeat 542 | retval := FUsbDeviceConnection.bulkTransfer(EpIn, Buffer, Buffer.Length, USBTIMEOUT); 543 | until (retval >= 0); 544 | 545 | BytesRead:=retval; 546 | if BytesRead>bufferMaxLength then BytesRead:=bufferMaxLength; 547 | // include ReportID : +1 548 | Inc(BytesRead); 549 | if BytesRead>ToRead then BytesRead:=ToRead; 550 | if BytesRead>SizeOf(readBufferByte) then BytesRead:=SizeOf(readBufferByte); 551 | 552 | if BytesRead>0 then 553 | begin 554 | for i:=0 to BytesRead-1 do 555 | readBufferByte[i+1]:=Buffer.Items[i]; 556 | Move(readBufferByte,Report,BytesRead); 557 | end; 558 | Move(Report,readBufferByte,1); 559 | 560 | Buffer.Free; 561 | 562 | Result :=(BytesRead>=0); 563 | 564 | { 565 | 566 | Buffer2:=TJByteBuffer.JavaClass.allocate(bufferMaxLength+1); 567 | Buffer2.clear; 568 | 569 | //inRequest := TJUsbRequest.Create; 570 | inRequest:=TJUsbRequest.JavaClass.init; 571 | inRequest.initialize(FUsbDeviceConnection, EpIn); 572 | 573 | retval:=inRequest.queue(buffer2, bufferMaxLength); 574 | 575 | if retval then 576 | begin 577 | returnrequest:=FUsbDeviceConnection.requestWait; 578 | //if returnrequest<>nil then 579 | begin 580 | if returnrequest.equals(inrequest) then 581 | begin 582 | Buffer2.rewind; 583 | BytesRead := bufferMaxLength; 584 | for i:=0 to BytesRead-1 do 585 | begin 586 | //if Buffer2.hasRemaining then readBufferByte[i+1]:=Buffer2.get; 587 | readBufferByte[i+1]:=Buffer2.get; 588 | end; 589 | Move(Report,readBufferByte,1); 590 | Move(readBufferByte,Report,SizeOf(Report)); 591 | end; 592 | end; 593 | end; 594 | //inRequest.close; 595 | } 596 | end; 597 | end; 598 | //Result :=(BytesRead>=0); 599 | end; 600 | 601 | 602 | function TJvHidDevice.WriteFile(var Report; ToWrite: DWORD; var BytesWritten: DWORD): Boolean; 603 | var 604 | bufferMaxLength:integer; 605 | i : Word; 606 | Buffer2 : JByteBuffer; 607 | Buffer : TJavaArray; 608 | retval: integer; 609 | outrequest: JUSbRequest; 610 | returnrequest: JUSbRequest; 611 | //retval: boolean; 612 | writeBufferByte: array[0..64] of byte; 613 | begin 614 | result:=False; 615 | 616 | if OpenFile then 617 | begin 618 | 619 | if Assigned(EpOut) then 620 | begin 621 | 622 | bufferMaxLength:=EPOut.getMaxPacketSize; 623 | 624 | FillChar(writeBufferByte, SizeOf(writeBufferByte), #0); 625 | Move(Report,writeBufferByte,ToWrite); 626 | 627 | Buffer := TJavaArray.Create(bufferMaxLength); 628 | for i:=1 to ToWrite-1 do Buffer.Items[i-1] := writeBufferByte[i]; 629 | 630 | repeat 631 | retval := FUsbDeviceConnection.bulkTransfer(EpOut, Buffer, Buffer.Length, USBTIMEOUT); 632 | until (retval >= 0); 633 | 634 | Buffer.Free; 635 | 636 | Result :=(retval>=0); 637 | 638 | result:=True; 639 | 640 | { 641 | Buffer2:=TJByteBuffer.JavaClass.allocate(bufferMaxLength+1); 642 | Buffer2.clear; 643 | 644 | //outrequest := TJUsbRequest.Create; 645 | outRequest:=TJUsbRequest.JavaClass.init; 646 | outrequest.initialize(FUsbDeviceConnection,EpOut); 647 | 648 | FillChar(writeBufferByte, SizeOf(writeBufferByte), #0); 649 | Move(Report,writeBufferByte,ToWrite); 650 | 651 | for i:=1 to ToWrite-1 do Buffer2.put(writeBufferByte[i]); 652 | 653 | retval := outrequest.queue(Buffer2, ToWrite-1); 654 | 655 | returnrequest:=FUsbDeviceConnection.requestWait; 656 | //if returnrequest<>nil then 657 | begin 658 | if returnrequest.equals(outrequest) then 659 | begin 660 | BytesWritten:=ToWrite; 661 | result:=True; 662 | end; 663 | end; 664 | //outRequest.close; 665 | } 666 | end; 667 | end; 668 | end; 669 | 670 | function TJvHidDevice.GetCaps: THIDPCaps; 671 | begin 672 | if Openfile then 673 | begin 674 | if Assigned(EpOut) AND (fCaps.OutputReportByteLength=0) 675 | then fCaps.OutputReportByteLength:=EpOut.getMaxPacketSize+1; 676 | if Assigned(EpIn) AND (fCaps.InputReportByteLength=0) 677 | then fCaps.InputReportByteLength:=EpIn.getMaxPacketSize+1; 678 | // for now ... not yet correct 679 | if Assigned(EpIn) AND (fCaps.FeatureReportByteLength=0) 680 | then fCaps.FeatureReportByteLength:=EpIn.getMaxPacketSize+1; 681 | end; 682 | Result:=fCaps; 683 | end; 684 | 685 | function TJvHidDevice.GetAttributes: boolean; 686 | begin 687 | result:=False; 688 | if Assigned(fusbdevice) then 689 | begin 690 | // if FAttributes.VendorID=0 then 691 | FAttributes.VendorID:=fusbdevice.getVendorId; 692 | // if FAttributes.ProductID=0 then 693 | FAttributes.ProductID:=fusbdevice.getProductId; 694 | // if FAttributes.VersionNumber=0 then 695 | FAttributes.VersionNumber:=fusbdevice.getDeviceProtocol; 696 | result:=True; 697 | end; 698 | end; 699 | 700 | function TJvHidDevice.CheckOut: Boolean; 701 | begin 702 | Result := Assigned(FMyController) and IsPluggedIn and not IsCheckedOut; 703 | if Result then 704 | begin 705 | FIsCheckedOut := True; 706 | Inc(FMyController.FNumCheckedOutDevices); 707 | Dec(FMyController.FNumCheckedInDevices); 708 | StartThread; 709 | end; 710 | end; 711 | 712 | function TJvHidDevice.GetDeviceString(Idx: Byte): string; 713 | const 714 | STD_USB_REQUEST_GET_DESCRIPTOR = $06; 715 | STD_USB_REQUEST_GET_REPORT = $01; 716 | LIBUSB_FEATURE_REPORT = $0301; //Feature report, ID = 1 717 | LIBUSB_DT_STRING = $03; 718 | var 719 | i,rdo:integer; 720 | rawDescs,buffer : TJavaArray; 721 | requestidx:integer; 722 | S : String; 723 | begin 724 | 725 | if Openfile then 726 | begin 727 | rawDescs := FUsbDeviceConnection.getRawDescriptors; 728 | 729 | if (13+Idx)>rawDescs.Length then 730 | begin 731 | result:=''; 732 | exit; 733 | end; 734 | 735 | requestidx := rawDescs[13+Idx]; 736 | 737 | rawDescs.Free; 738 | 739 | buffer := TJavaArray.Create(255); 740 | 741 | rdo := FUsbDeviceConnection.controlTransfer( 742 | (TJUsbConstantsUSB_DIR_IN OR TJUsbConstantsUSB_TYPE_STANDARD), 743 | STD_USB_REQUEST_GET_DESCRIPTOR, 744 | ((LIBUSB_DT_STRING SHL 8) OR requestidx), 745 | 0, 746 | buffer, 747 | $FF, 748 | 0); 749 | 750 | if rdo>100 then rdo:=100; 751 | 752 | if rdo<3 then 753 | begin 754 | result:=''; 755 | exit; 756 | end; 757 | 758 | S:=''; 759 | for i:=1 to (rdo-2) do 760 | begin 761 | S:=S+Char(buffer.Items[i+1]); 762 | end; 763 | result:=S; 764 | buffer.Free; 765 | end 766 | else result:=''; 767 | end; 768 | 769 | function TJvHidDevice.GetFeatureReport: string; 770 | const 771 | STD_USB_REQUEST_RECIPIENT = $01; // Interface 772 | STD_USB_REQUEST_GET_REPORT = $01; //HID GET_REPORT 773 | STD_USB_REQUEST_SET_REPORT = $09; //HID SET_REPORT 774 | LIBUSB_FEATURE_REPORT = $0301; //Feature report ($0300), ID = 1 ($01) 775 | LIBUSB_FEATURE_REPORT_LENGTH = $FF; 776 | var 777 | i,rdo:integer; 778 | buffer : TJavaArray; 779 | S : String; 780 | begin 781 | 782 | if Openfile then 783 | begin 784 | 785 | buffer := TJavaArray.Create(255); 786 | 787 | rdo := FUsbDeviceConnection.controlTransfer( 788 | (TJUsbConstantsUSB_DIR_IN OR TJUsbConstantsUSB_TYPE_CLASS OR STD_USB_REQUEST_RECIPIENT), 789 | STD_USB_REQUEST_GET_REPORT, 790 | LIBUSB_FEATURE_REPORT, 791 | 0, 792 | buffer, 793 | LIBUSB_FEATURE_REPORT_LENGTH, 794 | 2000); 795 | 796 | if rdo<0 then 797 | begin 798 | buffer.Free; 799 | result:=''; 800 | exit; 801 | end; 802 | 803 | if rdo>255 then rdo:=255; 804 | 805 | S:=''; 806 | for i:=0 to rdo do 807 | begin 808 | S:=S+Char(buffer.Items[i]); 809 | end; 810 | result:=S; 811 | buffer.Free; 812 | end 813 | else result:=''; 814 | end; 815 | 816 | 817 | function TJvHidDevice.GetVendorName: String; 818 | begin 819 | if FVendorName = '' then 820 | begin 821 | FVendorName := GetDeviceString(1); 822 | end; 823 | Result := FVendorName; 824 | end; 825 | 826 | function TJvHidDevice.GetProductName: String; 827 | begin 828 | if FProductName = '' then 829 | begin 830 | FProductName := GetDeviceString(2); 831 | //FProductName := JStringToString(FUsbDevice.getDeviceName); 832 | end; 833 | Result := FProductName; 834 | end; 835 | 836 | function TJvHidDevice.GetSerialNumber: String; 837 | begin 838 | if FSerialNumber = '' then 839 | begin 840 | FSerialNumber:=GetDeviceString(3); 841 | //if Openfile then FSerialNumber:=JStringToString(FUsbDeviceConnection.getSerial); 842 | end; 843 | Result := FSerialNumber; 844 | end; 845 | 846 | procedure TJvHidDevice.DoUnplug; 847 | begin 848 | CloseFile; 849 | FIsPluggedIn := False; 850 | // event even for checked in devices 851 | if Assigned(FUnplug) then 852 | FUnplug(Self); 853 | // guarantees that event is only called once 854 | OnUnplug := nil; 855 | end; 856 | 857 | 858 | constructor TJvHidDevice.CtlCreate(const APnPInfo: TJvHidPnPInfo; const LocalController: TJvHidDeviceController); 859 | begin 860 | inherited Create; 861 | 862 | FPnPInfo := APnPInfo; 863 | FUSBDevice:=FPnPInfo.FUSBDevice; 864 | FMyController := LocalController; 865 | 866 | FIsPluggedIn := True; 867 | FIsCheckedOut := False; 868 | FIsEnumerated := False; 869 | FVendorName := ''; 870 | FProductName := ''; 871 | FSerialNumber := ''; 872 | FLanguageStrings := TStringList.Create; 873 | FDebugInfo := TStringList.Create; 874 | 875 | FillChar(fCaps, SizeOf(THIDPCaps), #0); 876 | FillChar(FAttributes, SizeOf(THIDDAttributes), #0); 877 | 878 | FThreadSleepTime := 100; 879 | FDataThread := nil; 880 | 881 | OnData := FMyController.OnDeviceData; 882 | OnUnplug := FMyController.OnDeviceUnplug; 883 | 884 | if NOT GetAttributes then 885 | raise EControllerError.CreateRes(@RsEDeviceCannotBeIdentified); 886 | 887 | // the file is closed to stop using up resources 888 | CloseFile; 889 | end; 890 | 891 | // dummy constructor to catch invalid Create calls 892 | constructor TJvHidDevice.Create; 893 | begin 894 | inherited Create; 895 | raise EControllerError.CreateRes(@RsEDirectHidDeviceCreationNotAllowed); 896 | end; 897 | 898 | destructor TJvHidDevice.Destroy; 899 | var 900 | I: Integer; 901 | TmpOnData: TJvHidDataEvent; 902 | TmpOnUnplug: TJvHidUnplugEvent; 903 | Dev: TJvHidDevice; 904 | begin 905 | // if we need to clone the object 906 | TmpOnData := OnData; 907 | TmpOnUnplug := OnUnplug; 908 | // to prevent strange problems 909 | OnData := nil; 910 | OnUnplug := nil; 911 | 912 | // free the data which needs special handling 913 | CloseFile; 914 | 915 | FLanguageStrings.Free; 916 | 917 | if FMyController <> nil then 918 | with FMyController do 919 | begin 920 | // delete device from controller list 921 | for I := 0 to FList.Count - 1 do 922 | if TJvHidDevice(FList.Items[I]) = Self then 923 | begin 924 | // if device is plugged in create a checked in copy 925 | if IsPluggedIn then 926 | begin 927 | Dev := nil; 928 | try 929 | Dev := TJvHidDevice.CtlCreate(FPnPInfo, FMyController); 930 | // make it a complete clone 931 | Dev.OnData := TmpOnData; 932 | Dev.OnUnplug := TmpOnUnplug; 933 | Dev.ThreadSleepTime := ThreadSleepTime; 934 | FList.Items[I] := Dev; 935 | // the FPnPInfo has been handed over to the new object 936 | FPnPInfo := nil; 937 | if IsCheckedOut then 938 | begin 939 | Dec(FNumCheckedOutDevices); 940 | Inc(FNumCheckedInDevices); 941 | end; 942 | except 943 | on EControllerError do 944 | begin 945 | FList.Delete(I); 946 | Dev.Free; 947 | Dec(FNumUnpluggedDevices); 948 | end; 949 | end; 950 | end 951 | else 952 | begin 953 | FList.Delete(I); 954 | Dec(FNumUnpluggedDevices); 955 | end; 956 | Break; 957 | end; 958 | end; 959 | FPnPInfo.Free; 960 | inherited Destroy; 961 | end; 962 | 963 | constructor TJvHidDeviceController.Create(AOwner: TComponent); 964 | var 965 | JavaObject : JObject; 966 | begin 967 | inherited Create(AOwner); 968 | 969 | FNumCheckedInDevices := 0; 970 | FNumCheckedOutDevices := 0; 971 | FNumUnpluggedDevices := 0; 972 | 973 | FInDeviceChange := False; 974 | 975 | //FList := THidDevList.Create(False); 976 | FList := THidDevList.Create; 977 | 978 | JavaObject := SharedActivityContext.getSystemService(TJContext.JavaClass.USB_SERVICE); 979 | FUsbManager := TJUSBManager.Wrap((JavaObject as ILocalObject).GetObjectID); 980 | if not Assigned(FUsbManager) then 981 | begin 982 | raise Exception.Create('No USB manager adapter present'); 983 | end; 984 | end; 985 | 986 | 987 | destructor TJvHidDeviceController.Destroy; 988 | var 989 | I: Integer; 990 | HidDev: TJvHidDevice; 991 | begin 992 | for I := 0 to FList.Count - 1 do 993 | begin 994 | HidDev := FList.Items[I]; 995 | with HidDev do 996 | begin 997 | // set to uncontrolled 998 | FMyController := nil; 999 | if IsCheckedOut then 1000 | DoUnplug; // pull the plug for checked out TJvHidDevices 1001 | //else 1002 | Free; // kill TJvHidDevices which are not checked out 1003 | end; 1004 | end; 1005 | FList.Free; 1006 | 1007 | inherited Destroy; 1008 | end; 1009 | 1010 | 1011 | 1012 | procedure TJvHidDeviceController.CheckIn(var HidDev: TJvHidDevice); 1013 | begin 1014 | if HidDev <> nil then 1015 | begin 1016 | HidDev.StopThread; 1017 | HidDev.CloseFile; 1018 | 1019 | if HidDev.IsPluggedIn then 1020 | begin 1021 | HidDev.FIsCheckedOut := False; 1022 | Dec(FNumCheckedOutDevices); 1023 | Inc(FNumCheckedInDevices); 1024 | end 1025 | else 1026 | HidDev.Free; 1027 | HidDev := nil; 1028 | end; 1029 | end; 1030 | 1031 | procedure TJvHidDeviceController.SetDevData(const DataEvent: TJvHidDataEvent); 1032 | var 1033 | I: Integer; 1034 | Dev: TJvHidDevice; 1035 | begin 1036 | if @DataEvent <> @FDevDataEvent then 1037 | begin 1038 | // change all OnData events with the same old value 1039 | for I := 0 to FList.Count - 1 do 1040 | begin 1041 | Dev := FList.Items[I]; 1042 | if @Dev.OnData = @FDevDataEvent then 1043 | Dev.OnData := DataEvent; 1044 | end; 1045 | FDevDataEvent := DataEvent; 1046 | end; 1047 | end; 1048 | 1049 | procedure TJvHidDeviceController.SetDeviceChangeEvent(const Notifier: TNotifyEvent); 1050 | begin 1051 | if @FDeviceChangeEvent <> @Notifier then 1052 | begin 1053 | FDeviceChangeEvent := Notifier; 1054 | { 1055 | if not (csLoading in ComponentState) then 1056 | DeviceChange; 1057 | } 1058 | end; 1059 | end; 1060 | 1061 | procedure TJvHidDeviceController.DoDeviceChange; 1062 | begin 1063 | if Assigned(FDeviceChangeEvent) then 1064 | FDeviceChangeEvent(Self); 1065 | end; 1066 | 1067 | 1068 | procedure TJvHidDeviceController.DoArrival(HidDev: TJvHidDevice); 1069 | begin 1070 | if Assigned(FArrivalEvent) then 1071 | begin 1072 | HidDev.FIsEnumerated := True; 1073 | FArrivalEvent(HidDev); 1074 | HidDev.FIsEnumerated := False; 1075 | end; 1076 | end; 1077 | 1078 | procedure TJvHidDeviceController.DoRemoval(HidDev: TJvHidDevice); 1079 | begin 1080 | if Assigned(FRemovalEvent) then 1081 | begin 1082 | HidDev.FIsEnumerated := True; 1083 | FRemovalEvent(HidDev); 1084 | HidDev.FIsEnumerated := False; 1085 | end; 1086 | end; 1087 | 1088 | procedure TJvHidDeviceController.SetDevUnplug(const Unplugger: TJvHidUnplugEvent); 1089 | var 1090 | I: Integer; 1091 | Dev: TJvHidDevice; 1092 | begin 1093 | if @Unplugger <> @FDevUnplugEvent then 1094 | begin 1095 | // change all OnUnplug events with the same old value 1096 | for I := 0 to FList.Count - 1 do 1097 | begin 1098 | Dev := FList.Items[I]; 1099 | if @Dev.OnUnplug = @FDevUnplugEvent then 1100 | Dev.OnUnplug := Unplugger; 1101 | end; 1102 | FDevUnplugEvent := Unplugger; 1103 | end; 1104 | end; 1105 | 1106 | function TJvHidDeviceController.CheckThisOut(var HidDev: TJvHidDevice; Idx: Integer; Check: Boolean): Boolean; 1107 | begin 1108 | Result := Check and not TJvHidDevice(FList.Items[Idx]).IsCheckedOut; 1109 | if Result then 1110 | begin 1111 | HidDev := FList[Idx]; 1112 | HidDev.FIsCheckedOut := True; 1113 | Inc(FNumCheckedOutDevices); 1114 | Dec(FNumCheckedInDevices); 1115 | HidDev.StartThread; 1116 | end; 1117 | end; 1118 | 1119 | // method CheckOutByProductName hands out the first HidDevice with a matching ProductName 1120 | 1121 | function TJvHidDeviceController.CheckOutByProductName(var HidDev: TJvHidDevice; 1122 | const ProductName: String): Boolean; 1123 | var 1124 | I: Integer; 1125 | begin 1126 | Result := False; 1127 | HidDev := nil; 1128 | if ProductName <> '' then 1129 | for I := 0 to FList.Count - 1 do 1130 | begin 1131 | Result := CheckThisOut(HidDev, I, ProductName = TJvHidDevice(FList[I]).ProductName); 1132 | if Result then 1133 | Break; 1134 | end; 1135 | end; 1136 | 1137 | // method CheckOutByVendorName hands out the first HidDevice with a matching VendorName 1138 | 1139 | function TJvHidDeviceController.CheckOutByVendorName(var HidDev: TJvHidDevice; 1140 | const VendorName: String): Boolean; 1141 | var 1142 | I: Integer; 1143 | begin 1144 | Result := False; 1145 | HidDev := nil; 1146 | if VendorName <> '' then 1147 | for I := 0 to FList.Count - 1 do 1148 | begin 1149 | Result := CheckThisOut(HidDev, I, VendorName = TJvHidDevice(FList[I]).VendorName); 1150 | if Result then 1151 | Break; 1152 | end; 1153 | end; 1154 | 1155 | // method CheckOutByCallback hands out the first HidDevice which is accepted by the Check function 1156 | // only checked in devices are presented to the Check function 1157 | // the device object is usable like during Enumerate 1158 | 1159 | 1160 | function TJvHidDeviceController.CheckOutByCallback(var HidDev: TJvHidDevice; 1161 | Check: TJvHidCheckCallback): Boolean; 1162 | var 1163 | I: Integer; 1164 | Dev: TJvHidDevice; 1165 | begin 1166 | Result := False; 1167 | HidDev := nil; 1168 | for I := 0 to FList.Count - 1 do 1169 | begin 1170 | Dev := FList[I]; 1171 | if not Dev.IsCheckedOut then 1172 | begin 1173 | Dev.FIsEnumerated := True; 1174 | Result := CheckThisOut(HidDev, I, Check(Dev)); 1175 | Dev.FIsEnumerated := False; 1176 | if not Result then 1177 | begin 1178 | Dev.CloseFile; 1179 | end; 1180 | if Result then 1181 | Break; 1182 | end; 1183 | end; 1184 | end; 1185 | 1186 | 1187 | // method CheckOutByID hands out the first HidDevice with a matching VendorID and ProductID 1188 | // Pid = -1 matches all ProductIDs 1189 | 1190 | function TJvHidDeviceController.CheckOutByID(var HidDev: TJvHidDevice; 1191 | const Vid, Pid: Integer): Boolean; 1192 | var 1193 | I: Integer; 1194 | begin 1195 | Result := False; 1196 | HidDev := nil; 1197 | for I := 0 to FList.Count - 1 do 1198 | begin 1199 | Result := CheckThisOut(HidDev, I, (Vid = TJvHidDevice(FList[I]).Attributes.VendorID) and 1200 | ((Pid = TJvHidDevice(FList[I]).Attributes.ProductID) or (Pid = -1))); 1201 | if Result then 1202 | Break; 1203 | end; 1204 | end; 1205 | 1206 | // method CheckOutByIndex hands out the HidDevice in the list with the named index 1207 | // this is mainly for check out during OnEnumerate 1208 | 1209 | function TJvHidDeviceController.CheckOutByIndex(var HidDev: TJvHidDevice; 1210 | const Idx: Integer): Boolean; 1211 | begin 1212 | Result := False; 1213 | HidDev := nil; 1214 | if (Idx >= 0) and (Idx < FList.Count) then 1215 | Result := CheckThisOut(HidDev, Idx, True); 1216 | end; 1217 | 1218 | function TJvHidDeviceController.CountByID(const Vid, Pid: Integer): Integer; 1219 | var 1220 | I: Integer; 1221 | begin 1222 | Result := 0; 1223 | for I := 0 to FList.Count - 1 do 1224 | if TJvHidDevice(FList[I]).IsPluggedIn and 1225 | (Vid = TJvHidDevice(FList[I]).Attributes.VendorID) and 1226 | ((Pid = TJvHidDevice(FList[I]).Attributes.ProductID) or (Pid = -1)) then 1227 | Inc(Result); 1228 | end; 1229 | 1230 | function TJvHidDeviceController.CountByProductName(const ProductName: String): Integer; 1231 | var 1232 | I: Integer; 1233 | begin 1234 | Result := 0; 1235 | for I := 0 to FList.Count - 1 do 1236 | if TJvHidDevice(FList[I]).IsPluggedIn and 1237 | (ProductName = TJvHidDevice(FList[I]).ProductName) then 1238 | Inc(Result); 1239 | end; 1240 | 1241 | function TJvHidDeviceController.CountByVendorName(const VendorName: String): Integer; 1242 | var 1243 | I: Integer; 1244 | begin 1245 | Result := 0; 1246 | for I := 0 to FList.Count - 1 do 1247 | if TJvHidDevice(FList[I]).IsPluggedIn and 1248 | (VendorName = TJvHidDevice(FList[I]).VendorName) then 1249 | Inc(Result); 1250 | end; 1251 | 1252 | function TJvHidDeviceController.CountByCallback(Check: TJvHidCheckCallback): Integer; 1253 | var 1254 | I: Integer; 1255 | Dev: TJvHidDevice; 1256 | begin 1257 | Result := 0; 1258 | for I := 0 to FList.Count - 1 do 1259 | begin 1260 | if TJvHidDevice(FList[I]).IsPluggedIn then 1261 | begin 1262 | Dev := FList[I]; 1263 | Dev.FIsEnumerated := True; 1264 | if Check(Dev) then 1265 | Inc(Result); 1266 | Dev.FIsEnumerated := False; 1267 | if not Dev.IsCheckedOut then 1268 | begin 1269 | Dev.CloseFile; 1270 | end; 1271 | end; 1272 | end; 1273 | end; 1274 | 1275 | 1276 | // method CheckOut simply hands out the first available HidDevice in the list 1277 | 1278 | function TJvHidDeviceController.CheckOut(var HidDev: TJvHidDevice): Boolean; 1279 | var 1280 | I: Integer; 1281 | begin 1282 | Result := False; 1283 | HidDev := nil; 1284 | for I := 0 to FList.Count - 1 do 1285 | begin 1286 | Result := CheckThisOut(HidDev, I, True); 1287 | if Result then 1288 | Break; 1289 | end; 1290 | end; 1291 | 1292 | 1293 | procedure TJvHidDeviceController.SetDevThreadSleepTime(const DevTime: Integer); 1294 | var 1295 | I: Integer; 1296 | Dev: TJvHidDevice; 1297 | begin 1298 | if DevTime <> FDevThreadSleepTime then 1299 | begin 1300 | // change all DevThreadSleepTime with the same old value 1301 | for I := 0 to FList.Count - 1 do 1302 | begin 1303 | Dev := FList.Items[I]; 1304 | if Dev.ThreadSleepTime = FDevThreadSleepTime then 1305 | Dev.ThreadSleepTime := DevTime; 1306 | end; 1307 | FDevThreadSleepTime := DevTime; 1308 | end; 1309 | end; 1310 | 1311 | 1312 | procedure TJvHidDeviceController.DeviceChange; 1313 | var 1314 | I,J: Integer; 1315 | HidDev: TJvHidDevice; 1316 | Changed: Boolean; 1317 | NewList:THidDevList; 1318 | 1319 | // internal worker function to find all HID devices and create their objects 1320 | procedure FillInList; 1321 | var 1322 | LocalHidDev: TJvHidDevice; 1323 | LocalPnPInfo: TJvHidPnPInfo; 1324 | DeviceList : JHashMap; 1325 | LocalUSBDevice : JUSBDevice; 1326 | LocalUSBInterface : JUSBInterface; 1327 | iter : Jiterator; 1328 | Handled: Boolean; 1329 | RetryCreate: Boolean; 1330 | begin 1331 | DeviceList := FUsbManager.getDeviceList; 1332 | iter := DeviceList.values.iterator; 1333 | while iter.hasNext do 1334 | begin 1335 | LocalUSBDevice := TJUSBDevice.Wrap((iter.next as ILocalObject).GetObjectID); 1336 | if LocalUsbDevice.getInterfaceCount>0 then 1337 | begin 1338 | LocalUsbInterface := LocalUsbDevice.getInterface(0); 1339 | // HID device available ? 1340 | if LocalUsbInterface.getInterfaceClass=TJUsbConstantsUSB_CLASS_HID then 1341 | begin 1342 | LocalPnPInfo := TJvHidPnPInfo.Create(LocalUsbDevice); 1343 | RetryCreate := False; 1344 | LocalHidDev := nil; 1345 | repeat 1346 | try 1347 | LocalHidDev := TJvHidDevice.CtlCreate(LocalPnPInfo, Self); 1348 | except 1349 | on EControllerError do 1350 | if Assigned(OnDeviceCreateError) then 1351 | begin 1352 | Handled := False; 1353 | OnDeviceCreateError(Self, LocalPnPInfo, Handled, RetryCreate); 1354 | if not Handled then 1355 | raise; 1356 | end 1357 | else 1358 | raise; 1359 | end; 1360 | until not RetryCreate; 1361 | if Assigned(LocalHidDev) then NewList.Add(LocalHidDev); 1362 | end; 1363 | end; 1364 | end; 1365 | end; 1366 | 1367 | begin 1368 | 1369 | Changed:=False; 1370 | 1371 | // get new device list 1372 | NewList := THidDevList.Create; 1373 | 1374 | FillInList; 1375 | 1376 | // unplug devices in FList which are not in NewList 1377 | for I := FList.Count - 1 downto 0 do 1378 | begin 1379 | HidDev := FList.Items[I]; 1380 | for J := NewList.Count - 1 downto 0 do 1381 | if (TJvHidDevice(NewList.Items[J]).PnPInfo.DeviceID = HidDev.PnPInfo.DeviceID) and 1382 | HidDev.IsPluggedIn then 1383 | begin 1384 | HidDev := nil; 1385 | Break; 1386 | end; 1387 | if HidDev <> nil then 1388 | begin 1389 | HidDev.DoUnplug; 1390 | DoRemoval(HidDev); 1391 | // delete from list 1392 | if not HidDev.IsCheckedOut then 1393 | begin 1394 | FList.Delete(I); 1395 | HidDev.Free; 1396 | //HidDev.Destroy; 1397 | end; 1398 | Changed := True; 1399 | end; 1400 | end; 1401 | 1402 | // delete devices from NewList which are in FList 1403 | for I := 0 to NewList.Count - 1 do 1404 | begin 1405 | //HidDev := NewList.Items[I]; 1406 | HidDev := NewList[I]; 1407 | for J := 0 to FList.Count - 1 do 1408 | if (HidDev.PnPInfo.DeviceID = TJvHidDevice(FList[J]).PnPInfo.DeviceID) and 1409 | TJvHidDevice(FList[J]).IsPluggedIn then 1410 | begin 1411 | HidDev.FMyController := nil; // prevent Free/Destroy from accessing this controller 1412 | HidDev.Free; 1413 | HidDev := nil; 1414 | //NewList[I] := nil; 1415 | Break; 1416 | end; 1417 | end; 1418 | 1419 | // add the remains in NewList to FList 1420 | for I := 0 to NewList.Count - 1 do 1421 | if NewList[I] <> nil then 1422 | begin 1423 | FList.Add(NewList[I]); 1424 | Changed := True; 1425 | DoArrival(NewList[I]); 1426 | end; 1427 | 1428 | //Toast('FList filled. Count: '+InttoStr(FList.Count)+'.'); 1429 | // throw away helper list 1430 | NewList.Free; 1431 | 1432 | // recount the devices 1433 | FNumCheckedInDevices := 0; 1434 | FNumCheckedOutDevices := 0; 1435 | FNumUnpluggedDevices := 0; 1436 | for I := 0 to FList.Count - 1 do 1437 | begin 1438 | HidDev := FList.Items[I]; 1439 | Inc(FNumCheckedInDevices, Ord(not HidDev.IsCheckedOut)); 1440 | Inc(FNumCheckedOutDevices, Ord(HidDev.IsCheckedOut)); 1441 | Inc(FNumUnpluggedDevices, Ord(not HidDev.IsPluggedIn)); 1442 | end; 1443 | FNumCheckedOutDevices := FNumCheckedOutDevices - FNumUnpluggedDevices; 1444 | 1445 | if Changed then 1446 | DoDeviceChange; 1447 | end; 1448 | 1449 | procedure TJvHidDeviceController.SetEnabled(Value: Boolean); 1450 | var 1451 | Filter: JIntentFilter; 1452 | begin 1453 | if Value <> FEnabled then 1454 | begin 1455 | FEnabled := Value; 1456 | if FEnabled then 1457 | begin 1458 | DeviceChange; 1459 | 1460 | {$ifdef WITHPERMISSION} 1461 | FPermissionIntent:=TJPendingIntent.JavaClass.getBroadcast(SharedActivityContext, 0, TJIntent.JavaClass.init(StringToJString(ACTION_USB_PERMISSION)), 0); 1462 | {$endif} 1463 | Filter := TJIntentFilter.JavaClass.init; 1464 | {$ifdef WITHPERMISSION} 1465 | Filter.addAction(StringToJString(ACTION_USB_PERMISSION)); 1466 | {$endif} 1467 | Filter.addAction(TJUsbManager.JavaClass.ACTION_USB_DEVICE_ATTACHED); 1468 | Filter.addAction(TJUsbManager.JavaClass.ACTION_USB_DEVICE_DETACHED); 1469 | 1470 | FBroadcastReceiverListener := TBroadcastReceiverListener.Create(Self); 1471 | FReceiver := TJFMXBroadcastReceiver.JavaClass.init(FBroadcastReceiverListener); 1472 | try 1473 | SharedActivityContext.getApplicationContext.registerReceiver( 1474 | FReceiver, 1475 | Filter); 1476 | except 1477 | end; 1478 | end 1479 | else 1480 | begin 1481 | if 1482 | (FReceiver <> nil) and 1483 | (not (SharedActivityContext as JActivity).isFinishing) 1484 | then 1485 | try 1486 | SharedActivityContext.getApplicationContext.unregisterReceiver(FReceiver); 1487 | except 1488 | end; 1489 | FReceiver := nil; 1490 | end; 1491 | end; 1492 | end; 1493 | 1494 | function HasPermission(const Permission: string): Boolean; 1495 | begin 1496 | //Permissions listed at http://d.android.com/reference/android/Manifest.permission.html 1497 | Result := SharedActivity.checkCallingOrSelfPermission( 1498 | StringToJString(Permission)) = 1499 | TJPackageManager.JavaClass.PERMISSION_GRANTED 1500 | end; 1501 | 1502 | constructor TBroadcastReceiverListener.Create(aOwner:TJvHidDeviceController); 1503 | begin 1504 | inherited Create; 1505 | FHidDC:=aOwner; 1506 | end; 1507 | 1508 | procedure TBroadcastReceiverListener.OnReceive( 1509 | context: JContext; 1510 | intent: JIntent); 1511 | begin 1512 | 1513 | //if TJUsbManager.JavaClass.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction) OR TJUsbManager.JavaClass.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction) then 1514 | if TJUsbManager.JavaClass.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction) then 1515 | begin 1516 | //HidDC.DeviceChange; 1517 | TThread.CreateAnonymousThread( 1518 | procedure 1519 | begin 1520 | TThread.Synchronize( 1521 | TThread.CurrentThread, 1522 | procedure 1523 | begin 1524 | //Toast('Android USB device attached.'); 1525 | HidDC.DeviceChange; 1526 | end 1527 | ); 1528 | end 1529 | ).Start; 1530 | end; 1531 | 1532 | if TJUsbManager.JavaClass.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction) then 1533 | begin 1534 | //HidDC.DeviceChange; 1535 | //CallInUiThread( 1536 | TThread.CreateAnonymousThread( 1537 | procedure 1538 | begin 1539 | TThread.Synchronize( 1540 | TThread.CurrentThread, 1541 | procedure 1542 | begin 1543 | //Toast('Android USB device detached.'); 1544 | HidDC.DeviceChange; 1545 | end 1546 | ); 1547 | end 1548 | ).Start; 1549 | end; 1550 | 1551 | 1552 | {$ifdef WITHPERMISSION} 1553 | 1554 | //if not HasPermission('android.permission.SEND_SMS') then 1555 | // MessageDlg('App does not have the SEND_SMS permission', 1556 | // TMsgDlgType.mtError, [TMsgDlgBtn.mbCancel], 0) 1557 | // else 1558 | 1559 | if JStringToString(intent.getAction)=ACTION_USB_PERMISSION then 1560 | begin 1561 | if (intent.getBooleanExtra(TJUsbManager.JavaClass.EXTRA_PERMISSION_GRANTED, false)) then 1562 | begin 1563 | Toast('Permission granted. Thanks !'); 1564 | if not HidDC.InDeviceChange then 1565 | try 1566 | HidDC.InDeviceChange := True; 1567 | HidDC.DeviceChange; 1568 | finally 1569 | HidDC.InDeviceChange := False; 1570 | end; 1571 | end 1572 | else 1573 | begin 1574 | Toast('Permission not granted'); 1575 | end; 1576 | end; 1577 | {$endif} 1578 | end; 1579 | 1580 | end. 1581 | -------------------------------------------------------------------------------- /Project2.dproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {42B324B5-68D3-4A29-A493-C2FA449199AF} 4 | 16.1 5 | FMX 6 | Project2.dpr 7 | True 8 | Debug 9 | Android 10 | 95 11 | Application 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Base 34 | true 35 | 36 | 37 | true 38 | Base 39 | true 40 | 41 | 42 | true 43 | Base 44 | true 45 | 46 | 47 | true 48 | Base 49 | true 50 | 51 | 52 | true 53 | Cfg_1 54 | true 55 | true 56 | 57 | 58 | true 59 | Cfg_1 60 | true 61 | true 62 | 63 | 64 | true 65 | Base 66 | true 67 | 68 | 69 | true 70 | true 71 | $(BDS)\bin\delphi_PROJECTICNS.icns 72 | true 73 | true 74 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 75 | true 76 | $(BDS)\bin\delphi_PROJECTICON.ico 77 | true 78 | true 79 | true 80 | Project2 81 | true 82 | true 83 | .\$(Platform)\$(Config) 84 | .\$(Platform)\$(Config) 85 | false 86 | false 87 | false 88 | false 89 | false 90 | 91 | 92 | $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png 93 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png 94 | $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png 95 | $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png 96 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png 97 | true 98 | FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;fmx;IndySystem;tethering;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapProviderClient;DbxCommonDriver;dbxcds;fmxFireDAC;CustomIPTransport;dsnap;IndyIPServer;IndyCore;IndyIPCommon;CloudService;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;dsnapxml;bindcompfmx;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;FireDACCommonDriver;bindengine;bindcompdbx;soaprtl;FMXTee;emsclient;FireDAC;inet;soapmidas;RESTComponents;dbexpress;IndyIPClient;$(DCC_UsePackage) 99 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=preferExternal;largeHeap=False;theme=TitleBar;hardwareAccelerated=true 100 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png 101 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png 102 | $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png 103 | Debug 104 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png 105 | 106 | 107 | true 108 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_640x1136.png 109 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png 110 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png 111 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_50x50.png 112 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png 113 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1496.png 114 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_144x144.png 115 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x748.png 116 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_58x58.png 117 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_320x480.png 118 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_640x960.png 119 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_87x87.png 120 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_57x57.png 121 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png 122 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png 123 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_72x72.png 124 | $(BDS)\bin\Artwork\iOS\iPad\FM_SettingIcon_58x58.png 125 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_750x1334.png 126 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png 127 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png 128 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2008.png 129 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_100x100.png 130 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist 131 | $(MSBuildProjectName) 132 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_29x29.png 133 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png 134 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1004.png 135 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png 136 | iPhoneAndiPad 137 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png 138 | FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;fmx;IndySystem;tethering;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapProviderClient;DbxCommonDriver;dbxcds;fmxFireDAC;CustomIPTransport;dsnap;IndyIPServer;fmxase;IndyCore;IndyIPCommon;CloudService;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;dsnapxml;bindcompfmx;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;FireDACCommonDriver;bindengine;bindcompdbx;soaprtl;FMXTee;emsclient;FireDAC;inet;soapmidas;RESTComponents;dbexpress;IndyIPClient;$(DCC_UsePackage) 139 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_114x114.png 140 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1242x2208.png 141 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png 142 | Debug 143 | $(BDS)\bin\Artwork\iOS\iPad\FM_SettingIcon_29x29.png 144 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png 145 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2208x1242.png 146 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png 147 | 148 | 149 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png 150 | true 151 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png 152 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_50x50.png 153 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_640x1136.png 154 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_144x144.png 155 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png 156 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x748.png 157 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_58x58.png 158 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_72x72.png 159 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_87x87.png 160 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_320x480.png 161 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_57x57.png 162 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png 163 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_640x960.png 164 | $(BDS)\bin\Artwork\iOS\iPad\FM_SettingIcon_58x58.png 165 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png 166 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_750x1334.png 167 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png 168 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png 169 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2008.png 170 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist 171 | $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_100x100.png 172 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png 173 | $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_29x29.png 174 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png 175 | iPhoneAndiPad 176 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1004.png 177 | $(BDS)\bin\Artwork\iOS\iPad\FM_SettingIcon_29x29.png 178 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png 179 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_114x114.png 180 | $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1496.png 181 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1242x2208.png 182 | $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png 183 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png 184 | $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png 185 | FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;fmx;IndySystem;tethering;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapProviderClient;DbxCommonDriver;dbxcds;fmxFireDAC;CustomIPTransport;dsnap;IndyIPServer;fmxase;IndyCore;IndyIPCommon;CloudService;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;dsnapxml;bindcompfmx;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;FireDACCommonDriver;bindengine;bindcompdbx;soaprtl;FMXTee;emsclient;FireDAC;inet;soapmidas;RESTComponents;dbexpress;IndyIPClient;$(DCC_UsePackage) 186 | $(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2208x1242.png 187 | 188 | 189 | true 190 | FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;tethering;DBXInterBaseDriver;DataSnapClient;DataSnapServer;DataSnapCommon;DataSnapProviderClient;DbxCommonDriver;dbxcds;fmxFireDAC;DBXOracleDriver;CustomIPTransport;dsnap;IndyIPServer;fmxase;IndyCore;IndyIPCommon;CloudService;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindengine;bindcompdbx;soaprtl;FMXTee;emsclient;FireDACMSSQLDriver;FireDAC;DBXInformixDriver;DataSnapServerMidas;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;soapmidas;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) 191 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities 192 | 193 | 194 | 1033 195 | $(BDS)\bin\default_app.manifest 196 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 197 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 198 | FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;frxe21;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapServer;DataSnapCommon;frx21;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;IndyIPCommon;CloudService;FmxTeeUI;FireDACIBDriver;CodeSiteExpressPkg;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;frxTee21;Tee;DBXOdbcDriver;frxDB21;vclFireDAC;xmlrtl;DataSnapNativeClient;svnui;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindengine;vclactnband;bindcompdbx;soaprtl;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDACMSSQLDriver;FireDAC;VclSmp;DBXInformixDriver;Intraweb;DataSnapConnectors;DataSnapServerMidas;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;FireDACMSAccDriver;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) 199 | true 200 | 201 | 202 | 1033 203 | $(BDS)\bin\default_app.manifest 204 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 205 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 206 | FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapServer;DataSnapCommon;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;IndyIPCommon;CloudService;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindengine;vclactnband;bindcompdbx;soaprtl;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDACMSSQLDriver;FireDAC;VclSmp;DBXInformixDriver;Intraweb;DataSnapConnectors;DataSnapServerMidas;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;FireDACMSAccDriver;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) 207 | true 208 | 209 | 210 | DEBUG;$(DCC_Define) 211 | true 212 | false 213 | true 214 | true 215 | true 216 | 217 | 218 | .\AndroidHeaders;.\AndroidUSBHeaders;$(DCC_UnitSearchPath) 219 | false 220 | false 221 | false 222 | false 223 | false 224 | false 225 | false 226 | false 227 | disabled 228 | center 229 | 1 230 | 231 | 232 | false 233 | 234 | 235 | false 236 | RELEASE;$(DCC_Define) 237 | 0 238 | 0 239 | 240 | 241 | 242 | MainSource 243 | 244 | 245 |
Form1
246 |
247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | Cfg_2 261 | Base 262 | 263 | 264 | Base 265 | 266 | 267 | Cfg_1 268 | Base 269 | 270 |
271 | 272 | Delphi.Personality.12 273 | Application 274 | 275 | 276 | 277 | Project2.dpr 278 | 279 | 280 | Embarcadero C++Builder Office 2000 Servers Package 281 | Embarcadero C++Builder Office XP Servers Package 282 | Microsoft Office 2000 Sample Automation Server Wrapper Components 283 | Microsoft Office XP Sample Automation Server Wrapper Components 284 | File C:\Windows\system32\FMX_UserLabBasicDsnDXE7.bpl not found 285 | File C:\Windows\system32\FMX_InstrumentLabDigitalDsnDXE7.bpl not found 286 | File C:\Windows\system32\FMX_InstrumentLabDsnDXE7.bpl not found 287 | 288 | 289 | 290 | 291 | 292 | splash_image.png 293 | true 294 | 295 | 296 | 297 | 298 | device_filter.xml 299 | true 300 | 301 | 302 | 303 | 304 | ic_launcher.png 305 | true 306 | 307 | 308 | 309 | 310 | .\assets\internal\ 311 | true 312 | 313 | 314 | 315 | 316 | libProject2.so 317 | true 318 | 319 | 320 | 321 | 322 | true 323 | 324 | 325 | 326 | 327 | true 328 | 329 | 330 | 331 | 332 | true 333 | 334 | 335 | true 336 | 337 | 338 | 339 | 340 | splash_image.png 341 | true 342 | 343 | 344 | 345 | 346 | device_filter.xml 347 | true 348 | 349 | 350 | 351 | 352 | classes.dex 353 | true 354 | 355 | 356 | 357 | 358 | libProject2.so 359 | true 360 | 361 | 362 | 363 | 364 | ic_launcher.png 365 | true 366 | 367 | 368 | 369 | 370 | device_filter.xml 371 | true 372 | 373 | 374 | 375 | 376 | ic_launcher.png 377 | true 378 | 379 | 380 | 381 | 382 | libProject2.so 383 | true 384 | 385 | 386 | 387 | 388 | splash_image.png 389 | true 390 | 391 | 392 | 393 | 394 | ic_launcher.png 395 | true 396 | 397 | 398 | 399 | 400 | splash_image.png 401 | true 402 | 403 | 404 | 405 | 406 | device_filter.xml 407 | true 408 | 409 | 410 | 411 | 412 | device_filter.xml 413 | true 414 | 415 | 416 | 417 | 418 | libProject2.so 419 | true 420 | 421 | 422 | 423 | 424 | ic_launcher.png 425 | true 426 | 427 | 428 | 429 | 430 | Project2.exe 431 | true 432 | 433 | 434 | 435 | 436 | device_filter.xml 437 | true 438 | 439 | 440 | 441 | 442 | device_filter.xml 443 | true 444 | 445 | 446 | 447 | 448 | true 449 | 450 | 451 | 452 | 453 | device_filter.xml 454 | true 455 | 456 | 457 | 458 | 459 | device_filter.xml 460 | true 461 | 462 | 463 | 464 | 465 | true 466 | 467 | 468 | 469 | 470 | device_filter.xml 471 | true 472 | 473 | 474 | 475 | 476 | res\xml 477 | true 478 | 479 | 480 | 481 | 482 | device_filter.xml 483 | true 484 | 485 | 486 | 487 | 488 | 1 489 | .dylib 490 | 491 | 492 | 0 493 | .bpl 494 | 495 | 496 | Contents\MacOS 497 | 1 498 | .dylib 499 | 500 | 501 | 1 502 | .dylib 503 | 504 | 505 | 506 | 507 | 1 508 | .dylib 509 | 510 | 511 | 0 512 | .dll;.bpl 513 | 514 | 515 | Contents\MacOS 516 | 1 517 | .dylib 518 | 519 | 520 | 1 521 | .dylib 522 | 523 | 524 | 525 | 526 | 1 527 | 528 | 529 | 1 530 | 531 | 532 | 533 | 534 | Contents 535 | 1 536 | 537 | 538 | 539 | 540 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 541 | 1 542 | 543 | 544 | 545 | 546 | res\drawable-normal 547 | 1 548 | 549 | 550 | 551 | 552 | library\lib\x86 553 | 1 554 | 555 | 556 | 557 | 558 | 1 559 | 560 | 561 | 1 562 | 563 | 564 | 565 | 566 | ../ 567 | 1 568 | 569 | 570 | 571 | 572 | library\lib\armeabi-v7a 573 | 1 574 | 575 | 576 | 577 | 578 | 1 579 | 580 | 581 | 1 582 | 583 | 584 | 585 | 586 | res\drawable-xlarge 587 | 1 588 | 589 | 590 | 591 | 592 | res\drawable-xhdpi 593 | 1 594 | 595 | 596 | 597 | 598 | 1 599 | 600 | 601 | 1 602 | 603 | 604 | 605 | 606 | res\drawable-xxhdpi 607 | 1 608 | 609 | 610 | 611 | 612 | library\lib\mips 613 | 1 614 | 615 | 616 | 617 | 618 | res\drawable 619 | 1 620 | 621 | 622 | 623 | 624 | Contents\MacOS 625 | 1 626 | 627 | 628 | 1 629 | 630 | 631 | 0 632 | 633 | 634 | 635 | 636 | Contents\MacOS 637 | 1 638 | .framework 639 | 640 | 641 | 0 642 | 643 | 644 | 645 | 646 | res\drawable-small 647 | 1 648 | 649 | 650 | 651 | 652 | ../ 653 | 1 654 | 655 | 656 | 657 | 658 | Contents\MacOS 659 | 1 660 | 661 | 662 | 1 663 | 664 | 665 | Contents\MacOS 666 | 0 667 | 668 | 669 | 670 | 671 | classes 672 | 1 673 | 674 | 675 | 676 | 677 | 1 678 | 679 | 680 | 1 681 | 682 | 683 | 684 | 685 | 1 686 | 687 | 688 | 1 689 | 690 | 691 | 692 | 693 | res\drawable 694 | 1 695 | 696 | 697 | 698 | 699 | Contents\Resources 700 | 1 701 | 702 | 703 | 704 | 705 | 1 706 | 707 | 708 | 709 | 710 | 1 711 | 712 | 713 | 1 714 | 715 | 716 | 717 | 718 | 1 719 | 720 | 721 | library\lib\armeabi-v7a 722 | 1 723 | 724 | 725 | 0 726 | 727 | 728 | Contents\MacOS 729 | 1 730 | 731 | 732 | 1 733 | 734 | 735 | 736 | 737 | library\lib\armeabi 738 | 1 739 | 740 | 741 | 742 | 743 | res\drawable-large 744 | 1 745 | 746 | 747 | 748 | 749 | 0 750 | 751 | 752 | 0 753 | 754 | 755 | 0 756 | 757 | 758 | Contents\MacOS 759 | 0 760 | 761 | 762 | 0 763 | 764 | 765 | 766 | 767 | 1 768 | 769 | 770 | 1 771 | 772 | 773 | 774 | 775 | res\drawable-ldpi 776 | 1 777 | 778 | 779 | 780 | 781 | res\values 782 | 1 783 | 784 | 785 | 786 | 787 | 1 788 | 789 | 790 | 1 791 | 792 | 793 | 794 | 795 | res\drawable-mdpi 796 | 1 797 | 798 | 799 | 800 | 801 | res\drawable-hdpi 802 | 1 803 | 804 | 805 | 806 | 807 | 1 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | True 819 | True 820 | True 821 | True 822 | True 823 | True 824 | 825 | 826 | 12 827 | 828 | 829 | 830 | 831 |
832 | --------------------------------------------------------------------------------