Read Write to USB?

Linux specific forum
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Read Write to USB?

Post by vwidmer »

I recently picked up a FF32 usb board and was hoping to try and be able to use it from PB I am new to the micro-controller world so its just a learning experience.

I have a very limited Python / C skill set and I found the python version of the code a bit easier for me to understand the then C counterpart.

Code: Select all

#!/usr/bin/env python
"""FLYFISH TECHNOLOGIES Ltd.
http://www.flyfish-tech.com/FF32/index.php

FF32 Python 2.7 module
Ported from the FF32 demo 'C' code to Python 2.7 by Douglas Otwell

This code is in the Public Domain. Use it at your own risk.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

# pyudev is required; install with 'sudo apt-get install python-pyudev' (on debian/raspian)
import pyudev

__version__ = "0.3.0"


class FF32:
    PRODUCT_NAME = "FF32"

    CMD_SET_ADDRESS = 0x10
    CMD_GET_ADDRESS = 0x11
    CMD_SET_VENDOR = 0x12
    CMD_GET_VENDOR = 0x13
    CMD_SET_PRODUCT = 0x14
    CMD_GET_PRODUCT = 0x15
    CMD_SET_SERIAL_NUMBER = 0x16
    CMD_GET_SERIAL_NUMBER = 0x17

    CMD_SET_DIGITAL_OUTPUT = 0x20
    CMD_SET_BLOCK_DIGITAL_OUTPUTS = 0x30
    CMD_READ_DIGITAL_INPUT = 0x21
    CMD_READ_BLOCK_DIGITAL_INPUTS = 0x31
    CMD_SET_PWM_OUTPUT = 0x22
    CMD_READ_ANALOG_INPUT = 0x23
    CMD_CONFIG_SPI_BUS = 0x24
    CMD_WRITE_SPI_BUS = 0x25
    CMD_READ_SPI_BUS = 0x26

    CMD_CONFIG_I2C_BUS = 0x27
    CMD_WRITE_I2C_BUS = 0x28
    CMD_READ_I2C_BUS = 0x29
    CMD_CONFIG_1WIRE_BUS = 0x2A
    CMD_WRITE_1WIRE_BUS = 0x2B
    CMD_READ_1WIRE_BUS = 0x2C

    CMD_GET_CHIP_INFO = 0x71

    def __init__(self, device_num=1):
        self.path = None
        self.file = None
        self.device_num = device_num

    def __enter__(self):
        self.getPath()
        self.openComm()
        return self

    def __exit__(self, type, value, traceback):
        self.closeComm()

    def getChipInfo(self):
        """Return the chip version as (major, minor)."""
        version = None
        bytes = bytearray([0x00, FF32.CMD_GET_CHIP_INFO])
        bytes = self.sendData(bytes)
        if bytes[1] == 0x0F and bytes[2] == 0x0B:
            version = (bytes[3], bytes[4]);

        return version

    def setAddress(self, addr):
        """Set the chip address."""
        bytes = bytearray([0x00, FF32.CMD_SET_ADDRESS, addr])
        bytes = self.sendData(bytes)
        if bytes[0] != 0x0E:
            raise FF32Error("Error setting the chip address; error code: 0x%02X" % (bytes[0]))

    def getAddress(self):
        """Get the chip address as a byte."""
        bytes = bytearray([0x00, FF32.CMD_GET_ADDRESS])
        bytes = self.sendData(bytes)

        return bytes[1]

    def setVendor(self, vendor):
        """Set the board vendor string."""
        bytes = bytearray([0x00, FF32.CMD_SET_VENDOR])
        bytes += bytearray(vendor[:30].ljust(31, chr(0)), 'utf-8')
        self.sendData(bytes)

    def getVendor(self):
        """Get the board vendor string."""
        bytes = bytearray([0x00, FF32.CMD_GET_VENDOR])
        bytes = self.sendData(bytes)
        vendor = bytes[1:bytes.index(0)].decode()

        return vendor

    def setProduct(self, product):
        """Set the board product string."""
        bytes = bytearray([0x00, FF32.CMD_SET_PRODUCT])
        bytes += bytearray(product[:30].ljust(31, chr(0)), 'utf-8')
        bytes = self.sendData(bytes)

    def getProduct(self):
        """Get the board product string."""
        bytes = bytearray([0x00, FF32.CMD_GET_PRODUCT])
        bytes = self.sendData(bytes)
        product = bytes[1:bytes.index(0)].decode()

        return product

    def setSerialNumber(self, serial):
        """Set the board serial number string."""
        bytes = bytearray([0x00, FF32.CMD_SET_SERIAL_NUMBER])
        bytes += bytearray(serial[:30].ljust(31, chr(0)), 'utf-8')
        bytes = self.sendData(bytes)

    def getSerialNumber(self):
        """Get the board serial number string."""
        bytes = bytearray([0x00, FF32.CMD_GET_SERIAL_NUMBER])
        bytes = self.sendData(bytes)
        serial = bytes[1:bytes.index(0)].decode()

        return serial

    def setDigitalOutput(self, xxx_todo_changeme, state):
        """Set a pin high (1) or low (0)."""
        (pin_block, pin_num) = xxx_todo_changeme
        self.__validatePin(pin_block, pin_num)
        bytes = bytearray([0x00, FF32.CMD_SET_DIGITAL_OUTPUT, self.convert_str_byte_int(pin_block), pin_num,state])
        #print(bytes)
        bytes = self.sendData(bytes)
        if bytes[0] != 0x0E:
            raise FF32Error("Error setting PWM output; error code: 0x%02X" % (bytes[0]))

    def setBlockDigitalOutputs(self, pin_block, bitmask, states):
        """Set a block of pins at a time, with a bitmask"""
        self.__validateBlock(pin_block, states)
        mask_hi = bitmask >> 8
        mask_low = bitmask - (mask_hi << 8)
        states_hi = states >> 8
        states_low = states - (states_hi << 8)
        bytes = bytearray(
            [0x00, FF32.CMD_SET_BLOCK_DIGITAL_OUTPUTS, self.convert_str_byte_int(pin_block), mask_hi, mask_low,
             states_hi, states_low])
        bytes = self.sendData(bytes)
        if bytes[0] != 0x0e:
            raise FF32Error("Error setting digital inputs; error code: 0x%02X" % (bytes[0]))

    def readDigitalInput(self, xxx_todo_changeme1):
        """Read the state of a pin, return an integer."""
        (pin_block, pin_num) = xxx_todo_changeme1
        self.__validatePin(pin_block, pin_num)
        bytes = bytearray([0x00, FF32.CMD_READ_DIGITAL_INPUT, self.convert_str_byte_int(pin_block), pin_num])
        bytes = self.sendData(bytes)
        if bytes[0] != FF32.CMD_READ_DIGITAL_INPUT:
            raise FF32Error("Error reading a digital pin; error code: 0x%02X" % (bytes[0]))

        return int(bytes[1])

    def readBlockDigitalInputs(self, pin_block, bitmask):
        mask_hi = bitmask >> 8
        mask_low = bitmask - (mask_hi << 8)
        bytes = bytearray(
            [0x00, FF32.CMD_READ_BLOCK_DIGITAL_INPUTS, self.convert_str_byte_int(pin_block), mask_hi, mask_low])
        bytes = self.sendData(bytes)
        if bytes[0] != FF32.CMD_READ_BLOCK_DIGITAL_INPUTS:
            raise FF32Error("Error reading digital inputs; error code: 0x%02X" % (bytes[0]))
        value = int(bytes[1] * 256 + bytes[2])

        return value

    def setPWMOutput(self, xxx_todo_changeme2, duty_cycle):
        """Set PWM output, 0 - 100."""
        (pin_block, pin_num) = xxx_todo_changeme2
        self.__validatePin(pin_block, pin_num)
        bytes = bytearray([0x00, FF32.CMD_SET_PWM_OUTPUT, self.convert_str_byte_int(pin_block), pin_num, duty_cycle])
        bytes = self.sendData(bytes)
        if bytes[0] != 0x0E:
            raise FF32Error("Error setting PWM output; error code: 0x%02X" % (bytes[0]))

    def readAnalogInput(self, xxx_todo_changeme3):
        """Read an analog pin and return tuple (an int representing Vcc: '3'=3V3 or '5'=5V, an int: 0-1023)."""
        (pin_block, pin_num) = xxx_todo_changeme3
        self.__validatePin(pin_block, pin_num)
        bytes = bytearray([0x00, FF32.CMD_READ_ANALOG_INPUT, self.convert_str_byte_int(pin_block), pin_num])
        bytes = self.sendData(bytes)
        if bytes[0] != FF32.CMD_READ_ANALOG_INPUT:
            raise FF32Error("Error reading an analog pin; error code: 0x%02X" % (bytes[0]))
        vcc = int(bytes[1])
        value = int(bytes[2] * 256 + bytes[3])

        return vcc, value

    def setSPIPins(self, xxx_todo_changeme4, xxx_todo_changeme5, xxx_todo_changeme6, xxx_todo_changeme7):
        """Configure SPI pins."""
        (cs_pin_block, cs_pin_num) = xxx_todo_changeme4
        (sck_pin_block, sck_pin_num) = xxx_todo_changeme5
        (mosi_pin_block, mosi_pin_num) = xxx_todo_changeme6
        (miso_pin_block, miso_pin_num) = xxx_todo_changeme7
        self.__validatePin(cs_pin_block, cs_pin_num)
        self.__validatePin(sck_pin_block, sck_pin_num)
        self.__validatePin(mosi_pin_block, mosi_pin_num)
        self.__validatePin(miso_pin_block, miso_pin_num)
        bytes = bytearray(
            [0x00, FF32.CMD_CONFIG_SPI_BUS, self.convert_str_byte_int(cs_pin_block), cs_pin_num,
             self.convert_str_byte_int(sck_pin_block), sck_pin_num, self.convert_str_byte_int(mosi_pin_block),
             mosi_pin_num, self.convert_str_byte_int(miso_pin_block), miso_pin_num])
        bytes = self.sendData(bytes)
        if bytes[0] != 0x0E:
            raise FF32Error("Error configuring I2C bus; error code: 0x%02X" % (bytes[0]))

    def writeSPIBus(self, data):
        """Write a bytarray to SPI bus."""
        if len(data) > 60:
            raise FF32Error("Error writing SPI data; write data length > 60 bytes")
        bytes = bytearray([0x00, FF32.CMD_WRITE_SPI_BUS, len(data)])
        bytes += data
        bytes = self.sendData(bytes)

    def readSPIBus(self, read_len, data):
        """Write and read bytearray to SPI buss."""
        if read_len > 60:
            raise FF32Error("Error writing SPI data; read data length > 60 bytes")
        if len(data) > 60:
            raise FF32Error("Error writing SPI data; write data length > 60 bytes")
        bytes = bytearray([0x00, FF32.CMD_READ_SPI_BUS, len(data), read_len])
        bytes += data
        bytes = self.sendData(bytes)
        if bytes[0] != FF32.CMD_READ_SPI_BUS:
            raise FF32Error("Error reading SPI data; error code: 0x%02X" % (bytes[0]))

        return bytes[2:]

    def setI2CPins(self, xxx_todo_changeme8, xxx_todo_changeme9):
        """Configure I2C pins."""
        (scl_pin_block, scl_pin_num) = xxx_todo_changeme8
        (sda_pin_block, sda_pin_num) = xxx_todo_changeme9
        self.__validatePin(scl_pin_block, scl_pin_num)
        self.__validatePin(sda_pin_block, sda_pin_num)
        bytes = bytearray([0x00, FF32.CMD_CONFIG_I2C_BUS, self.convert_str_byte_int(scl_pin_block), scl_pin_num, self.convert_str_byte_int(sda_pin_block), sda_pin_num])
        bytes = self.sendData(bytes)
        if bytes[0] != 0x0E:
            raise FF32Error("Error configuring I2C bus; error code: 0x%02X" % (bytes[0]))

    def writeI2CBus(self, data):
        """Write a bytarray to I2C bus."""
        if len(data) > 60:
            raise FF32Error("Error writing I2C data; write data length > 60 bytes")
        bytes = bytearray([0x00, FF32.CMD_WRITE_I2C_BUS, len(data)])
        bytes += data
        bytes = self.sendData(bytes)
        if bytes[0] != 0x0E:
            raise FF32Error("Error writing I2C data; error code: 0x%02X" % (bytes[0]))

    def readI2CBus(self, read_len, data):
        """Write and read bytearray to I2C bus."""
        if read_len > 60:
            raise FF32Error("Error writing I2C data; read data length > 60 bytes")
        if len(data) > 60:
            raise FF32Error("Error writing I2C data; write data length > 60 bytes")
        bytes = bytearray([0x00, FF32.CMD_READ_I2C_BUS, len(data), read_len])
        bytes += data
        bytes = self.sendData(bytes)
        if bytes[0] != FF32.CMD_READ_I2C_BUS:
            raise FF32Error("Error writing I2C data; error code: 0x%02X" % (bytes[0]))

        return bytes[2:]

    def set1WirePin(self, xxx_todo_changeme10):
        """Configure 1-wire pins."""
        (dq_pin_block, dq_pin_num) = xxx_todo_changeme10
        self.__validatePin(dq_pin_block, dq_pin_num)
        bytes = bytearray([0x00, FF32.CMD_CONFIG_1WIRE_BUS, self.convert_str_byte_int(dq_pin_block), dq_pin_num])
        bytes = self.sendData(bytes)
        if bytes[0] != 0x0E:
            raise FF32Error("Error configuring 1-Wire bus; error code: 0x%02X" % (bytes[0]))

    def write1WireBus(self, data):
        """Write a bytarray to 1-Wire bus."""
        if len(data) > 60:
            raise FF32Error("Error writing 1-Wire data; data length > 60 bytes")
        bytes = bytearray([0x00, FF32.CMD_WRITE_1WIRE_BUS, len(data)])
        bytes = self.sendData(bytes + data)
        if bytes[0] != 0x0E:
            raise FF32Error("Error writing 1-Wire data; error code: 0x%02X" % (bytes[0]))

    def read1WireBus(self, read_len, data):
        """Write and read bytearray to 1-Wire bus."""
        if read_len > 60:
            raise FF32Error("Error writing 1-Wire data; read data length > 60 bytes")
        if len(data) > 60:
            raise FF32Error("Error writing 1-Wire data; write data length > 60 bytes")
        bytes = bytearray([0x00, FF32.CMD_READ_1WIRE_BUS, len(data), read_len])
        bytes += data
        bytes = self.sendData(bytes)
        if bytes[0] != FF32.CMD_READ_1WIRE_BUS:
            raise FF32Error("Error writing 1-Wire data; error code: 0x%02X" % (bytes[0]))

        return bytes[2:]

    def writeByteI2C(self, addr, byte):
        """Write a byte to a slave address"""
        addr = addr * 2
        data = bytearray([addr, byte])
        bytes = self.writeI2CBus(data)

    def writeBlockI2C(self, addr, bytes):
        """Write a bytearray to a slave address"""
        addr = addr * 2
        data = bytearray([addr])
        data += bytes
        bytes = self.writeI2CBus(data)

    def readByteI2C(self, addr):
        """Read a byte from a slave address"""
        addr = (addr * 2) + 1
        data = bytearray([addr])
        bytes = self.readI2CBus(1, data)

        return bytes[0]

    def readWordI2C(self, addr):
        """Read a (two byte) word from a slave address (little-endian)"""
        addr = (addr * 2) + 1
        data = bytearray([addr])
        bytes = self.readI2CBus(2, data)
        little_byte = bytes[0]
        big_byte = bytes[1]
        word = big_byte * 256 + little_byte

        return word

    def readBlockI2C(self, addr, read_len):
        """Read a bytearray from a slave address"""
        addr = (addr * 2) + 1
        data = bytearray([addr])
        bytes = self.readI2CBus(read_len, data)

        return bytes[0:read_len]

    #
    # these are internal methods, but are left public for flexibility
    #

    def sendData(self, bytes):
        """Send a bytarray to the device and return a bytearray response."""
        self.file.write(bytes)
        str = self.file.read(64)
        bytes = bytearray(str)
        if len(bytes) == 0:
            raise FF32Error("No response from chip")

        return bytes

    def openComm(self):
        """Open the device."""
        self.file = open(self.path, "r+b", buffering=0)

    def closeComm(self):
        """Close the device."""
        self.file.close()

    def getPath(self):
        """Return the path name of the device"""
        count = 1
        context = pyudev.Context()
        for device in context.list_devices(subsystem="hidraw"):
            path = device.device_node;
            parentDevice = device.find_parent("usb", device_type="usb_device")
            # print("test")
            # print(parentDevice)
            # print(parentDevice.__getitem__("ID_MODEL"))
            # for attributes in parentDevice:
            #     # print(attributes)
            #     print(parentDevice.__getitem__(attributes))
            try:
                product = parentDevice.__getitem__("ID_MODEL")
                if (product == FF32.PRODUCT_NAME):
                    if (count == self.device_num):
                        self.path = path;
                        print(path)
                        return
                    count += 1
            except KeyError:
                pass

        raise FF32Error("Error locating FF32 USB device. Check USB cable.")

    #
    # private methods
    #

    def __validatePin(self, pin_block, pin_num):
        if pin_block != "A" and pin_block != "B":
            raise FF32Error("Invalid pin block; must be 'A' or 'B'")
        if pin_block == "A":
            if pin_num < 1 or pin_num > 6:
                raise FF32Error("Invalid pin number for block A; must be between 1 and 6")
        if pin_block == "B":
            if pin_num < 1 or pin_num > 12:
                raise FF32Error("Invalid pin number for block B; must be between 1 and 12")

    def __validateBlock(self, pin_block, states):
        if pin_block != "A" and pin_block != "B":
            raise FF32Error("Invalid pin block; must be 'A' or 'B'")
        if pin_block == "A":
            if states < 0 or states > 63:
                raise FF32Error("Invalid pin states for block A; must be between 0 and 63")
        if pin_block == "B":
            if states < 0 or states > 4095:
                raise FF32Error("Invalid pin states for block B; must be between 0 and 4095")

    def convert_str_byte_int(self, value):
        return int.from_bytes(value.encode('utf-8'), byteorder='little')


class FF32Error(Exception):
    pass


if __name__ == "__main__":
    with FF32() as ff32:
        print(("pyff32 module version is %s" % __version__))
        version = ff32.getChipInfo()
        if version:
            print(("Chip is FF32, silicon version %d.%d" % version))
        else:
            print("Chip is not FF32")
From what it looks like I have to read write directly to the USB.
Which from the looks of it on linux I have to use libusb?

I found this

Code: Select all

https://www.purebasic.fr/german/viewtopic.php?f=8&t=27047
Files:

Code: Select all

https://freakscorner.de/owncloud/index.php/s/HwkXCDHLNASPSAT
when I run the example code I get some strange characters.

Code: Select all

Version: 1.0.22.11312琀潯洠湡⁹潣普杩牵瑡潩獮搀獥牴祯搠癥捩⁥搥┮d敮 (瑨灴⼺氯扩獵⹢湩潦)
䥌啂䉓卟䍕䕃卓⼠䰠䉉单彂剔乁䙓剅䍟䵏䱐呅䑅
*context = 94641999562272
Bus 004 Device 013: ID 04E8:6860 䅓卍乕G 䅓卍乕彇湁牤楯d
[ERR] LIBUSB::openDevice: 䥌啂䉓䕟剒剏䅟䍃卅S䥌啂䉓䕟剒剏也彏䕄䥖䕃䰀䉉单
Bus 004 Device 002: ID 8087:0024 
[ERR] LIBUSB::openDevice: 䥌啂䉓䕟剒剏䅟䍃卅S䥌啂䉓䕟剒剏也彏䕄䥖䕃䰀䉉单
Bus 004 Device 001: ID 1D6B:0002 
[ERR] LIBUSB::openDevice: 䥌啂䉓䕟剒剏䅟䍃卅S䥌啂䉓䕟剒剏也彏䕄䥖䕃䰀䉉单
Bus 003 Device 006: ID 5986:02D5 
Bus 003 Device 005: ID 0A5C:21E6 牂慯捤浯䌠牯p 䍂㉍㜰㈰ぁ
[ERR] LIBUSB::openDevice: 䥌啂䉓䕟剒剏䅟䍃卅S䥌啂䉓䕟剒剏也彏䕄䥖䕃䰀䉉单
Bus 003 Device 004: ID 147E:2020 
[ERR] LIBUSB::openDevice: 䥌啂䉓䕟剒剏䅟䍃卅S䥌啂䉓䕟剒剏也彏䕄䥖䕃䰀䉉单
Bus 003 Device 037: ID 04D8:F8B9 
[ERR] LIBUSB::openDevice: 䥌啂䉓䕟剒剏䅟䍃卅S䥌啂䉓䕟剒剏也彏䕄䥖䕃䰀䉉单
Bus 003 Device 002: ID 8087:0024 
[ERR] LIBUSB::openDevice: 䥌啂䉓䕟剒剏䅟䍃卅S䥌啂䉓䕟剒剏也彏䕄䥖䕃䰀䉉单
Bus 003 Device 001: ID 1D6B:0002 
[ERR] LIBUSB::openDevice: 䥌啂䉓䕟剒剏䅟䍃卅S䥌啂䉓䕟剒剏也彏䕄䥖䕃䰀䉉单
Bus 002 Device 001: ID 1D6B:0003 
[ERR] LIBUSB::openDevice: 䥌啂䉓䕟剒剏䅟䍃卅S䥌啂䉓䕟剒剏也彏䕄䥖䕃䰀䉉单
Bus 001 Device 001: ID 1D6B:0002 
Again I dont understand how it works so well..

So if anyone can help me, point me in the right direction, tell me if it is isnt possible to do with PB, or howto do it would greatly appreciate it.
Thanks
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Read Write to USB?

Post by vwidmer »

Found this other libusb code on a .Ru forum

http://purebasic.mybb.ru/viewtopic.php?id=389

But its giving some errors with native types and pointers maybe some one knows to help make it work?

Thanks
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Read Write to USB?

Post by vwidmer »

So I tried updating the last code here is what I came up with based on the new libusb

https://libusb.info/

of course this is all stuff above my level of knowledge so if some one else can help to maybe make it work.

Code: Select all

;TestUSB.pb

;first of all, we have to call usb_init(). If result is > 0 than we can use the libusb0.dll

IncludeFile "USBlibP.pb"     ;Functions we can call from libusb0.dll

; Variables
Global *usb_busses.usb_bus
Global *usb_device.usb_device
Global *usb_dev_handle.usb_dev_handle

#MY_VID = $0483
#MY_PID = $FFF0

;// Device configuration And Interface id.
#MY_CONFIG = 1
#MY_INTF = 0

;// Device endpoint(s)
#EP_IN = $81
#EP_OUT = $01

;/ Device of bytes To transfer.
#BUF_SIZE = 64



Procedure showBussesAndDevicesWithInformation()
  ;Debug "Anzahl Busse: " + Str(usb_find_busses())
  Debug "Anzahl Devices: " + Str(libusb_get_device_list())
  
  *usb_busses = libusb_get_bus_number()
  
  While *usb_busses
    Debug ""
    Debug "Busname: " + PeekS(@*usb_busses\dirname)
    
    *devices.usb_device = *usb_busses\devices
    *usb_device = *usb_busses\devices
    
    While *devices
      Debug "Filename: " + PeekS(@*devices\filename)
      Debug "devnum: " + Str(*devices\devnum)
      ;Debug "dev: " + Str(*devices\dev)
      Debug "num_children: " + Str(*devices\num_children)
      Debug "children: " + Str(*devices\children)
      
      If *devices\descriptor
        Debug ""
        Debug "Device Descriptor:"
        Debug "    bcdDevice: " + Hex(*devices\descriptor\bcdDevice)
        Debug "    bcdUSB: " + Hex(*devices\descriptor\bcdUSB)
        Debug "    bDescriptorType: " + Hex(*devices\descriptor\bDescriptorType)
        Debug "    bDeviceClass: " + Hex(*devices\descriptor\bDeviceClass)
        Debug "    bDeviceProtocol: " + Hex(*devices\descriptor\bDeviceProtocol)
        Debug "    bDeviceSubClass: " + Hex(*devices\descriptor\bDeviceSubClass)
        Debug "    bLength: " + Hex(*devices\descriptor\bLength)
        Debug "    bMaxPacketSize0: " + Hex(*devices\descriptor\bMaxPacketSize0)
        Debug "    bNumConfigurations: " + Hex(*devices\descriptor\bNumConfigurations)
        Debug "    idProduct: " + RSet(Hex(*devices\descriptor\idProduct), 4, "0")
        Debug "    idVendor: " + RSet(Hex(*devices\descriptor\idVendor), 4, "0")
        Debug "    iManufacturer: " + Hex(*devices\descriptor\iManufacturer)
        Debug "    iProduct: " + Hex(*devices\descriptor\iProduct)
        Debug "    iSerialNumber: " + Hex(*devices\descriptor\iSerialNumber)
      EndIf
      
      If *devices\config
        Debug ""
        Debug "Device Config:"
        Debug "    bConfigurationValue: " + Hex(*devices\config\bConfigurationValue)
        Debug "    bDescriptorType: " + Hex(*devices\config\bDescriptorType)
        Debug "    bLength: " + Hex(*devices\config\bLength)
        Debug "    bmAttributes: " + Hex(*devices\config\bmAttributes)
        Debug "    bNumInterfaces: " + Hex(*devices\config\bNumInterfaces)
        ;Debug "    extra: " + Hex(*devices\config\extra)
        Debug "    extralen: " + Hex(*devices\config\extralen)
        Debug "    iConfiguration: " + Hex(*devices\config\iConfiguration)
        Debug "    MaxPower: " + Hex(*devices\config\MaxPower)
        Debug "    wTotalLength: " + Hex(*devices\config\wTotalLength)
        
        If *devices\config\Interface
          Debug ""
          Debug "    Interface:"
          Debug "        num_altsetting: " + Hex(*devices\config\Interface\num_altsetting)
          
          If *devices\config\Interface\altsetting
            Debug ""
            Debug "        altsetting:"
            Debug "            bAlternateSetting: " + Hex(*devices\config\Interface\altsetting\bAlternateSetting)
            Debug "            bDescriptorType: " + Hex(*devices\config\Interface\altsetting\bDescriptorType)
            Debug "            bInterfaceClass: " + Hex(*devices\config\Interface\altsetting\bInterfaceClass)
            Debug "            bInterfaceNumber: " + Hex(*devices\config\Interface\altsetting\bInterfaceNumber) 
            Debug "            bInterfaceProtocol: " + Hex(*devices\config\Interface\altsetting\bInterfaceProtocol)
            Debug "            bInterfaceSubClass: " + Hex(*devices\config\Interface\altsetting\bInterfaceSubClass)
            Debug "            bLength: " + Hex(*devices\config\Interface\altsetting\bLength)
            ;Debug "            extra: " + Hex(*devices\config\Interface\altsetting\extra)
            Debug "            extralen: " + Hex(*devices\config\Interface\altsetting\extralen)
            Debug "            iInterface: " + Hex(*devices\config\Interface\altsetting\iInterface)
            Debug "            bNumEndpoints: " + Hex(*devices\config\Interface\altsetting\bNumEndpoints)
            
            If *devices\config\Interface\altsetting\endpoint
              Debug ""
              Debug "            endpoint: "
              Debug "                bDescriptorType: " + Hex(*devices\config\Interface\altsetting\endpoint\bDescriptorType)
              Debug "                bEndpointAddress: " + Hex(*devices\config\Interface\altsetting\endpoint\bEndpointAddress)
              Debug "                bInterval: " + Hex(*devices\config\Interface\altsetting\endpoint\bInterval)
              Debug "                bLength: " + Hex(*devices\config\Interface\altsetting\endpoint\bLength)
              Debug "                bmAttributes: " + Hex(*devices\config\Interface\altsetting\endpoint\bmAttributes)
              Debug "                bRefresh: " + Hex(*devices\config\Interface\altsetting\endpoint\bRefresh)
              Debug "                bSynchAddress: " + Hex(*devices\config\Interface\altsetting\endpoint\bSynchAddress)
              ;Debug "                extra: " + Hex(*devices\config\Interface\altsetting\endpoint\extra)
              Debug "                extralen: " + Hex(*devices\config\Interface\altsetting\endpoint\extralen)
              Debug "                wMaxPacketSize: " + Hex(*devices\config\Interface\altsetting\endpoint\wMaxPacketSize)
            EndIf
          EndIf
          
        EndIf
        
      EndIf
      
      *devices = *devices\next
    Wend
    
    *usb_busses = *usb_busses\Next
  Wend 
EndProcedure

Procedure OpenAndCloseDevice2()
  If *usb_device = 0
    ProcedureReturn 0
  EndIf
  *usb_dev_handle = 0
  ;usb_find_busses()
  libusb_get_device_list()
  *usb_busses = libusb_get_bus_number()
  
  While *usb_busses
    
    *devices.usb_device = *usb_busses\devices
    *usb_device = *usb_busses\devices
    
    While *devices
      If *devices\descriptor\idVendor=#MY_VID And *devices\descriptor\idProduct=#MY_PID
        Debug "Совпали VID\PID"
        Debug ""
        Debug "idProduct: " + RSet(Hex(*usb_device\descriptor\idProduct), 4, "0")
        Debug "idVendor: " + RSet(Hex(*usb_device\descriptor\idVendor), 4, "0")
        Debug ""+Str(@*usb_device)
        Debug SizeOf(usb_device)
        
        ;UsbOppenn.Prot_UsbOppenn = GetFunction(libUsbID, "libusb_open")
        ;*usb_dev_handle = UsbOppenn(*usb_device)
        
        ;ProcedureReturn 0
        
        *usb_dev_handle = libusb_open(*usb_device)
        ;libusb_open(*usb_device)
        
        
        
        Debug ""
        Debug "Open and Close Device"
        Debug *usb_dev_handle
        Debug libusb_close(*usb_dev_handle)
        
        ProcedureReturn 0
        
      EndIf
      
      *devices = *devices\next
    Wend
    
    *usb_busses = *usb_busses\Next
  Wend   
  
EndProcedure

Procedure OpenAndCloseDevice()
  If *usb_device = 0
    ProcedureReturn 0
  EndIf
  
  Debug ""
  Debug "idProduct: " + RSet(Hex(*usb_device\descriptor\idProduct), 4, "0")
  Debug "idVendor: " + RSet(Hex(*usb_device\descriptor\idVendor), 4, "0")
  Debug ""
  
  *usb_dev_handle = libusb_open(*usb_device)
  
  ;libusb_open(*usb_device)
  
  Debug ""
  Debug "Open and Close Device"
  Debug *usb_dev_handle
  Debug libusb_close(*usb_dev_handle)
EndProcedure

Procedure libUSB0()
  Debug "Start"
  If libusb_init()
    Debug "usbinit"
    showBussesAndDevicesWithInformation()
    
    *usb_version.usb_version = libusb_get_version()
    
    Debug ""
    Debug "DLL Version: " + Str(*usb_version\dll\major) + "." + Str(*usb_version\dll\minor) + "." + Str(*usb_version\dll\micro) + "." + Str(*usb_version\dll\nano)
    Debug "Driver Version: " + Str(*usb_version\driver\major) + "." + Str(*usb_version\driver\minor) + "." + Str(*usb_version\driver\micro) + "." + Str(*usb_version\driver\nano)
    
    OpenAndCloseDevice2()
    ;this method won't work, but why?
    ;OpenAndCloseDevice()
    
    CloseLibrary(libUsbID)
  EndIf
EndProcedure

libUSB0()

Code: Select all

;USBlibP.pb

EnableExplicit

IncludeFile "usbheader.pb"; constants and structures for neobohodimye libusb0.dll

; function prototypes
; ----------------------------------------------------------------------

; allready tested and works fine

Prototype.l prot_libusb_get_version()
Prototype.l prot_libusb_init()
Prototype.l prot_libusb_find_busses()
Prototype.l prot_libusb_get_device_list()
Prototype.l prot_libusb_get_bus_number()


; ----------------------------------------------------------------------

; Don't work for me, but don't know why :(

Prototype.q prot_libusb_open(*dev.usb_device)      ;returns *usb_dev_handle
Prototype.l prot_libusb_close(*dev.usb_dev_handle) ;returns 0 if success
Prototype.l prot_libusb_set_configuration(*dev.usb_dev_handle, configuration.l) ;returns 0 If success
Prototype.l prot_libusb_set_altinterface(*dev.usb_dev_handle, alternate.l)
Prototype.l prot_libusb_resetep(*dev.usb_dev_handle, ep.l) ; usb_resetep is deprecated. Use usb_clear_halt
Prototype.l prot_libusb_clear_halt(*dev.usb_dev_handle, ep.l)
Prototype.l prot_libusb_reset(*dev.usb_dev_handle)
Prototype.l prot_libusb_claim_interface(*dev.usb_dev_handle, hInterface.l)
Prototype.l prot_libusb_release_interface(*dev.usb_dev_handle, hInterface)

Prototype.l prot_libusb_control_msg(*dev.usb_dev_handle, requesttype.l, request.l, value.l, index.l, *bytes, size.l, timeout.l)
Prototype.l prot_libusb_get_string(*dev.usb_dev_handle, index.l, langid.l, *buf, buflen.i)
Prototype.l prot_libusb_get_string_simple(*dev.usb_dev_handle, index.l, *buf, buflen.i)
Prototype.l prot_libusb_get_descriptor(*dev.usb_dev_handle, type.c, index.c, *buf, size.l)
Prototype.l prot_libusb_get_descriptor_by_endpoint(*dev.usb_dev_handle, ep.l, type.c, index.c, *buf, size.l)

Prototype.l prot_libusb_bulk_write(*dev.usb_dev_handle, ep.l, *bytes, size.l, timeout.l)
Prototype.l prot_libusb_bulk_read(*dev.usb_dev_handle, ep.l, *bytes, size.l, timeout.l)

Prototype.l prot_libusb_interrupt_write(*dev.usb_dev_handle, ep.l, *bytes, size.l, timeout.l)
Prototype.l prot_libusb_interrupt_read(*dev.usb_dev_handle, ep.l, *bytes, size.l, timeout.l)

Prototype.l prot_libusb_get_driver_np(*dev.usb_dev_handle, hInterface.l, *name, namelen.l)
Prototype.l prot_libusb_detach_kernel_driver_np(*dev.usb_dev_handle, hInterface.l)



Global libUsbID = OpenLibrary(#PB_Any, "/usr/lib/libusb-1.0.so")

;Define Function-Pointers for CallFunctionFast
If IsLibrary(libUsbID)
  
  
  Global libusb_get_version.prot_libusb_get_version             = GetFunction(libUsbID, "libusb_get_version")
  
  ;Wherein core -Functions
  Global libusb_init.prot_libusb_init                           = GetFunction(libUsbID, "libusb_init")
  Global libusb_find_busses.prot_libusb_find_busses             = GetFunction(libUsbID, "libusb_find_busses")
  Global libusb_get_device_list.prot_libusb_get_device_list           = GetFunction(libUsbID, "libusb_get_device_list")
  Global libusb_get_bus_number.prot_libusb_get_bus_number               = GetFunction(libUsbID, "libusb_get_bus_number")
  
  ;-Device operations
  Global libusb_open.prot_libusb_open                           = GetFunction(libUsbID, "libusb_open")
  Global libusb_close.prot_libusb_close                         = GetFunction(libUsbID, "libusb_close")
  Global libusb_set_configuration.prot_libusb_set_configuration = GetFunction(libUsbID, "libusb_set_configuration")
  Global libusb_set_altinterface.prot_libusb_set_altinterface   = GetFunction(libUsbID, "libusb_set_altinterface")
  Global libusb_resetep.prot_libusb_resetep                     = GetFunction(libUsbID, "libusb_resetep")
  Global libusb_clear_halt.prot_libusb_clear_halt               = GetFunction(libUsbID, "libusb_clear_halt")
  Global libusb_reset.prot_libusb_reset                         = GetFunction(libUsbID, "libusb_reset")
  Global libusb_claim_interface.prot_libusb_claim_interface     = GetFunction(libUsbID, "libusb_claim_interface")
  Global libusb_release_interface.prot_libusb_release_interface = GetFunction(libUsbID, "libusb_release_interface")
  
  ;-Control Transfer
  Global libusb_control_msg.prot_libusb_control_msg             = GetFunction(libUsbID, "libusb_control_msg")
  Global libusb_get_string.prot_libusb_get_string               = GetFunction(libUsbID, "libusb_get_string")
  Global libusb_get_string_simple.prot_libusb_get_string_simple = GetFunction(libUsbID, "libusb_get_string_simple")
  Global libusb_get_descriptor.prot_libusb_get_descriptor       = GetFunction(libUsbID, "libusb_get_descriptor")
  Global libusb_get_descriptor_by_endpoint.prot_libusb_get_descriptor_by_endpoint = GetFunction(libUsbID, "libusb_get_descriptor_by_endpoint")
  
  ;-Bulk Transfer
  Global libusb_bulk_write.prot_libusb_bulk_write               = GetFunction(libUsbID, "libusb_bulk_write")
  Global libusb_bulk_read.prot_libusb_bulk_read                 = GetFunction(libUsbID, "libusb_bulk_read")
  
  ;-Interrupt Transfer
  Global libusb_interrupt_write.prot_libusb_interrupt_write     = GetFunction(libUsbID, "libusb_interrupt_write")
  Global libusb_interrupt_read.prot_libusb_interrupt_read       = GetFunction(libUsbID, "libusb_interrupt_read")
  
  ; -No Portable
  Global libusb_get_driver_np.prot_libusb_get_driver_np         = GetFunction(libUsbID, "libusb_get_driver_np")
  Global libusb_detach_kernel_driver_np.prot_libusb_detach_kernel_driver_np = GetFunction(libUsbID, "libusb_detach_kernel_driver_np")
  
EndIf

DisableExplicit

Code: Select all

;usbheader.pb

#LIBUSB_PATH_MAX = 512

; Device And/Or Interface Class codes

#LIBUSB_CLASS_PER_INTERFACE =   0  ; For DeviceClass
#LIBUSB_CLASS_AUDIO         =   1
#LIBUSB_CLASS_COMM          =   2
#LIBUSB_CLASS_HID           =   3
#LIBUSB_CLASS_PRINTER       =   7
#LIBUSB_CLASS_MASS_STORAGE  =   8
#LIBUSB_CLASS_HUB           =   9
#LIBUSB_CLASS_DATA          =  10
#LIBUSB_CLASS_VENDOR_SPEC   = $ff

; Descriptor types
#LIBUSB_DT_DEVICE    = $01
#LIBUSB_DT_CONFIG    = $02
#LIBUSB_DT_STRING    = $03
#LIBUSB_DT_INTERFACE = $04
#LIBUSB_DT_ENDPOINT  = $05

#LIBUSB_DT_HID      = $21
#LIBUSB_DT_REPORT   = $22
#LIBUSB_DT_PHYSICAL = $23
#LIBUSB_DT_HUB      = $29

; Descriptor sizes per descriptor type
#LIBUSB_DT_DEVICE_SIZE         =  18
#LIBUSB_DT_CONFIG_SIZE         =   9
#LIBUSB_DT_INTERFACE_SIZE      =   9
#LIBUSB_DT_ENDPOINT_SIZE       =   7
#LIBUSB_DT_ENDPOINT_AUDIO_SIZE =   9  ; Audio extension
#LIBUSB_DT_HUB_NONVAR_SIZE     =   7


; All standard descriptors have these 2 fields in common
Structure usb_descriptor_header
  bLength.c
  bDescriptorType.c
EndStructure

; String descriptor
Structure usb_string_descriptor
  bLength.c
  bDescriptorType.c
  wData.u[1]
EndStructure

; HID descriptor
Structure usb_hid_descriptor
  bLength.c
  bDescriptorType.c
  bcdHID.u
  bCountryCode.c
  bNumDescriptors.c
EndStructure

; Endpoint descriptor
#LIBUSB_MAXENDPOINTS  = 32
Structure usb_endpoint_descriptor
  bLength.c
  bDescriptorType.c
  bEndpointAddress.c
  bmAttributes.c
  wMaxPacketSize.u
  bInterval.c
  bRefresh.c
  bSynchAddress.c

  ;*extra.c ; Extra descriptors
  extralen.l
EndStructure

#LIBUSB_ENDPOINT_ADDRESS_MASK     = $0f    ; in bEndpointAddress
#LIBUSB_ENDPOINT_DIR_MASK         = $80

#LIBUSB_ENDPOINT_TYPE_MASK        = $03    ; in bmAttributes
#LIBUSB_ENDPOINT_TYPE_CONTROL     =   0
#LIBUSB_ENDPOINT_TYPE_ISOCHRONOUS =   1
#LIBUSB_ENDPOINT_TYPE_BULK        =   2
#LIBUSB_ENDPOINT_TYPE_INTERRUPT   =   3

; Interface descriptor
#LIBUSB_MAXINTERFACES = 32
Structure usb_interface_descriptor
  bLength.c
  bDescriptorType.c
  bInterfaceNumber.c
  bAlternateSetting.c
  bNumEndpoints.c
  bInterfaceClass.c
  bInterfaceSubClass.c
  bInterfaceProtocol.c
  iInterface.c

  *endpoint.usb_endpoint_descriptor

  ;*extra.c ; Extra descriptors
  extralen.l
EndStructure

#LIBUSB_MAXALTSETTING = 128  ; Hard limit

Structure usb_interface
  *altsetting.usb_interface_descriptor

  num_altsetting.l
EndStructure

; Configuration descriptor information..
#LIBUSB_MAXCONFIG = 8
Structure usb_config_descriptor
  bLength.c
  bDescriptorType.c
  wTotalLength.u
  bNumInterfaces.c
  bConfigurationValue.c
  iConfiguration.c
  bmAttributes.c
  MaxPower.c

  *Interface.usb_interface

 ; *extra.c  ; Extra descriptors
  extralen.l
EndStructure

; Device descriptor
Structure usb_device_descriptor
  bLength.c
  bDescriptorType.c
  bcdUSB.u
  bDeviceClass.c
  bDeviceSubClass.c
  bDeviceProtocol.c
  bMaxPacketSize0.c
  idVendor.u
  idProduct.u
  bcdDevice.u
  iManufacturer.c
  iProduct.c
  iSerialNumber.c
  bNumConfigurations.c
EndStructure

Structure usb_ctrl_setup
  bRequestType.c
  bRequest.c
  wValue.u
  wIndex.u
  wLength.u
EndStructure

; Standard requests

#LIBUSB_REQ_GET_STATUS         = $00
#LIBUSB_REQ_CLEAR_FEATURE      = $01
; $02 is reserved
#LIBUSB_REQ_SET_FEATURE        = $03
; $04 is reserved
#LIBUSB_REQ_SET_ADDRESS        = $05
#LIBUSB_REQ_GET_DESCRIPTOR     = $06
#LIBUSB_REQ_SET_DESCRIPTOR     = $07
#LIBUSB_REQ_GET_CONFIGURATION  = $08
#LIBUSB_REQ_SET_CONFIGURATION  = $09
#LIBUSB_REQ_GET_INTERFACE      = $0A
#LIBUSB_REQ_SET_INTERFACE      = $0B
#LIBUSB_REQ_SYNCH_FRAME        = $0C

#LIBUSB_TYPE_STANDARD          = ($00 << 5)
#LIBUSB_TYPE_CLASS             = ($01 << 5)
#LIBUSB_TYPE_VENDOR            = ($02 << 5)
#LIBUSB_TYPE_RESERVED          = ($03 << 5)

#LIBUSB_RECIP_DEVICE           = $00
#LIBUSB_RECIP_INTERFACE        = $01
#LIBUSB_RECIP_ENDPOINT         = $02
#LIBUSB_RECIP_OTHER            = $03

; Various libusb API related stuff

#LIBUSB_ENDPOINT_IN    = $80
#LIBUSB_ENDPOINT_OUT   = $00

; Error codes
#LIBUSB_ERROR_BEGIN    = 500000

; This is supposed To look weird. This file is generated from autoconf
; And I didn't want to make this too complicated.

; #LIBUSB_LE16_TO_CPU(x)

; Device reset types For usb_reset_ex.
; http://msdn.microsoft.com/en-us/library/ff537269%28VS.85%29.aspx
; http://msdn.microsoft.com/en-us/library/ff537243%28v=vs.85%29.aspx

#LIBUSB_RESET_TYPE_RESET_PORT = (1 << 0)
#LIBUSB_RESET_TYPE_CYCLE_PORT = (1 << 1)
#LIBUSB_RESET_TYPE_FULL_RESET = (#LIBUSB_RESET_TYPE_CYCLE_PORT | #LIBUSB_RESET_TYPE_RESET_PORT)


; Data types
; struct usb_device
; struct usb_bus

Structure usb_device
  *next.usb_device
  *prev.usb_device

  filename.c[#LIBUSB_PATH_MAX]

  *bus.usb_bus

  descriptor.usb_device_descriptor
  *config.usb_config_descriptor

  ;*dev.l  ; Darwin support

  devnum.c

  num_children.c
  *children.usb_device
EndStructure

Structure usb_bus
  *next.usb_bus
  *prev.usb_bus

  dirname.c[#LIBUSB_PATH_MAX]

  *devices.usb_device
  location.l

  *root_dev.usb_device
EndStructure

; Version information, Windows specific
Structure dll
  major.l
  minor.l
  micro.l
  nano.l
EndStructure

Structure driver
  major.l
  minor.l
  micro.l
  nano.l
EndStructure
 
Structure usb_version
  dll.dll
  driver.driver
EndStructure

Structure usb_dev_handle
  fd.l

  *bus.usb_bus
  *device.usb_device

  config.l
  hinterface.l
  altsetting.l

  ; Added by RMT so implementations can store other per-open-device Data
  ;*impl_info.l
EndStructure
Original Code: http://purebasic.mybb.ru/viewtopic.php?id=389
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
Post Reply