mceusb: No keypresses on Formosa Infrared Receiver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello there,

while using the Formos Infrared Receiver (147a:e016), I've noticed, that
it won't stop blinking and doesn't register any presses.
This issue appears to have been present since 2019,
according to a thread on a German VDR forum.
And appears to be a regression, as according to that thread it used to
work with their software
(yavdr-0.6.2, which appears to based on kernel 3.13.0).

I've tried this on 5.16-rc2 (mainline on an X86 machine) and with
6.6.62+rpt-rpi-v8 from the latest Raspberry Pi OS.

I've analyzed a PCAP dump from a Windows 7 machine to see where the
initialization differs and noticed,
that an undocumented byte 0xF4 is being sent, after DEVICE_RESUME and
G_REVISION (which are both sent in one packet).

By unbinding the driver, manually sending 0xF4 to the device and
rebinding the driver, I'm able to workaround this issue.
The blinking is gone and keypresses are now received. (Except for the OK
key).

No further testing has been done.

I'm willing to provide PCAP traces, if of interest.

I've attached the userspace C program for the workaround (which requires
libusb-1.0 to build).

Greetings,
Patrick
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/usbdevice_fs.h>
#include <libusb-1.0/libusb.h>

int main(int argc, char *argv[])
{
  (void)argc;
  (void)argv;

  int result;
  libusb_device_handle *hDevice = NULL;

  uint8_t data[64] = {0};
  int bytesRead = 0;

  result = libusb_init(NULL);
  if (result < 0)
  {
    printf("libusb initialization failed:\n");
  }
  libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
  hDevice = libusb_open_device_with_vid_pid(NULL, 0x147a, 0xe016);
  result = hDevice ? 0 : -EIO;

  if (result < 0)
  {
    printf("failed to open device:\n error: %s \n", strerror(errno)); // file
    return 1;
  }

  // Unregister kernel driver
  result = libusb_kernel_driver_active(hDevice, 0);
  if (result == 1)
  {
    result = libusb_detach_kernel_driver(hDevice, 0);
    if (result < 0)
    {
      printf("failed to detach kernel driver: %s, errno: %s\n", libusb_error_name(result), strerror(errno));
    }
  }

  int err = libusb_claim_interface(hDevice, 0);

  if (err)
  {
    printf("Error: %s, errno: %s\n", libusb_error_name(err), strerror(errno));
    return 1;
  }

  data[0] = 0xf4;
  result = libusb_bulk_transfer(hDevice, LIBUSB_ENDPOINT_OUT | 0x01, data, 1, &bytesRead, 0);

  sleep(1);

  result = libusb_release_interface(hDevice, 0);
  if (result < 0)
  {
    printf("failed to release interface: %s, errno: %s\n", libusb_error_name(result), strerror(errno));
  }

  // reattach kernel driver
  result = libusb_attach_kernel_driver(hDevice, 0);
  if (result < 0)
  {
    printf("failed to attach kernel driver: %s, errno: %s\n", libusb_error_name(result), strerror(errno));
  }


  libusb_close(hDevice);
  libusb_exit(NULL);
  printf("Workaround applied successfully\n");
}

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux