rene-aguirre / pywinusb

USB / HID windows helper library
BSD 3-Clause "New" or "Revised" License
207 stars 63 forks source link

Question about get input and send output from my custom USB device. #66

Open zhji2822 opened 4 years ago

zhji2822 commented 4 years ago

Here are my codes:

import pywinusb.hid as hid
from ctypes import *

class hidHelper(object):
    def __init__(self, vid=0x0483, pid=0xa005):
        self.alive = False
        self.device = None
        self.report = None
        self.vid = vid
        self.pid = pid

    def start(self):
        _filter = hid.HidDeviceFilter(vendor_id = self.vid, product_id = self.pid)
        hid_device = _filter.get_devices()
        if len(hid_device) > 0:
            self.device = hid_device[0]
            self.device.open()
            self.out_report = self.device.find_output_reports()
            self.in_report = self.device.find_input_reports()
            self.alive = True
    def stop(self):
        self.alive = False
        if self.device:
            self.device.close()
if __name__ == '__main__':
    myhid = hidHelper()
    myhid.start()
    input_interrupt_transfers = False
    if myhid.alive:
        send_list = [0xFF]*1101
        send_list[0] = 0xfd
        myhid.out_report[0].send(send_list)
        myhid.in_report[0].get()
        import time
        time.sleep(0.5)
        myhid.stop()

I used bus hound to monitor the communication. I get output that PC sent to the device with full 0xFF and 0xFD in the first place twice, and I only expect once. Then there are response from my USB device but my code can not get that, is there any thing wrong with my code? @rene-aguirre @j3hyde @c1728p9 @ElectricRCAircraftGuy Thank you for your time!

rene-aguirre commented 4 years ago

Seems this quite excessive:

send_list = [0xFF]*1101

That'd cause to create a list of more than 1kB for your output report.

For the input report check the examples. Input reports are asynchronous, only feature reports can be polled.

You need to prepare a handler (callback) to receive the input reports.

On Mon, Aug 24, 2020 at 11:36 PM zhji2822 notifications@github.com wrote:

Here are my codes:

import pywinusb.hid as hid from ctypes import *

class hidHelper(object): def init(self, vid=0x0483, pid=0xa005): self.alive = False self.device = None self.report = None self.vid = vid self.pid = pid

def start(self):
    _filter = hid.HidDeviceFilter(vendor_id = self.vid, product_id = self.pid)
    hid_device = _filter.get_devices()
    if len(hid_device) > 0:
        self.device = hid_device[0]
        self.device.open()
        self.out_report = self.device.find_output_reports()
        self.in_report = self.device.find_input_reports()
        self.alive = True
def stop(self):
    self.alive = False
    if self.device:
        self.device.close()

if name == 'main': myhid = hidHelper() myhid.start() input_interrupt_transfers = False if myhid.alive: send_list = [0xFF]*1101 send_list[0] = 0xfd myhid.out_report[0].send(send_list) myhid.in_report[0].get() import time time.sleep(0.5) myhid.stop()

I used bus hound to monitor the communication. I get output that PC sent to the device with full 0xFF and 0xFD in the first place twice, and I only expect once. Then there are response from my USB device but my code can not get that, is there any thing wrong with my code? @rene-aguirre https://github.com/rene-aguirre Thank you for your time!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/rene-aguirre/pywinusb/issues/66, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAF3G7VDJVSDM2BT4IMCBJDSCNLYVANCNFSM4QKJEIVA .

zhji2822 commented 4 years ago

Thank you for your help! I am afraid that I cannot change size of the input and output report size since it is fixed for the device I am communicating with. And for the handler part, do you mean use function that is written in core.py to define a handler for input report? it is copied below:

 def add_event_handler(self, full_usage_id, handler_function,
            event_kind = HID_EVT_ALL, aux_data = None):
        """Add event handler for usage value/button changes,
        returns True if the handler function was updated"""
        report_id = self.find_input_usage(full_usage_id)
        if report_id != None:
            # allow first zero to trigger changes and releases events
            self.__input_report_templates[report_id][full_usage_id].__value = None
        if report_id == None or not handler_function:
            # do not add handler
            return False
        assert(isinstance(handler_function, collections.Callable)) # must be a function
        # get dictionary for full usages
        top_map_handler = self.__evt_handlers.get(full_usage_id, dict())
        event_handler_set = top_map_handler.get(event_kind, dict())
        # update handler
        event_handler_set[handler_function] = aux_data
        if event_kind not in top_map_handler:
            top_map_handler[event_kind] = event_handler_set
        if full_usage_id not in self.__evt_handlers:
            self.__evt_handlers[full_usage_id] = top_map_handler
        return True
zhji2822 commented 4 years ago

It works! But I got duplicated output and input during the communication. I used bus hound for monitoring and it is shown in the image. Is this because of some default setting? that I need to change? I also uploaded my edited code below.

Capture

import pywinusb.hid as hid
import time

class hidHelper(object):
    def __init__(self, vid=0x0483, pid=0xa005):
        self.alive = False
        self.device = None
        self.report = None
        self.vid = vid
        self.pid = pid

    def setcallback(self):
        '''
        设置接收数据回调函数
        '''
        if self.device:
            self.device.set_raw_data_handler(self.read)

    def read(self, data):
        '''
        接收数据回调函数
       '''

        print([hex(item).upper() for item in data[1:]])

    def start(self):
        '''
        开始,打开HID设备
        '''
        _filter = hid.HidDeviceFilter(vendor_id = self.vid, product_id = self.pid)
        hid_device = _filter.get_devices()
        if len(hid_device) > 0:
            self.device = hid_device[0]
            self.device.open()
            self.setcallback()
            self.out_report = self.device.find_output_reports()
            self.in_report = self.device.find_input_reports()
            self.alive = True

    def stop(self):
        '''
        停止,关闭HID设备
        '''
        self.alive = False
        if self.device:
            self.device.close()

if __name__ == '__main__':
    myhid = hidHelper()
    myhid.start()
    input_interrupt_transfers = False
    if myhid.alive:
        send_list = [0xFF]*1101
        send_list[0] = 0xfd
        myhid.out_report[0].send(send_list)
        myhid.in_report[0].get()
        time.sleep(0.5)
        myhid.stop()
rene-aguirre commented 4 years ago

The monitor shows you report is only 100 byte long, this shows there is something wrong with your descriptor.

Usually the report size limit is the endpoint transfer size limit.

Remove the .get() is not required.

On Wed, Aug 26, 2020 at 6:28 PM zhji2822 notifications@github.com wrote:

It works! But I got duplicated output and input during the communication. I used bus hound for monitoring and it is shown in the image. Is this because of some default setting? that I need to change? I also uploaded my edited code below.

[image: Capture] https://user-images.githubusercontent.com/28940774/91372846-5edbb300-e847-11ea-8945-9bb26ffc6fa2.PNG

import pywinusb.hid as hid

import time

class hidHelper(object):

def __init__(self, vid=0x0483, pid=0xa005):

    self.alive = False

    self.device = None

    self.report = None

    self.vid = vid

    self.pid = pid

def setcallback(self):

    '''

    设置接收数据回调函数

    '''

    if self.device:

        self.device.set_raw_data_handler(self.read)

def read(self, data):

    '''

    接收数据回调函数

   '''

    print([hex(item).upper() for item in data[1:]])

def start(self):

    '''

    开始,打开HID设备

    '''

    _filter = hid.HidDeviceFilter(vendor_id = self.vid, product_id = self.pid)

    hid_device = _filter.get_devices()

    if len(hid_device) > 0:

        self.device = hid_device[0]

        self.device.open()

        self.setcallback()

        self.out_report = self.device.find_output_reports()

        self.in_report = self.device.find_input_reports()

        self.alive = True

def stop(self):

    '''

    停止,关闭HID设备

    '''

    self.alive = False

    if self.device:

        self.device.close()

if name == 'main':

myhid = hidHelper()

myhid.start()

input_interrupt_transfers = False

if myhid.alive:

    send_list = [0xFF]*1101

    send_list[0] = 0xfd

    myhid.out_report[0].send(send_list)

    myhid.in_report[0].get()

    time.sleep(0.5)

    myhid.stop()

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/rene-aguirre/pywinusb/issues/66#issuecomment-681237144, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAF3G7STTDJVGR3PFVR6E6DSCWZE3ANCNFSM4QKJEIVA .

zhji2822 commented 4 years ago

Thank you. I am confused about where did you get that my report is 100 byte long. if you got that by looking at the length of input/output data, you were mislead by my mistake. Sorry, to make fewer screening shots I limited the number of bytes bus hound show. and here are the complete screen shots. The actual data is 1101 bytes long but we can find it sent out same output data twice to the USB device. and I only have one send order. 1 2 3 4 5 6 7 8 9