lee
Posts: 14
Joined: Sat Mar 03, 2012 3:38 pm

Pi Zero as a USB keyboard (HID gadget)

Sat Jun 18, 2016 8:03 pm

I am trying to make a network-controlled keyboard emulator with a Pi Zero. I am using a NIC connected to GPIO as detailed here, and this part is working fine. The problem is I simply cannot persuade the g_hid module to load. I have been using gbaman's "method 2" as a base for this (as I need to have "dtoverlay=enc28j60" in /boot/config.txt for the NIC to work). The result is always "No such device" whether or not "g_hid" is in /etc/modules or if I use modprobe, and I have no idea why:

Code: Select all

[email protected]:~ $ uname -a
Linux pi0kbtest 4.4.13+ #894 Mon Jun 13 12:43:26 BST 2016 armv6l GNU/Linux
[email protected]:~ $ sudo dtoverlay dwc2
[email protected]:~ $ dtoverlay -l
Overlays (in load order):
0:  dwc2
[email protected]:~ $ lsmod
Module                  Size  Used by
joydev                  9194  0
evdev                  11650  0
cfg80211              499234  0
rfkill                 21397  1 cfg80211
enc28j60               20106  0
snd_bcm2835            23163  0
snd_pcm                95441  1 snd_bcm2835
snd_timer              22396  1 snd_pcm
snd                    68368  3 snd_bcm2835,snd_timer,snd_pcm
spi_bcm2835             8032  0
bcm2835_gpiomem         3823  0
bcm2835_wdt             4133  0
uio_pdrv_genirq         3718  0
uio                    10230  1 uio_pdrv_genirq
libcomposite           49383  0
udc_core               12769  1 libcomposite
ipv6                  367607  24
[email protected]:~ $
[email protected]:~ $ sudo modprobe dwc2
[email protected]:~ $ sudo modprobe g_hid
modprobe: ERROR: could not insert 'g_hid': No such device
[email protected]:~ $ lsmod
Module                  Size  Used by
dwc2                  109939  0
joydev                  9194  0
evdev                  11650  0
cfg80211              499234  0
rfkill                 21397  1 cfg80211
enc28j60               20106  0
snd_bcm2835            23163  0
snd_pcm                95441  1 snd_bcm2835
snd_timer              22396  1 snd_pcm
snd                    68368  3 snd_bcm2835,snd_timer,snd_pcm
spi_bcm2835             8032  0
bcm2835_gpiomem         3823  0
bcm2835_wdt             4133  0
uio_pdrv_genirq         3718  0
uio                    10230  1 uio_pdrv_genirq
libcomposite           49383  0
udc_core               12769  2 dwc2,libcomposite
ipv6                  367607  24
  • Pi Zero rev 1.2 from 2015
  • Raspbian Jessie Lite image dated 2016-05-27
  • Run rpi-update, firmware and all packages up to date
  • "dtoverlay=dwc2" in /boot/config.txt (in addition to or instead of "dtoverlay=enc28j60") doesn't change the result of trying to load the g_hid module
  • Linux pi0kbtest 4.4.13+ #894 Mon Jun 13 12:43:26 BST 2016 armv6l GNU/Linux
  • Tried following "method 2" without the NIC attached or "dtoverlay=enc28j60", with the same result
What am I missing here?! It is driving me crazy!

User avatar
rpdom
Posts: 12885
Joined: Sun May 06, 2012 5:17 am
Location: Ankh-Morpork

Re: Pi Zero as a USB keyboard (HID gadget)

Sat Jun 18, 2016 10:11 pm

I saw you say you were having problems with this on IRC earlier.

I think this needs USB Gadget mode enabled in the kernel and it looks like the current kernels don't have this in

Code: Select all

# CONFIG_USB_GADGET is not set
(that's a freshly apt-get upgraded 4.4.11-v7+ kernel)

You may need to build your own kernel to get this working.

lee
Posts: 14
Joined: Sat Mar 03, 2012 3:38 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sat Jun 18, 2016 11:43 pm

rpdom wrote:I saw you say you were having problems with this on IRC earlier.

I think this needs USB Gadget mode enabled in the kernel and it looks like the current kernels don't have this in

Code: Select all

# CONFIG_USB_GADGET is not set
(that's a freshly apt-get upgraded 4.4.11-v7+ kernel)

You may need to build your own kernel to get this working.
Huh, how did you check that? I don't have a /proc/config.gz, and uname -a says:
Linux pi0kbtest 4.4.13+ #894 Mon Jun 13 12:43:26 BST 2016 armv6l GNU/Linux
which was installed during the "rpi-update" I ran shortly after getting the NIC working.

Is there somewhere else the current kernel config would be lurking?

User avatar
rpdom
Posts: 12885
Joined: Sun May 06, 2012 5:17 am
Location: Ankh-Morpork

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Jun 19, 2016 6:51 am

lee wrote:
Huh, how did you check that? I don't have a /proc/config.gz, and uname -a says:
Linux pi0kbtest 4.4.13+ #894 Mon Jun 13 12:43:26 BST 2016 armv6l GNU/Linux
which was installed during the "rpi-update" I ran shortly after getting the NIC working.

Is there somewhere else the current kernel config would be lurking?
The config is in a module now, instead of the main kernel. If you "sudo modprobe configs" you will get the /proc/config.gz appearing.

lee
Posts: 14
Joined: Sat Mar 03, 2012 3:38 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Jun 19, 2016 1:17 pm

rpdom wrote:The config is in a module now, instead of the main kernel. If you "sudo modprobe configs" you will get the /proc/config.gz appearing.
I never knew that was a thing... it has been a long time indeed since I looked at compiling kernels!

However, in this kernel, the support is modular rather than not set. The module seems to be "udc-core", which is a currently inserted module. Some googling indicates that the gadgetfs module may be required too - it also inserts fine, but I simply can't get any of the g_* modules to play nicely, not even the g_zero "dummy" module; they all return "No such device".

Code: Select all

[email protected]:~ $ sudo modprobe -v -v -v g_hid
modprobe: INFO: ../libkmod/libkmod.c:354 kmod_set_log_fn() custom logging function 0x7f6336c4 registered
modprobe: DEBUG: ../libkmod/libkmod-index.c:790 index_mm_open() file=/lib/modules/4.4.13+/modules.dep.bin
modprobe: DEBUG: ../libkmod/libkmod-index.c:790 index_mm_open() file=/lib/modules/4.4.13+/modules.alias.bin
modprobe: DEBUG: ../libkmod/libkmod-index.c:790 index_mm_open() file=/lib/modules/4.4.13+/modules.symbols.bin
modprobe: DEBUG: ../libkmod/libkmod-index.c:790 index_mm_open() file=/lib/modules/4.4.13+/modules.builtin.bin
modprobe: DEBUG: ../libkmod/libkmod-module.c:540 kmod_module_new_from_lookup() input alias=g_hid, normalized=g_hid
modprobe: DEBUG: ../libkmod/libkmod-module.c:546 kmod_module_new_from_lookup() lookup modules.dep g_hid
modprobe: DEBUG: ../libkmod/libkmod.c:545 kmod_search_moddep() use mmaped index 'modules.dep' modname=g_hid
modprobe: DEBUG: ../libkmod/libkmod.c:392 kmod_pool_get_module() get module name='g_hid' found=(nil)
modprobe: DEBUG: ../libkmod/libkmod.c:400 kmod_pool_add_module() add 0x80138568 key='g_hid'
modprobe: DEBUG: ../libkmod/libkmod.c:392 kmod_pool_get_module() get module name='libcomposite' found=(nil)
modprobe: DEBUG: ../libkmod/libkmod.c:392 kmod_pool_get_module() get module name='libcomposite' found=(nil)
modprobe: DEBUG: ../libkmod/libkmod.c:400 kmod_pool_add_module() add 0x801387b0 key='libcomposite'
modprobe: DEBUG: ../libkmod/libkmod-module.c:190 kmod_module_parse_depline() add dep: /lib/modules/4.4.13+/kernel/drivers/usb/gadget/libcomposite.ko
modprobe: DEBUG: ../libkmod/libkmod.c:392 kmod_pool_get_module() get module name='udc_core' found=(nil)
modprobe: DEBUG: ../libkmod/libkmod.c:392 kmod_pool_get_module() get module name='udc_core' found=(nil)
modprobe: DEBUG: ../libkmod/libkmod.c:400 kmod_pool_add_module() add 0x801388a8 key='udc_core'
modprobe: DEBUG: ../libkmod/libkmod-module.c:190 kmod_module_parse_depline() add dep: /lib/modules/4.4.13+/kernel/drivers/usb/gadget/udc/udc-core.ko
modprobe: DEBUG: ../libkmod/libkmod-module.c:196 kmod_module_parse_depline() 2 dependencies for g_hid
modprobe: DEBUG: ../libkmod/libkmod-module.c:567 kmod_module_new_from_lookup() lookup g_hid=0, list=0x80137510
modprobe: DEBUG: ../libkmod/libkmod-module.c:1726 kmod_module_get_initstate() could not open '/sys/module/g_hid/initstate': No such file or directory
modprobe: DEBUG: ../libkmod/libkmod-module.c:1736 kmod_module_get_initstate() could not open '/sys/module/g_hid': No such file or directory
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_pcsp mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_usb_audio mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=cx88_alsa mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_atiixp_modem mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_intel8x0m mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_via82xx_modem mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=dma mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708_fb mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708_fb mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=smsc95xx mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708_fb mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=vc_mem mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=vc_mem mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=dwc_otg mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=fsck mod->name=udc_core mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1287 kmod_module_probe_insert_module() Ignoring module 'udc_core': already loaded
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_pcsp mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_usb_audio mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=cx88_alsa mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_atiixp_modem mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_intel8x0m mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_via82xx_modem mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=dma mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708_fb mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708_fb mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=smsc95xx mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708_fb mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=vc_mem mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=vc_mem mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=dwc_otg mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=fsck mod->name=libcomposite mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1287 kmod_module_probe_insert_module() Ignoring module 'libcomposite': already loaded
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_pcsp mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_usb_audio mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=cx88_alsa mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_atiixp_modem mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_intel8x0m mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=snd_via82xx_modem mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=dma mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708_fb mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708_fb mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=smsc95xx mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708_fb mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=bcm2708 mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=vc_mem mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=vc_mem mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=dwc_otg mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1374 kmod_module_get_options() modname=fsck mod->name=g_hid mod->alias=(null)
modprobe: DEBUG: ../libkmod/libkmod-module.c:1726 kmod_module_get_initstate() could not open '/sys/module/g_hid/initstate': No such file or directory
modprobe: DEBUG: ../libkmod/libkmod-module.c:1736 kmod_module_get_initstate() could not open '/sys/module/g_hid': No such file or directory
modprobe: DEBUG: ../libkmod/libkmod-module.c:728 kmod_module_get_path() name='g_hid' path='/lib/modules/4.4.13+/kernel/drivers/usb/gadget/legacy/g_hid.ko'
modprobe: DEBUG: ../libkmod/libkmod-module.c:728 kmod_module_get_path() name='g_hid' path='/lib/modules/4.4.13+/kernel/drivers/usb/gadget/legacy/g_hid.ko'
insmod /lib/modules/4.4.13+/kernel/drivers/usb/gadget/legacy/g_hid.ko
modprobe: DEBUG: ../libkmod/libkmod-module.c:728 kmod_module_get_path() name='g_hid' path='/lib/modules/4.4.13+/kernel/drivers/usb/gadget/legacy/g_hid.ko'
modprobe: INFO: ../libkmod/libkmod-module.c:868 kmod_module_insert_module() Failed to insert module '/lib/modules/4.4.13+/kernel/drivers/usb/gadget/legacy/g_hid.ko': No such device
modprobe: ERROR: could not insert 'g_hid': No such device
modprobe: DEBUG: ../libkmod/libkmod-module.c:452 kmod_module_unref() kmod_module 0x80138568 released
modprobe: DEBUG: ../libkmod/libkmod.c:408 kmod_pool_del_module() del 0x80138568 key='g_hid'
modprobe: DEBUG: ../libkmod/libkmod-module.c:452 kmod_module_unref() kmod_module 0x801388a8 released
modprobe: DEBUG: ../libkmod/libkmod.c:408 kmod_pool_del_module() del 0x801388a8 key='udc_core'
modprobe: DEBUG: ../libkmod/libkmod-module.c:452 kmod_module_unref() kmod_module 0x801387b0 released
modprobe: DEBUG: ../libkmod/libkmod.c:408 kmod_pool_del_module() del 0x801387b0 key='libcomposite'
modprobe: INFO: ../libkmod/libkmod.c:321 kmod_unref() context 0x80137110 released
I'm sure it's something fundamental, but I have no idea what...

User avatar
rpdom
Posts: 12885
Joined: Sun May 06, 2012 5:17 am
Location: Ankh-Morpork

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Jun 19, 2016 3:58 pm

Ok, I checked back now that I am home with a Pi in front of me and I realise I was looking at the config for a Pi2/3 kernel, which won't have gadget mode available anyway.

Back on a Pi Zero, with a recent kernel, I get the same issue as you. Curious... I shall keep looking at it.
[edit]
It seems like it needs a /dev/hidg0 device file creating first. I shall see if I can find how to do that.

lee
Posts: 14
Joined: Sat Mar 03, 2012 3:38 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Jun 19, 2016 5:51 pm

I was specifying in /boot/config.txt

Code: Select all

dtoverlay=enc28j60
in order to get the NIC to function, and then after boot, (using nmap to find it, then ssh'ing in and) running

Code: Select all

sudo dtoverlay dwc2
and ensuring with lsmod that the dwc2 module was loaded. However, it seems that this is a good chunk of where I am going wrong - specifying dtoverlay in config.txt does not appear to be the same as running the dtoverlay command later after the system has booted - so if I am accessing the Pi Zero via the network, with "dtoverlay=enc28j60" in config.txt, then after logging in run "sudo dtoverlay dwc2", this is NOT sufficient. If I have "dtoverlay=dwc2" in config.txt and then run scripts to create a /dev/hidg0, while logged in locally, it does create the device.

In all cases, I still can't "modprobe g_hid" without getting a "No such device" error. But I can create a /dev/hidg0 with a script, libcomposite, and configfs!

First off, I needed a custom device tree overlay in order to make this work, so I put this into lee.dts:

Code: Select all

// Custom overlay that combines enc28j60 & dwc2 overlays
// Probably a better way to do this with /include/ but I don't know how and this worked for me
/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2708";

	[email protected] {
		target = <&spi0>;
		__overlay__ {
			/* needed to avoid dtc warning */
			#address-cells = <1>;
			#size-cells = <0>;

			status = "okay";

			eth1: [email protected]{
				compatible = "microchip,enc28j60";
				reg = <0>; /* CE0 */
				pinctrl-names = "default";
				pinctrl-0 = <&eth1_pins>;
				interrupt-parent = <&gpio>;
				interrupts = <25 0x2>; /* falling edge */
				spi-max-frequency = <12000000>;
				status = "okay";
			};
		};
	};

	[email protected] {
		target = <&spidev0>;
		__overlay__ {
			status = "disabled";
		};
	};

	[email protected] {
		target = <&gpio>;
		__overlay__ {
			eth1_pins: eth1_pins {
				brcm,pins = <25>;
				brcm,function = <0>; /* in */
				brcm,pull = <0>; /* none */
			};
		};
	};

    [email protected] {
		target = <&usb>;
		#address-cells = <1>;
		#size-cells = <1>;
		dwc2_usb: __overlay__ {
			compatible = "brcm,bcm2835-usb";
			reg = <0x7e980000 0x10000>;
			interrupts = <1 9>;
			dr_mode = "otg";
			g-np-tx-fifo-size = <32>;
			g-rx-fifo-size = <256>;
			g-tx-fifo-size = <256 128 128 64 64 64 32>;
			status = "okay";
		};
    };
    
	__overrides__ {
		int_pin = <&eth1>, "interrupts:0",
		          <&eth1_pins>, "brcm,pins:0";
		speed   = <&eth1>, "spi-max-frequency:0";
		dr_mode = <&dwc2_usb>, "dr_mode";
		g-np-tx-fifo-size = <&dwc2_usb>,"g-np-tx-fifo-size:0";
		g-rx-fifo-size = <&dwc2_usb>,"g-rx-fifo-size:0";
		g-tx-fifo-size = <&dwc2_usb>,"g-tx-fifo-size:0";
	};
};
(those are tabs rather than spaces, I don't know how important that is but this is what worked for me)

I simply took the source for the NIC DTO and the source for the dwc2 overlay and combined them and modifying slightly (added the dwc2 [email protected] as [email protected] - I have no idea if I could have literally copied and pasted but this seemed more sensible). I originally looked up these files to see if there was some kind of conflict between them while trying to debug loading them in different orders with the dtoverlay command after booting - doesn't look like it to me. But I know next to nothing about the device tree :D

Based on the documentation here, I ran:

Code: Select all

sudo apt-get install device-tree-compiler # just to make sure, it was already installed for me in the Raspbian Jessie Lite 2015-05-27 image
dtc [email protected] -I dts -O dtb -o lee.dtbo lee.dts
... which gave me ...

Code: Select all

[email protected]:~ $ dtc [email protected] -I dts -O dtb -o lee.dtbo lee.dts
Warning (unit_address_vs_reg): Node /[email protected] has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /[email protected] has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /[email protected] has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /[email protected] has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /[email protected]/__overlay__ has a reg or ranges property, but no unit name
and a lee.dtbo file. I copied both lee.dtbo and lee.dts into /boot/overlays (because I am lazy) and modified /boot/config.txt to include

Code: Select all

dtoverlay=lee
then proceeded with the customary goat sacrifice and prayers to the dark one, tried a reboot aaaaaaand...
... it worked! The result is, I now have the Pi Zero on the network (and a static MAC set so it gets the same IP address every time, as trying to configure it in /etc/network/interfaces seems to do nothing) and can run a script to create a /dev/hidg0 which I will hopefully be able to write to to send keystrokes. The script is:

Code: Select all

#!/bin/bash
# From the README at https://github.com/girst/hardpass

dtoverlay dwc2
modprobe dwc2
modprobe libcomposite
cd /sys/kernel/config/usb_gadget/
mkdir -p g1
cd g1
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
mkdir -p strings/0x409
echo "fedcba9876543210" > strings/0x409/serialnumber
echo "girst" > strings/0x409/manufacturer
echo "Hardpass" > strings/0x409/product
N="usb0"
mkdir -p functions/hid.$N
echo 1 > functions/hid.usb0/protocol
echo 1 > functions/hid.usb0/subclass
echo 8 > functions/hid.usb0/report_length
echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc
C=1
mkdir -p configs/c.$C/strings/0x409
echo "Config $C: ECM network" > configs/c.$C/strings/0x409/configuration
echo 250 > configs/c.$C/MaxPower
ln -s functions/hid.$N configs/c.$C/
ls /sys/class/udc > UDC
It appears that this script MUST be run BEFORE plugging the device into a host. I don't yet know what repercussions this has for running it during boot, while the device is attached to a host.

So in theory, now I need to write scancodes to /dev/hidg0 and I should end up with a network controllable keyboard. Somehow I doubt this last part is going to be quite that easy!

User avatar
rpdom
Posts: 12885
Joined: Sun May 06, 2012 5:17 am
Location: Ankh-Morpork

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Jun 19, 2016 6:22 pm

You've made good progress. Better than I managed :-)

lee
Posts: 14
Joined: Sat Mar 03, 2012 3:38 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Jun 19, 2016 7:33 pm

So, it's not too bad actually; this reference was very helpful, especially with the official docs (chapter 10), and a list of codes (or an easier to read version). The author of hardpass provides the details here near the bottom under "Keyboard / Mouse / Joystick (HID)", and the scan program works well, but I want to understand how it works too, so for now I am echoing to /dev/hidg0.

Here are a few misc links that didn't really fit in any of the other posts but still contained useful information:
https://github.com/qlyoung/keyboard-gadget
https://github.com/girst/hardpass
https://wiki.tizen.org/wiki/USB/Linux_U ... o_g_hid.ko
http://trac.gateworks.com/wiki/linux/OTG
hid_gadget_test source from bottom of https://www.kernel.org/doc/Documentatio ... et_hid.txt

kovacsadam07
Posts: 6
Joined: Tue Sep 01, 2015 10:35 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Jul 03, 2016 9:31 am

Very nice and usefull post!

Btw:
so it gets the same IP address every time, as trying to configure it in /etc/network/interfaces seems to do nothing
I guess it is beacuse /etc/network/interfaces apllies before the NIC gets eth0. Any idea about this? I would use that NIC as dhcp, so i would need a fix ip. 'service networking restart' solves the problem, but is there any other way? Something nice, not-as-hacky?

lee
Posts: 14
Joined: Sat Mar 03, 2012 3:38 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Wed Jul 13, 2016 10:11 pm

kovacsadam07 wrote:Very nice and usefull post!
Btw:
so it gets the same IP address every time, as trying to configure it in /etc/network/interfaces seems to do nothing
I guess it is beacuse /etc/network/interfaces apllies before the NIC gets eth0. Any idea about this? I would use that NIC as dhcp, so i would need a fix ip. 'service networking restart' solves the problem, but is there any other way? Something nice, not-as-hacky?
I'm sure there's a better way, I just don't know what it is, and what I have is good enough for what I'm after so I don't have any motivation to work on this relatively minor problem. If you figure it out though please post back here!

Seehank
Posts: 5
Joined: Sun Mar 26, 2017 9:34 am

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Mar 26, 2017 10:02 am

Hey guys, since we are pinning into GPIO. Will this work on RPi 2/3 ?

lee
Posts: 14
Joined: Sat Mar 03, 2012 3:38 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Mar 26, 2017 11:07 am

Seehank wrote:Hey guys, since we are pinning into GPIO. Will this work on RPi 2/3 ?
Will what work? Attaching a NIC via GPIO? I don't see why not. Pretty sure the same limitations will apply, so it'll be 10Mbit if you're lucky.
If you mean "make a Pi 2/3 emulate a USB host", no - must be a Pi Zero. I haven't tried a Zero W but I am pretty sure it'll work.

Seehank
Posts: 5
Joined: Sun Mar 26, 2017 9:34 am

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Mar 26, 2017 11:33 am

The second one lee, you answeared to me, thanx :)

See I am trying to put together pretty similar machine as you. My story is:

1. I need RPi Z to act as HID Keyboard to send some pieces of text to a PC to basically fill in a form.
2. I need to get the data I want to write from online server via Ethernet
3. and I want this action to be triggered by scan of NFC card via NFC reader

So basically a person scans an NFC card and based on what the NFC says it will ping an online server and start filling in information as a HID keyboard. I know it sound like a stupid solution, but I really have a reason to do this hack, since the other PC has a very proprietary OS installed since it servers as a single purpose UI.

Now I know the NFC reader works just fine, I definitelly will be able to connectto our API online and get data on trigger (this I should handle with Adafruit Ethernet Hub and USB Hub w/ Micro USB OTG Connector) BUT than comes the part to act like a HID where I guess I am out of USB sockets since one powers my Pi and the other one is taken by the hub and I am really affraid that in order to act like a HID I need to use directly one USB socket set to slave.

Am I correct? Do you have any suggestion if so? I am more of a begginer in RPi so I hope my question is not too stupid. I would appretiate your piece of mind very much.

User avatar
davidcoton
Posts: 3207
Joined: Mon Sep 01, 2014 2:37 pm
Location: Cambridge, UK

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Mar 26, 2017 11:54 am

The problem is that you can't run USB gadget mode through a Pi-connected hub -- that takes out the B models. And since there is only one USB port on the SOC, the Zeros and the A models can't have a USB peripheral and run in gadget mode. The Zero power socket does not have any data connections.

So for your project you would need to find a card reader that connects some way other than USB.
"Thanks for saving my life." See https://www.raspberrypi.org/forums/viewtopic.php?p=1327656#p1327656
“Raspberry Pi is a trademark of the Raspberry Pi Foundation”

lee
Posts: 14
Joined: Sat Mar 03, 2012 3:38 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Mar 26, 2017 11:54 am

Seehank wrote:The second one lee, you answeared to me, thanx :)

See I am trying to put together pretty similar machine as you. My story is:

1. I need RPi Z to act as HID Keyboard to send some pieces of text to a PC to basically fill in a form.
2. I need to get the data I want to write from online server via Ethernet
3. and I want this action to be triggered by scan of NFC card via NFC reader

So basically a person scans an NFC card and based on what the NFC says it will ping an online server and start filling in information as a HID keyboard. I know it sound like a stupid solution, but I really have a reason to do this hack, since the other PC has a very proprietary OS installed since it servers as a single purpose UI.

Now I know the NFC reader works just fine, I definitelly will be able to connectto our API online and get data on trigger (this I should handle with Adafruit Ethernet Hub and USB Hub w/ Micro USB OTG Connector) BUT than comes the part to act like a HID where I guess I am out of USB sockets since one powers my Pi and the other one is taken by the hub and I am really affraid that in order to act like a HID I need to use directly one USB socket set to slave.

Am I correct? Do you have any suggestion if so? I am more of a begginer in RPi so I hope my question is not too stupid. I would appretiate your piece of mind very much.
I haven't done anything with NFC and a Pi yet, but these are my thoughts. No guarantees of accuracy!

First of all, determine what specific kind of tags you are using (assuming they already exist, otherwise if you are free to choose your own it doesn't matter, as you will just buy compatible ones). Then I'd look at buying this reader from Adafruit as it is a 3.3v device (so you won't need a level shifter as the Pi is a 3.3v logic level device), speaks I2C, and there's a tutorial to make it talk to a Pi (although it looks like that may be for the other hardware version of the reader that Adafruit sell, and I think that this tutorial is wrong nowadays as it dates from 2012 and libnfc can now use I2C and not just UART to communicate). With one of these attached via GPIO, you still have the single USB port free, and if you're using a Pi Zero W you have a built-in network connection, otherwise you could use the SPI based ethernet module detailed above (you can run I2C and SPI at the same time).

Seehank
Posts: 5
Joined: Sun Mar 26, 2017 9:34 am

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Mar 26, 2017 12:04 pm

Thank you for your piece of mind, I appreciate it. Now what do you think? If I connect this board to my Zero, will will it take my USB socket? Seems to me it connects directly to the both USBs so probably yes, but its worth a shot :)

If so, that this is same HUB as I mentioned before and I am in the same spot again.

For the reader lee I need something very simple, easy to purchase easy to change so that is why I went after USB one.

lee
Posts: 14
Joined: Sat Mar 03, 2012 3:38 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Mar 26, 2017 12:25 pm

Seehank wrote:Thank you for your piece of mind, I appreciate it. Now what do you think? If I connect this board to my Zero, will will it take my USB socket? Seems to me it connects directly to the both USBs so probably yes, but its worth a shot :)
From the page you linked: "The original microusb port on Raspberry PI Zero cannot be used any more! So you need to use one of the other two USB ports or additional USB hub if you need more USB ports." - so no, this won't let you use the micro USB port in host mode.
Seehank wrote:For the reader lee I need something very simple, easy to purchase easy to change so that is why I went after USB one.
If you want very simple and easy to purchase then you are looking in the wrong place - these are not products that are plug and play, you have to do the leg work. If you want a commercial solution, you need to find a supplier that will build it for you (and likely, charge you a whole lot of money in the process). A USB reader is simply not suitable for what you are trying to accomplish.

Seehank
Posts: 5
Joined: Sun Mar 26, 2017 9:34 am

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Mar 26, 2017 12:28 pm

Thank you very much for the answears.

coldtofu
Posts: 1
Joined: Tue Apr 25, 2017 2:22 am

Re: Pi Zero as a USB keyboard (HID gadget)

Tue Apr 25, 2017 2:33 am

Hi Seehank,
I'm also working on this project with a Pi-Zero, but I'm encountering segmentation fault in the following line:

Code: Select all

ls /sys/class/udc > UAC

Code: Select all

[FAILED] Failed to start /etc/rc.local Compatiblity.
Was wondering if you ever encountered this or know what is wrong?
Thanks and regards,
c.tofu

Slumberwatcher
Posts: 1
Joined: Sun May 14, 2017 6:01 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sun May 14, 2017 6:16 pm

Hi...

I had the same problem apparently it seems like they have changed something in the kernel so that the kernel module usb_f_hid.ko cause a segfault when you try to activate a hid device... https://github.com/raspberrypi/linux/issues/1943

My solution was to downgrade to an older kernel (4.4.49+) by running:

Code: Select all

rpi-update 2ca627126e49c152beb1bf7abd7122ce076dcc65
And after a reboot I could create devices again. :) Not sure if you are supposed to create devices in another way now, or if they plan on fixing it...but for the moment it works for me and I can keep on hacking.

Hope it helps.

/Slumber

doublehp
Posts: 72
Joined: Wed May 02, 2012 1:11 am

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Nov 26, 2017 11:06 am

Can all versions of rpi0 do it ? 1.2, 1.3, W ?

DirkS
Posts: 9270
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Nov 26, 2017 11:06 am

doublehp wrote:
Sun Nov 26, 2017 11:06 am
Can all versions of rpi0 do it ? 1.2, 1.3, W ?
yes

RDPUser
Posts: 72
Joined: Tue Jan 30, 2018 12:18 pm

Re: Pi Zero as a USB keyboard (HID gadget)

Sun Apr 08, 2018 7:36 pm

I've also found this tutorial https://www.rmedgar.com/blog/using-rpi- ... definition and https://gist.github.com/gbaman/50b6cca61dd1c3f88f41 and I'm sure everything works, so that the Pi is recognized as keyboard. But how do I send keystrokes or mouse input to the PC?

doublehp
Posts: 72
Joined: Wed May 02, 2012 1:11 am

Re: Pi Zero as a USB keyboard (HID gadget)

Sun May 20, 2018 7:08 pm

RDPUser I am doing using very complex setup involving ... netcat, screen, tcpdump and other very funky tools; my project is not stable yet, and I did not yet publish my tutorial. In short, it's PITA, but it can be done.

My setup is really a huge hell. My client is a mobile phone, which connects to a webpage (orange pi), which is including a novnc server (orange pi), which calls a VNC server (rpi). Because of novnc, vnc can transmit only mouse moves; so my webpage contains a zone (outside of the VNC view) to enter keystrokes which are sent to the webserver (via web - the orange pi), which sends them via netcat to the rpi, to send them to the PC host via USB-gadget ... so, the rpi can handle both keystrokes and mouse moves, but acquires instructions via two different methods. And each rpi is running two VNC streams. And because all this is not enough, I will need to add a second USB mouse because USB-gadget does not always work fine on the target host, so the pi will emulate a second mouse via a non-gadget method for when the gadget method fails (I will use a legacy USB mouse, plugged directly on the target, but, a USB mouse with old ball system, and control the optical gates using GPIO ... ).

Return to “Advanced users”