Tag Archives: driver

Wii U Gamepad Connection

I’ve been playing with the Wii-U Gamepad lately and am trying to figure out how it connects to the Wii U console. Once we get that working, we can start reverse-engineering the protocol and write a linux driver for it. It would make a great remote display for every linux box. So how does it work?

The communication between Wii-U and GamePad is done via 5Ghz Wi-Fi. It uses the range 5150-5250 Mhz (Sony UWA-BR100 is a nice dual-band ath9_htc USB dongle with perfect linux support). The console opens a soft AP without any encryption. SSID is set similar to “WiiU34af2c5fa6134af2c5fa61c_STA1”. The GamePad connects to this AP and then creates some private link. I haven’t figured out how this works, yet.

The IE fields do not advertise any Wifi-Direct (P2P), Wifi-Display (WFD) or Direct-Link (TDLS) features. The only features found are WMM QoS fields.

How to proceed? I need to figure out how to create a soft-AP with the advertised features so I can make the GamePad connect to me. Two Nintendo extensions are advertised “OUI a4:c0:e1” which probably identify the AP. The other vendor IEs are Broadcom/EPIGRAM IDs which can also be found on other networks. After that, I need to test P2P discovery, TDLS discovery or 802.11e DLS setup to find out what kind of direct-link Nintendo uses. According to Broadcom’s Dino Bekis a form a Miracast is used which would mandate P2P or TDLS.

If anyone has more information on that, I’d be very thankful!

Btw., dhcp is provided on the unprotected soft-AP and I can ping the console but my port-scans didn’t return any useful information. I will try connecting to WFD/RTSP default port 7236 next…

 

Soft-AP during Synchronization:

BSS 34:af:2c:5f:a6:1c (on wlan1)
	TSF: 3126337 usec (0d, 00:00:03)
	freq: 5180
	beacon interval: 100
	capability: ESS (0x0001)
	signal: -55.00 dBm
	last seen: 3208 ms ago
	Information elements from Probe Response frame:
	SSID: WiiU34af2c5fa6134af2c5fa61c_STA1
	Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0 
	HT capabilities:
		Capabilities: 0x1c
			HT20
			SM Power Save disabled
			RX Greenfield
			No RX STBC
			Max AMSDU length: 3839 bytes
			No DSSS/CCK HT40
		Maximum RX AMPDU length 16383 bytes (exponent: 0x001)
		Minimum RX AMPDU time spacing: 8 usec (0x06)
		HT RX MCS rate indexes supported: 0-15
		HT TX MCS rate indexes are undefined
	HT operation:
		 * primary channel: 36
		 * secondary channel offset: no secondary
		 * STA channel width: 20 MHz
		 * RIFS: 1
		 * HT protection: no
		 * non-GF present: 0
		 * OBSS non-GF present: 0
		 * dual beacon: 0
		 * dual CTS protection: 0
		 * STBC beacon: 0
		 * L-SIG TXOP Prot: 0
		 * PCO active: 0
		 * PCO phase: 0
	Vendor specific: OUI a4:c0:e1, data: f5 00
	Vendor specific: OUI a4:c0:e1, data: f4 10 4a 00 01 10 10 44 00 01 02 10 41 00 01 01 10 12 00 02 00 00 10 53 00 02 00 84 10 3b 00 01 03 10 47 00 10 22 21 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 21 00 08 42 72 6f 61 64 63 6f 6d 10 23 00 06 53 6f 66 74 41 50 10 24 00 01 30 10 42 00 01 30 10 54 00 08 00 06 a4 c0 e1 f4 00 01 10 11 00 10 57 69 69 55 33 34 61 66 32 63 35 66 61 36 31 63 10 08 00 02 00 84
	Vendor specific: OUI 00:10:18, data: 02 00 00 04 00 00
	WMM:	 * Parameter version 1
		 * u-APSD
		 * BE: CW 15-31, AIFSN 2, TXOP 1504 usec
		 * BK: CW 15-1023, AIFSN 7
		 * VI: CW 15-31, AIFSN 3, TXOP 3008 usec
		 * VO: CW 15-31, AIFSN 3, TXOP 1504 usec

Soft-AP during normal operation with GamePad:

BSS 34:af:2c:5f:a6:1c (on wlan1)
	TSF: 413388858 usec (0d, 00:06:53)
	freq: 5180
	beacon interval: 100
	capability: ESS Privacy (0x0011)
	signal: -48.00 dBm
	last seen: 3201 ms ago
	Information elements from Probe Response frame:
	SSID: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
	Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0 
	TIM: DTIM Count 1 DTIM Period 3 Bitmap Control 0x0 Bitmap[0] 0x0
	RSN:	 * Version: 1
		 * Group cipher: a4-c0-e1:4
		 * Pairwise ciphers: a4-c0-e1:4
		 * Authentication suites: a4-c0-e1:2
		 * Capabilities: 4-PTKSA-RC (0x0008)
	HT capabilities:
		Capabilities: 0x1c
			HT20
			SM Power Save disabled
			RX Greenfield
			No RX STBC
			Max AMSDU length: 3839 bytes
			No DSSS/CCK HT40
		Maximum RX AMPDU length 16383 bytes (exponent: 0x001)
		Minimum RX AMPDU time spacing: 8 usec (0x06)
		HT RX MCS rate indexes supported: 0-15
		HT TX MCS rate indexes are undefined
	HT operation:
		 * primary channel: 36
		 * secondary channel offset: no secondary
		 * STA channel width: 20 MHz
		 * RIFS: 1
		 * HT protection: no
		 * non-GF present: 1
		 * OBSS non-GF present: 0
		 * dual beacon: 0
		 * dual CTS protection: 0
		 * STBC beacon: 0
		 * L-SIG TXOP Prot: 0
		 * PCO active: 0
		 * PCO phase: 0
	Vendor specific: OUI 00:90:4c, data: 07 00 45 55 17
	Vendor specific: OUI 00:10:18, data: 02 01 00 04 00 00
	WMM:	 * Parameter version 1
		 * u-APSD
		 * BE: CW 15-31, AIFSN 2, TXOP 1504 usec
		 * BK: CW 15-1023, AIFSN 7
		 * VI: CW 15-31, AIFSN 3, TXOP 3008 usec
		 * VO: CW 15-31, AIFSN 3, TXOP 1504 usec
Advertisements

UHID: User-Space HID I/O drivers

Linux-next currently contains a new HID transport-level driver called UHID. If nothing goes wrong it will be released with linux-3.6 in about 2 months. The curious reader can currently find it in the HID maintainer’s (Jiri Kosina) tree. I get often asked what this driver is good for and why uinput wasn’t used to achieve the same? Lets look closer at this:

HID Subsystem Overview

The kernel HID subsystem (./drivers/hid/) implements the HID specifications and is responsible for handling HID requests from devices and forwarding them to the related kernel interfaces. The most known devices are USB keyboards. Therefore, the HID subsystem contains an USBHID called driver (it can be found in ./drivers/hid/usbhid/) which takes care of handling the transport-level I/O details of the USB HID devices. It registers each device it finds with the HID core and therefore is only responsible for handling pure I/O. The protocol parsing is done by the HID core. There is also the HIDP driver (it can be found in ./net/bluetooth/hidp) which does the same for Bluetooth devices. USBHID and HIDP are called “hid_ll_drivers: HID low level drivers” and are responsible for the transport-level (or I/O), thus also called “transport-level driver” or “I/O driver”.

In a perfect world, the HID core would handle the HID reports from the low-level drivers, parse them and feed them into the input subsystem which provides them as input data to user-space. However, many devices need some quirks to work correctly as they are not standard-conforming. Therefore, the “hid_driver: HID device driver” infrastructure was built which allows to write HID drivers handling the device-specific quirks or protocol. They are mostly independent of the transport-level and can work with any low-level HID driver. Some drivers (specifically hid-picolcd and hid-wiimote) even implement complex input-unrelated protocols on top of HID to allow full device-control.

UHID Driver

The UHID driver is a “low-level/transport-level driver (hid_ll_driver)” which was written to allow user-space to act as I/O drivers for the HID subsystem. The UHID driver does not allow writing HID-device drivers (hid_driver), though. There is already the “hidraw” driver which can serve for this purpose.

User-space can simply open /dev/uhid and create/destroy hid-devices in the hid-core. Each open file-descriptor on /dev/uhid can control exactly one device. Let’s look at this from the perspective of HoG (HID over GATT/Bluetooth-Low-Energy): GATT is a Bluetooth protocol implemented in user-space. When user-space opens an LE (low-energy) connection to a Bluetooth device, the device can advertise HID capabilities via GATT. User-space then opens /dev/uhid and creates a new device via the UHID_CREATE message. The UHID driver registers the new device with the HID core and user-space can now transmit I/O data to the kernel. The important design pattern is, that the transport-driver is actually implemented in user-space. If it was realized in kernel-space, then you wouldn’t need UHID and could register your own low-level HID driver. The reasons why HoG is implemented in user-space are out of the scope of this document.

So why doesn’t HoG use uinput? uinput is a kernel module that allows creating kernel input-devices from user-space. It does not do any sophisticated protocol parsing or similar but simply forwards the events to all interested listeners. If HoG was using uinput, it would have to implement the whole HID stack in user-space, although the kernel already has the whole infrastructure for that. Hence, we would duplicate a whole bunch of code without a real gain. uinput isn’t even faster than UHID, neither is it smaller. uinput is simply not suited for this use-case. Therefore, UHID was created.

UHID Design

Each open file-descriptor on /dev/uhid can register a single HID device with the HID-core. Communication is solely done via write()/read() with a special buffer-format. The in-tree documentation describes the protocol in full detail. Each write()/read() call transmit zero or one messages. If multiple messages are to be transmitted, user-space must use readv()/writev(). The UHID_CREATE and UHID_DESTROY messages allow user-space to register and destroy the HID device so it can control the device lifetime. UHID_INPUT is used to feed raw I/O data into the kernel. Similarly, the kernel sends several events to user-space (which can be poll()’ed for) to notify the application about new output-data or device-state changes.

The initial patchset already includes an example program that demonstrates how to use the UHID API. It emulates an HID mouse with 3 buttons and a mouse-wheel. Obviously, this program can be easily written with uinput and uinput would be better suited for this use-case. But again, this is only an example to demonstrate how this is achieved. Systems like HoG cannot use uinput so they can now be seamlessly integrated into the linux eco-system with UHID, without needing any special application support to use these new devices.

User-space HoG implementation has already been merged into BlueZ so you can test this feature when running linux-next. Lets see how all this works out. If the performance is Ok, there is also the idea of moving HIDP into user-space, too. That is, both Bluetooth HID transport-drivers would run inside of the user-space Bluetooth daemon. But lets first make sure HoG is working great!