3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * Copyright (c) 2010 Hans Petter Selasky
6 * Copyright (c) 2018 The FreeBSD Foundation
9 * Portions of this software were developed by Edward Tomasz Napierala
10 * under sponsorship from the FreeBSD Foundation.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * This file contains the USB template for an USB Mouse Device.
38 #ifdef USB_GLOBAL_INCLUDE_FILE
39 #include USB_GLOBAL_INCLUDE_FILE
41 #include <sys/stdint.h>
42 #include <sys/stddef.h>
43 #include <sys/param.h>
44 #include <sys/queue.h>
45 #include <sys/types.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
49 #include <sys/module.h>
51 #include <sys/mutex.h>
52 #include <sys/condvar.h>
53 #include <sys/sysctl.h>
55 #include <sys/unistd.h>
56 #include <sys/callout.h>
57 #include <sys/malloc.h>
60 #include <dev/usb/usb.h>
61 #include <dev/usb/usbdi.h>
62 #include <dev/usb/usb_core.h>
63 #include <dev/usb/usb_cdc.h>
64 #include <dev/usb/usb_ioctl.h>
65 #include <dev/usb/usb_util.h>
67 #include <dev/usb/template/usb_template.h>
68 #endif /* USB_GLOBAL_INCLUDE_FILE */
72 MOUSE_INTERFACE_INDEX,
73 MOUSE_MANUFACTURER_INDEX,
75 MOUSE_SERIAL_NUMBER_INDEX,
79 #define MOUSE_DEFAULT_VENDOR_ID USB_TEMPLATE_VENDOR
80 #define MOUSE_DEFAULT_PRODUCT_ID 0x27da
81 #define MOUSE_DEFAULT_INTERFACE "Mouse interface"
82 #define MOUSE_DEFAULT_MANUFACTURER USB_TEMPLATE_MANUFACTURER
83 #define MOUSE_DEFAULT_PRODUCT "Mouse Test Interface"
84 #define MOUSE_DEFAULT_SERIAL_NUMBER "March 2008"
86 static struct usb_string_descriptor mouse_interface;
87 static struct usb_string_descriptor mouse_manufacturer;
88 static struct usb_string_descriptor mouse_product;
89 static struct usb_string_descriptor mouse_serial_number;
91 static struct sysctl_ctx_list mouse_ctx_list;
95 /* The following HID descriptor was dumped from a HP mouse. */
97 static uint8_t mouse_hid_descriptor[] = {
98 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01,
99 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
100 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
101 0x81, 0x02, 0x95, 0x05, 0x81, 0x03, 0x05, 0x01,
102 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, 0x15, 0x81,
103 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03, 0x81, 0x06,
107 static const struct usb_temp_packet_size mouse_intr_mps = {
108 .mps[USB_SPEED_LOW] = 8,
109 .mps[USB_SPEED_FULL] = 8,
110 .mps[USB_SPEED_HIGH] = 8,
113 static const struct usb_temp_interval mouse_intr_interval = {
114 .bInterval[USB_SPEED_LOW] = 2, /* 2ms */
115 .bInterval[USB_SPEED_FULL] = 2, /* 2ms */
116 .bInterval[USB_SPEED_HIGH] = 5, /* 2ms */
119 static const struct usb_temp_endpoint_desc mouse_ep_0 = {
120 .ppRawDesc = NULL, /* no raw descriptors */
121 .pPacketSize = &mouse_intr_mps,
122 .pIntervals = &mouse_intr_interval,
123 .bEndpointAddress = UE_DIR_IN,
124 .bmAttributes = UE_INTERRUPT,
127 static const struct usb_temp_endpoint_desc *mouse_endpoints[] = {
132 static const uint8_t mouse_raw_desc[] = {
133 0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, sizeof(mouse_hid_descriptor),
137 static const void *mouse_iface_0_desc[] = {
142 static const struct usb_temp_interface_desc mouse_iface_0 = {
143 .ppRawDesc = mouse_iface_0_desc,
144 .ppEndpoints = mouse_endpoints,
145 .bInterfaceClass = UICLASS_HID,
146 .bInterfaceSubClass = UISUBCLASS_BOOT,
147 .bInterfaceProtocol = UIPROTO_MOUSE,
148 .iInterface = MOUSE_INTERFACE_INDEX,
151 static const struct usb_temp_interface_desc *mouse_interfaces[] = {
156 static const struct usb_temp_config_desc mouse_config_desc = {
157 .ppIfaceDesc = mouse_interfaces,
160 .iConfiguration = MOUSE_INTERFACE_INDEX,
163 static const struct usb_temp_config_desc *mouse_configs[] = {
168 static usb_temp_get_string_desc_t mouse_get_string_desc;
169 static usb_temp_get_vendor_desc_t mouse_get_vendor_desc;
171 struct usb_temp_device_desc usb_template_mouse = {
172 .getStringDesc = &mouse_get_string_desc,
173 .getVendorDesc = &mouse_get_vendor_desc,
174 .ppConfigDesc = mouse_configs,
175 .idVendor = MOUSE_DEFAULT_VENDOR_ID,
176 .idProduct = MOUSE_DEFAULT_PRODUCT_ID,
178 .bDeviceClass = UDCLASS_COMM,
179 .bDeviceSubClass = 0,
180 .bDeviceProtocol = 0,
181 .iManufacturer = MOUSE_MANUFACTURER_INDEX,
182 .iProduct = MOUSE_PRODUCT_INDEX,
183 .iSerialNumber = MOUSE_SERIAL_NUMBER_INDEX,
186 /*------------------------------------------------------------------------*
187 * mouse_get_vendor_desc
190 * NULL: Failure. No such vendor descriptor.
191 * Else: Success. Pointer to vendor descriptor is returned.
192 *------------------------------------------------------------------------*/
194 mouse_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen)
196 if ((req->bmRequestType == 0x81) && (req->bRequest == 0x06) &&
197 (req->wValue[0] == 0x00) && (req->wValue[1] == 0x22) &&
198 (req->wIndex[1] == 0) && (req->wIndex[0] == 0)) {
200 *plen = sizeof(mouse_hid_descriptor);
201 return (mouse_hid_descriptor);
206 /*------------------------------------------------------------------------*
207 * mouse_get_string_desc
210 * NULL: Failure. No such string.
211 * Else: Success. Pointer to string descriptor is returned.
212 *------------------------------------------------------------------------*/
214 mouse_get_string_desc(uint16_t lang_id, uint8_t string_index)
216 static const void *ptr[MOUSE_MAX_INDEX] = {
217 [MOUSE_LANG_INDEX] = &usb_string_lang_en,
218 [MOUSE_INTERFACE_INDEX] = &mouse_interface,
219 [MOUSE_MANUFACTURER_INDEX] = &mouse_manufacturer,
220 [MOUSE_PRODUCT_INDEX] = &mouse_product,
221 [MOUSE_SERIAL_NUMBER_INDEX] = &mouse_serial_number,
224 if (string_index == 0) {
225 return (&usb_string_lang_en);
227 if (lang_id != 0x0409) {
230 if (string_index < MOUSE_MAX_INDEX) {
231 return (ptr[string_index]);
237 mouse_init(void *arg __unused)
239 struct sysctl_oid *parent;
242 usb_make_str_desc(&mouse_interface, sizeof(mouse_interface),
243 MOUSE_DEFAULT_INTERFACE);
244 usb_make_str_desc(&mouse_manufacturer, sizeof(mouse_manufacturer),
245 MOUSE_DEFAULT_MANUFACTURER);
246 usb_make_str_desc(&mouse_product, sizeof(mouse_product),
247 MOUSE_DEFAULT_PRODUCT);
248 usb_make_str_desc(&mouse_serial_number, sizeof(mouse_serial_number),
249 MOUSE_DEFAULT_SERIAL_NUMBER);
251 snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_MOUSE);
252 sysctl_ctx_init(&mouse_ctx_list);
254 parent = SYSCTL_ADD_NODE(&mouse_ctx_list,
255 SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
256 parent_name, CTLFLAG_RW,
257 0, "USB Mouse device side template");
258 SYSCTL_ADD_U16(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
259 "vendor_id", CTLFLAG_RWTUN,
260 &usb_template_mouse.idVendor, 1, "Vendor identifier");
261 SYSCTL_ADD_U16(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
262 "product_id", CTLFLAG_RWTUN,
263 &usb_template_mouse.idProduct, 1, "Product identifier");
265 SYSCTL_ADD_PROC(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
266 "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
267 &mouse_interface, sizeof(mouse_interface), usb_temp_sysctl,
268 "A", "Interface string");
270 SYSCTL_ADD_PROC(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
271 "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
272 &mouse_manufacturer, sizeof(mouse_manufacturer), usb_temp_sysctl,
273 "A", "Manufacturer string");
274 SYSCTL_ADD_PROC(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
275 "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
276 &mouse_product, sizeof(mouse_product), usb_temp_sysctl,
277 "A", "Product string");
278 SYSCTL_ADD_PROC(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
279 "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
280 &mouse_serial_number, sizeof(mouse_serial_number), usb_temp_sysctl,
281 "A", "Serial number string");
285 mouse_uninit(void *arg __unused)
288 sysctl_ctx_free(&mouse_ctx_list);
291 SYSINIT(mouse_init, SI_SUB_LOCK, SI_ORDER_FIRST, mouse_init, NULL);
292 SYSUNINIT(mouse_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, mouse_uninit, NULL);