USB HID设备仅触发1个事件


11

我有一个ASUS PSR 2000 Web冲浪遥控器随附的eDIO USB多功能遥控器(一个红外接收器)。

我正在尝试将Remote COntroller连接到我的pi,以便它接收到由远程发送的击键。

控制器被检测为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 2012年

这个问题很好。但是,它是相当本地化的,因此我确定不会有太多人遇到相同的问题。知道我看到克里斯·华莱士的说话船使用的东西非常相似,可能会让您感到平静,因此您可以看一下。为了诊断问题,我首先要问的是:您是否正在使用自供电的集线器,因为这可能是电源问题。
吉文斯,2012年

您尝试过没有|xxd吗?它缓冲输出。我irw从包lirc中获取了我的遥控器发送的键码。
macrojames,2012年

自定义驱动程序将意味着一个Linux内核补丁。比较容易的选择是使用libusb,因为libusb可以直接访问USB端点。
拉尔斯·珀特(LarsPötter)2012年

Answers:


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 Logger之一,这将非常棘手。但是Linux内核支持软件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()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.