Urządzenie USB HID odpala tylko 1 zdarzenie


11

Mam wielofunkcyjny kontroler USB eDIO (odbiornik podczerwieni), który został dostarczony z pilotem do surfingu w sieci ASUS PSR 2000.

Próbuję podłączyć Zdalny kontroler do mojego pi, aby odbierał naciśnięcia klawiszy wysyłane przez pilota.

Kontroler jest wykrywany jako urządzenie HID. Oto szczegóły komendy 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

Mogę również wyświetlić urządzenie docelowe w folderze deweloperskim z utworzonym zdarzeniem

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

Powiązana z nim procedura obsługi zdarzeń wygląda następująco:

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

Problem polega na tym, że próbuję odczytać dane wyjściowe z procedury obsługi zdarzeń utworzonej dla urządzenia. Pierwsze naciśnięcie klawisza jest zarejestrowane, ale kolejne naciśnięcia klawiszy nie są wyświetlane przez polecenie CAT.

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

Proszę zasugerować mi, co mogę zrobić, aby urządzenie działało. Naciśnięcie dowolnego klawisza po pierwszym naciśnięciu klawisza nie zwróci niczego, chyba że urządzenie zostanie ponownie podłączone.

Proszę zasugerować, co należy zrobić, aby rozwiązać problem.


Ktoś coś ??? Nie mam pojęcia, co się dzieje z urządzeniem. Być może moderator może pomóc mi lepiej sformułować pytanie, jeśli jest to problem?
SteveIrwin,

Pytanie jest dobre. Jest jednak dość zlokalizowana, więc jestem pewien, że niewiele osób miałoby ten sam problem. Może cię uspokoić fakt, że widziałem coś bardzo podobnego używanego przez gadającą łódź Chrisa Wallace'a, abyś mógł na to rzucić okiem. Pierwszą rzeczą, o którą chciałbym zapytać w celu zdiagnozowania problemu, jest; czy używasz koncentratora z własnym zasilaniem, ponieważ może to być problem z zasilaniem.
Jivings

Próbowałeś bez |xxd? Buforuje dane wyjściowe. Użyłem irwz paczki, lircaby uzyskać kody dostępu wysłane przez mojego pilota.
makrojames,

niestandardowy sterownik oznaczałby łatkę na jądro Linuksa. Łatwiejszą opcją jest użycie libusb, ponieważ libusb daje bezpośredni dostęp do punktów końcowych USB.
Lars Pötter,

Odpowiedzi:


5

Problemem wydają się niekompletne opisy USB:

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

Deskryptor, który można odczytać, mówi, że to Mysz.

  bInterfaceProtocol      2 Mouse

I że będzie deskryptor 20 bajtów, który opisuje format danych:

  bDescriptorType        34 Report
  wDescriptorLength      20

Ale tego brakuje.

Występuje albo dziwny problem z konkretną kombinacją sprzętu i oprogramowania, albo programista był leniwy i nie wdrożył deskryptora raportu, ponieważ ich własny sterownik prawdopodobnie go nie potrzebuje. Ale najprawdopodobniej wprowadzono w błąd sterownik, który tworzy urządzenie wejściowe.

Możesz spróbować użyć libusb do odczytania 4 bajtów z punktu końcowego. Być może odpytywanie działa. Lub spójrz na komunikację USB, gdy używasz urządzenia z oryginalnym sterownikiem. I tak, jest to bardzo trudne, jeśli nie masz przy sobie jednego z drogich rejestratorów USB. Ale jądro Linuksa obsługuje programowe rejestrowanie USB i dostępne są niektóre rejestratory oprogramowania dla systemu Windows.


4

Wreszcie miałem czas na napisanie własnej implementacji przy użyciu biblioteki PyUSB, która jest opakowaniem dla Libusb.

Publikuję kod tutaj, może komuś pomóc.

Mam inny fragment kodu, który tworzy plik konfiguracyjny, który jest tutaj używany. Nie zmapowałem wszystkich kluczy zdalnych, ponieważ nie potrzebuję ich wszystkich.

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()
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.