Drivers LXD Input Devices
When LXD 2.0 shipped with Ubuntu 16.04, LXD networking was pretty simple. You could either use that “lxdbr0” bridge that “lxd init” would have you configure, provide your own or just use an existing physical interface for your containers. The aptpackage of LXD is already available in the Ubuntu 18.04.2 image, found in the Windows Store. However, the LXD service is not running by default and we will to start it. Ubuntu@DESKTOP-WSL2:$ sudo service lxd start. Now we can run sudo lxd initto configure LXD. We accept the defaults (btrfs storage driver, 50GB default storage). Windows may install drivers for select devices, say the graphics card, under certain circumstances. This happens by default for instance when the device is setup, but may also happen when Microsoft pushes driver updates through Windows Updates.
LXD supports the following network types:
LXD supports creating and managing storage pools and storage volumes. General keys are top-level. Driver specific keys are namespaced by driver name. Volume keys apply to any volume created in the pool unless the value is overridden on a per-volume basis. To find drivers for hardware that Windows refuses to recognize, open Device Manager (a search from the Start menu or Windows 8 Start screen brings it up lickity-split), right-click on the listing.
- bridge: Creates an L2 bridge for connecting instances to (can provide local DHCP and DNS). This is the default.
- macvlan: Provides preset configuration to use when connecting instances to a parent macvlan interface.
- sriov: Provides preset configuration to use when connecting instances to a parent SR-IOV interface.
- ovn: Creates a logical network using the OVN software defined networking system.
- physical: Provides preset configuration to use when connecting OVN networks to a parent interface.
The desired type can be specified using the --type
argument, e.g.
If no --type
argument is specified, the default type of bridge
is used.
The configuration keys are namespaced with the following namespaces currently supported for all network types:
maas
(MAAS network identification)user
(free form key/value for user metadata)
network: bridge
As one of the possible network configuration types under LXD, LXD supports creating and managing network bridges.LXD bridges can leverage underlying native Linux bridges and Open vSwitch.
Creation and management of LXD bridges is performed via the lxc network
command.A bridge created by LXD is by default 'managed' which means that LXD also will additionally set up a local dnsmasq
DHCP server and if desired also perform NAT for the bridge (this is the default.)
When a bridge is managed by LXD, configuration values under the bridge
namespace can be used to configure it.
Additionally, LXD can utilize a pre-existing Linux bridge. In this case, the bridge does not need to be created vialxc network
and can simply be referenced in an instance or profile device configuration as follows:
Network configuration properties:
A complete list of configuration settings for LXD networks can be found below.
The following configuration key namespaces are currently supported for bridge networks:
bridge
(L2 interface configuration)fan
(configuration specific to the Ubuntu FAN overlay)tunnel
(cross-host tunneling configuration)ipv4
(L3 IPv4 configuration)ipv6
(L3 IPv6 configuration)dns
(DNS server and resolution configuration)raw
(raw configuration file content)
It is expected that IP addresses and subnets are given using CIDR notation (1.1.1.1/24
or fd80:1234::1/64
).
The exception being tunnel local and remote addresses which are just plain addresses (1.1.1.1
or fd80:1234::1
).
Key | Type | Condition | Default | Description |
---|---|---|---|---|
bridge.driver | string | - | native | Bridge driver ('native' or 'openvswitch') |
bridge.external_interfaces | string | - | - | Comma separate list of unconfigured network interfaces to include in the bridge |
bridge.hwaddr | string | - | - | MAC address for the bridge |
bridge.mode | string | - | standard | Bridge operation mode ('standard' or 'fan') |
bridge.mtu | integer | - | 1500 | Bridge MTU (default varies if tunnel or fan setup) |
dns.domain | string | - | lxd | Domain to advertise to DHCP clients and use for DNS resolution |
dns.mode | string | - | managed | DNS registration mode ('none' for no DNS record, 'managed' for LXD generated static records or 'dynamic' for client generated records) |
dns.search | string | - | - | Full comma separated domain search list, defaulting to dns.domain value |
fan.overlay_subnet | string | fan mode | 240.0.0.0/8 | Subnet to use as the overlay for the FAN (CIDR notation) |
fan.type | string | fan mode | vxlan | The tunneling type for the FAN ('vxlan' or 'ipip') |
fan.underlay_subnet | string | fan mode | auto (on create only) | Subnet to use as the underlay for the FAN (CIDR notation). Use 'auto' to use default gateway subnet |
ipv4.address | string | standard mode | auto (on create only) | IPv4 address for the bridge (CIDR notation). Use 'none' to turn off IPv4 or 'auto' to generate a new random unused subnet |
ipv4.dhcp | boolean | ipv4 address | true | Whether to allocate addresses using DHCP |
ipv4.dhcp.expiry | string | ipv4 dhcp | 1h | When to expire DHCP leases |
ipv4.dhcp.gateway | string | ipv4 dhcp | ipv4.address | Address of the gateway for the subnet |
ipv4.dhcp.ranges | string | ipv4 dhcp | all addresses | Comma separated list of IP ranges to use for DHCP (FIRST-LAST format) |
ipv4.firewall | boolean | ipv4 address | true | Whether to generate filtering firewall rules for this network |
ipv4.nat.address | string | ipv4 address | - | The source address used for outbound traffic from the bridge |
ipv4.nat | boolean | ipv4 address | false | Whether to NAT (defaults to true for regular bridges where ipv4.address is generated and always defaults to true for fan bridges) |
ipv4.nat.order | string | ipv4 address | before | Whether to add the required NAT rules before or after any pre-existing rules |
ipv4.ovn.ranges | string | - | - | Comma separate list of IPv4 ranges to use for child OVN network routers (FIRST-LAST format) |
ipv4.routes | string | ipv4 address | - | Comma separated list of additional IPv4 CIDR subnets to route to the bridge |
ipv4.routing | boolean | ipv4 address | true | Whether to route traffic in and out of the bridge |
ipv6.address | string | standard mode | auto (on create only) | IPv6 address for the bridge (CIDR notation). Use 'none' to turn off IPv6 or 'auto' to generate a new random unused subnet |
ipv6.dhcp | boolean | ipv6 address | true | Whether to provide additional network configuration over DHCP |
ipv6.dhcp.expiry | string | ipv6 dhcp | 1h | When to expire DHCP leases |
ipv6.dhcp.ranges | string | ipv6 stateful dhcp | all addresses | Comma separated list of IPv6 ranges to use for DHCP (FIRST-LAST format) |
ipv6.dhcp.stateful | boolean | ipv6 dhcp | false | Whether to allocate addresses using DHCP |
ipv6.firewall | boolean | ipv6 address | true | Whether to generate filtering firewall rules for this network |
ipv6.nat.address | string | ipv6 address | - | The source address used for outbound traffic from the bridge |
ipv6.nat | boolean | ipv6 address | false | Whether to NAT (will default to true if unset and a random ipv6.address is generated) |
ipv6.nat.order | string | ipv6 address | before | Whether to add the required NAT rules before or after any pre-existing rules |
ipv6.ovn.ranges | string | - | - | Comma separate list of IPv6 ranges to use for child OVN network routers (FIRST-LAST format) |
ipv6.routes | string | ipv6 address | - | Comma separated list of additional IPv6 CIDR subnets to route to the bridge |
ipv6.routing | boolean | ipv6 address | true | Whether to route traffic in and out of the bridge |
maas.subnet.ipv4 | string | ipv4 address | - | MAAS IPv4 subnet to register instances in (when using network property on nic) |
maas.subnet.ipv6 | string | ipv6 address | - | MAAS IPv6 subnet to register instances in (when using network property on nic) |
raw.dnsmasq | string | - | - | Additional dnsmasq configuration to append to the configuration file |
tunnel.NAME.group | string | vxlan | 239.0.0.1 | Multicast address for vxlan (used if local and remote aren't set) |
tunnel.NAME.id | integer | vxlan | 0 | Specific tunnel ID to use for the vxlan tunnel |
tunnel.NAME.interface | string | vxlan | - | Specific host interface to use for the tunnel |
tunnel.NAME.local | string | gre or vxlan | - | Local address for the tunnel (not necessary for multicast vxlan) |
tunnel.NAME.port | integer | vxlan | 0 | Specific port to use for the vxlan tunnel |
tunnel.NAME.protocol | string | standard mode | - | Tunneling protocol ('vxlan' or 'gre') |
tunnel.NAME.remote | string | gre or vxlan | - | Remote address for the tunnel (not necessary for multicast vxlan) |
tunnel.NAME.ttl | integer | vxlan | 1 | Specific TTL to use for multicast routing topologies |
Those keys can be set using the lxc tool with:
Integration with systemd-resolved
If the system running LXD uses systemd-resolved to perform DNSlookups, it's possible to notify resolved of the domain(s) thatLXD is able to resolve. This requires telling resolved thespecific bridge(s), nameserver address(es), and dns domain(s).
For example, if LXD is using the lxdbr0
interface, get theipv4 address with lxc network get lxdbr0 ipv4.address
command(the ipv6 can be used instead or in addition), and the domainwith lxc network get lxdbr0 dns.domain
(if unset, the domainis lxd
as shown in the table above). Then notify resolved:
Replace lxdbr0
with the actual bridge name, and 1.2.3.4
withthe actual address of the nameserver (without the subnet netmask).
Also replace lxd
with the domain name. Note the ~
before thedomain name is important; it tells resolved to use thisnameserver to look up only this domain; no matter what youractual domain name is, you should prefix it with ~
. Also,since the shell may expand the ~
character, you may need toinclude it in quotes.
In newer releases of systemd, the systemd-resolve
command has beendeprecated, however it is still provided for backwards compatibility(as of this writing). The newer method to notify resolved is usingthe resolvectl
command, which would be done in two steps:
This resolved configuration will persist as long as the bridgeexists, so you must repeat this command each reboot and afterLXD is restarted. Also note this only works if the bridgedns.mode
is not none
.
Note that depending on the dns.domain
used, you may need to disableDNSSEC in resolved to allow for DNS resolution. This can be done throughthe DNSSEC
option in resolved.conf
.
IPv6 prefix size
For optimal operation, a prefix size of 64 is preferred.Larger subnets (prefix smaller than 64) should work properly too butaren't typically that useful for SLAAC.
Smaller subnets while in theory possible when using stateful DHCPv6 forIPv6 allocation aren't properly supported by dnsmasq and may be thesource of issue. If you must use one of those, static allocation oranother standalone RA daemon be used.
Allow DHCP, DNS with Firewalld
In order to allow instances to access the DHCP and DNS server that LXD runs on the host when using firewalldyou need to add the host's bridge interface to the trusted
zone in firewalld.
To do this permanently (so that it persists after a reboot) run the following command:
E.g. for a bridged network called lxdbr0
run the command:
This will then allow LXD's own firewall rules to take effect.
How to let Firewalld control the LXD's iptables rules
When using firewalld and LXD together, iptables rules can overlaps. For example, firewalld could erase LXD iptables rules if it is started after LXD daemon, then LXD container will not be able to do any oubound internet access.One way to fix it is to delegate to firewalld the LXD's iptables rules and to disable the LXD ones.
First step is to allow DNS and DHCP.
Then to tell to LXD totally stop to set iptables rules (because firewalld will do it):
Finally, to enable iptables firewalld's rules for LXD usecase (in this example, we suppose the bridge interface is lxdbr0
and the associated IP range is 10.0.0.0/24
:
To check the rules are taken into account by firewalld:
Warning: what is exposed above is not a fool-proof approach and may end up inadvertently introducing a security risk.
network: macvlan
The macvlan network type allows one to specify presets to use when connecting instances to a parent interfaceusing macvlan NICs. This allows the instance NIC itself to simply specify the network
it is connecting to withoutknowing any of the underlying configuration details.
Network configuration properties:
Key | Type | Condition | Default | Description |
---|---|---|---|---|
maas.subnet.ipv4 | string | ipv4 address | - | MAAS IPv4 subnet to register instances in (when using network property on nic) |
maas.subnet.ipv6 | string | ipv6 address | - | MAAS IPv6 subnet to register instances in (when using network property on nic) |
mtu | integer | - | - | The MTU of the new interface |
parent | string | - | - | Parent interface to create macvlan NICs on |
vlan | integer | - | - | The VLAN ID to attach to |
network: sriov
The sriov network type allows one to specify presets to use when connecting instances to a parent interfaceusing sriov NICs. This allows the instance NIC itself to simply specify the network
it is connecting to withoutknowing any of the underlying configuration details.
Network configuration properties:
Key | Type | Condition | Default | Description |
---|---|---|---|---|
maas.subnet.ipv4 | string | ipv4 address | - | MAAS IPv4 subnet to register instances in (when using network property on nic) |
maas.subnet.ipv6 | string | ipv6 address | - | MAAS IPv6 subnet to register instances in (when using network property on nic) |
mtu | integer | - | - | The MTU of the new interface |
parent | string | - | - | Parent interface to create sriov NICs on |
vlan | integer | - | - | The VLAN ID to attach to |
network: ovn
The ovn network type allows the creation of logical networks using the OVN SDN. This can be useful for labs andmulti-tenant environments where the same logical subnets are used in multiple discrete networks.
A LXD OVN network can be connected to an existing managed LXD bridge network in order for it to gain outboundaccess to the wider network. All connections from the OVN logical networks are NATed to a dynamic IP allocated bythe parent network.
Standalone LXD OVN setup
This will create a standalone OVN network that is connected to the parent network lxdbr0 for outbound connectivity.
Install the OVN tools and configure the OVN integration bridge on the local node:
Create an OVN network and an instance using it:
Key | Type | Condition | Default | Description |
---|---|---|---|---|
bridge.hwaddr | string | - | - | MAC address for the bridge |
bridge.mtu | integer | - | 1442 | Bridge MTU (default allows host to host geneve tunnels) |
dns.domain | string | - | lxd | Domain to advertise to DHCP clients and use for DNS resolution |
dns.search | string | - | - | Full comma separated domain search list, defaulting to dns.domain value |
ipv4.address | string | standard mode | auto (on create only) | IPv4 address for the bridge (CIDR notation). Use 'none' to turn off IPv4 or 'auto' to generate a new random unused subnet |
ipv4.dhcp | boolean | ipv4 address | true | Whether to allocate addresses using DHCP |
ipv4.nat | boolean | ipv4 address | false | Whether to NAT (will default to true if unset and a random ipv4.address is generated) |
ipv6.address | string | standard mode | auto (on create only) | IPv6 address for the bridge (CIDR notation). Use 'none' to turn off IPv6 or 'auto' to generate a new random unused subnet |
ipv6.dhcp | boolean | ipv6 address | true | Whether to provide additional network configuration over DHCP |
ipv6.dhcp.stateful | boolean | ipv6 dhcp | false | Whether to allocate addresses using DHCP |
ipv6.nat | boolean | ipv6 address | false | Whether to NAT (will default to true if unset and a random ipv6.address is generated) |
network | string | - | - | Uplink network to use for external network access |
network: physical
The physical network type allows one to specify presets to use when connecting OVN networks to a parent interface.
Network configuration properties:
Key | Type | Condition | Default | Description |
---|---|---|---|---|
maas.subnet.ipv4 | string | ipv4 address | - | MAAS IPv4 subnet to register instances in (when using network property on nic) |
maas.subnet.ipv6 | string | ipv6 address | - | MAAS IPv6 subnet to register instances in (when using network property on nic) |
mtu | integer | - | - | The MTU of the new interface |
parent | string | - | - | Parent interface to create sriov NICs on |
vlan | integer | - | - | The VLAN ID to attach to |
ipv4.gateway | string | standard mode | - | IPv4 address for the gateway and network (CIDR notation) |
ipv4.ovn.ranges | string | - | - | Comma separate list of IPv4 ranges to use for child OVN network routers (FIRST-LAST format) |
ipv4.routes | string | ipv4 address | - | Comma separated list of additional IPv4 CIDR subnets that can be used with child OVN networks ipv4.routes.external setting |
ipv4.routes.anycast | boolean | ipv4 address | false | Allow the overlapping routes to be used on multiple networks/NIC at the same time. |
ipv6.gateway | string | standard mode | - | IPv6 address for the gateway and network (CIDR notation) |
ipv6.ovn.ranges | string | - | - | Comma separate list of IPv6 ranges to use for child OVN network routers (FIRST-LAST format) |
ipv6.routes | string | ipv6 address | - | Comma separated list of additional IPv6 CIDR subnets that can be used with child OVN networks ipv6.routes.external setting |
ipv6.routes.anycast | boolean | ipv6 address | false | Allow the overlapping routes to be used on multiple networks/NIC at the same time. |
dns.nameservers | string | standard mode | - | List of DNS server IPs on physical network |
ovn.ingress_mode | string | standard mode | l2proxy | Sets the method that OVN NIC external IPs will be advertised on uplink network. Either l2proxy (proxy ARP/NDP) or routed . |
Non-HID keyboards and mice can connect over multiple legacy buses but still use the same class driver. This section contains details on the class drivers themselves. The following sections goes into details on the controllers.
This topic describes the typical physical configuration of keyboard and mouse devices in Microsoft Windows 2000 and later.
The following figures show two common configurations that employ a single keyboard and a single mouse.
The figure on the left shows a keyboard and a mouse connected to a system bus through independent controllers. A typical configuration consists of a PS/2-style keyboard operated through an i8042 controller, and a serial-style mouse operated through a serial port controller.
The following additional information is important for keyboard and mice manufactures:
- Keyboards are opened in exclusive mode by the operating system stack for security reasons
- Windows supports the simultaneous connection of more than one keyboard and mouse device.
- Windows does not support independent access by a client to each device.
Class driver features
This topic describes the features of the following Microsoft Windows 2000 and later system class drivers:
Kbdclass, the class driver for devices of GUID_CLASS_KEYBOARD device class
Mouclass, the class driver for devices of GUID_CLASS_MOUSE device class
Kbdclass implements the Kbdclass service and its executable image is kbdclass.sys.
Mouclass implements the Mouclass service and its executable image is mouclass.sys.
Kbdclass and Mouclass each feature:
Generic and hardware-independent operation of the device class.
Plug and Play, power management, and Windows Management Instrumentation (WMI).
Operation of legacy devices.
Simultaneous operation of more than one device.
Connection of a class service callback routine that a function driver uses to transfer data from the input data buffer of the device to the data buffer of the class driver.
Configuration of device objects
The following figure shows the configuration of device objects for a Plug and Play PS/2-style keyboard and mouse device. Each class driver creates an upper-level class filter device object (filter DO) that is attached to a function device object (FDO) through an optional upper-level device filter DO. An upper-level device filter driver creates the upper-level device filter DO. I8042prt creates the function DO and attaches it to a physical device object (PDO) created by the root bus driver.
PS/2 Keyboard
The keyboard driver stack consists of the following.
- Kbdclass, the upper-level keyboard class filter driver
- One or more optional upper-level keyboard filter driver
- I8042prt, the function driver
PS/2 Mouse
The mouse driver stack consists of the following.
- Mouclass, the upper-level mouse class filter driver
- One or more optional upper-level mouse filter driver
- I8042prt, the function driver
Kbdclass and Mouclass can support more than one device in two different modes. In the one-to-one mode, each device has an independent device stack. The class driver creates and attaches an independent class DO to each device stack. Each device stack has its own control state and input buffer. The Microsoft Win32 subsystem accesses input from each device through a unique file object.
In the grandmaster mode, the class driver operates all the devices in the following way:
The class driver creates both a grandmaster class DO that represents all of the devices and a subordinate class DO for each device.
The class driver attaches a subordinate class DO to each device stack. Below the subordinate class DO, the device stack is same as that created in the one-to-one mode.
The grandmaster class DO controls the operation of all the subordinate DOs.
The Win32 subsystem accesses all device input through the file object that represents the grandmaster class device.
All device input is buffered in the grandmaster's data queue.
The grandmaster maintains a single global device state.
Kbdclass and Mouclass operate in the one-to-one mode if their registry entry value ConnectMultiplePorts is set to 0x00 (under the key HKLMServicesCurrentControlSet<class service>Parameters, where class service is Kbdclass or Mouclass). Otherwise Kbdclass and Mouclass operate in grandmaster mode.
Open and close via the class driver
The Microsoft Win32 subsystem opens all keyboard and mouse devices for its exclusive use. For each device class, the Win32 subsystem treats input from all the devices as if the input came from a single input device. An application cannot request to receive input from only one particular device.
The Win32 subsystem dynamically opens Plug and Play input devices after it receives notification from the Plug and Play manager that a GUID_CLASS_KEYBOARD or GUID_CLASS_MOUSE device interface is enabled. The Win32 subsystem closes Plug and Play devices after it receives notification that an opened interface is disabled. The Win32 subsystem also opens legacy devices by name (for example, 'DeviceKeyboardLegacyClass0'). Note that once the Win32 subsystem successfully opens a legacy device, it cannot determine if the device is later physically removed.
After Kbdclass and Mouclass receive a create request they do the following for Plug and Play and legacy operation:
Plug and Play Operation
If the device is in the Plug and Play started state, the class driver sends the IRP_MJ_CREATE request down the driver stack. Otherwise the class driver completes the request without sending the request down the driver stack. The class driver sets the trusted file that has read access to the device. If there is a grandmaster device, the class driver sends a create request to all the ports that are associated with the subordinate class devices.
Legacy Operation
The class driver sends an internal device control request to the port driver to enable the device.
Connect a service callback to a device
The class drivers must connect their class service to a device before the device can be opened. The class drivers connect their class service after they attach a class DO to a device stack. The function driver uses the class service callback to transfer input data from a device to the class data queue for the device. The function driver's ISR dispatch completion routine for a device calls the class service callback. Kbdclass provides the class service callback KeyboardClassServiceCallback, and Mouclass provides the class service callback MouseClassServiceCallback.
A vendor can modify the operation of a class service callback by installing an upper-level filter driver for a device. The sample keyboard filter driver Kbfiltr defines the KbFilter_ServiceCallback callback, and the sample mouse filter driver Moufiltr defines the MouFilter_ServiceCallback callback. The sample filter service callbacks can be configured to modify the input data that is transferred from the port input buffer for a device to the class data queue. For example, the filter service callback can delete, transform, or insert data.
The class and filter service callbacks are connected in the following way:
The class driver sends an internal device connect request down the device stack (IOCTL_INTERNAL_KEYBOARD_CONNECT or IOCTL_INTERNAL_MOUSE_CONNECT). The class connect data is specified by a CONNECT_DATA structure that includes a pointer to the class device object, and a pointer to the class service callback.
After the filter driver receives the connect request, it saves a copy of the class connect data, and replaces the request's connect data with filter connect data. The filter connect data specifies a pointer to the filter device object and a pointer to the filter driver service callback. The filter driver then sends the filtered connect request to the function driver.
The class and filter service callbacks are called in the following way:
The function driver uses the filter connect data to make the initial callback to the filter service callback.
After filtering the input data, the filter service callback uses the class connect data that it saved to make a callback to the class service callback.
Query and set a keyboard device
I8042prt supports the following internal device control requests to query information about a keyboard device, and to set parameters on a keyboard device:
For more information about all keyboard device control requests, see Human Interface Devices Reference.
Scan code mapper for keyboards
In Microsoft Windows operating systems, PS/2-compatible scan codes provided by an input device are converted into virtual keys, which are propagated through the system in the form of Windows messages. If a device produces an incorrect scan code for a certain key, the wrong virtual key message will be sent. This can be fixed by writing a filter driver that analyzes the scan codes generated by firmware and modifies the incorrect scan code to one understood by the system. However, this is a tedious process and can sometimes lead to severe problems, if errors exist in the kernel-level filter driver.
Windows 2000 and Windows XP include a new Scan Code Mapper, which provides a method that allows for mapping of scan codes. The scan code mappings for Windows are stored in the following registry key:
Note There is also a Keyboard Layouts key (notice the plural form) under the Control key, but that key should not be modified.
In the Keyboard Layout key, the Scancode Map value must be added. This value is of type REG_BINARY (little Endian format) and has the data format specified in the following table.
Drivers Lxd Input Devices Input
Start offset (in bytes) | Size (in bytes) | Data |
---|---|---|
0 | 4 | Header: Version Information |
4 | 4 | Header: Flags |
8 | 4 | Header: Number of Mappings |
12 | 4 | Individual Mapping |
... | ... | ... |
Last 4 bytes | 4 | Null Terminator (0x00000000) |
The first and second DWORDS store header information and should be set to all zeroes for the current version of the Scan Code Mapper. The third DWORD entry holds a count of the total number of mappings that follow, including the null terminating mapping. The minimum count would therefore be 1 (no mappings specified). The individual mappings follow the header. Each mapping is one DWORD in length and is divided into two WORD length fields. Each WORD field stores the scan code for a key to be mapped.
Once the map is stored in the registry, the system must be rebooted for the mappings to take effect. Note that if the mapping of a scan code is necessary on a keypress, the step is performed in user mode just before the scan code is converted to a virtual key. Doing this conversion in user mode can present certain limitations, such as mapping not working correctly when running under Terminal Services.
To remove these mappings, remove the Scancode Map registry value and reboot.
Example 1
The following presents an example. To swap the left CTRL key with the CAPS LOCK key, use a registry editor (preferably Regedt32.exe) to modify the Scancode Map key with the following value:
The following table contains these entries broken into DWORD fields and the bytes swapped.
Value: Interpretation
0x00000000: Header: Version. Set to all zeroes.
Drivers LXD Input Devices
0x00000000: Header: Flags. Set to all zeroes.
0x00000003: Three entries in the map (including null entry).
0x001D003A: Left CTRL key --> CAPS LOCK (0x1D --> 0x3A).
0x003A001D: CAPS LOCK --> Left CTRL key (0x3A --> 0x1D).
0x00000000: Null terminator.
Example 2
It is also possible to add a key not generally available on a keyboard or to remove a key that is never used. The following example shows the value stored in Scancode Map to remove the right CTRL key and change the functionality of the right ALT key to work as a mute key:
The following table contains these entries broken into DWORD fields and the bytes swapped.
Value: Interpretation
0x00000000: Header: Version. Set to all zeroes.
0x00000000: Header: Flags. Set to all zeroes.
0x00000003: Three entries in the map (including null entry).
0xE01D0000: Remove the right CTRL key (0xE01D --> 0x00).
0xE038E020: Right ALT key --> Mute key (0xE038 --> 0xE020).
0x00000000: Null terminator.
After the necessary data is generated, it can be inserted into the registry in several ways.
- A .reg file can be generated that can be easily incorporated into the system registry using a registry editor.
- An .inf file can also be created with an [AddReg] section that contains the registry information to be added.
- Regedt32.exe can be used to manually add the information to the registry.
The Scan Code Mapper has several advantages and disadvantages.
The advantages include:
- The Mapper can be used as an easy fix to correct firmware errors.
- Frequently used keys can be added to the keyboard by modifying the map in registry. Keys that aren't often used (for example, right CTRL key) can be mapped to null (removed) or exchanged for other keys.
- Key locations can be altered easily. Users can easily customize the location of frequently used keys for their benefit.
The following disadvantages are recognized:
- Once the map is stored in the registry, a system reboot is required to activate it.
- The mappings stored in the registry work at system level and apply to all users. These mappings cannot be set to work differently depending on the current user.
- The current implementation restricts the functionality of the map such that mappings always apply to all keyboards connected to the system. It is not currently possible to create a map on a per-keyboard basis.
Query a mouse device
I8042prt supports the following internal device control request to query information about a mouse device:
For more information about all mouse device control requests, see Human Interface Devices Reference.
Registry settings associated with mouse class driver
The following is a list of registry keys associated with the mouse class driver.
[Key: HKLMSYSTEMCurrentControlSetServicesMouclassParameters]
- MaximumPortsServiced – Not used on Windows XP and later. Only for Windows NT4.
- PointerDeviceBaseName – Specifies the base name for the device objects created by the mouse class device driver
- ConnectMultiplePorts – Determines whether there is one or more than one port device object for each class device object. This entry is used primarily by device drivers.
- MouseDataQueueSize - Specifies the number of mouse events buffered by the mouse driver. It also is used in calculating the size of the mouse driver's internal buffer in the nonpaged memory pool.
Absolute pointing devices
For devices of type GUID_CLASS_MOUSE, a device's function driver:
Handles device-specific input.
Creates the MOUSE_INPUT_DATA structures required by MouseClassServiceCallback.
Transfers MOUSE_INPUT_DATA structures to the Mouclass data queue by calling MouseClassServiceCallback in its ISR dispatch completion routine.
For an absolute pointing device, the device's function driver must set the LastX, LastY, and Flags members of the MOUSE_INPUT_DATA structures in the following way:
Drivers Lxd Input Devices Interface
In addition to dividing the device input value by the maximum capability of the device, the driver scales the device input value by 0xFFFF:
The driver sets the MOUSE_MOVE_ABSOLUTE flag in Flags.
If the input should be mapped by Window Manager to an entire virtual desktop, the driver sets the MOUSE_VIRTUAL_DESKTOP flag in Flags. If the MOUSE_VIRTUAL_DESKTOP flag is not set, Window Manager maps the input to only the primary monitor.
The following specifies, by type of device, how these special requirements for an absolute pointing device are implemented:
Drivers Lxd Input Devices Device
HID devices:
Mouhid, the Windows function driver for HID mouse devices, implements these special requirements automatically.
PS/2-style devices:
An upper-level filter driver is required. The filter driver supplies an IsrHook callback and a class service callback. I8042prt calls the IsrHook to handle raw device input, and calls the filter class service callback to filter the input. The filter class service callback, in turn, calls MouseClassServiceCallback. The combination of the IsrHook callback and the class service callback handles device-specific input, creates the required MOUSE_INPUT_DATA structures, scales the device input data, and sets the MOUSE_MOVE_ABSOLUTE flag.
Plug and Play COM port devices that are enumerated by Serenum:
A Plug and Play function driver is required. The function driver creates the required MOUSE_INPUT_DATA structures, scales the device input data, and sets the MOUSE_MOVE_ABSOLUTE flag before it calls MouseClassServiceCallback.
Non-Plug and Play COM port devices:
A device-specific function driver is required. The function driver creates the required MOUSE_INPUT_DATA structures, scales the device input data, and sets the MOUSE_MOVE_ABSOLUTE flag before it calls MouseClassServiceCallback.
Device on an unsupported bus:
A device-specific function driver is required. The function driver creates the required MOUSE_INPUT_DATA structures, scales the device input data, and sets the MOUSE_MOVE_ABSOLUTE flag before it calls MouseClassServiceCallback.