iMX6ULL driver development | Let imx6ull development board support usb interface FC game controller

There is an idle linux development board iMX6ULL that has been eating ashes, and I don't use it to do something, I always feel sorry for it. Let's play it in spare time, it's better than brushing a certain sound. Buy a game controller with a usb interface from Duoduo, let the development board support it, and then you can continue to play childhood classic games on it.

 I am using the I.MX6U-ALPHA development board of punctual atom, and the board resources are very rich. Plan to engage in a series of fun things to do on it. Including linux driver development and application development, you can finally apply what you have learned, learn by playing, and interest is the best teacher.

 Let me show you how the FC gamepad I bought looks like this. It is ordinary, but cheap, and still has a classic taste.

Driver porting process

Determine device type

To make the board support the FC game controller of this USB interface, you must first know what interface protocol the controller uses. Plug it into the win10 computer and look at it. It is a HID type device with USB protocol interface. USB-HID is the abbreviation of Universal Serial Bus-Human Interface Device. From its name, it can be understood that HID devices are devices that directly interact with humans, such as keyboards, mice, and joysticks.

The USB hardware ports are unified, but the USB devices are diverse, and the USB host distinguishes different USB devices according to the descriptors of the USB devices. Each USB device has its own descriptor. When the USB device is inserted, the host will send a command to the slave, and the slave will return specific descriptor information after receiving the command. The host identifies the relevant information of the slave device by parsing the received descriptor. This process is the device enumeration (enumeration) process.

Get USB VID and PID information

After my FC controller is plugged into the computer, the usb-hid device is recognized. You can view its vid and pid information directly in the device manager of the computer. This information is very useful and will be used for later driver transplantation.

已启动设备 HID\VID_0810&PID_0001\6&1eff4ed2&0&0000。

驱动程序名称: input.inf

Find the linux kernel source code and lock related drivers

Under the linux/drivers/hid/ path of the linux kernel source code, there are driver source codes related to HID. Open the hid-core.c file (HID support for Linux), and check whether the source file contains the VID and PID information of the usb device. If not, add VID and PID information to hid_have_special_driver. Some macro definitions in this can be viewed in the file hid-ids.h.

The github address of the torvalds linux source code:

GitHub - torvalds/linux: Linux kernel source tree

/*
 * A list of devices for which there is a specialized driver on HID bus.
 *
 * Please note that for multitouch devices (driven by hid-multitouch driver),
 * there is a proper autodetection and autoloading in place (based on presence
 * of HID_DG_CONTACTID), so those devices don't need to be added to this list,
 * as we are doing the right thing in hid_scan_usage().
 *
 * Autodetection for (USB) HID sensor hubs exists too. If a collection of type
 * physical is found inside a usage page of type sensor, hid-sensor-hub will be
 * used as a driver. See hid_scan_report().
 */
static const struct hid_device_id hid_have_special_driver[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) },
    
//......

}

Find gamepad drivers that approximate hid

Open the kernel configuration options to view through make menuconfig.

 Found a DragonRise Inc, game controller. Although it is not sure that it is a perfect match for my FC controller, at least from the name, this is a hid device for a game controller.

 If there is a default kernel configuration options file, you can also add option switches directly:

CONFIG_HID_DRAGONRISE=y

The driver source file related to this is linux/drivers/hid/hid-dr.c. Open this file and add the VID and PID information of my usb device.

static const struct hid_device_id dr_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006),  },
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011),  },
        { HID_USB_DEVICE(0x0810, 0x0001),  },
        { }
};

Compile the kernel driver

#使用Yocto SDK里的GCC 5.3.0交叉编译器编译出厂Linux源码,可不用指定ARCH等,直接执行Make
source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
#编译前先清除
make distclean
#配置defconfig文件
make imx_v7_defconfig -j 16
#开始编译zImage
make zImage -j 16

After that, update the kernel on the board and reboot the device. Plug in the USB gamepad, enter dmesg to view the kernel log information, and see if the device node is recognized.

dmesg

View input devices, get input event information

/dev/input/ directory

The events in the /dev/input/ directory are all generated by calling input_register_device(struct input_dev *dev) in the driver. The files in my /dev/input/ directory are as follows:

$ ls /dev/input/
by-id  by-path  event0  event1  event2  event3 

Each event represents an event. So how do you know which device each event corresponds to? It can be viewed with the help of /proc/bus .

/proc/bus/input/devices

/proc/bus/input/devices stores the relevant device information corresponding to the event. What I see on my board is as follows:

$ cat /proc/bus/input/devices

It can be seen that the content behind the "H:" line of each item is the corresponding event. 

Read /dev/input/eventx directly

Use cat to view the content of the input event, operate the corresponding input device, and the event will report the content. Interpreting as a string will result in garbled characters. So you can use hexdump to read hexadecimal data.

Test read demo

The linux kernel uses the input_event structure to describe all input events.

/*
 * The event structure itself
 */

struct input_event {
	struct timeval time;
	__u16 type;
	__u16 code;
	__s32 value;
};

In order to verify whether the usb gamepad is working, and to obtain its corresponding key value, write a small demo test to read it.

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h> 


#define _EV_KEY         0x01    /* button pressed/released */
#define _EV_ABS         0x03    
#define _EV_MSC         0x04   

int main() {
    printf("hello,usb hid joystick key test\n");
    int fd = open("/dev/input/event3", O_RDONLY);
    struct input_event e;
    while(1) {
        read(fd, &e, sizeof(e));
        switch(e.type) {
            case _EV_KEY:
                printf("type: %d, code: %d,value: %d, time: %d\n", e.type, e.code,e.value, e.time);
                break;
            case _EV_ABS:
                printf("type: %d, code: %d,value: %d, time: %d\n", e.type, e.code,e.value, e.time);
                break;
            case _EV_MSC:
            printf("type: %d, code: %d,value: %d, time: %d\n", e.type, e.code,e.value, e.time);
            break;
            default:
                if(e.type != 0){
                printf("type:%d, code: %d,value: %d, time: %d\n",e.type, e.code,e.value, e.time);
                }
        }
    }
    close(fd);
    return 0;
}

evtest test tool

When developing input subsystem drivers, the evtest tool is often used for testing. evtest is a tool for printing evdev kernel events. It directly reads and prints events with values ​​and symbol names described by the device from the kernel device. It can be used to debug input devices such as mouse, keyboard, and touchpad. Typically used to debug problems with input devices.

In the output data, "type" is the input type, which can be "EV KEY", "EV SW", "EV SND", "EV LED" or a value; "value" can be decimal or hexadecimal, or Is the constant name of the query kev/switch/sound/LED.

Download and install the evtest tool

Download address: Index of /debian/pool/main/e/evtest/ | Nanyang Institute of Technology Open Source Mirror Station | Nanyang Institute of Technology Open Source Mirror

cross compile installation

#解压缩
$ tar   -xjvf   evtest_1.33.orig.tar.bz2
$ cd evtest-1.33/

#加载环境
source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

#生成makefile,指定交叉编译
.confiqure --host=arm-linux

#编译
make

The evtest tool uses

 Run the example

time: The time when the event was generated.

type: event type, the common ones are: EV_KEY (keyboard), EV_REL (relative coordinates), EV_ABS (absolute coordinates), defined in [input-event-codes.h] (https://github.com/torvalds/linux /blob/master/include/uapi/linux/input-event-codes.h#LC35) or input.h.

code: The code of the event, which further describes the event, such as: the key value ( KEY_NUMLOCK、KEY_ESC、KEY_1、KEY_A) of the keyboard event.

value: The value of the event, a more specific description of the event, such as: button按下/抬起。

The following is the feedback information of each key captured by using the devtest tool (press up, down, left, right, select, start, etc. once each):

The key value on the handle is determined

The FC handle generally contains the following keys. Left, right, up, down, start, select, A, B, X, Y.

     /**
     * FC手柄 bit 键位对应关系 真实手柄中有一个定时器,处理 连A  连B
     * 0  1   2       3       4    5      6     7
     * A  B   Select  Start  Up   Down   Left  Right
     */

If the FC gamepad with the usb interface you bought is from DragonRise Inc. game, it is estimated that you don’t need to test the key value above, and you can use it directly after enabling it. But the one I bought casually needs to be tested and matched before it can be used.

 After the above tests, the corresponding relationship between key and value is finally determined as follows:

gamepad button read key value
left arrow key up type: 3, code:1,value: 0
type: 3, code:1,value: 127
left arrow key down type: 3, code:1,value: 255
type: 3, code:1,value: 127
left arrow key left type: 3, code:0,value: 0
type: 3, code:0,value: 127
left arrow key right type: 3, code:0,value: 255
type: 3, code:0,value: 127
SELECT key type: 1, code:296,value: 1
type: 1, code:296,value: 0
START button type: 1, code:297,value: 1
type: 1, code:297,value: 0
right number key 1 type: 1, code:288,value: 1
type: 1, code:288,value: 0
right number key 2 type: 1, code:289,value: 1
type: 1, code:289,value: 0
right number key 3 type: 1, code:290,value: 1
type: 1, code:290,value: 0
right number key 4 type: 1, code:291,value: 1
type: 1, code:291,value: 0

In the end, I tried the control and there is no problem at all, and it is very smooth! You can play happily, bring a power bank, this is my mobile game console, it supports unlimited fun classic games! The porting of the Nes emulator will be announced one by one later, welcome to pay attention to the collection. 

other resources

USB HID_Soc lighting master's blog-CSDN blog

For V3S not to eat ashes, transplant NES games / Allwinner SOC / WhyCan Forum (Wow cool developer community)

V3S ported nes game simulator (with game collection)_v3s compiled game simulator_qq_46604211's blog-CSDN blog

Detailed method of viewing input devices and obtaining input events under Linux - evtest command - Programmer Sought

Linux driver development study notes nine: detailed explanation of the menuconfig process

Developer Search-Beta-Make Technology Search Easier
and Efficient
 

USB_HID Basics_usbhid_jansert's Blog-CSDN Blog

Play USB HID series: use C language and libusb to develop USB HID under Linux_whstudio123's blog-CSDN Blog

i.MX6ULL driver development | 20 - Linux input subsystem_imx6ull input driver framework_Mculover666's blog-CSDN blog

GitHub - torvalds/linux: Linux kernel source tree

Embedded Linux: V3s porting NES games, sound, gamepad_Quanzhi v3s porting nes_liefyuan's blog-CSDN Blog

Guess you like

Origin blog.csdn.net/qq8864/article/details/132063201