PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » OpenSource » Модуль для работы с USB HID


Модуль для работы с USB HID

Сообщений 1 страница 5 из 5

1

Нужна версия PureBasic 5.20 и выше.

Код модуля.

Код:
DeclareModule HID

;-DeclareModule

Structure HID_CAPS
  Usage.w
  UsagePage.w
  InputReportByteLength.w
  OutputReportByteLength.w
  FeatureReportByteLength.w
  Reserved.w[17]
  NumberLinkCollectionNodes.w
  NumberInputButtonCaps.w
  NumberInputValueCaps.w
  NumberInputDataIndices.w
  NumberOutputButtonCaps.w
  NumberOutputValueCaps.w
  NumberOutputDataIndices.w
  NumberFeatureButtonCaps.w
  NumberFeatureValueCaps.w
  NumberFeatureDataIndices.w
EndStructure

Structure HID_Sub_DeviceInfo
  VendorID.u
  ProductID.u
  VersionNumber.u
  NumInputBuffers.u
  InputReportByteLength.u
  OutputReportByteLength.u
  FeatureReportByteLength.u
  Manufacturer.s
  Product.s
  SerialNumber.s
EndStructure

Structure HID_DeviceInfo
  CountDevice.w              ; Число обнаруженных HID устройств
  DeviceInfo.HID_Sub_DeviceInfo[258]
EndStructure


Structure HID_Attributes
  VID.u
  PID.u
  VersionNumber.u
EndStructure

Declare HID_Init()
Declare HID_End()
Declare OpenDevice(PID.u, VID.u, VersionNumber.w=-1, Index.u=0)
Declare CloseDevice(hDevice)
Declare TestDevice(PID.u, VID.u, VersionNumber.w=-1, Index.u=0)
Declare DeviceInfo(*Info.HID_DeviceInfo)
Declare ReadDevice(hDevice, *Buffer, Len)
Declare WriteDevice(hDevice, *Buffer, Len)
Declare GetFeature(hDevice, *Buffer, Len)
Declare SetFeature(hDevice, *Buffer, Len)
Declare GetInputReport(hDevice, *Buffer, Len)
Declare SetOutputReport(hDevice, *Buffer, Len)
Declare GetCaps(hDevice, *Capabilities.HID_CAPS)
 ; Узнаём по хендлу устройства, его PID, VID и номер версии.
Declare GetAttributes(hDevice, *DeviceInfo.HID_Attributes)
Declare GetNumInputBuffers(hDevice)
Declare.s GetManufacturerString(hDevice)
Declare.s GetProductString(hDevice)
Declare.s GetSerialNumberString(hDevice)
Declare.s GetIndexedString(hDevice, Index)

EndDeclareModule




Module HID


Structure HIDD_ATTRIBUTES
  Size.l
  VendorID.u
  ProductID.u
  VersionNumber.w
EndStructure

Structure PSP_DEVICE_INTERFACE_DETAIL_DATA
  cbSize.l
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    DevicePath.l
  CompilerElse 
    DevicePath.c
  CompilerEndIf
EndStructure

CompilerIf Defined(SP_DEVICE_INTERFACE_DATA, #PB_Structure)=0
  Structure SP_DEVICE_INTERFACE_DATA
    cbSize.l
    InterfaceClassGuid.GUID
    Flags.l
    Reserved.l
  EndStructure
CompilerEndIf

EnableExplicit
Define.i

Prototype pGetHidGuid(*HidGuid.GUID)
Prototype pGetAttributes(*HidDeviceObject, *Attributes.HIDD_ATTRIBUTES)
Prototype pGetPreparsedData(*HidDeviceObject, *PreparsedData)
Prototype pGetCaps(*PreparsedData, *Capabilities.HID_CAPS)
Prototype pFreePreparsedData(PreparsedData)
Prototype pGetNumInputBuffers(HidHandle, *NumInputBuffers)
Prototype pGetManufacturerString(HidHandle, *Buffer, Len)
Prototype pGetProductString(HidHandle, *Buffer, Len)
Prototype pGetSerialNumberString(HidHandle, *Buffer, Len)
Prototype pGetIndexedString(HidHandle, Index, *Buffer, Len)
Prototype pGetFeature(HidHandle, *Buffer, Len)
Prototype pSetFeature(HidHandle, *Buffer, Len)
Prototype pGetInputReport(HidHandle, *Buffer, Len)
Prototype pSetOutputReport(HidHandle, *Buffer, Len)
Prototype pSetupDiEnumDeviceInterfaces(*DeviceInfoSet, DeviceInfoData, *InterfaceClassGuid.GUID,
                                       MemberIndex, *DeviceInterfaceData.SP_DEVICE_INTERFACE_DATA)
Prototype pSetupDiGetDeviceInterfaceDetail(*DeviceInfoSet, *DeviceInterfaceData.SP_DEVICE_INTERFACE_DATA,
                                           DeviceInterfaceDetailData, DeviceInterfaceDetailDataSize, 
                                           *RequiredSize, *DeviceInfoData)

Define hid_Lib, Setupapi_Lib, OS_Version

Procedure HID_Init()
  Shared hid_Lib, Setupapi_Lib, OS_Version
  
  OS_Version = OSVersion()
  
  hid_Lib=LoadLibrary_("hid.dll")
  Setupapi_Lib=LoadLibrary_("setupapi.dll")
  
  Global fGetHidGuid.pGetHidGuid=GetProcAddress_(hid_Lib, ?GetHidGuid)
  Global fGetAttributes.pGetAttributes=GetProcAddress_(hid_Lib, ?GetAttributes)
  Global fGetPreparsedData.pGetPreparsedData=GetProcAddress_(hid_Lib, ?GetPreparsedData)
  Global fFreePreparsedData.pFreePreparsedData=GetProcAddress_(hid_Lib, ?FreePreparsedData)
  Global fGetCaps.pGetCaps=GetProcAddress_(hid_Lib, ?GetCaps)
  Global fGetInputReport.pGetInputReport=GetProcAddress_(hid_Lib, ?GetInputReport)
  Global fSetOutputReport.pSetOutputReport=GetProcAddress_(hid_Lib, ?SetOutputReport)
  Global fGetFeature.pGetFeature=GetProcAddress_(hid_Lib, ?GetFeature)
  Global fSetFeature.pSetFeature=GetProcAddress_(hid_Lib, ?SetFeature)
  Global fGetNumInputBuffers.pGetNumInputBuffers=GetProcAddress_(hid_Lib, ?GetNumInputBuffers)
  Global fGetManufacturerString.pGetManufacturerString=GetProcAddress_(hid_Lib, ?GetManufacturerString)
  Global fGetProductString.pGetProductString=GetProcAddress_(hid_Lib, ?GetProductString)
  Global fGetSerialNumberString.pGetSerialNumberString=GetProcAddress_(hid_Lib, ?GetSerialNumberString)
  Global fGetIndexedString.pGetIndexedString=GetProcAddress_(hid_Lib, ?GetIndexedString)
  Global fSetupDiEnumDeviceInterfaces.pSetupDiEnumDeviceInterfaces=GetProcAddress_(Setupapi_Lib,
                                                                                   ?SetupDiEnumDeviceInterfaces)
  Global fSetupDiGetDeviceInterfaceDetail.pSetupDiGetDeviceInterfaceDetail=GetProcAddress_(Setupapi_Lib,
                                                                                           ?Setup_InterfaceDetail)
  
  DataSection
    
    GetHidGuid:
    ! db "HidD_GetHidGuid", 0, 0
    
    GetAttributes:
    ! db "HidD_GetAttributes", 0, 0
    
    GetPreparsedData:
    ! db "HidD_GetPreparsedData", 0, 0
    
    FreePreparsedData:
    ! db "HidD_FreePreparsedData", 0, 0
    
    GetCaps:
    ! db "HidP_GetCaps", 0, 0
    
    GetInputReport:
    ! db "HidD_GetInputReport", 0, 0
    
    SetOutputReport:
    ! db "HidD_SetOutputReport", 0, 0
    
    GetFeature:
    ! db "HidD_GetFeature", 0, 0
    
    SetFeature:
    ! db "HidD_SetFeature", 0, 0
    
    GetNumInputBuffers:
    ! db "HidD_GetNumInputBuffers", 0, 0
    
    GetManufacturerString:
    ! db "HidD_GetManufacturerString", 0, 0
    
    GetProductString:
    ! db "HidD_GetProductString", 0, 0
    
    GetSerialNumberString:
    ! db "HidD_GetSerialNumberString", 0, 0
    
    GetIndexedString:
    ! db "HidD_GetIndexedString", 0, 0
    
    SetupDiEnumDeviceInterfaces:
    ! db "SetupDiEnumDeviceInterfaces", 0, 0
    
    Setup_InterfaceDetail:
    CompilerIf #PB_Compiler_Unicode=0
      ! db "SetupDiGetDeviceInterfaceDetailA", 0, 0
    CompilerElse
      ! db "SetupDiGetDeviceInterfaceDetailW", 0, 0
    CompilerEndIf
    
  EndDataSection
  
EndProcedure

Procedure HID_End()
  Shared hid_Lib, Setupapi_Lib
  If hid_Lib
    FreeLibrary_(hid_Lib)
  EndIf
  If Setupapi_Lib
    FreeLibrary_(Setupapi_Lib)
  EndIf
EndProcedure

Procedure FunctInfo(hDevice, *Info.HID_DeviceInfo)
  Protected Attributes.HIDD_ATTRIBUTES, i
  Protected HIDP_CAPS.HID_CAPS
    
  Attributes\Size = SizeOf(HIDD_ATTRIBUTES)
  
  If fGetAttributes(hDevice, @Attributes)
    
    i = *Info\CountDevice
    *Info\CountDevice+1
    
    *Info\DeviceInfo[i]\VendorID        = Attributes\VendorID
    *Info\DeviceInfo[i]\ProductID       = Attributes\ProductID
    *Info\DeviceInfo[i]\VersionNumber   = Attributes\VersionNumber
    
    *Info\DeviceInfo[i]\Manufacturer    = GetManufacturerString(hDevice)
    *Info\DeviceInfo[i]\Product         = GetProductString(hDevice)
    *Info\DeviceInfo[i]\SerialNumber    = GetSerialNumberString(hDevice)
    *Info\DeviceInfo[i]\NumInputBuffers = GetNumInputBuffers(hDevice)
    GetCaps(hDevice, @HIDP_CAPS)
    *Info\DeviceInfo[i]\InputReportByteLength   = HIDP_CAPS\InputReportByteLength
    *Info\DeviceInfo[i]\OutputReportByteLength  = HIDP_CAPS\OutputReportByteLength
    *Info\DeviceInfo[i]\FeatureReportByteLength = HIDP_CAPS\FeatureReportByteLength
    
  EndIf
  
EndProcedure

; Получение доступа к HID устройству
Procedure Open_HID_Device(PID.u, VID.u, VersionNumber.w=-1, Index.u=0, *Funct=0, *Info.HID_DeviceInfo=0)
  Protected HidGuid.Guid
  Protected devInfoData.SP_DEVICE_INTERFACE_DATA
  Protected Attributes.HIDD_ATTRIBUTES, Security.SECURITY_ATTRIBUTES
  Protected *detailData.PSP_DEVICE_INTERFACE_DETAIL_DATA
  Protected Length.l, CurrentIndex.w, hDevInfo
  Protected i, Result, DevicePath.s
  Protected Required, hDevice
  
  If fGetHidGuid=0 Or fSetupDiEnumDeviceInterfaces=0 Or
     fSetupDiGetDeviceInterfaceDetail=0 Or fGetAttributes=0
    ProcedureReturn 0
  EndIf
  
  devInfoData\cbSize = SizeOf(SP_DEVICE_INTERFACE_DATA)
  
  Security\nLength=SizeOf(SECURITY_ATTRIBUTES)
  Security\bInheritHandle=1
  Security\lpSecurityDescriptor = 0
  
  fGetHidGuid(@HidGuid)
  
  hDevInfo=SetupDiGetClassDevs_(@HidGuid,0,0, #DIGCF_PRESENT|#DIGCF_DEVICEINTERFACE)
  If hDevInfo=0
    ProcedureReturn 0
  EndIf
  
  
  For i=0 To 255
    
    Result=fSetupDiEnumDeviceInterfaces(hDevInfo, 0, @HidGuid, i, @devInfoData)
    If Result
      Result = fSetupDiGetDeviceInterfaceDetail(hDevInfo, @devInfoData, 0, 0,@Length, 0)
      *detailData=AllocateMemory(Length)
      *detailData\cbSize=SizeOf(PSP_DEVICE_INTERFACE_DETAIL_DATA)
      Result = fSetupDiGetDeviceInterfaceDetail(hDevInfo, @devInfoData, *detailData, Length+1, @Required, 0)
      
      DevicePath.s=PeekS(@*detailData\DevicePath)
      FreeMemory(*detailData)
      
      hDevice=CreateFile_(@DevicePath, #GENERIC_READ|#GENERIC_WRITE,
                          #FILE_SHARE_READ|#FILE_SHARE_WRITE, @Security, #OPEN_EXISTING, 0, 0)
      
      If hDevice<>#INVALID_HANDLE_VALUE
        
        If *Funct And *Info
          
          CallFunctionFast(*Funct, hDevice, *Info)
          CloseHandle_(hDevice)
          
        Else
          
          Attributes\Size = SizeOf(HIDD_ATTRIBUTES)
          Result = fGetAttributes(hDevice, @Attributes)
          
          If Attributes\ProductID=PID And Attributes\VendorID=VID And 
             (Attributes\VersionNumber=VersionNumber Or VersionNumber=-1 ) 
            If CurrentIndex=Index
              SetupDiDestroyDeviceInfoList_(hDevInfo)
              ProcedureReturn hDevice
            Else
              CurrentIndex+1
              CloseHandle_(hDevice)
            EndIf 
          Else
            CloseHandle_(hDevice)
          EndIf 
          
        EndIf
        
      EndIf
    Else
      Break 
    EndIf
  Next i
  
  SetupDiDestroyDeviceInfoList_(hDevInfo)
  ProcedureReturn 0
EndProcedure

Procedure OpenDevice(PID.u, VID.u, VersionNumber.w=-1, Index.u=0)
  ProcedureReturn Open_HID_Device(PID, VID, VersionNumber, Index, 0, 0)
EndProcedure

Procedure CloseDevice(hDevice) ; Закрытие HID устройства.
  If hDevice
    ProcedureReturn CloseHandle_(hDevice)
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure TestDevice(PID.u, VID.u, VersionNumber.w=-1, Index.u=0)
  Protected hHid.i, Result
  
  hHid=OpenDevice(PID, VID, VersionNumber, Index)
  If hHid
    CloseDevice(hHid)
    Result=#True
  Else
    Result=#False
  EndIf
  
  ProcedureReturn Result
EndProcedure

Procedure DeviceInfo(*Info.HID_DeviceInfo)
  If *Info
    ClearStructure(*Info, HID_DeviceInfo)
    Open_HID_Device(0, 0, 0, 0, @FunctInfo(), *Info)
    ProcedureReturn Bool(*Info\CountDevice>0)
  EndIf
EndProcedure

Procedure ReadDevice(hDevice, *Buffer, Len) ; Чтение данных из HID устройства
  Protected Written.l=0
  
  If hDevice=0 Or *Buffer=0 Or Len<=0
    ProcedureReturn 0
  EndIf
  
  ReadFile_(hDevice, *Buffer, Len, @Written, 0)
  ProcedureReturn Written
EndProcedure

Procedure WriteDevice(hDevice, *Buffer, Len) ; Запись данных в HID устройство
  Protected Written.l=0
  
  If hDevice=0 Or *Buffer=0 Or Len<=0
    ProcedureReturn 0
  EndIf
  
  WriteFile_(hDevice, *Buffer, Len, @Written,  0)
  ProcedureReturn Written
EndProcedure


Procedure GetFeature(hDevice, *Buffer, Len)
  If hDevice And *Buffer And Len>0 And fGetFeature
    ProcedureReturn fGetFeature(hDevice, *Buffer, Len)
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure SetFeature(hDevice, *Buffer, Len)
  If hDevice And *Buffer And Len>0 And fSetFeature
    ProcedureReturn fSetFeature(hDevice, *Buffer, Len)
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

 ; Чтение входного репорта. ВНИМАНИЕ функция появилась только в WinXP
Procedure GetInputReport(hDevice, *Buffer, Len)
  Shared OS_Version
  If hDevice And *buffer And Len>0 And
     OS_Version>=#PB_OS_Windows_XP And fGetInputReport
    ProcedureReturn fGetInputReport(hDevice, *Buffer, Len)
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

 ; Запись в устройство выходного репорта. ВНИМАНИЕ функция появилась только в WinXP
Procedure SetOutputReport(hDevice, *Buffer, Len)
  Shared OS_Version
  If hDevice And *buffer And Len>0 And
     OS_Version>=#PB_OS_Windows_XP And fSetOutputReport
    ProcedureReturn fSetOutputReport(hDevice, *Buffer, Len)
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure GetCaps(hDevice, *Capabilities.HID_CAPS) ; Узнаём размеры буферов и др. информацию об устройстве
  Protected result=0, PreparsedData
  If hDevice And fGetPreparsedData And
     fGetCaps And fFreePreparsedData
    
    If fGetPreparsedData(hDevice, @PreparsedData) 
      fGetCaps(PreparsedData, *Capabilities) 
      fFreePreparsedData(PreparsedData)
      result=1
    EndIf  
    
  EndIf
  ProcedureReturn result
EndProcedure

 ; Узнаём по хендлу устройства, его PID, VID и номер версии.
Procedure GetAttributes(hDevice, *DeviceInfo.HID_Attributes)
  Protected Info.HIDD_ATTRIBUTES, Result=#False
  
  If hDevice And *DeviceInfo And fGetAttributes
    Info\Size = SizeOf(HIDD_ATTRIBUTES)
    If fGetAttributes(hDevice, @Info)
      CopyMemory(@Info+OffsetOf(HIDD_ATTRIBUTES\VendorID), *DeviceInfo, SizeOf(HID_Attributes))
      Result=#True
    EndIf
  EndIf
  
  ProcedureReturn Result
EndProcedure

Procedure GetNumInputBuffers(hDevice)
  Protected NumInputBuffers=0
  If hDevice And fGetNumInputBuffers
    fGetNumInputBuffers(hDevice, @NumInputBuffers)
  EndIf
  ProcedureReturn NumInputBuffers
EndProcedure

Procedure.s GetManufacturerString(hDevice) ; Получаем идентификатор изготовителя
  Protected Result.s="", *mem
  If hDevice And fGetManufacturerString
    *mem=AllocateMemory(256)
    If *mem
      If fGetManufacturerString(hDevice, *mem, 252)
        Result=PeekS(*mem,-1,#PB_Unicode)
      EndIf
      FreeMemory(*mem)
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.s GetProductString(hDevice) ; Получаем идентификатор продукта
  Protected Result.s="", *mem
  If hDevice And fGetProductString
    *mem=AllocateMemory(256)
    If *mem
      If fGetProductString(hDevice, *mem, 252)
        Result=PeekS(*mem,-1,#PB_Unicode)
      EndIf
      FreeMemory(*mem)
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.s GetSerialNumberString(hDevice) ; Получаем серийный номер продукта
  Protected Result.s="", *mem
  If hDevice And fGetSerialNumberString
    *mem=AllocateMemory(256)
    If *mem
      If fGetSerialNumberString(hDevice, *mem, 252)
        Result=PeekS(*mem,-1,#PB_Unicode)
      EndIf
      FreeMemory(*mem)
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure.s GetIndexedString(hDevice, Index) ; Чтение строки по её индексу из устройства
  Protected Result.s="", *mem
  If hDevice And fGetIndexedString
    *mem=AllocateMemory(256)
    If *mem
      If fGetIndexedString(hDevice, Index, *mem, 252)
        Result=PeekS(*mem,-1,#PB_Unicode)
      EndIf
      FreeMemory(*mem)
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure

EndModule

Примеры использования модуля.

Кликните чтобы увидеть примеры.

Проверка наличия устройства с идентификаторами PID=1 и VID=$1234.

Код:
#USB_PID=1
#USB_VID=$1234

XIncludeFile "HID_Module.pbi"

Procedure Timer1()
If HID::TestDevice(#USB_PID, #USB_VID)=1
  SetGadgetText(1,"Устройство подключено")
  SetGadgetColor(1,#PB_Gadget_FrontColor,$92616D)
Else
  SetGadgetText(1,"Устройство отсутствует")
  SetGadgetColor(1,#PB_Gadget_FrontColor,$0000FF)
EndIf
EndProcedure

HID::HID_Init()

OpenWindow(0,0,0,280,100,"HID_Lib_DeviceTest",#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
TextGadget(0,40,10,200,16,"PID - "+Hex(#USB_PID)+"H;    VID - "+Hex(#USB_VID)+"H",#PB_Text_Center )
TextGadget(1,80,40,200,16,"")
Timer1()
AddWindowTimer(0, 1, 500)

Repeat
  Event=WaitWindowEvent()
  If Event=#PB_Event_Timer
    If  EventTimer()=1
      Timer1()
    EndIf
  EndIf
Until Event = #PB_Event_CloseWindow

HID::HID_End()

Информация об всех HID устройствах.

Код:
XIncludeFile "HID_Module.pbi"

Procedure HID_DeviceInfo()
  ClearGadgetItems(0)
  Info.HID::HID_DeviceInfo
  If HID::DeviceInfo(@Info)
    If Info\CountDevice>0
      For i=0 To Info\CountDevice-1
        AddGadgetItem(0,i,Info\DeviceInfo[i]\Manufacturer)
        SetGadgetItemText(0,i,Info\DeviceInfo[i]\Product,1)
        SetGadgetItemText(0,i,Hex(Info\DeviceInfo[i]\ProductID,#PB_Word)+"H",2)
        SetGadgetItemText(0,i,Hex(Info\DeviceInfo[i]\VendorID,#PB_Word)+"H",3)
        SetGadgetItemText(0,i,Hex(Info\DeviceInfo[i]\VersionNumber,#PB_Word)+"H",4)
        SetGadgetItemText(0,i,Info\DeviceInfo[i]\SerialNumber,5)
        SetGadgetItemText(0,i,Str(Info\DeviceInfo[i]\NumInputBuffers),6)
        SetGadgetItemText(0,i,Str(Info\DeviceInfo[i]\InputReportByteLength),7)
        SetGadgetItemText(0,i,Str(Info\DeviceInfo[i]\OutputReportByteLength),8)
        SetGadgetItemText(0,i,Str(Info\DeviceInfo[i]\FeatureReportByteLength),9)
      Next i
    EndIf
  EndIf
EndProcedure

HID::HID_Init()

OpenWindow(0,0,0,930,294,"Иформация о USB HID устройствах",#PB_Window_MinimizeGadget|#PB_Window_Invisible|#PB_Window_ScreenCentered)
ListIconGadget(0,2,2,924,290,"Изготовитель",100,#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect)
AddGadgetColumn(0,1,"Продукт",100)
AddGadgetColumn(0,2,"PID",48)
AddGadgetColumn(0,3,"VID",48)
AddGadgetColumn(0,4,"Номер версии",90)
AddGadgetColumn(0,5,"Серийный номер",104)
AddGadgetColumn(0,6,"Число вх. буферов",110)
AddGadgetColumn(0,7,"Размер вх. репорта",120)
AddGadgetColumn(0,8,"Размер вых. репорта",124)
AddGadgetColumn(0,9,"FEATURE",70)
HID_DeviceInfo()
HideWindow(0,0)

AddWindowTimer(0, 1, 400)

Repeat
  Event=WaitWindowEvent()
  If Event=#PB_Event_Timer
    If  EventTimer()=1
      HID_DeviceInfo()
    EndIf
  EndIf
Until Event = #PB_Event_CloseWindow

HID::HID_End()

Два примера отсюда. http://pure-basic.narod.ru/article/pickit2.html

Код:
#USB_PID       = $33  ; Идентификаторы программатора PicKit2.
#USB_VID       = $4D8

#END_OF_BUFFER = $AD  ; Этим заполняется пустое пространство в буфере.
#PACKET_SIZE   =  65  ; Размер HID репорта программатора.

XIncludeFile "HID_Module.pbi"

Procedure VddOn(Handle) ; Включить питание
  Dim OutBuffer.a(#PACKET_SIZE+2)
  FillMemory(@OutBuffer()+1, #PACKET_SIZE, #END_OF_BUFFER, #PB_Byte)  ; Заполнение массива, данными из константы #END_OF_BUFFER
  OutBuffer(0)=0
  OutBuffer(1)=$A6 ; EXECUTE_SCRIPT
  OutBuffer(2)=2
  OutBuffer(3)=$FC ; _VDD_GND_OFF
  OutBuffer(4)=$FF ; _VDD_ON
  ProcedureReturn HID::WriteDevice(Handle, @OutBuffer(), #PACKET_SIZE) ; Передача данных в программатор PICkit2
EndProcedure

Procedure VddOff(Handle) ; Выключить питание
  Dim OutBuffer.a(#PACKET_SIZE+2)
  FillMemory(@OutBuffer()+1, #PACKET_SIZE, #END_OF_BUFFER, #PB_Byte)  ; Заполнение массива, данными из константы #END_OF_BUFFER
  OutBuffer(0)=0
  OutBuffer(1)=$A6 ; EXECUTE_SCRIPT
  OutBuffer(2)=2
  OutBuffer(3)=$FE ; _VDD_OFF
  OutBuffer(4)=$FD ; _VDD_GND_ON
  ProcedureReturn HID::WriteDevice(Handle, @OutBuffer(), #PACKET_SIZE) ; Передача данных в программатор PICkit2
EndProcedure

HID::HID_Init()

Handle=HID::OpenDevice(#USB_PID, #USB_VID) ; Установка связи с PicKit2
If Handle
  VddOn(Handle)  ; Включить питание
  Delay(2000)    ; Пауза 2 секунды
  VddOff(Handle) ; Выключить питание
  HID::CloseDevice(Handle)  ; Разрыв связи с PicKit2
Else
  MessageRequester("", "Нет связи с PicKit2!", 48)
EndIf

HID::HID_End()
Код:
#USB_PID       = $33  ; Идентификаторы программатора PicKit2.
#USB_VID       = $4D8

#END_OF_BUFFER = $AD  ; Этим заполняеся пустое просторанство в буфере.
#PACKET_SIZE   =  65  ; Размер HID репорта программатора.

#NO_Device = "Нет связи с PicKit2"

XIncludeFile "HID_Module.pbi"

Procedure.u Read_Status(Handle) ; Чтение состояния программатора PicKit2.
  
  ; Data[1]  = Status Low
  ;       <7> unused
  ;       <6> 1 = PICkit 2 button pressed
  ;       <5> 1 = VppError (Vpp < Vfault)
  ;       <4> 1 = VddError (Vdd < Vfault)
  ;       <3> 1 = Vpp On
  ;       <2> 1 = Vpp GND On
  ;       <1> 1 = Vdd On
  ;       <0> 1 = Vdd GND On
  ; Data[2] = Status High
  ;       <7> 1 = Download Buffer Overflow
  ;       <6> 1 = Script Buffer Overflow, invalid
  ;                     Script length Or index
  ;       <5> 1 = Run Script on Empty Script
  ;       <4> 1 = Script abort- download empty
  ;       <3> 1 = Script abort- upload full
  ;       <2> 1 = ICD transfer timeout/Bus Error
  ;       <1> 1 = UART Mode enabled
  ;       <0> 1 = PICkit 2 reset since last 
  ;                     Status Read.
  ; NOTE: Turns BUSY_LED off.
  
  St.u=0                          ; Переменная типа Unicode (беззнаковая, 2 байта)
  Dim InBuffer.a(#PACKET_SIZE+2)  ; Массив, использующися как буфер приёма от PICkit2.
  Dim OutBuffer.a(#PACKET_SIZE+2) ; Массив, использующися как буфер передачи в PICkit2.
  FillMemory(@OutBuffer()+1, #PACKET_SIZE, #END_OF_BUFFER, #PB_Byte)  ; Заполнение массива, данными из константы #END_OF_BUFFER.
  OutBuffer(0)=0
  OutBuffer(1)=$A2 ; READ_STATUS
  If HID::WriteDevice(Handle, @OutBuffer(), #PACKET_SIZE) = #PACKET_SIZE  ; Передача данных в программатор PICkit2.
    If HID::ReadDevice(Handle, @InBuffer(), #PACKET_SIZE) = #PACKET_SIZE  ; Чтение данных из программатора PICkit2.
      CopyMemory(@InBuffer()+1, @St, 2)                                      ; Копирование данных из массива в переменную.
    EndIf
  EndIf
  
  ProcedureReturn St
EndProcedure


Procedure Timer1() ; Эта процедура вызывается по таймеру, каждые 100 мс.
  Shared Handle
  Static Old_Test
  Test=HID::TestDevice(#USB_PID, #USB_VID) ; Есть ли требуемое USB HID устройство?
  If Test<>Old_Test
    Old_Test=Test
    If Test 
      HID::CloseDevice(Handle)
      Handle=HID::OpenDevice(#USB_PID, #USB_VID) ; Подключение к USB HID устройству.
      SetGadgetText(0,"PicKit2 подключён")
    Else
      HID::CloseDevice(Handle)                   ; Разрыв связи с USB HID устройством.
      Handle=0
      SetGadgetText(0,#NO_Device)
      SetGadgetText(2,"НЕТ")
    EndIf
  EndIf
  
  If Test=1                       ; Программатор подключён PICkit2 и нормально работает.
    Status.u=Read_Status(Handle)  ; Получаем данные о статусе программатора
    If Status & %01000000 >0      ; и выделяем данные о состоянии кнопки.
      SetGadgetText(2,"ДА")
    Else
      SetGadgetText(2,"НЕТ")
    EndIf
  EndIf
EndProcedure

HID::HID_Init()

; Открываем окно
OpenWindow(0,0,0,140,80,"PICkit2",#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
TextGadget(0,2,2,140,16, #NO_Device, #PB_Text_Center) ; Здесь отображается полключён ли PicKit2.
TextGadget(1,10,40,80,16,"Нажата кнопка")
TextGadget(2,100,40,40,16,"НЕТ")                      ; Здесь отображается состояние кнопки.
SetGadgetColor(2, #PB_Gadget_FrontColor, $FD0402)
AddWindowTimer(0,1,100)                                  ; Запуск таймера с периодом 100 мс.
Repeat                                                   ; Начало главного цикла
  Event=WaitWindowEvent()
  If Event=#PB_Event_Timer And EventTimer()=1           ; Сработал таймер.
    Timer1()  
  EndIf
Until Event=#PB_Event_CloseWindow                        ; Событие закрытия окна - прерываем цикл.

HID::HID_End()

Пример отсюда. Простое USB HID устройство на ATmega8.

Код:
#USB_PID=1
#USB_VID=$1234
Global W_DeviceHandle=0, R_DeviceHandle=0

XIncludeFile "HID_Module.pbi"

Procedure FindDevice_Timer()
Static Old_Test
Test=HID::TestDevice(#USB_PID, #USB_VID)
 If Test<>Old_Test
  Old_Test=Test
  If Test 
     HID::CloseDevice(W_DeviceHandle)
     HID::CloseDevice(R_DeviceHandle)
     W_DeviceHandle=HID::OpenDevice(#USB_PID, #USB_VID)
     R_DeviceHandle=HID::OpenDevice(#USB_PID, #USB_VID)
     SetGadgetText(1,"Подключено HID устройство")
  Else
     HID::CloseDevice(W_DeviceHandle)
     HID::CloseDevice(R_DeviceHandle)
     W_DeviceHandle=0 : R_DeviceHandle=0
     SetGadgetText(1,"Устройство не обнаруженно ( PID — "+Hex(#USB_PID)+"H;  VID — "+Hex(#USB_VID)+"H) ")
     SetGadgetText(5,"Нет")
  EndIf
 EndIf
EndProcedure

Procedure SendDevice(Command.w)
 If W_DeviceHandle
   HID::WriteDevice(W_DeviceHandle, @Command,2)
 Else
   MessageRequester("", "Нет связи с устройством!", #MB_OK|#MB_ICONWARNING)
 EndIf
EndProcedure

Procedure Thread(*xx)
Dim InBuffer.b(2)
 Repeat
   If R_DeviceHandle
     HID::ReadDevice(R_DeviceHandle, @InBuffer(), 2)
       If InBuffer(1)=20
         SetGadgetText(5,"Да")
       ElseIf InBuffer(1)=40
         SetGadgetText(5,"Нет")
       EndIf
   EndIf
   Delay(10)
 ForEver
EndProcedure

HID::HID_Init()

OpenWindow(0,0,0,320,100,"Пример работы с HID устройством",#PB_Window_MinimizeGadget|#PB_Window_Invisible|#PB_Window_ScreenCentered)
   TextGadget(1,10,10,300,16,"Устройство не обнаруженно ( PID — "+Hex(#USB_PID)+"H;  VID — "+Hex(#USB_VID)+"H )",#PB_Text_Center)
   ButtonGadget(2,40,70,120,24,"Зажечь светодиод")
   ButtonGadget(3,170,70,120,24,"Погасить светодиод")
   TextGadget(4,50,40,98,16,"Кнопка нажата?")
   StringGadget(5,140,36,40,20,"Нет",1|#PB_String_ReadOnly)
FindDevice_Timer()
HideWindow(0,0)
SetTimer_(WindowID(0),1,200,@FindDevice_Timer())
CreateThread(@Thread(),0)
Repeat
  Event=WaitWindowEvent()
  If Event=#PB_Event_Gadget
    Select EventGadget()
      Case 2
        SendDevice($AA00)
      Case 3
        SendDevice($5500)
    EndSelect
  EndIf
Until Event=#PB_Event_CloseWindow

HID::HID_End()

Пример отсюда. USB термометр на ATmega8 и PIC18F4550

Код:
#USB_PID=$EF04
#USB_VID=$AAAA
#NO_Device="Нет связи с термометром"
LoadFont(2,"Arial",22,#PB_Font_Bold)

XIncludeFile "HID_Module.pbi"

Procedure FindDevice_Timer() ; Периодическая (каждые 400 мс.) проверка доступности термометра
Shared DeviceHandle
Static Old_Test
Test=HID::TestDevice(#USB_PID, #USB_VID) ; Есть ли требуемое USB HID устройство?
 If Test<>Old_Test
  Old_Test=Test
  If Test 
     HID::CloseDevice(DeviceHandle)
     DeviceHandle=HID::OpenDevice(#USB_PID, #USB_VID) ; Подключение к USB HID устройству
     SetGadgetText(0,"Термометр подключён")
  Else
     HID::CloseDevice(DeviceHandle)                   ; Разрыв связи с USB HID устройством
     DeviceHandle=0
     SetGadgetText(0,#NO_Device)
     SetGadgetText(1,"OFF")
  EndIf
 EndIf
EndProcedure

Procedure Thread(*x) ; Эта процедура работает в отдельном потоке
 Shared DeviceHandle
 Dim In.c(4)  ; Байтовый массив, используемый как бцфер приёма данных.
 Temp.w       ; Переменная типа Word.
 
 Repeat
   If DeviceHandle   ; Установлена ли связь с USB термометром?
     In(0)=0
     HID::ReadDevice(DeviceHandle, @In(), 3) ; Чтение данных из USB термометра
       Temp=In(2)
       Temp<<8                                  ; Сдвиг влево на 8 пизиций
       Temp | In(1)
       Result.f=Temp/16
       If Result<150 And Result>-58           ; Отсеиваем возможные глюки!
         SetGadgetText(1,StrF(Result,1)+" °C")      ; Отображение температуры в окне
       EndIf
   EndIf
   Delay(100)
 ForEver
 
EndProcedure

HID::HID_Init()

; Открываем окно
OpenWindow(0,0,0,170,70,"USB_Termo", #PB_Window_MinimizeGadget|#PB_Window_Invisible|#PB_Window_ScreenCentered)
 StickyWindow(0,1)
 TextGadget(0,4,4,162,16,#NO_Device,#PB_Text_Center)
 StringGadget(1,16,24,140,40,"OFF",#PB_Text_Center|#PB_String_ReadOnly)
   SetGadgetFont(1,FontID(2))
   SetGadgetColor(1,#PB_Gadget_FrontColor,$DF0000)
FindDevice_Timer()
HideWindow(0,0)

AddWindowTimer(0,1,400)    ; Запуск таймера
CreateThread(@Thread(),0)  ; Создание отдельного потока из процедуры Thread()

Repeat ; Главный цикл проги Repeat - Until
  Event=WaitWindowEvent() ; Идентификатор события
  If  Event=#PB_Event_Timer
    If EventTimer()=1
      FindDevice_Timer()  ; Вызов процедуры по таймеру, каждые 400 мс.
    EndIf
  EndIf
Until Event=#PB_Event_CloseWindow ; Прерывание главного цикла при закрытии окна

HID::HID_End()

HID_Tester.

Код:
; PureBasic Visual Designer v3.95 build 1485 (PB4Code)


;- Window Constants
;
Enumeration
  #Main_Window
EndEnumeration

;- Gadget Constants
;
Enumeration
  #Text_Device_list
  #ListIcon_Device
  #Text_Log
  #Button_Start
  #Button_Stop
  #Text_Selected_device
  #String_Selected_device
  #Container_Data
  #Option_Random
  #Option_SelectData
  #CheckBox_ReadDevice_State = #Option_SelectData + 17
  #Text_Pause
  #String_Pause
  #Editor_Log
  #Button_UpdateDeviceList
EndEnumeration

XIncludeFile "HID_Module.pbi"

Structure Thread_Device_IO_Info
  ReadDevice_State.b
  Pause.l
  DeviceInfo.HID::HID_CAPS
  RandomState.b
  Bytes.u[10]
EndStructure

Global PID_Device.u, VID_Device.u, VersionNumber_Device.u, DeviceHandle=0

Thread_Device_Info.Thread_Device_IO_Info



Procedure HID_DeviceInfo(*x)
  Protected HID_Info.HID::HID_DeviceInfo
  Protected Hid_Count=0
  
  If HID::DeviceInfo(@HID_Info)
    If HID_Info\CountDevice>0 And Hid_Count<>HID_Info\CountDevice
      Hid_Count=HID_Info\CountDevice
      ClearGadgetItems(#ListIcon_Device)
      For i=0 To HID_Info\CountDevice-1
        AddGadgetItem(#ListIcon_Device,i,HID_Info\DeviceInfo[i]\Product)
        SetGadgetItemText(#ListIcon_Device,i,Hex(HID_Info\DeviceInfo[i]\ProductID,#PB_Unicode)+"H",1)
        SetGadgetItemText(#ListIcon_Device,i,Str(HID_Info\DeviceInfo[i]\ProductID),7)
        SetGadgetItemText(#ListIcon_Device,i,Hex(HID_Info\DeviceInfo[i]\VendorID,#PB_Unicode)+"H",2)
        SetGadgetItemText(#ListIcon_Device,i,Str(HID_Info\DeviceInfo[i]\VendorID),8)
        SetGadgetItemText(#ListIcon_Device,i,Hex(HID_Info\DeviceInfo[i]\VersionNumber,#PB_Unicode)+"H",3)
        SetGadgetItemText(#ListIcon_Device,i,Str(HID_Info\DeviceInfo[i]\VersionNumber),9)
        SetGadgetItemText(#ListIcon_Device,i,Str(HID_Info\DeviceInfo[i]\InputReportByteLength),4)
        SetGadgetItemText(#ListIcon_Device,i,Str(HID_Info\DeviceInfo[i]\OutputReportByteLength),5)
        SetGadgetItemText(#ListIcon_Device,i,Str(HID_Info\DeviceInfo[i]\FeatureReportByteLength),6)
      Next i
    EndIf
  EndIf
  
EndProcedure

Procedure Disables_Gadgets(State)
  DisableGadget(#Button_Start, State)
  DisableGadget(#Button_Stop, State!1)
  DisableGadget(#ListIcon_Device, State)
  DisableGadget(#String_Pause, State)
  DisableGadget(#Container_Data, State)
  DisableGadget(#CheckBox_ReadDevice_State, State)
EndProcedure

Procedure FindDevice_Timer() ; Процедура вызывается по таймеру, каджие 200 мс.
  Static Old_Test
  Shared FindDevice_Ignore
  Shared Thread_Device_IO_Bugs, Thread_Device_IO_ID
  
  If PID_Device<>0 And VID_Device<>0
    Test=HID::TestDevice(PID_Device, VID_Device, VersionNumber_Device) ; Проверка доступности HID устройства
    If Test<>Old_Test Or FindDevice_Ignore=1
      FindDevice_Ignore=0
      Old_Test=Test
      If Test 
        HID::CloseDevice(DeviceHandle) ; Освобождение хендлов, если таковые есть
        ; Получение идентификаторов HID устройства
        DeviceHandle=HID::OpenDevice(PID_Device, VID_Device, VersionNumber_Device) ; Хендл для записи
        If DeviceHandle
          SetGadgetColor(#String_Selected_device, #PB_Gadget_FrontColor, RGB(64, 140, 76))
        Else
          SetGadgetColor(#String_Selected_device, #PB_Gadget_FrontColor, RGB(190, 0, 0))
        EndIf
      Else
        HID::CloseDevice(W_DeviceHandle) ; Освобождение хендлов, если таковые есть
        DeviceHandle=0
        SetGadgetColor(#String_Selected_device, #PB_Gadget_FrontColor, RGB(190, 0, 0))
      EndIf
    EndIf
  EndIf
  
  If Thread_Device_IO_ID 
    If Thread_Device_IO_Bugs>4
      Disables_Gadgets(0)
      If IsThread(Thread_Device_IO_ID)
        KillThread(Thread_Device_IO_ID)
        Thread_Device_IO_ID = 0
        MessageRequester("", "Thread is not responding!"+Chr(10)+"This is probably caused by bug"+Chr(10)+"connection with USB HID device!"+Chr(10)+Chr(10)+"Thread is killed!", 16)
      Else
        Thread_Device_IO_Bugs=0
      EndIf 
    Else
      Thread_Device_IO_Bugs+1
    EndIf
  EndIf
EndProcedure


Procedure.s ByteToString(*Point, Size)
  Protected String.s
  String = ""
  For i=0 To Size
    String+RSet(Hex(PeekA(*Point+i), #PB_Ascii), 2, "0")+" "
  Next i
  ProcedureReturn String
EndProcedure

Procedure Thread_Device_IO(*Point)
  Shared Thread_Start, Thread_Device_IO_ID
  Shared Thread_Device_IO_Bugs, FindDevice_Ignore
  Protected StructInfo.Thread_Device_IO_Info
  CopyMemory(*Point, @StructInfo, SizeOf(Thread_Device_IO_Info))
  
  InputReport = StructInfo\DeviceInfo\InputReportByteLength
  OutputReport = StructInfo\DeviceInfo\OutputReportByteLength
  Feature =  StructInfo\DeviceInfo\FeatureReportByteLength
  
  Dim OutBuf.a(OutputReport+2)
  Dim InBuf.a(InputReport+2)
  
  CompareMem=InputReport
  If OutputReport < InputReport
    CompareMem = OutputReport
  EndIf
  
  Counter = 1
  Counter_x=Counter+99;9 
  Repeat
    
    If DeviceHandle
       FillMemory(@OutBuf(), OutputReport, 0, #PB_Byte)
       FillMemory(@InBuf(), InputReport, 0, #PB_Byte)
       
       If StructInfo\RandomState = 1
         Temp1=8
         If OutputReport<8
           Temp1=OutputReport
         EndIf
         For z=1 To Temp1
           
           If StructInfo\Bytes[z] >255
             Temp.a=Random(255)
           Else
             Temp.a=StructInfo\Bytes[z]
           EndIf
           OutBuf(z) = Temp
         Next z
       Else
         For z=1 To OutputReport
           Temp.a=Random(255)
           OutBuf(z) = Temp
         Next z
       EndIf
       
       OutCount=HID::WriteDevice(DeviceHandle, @OutBuf(),OutputReport)

       If OutCount = OutputReport
         If StructInfo\ReadDevice_State = 1
           InCount=HID::ReadDevice(DeviceHandle, @InBuf(),InputReport)
           If InCount = InputReport
             If CompareMem<>0 And CompareMemory(@OutBuf(), @InBuf(), CompareMem)<>1
               AddGadgetItem(#Editor_Log, -1, RSet(Str(Counter), 6, " ")+"  ERROR    Bug compare memory  Send: "+ByteToString(@OutBuf()+1, CompareMem-2)+";    Read: "+ByteToString(@InBuf()+1, CompareMem-2))
               Break
             EndIf
           Else
             AddGadgetItem(#Editor_Log, -1, RSet(Str(Counter), 6, " ")+"  ERROR    Bug read device (read "+Str(InCount)+" bytes)  Send: "+ByteToString(@OutBuf()+1, OutputReport-2)+";    Read: "+ByteToString(@InBuf()+1, InputReport-2))
             Break
           EndIf
         EndIf
       Else
         AddGadgetItem(#Editor_Log, -1, RSet(Str(Counter), 6, " ")+"  ERROR    Bug write device (send "+Str(OutCount)+" bytes).  Send: "+ByteToString(@OutBuf()+1, OutputReport-2));"
         Break
       EndIf
       
       
       
       
;        OutCount=HID::SetFeature(DeviceHandle, @OutBuf(),Feature)
; 
;        If OutCount = 1
;          If StructInfo\ReadDevice_State = 1
;            InCount=HID::GetFeature(DeviceHandle, @InBuf(),Feature)
;            If InCount = 1
;              If Feature<>0 And CompareMemory(@OutBuf(), @InBuf(), Feature)<>1
;                AddGadgetItem(#Editor_Log, -1, RSet(Str(Counter), 6, " ")+"  ERROR    Bug compare memory  Send: "+ByteToString(@OutBuf()+1, Feature-2)+";    Read: "+ByteToString(@InBuf()+1, Feature-2))
;                Break
;              EndIf
;            Else
;              AddGadgetItem(#Editor_Log, -1, RSet(Str(Counter), 6, " ")+"  ERROR    Bug read device (read "+Str(InCount)+" bytes)  Send: "+ByteToString(@OutBuf()+1, Feature-2)+";    Read: "+ByteToString(@InBuf()+1, Feature-2))
;              Break
;            EndIf
;          EndIf
;        Else
;          AddGadgetItem(#Editor_Log, -1, RSet(Str(Counter), 6, " ")+"  ERROR    Bug write device (send "+Str(OutCount)+" bytes).");  Send: "+ByteToString(@OutBuf()+1, OutputReport-2)
;          Break
;        EndIf
       
       If Counter_x<=Counter
       AddGadgetItem(#Editor_Log, -1, RSet(Str(Counter), 6, " ")+"  OK    Send: "+ByteToString(@OutBuf()+1, OutCount-2))
       SendMessage_(GadgetID(#Editor_Log), #EM_SETSEL, -1, -1)
       Counter_x+100;0
       EndIf
    EndIf 
    
    If StructInfo\Pause>10
      Delay(StructInfo\Pause)
    EndIf
    
    Thread_Device_IO_Bugs = 0
    Counter + 1
  Until Thread_Start<>1 Or DeviceHandle = 0
  SendMessage_(GadgetID(#Editor_Log), #EM_SETSEL, -1, -1)
  Disables_Gadgets(0)
  HID::CloseDevice(DeviceHandle)
  FindDevice_Ignore = 1
  Thread_Device_IO_ID = 0
EndProcedure

Procedure Open_Main_Window()
  If OpenWindow(#Main_Window, 241, 107, 596, 520, "USB HID Tester",  #PB_Window_MinimizeGadget | #PB_Window_Invisible | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
      TextGadget(#Text_Device_list, 5, 5, 280, 15, "Device list:")
      ButtonGadget(#Button_UpdateDeviceList, 510,2,80,18,"Update")
      ListIconGadget(#ListIcon_Device, 5, 20, 585, 100, "Product", 58, #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_HeaderDragDrop|#PB_ListIcon_AlwaysShowSelection)
         AddGadgetColumn(#ListIcon_Device,1,"PID",48)
         AddGadgetColumn(#ListIcon_Device,2,"VID",48)
         AddGadgetColumn(#ListIcon_Device,3,"Version Number",94)
         AddGadgetColumn(#ListIcon_Device,4,"Imput report (bytes)",110)
         AddGadgetColumn(#ListIcon_Device,5,"Output report (bytes)",114)
         AddGadgetColumn(#ListIcon_Device,6,"Feature (bytes)",90)
         AddGadgetColumn(#ListIcon_Device,7,"",0)
         AddGadgetColumn(#ListIcon_Device,8,"",0)
         AddGadgetColumn(#ListIcon_Device,9,"",0)
      TextGadget(#Text_Selected_device, 5, 130, 100, 15, "Selected device:")
      StringGadget(#String_Selected_device, 110, 125, 480, 20, "", #PB_String_ReadOnly)
      ContainerGadget(#Container_Data,5,150,585,50,#PB_Container_Flat)
         OptionGadget(#Option_Random,4,6,90,15,"Random data") : SetGadgetState(#Option_Random,1)
         OptionGadget(#Option_SelectData,4,26,80,15,"Select data")
         
         Pos=100
         For i=#Option_SelectData+1 To #Option_SelectData+16 Step 2
           TextGadget(i, Pos, 28, 10, 15, Str((i-#Option_SelectData+2)/2)) : DisableGadget(i, 1)
           StringGadget(i+1, Pos+10, 24, 30, 20, "0", #PB_String_Numeric|#PB_Text_Center) : DisableGadget(i+1, 1)
           SetGadgetAttribute(i+1, #PB_String_MaximumLength, 3)
           Pos+58
         Next i
      CloseGadgetList()
      
      
      TextGadget(#Text_Log, 5, 165+50, 30, 15, "Log:") : SetGadgetColor(#Text_Log, #PB_Gadget_FrontColor, RGB(0, 0, 235))
      ButtonGadget(#Button_Start, 440, 155+50, 75, 25, "Start")
      ButtonGadget(#Button_Stop, 530, 155+50, 60, 25, "Stop") : DisableGadget(#Button_Stop, 1)
      EditorGadget(#Editor_Log, 5, 185+50, 585, 280, #PB_Editor_ReadOnly)
         SetGadgetFont(#Editor_Log, LoadFont(0, "Lucida Console", 8))
      CheckBoxGadget(#CheckBox_ReadDevice_State, 50, 165+50, 135, 15, "Read data from device")
      TextGadget(#Text_Pause, 210, 165+50, 145, 15, "Pause between packets, ms:")
      StringGadget(#String_Pause, 360, 160+50, 40, 20, "0", #PB_String_Numeric)
       SetGadgetAttribute(#String_Pause, #PB_String_MaximumLength, 3)
  EndIf
EndProcedure

HID::HID_Init()

Open_Main_Window()
AddWindowTimer(#Main_Window, 1, 800)
;HID_DeviceInfo(0)
Th_FindDevice=CreateThread(@HID_DeviceInfo(), 0)
For i=1 To 20
  WaitWindowEvent(1)
Next i
HideWindow(#Main_Window, #False)

Repeat
  Event=WaitWindowEvent()
  
  If Event=#PB_Event_Timer
    Select EventTimer()
      Case 1
        FindDevice_Timer()
      ;Case 2
    EndSelect
    
    
  ElseIf Event=#PB_Event_Gadget
    Select EventGadget()
        
      Case  #Button_UpdateDeviceList
        HID_DeviceInfo(0)
      Case #ListIcon_Device
        If EventType()=#PB_EventType_LeftDoubleClick
          ListPos=GetGadgetState(#ListIcon_Device)
          If ListPos>=0
            HID::CloseDevice(W_DeviceHandle)
            DeviceHandle=0
            PID_Device = Val(GetGadgetItemText(#ListIcon_Device, ListPos, 7))
            VID_Device = Val(GetGadgetItemText(#ListIcon_Device, ListPos, 8))
            VersionNumber_Device = Val(GetGadgetItemText(#ListIcon_Device, ListPos, 9))
            SetGadgetColor(#String_Selected_device, #PB_Gadget_FrontColor, #PB_Default)
            SetGadgetText(#String_Selected_device, GetGadgetItemText(#ListIcon_Device, ListPos, 0)+";  PID: "+Hex(PID_Device,#PB_Unicode)+"H"+";  VID: "+Hex(VID_Device,#PB_Unicode)+"H"+";  S/N: "+Hex(VersionNumber_Device,#PB_Unicode)+"H")
            FindDevice_Ignore=1
          EndIf
        EndIf
        
        
      Case #Button_Start
       If DeviceHandle
         Thread_Start=1
          Thread_Device_Info\ReadDevice_State=GetGadgetState(#CheckBox_ReadDevice_State)
          Thread_Device_Info\Pause=Val(GetGadgetText(#String_Pause))
          If Thread_Device_Info\Pause<0
            Thread_Device_Info\Pause=0
          ElseIf Thread_Device_Info\Pause > 1000
            Thread_Device_Info\Pause = 1000
          EndIf
          HID::GetCaps(DeviceHandle, @Thread_Device_Info\DeviceInfo)
          Thread_Device_Info\RandomState = GetGadgetState(#Option_Random) ! 1
          If Thread_Device_Info\RandomState = 1
            For i=#Option_SelectData+1 To #Option_SelectData+16 Step 2
              Thread_Device_Info\Bytes[(i-#Option_SelectData+2)/2] = Val(GetGadgetText(i+1))
            Next i
          EndIf
          Thread_Device_IO_Bugs=0
          ClearGadgetItems(#Editor_Log)
          Thread_Device_IO_ID=CreateThread(@Thread_Device_IO(), @Thread_Device_Info)
          If Thread_Device_IO_ID
            Disables_Gadgets(1)
          Else 
            MessageRequester("", "An error occurred when starting a thread!", 16)
          EndIf
        Else
          If GetGadgetText(#String_Selected_device)=""
            MessageRequester("", "Select a device from the list."+Chr(10)+"(Double click the left mouse button).", 48)
          Else
            MessageRequester("", "No devices found with the specified PID & VID", 48)
          EndIf
        EndIf 
        
        
      Case #Button_Stop
        If Thread_Device_IO_ID<>0
          Thread_Start+1
          If Thread_Start>4
            If IsThread(Thread_Device_IO_ID)
              KillThread(Thread_Device_IO_ID)
            EndIf
            Thread_Device_IO_Bugs=0
            Thread_Start=0
            Disables_Gadgets(0)
            MessageRequester("", "Thread is not responding!"+Chr(10)+"This is probably caused by an bug"+Chr(10)+"connection withUSB HID device!"+Chr(10)+Chr(10)+"Thread is killed.", 48)
          EndIf
        Else
          Disables_Gadgets(0)
          Thread_Start = 0
        EndIf
        
        
      Case #Option_Random, #Option_SelectData
        State=GetGadgetState(#Option_Random)
        For i=#Option_SelectData+1 To #Option_SelectData+16
           DisableGadget(i, State)
        Next i
    EndSelect
  EndIf
  
  
Until Event=#PB_Event_CloseWindow

If IsThread(Th_FindDevice)
  KillThread(Th_FindDevice)
EndIf

If IsThread(Thread_Device_IO_ID)
  KillThread(Thread_Device_IO_ID)
EndIf

HID::HID_End()

Узнаем PID, VID и номер версии по идентификатору устройства.

Код:
#USB_PID=1
#USB_VID=$1234

XIncludeFile "HID_Module.pbi"
UseModule HID

HID_Init()

hDevice = OpenDevice(#USB_PID, #USB_VID)
If hDevice
  
  Info.HID_Attributes
  If GetAttributes(hDevice, @Info)
    MessageRequester("", "PID "+Info\PID+Chr(10)+
                         "VID "+Info\VID+Chr(10)+
                         "Номер версии "+Info\VersionNumber, #MB_OK|#MB_ICONINFORMATION)
  Else
    MessageRequester("", "Ошибка функции GetAttributes", #MB_OK|#MB_ICONWARNING)
  EndIf
  
  CloseDevice(hDevice)
Else
  MessageRequester("", "Устройство не найдено"+Chr(10)+
                       "PID "+#USB_PID+"  VID "+#USB_VID, #MB_OK|#MB_ICONWARNING)
EndIf

HID_End()

Файлы. http://pure-basic.narod.ru/forum_files/HID_Module.zip

+1

2

Спасибо.

0

3

Добавил функцию GetAttributes в модуль, позволяющую узнать PID, VID и номер версии по идентификатору устройства.

0

4

Спасибо!!!  :glasses:
Правда не смог соеденить HID от другой клавиатуры, но с штатной соединяет.
Никак не разберусь почему.

Отредактировано Ev3658 (25.10.2021 02:05:24)

0

5

Ev3658 написал(а):

Правда не смог соеденить HID от другой клавиатуры

С клавиатурой не пробовал, т. к. особого смысла в этом нет. Зачем это понадобилось?
Модуль использовал для обмена с МК.

0


Вы здесь » PureBasic - форум » OpenSource » Модуль для работы с USB HID