Development environment:
Platform: DM8168
Kernel: Linux 2.6.32
rdk:dvrrdk_04.00.00.03
USB port: DM8168 has two USB port to choose, because special reason I choose is USB1, please choose USB port according to actual need
, the following configuration is slightly different.
1 Configuring the Kernel
According to the reference http://processors.wiki.ti.com/index.php/DM81xx_AM38XX_USB_User_Guide#Introduction
Http://processors.wiki.ti.com/index.php/Usbgeneralpage#One_port_as_host_and_other_port_as_Gadget_.28for_DM81XX.29.
Excerpts are as follows:
1) Select Host and gadget support
Menuconfig->device DRVIERS->USB Support
<*> Support for Host-side USB [ ] USB verbose debug messages [*] USB announce new devices *** Miscellaneous USB options *** ...... <*> USB Gadget Support --->
2) Select USB OTG Support (for ti816x)
Menuconfig->device DRVIERS->USB Support
<*> inventra highspeed Dual Role Controller (TI, ADI, ...) Platform Glue Layer * * * < > TUSB6010 & Lt > OMAP2430 and onwards < > am35x <*> ti81xx ti816x USB connector ' s ID pin control (from software setting)---> Force TI8 16X USB0 to (host mode)---> Force ti816x USB1 to (host mode)---> Driver Mode (Both host and Peripheral:usb OTG (on the Go) Device)---> [] Disable DMA PIO) [*] Enable debugging messages
3) Select Gadget device controller and Gadget driver as modules
Menuconfig->device DRVIERS->USB Support
<*> USB Gadget Support--->---USB Gadget support [] Debugging messages (development) (new) [] Debugging Information Files (development) (new) [] Debugging information files in Debugfs (development) (NEW) (2) Maximum VBUS Power usage (2 -500 MA) (NEW) USB peripheral Controller (Inventra HDRC USB Peripheral (TI, ADI, ...)) ---> <M> USB Gadget Drivers <m > Gadget Zero (Development) [] HNP Test Device (N EW) < > Audio Gadget (Experimental) (NEW) <M> Ethernet Gadget (with CDC Ethernet support) [*] RNDIS Support (NEW) [] Ethernet Emulation Model (EEM) Support (new) < > Gadget Filesystem (Experimental) (new) < > Function Filesystem (Experimental) (NEW) <M> file-backed Storage Gadget [*] File-b acked Storage Gadget Testing version
4) Unselect The OTG targeted peripherals list
Menuconfig->device DRVIERS->USB Support
<*> Support for Host-side USB .... [*] USB runtime power management (autosuspend) and wakeup -*- OTG support [ ] Rely on OTG Targeted Peripherals List [ ] Disable external hubs
Complete the above steps to save the exit first.
2 Device Registration
In order to realize the device is recognized, you need to enroll the device. Modify the HID.C path: Dvrrdk_04.00.00.03/ti_tools/linux_lsp/kernel/linux-dvr-rdk/drivers/usb/gadget.
Because the mouse keyboard is a common USB device, the device descriptor is good to get, if you want to customize the HID device, refer to the USB protocol. PDF (easy to find on the web).
Modify the following
#include <linux/usb/g_hid.h>/* hid descriptor for a keyboard */static struct hidg_func_descriptor pcdm8168_ Keyboard_data = {. Subclass = 0,/* No Subclass */. Protocol = 1,/* keyboard */. Report_length = 8,. report_desc_length =,. Report_desc = {0x05, 0x01,/* Usage_page (Generic Desktop) */0x09, 0x06,/* USAGE (Keyboard) */0XA1, 0x01,/* COLLECTION (application) */0x05, 0x07 ,/* Usage_page (Keyboard) */0x19, 0XE0,/* Usage_minimum (Keyboard leftcontrol) */0x29, 0xe7,/* Usage_maximum (Keyboard right GUI) */0x15, 0x00,/* logical_minimum (0) */0x25, 0x01,/* logical_ma Ximum (1) */0x75, 0x01,/* report_size (1) */0x95, 0x08,/* REPORT_COUNT (8) */0x81, 0x02, /* INPUT (data,var,abs) */0x95, 0x01,/* REPORT_COUNT (1) */0x75, 0x08,/* REPORT_SIZE (8) */ 0X81, 0x03,/* INPUT (Cnst,Var,abs) */0x95, 0x05,/* REPORT_COUNT (5) */0x75, 0x01,/* report_size (1) */0x05, 0x08, /* Usage_page (LEDs) */0x19, 0x01,/* Usage_minimum (Num Lock) */0x29, 0x05,/* Usage_maximum (Kana ) */0x91, 0x02,/* OUTPUT (data,var,abs) */0x95, 0x01,/* REPORT_COUNT (1) */0x75, 0x03, /* REPORT_SIZE (3) */0x91, 0x03,/* OUTPUT (cnst,var,abs) */0x95, 0x06,/* REPORT_COUNT (6) */ 0X75, 0x08,/* REPORT_SIZE (8) */0x15, 0x00,/* logical_minimum (0) */0x25, 0X65,/* logical_ma Ximum (101) */0x05, 0x07,/* Usage_page (Keyboard) */0x19, 0x00,/* Usage_minimum (Reserved) */ 0x29, 0X65,/* Usage_maximum (Keyboard application) */0x81, 0x00,/* INPUT (data,ary,abs) */0xc0 /* end_collection */}};/*hid descriptor for a mouse*/static struct hidg_func_descriptor pcdm8168_mouse_data = { . Subclass = 0,/*no subclass*/. Protocol = 2,/*mouse*/. report_length = 4,. report_desc_length =,. report_desc={0x05 , 0x01,/*usage Page (Generic Desktop Controls) */0x09,0x02,/*usage (Mouse) */0xa1,0x01,/*collction (App lication) */0x09,0x01,/*usage (pointer) */0xa1,0x00,/*collction (physical) */0x05,0x09,/*usage Page (Button) */0x19,0x01,/*usage Minimum (1) */0x29,0x03,/*usage Maximum (3) */0x15,0x00,/*log ical Minimum (1) */0x25,0x01,/*logical Maximum (1) */0x95,0x03,/*report Count (5) */0x75,0x01,/* Report Size (1) */0x81,0x02,/*input (data,variable,absolute,bitfiled) */0x95,0x01,/*report Count (1) */ 0x75,0x05,/*report Size (5) */0x81,0x01,/*input (constant,array,absolute,bitfiled) */0x05,0x01,/*us Age Page (Generic Desktop Controls) */0x09,0x30,/*usage (x) */0x09,0x31,/*usage (y) */0x09,0x38,/ *usage (Wheel) */0X15,0X81,/*logical Minimum ( -127) */0x25,0x7f,/*logical Maximum (127) */0x75,0x08,/*report Size (8) */ 0x95,0x02,/*report Count (2) */0x81,0x06,/*input (data,variable,relative,bitfiled) */0xc0,/*end C ollection*/0xc0/*end collection*/}};static struct Platform_device pcdm8168_hid_keyboard = {. Name = "Hi DG ",. id = 0,. num_resources = 0,. Resource = 0,. Dev.platform_data = &pcdm8168_keyboard_dat a,};static struct Platform_device pcdm8168_hid_mouse = {. Name = "HIDG",. id = 1,. num_resources = 0, . Resource = 0,. dev.platform_data = &pcdm8168_mouse_data,};static int __init hidg_init (void) {int status; Status = Platform_device_register (&pcdm8168_hid_keyboard); if (Status < 0) {PRINTK ("Platform_driver hid keyboard:*****wrong\n"); Platform_device_unregister (&pcdm8168_hid_keyboard); return status; } status = Platform_deviCe_register (&pcdm8168_hid_mouse); if (Status < 0) {PRINTK ("Platform_driver hid mouse:*****wrong\n"); Platform_device_unregister (&pcdm8168_hid_mouse); return status; } status = Platform_driver_probe (&hidg_plat_driver, hidg_plat_driver_probe); if (Status < 0) {PRINTK ("platform_driver_probe:*****wrong\n"); return status; } status = Usb_composite_probe (&hidg_driver, Hid_bind); if (Status < 0) platform_driver_unregister (&hidg_plat_driver); return status;} static void __exit Hidg_cleanup (void) {platform_driver_unregister (&hidg_plat_driver); Platform_device_unregister (&pcdm8168_hid_keyboard); Platform_device_unregister (&pcdm8168_hid_mouse); Usb_composite_unregister (&hidg_driver);}
3 compiling
Continue with the kernel configuration for subsequent operations
1) Build uimage and USB gadget modules
Build the kernel image and the USB gadget as modules (like
G_ether.ko, G_file_storage.ko, G_mass_storage.ko or G_zero.ko. etc).
Compile the kernel and the modified code above, compiling according to your development environment
Mine is make LSP.
4 Testing
Connect the 8168 board to the PC via USB cable.
1) Insert The gadget modules
Load the kernel image and make sure above setup was done before insert
The modules. Insert the gadget modules for usb0 port.
Insmod ko (eg: #insert g_ether.ko) Insert the gadget
Module for USB1 Port.
Insmod ko (eg: #insert g_file_storage.kofile= stall=0 buflen=65536)
8168 power on, go to working directory, make Init and make load (personal)
Because I use the board is USB1, not using USB0, but because of the characteristics of 8168, USB0 also must be configured,
My configuration is as follows:
Insmod G_ether.ko
Insmod G_hid.ko
When you open the PC, the manager will find that 8168 has been identified as a mouse and keyboard.
In order to test whether the function of the normal need to write a small test program,
As follows:
#include <pthread.h> #include <string.h> #include <stdio.h> #include <ctype.h> #include < fcntl.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #define Buf_len 512struct options{const char *opt; unsigned char val;}; static struct options kmod[] = {. opt = "--left-ctrl",. val = 0x01}, {. opt = "--right-ctrl",. val = 0 X10}, {. opt = "--left-shift",. val = 0x02}, {. opt = "--right-shift",. val = 0x20}, {. opt = "--left-alt" ,. val = 0x04}, {. opt = "--right-alt",. val = 0x40}, {. opt = "--left-meta",. val = 0x08}, {. opt = "--right-meta",. val = 0x80}, {. opt = null}};static struct options kval[] = {{. opt = "--return",. V Al = 0x28}, {. opt = "--esc",. val = 0x29}, {. opt = "--BCKSPC",. val = 0x2a}, {. opt = "--tab",. val = 0x2 b}, {. opt = "--spacebar",. val = 0x2c}, {. opt = "--caps-lock",. val = 0x39}, {. opt = "--f1",. val = 0x3a}, {. opt = "--f2",. val = 0x3b}, {. opt = "--f3",. val = 0x3c}, {. opt = "--f4",. V Al = 0x3d}, {. opt = "--f5",. val = 0x3e}, {. opt = "--f6",. val = 0x3f}, {. opt = "--f7",. val = 0x40}, {. opt = "--f8",. val = 0x41}, {. opt = "--f9",. val = 0x42}, {. opt = "--f10",. val = 0x {. opt = "--f11",. val = 0x44}, {. opt = "--f12",. val = 0x45}, {. opt = "--insert",. val = 0x49}, {. opt = "--home",. val = 0x4a}, {. opt = "--pageup",. val = 0x4b}, {. opt = "--del",. val = 0x4c}, {. opt = "--end",. val = 0x4d}, {. opt = "--pagedown",. val = 0x4e}, {. opt = "--right",. val = 0x4f}, {. opt = "- Left ",. val = 0x50}, {. opt ="--down ",. val = 0x51}, {. opt ="--kp-enter ",. val = 0x58}, {. opt ="--up ", . val = 0x52}, {. opt = "--num-lock",. val = 0x53}, {. opt = Null}};int Keyboard_fill_report (char report[8], Char Buf[buf_len],int *hOld) {char *tok = strtok (buf, ""); int key = 0; int i = 0; for (; Tok! = NULL; tok = Strtok (NULL, "")) {if (strcmp (Tok, "--quit") = = 0) return-1; if (strcmp (Tok, "--hold") = = 0) {*hold = 1; Continue } if (Key < 6) {for (i = 0; kval[i].opt! = NULL; i++) if (strcmp (tok, kval[i].opt) = = 0) {report[2 + key++] = Kval[i].val; Break } if (kval[i].opt! = NULL) Continue; } if (Key < 6) if (Islower (Tok[0])) {report[2 + key++] = (tok[0]-(' a '-0x04)); Continue } for (i = 0; kmod[i].opt! = NULL; i++) if (strcmp (tok, kmod[i].opt) = = 0) {Report[0] = Report[0] | Kmod[i].val; Break } if (kmod[i].opt! = NULL) Continue; if (Key < 6) fprintf (stderr, "unknown option:%s\n", Tok); } return 8;} static struct options mmod[] = {. opt = "--b1",. val = 0x01}, {. opt = "--b2",. val = 0x02}, {. opt = "--b3",. val = 0x04}, {. opt = Null}};int Mouse_fill_report (char report[8],char buf[buf_len],int *hold) {char *tok = strtok (buf, " "); int mvt = 0; int i = 0; for (; Tok! = NULL; tok = Strtok (NULL, "")) {if (strcmp (Tok, "--quit") = = 0) return-1; if (strcmp (Tok, "--hold") = = 0) {*hold = 1; Continue } for (i = 0; mmod[i].opt! = NULL; i++) if (strcmp (tok, mmod[i].opt) = = 0) { Report[0] = Report[0] | Mmod[i].val; Break } if (mmod[i].opt! = NULL) Continue; if (! ( Tok[0] = = '-' && tok[1] = = '-') && MVT < 2) {errno = 0; Report[1 + mvt++] = (char) strtol (Tok, NULL, 0); if (errno! = 0) { fprintf (stderr, "Bad value: '%s ' \ n", Tok); Report[1 + mvt--] = 0; } continue; } fprintf (stderr, "unknown option:%s\n", Tok); } return 3;} void Print_options (char c) {int i = 0; if (c = = ' k ') {printf ("keyboard options:\n" "--hold\n"); for (i = 0; kmod[i].opt! = NULL; i++) printf ("\t\t%s\n", kmod[i].opt); printf ("\ n keyboard values:\n" "[A-z] or\n"); for (i = 0; kval[i].opt! = NULL; i++) printf ("\t\t%-8s%s", kval[i].opt, I% 2?) "\ n": ""); printf ("--quit to close\n"); printf ("\ n"); } else if (c = = ' m ') {printf ("Mouse options:\n" "--hold\n"); for (i = 0; mmod[i].opt! = NULL; i++) printf ("\t\t%s\n", mmod[i].opt); printf ("\ n mouse values:\n" "Signed numbers\n" "--quit to Close\n"); } }int main (int argc,const char *argv[]) {const char *filename = NULL; int fd = 0; Char Buf[buf_len]; int Cmd_len; Char Report[8]; int to_send = 8; int hold = 0; Fd_set RfDs; int retval,i; if (ARGC < 3) {fprintf (stderr, "Usage:%s devname mouse|keyboard\n", argv[0]); return 1; } if (argv[2][0]! = ' k ' && argv[2][0]! = ' m ') {return 2; } filename = argv[1]; if (FD = open (filename, o_rdwr, 0666) = = =-1) {perror (filename); return 3; } print_options (Argv[2][0]); while (Fd_zero) {&rfds); Fd_set (Stdin_fileno, &rfds); Fd_set (FD, &rfds); retval = Select (FD + 1, &rfds, NULL, NULL, NULL); if (retval = =-1 && errno = = eintr) continue; if (retval < 0) {perror ("select ()"); return 4; } if (Fd_isset (FD, &rfds)) {Cmd_len = Read (FD, buf, buf_len-1); printf ("recv report:"); for (i = 0; i < Cmd_len; i++) printf ("%02x", Buf[i]); printf ("\ n"); } if (Fd_isset (Stdin_fileno, &rfds)) {memset (report, 0x0, sizeof); Cmd_len = Read (Stdin_fileno, buf, buf_len-1); if (Cmd_len = = 0) break; Buf[cmd_len-1] = ' + '; hold = 0; memset (report, 0x0, sizeof); if (argv[2][0] = = ' k ') To_send = keyboard_fill_report (report, buf, &hold); else if (argv[2][0] = = ' m ') To_send = mouse_fill_report (report, buf, &hold); if (to_send = =-1) break; if (Write (FD, report, to_send)! = to_send) {perror (filename); return 5; } if (!hold) {memset (report, 0x0, sizeof); if (Write (FD, report, to_send)! = to_send) { perror (filename); return 6; }}}}: Close (FD); return 0;}
Need a cross compiler to compile, I'm using arm-none-linux-gnueabi-gcc-4.3.3
When the compilation is complete, the generated execution file CP is executed separately from the device.
./pcdm8168_hid/dev/hidg0 K and./PCDM8168_HID/DEV/HIDG1 m
Follow the prompts to do so.
Statement : The above is the reference http://www.oschina.net/question/1174645_135969 completed, ideas and code is generally based on their ideas, only modified the individual device descriptor.
dm816x implement USB HID Gadget mouse keyboard function