FreeBSD kernel usb device Code
usb_template_mouse.c
Go to the documentation of this file.
1/* $FreeBSD$ */
2/*-
3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 *
5 * Copyright (c) 2010 Hans Petter Selasky
6 * Copyright (c) 2018 The FreeBSD Foundation
7 * All rights reserved.
8 *
9 * Portions of this software were developed by Edward Tomasz Napierala
10 * under sponsorship from the FreeBSD Foundation.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
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.
20 *
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
31 * SUCH DAMAGE.
32 */
33
34/*
35 * This file contains the USB template for an USB Mouse Device.
36 */
37
38#ifdef USB_GLOBAL_INCLUDE_FILE
39#include USB_GLOBAL_INCLUDE_FILE
40#else
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>
48#include <sys/bus.h>
49#include <sys/module.h>
50#include <sys/lock.h>
51#include <sys/mutex.h>
52#include <sys/condvar.h>
53#include <sys/sysctl.h>
54#include <sys/sx.h>
55#include <sys/unistd.h>
56#include <sys/callout.h>
57#include <sys/malloc.h>
58#include <sys/priv.h>
59
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>
66
68#endif /* USB_GLOBAL_INCLUDE_FILE */
69
70enum {
77};
78
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"
85
90
91static struct sysctl_ctx_list mouse_ctx_list;
92
93/* prototypes */
94
95/* The following HID descriptor was dumped from a HP mouse. */
96
97static 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,
104 0xc0, 0xc0
105};
106
108 .mps[USB_SPEED_LOW] = 8,
109 .mps[USB_SPEED_FULL] = 8,
110 .mps[USB_SPEED_HIGH] = 8,
111};
112
114 .bInterval[USB_SPEED_LOW] = 2, /* 2ms */
115 .bInterval[USB_SPEED_FULL] = 2, /* 2ms */
116 .bInterval[USB_SPEED_HIGH] = 5, /* 2ms */
117};
118
119static 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,
125};
126
127static const struct usb_temp_endpoint_desc *mouse_endpoints[] = {
128 &mouse_ep_0,
129 NULL,
130};
131
132static const uint8_t mouse_raw_desc[] = {
133 0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, sizeof(mouse_hid_descriptor),
134 0x00
135};
136
137static const void *mouse_iface_0_desc[] = {
139 NULL,
140};
141
144 .ppEndpoints = mouse_endpoints,
145 .bInterfaceClass = UICLASS_HID,
146 .bInterfaceSubClass = UISUBCLASS_BOOT,
147 .bInterfaceProtocol = UIPROTO_MOUSE,
148 .iInterface = MOUSE_INTERFACE_INDEX,
149};
150
153 NULL,
154};
155
158 .bmAttributes = 0,
159 .bMaxPower = 0,
160 .iConfiguration = MOUSE_INTERFACE_INDEX,
161};
162
163static const struct usb_temp_config_desc *mouse_configs[] = {
165 NULL,
166};
167
170
173 .getVendorDesc = &mouse_get_vendor_desc,
174 .ppConfigDesc = mouse_configs,
175 .idVendor = MOUSE_DEFAULT_VENDOR_ID,
176 .idProduct = MOUSE_DEFAULT_PRODUCT_ID,
177 .bcdDevice = 0x0100,
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,
184};
185
186/*------------------------------------------------------------------------*
187 * mouse_get_vendor_desc
188 *
189 * Return values:
190 * NULL: Failure. No such vendor descriptor.
191 * Else: Success. Pointer to vendor descriptor is returned.
192 *------------------------------------------------------------------------*/
193static const void *
195{
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)) {
199 *plen = sizeof(mouse_hid_descriptor);
200 return (mouse_hid_descriptor);
201 }
202 return (NULL);
203}
204
205/*------------------------------------------------------------------------*
206 * mouse_get_string_desc
207 *
208 * Return values:
209 * NULL: Failure. No such string.
210 * Else: Success. Pointer to string descriptor is returned.
211 *------------------------------------------------------------------------*/
212static const void *
213mouse_get_string_desc(uint16_t lang_id, uint8_t string_index)
214{
215 static const void *ptr[MOUSE_MAX_INDEX] = {
221 };
222
223 if (string_index == 0) {
224 return (&usb_string_lang_en);
225 }
226 if (lang_id != 0x0409) {
227 return (NULL);
228 }
229 if (string_index < MOUSE_MAX_INDEX) {
230 return (ptr[string_index]);
231 }
232 return (NULL);
233}
234
235static void
236mouse_init(void *arg __unused)
237{
238 struct sysctl_oid *parent;
239 char parent_name[3];
240
249
250 snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_MOUSE);
251 sysctl_ctx_init(&mouse_ctx_list);
252
253 parent = SYSCTL_ADD_NODE(&mouse_ctx_list,
254 SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
255 parent_name, CTLFLAG_RW | CTLFLAG_MPSAFE,
256 0, "USB Mouse device side template");
257 SYSCTL_ADD_U16(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
258 "vendor_id", CTLFLAG_RWTUN,
259 &usb_template_mouse.idVendor, 1, "Vendor identifier");
260 SYSCTL_ADD_U16(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
261 "product_id", CTLFLAG_RWTUN,
262 &usb_template_mouse.idProduct, 1, "Product identifier");
263#if 0
264 SYSCTL_ADD_PROC(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
265 "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
267 "A", "Interface string");
268#endif
269 SYSCTL_ADD_PROC(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
270 "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
272 "A", "Manufacturer string");
273 SYSCTL_ADD_PROC(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
274 "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
276 "A", "Product string");
277 SYSCTL_ADD_PROC(&mouse_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
278 "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
280 "A", "Serial number string");
281}
282
283static void
284mouse_uninit(void *arg __unused)
285{
286
287 sysctl_ctx_free(&mouse_ctx_list);
288}
289
290SYSINIT(mouse_init, SI_SUB_LOCK, SI_ORDER_FIRST, mouse_init, NULL);
291SYSUNINIT(mouse_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, mouse_uninit, NULL);
const struct usb_temp_interface_desc ** ppIfaceDesc
Definition: usb_template.h:79
usb_temp_get_string_desc_t * getStringDesc
Definition: usb_template.h:86
const void ** ppRawDesc
Definition: usb_template.h:56
const void ** ppRawDesc
Definition: usb_template.h:69
uint8_t bInterval[USB_SPEED_MAX]
Definition: usb_template.h:52
uint16_t mps[USB_SPEED_MAX]
Definition: usb_template.h:48
#define UE_INTERRUPT
Definition: usb.h:544
#define UISUBCLASS_BOOT
Definition: usb.h:454
#define UE_DIR_IN
Definition: usb.h:531
#define UICLASS_HID
Definition: usb.h:453
@ USB_SPEED_LOW
Definition: usb.h:753
@ USB_SPEED_FULL
Definition: usb.h:754
@ USB_SPEED_HIGH
Definition: usb.h:755
#define UIPROTO_MOUSE
Definition: usb.h:456
#define UDCLASS_COMM
Definition: usb.h:372
const struct usb_string_lang usb_string_lang_en
Definition: usb_core.c:63
uint16_t * plen
Definition: usb_if.m:53
const void * req
Definition: usb_if.m:51
@ USB_TEMP_MOUSE
Definition: usb_ioctl.h:58
int usb_temp_sysctl(SYSCTL_HANDLER_ARGS)
Definition: usb_template.c:173
const void *() usb_temp_get_vendor_desc_t(const struct usb_device_request *req, uint16_t *plen)
Definition: usb_template.h:45
const void *() usb_temp_get_string_desc_t(uint16_t lang_id, uint8_t string_index)
Definition: usb_template.h:44
SYSINIT(mouse_init, SI_SUB_LOCK, SI_ORDER_FIRST, mouse_init, NULL)
#define MOUSE_DEFAULT_VENDOR_ID
static const struct usb_temp_packet_size mouse_intr_mps
struct usb_temp_device_desc usb_template_mouse
static struct usb_string_descriptor mouse_serial_number
static const struct usb_temp_config_desc * mouse_configs[]
static const struct usb_temp_config_desc mouse_config_desc
static void mouse_uninit(void *arg __unused)
static struct usb_string_descriptor mouse_product
static uint8_t mouse_hid_descriptor[]
static const struct usb_temp_interval mouse_intr_interval
static const struct usb_temp_interface_desc mouse_iface_0
@ MOUSE_LANG_INDEX
@ MOUSE_PRODUCT_INDEX
@ MOUSE_MANUFACTURER_INDEX
@ MOUSE_SERIAL_NUMBER_INDEX
@ MOUSE_MAX_INDEX
@ MOUSE_INTERFACE_INDEX
static struct usb_string_descriptor mouse_interface
static const struct usb_temp_interface_desc * mouse_interfaces[]
static struct sysctl_ctx_list mouse_ctx_list
static const struct usb_temp_endpoint_desc * mouse_endpoints[]
static struct usb_string_descriptor mouse_manufacturer
static usb_temp_get_string_desc_t mouse_get_string_desc
#define MOUSE_DEFAULT_SERIAL_NUMBER
#define MOUSE_DEFAULT_MANUFACTURER
static const struct usb_temp_endpoint_desc mouse_ep_0
static const uint8_t mouse_raw_desc[]
static usb_temp_get_vendor_desc_t mouse_get_vendor_desc
static void mouse_init(void *arg __unused)
#define MOUSE_DEFAULT_PRODUCT_ID
#define MOUSE_DEFAULT_INTERFACE
SYSUNINIT(mouse_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, mouse_uninit, NULL)
#define MOUSE_DEFAULT_PRODUCT
static const void * mouse_iface_0_desc[]
uint8_t usb_make_str_desc(void *ptr, uint16_t max_len, const char *s)
Definition: usb_util.c:193