USB HID-Gerät löst nur 1 Ereignis aus

10

Ich habe eine eDIO USB Multi-Fernbedienung (einen Infrarotempfänger), die mit der ASUS PSR 2000 Web Surfing-Fernbedienung geliefert wurde.

Ich versuche, den Remote COntroller mit meinem Pi zu verbinden, damit er die von der Fernbedienung gesendeten Tastenanschläge empfängt.

Der Controller wird als HID-Gerät erkannt. Hier sind die Details aus dem Befehl lsusb -v

    Bus 001 Device 007: ID 147a:e001 Formosa Industrial Computing, Inc.
    Couldn't open device, some information will be missing
    Device Descriptor:
    bLength                18
    bDescriptorType         1
    bcdUSB               1.10
    bDeviceClass            0 (Defined at Interface level)
   bDeviceSubClass         0
   bDeviceProtocol         0
   bMaxPacketSize0         8
   idVendor           0x147a Formosa Industrial Computing, Inc.
   idProduct          0xe001
   bcdDevice            1.22
   iManufacturer           1
   iProduct                2
   iSerial                 0
   bNumConfigurations      1
  Configuration Descriptor:
  bLength                 9
  bDescriptorType         2
wTotalLength           34
bNumInterfaces          1
bConfigurationValue     1
iConfiguration          4
bmAttributes         0xa0
  (Bus Powered)
  Remote Wakeup
MaxPower              300mA
Interface Descriptor:
  bLength                 9
  bDescriptorType         4
  bInterfaceNumber        0
  bAlternateSetting       0
  bNumEndpoints           1
  bInterfaceClass         3 Human Interface Device
  bInterfaceSubClass      1 Boot Interface Subclass
  bInterfaceProtocol      2 Mouse
  iInterface              0
    HID Device Descriptor:
      bLength                 9
      bDescriptorType        33
      bcdHID               1.10
      bCountryCode            0 Not supported
      bNumDescriptors         1
      bDescriptorType        34 Report
      wDescriptorLength      20
     Report Descriptors:
       ** UNAVAILABLE **
  Endpoint Descriptor:
    bLength                 7
    bDescriptorType         5
    bEndpointAddress     0x81  EP 1 IN
    bmAttributes            3
      Transfer Type            Interrupt
      Synch Type               None
      Usage Type               Data
    wMaxPacketSize     0x0004  1x 4 bytes
    bInterval              10

Ich kann das Zielgerät auch im dev-Ordner mit einem erstellten Ereignis anzeigen

    pi@raspberrypi /dev/input/by-id $ dir
    usb-Cypress_Semiconductor_eDio_USB_Multi_Remote_Controlle-event-if00

Der damit verbundene Ereignishandler lautet wie folgt, wie aus dem folgenden Befehl ersichtlich.

pi@raspberrypi /proc/bus/input $ cat devices
I: Bus=0003 Vendor=147a Product=e001 Version=0110
N: Name="Cypress Semiconductor eDio USB Multi Remote Controlle"
P: Phys=usb-bcm2708_usb-1.2/input0
S: Sysfs=/devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2:1.0/input/input2
U: Uniq=
H: Handlers=event0
B: PROP=0
B: EV=1

Das Problem ist, wenn ich versuche, die Ausgabe des für das Gerät erstellten Ereignishandlers zu lesen. Der erste Tastendruck wird registriert, aber die nachfolgenden Tastenanschläge werden vom CAT-Befehl nicht angezeigt.

 pi@raspberrypi /dev/input $ cat event0 | xxd
 0000000: e007 9450 9476 0900 0000 0000 0000 0000  ...P.v..........

Bitte schlagen Sie mir vor, was ich tun kann, um das Gerät zum Laufen zu bringen. Durch Drücken einer beliebigen Taste nach dem ersten Tastendruck wird nichts zurückgegeben, es sei denn, das Gerät ist neu angeschlossen.

Bitte schlagen Sie vor, was getan werden muss, um das Problem zu beheben.

SteveIrwin
quelle
Jemand irgendetwas ??? Ich habe keine Ahnung, was mit dem Gerät los ist. Vielleicht kann mir ein Moderator helfen, die Frage besser zu formulieren, wenn das hier ein Problem ist?
SteveIrwin
Die Frage ist gut. Es ist jedoch ziemlich lokalisiert, so dass ich sicher bin, dass nicht viele Leute das gleiche Problem gehabt hätten. Es mag Sie beruhigen zu wissen, dass ich etwas sehr Ähnliches gesehen habe, das von Chris Wallaces sprechendem Boot benutzt wurde, damit Sie sich das ansehen können. Das erste, was ich fragen würde, um das Problem zu diagnostizieren, ist: Verwenden Sie einen Hub mit eigener Stromversorgung, da dies ein Stromproblem sein kann?
Jivings
Hast du es ohne versucht |xxd? Es puffert die Ausgabe. Ich habe irwaus dem Paket verwendet lirc, um die von meiner Fernbedienung gesendeten Schlüsselcodes zu erhalten.
Makrojames
Benutzerdefinierter Treiber würde einen Linux-Kernel-Patch bedeuten. Die einfachere Option ist die Verwendung von libusb, da libusb direkten Zugriff auf die USB-Endpunkte bietet.
Lars Pötter

Antworten:

5

Das Problem scheinen die unvollständigen USB-Deskriptoren zu sein:

  Couldn't open device, some information will be missing
  Report Descriptors:
  ** UNAVAILABLE **

Der Deskriptor, der gelesen werden könnte, sagt, dass dies eine Maus ist.

  bInterfaceProtocol      2 Mouse

Und dass es einen Deskriptor von 20 Bytes geben würde, der das Datenformat beschreibt:

  bDescriptorType        34 Report
  wDescriptorLength      20

Aber dieser fehlt.

Es gibt entweder ein seltsames Problem mit Ihrer spezifischen Kombination aus Hardware und Software oder der Programmierer war faul und hat den Berichtsdeskriptor nicht implementiert, da sein eigener Treiber ihn wahrscheinlich nicht benötigt. Aber höchstwahrscheinlich hat das den Treiber, der das Eingabegerät erstellt, verwirrt.

Sie können versuchen, mit libusb die 4 Bytes vom Endpunkt zu lesen. Vielleicht funktioniert das Polling. Oder sehen Sie sich die USB-Kommunikation an, wenn Sie das Gerät mit dem Originaltreiber verwenden. Und ja, das ist sehr schwierig, wenn Sie nicht zufällig einen der teuren USB-Logger herumliegen haben. Der Linux-Kernel unterstützt jedoch die Software-USB-Protokollierung, und es sind einige Software-Logger für Windows verfügbar.

Lars Pötter
quelle
4

Endlich hatte ich Zeit, meine eigene Implementierung mit der PyUSB-Bibliothek zu schreiben, die ein Wrapper für Libusb ist.

Ich poste den Code hier. Könnte jemandem helfen.

Ich habe einen weiteren Code, der die hier verwendete Konfigurationsdatei erstellt. Ich habe nicht alle Remote-Schlüssel zugeordnet, da ich nicht alle benötige.

import usb.core
import usb.util
import ConfigParser 
import shlex
import subprocess
import logging

# find our device
diction={
  6402315641282315:'1',
  6402415641282415:'2',
  6402515641282515:'3',
  6402615641282615:'4',
  6402715641282715:'5',
  6402815641282815:'6',
  6402915641282915:'7',
  6403015641283015:'8',
  6403115641283115:'9',
  }



def load_config():
    dict={}
    config = ConfigParser.RawConfigParser()
    config.read('/codes/remote/remote.cfg')

    dict['vendor']=config.getint('Settings','idVendor')

    dict['product']=config.getint('Settings','idProduct')

    dict['interface']=config.getint('Settings', 'interface')

    r=config.options('Key Mappings')

    for item in r:
        if config.get('Key Mappings',item)!='': 
            dict[item]=config.get('Key Mappings',item)
            #print config.get('Key Mappings',item)
    return dict

def pyus():

    try:
        load_log()
        dict=load_config()
        join_int = lambda nums: int(''.join(str(i) for i in nums))
        #print dict

        dev = usb.core.find(idVendor=dict['vendor'], idProduct=dict['product'])
        interface=dict['interface']

        if dev is None:
            raise ValueError('Device not found')

        if dev.is_kernel_driver_active(interface) is True:
                #print "but we need to detach kernel driver"
                dev.detach_kernel_driver(interface)
        #dev.detatch_kernel_driver(interface) 
        # set the active configuration. With no arguments, the first
        # configuration will be the active one
        dev.set_configuration()

        # get an endpoint instance
        cfg = dev.get_active_configuration()
        interface_number = cfg[(0,0)].bInterfaceNumber
        alternate_setting = usb.control.get_interface(dev,interface_number)
        intf = usb.util.find_descriptor(
            cfg, bInterfaceNumber = interface_number,
            bAlternateSetting = alternate_setting
        )

        ep = usb.util.find_descriptor(
            intf,
            # match the first IN endpoint
            custom_match = \
            lambda e: \
                usb.util.endpoint_direction(e.bEndpointAddress) == \
                usb.util.ENDPOINT_IN
        )

        assert ep is not None
        #print 'packet details',ep.bEndpointAddress , ep.wMaxPacketSize

        while 1:
            try:
                data = dev.read(ep.bEndpointAddress, ep.wMaxPacketSize*2,interface,1000)
                data=data.tolist()
                key=join_int(data)
                #print "Key is " , key
                if  key in diction:

                    try:
                        args=shlex.split(dict[diction[key]])
                        #print args
                        p=subprocess.Popen(args, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
                        #print "Pressed key is ",diction[key]
                    except:
                        pass


            except usb.core.USBError as e:
                pass
    except:
        pass

pyus()
SteveIrwin
quelle