Пристрій USB HID запускає лише 1 подію


11

У мене є мультимедійний дистанційний контролер eDIO USB (інфрачервоний приймач), який поставляється з дистанційним управлінням веб-серфінгу ASUS PSR 2000.

Я намагаюся підключити віддалений COntroller до мого пі, щоб він отримував натискання клавіш, надіслані дистанційним.

Контролер виявляється як пристрій HID. Ось деталі з команди 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

Я також можу переглядати цільовий пристрій у папці Dev із створеною подією

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

Обробник подій, пов'язаний з ним, виглядає так, як видно з наступної команди.

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

Проблема полягає в тому, що я намагаюся прочитати вихід з обробника подій, створений для пристрою. Перший натискання клавіші зареєстровано, але наступні обведення клавіш командою CAT не відображаються.

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

Підкажіть, будь ласка, що я можу зробити, щоб пристрій працював. Якщо натиснути будь-яку клавішу після першого натискання клавіші, нічого не повернеться, якщо пристрій не підключено до мережі.

Підкажіть, будь ласка, що потрібно зробити, щоб вирішити проблему.


Хто-небудь щось ??? Я не знаю, що відбувається з пристроєм. Можливо, модератор може допомогти мені вирішити питання краще, якщо в цьому проблема?
SteveIrwin

Питання добре. Однак він досить локалізований, тому я впевнений, що не багато людей мали б ту саму проблему. Це може вас заспокоїти, коли ви знаєте, що я бачив щось дуже подібне, яке використовував розмовний човен Кріса Уолласа, щоб ви могли поглянути на це. Перше, що я б просив, щоб діагностувати проблему, - це; чи використовуєте ви автономний концентратор, тому що це може бути проблемою живлення.
Відхилення

Ви пробували без |xxd? Він буферизує вихід. Я використовував irwз пакета, lircщоб отримати ключові коди, надіслані моїм пультом.
makrojames

нестандартний драйвер означатиме патч ядра Linux. Простіший варіант - використовувати libusb, оскільки libusb надає прямий доступ до кінцевих точок USB.
Lars Pötter

Відповіді:


5

Здається, що проблема полягає у неповному USB Descrioptors:

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

Дескриптор, який можна було прочитати, говорить, що це Миша.

  bInterfaceProtocol      2 Mouse

І щоб був Дескриптор на 20 байт, який описує формат даних:

  bDescriptorType        34 Report
  wDescriptorLength      20

Але цього немає.

Є або дивна проблема з вашим конкретним поєднанням апаратного та програмного забезпечення, або програміст був ледачим і не реалізував Дескриптор звітів, оскільки їх власний драйвер, мабуть, не потребує. Але, швидше за все, це заплутало драйвер, який створює пристрій введення.

Ви можете спробувати скористатися libusb, щоб прочитати 4 байти з кінцевої точки. Можливо, опитування працює. Або погляньте на зв’язок USB, коли ви використовуєте пристрій з оригінальним драйвером. І так, це дуже складно, якщо у вас не трапиться один із дорогих USB-реєстраторів. Але Linux Kernel має підтримку програмного забезпечення USB-реєстрації, і є деякі програмні журнали для Windows.


4

Нарешті я отримав час написати власну реалізацію, використовуючи бібліотеку PyUSB, яка є обгорткою для Libusb.

Я розміщую тут код. Можливо, хтось допоможе.

У мене є ще один фрагмент коду, який створює файл конфігурації, який тут використовується. Не зіставив усі віддалені клавіші, оскільки мені не потрібні всі.

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()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.