PureBasic - форум

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

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



Linux libusb / hidlib?

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

1

sorry for the english,

I am looking for a working libusb/hidlib for linux to control microcontroller if any one can help please.

Thanks.

Google Translation

извините за английский,

Я ищу рабочий libusb / hidlib для linux для управления микроконтроллером, если кто-нибудь может помочь.

Благодарю.

Гугл-перевод

izvinite za angliyskiy,

YA ishchu rabochiy libusb / hidlib dlya linux dlya upravleniya mikrokontrollerom, yesli kto-nibud' mozhet pomoch'.

Blagodaryu.

Gugl-perevod

0

2

Вот здесь программа для Windows и Linux для прошивки микроконтроллеров использующая libusb. http://bascomavr.3bb.ru/viewtopic.php?id=1571

0

3

Thank you for the code.. I will try to make it work with "FF34" board from "http://www.flyfish-tech.com/FF32/index.php" I am not very professional programmer always learning. The libusb code is more advanced maybe then what I can understand but will try. Thanks again for your help.

Спасибо за код. Я попытаюсь заставить его работать с доской «FF34» с «http://www.flyfish-tech.com/FF32/index.php». Я не очень профессиональный программист, который всегда учится. Код libusb более продвинут, может быть, тогда я пойму, но попробую. В очередной раз благодарим за помощь.

0

4

Trying to get to connect but am stuck here do you see my problem?

Попытка связаться, но я застрял здесь, вы видите мою проблему?

Test.pb

Код:
XIncludeFile "DFUm.pbi"
UseModule DFU

Structure ArrA
  a.a[0]
EndStructure

Procedure ProgressProg(Pos)
  Debug Pos
EndProcedure

Procedure.s ErrToText(ErrCode.l)
  Protected Str.s=""
  
  Select ErrCode
    Case #DFU_Err_OK
      ;Str = "Ошибок нет."
    Case #DFU_Err_NoInit
      Str = "The library is not initialized."
    Case #DFU_Err_ChipBad
      Str = "Unsupported microcontroller type."
    Case #DFU_Err_Internal
      Str = "Internal ERROR program."
    Case #DFU_Err_NotChip
      Str = "The selected microcontroller could not be found."
    Case #DFU_Err_OpenDev
      Str = "ERROR installation of communication with the USB device (loader)."
    Case #DFU_Err_ConfigDev
      Str = "ERROR configuration or USB interface."
    Case #DFU_Err_DevNotRespond
      Str = "The loader did not respond to the request."
    Case #DFU_Err_BadParam
      Str = "Invalid function parameter."
    Case #DFU_Err_TimeOut
      Str = "Exit by timeout."
    Case #DFU_Err_DownFunct
      Str = "ERROR when sending data to the loader."
    Case #DFU_Err_UpFunct
      Str = "ERROR when retrieving data from the loader."
    Case #DFU_Err_IncorrectFile
      Str = "Invalid file."
    Case #DFU_Err_OpenFile
      Str = "Could not open file."
    Case #DFU_Err_IncorrectData
      Str = "Mismatch data, for example, when checking the recorded firmware in the MC."
    Case #DFU_Err_StatusParam
      Str = "ERROR function status."
    Case #DFU_Err_ProtectMem
      Str = "Memory is protected."
  EndSelect
  
  ProcedureReturn Str
EndProcedure

Macro ShowErr(Text="")
  Debug Text+"ERROR - "+ErrToText(DFU_GetLastErr())
EndMacro

Procedure BootIO()
  Debug "- BootIO()"
  Protected hDev.i, SizeL.l
  Protected Info.DFU_ChipParam
  Protected *WriteBuff.ArrA=0, *ReadBuff.ArrA=0
  Protected MemType, MType.s, x
  
  hDev = DFU_DevOpen(0)
  Debug "-- BootIO().hDev: " + hDev
  If hDev
    Debug "2"
    DFU_SetProgressCB(hDev, @ProgressProg())
    
    Debug "Communication with the loader is started"
    
    Repeat : Until WindowEvent() = 0
    
    If DFU_ChipInfo(hDev, @Info)
      Debug "3"
      Debug "Microcontroller - "+ Info\ChipType
      Debug "Boot Loader Version - 1."+RSet(Str(Info\BootVersion), 2, "0")
      Debug "Boot ID - "+RSet(Hex(Info\bootID1, #PB_Ascii), 2, "0")+
            " "+RSet(Hex(Info\bootID2, #PB_Ascii), 2, "0")
      Debug "Signature - "+RSet(Hex(Info\Manufacturer, #PB_Ascii), 2, "0")+
            " "+RSet(Hex(Info\Family, #PB_Ascii), 2, "0")+
            " "+RSet(Hex(Info\ProductName, #PB_Ascii), 2, "0")+
            " "+RSet(Hex(Info\Revision, #PB_Ascii), 2, "0")
    EndIf
    
    ;Repeat : Until WindowEvent() = 0
       
    DFU_DevClose(hDev)
  Else
    ShowErr()
  EndIf
  
EndProcedure

If DFU_Init()=0
  Debug "DFU_Init: 0 - ERROR USB library initialization. Probably the driver is not installed"
  End
Else
  Debug "DFU_Init: 1 - USB library initialized."
EndIf

BootIO()

DFUm.pbi

Код:
;- DeclareModule

DeclareModule DFU

;Define.i

;{ Constants and structures.
Enumeration
  #DFU_ChipType_Auto    ; Automatic recognition of the microcontroller type.
  #DFU_ChipType_FF32    ; FF32 HEX(04d8:f8b9) DEC(1240:63673)
    ; ATmega
  #DFU_ChipType_16U4    ; ATmega16U4
  #DFU_ChipType_32U4    ; ATmega32U4
  #DFU_ChipType_Max
EndEnumeration

#DFU_ChipType_Unknown = $7F ; Could not determine the type of MC.

Enumeration
  #DFU_StartApp_WDT  ; Start the program by restarting the MK with the "dog".
  #DFU_StartApp_JMP0 ; Start the program by going to the zero address.
EndEnumeration

Enumeration
  #DFU_MemType_Flash
  #DFU_MemType_EEPROM
EndEnumeration

Enumeration ;- Error codes.
  #DFU_Err_OK       ; There are no errors.
  #DFU_Err_NoInit   ; The library is not initialized. You must successfully execute the DFU_Init () function.
  #DFU_Err_ChipBad  ; Unsupported MK type.
  #DFU_Err_Internal ; Внутреняя ошибка программы, например не удалось запросить у системы блок памяти.
  #DFU_Err_NotChip  ; Не найден МК с заданными PID и VID.
  #DFU_Err_OpenDev  ; Ошибка установки связи с USB устройством (МК с загрузчиком).
  #DFU_Err_ConfigDev; Ошибка конфигурации или интерфейса USB.
  #DFU_Err_DevNotRespond ; Загрузчик не ответил на запрос.
  #DFU_Err_BadParam ; Некорректный параметр функции.
  #DFU_Err_TimeOut  ; Выход по таймауту.
  #DFU_Err_DownFunct; Ошибка при отправке данных загрузчику.
  #DFU_Err_UpFunct  ; Ошибка при получении данных от загрузчика.
  #DFU_Err_IncorrectFile ; Invalid file.
  #DFU_Err_OpenFile      ; Could not open file.
  #DFU_Err_IncorrectData ; Mismatch data, for example, when checking the recorded firmware in the MK.
  #DFU_Err_StatusParam   ; Ошибка функции статуса.
  #DFU_Err_ProtectMem ; Память защищена.
EndEnumeration

Structure DFU_ChipParam
  BootVersion.a  ; Версия загрузчика
  bootID1.a      ; boot ID1 устройства
  bootID2.a      ; boot ID2 устройства
  Manufacturer.a ; Код производителя
  Family.a       ; Код семейства
  ProductName.a  ; Имя продукта
  Revision.a     ; Ревизия продукта
  ChipType.b     ; Тип микроконтроллера. См. константы DFU_ChipType_xxxx
EndStructure

Structure DFU_CheckInfo ; Информация о верификации памяти.
  Address.l    ; Адрес первого несовпавшего байта (-1 если все совпали или произошла ошибка).
  Res.b        ; Результат верификации. Если успешный - больше 0, при несовпадении - 0, при ошибке - меньше 0.
  ChipByte.a   ; Байт считанный с МК.
  BuffByte.a   ; Байт находящийся в буфере проверки.
  LastErr.l    ; Код ошибки.
EndStructure

;}

; It is necessary to call in the beginning of work with the library. Returns not zero if the initialization is successful.
Declare DFU_Init()
; The code of the current error.
Declare.l DFU_GetLastErr()
; Установка связи в МК. См. константы DFU_ChipType_xxxx. Вернет не 0 (DevID) в случае успешного выполнения.
Declare DFU_DevOpen(ChipType.b)
; Разрыв связи с МК. Вернет не 0 в случае успешного выполнения.
Declare DFU_DevClose(*DevID)
; Стирание памяти программ. Вернет отрицательное число в случае ошибки.
Declare DFU_EraseFlash(*DevID)
; Запуск основной программы из загрузчика. См. константы #DFU_StartApp_xxxx.
Declare DFU_StartApp(*DevID, Mode=#DFU_StartApp_WDT)
; Информация о конфигурации и производителе. Вернет не 0 в случае успешного выполнения.
Declare DFU_ChipInfo(*DevID, *Info.DFU_ChipParam)
; Установка адреса CallBack процедуры. Вернет не 0 в случае успешного выполнения.
Declare DFU_SetProgressCB(*DevID, *CB_Proc)
; Прошивка памяти программ микроконтроллера. Вернет не 0 в случае успешного выполнения.
Declare DFU_ProgFlash(*DevID, File.s, *CheckInfo.DFU_CheckInfo=0)
; Прошивка памяти программ микроконтроллера. Вернет не 0 в случае успешного выполнения.
Declare DFU_ProgEEPROM(*DevID, File.s, *CheckInfo.DFU_CheckInfo=0)

; Writes (stitches) to the MK from the buffer * Buff the number of bytes specified in the Size.
; Where to write (Flash or EEPROM depends on the MemType parameter).
; The procedure returns not 0 if successful.
Declare DFU_WriteBuff(*DevID, *Buff, Size, MemType=#DFU_MemType_Flash)

; Reads from the MK to the buffer * Buff the number of bytes specified in the Size.
; Whence it reads (Flash or EEPROM depends on the MemType parameter).
; The procedure returns not 0 if successful.
Declare DFU_ReadBuff(*DevID, *Buff, Size, MemType=#DFU_MemType_Flash)

EndDeclareModule

Module DFU

EnableExplicit
;- Private
;- Constants of DFU.
;{

; DFU commands
#DFU_DETACH                      = 0
#DFU_DNLOAD                      = 1
#DFU_UPLOAD                      = 2
#DFU_GETSTATUS                   = 3
#DFU_CLRSTATUS                   = 4
#DFU_GETSTATE                    = 5
#DFU_ABORT                       = 6

#USB_CLASS_APP_SPECIFIC          = $fe
#DFU_SUBCLASS                    = $01
#DFU_TIMEOUT                     = 20000
#DFU_DETACH_TIMEOUT              = 1000


; DFU states
#STATE_APP_IDLE                  = $00
#STATE_APP_DETACH                = $01
#STATE_DFU_IDLE                  = $02
#STATE_DFU_DOWNLOAD_SYNC         = $03
#STATE_DFU_DOWNLOAD_BUSY         = $04
#STATE_DFU_DOWNLOAD_IDLE         = $05
#STATE_DFU_MANIFEST_SYNC         = $06
#STATE_DFU_MANIFEST              = $07
#STATE_DFU_MANIFEST_WAIT_RESET   = $08
#STATE_DFU_UPLOAD_IDLE           = $09
#STATE_DFU_ERROR                 = $0a


;DFU status
#DFU_STATUS_OK                   = $00
#DFU_STATUS_ERROR_TARGET         = $01
#DFU_STATUS_ERROR_FILE           = $02
#DFU_STATUS_ERROR_WRITE          = $03
#DFU_STATUS_ERROR_ERASE          = $04
#DFU_STATUS_ERROR_CHECK_ERASED   = $05
#DFU_STATUS_ERROR_PROG           = $06
#DFU_STATUS_ERROR_VERIFY         = $07
#DFU_STATUS_ERROR_ADDRESS        = $08
#DFU_STATUS_ERROR_NOTDONE        = $09
#DFU_STATUS_ERROR_FIRMWARE       = $0a
#DFU_STATUS_ERROR_VENDOR         = $0b
#DFU_STATUS_ERROR_USBR           = $0c
#DFU_STATUS_ERROR_POR            = $0d
#DFU_STATUS_ERROR_UNKNOWN        = $0e
#DFU_STATUS_ERROR_STALLEDPKT     = $0f


#ATMEL_USER_PAGE_OFFSET = $80800000

#ATMEL_ERASE_BLOCK_0    = 0
#ATMEL_ERASE_BLOCK_1    = 1
#ATMEL_ERASE_BLOCK_2    = 2
#ATMEL_ERASE_BLOCK_3    = 3
#ATMEL_ERASE_ALL        = 4

#ATMEL_SET_CONFIG_BSB   = 0
#ATMEL_SET_CONFIG_SBV   = 1
#ATMEL_SET_CONFIG_SSB   = 2
#ATMEL_SET_CONFIG_EB    = 3
#ATMEL_SET_CONFIG_HSB   = 4

#ATMEL_SECURE_OFF       = 0 ; Security bit is cleared
#ATMEL_SECURE_ON        = 1 ; Security bit is set
#ATMEL_SECURE_MAYBE     = 2 ; Call To check security bit failed

#ATMEL_64KB_PAGE             = $10000
#ATMEL_MAX_TRANSFER_SIZE     = $0400
#ATMEL_FOOTER_SIZE           = 16
#ATMEL_CONTROL_BLOCK_SIZE    = 32
#ATMEL_AVR32_CTRL_BLOCK_SIZE = 64
#ATMEL_MAX_FLASH_BUFFER_SIZE = #ATMEL_MAX_TRANSFER_SIZE +
                               #ATMEL_AVR32_CTRL_BLOCK_SIZE +
                               #ATMEL_AVR32_CTRL_BLOCK_SIZE +
                               #ATMEL_FOOTER_SIZE

#MK_8051   = (1<<0)
#MK_AVR    = (1<<1)
#MK_AVR32  = (1<<2)
#MK_XMEGA  = (1<<3)
;#DC_STM32   = (1<<4)

#GRP_AVR32  = (#MK_AVR32 | #MK_XMEGA)
#GRP_AVR    = (#MK_AVR | #MK_8051)
;#GRP_STM32  = (#DC_STM32)


Enumeration
  #mem_flash
  #mem_eeprom
  #mem_security
  #mem_config
  #mem_boot
  #mem_sig
  #mem_user
  #mem_ram
  #mem_ext0
  #mem_ext1
  #mem_ext2
  #mem_ext3
  #mem_ext4
  #mem_ext5
  #mem_ext6
  #mem_ext7
  #mem_extdf
EndEnumeration

;Enumeration
  #MemType_Flash  = #DFU_MemType_Flash
  #MemType_EEPROM = #DFU_MemType_EEPROM
;EndEnumeration

;}

;- **** DFU Programmer ****
IncludeFile "libusb.pbi"

Prototype pProgressCB(Percent)
Declare SetProgress(*DevID, Pos, Ends)
Declare GetFlashBlock(*DevID, *Buff, Start, Ends, MemEnd, Type)


;{ Structure

Structure ArrA
  a.a[0]
EndStructure

Structure UsbID
  PID.u
  VID.u
EndStructure

Structure UsbParam Extends UsbID
  Array Arr.UsbID(0)
EndStructure

Structure DFU_Status
  bStatus.a
  bwPollTimeout.l
  bState.a
  iString.a
EndStructure

Structure DevID_AVR Extends UsbID
  ChipType.b     ; Type of microcontroller. See the constants DFU_ChipType_xxxx
  DevType.a      ; Type MK (#ADC_AVR, #ADC_XMEGA, # ADC_AVR32 and so on).
  *ProgressCB.pProgressCB
EndStructure

Structure DevID
  hDev.i
  usbInterface.i
  Transaction.i
  Avr.DevID_AVR
EndStructure
;}

Global gInitLibState = #False

CompilerIf #PB_Compiler_Thread
  Threaded gLastErr.l = 0
CompilerElse
  Global gLastErr.l = 0
CompilerEndIf

Procedure SetLastErr(ErrCode.l)
  gLastErr = ErrCode
EndProcedure

Procedure TransferIn(*DevID.DevID, Request, Value, *Data, Size)
  Protected Res = 0
  
  If *DevID And *DevID\hDev
    Res = usb_control_msg(*DevID\hDev, #USB_ENDPOINT_IN | #USB_TYPE_CLASS | #USB_RECIP_INTERFACE,
                          Request, Value, *DevID\usbInterface, *Data, Size, #DFU_TIMEOUT)
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure TransferOut(*DevID.DevID, Request, Value, *Data, Size)
  Protected Res = 0
  
  If *DevID And *DevID\hDev
    Res = usb_control_msg(*DevID\hDev, #USB_ENDPOINT_OUT | #USB_TYPE_CLASS | #USB_RECIP_INTERFACE,
                          Request, Value, *DevID\usbInterface, *Data, Size, #DFU_TIMEOUT)
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure Detach(*DevID.DevID, Timeout)
  ProcedureReturn TransferOut(*DevID, #DFU_DETACH, Timeout, #Null, 0)
EndProcedure

Procedure Download(*DevID.DevID, *Data, Size)
  Protected Res
  
  Res = TransferOut(*DevID, #DFU_DNLOAD, *DevID\Transaction, *Data, Size)
  *DevID\Transaction+1
  
  ProcedureReturn Res
EndProcedure

Procedure Upload(*DevID.DevID, *Data, Size)
  Protected Res
  
  Res = TransferIn(*DevID, #DFU_UPLOAD, *DevID\Transaction, *Data, Size)
  *DevID\Transaction+1
  
  ProcedureReturn Res
EndProcedure

Procedure GetStatus(*DevID.DevID, *Status.DFU_Status)
  Protected Res = 0, Buffer.q = 0
  
  If *Status
    *Status\bStatus       = #DFU_STATUS_ERROR_UNKNOWN
    *Status\bwPollTimeout = 0
    *Status\bState        = #STATE_DFU_ERROR
    *Status\iString       = 0
    
    Res = TransferIn(*DevID, #DFU_GETSTATUS, 0, @Buffer, 6)
    If Res = 6
      *Status\bStatus       = PeekA(@Buffer)
      *Status\bwPollTimeout = PeekL(@Buffer+1) & $00FFFFFF
      *Status\bState        = PeekA(@Buffer+4)
      *Status\iString       = PeekA(@Buffer+5)
    Else
      Res = 0
    EndIf
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure ClearStatus(*DevID.DevID)
  ProcedureReturn TransferOut(*DevID, #DFU_CLRSTATUS, 0, #Null, 0)
EndProcedure

Procedure GetState(*DevID.DevID)
  Protected Res = 0, Buffer.a = 0
  
  Res = TransferIn(*DevID, #DFU_GETSTATE, 0, @Buffer, SizeOf(Buffer))
  
  If Res > 0
    Res = Buffer
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure Abort(*DevID.DevID)
  ProcedureReturn TransferOut(*DevID, #DFU_ABORT, 0, #Null, 0)
EndProcedure

;- **** libusb0 ****
Procedure FindDevide(*ID.UsbParam) ; Search for a USB device with the required PID and VID.
  Debug "- FindDevide()"
  Protected *usb_busses.usb_bus
  Protected *devices.usb_device
  Protected *usb_dev=0, i, Count
  
  If *ID
    
    Debug "-- FindDevide().*ID"
    Count = ArraySize(*ID\Arr())
    usb_find_busses()
    usb_find_devices()
    *usb_busses = usb_get_busses()
    
    While *usb_busses
      *devices = *usb_busses\devices
      Debug "-- FindDevide().*ID.*usb_busses: " + *usb_busses\devices
      While *devices
        Debug "-- FindDevide().*ID.*usb_busses.*devices"
        
        If *ID\PID<>0 Or *ID\VID<>0
          Debug "-- FindDevide().*ID.*usb_busses.*devices.IF"
                      Debug "-- FindDevide().*ID.*usb_busses.*devices.IF: " + *devices\descriptor\idProduct + " ---- " + *ID\PID
            Debug "-- FindDevide().*ID.*usb_busses.*devices.IF: " + *devices\descriptor\idVendor + " ---- " + *ID\VID

          If *devices\descriptor\idProduct=*ID\PID And 
             *devices\descriptor\idVendor=*ID\VID
            *usb_dev = *devices
            Debug "-- FindDevide().*ID.*usb_busses.*devices.IF: " + *devices\descriptor\idProduct + " ---- " + *ID\PID
            Debug "-- FindDevide().*ID.*usb_busses.*devices.IF: " + *devices\descriptor\idVendor + " ---- " + *ID\VID
            
          EndIf
        Else
          Debug "-- FindDevide().*ID.*usb_busses.*devices.ELSE"
          For i=0 To Count
            ;Debug "-- FindDevide().*ID.Count(" + Count + "): " + *devices\descriptor\idProduct + " ---- " + *ID\Arr(i)\PID
            ;Debug "-- FindDevide().*ID.Count(" + Count + "): " + *devices\descriptor\idVendor + " ---- " + *ID\Arr(i)\VID
            If *devices\descriptor\idProduct=*ID\Arr(i)\PID And 
               *devices\descriptor\idVendor=*ID\Arr(i)\VID
              *ID\PID = *devices\descriptor\idProduct
              *ID\VID = *devices\descriptor\idVendor
              *usb_dev = *devices
              Debug "-- FindDevide().*ID.Count.Count: " + *devices\descriptor\idProduct + " ---- " + *ID\Arr(i)\PID
              Debug "-- FindDevide().*ID.Count.Count: " + *devices\descriptor\idVendor + " ---- " + *ID\Arr(i)\VID
              Break
            EndIf
          Next
        EndIf
        
        *devices = *devices\Next
      Wend
      *usb_busses = *usb_busses\Next
    Wend 
    
  EndIf
  
  ProcedureReturn *usb_dev
EndProcedure

Procedure CloseDevice(hDev)
  If hDev
    usb_close(hDev)
  EndIf
EndProcedure

Procedure DevInterface(*Dev.usb_device)
  Debug "- DevInterface()"
  Protected Res = -1, c, i
  Protected *Config.usb_config_descriptor
  Protected *Interface.usb_interface_descriptor
  
  Debug "- DevInterface().bNumConfigurations: " + Str(*Dev\descriptor\bNumConfigurations-1)
  For c=0 To *Dev\descriptor\bNumConfigurations-1
    Debug "- DevInterface().*Dev\config: " + *Dev\config
    Debug "- DevInterface().SizeOf.usb_config_descriptor: " + SizeOf(usb_config_descriptor)
    *Config = *Dev\config + (SizeOf(usb_config_descriptor) * c)
    Debug "- DevInterface().config: " + *Config
    For i=0 To *config\Interface\num_altsetting-1
      *Interface = *config\Interface\altsetting + (SizeOf(usb_interface_descriptor) * i)
      
        ; As though this check should be, but in "iron" bInterfaceClass and bInterfaceSubClass are equal 0!
;       If *Interface\bInterfaceClass = #USB_CLASS_APP_SPECIFIC And
;          *Interface\bInterfaceSubClass = #DFU_SUBCLASS
      Res = *Interface\bInterfaceNumber
      Debug "- DevInterface().Res: " +  Res
        Break 2
;       EndIf
    Next
  Next
  
  
  ProcedureReturn Res
EndProcedure

Procedure MakeIdle(*DevID.DevID)
  Protected Status.DFU_Status
  Protected retries = 4, x=400, Res = #False
  
  Abort(*DevID)
  
  While retries > 0
    
    If GetStatus(*DevID, @Status)=0
      ClearStatus(*DevID)
      x-1
      If x<=0
        Break
      EndIf
      Continue
    EndIf
    
    Select Status\bState
      Case #STATE_DFU_IDLE
        
        If Status\bStatus = #DFU_STATUS_OK
          Res = #True
          Break
        EndIf
        ClearStatus(*DevID)
        
      Case #STATE_DFU_DOWNLOAD_SYNC, #STATE_DFU_DOWNLOAD_IDLE, #STATE_DFU_MANIFEST_SYNC,
           #STATE_DFU_UPLOAD_IDLE, #STATE_DFU_DOWNLOAD_BUSY, #STATE_DFU_MANIFEST
        Abort(*DevID)
        
      Case #STATE_DFU_ERROR
        ClearStatus(*DevID)
        
      Case #STATE_APP_IDLE
        Detach(*DevID, #DFU_DETACH_TIMEOUT)
        
      Case #STATE_APP_DETACH, #STATE_DFU_MANIFEST_WAIT_RESET
        usb_reset(*DevID\hDev)
    EndSelect
    
    retries - 1
    
  Wend
  
  ProcedureReturn Res
EndProcedure

Procedure OpenDevice_Connect(*Dev.usb_device, *DevID.DevID)
  Debug "- OpenDevice_Connect()"
  Protected hDev=0, x=#False
  
  *DevID\usbInterface = DevInterface(*Dev)
  If *DevID\usbInterface>=0
    ;Debug "-- OpenDevice_Connect().*DevID"
    Debug "-- OpenDevice_Connect().*DevID("+*dev+")"
    hDev = usb_open(*dev)
    Debug "-- OpenDevice_Connect().*DevID.hDev(" + hDev + ")"
    *DevID\hDev = hDev
    If hDev
      Debug "--- OpenDevice_Connect().*DevID.hDev"
      Debug "-------(((( " + usb_set_configuration(hDev, 1)
      If usb_set_configuration(hDev, 1) = 0
        Debug "---- OpenDevice_Connect().*DevID.hDev.usb_set_configuration"
        If usb_claim_interface(hDev, *DevID\usbInterface) = 0
          Debug "---- OpenDevice_Connect().*DevID.hDev.usb_set_configuration.usb_claim_interface"
          If MakeIdle(*DevID)
            x=#True
          Else
            usb_release_interface(hDev, *DevID\usbInterface)
            SetLastErr(#DFU_Err_DevNotRespond)
          EndIf
        Else
          SetLastErr(#DFU_Err_ConfigDev)
        EndIf
      Else
        SetLastErr(#DFU_Err_ConfigDev)
      EndIf
    Else
      SetLastErr(#DFU_Err_OpenDev)
    EndIf
  Else
    SetLastErr(#DFU_Err_ConfigDev)
  EndIf
  
  If hDev And x=#False
    CloseDevice(hDev)
    hDev = 0
  EndIf
  
  ProcedureReturn hDev
EndProcedure

Procedure OpenDevice(PID.u, VID.u, *DevID.DevID)
  Debug "- OpenDevice()"
  Protected *Dev, hDev
  Protected ID.UsbParam
  
  ID\PID = PID
  ID\VID = VID
  Debug "- OpenDevice() PID: " + PID + " VID: " + VID
  *Dev=FindDevide(@ID)
  If *Dev  ; Device found.
    Debug "-- OpenDevice().*Dev - Found"
    hDev = OpenDevice_Connect(*Dev, *DevID)
  Else
    SetLastErr(#DFU_Err_NotChip)
  EndIf
  
  ProcedureReturn hDev
EndProcedure

Procedure OpenMultiDevice(Array ID.UsbID(1), ; An array of USB device identifiers.
                          *DevID.DevID,      ; Device identifier (for other functions).
                          *ID.UsbID=0)       ; If any device is found, its identifier will be written down here.
  Debug "- OpenMultiDevice()"
  Protected *Dev, hDev=0, ID.UsbParam
  
  If *DevID
    Debug "-- OpenMultiDevice().*DevID"
    ID\PID = 0
    ID\VID = 0
    CopyArray(ID(), ID\Arr())
    *Dev=FindDevide(@ID)
    If *Dev  ; Device found.
      Debug "--- OpenMultiDevice().*DevID.*Dev"
      hDev = OpenDevice_Connect(*Dev, *DevID)
      If hDev
        Debug "---- OpenMultiDevice().*DevID.*Dev.hDev"
        If *ID 
          *ID\PID = ID\PID
          *ID\VID = ID\VID
        EndIf
      EndIf
    Else
      SetLastErr(#DFU_Err_NotChip)
    EndIf
  EndIf
  
  ProcedureReturn hDev
EndProcedure


;- **** Programmer ****

Procedure EraseFlash(*DevID.DevID, Mode=#ATMEL_ERASE_ALL) ; Erasing program memory.
  Protected Dim Command.a(3)
  Protected Status.DFU_Status
  Protected Res = -1, Retries = 0
  
  If *DevID
    
    PokeL(@Command(), $00000004)
    
    Select Mode
      Case #ATMEL_ERASE_BLOCK_0 : Command(2) = $00
      Case #ATMEL_ERASE_BLOCK_1 : Command(2) = $20
      Case #ATMEL_ERASE_BLOCK_2 : Command(2) = $40
      Case #ATMEL_ERASE_BLOCK_3 : Command(2) = $80
      Case #ATMEL_ERASE_ALL     : Command(2) = $FF
      Default
        SetLastErr(#DFU_Err_BadParam)
        ProcedureReturn -2
    EndSelect
    
    If Download(*DevID, @Command(), 3) = 3
      Repeat
        
        If GetStatus(*DevID, @Status)
          If Status\bStatus = #DFU_STATUS_ERROR_NOTDONE And
             Status\bState = #STATE_DFU_DOWNLOAD_BUSY
            Delay(100)
          Else
            If Status\bStatus = #DFU_STATUS_ERROR_WRITE
              SetLastErr(#DFU_Err_ProtectMem)
            Else
              Res = Status\bStatus
            EndIf
            Break
          EndIf
        Else
          ClearStatus(*DevID)
        EndIf
        
        Retries+1
        
        If Retries > 20
          SetLastErr(#DFU_Err_TimeOut)
          Break
        EndIf
        
      ForEver
    Else
      SetLastErr(#DFU_Err_DownFunct)
    EndIf
    
  Else
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure StartApp(*DevID.DevID, Mode=#DFU_StartApp_WDT) ; Run the main program from the bootloader.
  Protected Dim Command.a(4)
  Protected Res = #False, Size=0
  
  If *DevID
    
    If Mode=#DFU_StartApp_WDT
      PokeL(@Command(), $00000304)
      Size = 3
    ElseIf Mode=#DFU_StartApp_JMP0
      PokeL(@Command(), $00010304)
      Command(4) = 0
      Size = 5
    EndIf
    
    If Size>0
      If Download(*DevID, @Command(), Size) = Size
        If Download(*DevID, 0, 0) = 0
          Res = #True
        Else
          SetLastErr(#DFU_Err_DownFunct)
        EndIf
      Else
        SetLastErr(#DFU_Err_DownFunct)
      EndIf
    Else
      SetLastErr(#DFU_Err_BadParam)
    EndIf
    
  Else
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Choice of the memory block MK (only for Xmega and AVR32).
Procedure SelectMemoryUnit(*DevID.DevID, Unit)
  Protected Dim Command.a(3)
  Protected Status.DFU_Status
  Protected Res = #False
  
  If *DevID\Avr\DevType & #GRP_AVR32
    
    If Unit>=0 And Unit <= #mem_extdf
      
      PokeL(@Command(), $00000306)
      Command(3) = Unit & 255
      
      If Download(*DevID, @Command(), 4) = 4
        If GetStatus(*DevID, @Status)
          If Status\bStatus = #DFU_STATUS_OK
            Res = #True
          Else
            If Status\bState = #STATE_DFU_ERROR
              ClearStatus(*DevID)
            EndIf
          EndIf
        Else
          SetLastErr(#DFU_Err_StatusParam)
        EndIf
      Else
        SetLastErr(#DFU_Err_DownFunct)
      EndIf
      
    EndIf
    
  Else
    Res = #True
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Selecting the memory page of the MC. The page size is 64 KB.
Procedure SelectMemoryPage(*DevID.DevID, Page.u)
  Protected Dim Command.a(5)
  Protected Status.DFU_Status
  Protected Res = #False, Size = 0
  
  If *DevID\Avr\DevType & #GRP_AVR32
    PokeL(@Command(), $00010306)
    Command(3) = (Page>>8) & 255
    Command(4) = Page & 255
    Size = 5
  ElseIf *DevID\Avr\DevType = #MK_AVR
    PokeL(@Command(), $00000306)
    Command(3) = Page & $FF
    Size = 4
  EndIf
  
  If Size = 0 Or Download(*DevID, @Command(), Size) = Size
    If GetStatus(*DevID, @Status)
      If Status\bStatus = #DFU_STATUS_OK
        Res = #True
      Else
        If Status\bState = #STATE_DFU_ERROR
          ClearStatus(*DevID)
        EndIf
      EndIf
    EndIf
  ElseIf Size > 0
    SetLastErr(#DFU_Err_DownFunct)
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Reading Configuration Information (Configuration Information)
; or manufacturer information (Manufacturer Information)
Procedure ReadCommand(*DevID.DevID, Data0.a, Data1.a)
  Protected Dim Command.a(3)
  Protected Status.DFU_Status
  Protected Res = -1
  
  If *DevID\Avr\DevType & #GRP_AVR32
    
    If SelectMemoryUnit(*DevID, Data0)
      If GetFlashBlock(*DevID.DevID, @Command(), Data1, Data1, -1, #MemType_Flash)
        Res = Command(Data1)
      EndIf
    EndIf
    
  Else
    
    PokeL(@Command(), $00000005)
    
    Command(1) = Data0
    Command(2) = Data1
    
    If Download(*DevID, @Command(), 3) = 3
      If GetStatus(*DevID, @Status)
        If Status\bStatus = #DFU_STATUS_OK
          Res = 0
          If Upload(*DevID, @Res, 1) <> 1
            Res = -2
          EndIf
        Else
          ClearStatus(*DevID)
        EndIf
      Else
        SetLastErr(#DFU_Err_StatusParam)
      EndIf
    Else
      SetLastErr(#DFU_Err_DownFunct)
    EndIf
    
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Formation of the header for recording data in the MC.
Procedure SetFlashHeader(*Header.ArrA, Start, Size, Type)
  Protected Res = #False
  
  If *Header And Start>=0 And Size>0 And (Type=#MemType_Flash Or Type=#MemType_EEPROM)
    *Header\a[0] = 1 ; Start programming.
    *Header\a[1] = Bool(Type=#MemType_EEPROM) ; Flash или EEPROM.
    ; Start address.
    *Header\a[2] = (Start>>8) & 255
    *Header\a[3] = Start & 255
    ; End address.
    *Header\a[4] = (Size>>8) & 255
    *Header\a[5] = Size & 255
    Res = #True
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure SetFlashFooter(*Message.ArrA, *Footer.ArrA, PID.u, VID.u)
  Protected CRC.l=0, Res = #False
  
  If *Message And *Footer
    ;PokeL(*Footer, CRC)      ; TODO - there must be a CRC calculation.
    
    *Footer\a[0] = (CRC>>24) & 255
    *Footer\a[1] = (CRC>>16) & 255
    *Footer\a[2] = (CRC>>8) & 255
    *Footer\a[3] = CRC & 255
    
    *Footer\a[4] = 16        ; Length of suffix.
    *Footer\a[5] = 'D' & 255 ; Signature.
    *Footer\a[6] = 'F' & 255
    *Footer\a[7] = 'U' & 255
    
    *Footer\a[8] = $01
    *Footer\a[9] = $10
    
    *Footer\a[10] = (VID>>8) & 255
    *Footer\a[11] = VID & 255
    
    *Footer\a[12] = (PID>>8) & 255
    *Footer\a[13] = PID & 255
    
    *Footer\a[14] = $FF
    *Footer\a[15] = $FF
    
;     PokeU(@*Footer\a[8], $0100)
;     PokeU(@*Footer\a[10], VID)
;     PokeU(@*Footer\a[12], PID)
;     PokeU(@*Footer\a[14], $FFFF) ; Device release number or FFFFh
    Res = #True
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Запись блока в флеш.
Procedure SetFlashBlock(*DevID.DevID, *Buff.ArrA, Start, Ends, MemEnd, Type)
  Protected Dim Message.a(#ATMEL_MAX_FLASH_BUFFER_SIZE)
  Protected *Header.ArrA, *Data.ArrA, *Footer
  Protected Status.DFU_Status
  Protected Res = #False, i, Length, x
  Protected ControlBlockSize, Alignment=0
  
  Length = Ends - Start
  
  If *DevID And *Buff And Start=>0 And Length>0 And Length < #ATMEL_64KB_PAGE And
     (Type=#MemType_Flash Or Type=#MemType_EEPROM)
    
    If *DevID\Avr\DevType & #GRP_AVR32
      ControlBlockSize = #ATMEL_AVR32_CTRL_BLOCK_SIZE
      Alignment = Start % #ATMEL_AVR32_CTRL_BLOCK_SIZE
    Else
      ControlBlockSize = #ATMEL_CONTROL_BLOCK_SIZE
      Alignment = 0
    EndIf
    
    *Header = @Message(0)
    *Data   = @Message(ControlBlockSize + Alignment)
    *Footer = *Data + Length
    
    If SetFlashHeader(*Header, Start % #ATMEL_64KB_PAGE,
                   (Ends-1) % #ATMEL_64KB_PAGE, Type)
      
      If *DevID\Avr\DevType & #MK_XMEGA
        *Header\a[1] = 0
      EndIf
      
      
      Length-1
      For i=0 To Length
        *Data\a[i] = *Buff\a[Start+i]
      Next i
      
      If SetFlashFooter(@Message(), *Footer, *DevID\Avr\PID, *DevID\Avr\VID)
        
        Length = *Footer - *Header + #ATMEL_FOOTER_SIZE
        
        If Download(*DevID, @Message(), Length) = Length 
          If GetStatus(*DevID, @Status)
            If Status\bStatus = #DFU_STATUS_OK
              Res = #True
            Else
              If Status\bState = #STATE_DFU_ERROR
                ClearStatus(*DevID)
              EndIf
              SetLastErr(#DFU_Err_StatusParam)
            EndIf
          Else
            SetLastErr(#DFU_Err_StatusParam)
          EndIf
        Else
          SetLastErr(#DFU_Err_DownFunct)
        EndIf
        
        SetProgress(*DevID, Ends, MemEnd)
        
      Else
        SetLastErr(#DFU_Err_BadParam)
      EndIf
    Else
      SetLastErr(#DFU_Err_BadParam)
    EndIf
  Else
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Запись в флеш-память МК.
Procedure SetFlash(*DevID.DevID,
                   *Buff, ; Адрес буфера с данными.
                   Size,  ; Размер буфера в байтах.
                   Start, ; Стартовый адрес (начиная с 0) куда записывать данные.
                   Type)  ; Тип памяти. См. константы #MemType_xxxx.
  Protected Res = #True
  Protected x, i, MemPage
  Protected Pos, MemEnd
  
  If *DevID And *Buff And Size>0 And Start>=0 And (Type=#MemType_Flash Or Type=#MemType_EEPROM)
    
    If Type=#MemType_Flash
      x=#mem_flash
    Else
      x=#mem_eeprom
    EndIf
    
    If SelectMemoryUnit(*DevID, x)
      Pos     = Start
      MemEnd  = Start + Size - 1
      MemPage = Start / #ATMEL_64KB_PAGE
      If SelectMemoryPage(*DevID, MemPage)
        
        SetProgress(*DevID, 0, 0)
        
        While Pos < MemEnd
          
          If MemPage <> Pos / (#ATMEL_64KB_PAGE-1)
            MemPage = Pos / (#ATMEL_64KB_PAGE-1)
            If SelectMemoryPage(*DevID, MemPage) = #False ; Ошибка!
              Res = #False
              SetLastErr(#DFU_Err_DownFunct)
              Break
            EndIf
          EndIf
          
          If MemEnd-Pos > #ATMEL_MAX_TRANSFER_SIZE
            x=#ATMEL_MAX_TRANSFER_SIZE
          Else
            x = MemEnd - Pos + 1
          EndIf
          
          If SetFlashBlock(*DevID, *Buff, Pos, x+Pos, MemEnd, Type) = #False
            Res = #False
            Break
          EndIf
          
          Pos + x
          
        Wend
        
      Else
        Res = #False
        SetLastErr(#DFU_Err_DownFunct)
      EndIf
    Else
      Res = #False
      SetLastErr(#DFU_Err_DownFunct)
    EndIf
    
  Else
    Res = #False
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Чтение блока
Procedure GetFlashBlock(*DevID.DevID, *Buff.ArrA, Start, Ends, MemEnd, Type)
  Protected Dim Command.a(5)
  Protected Status.DFU_Status
  Protected Res = #False, Length
  
  If Start = Ends
    Ends + 1
  EndIf
  
  Length = Ends - Start
    
  If *DevID And *Buff And Start>=0 And Length>0 And Length<#ATMEL_64KB_PAGE And
     (Type=#MemType_Flash Or Type=#MemType_EEPROM)
    
    Command(0) = $03
    
    If Type=#MemType_EEPROM And *DevID\Avr\DevType & #GRP_AVR
      Command(1) = 2
    EndIf
    
    Command(2) = (Start>>8) & 255
    Command(3) = Start & 255
    Command(4) = ((Ends-1)>>8) & 255
    Command(5) = (Ends-1) & 255
    
    If Download(*DevID, @Command(), 6) = 6
      If Upload(*DevID, *Buff+Start, Length) = Length
        If GetStatus(*DevID, @Status)
          If Status\bStatus = #DFU_STATUS_OK
            Res = #True
          Else
            If Status\bStatus = #DFU_STATUS_ERROR_FILE
              SetLastErr(#DFU_Err_ProtectMem)
            Else
              SetLastErr(#DFU_Err_StatusParam)
            EndIf
            ClearStatus(*DevID)
          EndIf
        Else
          SetLastErr(#DFU_Err_StatusParam)
        EndIf
      Else
        SetLastErr(#DFU_Err_UpFunct)
      EndIf
    Else
      SetLastErr(#DFU_Err_DownFunct)
    EndIf
    
    SetProgress(*DevID, Ends, MemEnd)
    
  Else
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  
  ProcedureReturn Res
EndProcedure

; Reading flash.
Procedure GetFlash(*DevID.DevID,
                   *Buff, ; The address of the buffer with data.
                   Size,  ; The size of the buffer in bytes.
                   Start, ; Start address (starting from 0) where to write data.
                   Type)  ; Type of memory. See the constants #MemType_xxxx.
  Protected Res = #True
  Protected x, i, MemPage
  Protected Pos, MemEnd
  
  If *DevID And *Buff And Size>0 And Start>=0 And (Type=#MemType_Flash Or Type=#MemType_EEPROM)
    
    If Type=#MemType_Flash
      x=#mem_flash
    Else
      x=#mem_eeprom
    EndIf
    
    If SelectMemoryUnit(*DevID, x)
      Pos     = Start
      MemEnd  = Start + Size - 1
      MemPage = Start / #ATMEL_64KB_PAGE
      If SelectMemoryPage(*DevID, MemPage)
        
        SetProgress(*DevID, 0, 0)
        
        While Pos < MemEnd
          
          If MemPage <> Pos / (#ATMEL_64KB_PAGE-1)
            MemPage = Pos / (#ATMEL_64KB_PAGE-1)
            If SelectMemoryPage(*DevID, MemPage) = #False ; Error!
              Res = #False
              SetLastErr(#DFU_Err_DownFunct)
              Break
            EndIf
          EndIf
          
          If MemEnd-Pos > #ATMEL_MAX_TRANSFER_SIZE ;#ATMEL_64KB_PAGE / 2
            x=#ATMEL_MAX_TRANSFER_SIZE ;#ATMEL_64KB_PAGE / 2
          Else
            x = MemEnd - Pos + 1
          EndIf
          
          If GetFlashBlock(*DevID, *Buff, Pos, x+Pos, MemEnd, Type) = #False
            Res = #False
            Break
          EndIf
          
          Pos + x
          
        Wend
        
      Else
        Res = #False
        SetLastErr(#DFU_Err_DownFunct)
      EndIf
    Else
      Res = #False
      SetLastErr(#DFU_Err_DownFunct)
    EndIf
    
  Else
    Res = #False
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure ProgMK(*DevID.DevID, File.s, Type, *CheckInfo.DFU_CheckInfo=0)
  Protected Res = #False, FileID, i, LastErr.l
  Protected SizeFile.q, *Buff.ArrA=0, *Check.ArrA=0
  
  FileID = ReadFile(#PB_Any, File)
  If FileID
    SizeFile = Lof(FileID)
    If SizeFile>0 And SizeFile<10000000
      *Buff = AllocateMemory(SizeFile)
      If *Buff
        If ReadData(FileID, *Buff, SizeFile) = SizeFile
          Res = SetFlash(*DevID, *Buff, SizeFile, 0, Type)
          
          If *CheckInfo ; You need to perform a memory test.
            *CheckInfo\Address = -1
            *CheckInfo\Res     = -1
            
            If Res
              *Check = AllocateMemory(SizeFile)
              If *Check
                LastErr = DFU_GetLastErr()
                If GetFlash(*DevID, *Check, SizeFile, 0, Type)
                  SizeFile-1
                  *CheckInfo\Res = 1
                  For i =0 To SizeFile
                    If *Buff\a[i]<>*Check\a[i]
                      *CheckInfo\Res = 0
                      *CheckInfo\Address  = i
                      *CheckInfo\BuffByte = *Buff\a[i]
                      *CheckInfo\ChipByte = *Check\a[i]
                      SetLastErr(#DFU_Err_IncorrectData)
                      Break
                    EndIf
                  Next i
                EndIf
                FreeMemory(*Check)
                *CheckInfo\LastErr = DFU_GetLastErr()
                SetLastErr(LastErr)
              EndIf
            EndIf
          EndIf
          
        Else
          SetLastErr(#DFU_Err_IncorrectFile)
        EndIf
        
        FreeMemory(*Buff)
      Else
        SetLastErr(#DFU_Err_Internal)
      EndIf
    Else
      SetLastErr(#DFU_Err_IncorrectFile)
    EndIf
    CloseFile(FileID)
  Else
    SetLastErr(#DFU_Err_OpenFile)
  EndIf
  
  ProcedureReturn Res
EndProcedure

;- **** Misc ****

Procedure DevType(ChipType.b)
  Debug "- DevType()"
  Protected Res = 0
  
  If ChipType>#DFU_ChipType_Auto And ChipType<#DFU_ChipType_Max
    Res = #MK_AVR32
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure.u TypeToPID(ChipType.b)
  Debug "- TypeToPID()"
  Protected PID.u = 0
  
  Select ChipType
    Case #DFU_ChipType_FF32 : PID = $f8b9 ; FF32 HEX(04d8:f8b9) DEC(1240:63673)
    Case #DFU_ChipType_16U4 : PID = $2FF3 ; ATmega16U4    
    Case #DFU_ChipType_32U4 : PID = $2FF4 ; ATmega32U4    
  EndSelect
  
  Debug "-- TypeToPID("+PID+") FF32 Hex(04d8:f8b9) DEC(1240:63673)"
  ProcedureReturn PID
EndProcedure

Procedure.b PidToType(PID.u)
  Debug "- PidToType()"
  Protected ChipType.b=-1
  
  Select PID
    Case $f8b9 : ChipType = #DFU_ChipType_FF32 ; FF32 HEX(04d8:f8b9) DEC(1240:63673)
    Case $2FF3 : ChipType = #DFU_ChipType_16U4
    Case $2FF4 : ChipType = #DFU_ChipType_32U4
    Default    : ChipType = #DFU_ChipType_Unknown
  EndSelect
  
  ProcedureReturn ChipType
EndProcedure

Procedure SetProgress(*DevID.DevID, Pos, Ends)
  Protected x.f
  
  If *DevID And *DevID\Avr\ProgressCB And Ends>=0
    If Pos>0
      If Pos<Ends
        x = 100 / (Ends/Pos)
      Else
        x = 100
      EndIf
    Else
      x=0
    EndIf
    *DevID\Avr\ProgressCB(x)
  EndIf
EndProcedure

Macro InitTest()
  Debug "- InitTest()"
  If gInitLibState <> #True
    SetLastErr(#DFU_Err_NoInit)
    Debug "-- InitTest(Err_NoInit)"
    ProcedureReturn 0
  Else
    SetLastErr(#DFU_Err_OK)
    Debug "-- InitTest(Err_OK)"
  EndIf
EndMacro

;- **** Public ****

Procedure DFU_Init() ; It is necessary to call in the beginning of work with the library. Returns not zero if the initialization is successful.
  Protected Res = #False, x
  
  usb_init()
  Res = #True
  gInitLibState = #True
  
  ProcedureReturn Res
EndProcedure

; Код текущей ошибки. См константы DFU_Err_xxxx.
Procedure.l DFU_GetLastErr()
  ProcedureReturn gLastErr
EndProcedure

Procedure DFU_DevOpen(ChipType.b) ; Installation of the bluetooth in the MK. See the constants DFU_ChipType_xxxx.
  Debug "- DFU_DevOpen()"
  Protected *Res = 0, *DevID.DevID
  Protected PID.u=$f8b9, VID.u=$04d8, i ; FF32 HEX(04d8:f8b9) DEC(1240:63673)
  
  InitTest()
  
  ;If ChipType>=#DFU_ChipType_Auto And ChipType<#DFU_ChipType_Max
    
  *DevID = AllocateMemory(SizeOf(DevID))
  Debug "-- DFU_DevOpen().DevID.SizeOf: " + SizeOf(DevID)
  If *DevID
    Debug "-- DFU_DevOpen().DevID: PASS"
      InitializeStructure(*DevID, DevID)
      
;       If ChipType=#DFU_ChipType_Auto
;         Debug "-- DFU_DevOpen().DevID.ChipType"
;         
;         Protected Dim ID.UsbID(#DFU_ChipType_Max-#DFU_ChipType_Auto-2)
;         Protected Usb.UsbID
;         
;         For i=#DFU_ChipType_Auto+1 To #DFU_ChipType_Max-1
;           ID(i-1)\VID = VID
;           ID(i-1)\PID = TypeToPID(i)
;           Debug "-- DFU_DevOpen().DevID.ChipType: VID: " + RSet(Hex(VID), 4, "0") + " PID: " + RSet(Hex(TypeToPID(i)), 4, "0")
;         Next i
;         
;         If OpenMultiDevice(ID(), *DevID, @Usb)
;           *DevID\Avr\PID = Usb\PID
;           *DevID\Avr\VID = Usb\VID
;           *DevID\Avr\ChipType = PidToType(*DevID\Avr\PID)
;           *DevID\Avr\DevType = DevType(*DevID\Avr\ChipType)
;           *Res = *DevID
;         EndIf
; 
;       Else
      
        Debug "-- DFU_DevOpen().DevID.PID"
        PID = TypeToPID(#DFU_ChipType_FF32)
        Debug "-- DFU_DevOpen().DevID.PID("+PID+")"
        
        If PID<>0
          Debug "-- DFU_DevOpen().DevID.PID0.OpenDevice: PID: " + PID + " VID: " + VID + " DevID: " + *DevID
          If OpenDevice(PID, VID, *DevID)
            Debug "-- DFU_DevOpen().DevID.OpenDevice"
            *DevID\Avr\PID = PID
            *DevID\Avr\VID = VID
            *DevID\Avr\ChipType = ChipType
            *DevID\Avr\DevType = DevType(ChipType)
            *Res = *DevID
          EndIf
        Else
          SetLastErr(#DFU_Err_ChipBad)
        EndIf
        
;      EndIf
      
    Else
      SetLastErr(#DFU_Err_Internal)
    EndIf
;   Else
;     SetLastErr(#DFU_Err_ChipBad)
;   EndIf
  
  If *DevID And *Res=0
    ClearStructure(*DevID, DevID)
    FreeMemory(*DevID)
  EndIf
  
  ProcedureReturn *Res
EndProcedure

Procedure DFU_DevClose(*DevID.DevID)    ; Разрыв связи с МК.
  Protected Res = #False
  
  InitTest()
  
  If *DevID And *DevID\hDev
    usb_release_interface(*DevID\hDev, *DevID\usbInterface)
    CloseDevice(*DevID\hDev)
    *DevID\hDev = 0
    ClearStructure(*DevID, DevID)
    FreeMemory(*DevID)
    Res = #True
  Else
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure DFU_EraseFlash(*DevID.DevID) ; Стирание памяти программ.
  
  InitTest()
  
  ProcedureReturn EraseFlash(*DevID)
EndProcedure

Procedure DFU_StartApp(*DevID.DevID, Mode=#DFU_StartApp_WDT) ; Запуск основной программы из загрузчика
  
  InitTest()
  
  ProcedureReturn StartApp(*DevID, Mode)
EndProcedure

Macro GetChipInfo(Info, d1, d2)
  x=ReadCommand(*DevID, d1, d2)
  If x>=0
    Info = x
  Else
    ProcedureReturn 0
  EndIf
EndMacro

Procedure DFU_ChipInfo(*DevID.DevID, *Info.DFU_ChipParam) ; Информаця о конфигурации и производителе.
  Protected Res = #False, x
  
  InitTest()
  
  If *DevID And *Info
    
    If *DevID\Avr\DevType & #GRP_AVR32
      GetChipInfo(*Info\BootVersion, 4, 0)
      GetChipInfo(*Info\bootID1, 4, 1)
      GetChipInfo(*Info\bootID2, 4, 2)
      GetChipInfo(*Info\Manufacturer, 5, 0)
      GetChipInfo(*Info\Family, 5, 1)
      GetChipInfo(*Info\ProductName, 5, 2)
      GetChipInfo(*Info\Revision, 5, 3)
    Else
      GetChipInfo(*Info\BootVersion, 0, 0)
      GetChipInfo(*Info\bootID1, 0, 1)
      GetChipInfo(*Info\bootID2, 0, 2)
      GetChipInfo(*Info\Manufacturer, 1, $30)
      GetChipInfo(*Info\Family, 1, $31)
      GetChipInfo(*Info\ProductName, 1, $60)
      GetChipInfo(*Info\Revision, 1, $61)
    EndIf
  
    *Info\ChipType = *DevID\Avr\ChipType
    Res = #True
    
  Else
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Прошивка памяти программ микроконтроллера.
Procedure DFU_ProgFlash(*DevID.DevID, File.s, *CheckInfo.DFU_CheckInfo=0)
  Protected Res = #False
  
  InitTest()
  
  If *DevID
    If LCase(GetExtensionPart(File))="bin"
      Res = ProgMK(*DevID, File, #MemType_Flash, *CheckInfo)
    Else
      SetLastErr(#DFU_Err_IncorrectFile)
    EndIf
  Else
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Прошивка памяти программ микроконтроллера.
Procedure DFU_ProgEEPROM(*DevID.DevID, File.s, *CheckInfo.DFU_CheckInfo=0)
  Protected Res = #False
  
  InitTest()
  
  If *DevID
    If LCase(GetExtensionPart(File))="eep"
      Res = ProgMK(*DevID, File, #MemType_EEPROM, *CheckInfo)
    Else
      SetLastErr(#DFU_Err_IncorrectFile)
    EndIf
  Else
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

Procedure DFU_SetProgressCB(*DevID.DevID, *CB_Proc) ; Установка адреса CallBack процедуры.
  Protected Res = #False
  
  InitTest()
  
  If *DevID
    *DevID\Avr\ProgressCB = *CB_Proc
    Res = #True
  Else
    SetLastErr(#DFU_Err_BadParam)
  EndIf
  
  ProcedureReturn Res
EndProcedure

; Записывает (прошивает) в МК из буфера *Buff число байт заданное в Size.
; Куда запишет (Flash или EEPROM зависит от параметра MemType).
; Процедура вернет не 0 в случае успешного выполнения.
Procedure DFU_WriteBuff(*DevID.DevID, *Buff, Size, MemType=#DFU_MemType_Flash)
  
  InitTest()
  
  ProcedureReturn SetFlash(*DevID, *Buff, Size, 0, MemType)
  
EndProcedure

; Считывает из МК в буфер *Buff число байт заданное в Size.
; Откуда читает (Flash или EEPROM зависит от параметра MemType).
; Процедура вернет не 0 в случае успешного выполнения.
Procedure DFU_ReadBuff(*DevID.DevID, *Buff, Size, MemType=#DFU_MemType_Flash)

  InitTest()
  
  ProcedureReturn GetFlash(*DevID, *Buff, Size, 0, MemType)
  
EndProcedure

EndModule

log / журнал

Код:
DFU_Init: 1 - USB library initialized.
- BootIO()
- DFU_DevOpen()
- InitTest()
-- InitTest(Err_OK)
-- DFU_DevOpen().DevID.SizeOf: 38
-- DFU_DevOpen().DevID: PASS
-- DFU_DevOpen().DevID.PID
- TypeToPID()
-- TypeToPID(63673) FF32 Hex(04d8:f8b9) DEC(1240:63673)
-- DFU_DevOpen().DevID.PID(63673)
-- DFU_DevOpen().DevID.PID0.OpenDevice: PID: 63673 VID: 1240 DevID: 93871810975580
- OpenDevice()
- OpenDevice() PID: 63673 VID: 1240
- FindDevide()
-- FindDevide().*ID
-- FindDevide().*ID.*usb_busses: 93871810243568
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 36 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 32903 ---- 1240
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 2 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 7531 ---- 1240
-- FindDevide().*ID.*usb_busses: 93871809902192
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 725 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 22918 ---- 1240
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 8678 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 2652 ---- 1240
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 8224 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 5246 ---- 1240
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 63673 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 1240 ---- 1240
-- FindDevide().*ID.*usb_busses.*devices.IF: 63673 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 1240 ---- 1240
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 36 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 32903 ---- 1240
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 2 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 7531 ---- 1240
-- FindDevide().*ID.*usb_busses: 93871813724160
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 3 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 7531 ---- 1240
-- FindDevide().*ID.*usb_busses: 93871813714944
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 11905 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 8888 ---- 1240
-- FindDevide().*ID.*usb_busses.*devices
-- FindDevide().*ID.*usb_busses.*devices.IF
-- FindDevide().*ID.*usb_busses.*devices.IF: 2 ---- 63673
-- FindDevide().*ID.*usb_busses.*devices.IF: 7531 ---- 1240
-- OpenDevice().*Dev - Found
- OpenDevice_Connect()
- DevInterface()
- DevInterface().bNumConfigurations: 0
- DevInterface().*Dev\config: 93871809944064
- DevInterface().SizeOf.usb_config_descriptor: 40
- DevInterface().config: 93871809944064
- DevInterface().Res: 0
-- OpenDevice_Connect().*DevID(93871810142208)
-- OpenDevice_Connect().*DevID.hDev(93871810045504)
--- OpenDevice_Connect().*DevID.hDev
-------(((( 4294967280
-- BootIO().hDev: 0
ERROR - ERROR configuration or USB interface.

0

5

Do you use this code for a connection with a FF34 chip? He is not meant for this.
You asked for an example of using libusb. This code is such an example. To communicate with FF34, you need to study the documentation and use the libusb.pbi file to write the program.

0