By Bill Sempf
Downloads
Coding for Custom Devices in Windows* 8.1 and Windows* RT 8.1 [PDF 803KB]
The Windows 8.1 operating system (as well as Windows RT 8.1) has a lot of interesting new features, not the least of which is the return of the vaunted Start button. New device support for Windows* Store apps, however, gives developers some exciting new use cases to explore.
One particularly useful feature of Windows 8.1 tablets is the USB port. Support for more sophisticated devices outside of basic driver interactions really makes you consider Windows 8.1 tablets for more line-of-business apps, like cash registers and kiosk user interaction.
New Device APIs
Application programming interfaces (APIs) for new devices focus on USB-driven hardware in Windows 8.1. Although all of them are interesting, this article focuses on two in particular: human interface devices (HIDs) and point-of-service (PoS) devices.
Human Interface Device Support
In Windows parlance, a human interface device means more than a keyboard or mouse. It’s true that HIDs started with those items, but they also included joysticks and game controllers. Now, though, HID is a protocol that can support a much larger set of devices, including those beyond the USB realm.
The HID protocol that Windows 8.1 supports is bus agnostic. What’s more, it has been generalized enough to handle a broad set of devices that humans use to communicate with computers, including various pointing devices, knobs and sliders, telephones, DVD-style controls, steering wheels, and rudder pedals. Of more interest to this article are sensor-type interfaces, such as those found on thermometers, pressure sensors, and bar code readers.
Point-of-Service Support
Point-of-service (PoS) device access is a bit more business layer and a bit less hardware layer than HID support, but there are many similarities. PoS specifically focuses on supporting the USB devices you would expect to find attached to cash registers, inventory systems, or time clocks—bar code scanners and magnetic card readers—making it unnecessary to use a camera or other built-in feature for this functionality.
Other Devices
PoS hardware isn’t the only type of devices added to Windows 8.1, however. New USB, Bluetooth*, and 3D printer device support shows up as well.
USB support isn’t new for Windows 8.1, but the idea of a custom device is. The bulk of this article is about how to write Windows Store apps for a device for which Microsoft does not provide a driver.
Windows Store apps now have access to the RFCOMM
and GATT
APIs to access Bluetooth devices. After a device has been paired and security checks approved, Windows RT has programmatic access to these devices. Similarly, printing isn’t new to Windows RT devices, but the addition of the IXpsDocumentPackageTarget3D
interface to the Windows RT APIs means that you theoretically can build Windows Store apps to run your MakerBot
—but that’s for a later article.
If you don’t happen to have a magstripe reader, 3D printer, and steering wheel for your development laptop, the JJG Technologies Super Multipurpose USB Test Tool (Super MUTT) can solve your problems. Microsoft helped design Super MUTT to help emulate such devices. This USB peripheral supports control, interrupt, bulk, isochronous, and streams data transfers.
Human Interface Devices
The HID standard was initially designed to connect mouse devices and keyboards via USB. It is bus agnostic by design, which allowed ports to other protocols, like Bluetooth and infrared. It is newly supported by Windows 8.1 in the Windows.Devices
namespace.
Integrating with Hardware Partners
The goal of HID support in Windows 8.1 is for manufacturers that create interface devices to be able to bundle Windows Store apps with their devices. Essentially, certified independent hardware vendors have the option to bundle a Windows Store app with their hardware so long as it uses the standard Windows hardware driver.
The hardware, once installed, would then be able to interact with the Windows Store to download and install the relevant app when the hardware is connected to the host. This makes an optimal, noninvasive environment for additional device functionality while making best use of the built-in Windows hardware support.
HID Types
Although the HID protocol was originally designed for literal human interaction, it has been expanded to support a large number of low-latency, I/O device interfaces. Now, a broad range of devices support HID, and interested device manufacturers can contact Microsoft for details. Developers should check the device documentation to ensure support. The new Windows 8.1 APIs define several HID classes, including:
- Mouse class driver and mapper driver
- Game controllers
- Keyboard and keypad class driver and mapper driver
- Flight Mode Switch
- System controls (Power)
- Consumer controls (
HIDServ.dll
) - Pen device
- Touch screen
- Sensors
- HID UPS battery
Enumeration and the DeviceSelector
Accessing HID objects is a two-step process. First, the app must find the Advanced Query Syntax (AQS) string related to the HID device you are manipulating. Then, the app can use the DeviceInformation.FindAllAsync()
method to retrieve a collection of DeviceInformation
objects.
You access the AQS string for the device via the HidDevice.GetDeviceSelector(usagePage, usageId)
method. This method takes values from the special-purpose hardware ID enumeration and returns the AQS string needed to get a collection of DeviceInformation
objects. See Table 1.
Table 1. Accessing the AQS string
Device Type | Usage Page | Usage | Hardware ID |
---|---|---|---|
Pointer | 0x01 | 0x01 | HID_DEVICE_SYSTEM_MOUSE |
Mouse | 0x01 | 0x02 | HID_DEVICE_SYSTEM_MOUSE |
Joystick | 0x01 | 0x04 | HID_DEVICE_SYSTEM_GAME |
Game pad | 0x01 | 0x05 | HID_DEVICE_SYSTEM_GAME |
Keyboard | 0x01 | 0x06 | HID_DEVICE_SYSTEM_KEYBOARD |
Keypad | 0x01 | 0x07 | HID_DEVICE_SYSTEM_KEYBOARD |
System control | 0x01 | 0x80 | HID_DEVICE_SYSTEM_CONTROL |
Consumer audio control | 0x0C | 0x01 | HID_DEVICE_SYSTEM_CONSUMER |
When an AQS string is available, the DeviceInformation.FindAllAsync(aqs)
method returns a collection of attached HIDs as DeviceInformation
objects. The DeviceInformation
class provides control and report classes. Control classes give the application control over certain defined values in the device, and report classes are how the app reads data back from the device.
Control Classes
Control
classes represent properties of an HID with which apps can interact. For instance, the sensitivity of a touchpad or the lights on a keyboard would be accessed via control classes. Control classes come in two flavors: Boolean (an on/off switch) and numeric.
Numeric controls are 64-bit integers that represent a value of some parameter of the HID. A DeviceInformation
object can support any number of NumericControls
, which are distinguished by ID and defined by the ControlDescription
property. The HidNumericControl
supports both static and scaled value properties that are the only read/write properties of the class. Read-only properties include the related UsageId
and UsagePage
, the ID and description, respectively, which are stored in the ControlDescription
property.
The HidBooleanControl
is just the on/off version of the numeric control. It has largely the same accessibility and functionality, except that the Value
property is Boolean. The property controls a device’s lights and power.
Report Classes
Report classes represent the values that the application needs to collect from the device. Reports provide data about available features, user input, and requests for device changes.
The host and device can communicate the supported feature through HidFeatureReport
. The Data
property holds relevant information about the features, including the Boolean and numeric controls that you can use to change or collect said data. The input coming from the device is found in HidInputReport
. The HidInputReport
class lets the app request the Data
property from a defined input vector. All data is provided at once. If there are multiple input vectors, they are delineated in the IBuffer
that the Data
property returns.
Output reports request changes on the device. This object breaks the model a bit; the output report is “sent” to the device to request a change. After the Data
property of the report has been set, it is sent using the SendOutputReport
method of the HidDevice
object.
Point-of-Service Devices
Whereas HIDs have an agreed-upon standard, PoS devices do not. PoS devices are those things we expect to see at cash registers, like bar code and magnetic stripe readers (although some magstripe readers do adhere to the HID standard).
Microsoft seems to be aiming squarely at making Windows 8.1 a viable target for PoS devices. Picture a retail store in which all the staff carry a Windows 8.1 tablet, ready to scan an item and take your card. With a unified standard for PoS devices, this vision could be a reality.
Microsoft Office integration in Windows is a big deal, with the advanced back-office offerings that Microsoft provides. Integrating Windows 8.1 tablet hardware with the back-office software was a priority, and hardware integration was part of that. Microsoft has chosen to focus on the two main units: bar code scanners for inventory and magnetic stripe readers for handling credit cards.
Bar Code Scanners
Bar code scanners are handled much like an HID device, with a class representing a device. The BarcodeScanner
class fires a StatusUpdated
event that alerts the host that input has been received. The DataReceived
event has the data from the status call. From there, the app can decode the input and interact with the underlying retail system.
To prevent conflicts with the underlying operating system, which might have low-level access to the incoming data, Windows RT has a facility for claiming a bar code scanner. The app can populate a BarcodeScanner
object with the first available scanner by calling the static BarcodeScanner.getDefaultAsync()
method. With an instance to the BarcodeScanner
object, the app can call claimScannerAsync()
to get exclusive access to that scanner. After the scanner has been claimed, subscribing to the datareceived
event gains access to the incoming data.
After data has been received, the BarcodeStatusReport
class has the data from the scan. Like the HID standard, the PoS protocol uses the “report” model to pass data back to the app. The report has these properties:
- ScanData : . The raw data coming back from the hardware
- ScanDataLabel : . The decoded label, which is just the useful data
- ScanDataType : . As expected, this is the label type as defined in the
BarcodeSymbologies
class
Bar codes come in a number of standard symbologies, all based on International Organization for Standardization (ISO) standards. The Windows RT classes handle several different symbologies, all of which can be found in the MSDN* library.
Magnetic Stripe Readers
Not surprisingly, the MagneticStripeReader
class works largely the same as the BarcodeReader
. The GetDefaultAsync
class gets the first available MagneticStripeReader
and populates the object. The ClaimReaderAsync
method locks the selected reader for the Windows Store app and returns a ClainedMagneticStripeReader
.
The claimed magnetic stripe reader has a set of events to tell the app what kind of card is swiped. The events include:
- AamvaCardDataReceived : A motor vehicle card was swiped.
- BankCardDataReceived : A bank card was swiped.
- VendorSpecificDataReceived : Some unrecognized card was swiped.
- ErrorOccurred : An error occurred with the card.
- ReleaseDeviceRequested : The device received a request to release an exclusive claim.
After data has been received, the magnetic stripe reader API provides strongly typed objects for the data of American Association of Motor Vehicle Administrators (AAMVA) and bank card data. AAMVA cards contain:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Bank cards contain:
|
|
|
|
|
|
|
|
|
The vendor-specific event handler returns the raw data—probably a placeholder for further expansion.
One benefit of magnetic cards over optical codes is encryption. Standardized algorithms are designed into the protocols to ensure broad coverage among consuming applications. The Devices
API handles the Triple DES Derived Unique Key Per Transaction out of the box (the most common bank card algorithm) and has a spot for vendor-specific algorithms.
Working with the Super MUTT
To test code that would be using an HID or PoS device, the best solution is a Super MUTT. This simple device (shown in Figure 1) can pretend to be an HID or PoS device to prototype code.
Figure 1. The Super MUTT device
Getting started with the Super MUTT device is somewhat involved. Here’s the basic process:
- Download the MUTT software package from MSDN.
- Install the emulators by running
install.cmd
for your processor type. - Run these two commands to set up the Super MUTT to run with Windows Store apps:
Muttutil.exe –forceupdatefirmware
Muttutil.exe –setwinrthid
With that done, download the HID sample from MSDN. The sample has a lot of overhead, but the code sample in Listing 1 gives you a more straightforward look at the core HID functionality, specifically enumerating devices, then configuring and populating a numeric report.
Listing 1. Coding for core Super MUTT functionality
using System; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using Windows.ApplicationModel.Activation; using Windows.Devices.Enumeration; using Windows.Devices.HumanInterfaceDevice; using Windows.Storage; using Windows.UI.Xaml; namespace UsingTheSuperMutt { sealed partial class App : Application { public App() { this.InitializeComponent(); } protected override void OnLaunched(LaunchActivatedEventArgs e) { Window.Current.Activate(); } private async void UseTheMutt() { //Initialize the device selector with the usage page and ID, the vendor and the product ID string selector = HidDevice.GetDeviceSelector(0xFF00, 0x0001, 0x045E, 0x078F); // Enumerate devices using the selector var devices = await DeviceInformation.FindAllAsync(selector); if (devices.Count > 0) { // Open the supermutt HidDevice device = await HidDevice.FromIdAsync(devices.ElementAt(0).Id, FileAccessMode.ReadWrite); //Let's make the light blink //Get the report from the SuperMutt that represents the LED var featureReport = device.CreateFeatureReport(0x0200); // Only grab the byte we need Byte[] bytesToModify = new Byte[1]; //Copy the report WindowsRuntimeBufferExtensions.CopyTo(featureReport.Data, 0x0000, bytesToModify, 0, bytesToModify.Length); //Set the blink rate bytesToModify[0] = 0x0004; //Move the edited report WindowsRuntimeBufferExtensions.CopyTo(bytesToModify, 0, featureReport.Data, 0x0100, bytesToModify.Length); //Send it to the SuperMutt await device.SendFeatureReportAsync(featureReport); } } } }
After running this code, the light on your Super MUTT should start blinking. You can play with the bytesToModify[0]
parameter to set the blink rate and see how the report would get to the device and persist in the memory. Obviously, each device’s report locations differ by manufacturer, but this base code will get a project started. You just need to change the address locations based on the device documentation.
Conclusion
The additions to the Windows.Devices
namespace in Windows RT shows Microsoft’s commitment to new interface devices working with Windows Store apps. Microsoft is clearly focused on supporting hardware vendors and developers who are including new hardware in the Windows 8 ecosystem.
Developers of new hardware have the ability to bundle Windows Store apps with new devices, making configuration, training, and even use of devices more integrated with desktop apps. The integrated support for many HID-supported devices will make app development easier and make using the built-in Windows drivers more appealing to device developers.
Developers of retail point-of-sale software will be pleased with the integration of magstripe and bar code readers into Windows RT. These new API classes make the creation of simple PoS systems much easier, along with the new deployment model and innovative user interface.
Resources
- The manufacturer of the Super MUTT: http://www.jjgtechnologies.com
- Bar code symbologies: http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.pointofservice.barcodesymbologies
- Drivers for the Super MUTT: http://msdn.microsoft.com/en-us/library/windows/hardware/jj590752.aspx
- Super MUTT sample project: http://code.msdn.microsoft.com/windowsapps/Custom-HID-Device-Access-40c3aa8f
About the Author
Bill Sempf is a software security architect. His experience includes business and technical analysis, software design, development, testing, server management and maintenance, and security. In his 20 years of professional experience, he has participated in the creation of more than 200 applications for large and small companies, managed the software infrastructure of two Internet service providers, coded complex software in every environment imaginable, tested the security of all types of applications and APIs, and made mainframes talk to cell phones. Bill is the author of C# 5 All in One for Dummies and Windows 8 Programming with HTML5 For Dummies; coauthor of Effective Visual Studio.NET, a frequent contributor to industry magazines, and has spoken at BlackHat, CodeMash, DerbyCon, BSides, and DevEssentials.
Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and/or other countries.
Copyright © 2013 Intel Corporation. All rights reserved.
*Other names and brands may be claimed as the property of others.