Il dispositivo USB HID genera solo 1 evento


10

Ho un controller remoto multiplo USB eDIO (un ricevitore a infrarossi) fornito con ASUS PSR 2000 Web Surfing Remote Control.

Sto cercando di connettere il Remote COntroller al mio pi in modo che riceva i tasti inviati dal telecomando.

Il controller viene rilevato come dispositivo HID. Ecco i dettagli dal comando 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

Posso anche visualizzare il dispositivo di destinazione nella cartella dev con un evento creato

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

Il gestore eventi ad esso associato è il seguente come visto dal seguente comando.

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

Il problema è quando sto cercando di leggere l'output dal gestore eventi creato per il dispositivo. La prima sequenza di tasti viene registrata ma i tasti successivi non vengono visualizzati dal comando CAT.

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

Per favore, suggeriscimi cosa posso fare per far funzionare il dispositivo. Premendo un tasto qualsiasi dopo la prima battuta non viene restituito nulla a meno che il dispositivo non sia ricollegato.

Si prega di suggerire cosa è necessario fare per risolvere il problema.


Qualcuno di tutto ??? Non ho idea di cosa stia succedendo con il dispositivo. Forse un moderatore può aiutarmi a inquadrare meglio la domanda se questo è un problema qui?
SteveIrwin,

La domanda è buona Tuttavia, è abbastanza localizzato, quindi sono sicuro che non molte persone avrebbero avuto lo stesso problema. Potrebbe calmarti sapere che ho visto qualcosa di molto simile usato dalla barca parlante di Chris Wallace in modo da poter dare un'occhiata a quello. La prima cosa che vorrei chiedere per diagnosticare il problema è; stai usando un hub autoalimentato, perché potrebbe essere un problema di alimentazione.
Jivings

Ci hai provato senza |xxd? Buffer l'output. Ho usato irwdal pacchetto lircper ottenere i codici chiave inviati dal mio telecomando.
macrojames

driver personalizzato significherebbe una patch del kernel Linux. L'opzione più semplice è usare libusb poiché libusb dà accesso diretto agli endpoint USB.
Lars Pötter,

Risposte:


5

Il problema sembra essere il descrittore USB incompleto:

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

Il descrittore che potrebbe essere letto dice che questo è un mouse.

  bInterfaceProtocol      2 Mouse

E che ci sarebbe un descrittore di 20 byte che descriva il formato dei dati:

  bDescriptorType        34 Report
  wDescriptorLength      20

Ma quello manca.

C'è uno strano problema con la tua specifica combinazione di hardware e software o il programmatore era pigro e non implementava il descrittore di report, poiché il suo driver probabilmente non ne aveva bisogno. Ma molto probabilmente ciò ha confuso il Driver che crea il dispositivo di input.

Puoi provare a usare libusb per leggere i 4 byte dall'endpoint. Forse il polling funziona. Oppure dai un'occhiata alla comunicazione USB quando usi il dispositivo con il driver originale. E sì, questo è molto complicato se non ti capita di avere uno dei costosi logger USB in circolazione. Ma il kernel Linux ha il supporto per la registrazione USB del software e sono disponibili alcuni logger software per Windows.


4

Finalmente ho avuto il tempo di scrivere la mia implementazione usando la libreria PyUSB che è un wrapper per Libusb.

Sto pubblicando il codice qui. Potrebbe aiutare qualcuno.

Ho un altro pezzo di codice che crea il file di configurazione che viene utilizzato qui. Non ho mappato tutte le chiavi remote poiché non ho bisogno di tutte.

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()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.