xref: /freebsd/sys/dev/usb/template/usb_template_kbd.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
1399e6543SHans Petter Selasky /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
48e06491aSEdward Tomasz Napierala  * Copyright (c) 2010 Hans Petter Selasky
58e06491aSEdward Tomasz Napierala  * Copyright (c) 2018 The FreeBSD Foundation
68e06491aSEdward Tomasz Napierala  * All rights reserved.
78e06491aSEdward Tomasz Napierala  *
88e06491aSEdward Tomasz Napierala  * Portions of this software were developed by Edward Tomasz Napierala
98e06491aSEdward Tomasz Napierala  * under sponsorship from the FreeBSD Foundation.
10399e6543SHans Petter Selasky  *
11399e6543SHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
12399e6543SHans Petter Selasky  * modification, are permitted provided that the following conditions
13399e6543SHans Petter Selasky  * are met:
14399e6543SHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
15399e6543SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer.
16399e6543SHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
17399e6543SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
18399e6543SHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
19399e6543SHans Petter Selasky  *
20399e6543SHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21399e6543SHans Petter Selasky  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22399e6543SHans Petter Selasky  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23399e6543SHans Petter Selasky  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24399e6543SHans Petter Selasky  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25399e6543SHans Petter Selasky  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26399e6543SHans Petter Selasky  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27399e6543SHans Petter Selasky  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28399e6543SHans Petter Selasky  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29399e6543SHans Petter Selasky  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30399e6543SHans Petter Selasky  * SUCH DAMAGE.
31399e6543SHans Petter Selasky  */
32399e6543SHans Petter Selasky 
33399e6543SHans Petter Selasky /*
34399e6543SHans Petter Selasky  * This file contains the USB template for an USB Keyboard Device.
35399e6543SHans Petter Selasky  */
36399e6543SHans Petter Selasky 
37d2b99310SHans Petter Selasky #ifdef USB_GLOBAL_INCLUDE_FILE
38d2b99310SHans Petter Selasky #include USB_GLOBAL_INCLUDE_FILE
39d2b99310SHans Petter Selasky #else
40399e6543SHans Petter Selasky #include <sys/stdint.h>
41399e6543SHans Petter Selasky #include <sys/stddef.h>
42399e6543SHans Petter Selasky #include <sys/param.h>
43399e6543SHans Petter Selasky #include <sys/queue.h>
44399e6543SHans Petter Selasky #include <sys/types.h>
45399e6543SHans Petter Selasky #include <sys/systm.h>
46399e6543SHans Petter Selasky #include <sys/kernel.h>
47399e6543SHans Petter Selasky #include <sys/bus.h>
48399e6543SHans Petter Selasky #include <sys/module.h>
49399e6543SHans Petter Selasky #include <sys/lock.h>
50399e6543SHans Petter Selasky #include <sys/mutex.h>
51399e6543SHans Petter Selasky #include <sys/condvar.h>
52399e6543SHans Petter Selasky #include <sys/sysctl.h>
53399e6543SHans Petter Selasky #include <sys/sx.h>
54399e6543SHans Petter Selasky #include <sys/unistd.h>
55399e6543SHans Petter Selasky #include <sys/callout.h>
56399e6543SHans Petter Selasky #include <sys/malloc.h>
57399e6543SHans Petter Selasky #include <sys/priv.h>
58399e6543SHans Petter Selasky 
59399e6543SHans Petter Selasky #include <dev/usb/usb.h>
60399e6543SHans Petter Selasky #include <dev/usb/usbdi.h>
6123ab0871SHans Petter Selasky #include <dev/usb/usb_core.h>
62399e6543SHans Petter Selasky #include <dev/usb/usb_cdc.h>
638e06491aSEdward Tomasz Napierala #include <dev/usb/usb_ioctl.h>
648e06491aSEdward Tomasz Napierala #include <dev/usb/usb_util.h>
65399e6543SHans Petter Selasky 
66399e6543SHans Petter Selasky #include <dev/usb/template/usb_template.h>
67d2b99310SHans Petter Selasky #endif			/* USB_GLOBAL_INCLUDE_FILE */
68399e6543SHans Petter Selasky 
69399e6543SHans Petter Selasky enum {
708e06491aSEdward Tomasz Napierala 	KBD_LANG_INDEX,
718e06491aSEdward Tomasz Napierala 	KBD_INTERFACE_INDEX,
721ee5bed7SEdward Tomasz Napierala 	KBD_MANUFACTURER_INDEX,
738e06491aSEdward Tomasz Napierala 	KBD_PRODUCT_INDEX,
741ee5bed7SEdward Tomasz Napierala 	KBD_SERIAL_NUMBER_INDEX,
758e06491aSEdward Tomasz Napierala 	KBD_MAX_INDEX,
76399e6543SHans Petter Selasky };
77399e6543SHans Petter Selasky 
781558eec6SEdward Tomasz Napierala #define	KBD_DEFAULT_VENDOR_ID		USB_TEMPLATE_VENDOR
79d01c1c8bSEdward Tomasz Napierala #define	KBD_DEFAULT_PRODUCT_ID		0x27db
808e06491aSEdward Tomasz Napierala #define	KBD_DEFAULT_INTERFACE		"Keyboard Interface"
81d01c1c8bSEdward Tomasz Napierala #define	KBD_DEFAULT_MANUFACTURER	USB_TEMPLATE_MANUFACTURER
828e06491aSEdward Tomasz Napierala #define	KBD_DEFAULT_PRODUCT		"Keyboard Test Device"
831ee5bed7SEdward Tomasz Napierala #define	KBD_DEFAULT_SERIAL_NUMBER	"March 2008"
84399e6543SHans Petter Selasky 
858e06491aSEdward Tomasz Napierala static struct usb_string_descriptor	kbd_interface;
861ee5bed7SEdward Tomasz Napierala static struct usb_string_descriptor	kbd_manufacturer;
878e06491aSEdward Tomasz Napierala static struct usb_string_descriptor	kbd_product;
881ee5bed7SEdward Tomasz Napierala static struct usb_string_descriptor	kbd_serial_number;
89399e6543SHans Petter Selasky 
908e06491aSEdward Tomasz Napierala static struct sysctl_ctx_list		kbd_ctx_list;
91399e6543SHans Petter Selasky 
92399e6543SHans Petter Selasky /* prototypes */
93399e6543SHans Petter Selasky 
94399e6543SHans Petter Selasky static const struct usb_temp_packet_size keyboard_intr_mps = {
95399e6543SHans Petter Selasky 	.mps[USB_SPEED_LOW] = 16,
96399e6543SHans Petter Selasky 	.mps[USB_SPEED_FULL] = 16,
97399e6543SHans Petter Selasky 	.mps[USB_SPEED_HIGH] = 16,
98399e6543SHans Petter Selasky };
99399e6543SHans Petter Selasky 
100399e6543SHans Petter Selasky static const struct usb_temp_interval keyboard_intr_interval = {
101e6ee4f7dSHans Petter Selasky 	.bInterval[USB_SPEED_LOW] = 2,	/* 2 ms */
102e6ee4f7dSHans Petter Selasky 	.bInterval[USB_SPEED_FULL] = 2,	/* 2 ms */
103e6ee4f7dSHans Petter Selasky 	.bInterval[USB_SPEED_HIGH] = 5,	/* 2 ms */
104399e6543SHans Petter Selasky };
105399e6543SHans Petter Selasky 
106df142785SHans Petter Selasky /* The following HID descriptor was dumped from a HP keyboard. */
107df142785SHans Petter Selasky 
108399e6543SHans Petter Selasky static uint8_t keyboard_hid_descriptor[] = {
109399e6543SHans Petter Selasky 	0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07,
110399e6543SHans Petter Selasky 	0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01,
111399e6543SHans Petter Selasky 	0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01,
112399e6543SHans Petter Selasky 	0x75, 0x08, 0x81, 0x01, 0x95, 0x03, 0x75, 0x01,
113399e6543SHans Petter Selasky 	0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, 0x02,
114399e6543SHans Petter Selasky 	0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06,
115399e6543SHans Petter Selasky 	0x75, 0x08, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05,
116399e6543SHans Petter Selasky 	0x07, 0x19, 0x00, 0x2a, 0xff, 0x00, 0x81, 0x00,
117399e6543SHans Petter Selasky 	0xc0
118399e6543SHans Petter Selasky };
119399e6543SHans Petter Selasky 
120399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc keyboard_ep_0 = {
121399e6543SHans Petter Selasky 	.ppRawDesc = NULL,		/* no raw descriptors */
122399e6543SHans Petter Selasky 	.pPacketSize = &keyboard_intr_mps,
123399e6543SHans Petter Selasky 	.pIntervals = &keyboard_intr_interval,
124399e6543SHans Petter Selasky 	.bEndpointAddress = UE_DIR_IN,
125399e6543SHans Petter Selasky 	.bmAttributes = UE_INTERRUPT,
126399e6543SHans Petter Selasky };
127399e6543SHans Petter Selasky 
128399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc *keyboard_endpoints[] = {
129399e6543SHans Petter Selasky 	&keyboard_ep_0,
130399e6543SHans Petter Selasky 	NULL,
131399e6543SHans Petter Selasky };
132399e6543SHans Petter Selasky 
133399e6543SHans Petter Selasky static const uint8_t keyboard_raw_desc[] = {
134399e6543SHans Petter Selasky 	0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, sizeof(keyboard_hid_descriptor),
135399e6543SHans Petter Selasky 	0x00
136399e6543SHans Petter Selasky };
137399e6543SHans Petter Selasky 
138399e6543SHans Petter Selasky static const void *keyboard_iface_0_desc[] = {
139399e6543SHans Petter Selasky 	keyboard_raw_desc,
140399e6543SHans Petter Selasky 	NULL,
141399e6543SHans Petter Selasky };
142399e6543SHans Petter Selasky 
143399e6543SHans Petter Selasky static const struct usb_temp_interface_desc keyboard_iface_0 = {
144399e6543SHans Petter Selasky 	.ppRawDesc = keyboard_iface_0_desc,
145399e6543SHans Petter Selasky 	.ppEndpoints = keyboard_endpoints,
1464ffeccf1SEdward Tomasz Napierala 	.bInterfaceClass = UICLASS_HID,
1474ffeccf1SEdward Tomasz Napierala 	.bInterfaceSubClass = UISUBCLASS_BOOT,
1484ffeccf1SEdward Tomasz Napierala 	.bInterfaceProtocol = UIPROTO_BOOT_KEYBOARD,
1498e06491aSEdward Tomasz Napierala 	.iInterface = KBD_INTERFACE_INDEX,
150399e6543SHans Petter Selasky };
151399e6543SHans Petter Selasky 
152399e6543SHans Petter Selasky static const struct usb_temp_interface_desc *keyboard_interfaces[] = {
153399e6543SHans Petter Selasky 	&keyboard_iface_0,
154399e6543SHans Petter Selasky 	NULL,
155399e6543SHans Petter Selasky };
156399e6543SHans Petter Selasky 
157399e6543SHans Petter Selasky static const struct usb_temp_config_desc keyboard_config_desc = {
158399e6543SHans Petter Selasky 	.ppIfaceDesc = keyboard_interfaces,
159d008c0d7SEdward Tomasz Napierala 	.bmAttributes = 0,
160d008c0d7SEdward Tomasz Napierala 	.bMaxPower = 0,
1618e06491aSEdward Tomasz Napierala 	.iConfiguration = KBD_PRODUCT_INDEX,
162399e6543SHans Petter Selasky };
163399e6543SHans Petter Selasky 
164399e6543SHans Petter Selasky static const struct usb_temp_config_desc *keyboard_configs[] = {
165399e6543SHans Petter Selasky 	&keyboard_config_desc,
166399e6543SHans Petter Selasky 	NULL,
167399e6543SHans Petter Selasky };
168399e6543SHans Petter Selasky 
169399e6543SHans Petter Selasky static usb_temp_get_string_desc_t keyboard_get_string_desc;
170399e6543SHans Petter Selasky static usb_temp_get_vendor_desc_t keyboard_get_vendor_desc;
171399e6543SHans Petter Selasky 
1728e06491aSEdward Tomasz Napierala struct usb_temp_device_desc usb_template_kbd = {
173399e6543SHans Petter Selasky 	.getStringDesc = &keyboard_get_string_desc,
174399e6543SHans Petter Selasky 	.getVendorDesc = &keyboard_get_vendor_desc,
175399e6543SHans Petter Selasky 	.ppConfigDesc = keyboard_configs,
1761558eec6SEdward Tomasz Napierala 	.idVendor = KBD_DEFAULT_VENDOR_ID,
1771558eec6SEdward Tomasz Napierala 	.idProduct = KBD_DEFAULT_PRODUCT_ID,
178399e6543SHans Petter Selasky 	.bcdDevice = 0x0100,
179399e6543SHans Petter Selasky 	.bDeviceClass = UDCLASS_COMM,
180399e6543SHans Petter Selasky 	.bDeviceSubClass = 0,
181399e6543SHans Petter Selasky 	.bDeviceProtocol = 0,
1821ee5bed7SEdward Tomasz Napierala 	.iManufacturer = KBD_MANUFACTURER_INDEX,
1838e06491aSEdward Tomasz Napierala 	.iProduct = KBD_PRODUCT_INDEX,
1841ee5bed7SEdward Tomasz Napierala 	.iSerialNumber = KBD_SERIAL_NUMBER_INDEX,
185399e6543SHans Petter Selasky };
186399e6543SHans Petter Selasky 
187399e6543SHans Petter Selasky /*------------------------------------------------------------------------*
188399e6543SHans Petter Selasky  *      keyboard_get_vendor_desc
189399e6543SHans Petter Selasky  *
190399e6543SHans Petter Selasky  * Return values:
191399e6543SHans Petter Selasky  * NULL: Failure. No such vendor descriptor.
192399e6543SHans Petter Selasky  * Else: Success. Pointer to vendor descriptor is returned.
193399e6543SHans Petter Selasky  *------------------------------------------------------------------------*/
194399e6543SHans Petter Selasky static const void *
keyboard_get_vendor_desc(const struct usb_device_request * req,uint16_t * plen)195399e6543SHans Petter Selasky keyboard_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen)
196399e6543SHans Petter Selasky {
197399e6543SHans Petter Selasky 	if ((req->bmRequestType == 0x81) && (req->bRequest == 0x06) &&
198399e6543SHans Petter Selasky 	    (req->wValue[0] == 0x00) && (req->wValue[1] == 0x22) &&
199399e6543SHans Petter Selasky 	    (req->wIndex[1] == 0) && (req->wIndex[0] == 0)) {
200399e6543SHans Petter Selasky 		*plen = sizeof(keyboard_hid_descriptor);
201399e6543SHans Petter Selasky 		return (keyboard_hid_descriptor);
202399e6543SHans Petter Selasky 	}
203399e6543SHans Petter Selasky 	return (NULL);
204399e6543SHans Petter Selasky }
205399e6543SHans Petter Selasky 
206399e6543SHans Petter Selasky /*------------------------------------------------------------------------*
207399e6543SHans Petter Selasky  *	keyboard_get_string_desc
208399e6543SHans Petter Selasky  *
209399e6543SHans Petter Selasky  * Return values:
210399e6543SHans Petter Selasky  * NULL: Failure. No such string.
211399e6543SHans Petter Selasky  * Else: Success. Pointer to string descriptor is returned.
212399e6543SHans Petter Selasky  *------------------------------------------------------------------------*/
213399e6543SHans Petter Selasky static const void *
keyboard_get_string_desc(uint16_t lang_id,uint8_t string_index)214399e6543SHans Petter Selasky keyboard_get_string_desc(uint16_t lang_id, uint8_t string_index)
215399e6543SHans Petter Selasky {
2168e06491aSEdward Tomasz Napierala 	static const void *ptr[KBD_MAX_INDEX] = {
2178e06491aSEdward Tomasz Napierala 		[KBD_LANG_INDEX] = &usb_string_lang_en,
2188e06491aSEdward Tomasz Napierala 		[KBD_INTERFACE_INDEX] = &kbd_interface,
2191ee5bed7SEdward Tomasz Napierala 		[KBD_MANUFACTURER_INDEX] = &kbd_manufacturer,
2208e06491aSEdward Tomasz Napierala 		[KBD_PRODUCT_INDEX] = &kbd_product,
2211ee5bed7SEdward Tomasz Napierala 		[KBD_SERIAL_NUMBER_INDEX] = &kbd_serial_number,
222399e6543SHans Petter Selasky 	};
223399e6543SHans Petter Selasky 
224399e6543SHans Petter Selasky 	if (string_index == 0) {
22523ab0871SHans Petter Selasky 		return (&usb_string_lang_en);
226399e6543SHans Petter Selasky 	}
227399e6543SHans Petter Selasky 	if (lang_id != 0x0409) {
228399e6543SHans Petter Selasky 		return (NULL);
229399e6543SHans Petter Selasky 	}
2308e06491aSEdward Tomasz Napierala 	if (string_index < KBD_MAX_INDEX) {
231399e6543SHans Petter Selasky 		return (ptr[string_index]);
232399e6543SHans Petter Selasky 	}
233399e6543SHans Petter Selasky 	return (NULL);
234399e6543SHans Petter Selasky }
2358e06491aSEdward Tomasz Napierala 
2368e06491aSEdward Tomasz Napierala static void
kbd_init(void * arg __unused)2378e06491aSEdward Tomasz Napierala kbd_init(void *arg __unused)
2388e06491aSEdward Tomasz Napierala {
2398e06491aSEdward Tomasz Napierala 	struct sysctl_oid *parent;
2408e06491aSEdward Tomasz Napierala 	char parent_name[3];
2418e06491aSEdward Tomasz Napierala 
2428e06491aSEdward Tomasz Napierala 	usb_make_str_desc(&kbd_interface, sizeof(kbd_interface),
2438e06491aSEdward Tomasz Napierala 	    KBD_DEFAULT_INTERFACE);
2441ee5bed7SEdward Tomasz Napierala 	usb_make_str_desc(&kbd_manufacturer, sizeof(kbd_manufacturer),
2451ee5bed7SEdward Tomasz Napierala 	    KBD_DEFAULT_MANUFACTURER);
2468e06491aSEdward Tomasz Napierala 	usb_make_str_desc(&kbd_product, sizeof(kbd_product),
2478e06491aSEdward Tomasz Napierala 	    KBD_DEFAULT_PRODUCT);
2481ee5bed7SEdward Tomasz Napierala 	usb_make_str_desc(&kbd_serial_number, sizeof(kbd_serial_number),
2491ee5bed7SEdward Tomasz Napierala 	    KBD_DEFAULT_SERIAL_NUMBER);
2508e06491aSEdward Tomasz Napierala 
2518e06491aSEdward Tomasz Napierala 	snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_KBD);
2528e06491aSEdward Tomasz Napierala 	sysctl_ctx_init(&kbd_ctx_list);
2538e06491aSEdward Tomasz Napierala 
2548e06491aSEdward Tomasz Napierala 	parent = SYSCTL_ADD_NODE(&kbd_ctx_list,
2558e06491aSEdward Tomasz Napierala 	    SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
256f8d2b1f3SPawel Biernacki 	    parent_name, CTLFLAG_RW | CTLFLAG_MPSAFE,
2578e06491aSEdward Tomasz Napierala 	    0, "USB Keyboard device side template");
2588e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_U16(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2598e06491aSEdward Tomasz Napierala 	    "vendor_id", CTLFLAG_RWTUN,
2608e06491aSEdward Tomasz Napierala 	    &usb_template_kbd.idVendor, 1, "Vendor identifier");
2618e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_U16(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2628e06491aSEdward Tomasz Napierala 	    "product_id", CTLFLAG_RWTUN,
2638e06491aSEdward Tomasz Napierala 	    &usb_template_kbd.idProduct, 1, "Product identifier");
2648e06491aSEdward Tomasz Napierala #if 0
2658e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2668e06491aSEdward Tomasz Napierala 	    "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2678e06491aSEdward Tomasz Napierala 	    &kbd_interface, sizeof(kbd_interface), usb_temp_sysctl,
2688e06491aSEdward Tomasz Napierala 	    "A", "Interface string");
2698e06491aSEdward Tomasz Napierala #endif
2708e06491aSEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2711ee5bed7SEdward Tomasz Napierala 	    "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2721ee5bed7SEdward Tomasz Napierala 	    &kbd_manufacturer, sizeof(kbd_manufacturer), usb_temp_sysctl,
2731ee5bed7SEdward Tomasz Napierala 	    "A", "Manufacturer string");
2741ee5bed7SEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2758e06491aSEdward Tomasz Napierala 	    "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2768e06491aSEdward Tomasz Napierala 	    &kbd_product, sizeof(kbd_product), usb_temp_sysctl,
2778e06491aSEdward Tomasz Napierala 	    "A", "Product string");
2781ee5bed7SEdward Tomasz Napierala 	SYSCTL_ADD_PROC(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
2791ee5bed7SEdward Tomasz Napierala 	    "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2801ee5bed7SEdward Tomasz Napierala 	    &kbd_serial_number, sizeof(kbd_serial_number), usb_temp_sysctl,
2811ee5bed7SEdward Tomasz Napierala 	    "A", "Serial number string");
2828e06491aSEdward Tomasz Napierala }
2838e06491aSEdward Tomasz Napierala 
2848e06491aSEdward Tomasz Napierala static void
kbd_uninit(void * arg __unused)2858e06491aSEdward Tomasz Napierala kbd_uninit(void *arg __unused)
2868e06491aSEdward Tomasz Napierala {
2878e06491aSEdward Tomasz Napierala 
2888e06491aSEdward Tomasz Napierala 	sysctl_ctx_free(&kbd_ctx_list);
2898e06491aSEdward Tomasz Napierala }
2908e06491aSEdward Tomasz Napierala 
2918e06491aSEdward Tomasz Napierala SYSINIT(kbd_init, SI_SUB_LOCK, SI_ORDER_FIRST, kbd_init, NULL);
292c70e38e4SHans Petter Selasky SYSUNINIT(kbd_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, kbd_uninit, NULL);
293