[chbot] Help with Python/HID

Mark Atherton markaren1 at xtra.co.nz
Tue Dec 24 06:06:07 GMT 2024


Hi all,

Help requested from Python newbie

I am working on a simple code fragment to drive a UART over HID using 
the FT260 in Python, but am having issues with writing data.

Code snip below has had it's layout messed with, but is normally 
indented OK.

send_feature_report and get_feature_report appear to configure the FT260 
using Report IDs which are off type 'Feature'

I don't appear to be able to send data using Report ID of type 'Output' 
with handle.write, it returns returns -1 which is a failure.

The payload is configured
	0xF0 (send 1..4 bytes)
	0x01 (payload length 1 byte)
	0x55 (payload data)

See AN_394_User_Guide_for_FT260.pdf

help(hid) is also included below.

Any help appreciated.

-Mark


--------

import hid
#import struct

FT260_VID = 0x0403  # Default Vendor ID for FTDI
FT260_PID = 0x6030  # Default Product ID for FT260

for device in hid.enumerate():
   if device['vendor_id'] == FT260_VID and device['product_id'] == 
FT260_PID:
     print(f"FT260 device found: {device['product_string']}")

print("Opening FT260 device...")
handle = hid.device()
handle.open(FT260_VID, FT260_PID)

bytes_written = handle.send_feature_report([0xA1,0x40]) 
        # Reset UART

bytes_read = handle.get_feature_report(report_num = 0xA1, max_length = 64)
print(["%02x" % (each) for each in bytes_read]);

handle.set_nonblocking(True);

bytes_written = 
handle.send_feature_report([0xA1,0x41,0x04,0x80,0x25,0x00,0x00,0x08,0x00,0x00,0x00])
print("wrote config ", bytes_written);

bytes_written = handle.write([0xF0, 0x01, 0x55])
print("wrote data ", bytes_written);

handle.close()
print("FT260 device closed.")

----

 >>> help(hid)
Help on module hid:

NAME
     hid

CLASSES
     builtins.object
         device

     class device(builtins.object)
      |  Device class.
      |
      |  A device instance can be used to read from and write to a HID 
device.
      |
      |  Methods defined here:
      |
      |  __reduce__ = __reduce_cython__(...)
      |
      |  __setstate__ = __setstate_cython__(...)
      |
      |  close(self)
      |      Close connection.
      |
      |      This should always be called after opening a connection.
      |
      |  error(self)
      |      Get error from device, or global error if no device is opened.
      |
      |      :return:
      |      :rtype: str
      |      :raises IOError:
      |
      |  get_feature_report(self, report_num, max_length)
      |      Receive feature report.
      |
      |      :param report_num:
      |      :type report_num: int
      |      :param max_length:
      |      :type max_length: int
      |      :return: Incoming feature report
      |      :rtype: List[int]
      |      :raises ValueError: If connection is not opened.
      |      :raises IOError:
      |
      |  get_indexed_string(self, index)
      |      Return indexed string.
      |
      |      :return:
      |      :rtype: str
      |      :raises ValueError: If connection is not opened.
      |      :raises IOError:
      |
      |  get_input_report(self, report_num, max_length)
      |      Get input report
      |
      |      :param report_num:
      |      :type report_num: int
      |      :param max_length:
      |      :type max_length: int
      |      :return:
      |      :rtype: List[int]
      |      :raises ValueError: If connection is not opened.
      |      :raises IOError:
      |
      |  get_manufacturer_string(self)
      |      Return manufacturer string (e.g. vendor name).
      |
      |      :return:
      |      :rtype: str
      |      :raises ValueError: If connection is not opened.
      |      :raises IOError:
      |
      |  get_product_string(self)
      |      Return product string (e.g. device description).
      |
      |      :return:
      |      :rtype: str
      |      :raises ValueError: If connection is not opened.
      |      :raises IOError:
      |
      |  get_report_descriptor(self, max_length=4096)
      |      Return the report descriptor up to max_length bytes.
      |      If max_length is bigger than the actual descriptor, the 
full descriptor will be returned.
      |
      |      :param max_length: Maximum number of bytes to read, must be 
positive
      |      :type max_length: int
      |
      |      :return:
      |      :rtype: List[int]
      |      :raises ValueError: If connection is not opened.
      |      :raises IOError: If read error
      |
      |  get_serial_number_string(self)
      |      Return serial number.
      |
      |      :return:
      |      :rtype: str
      |      :raises ValueError: If connection is not opened.
      |      :raises IOError:
      |
      |  open(self, vendor_id=0, product_id=0, serial_number=None)
      |      Open the connection.
      |
      |      :param vendor_id: Vendor id to connect to, default = 0
      |      :type vendor_id: int, optional
      |      :param product_id: Product id to connect to, default = 0
      |      :type product_id: int, optional
      |      :param serial_number:
      |      :type serial_number: unicode, optional
      |      :raises IOError:
      |
      |  open_path(self, path)
      |      Open connection by path.
      |
      |      :param path: Path to device
      |      :type path: bytes
      |      :raises IOError:
      |
      |  read(self, max_length, timeout_ms=0)
      |      Return a list of integers (0-255) from the device up to 
max_length bytes.
      |
      |      :param max_length: Maximum number of bytes to read
      |      :type max_length: int
      |      :param timeout_ms: Number of milliseconds until timeout 
(default: no timeout)
      |      :type timeout_ms: int, optional
      |      :return: Read bytes
      |      :rtype: List[int]
      |
      |  send_feature_report(self, buff)
      |      Accept a list of integers (0-255) and send them to the device.
      |
      |      :param buff: Data to send (must be convertible into bytes)
      |      :type buff: any
      |      :return: Send result
      |      :rtype: int
      |
      |  set_nonblocking(self, v)
      |      Set the nonblocking flag.
      |
      |      :param v: Flag value (1 or 0, True or False)
      |      :type v: int, bool
      |      :return: Flag result
      |      :rtype: int
      |
      |  write(self, buff)
      |      Accept a list of integers (0-255) and send them to the device.
      |
      |      :param buff: Data to write (must be convertible to `bytes`)
      |      :type buff: Any
      |      :return: Write result
      |      :rtype: int
      |
      | 
----------------------------------------------------------------------
      |  Static methods defined here:
      |
      |  __new__(*args, **kwargs) from builtins.type
      |      Create and return a new object.  See help(type) for 
accurate signature.

FUNCTIONS
     __reduce_cython__(self)

     __setstate_cython__(self, __pyx_state)

     enumerate(vendor_id=0, product_id=0)
         Return a list of discovered HID devices.

         The fields of dict are:

          - 'path'
          - 'vendor_id'
          - 'product_id'
          - 'serial_number'
          - 'release_number'
          - 'manufacturer_string'
          - 'product_string'
          - 'usage_page'
          - 'usage'
          - 'interface_number'

         :param vendor_id: Vendor id to look for, default = 0
         :type vendor_id: int, optional
         :param product_id: Product id to look for, default = 0
         :type product_id: int, optional
         :return: List of device dictionaries
         :rtype: List[Dict]

     version_str()
         Return a runtime version string of the hidapi C library.

         :return: version string of library
         :rtype: str

DATA
     __test__ = {}

VERSION
     0.14.0.post4

FILE
 
c:\users\user\appdata\local\programs\python\python37\lib\site-packages\hid.cp37-win_amd64.pyd



More information about the Chchrobotics mailing list