11

I have a eDIO USB Multi Remote Controller( a Infrared Reciever) that came with ASUS PSR 2000 Web Surfing Remote Control.

I am trying to connect the Remote COntroller to my pi so that it recieves the keystrokes sent by the remote.

The controller is detected as a HID device. Here are the details from the lsusb -v command

    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

I can also view the target device in the dev folder with an event created

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

The event handler associated with it is as follows as seen from the following command.

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

The problem is when I am trying to read the output from the event handler created for the device.The first keystroke is registered but the subsequent key strokes are not displayed by the CAT command.

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

Please suggest me what can I do to get the device working. Pressing any keys after the first keystroke doesn't return anything unless the device is replugged.

Please suggest what needs to be done to fix the issue.

4
  • Anyone anything???I am clueless on what's going on with the device. Perhaps a moderator can help me frame the question better if thats a problem here?
    – SteveIrwin
    Nov 3, 2012 at 15:56
  • The question is good. However, it's quite localized, so I'm sure not many people would have had the same problem. It may calm you to know that I have seen something very similar used by Chris Wallace's talking boat so you could have a look at that. The first thing I would ask in order to diagnose the problem is; are you using a self powered hub, because it could be a power issue.
    – Jivings
    Nov 4, 2012 at 18:12
  • Have you tried without |xxd ? It buffers the output. I used irw from package lirc to get the keycodes sent by my remote.
    – macrojames
    Nov 5, 2012 at 8:23
  • custom driver would mean a Linux Kernel Patch. The easier option is to use libusb as libusb gives direct access to the USB Endpoints. Nov 8, 2012 at 16:36

2 Answers 2

5

The Problem seems to be the incomplete USB Descrioptors:

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

The Descriptor that could be read say that this is a Mouse.

  bInterfaceProtocol      2 Mouse

And that there would be a Descriptor of 20 Bytes that describes the data format:

  bDescriptorType        34 Report
  wDescriptorLength      20

But that one is missing.

There is either a strange Problem with your specific combination of Hardware and Software or the Programmer was lazy and did not implement the Report Descriptor, as their own Driver probably does not need it. But most probably that got the Driver that creates the input device confused.

You can try to use libusb to read the 4 bytes from the endpoint. Perhaps polling works. Or take a look at the USB communication when you use the device with the original driver. And yes this is very tricky if you don't happen to have one of the expensive USB Loggers laying around. But the Linux Kernel has support for Software USB Logging and there are some software Loggers for Windows available.

0
4

Finally I got time to write my own implementation using the PyUSB library which is a wrapper for Libusb.

I am posting the code here.Might help someone.

I have another piece of code that creates the configuration file which is used here.Haven't mapped all the remote keys since I don't need all of them.

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()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.