usb_template_mouse.c revision 302408
11590Srgrimes/* $FreeBSD: stable/11/sys/dev/usb/template/usb_template_mouse.c 246125 2013-01-30 16:05:54Z hselasky $ */ 21590Srgrimes/*- 31590Srgrimes * Copyright (c) 2010 Hans Petter Selasky. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 141590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241590Srgrimes * SUCH DAMAGE. 251590Srgrimes */ 261590Srgrimes 271590Srgrimes/* 281590Srgrimes * This file contains the USB template for an USB Mouse Device. 291590Srgrimes */ 301590Srgrimes 311590Srgrimes#ifdef USB_GLOBAL_INCLUDE_FILE 321590Srgrimes#include USB_GLOBAL_INCLUDE_FILE 331590Srgrimes#else 341590Srgrimes#include <sys/stdint.h> 3516509Sjraynard#include <sys/stddef.h> 361590Srgrimes#include <sys/param.h> 3716509Sjraynard#include <sys/queue.h> 3816509Sjraynard#include <sys/types.h> 3916509Sjraynard#include <sys/systm.h> 401590Srgrimes#include <sys/kernel.h> 411590Srgrimes#include <sys/bus.h> 421590Srgrimes#include <sys/module.h> 431590Srgrimes#include <sys/lock.h> 441590Srgrimes#include <sys/mutex.h> 451590Srgrimes#include <sys/condvar.h> 461590Srgrimes#include <sys/sysctl.h> 471590Srgrimes#include <sys/sx.h> 4816509Sjraynard#include <sys/unistd.h> 491590Srgrimes#include <sys/callout.h> 5016509Sjraynard#include <sys/malloc.h> 511590Srgrimes#include <sys/priv.h> 521590Srgrimes 531590Srgrimes#include <dev/usb/usb.h> 541590Srgrimes#include <dev/usb/usbdi.h> 551590Srgrimes#include <dev/usb/usb_core.h> 561590Srgrimes#include <dev/usb/usb_cdc.h> 571590Srgrimes 581590Srgrimes#include <dev/usb/template/usb_template.h> 591590Srgrimes#endif /* USB_GLOBAL_INCLUDE_FILE */ 601590Srgrimes 611590Srgrimesenum { 621590Srgrimes INDEX_LANG, 631590Srgrimes INDEX_MOUSE, 641590Srgrimes INDEX_PRODUCT, 651590Srgrimes INDEX_MAX, 661590Srgrimes}; 671590Srgrimes 681590Srgrimes#define STRING_PRODUCT \ 691590Srgrimes "M\0o\0u\0s\0e\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e" 701590Srgrimes 711590Srgrimes#define STRING_MOUSE \ 721590Srgrimes "M\0o\0u\0s\0e\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 731590Srgrimes 741590Srgrimes/* make the real string descriptors */ 751590Srgrimes 761590SrgrimesUSB_MAKE_STRING_DESC(STRING_MOUSE, string_mouse); 771590SrgrimesUSB_MAKE_STRING_DESC(STRING_PRODUCT, string_product); 781590Srgrimes 791590Srgrimes/* prototypes */ 801590Srgrimes 811590Srgrimes/* The following HID descriptor was dumped from a HP mouse. */ 821590Srgrimes 831590Srgrimesstatic uint8_t mouse_hid_descriptor[] = { 841590Srgrimes 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, 851590Srgrimes 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 861590Srgrimes 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 871590Srgrimes 0x81, 0x02, 0x95, 0x05, 0x81, 0x03, 0x05, 0x01, 881590Srgrimes 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, 0x15, 0x81, 891590Srgrimes 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03, 0x81, 0x06, 901590Srgrimes 0xc0, 0xc0 911590Srgrimes}; 921590Srgrimes 931590Srgrimesstatic const struct usb_temp_packet_size mouse_intr_mps = { 941590Srgrimes .mps[USB_SPEED_LOW] = 8, 951590Srgrimes .mps[USB_SPEED_FULL] = 8, 961590Srgrimes .mps[USB_SPEED_HIGH] = 8, 971590Srgrimes}; 981590Srgrimes 991590Srgrimesstatic const struct usb_temp_interval mouse_intr_interval = { 1001590Srgrimes .bInterval[USB_SPEED_LOW] = 2, /* 2ms */ 1011590Srgrimes .bInterval[USB_SPEED_FULL] = 2, /* 2ms */ 1021590Srgrimes .bInterval[USB_SPEED_HIGH] = 5, /* 2ms */ 1031590Srgrimes}; 1041590Srgrimes 1051590Srgrimesstatic const struct usb_temp_endpoint_desc mouse_ep_0 = { 1061590Srgrimes .ppRawDesc = NULL, /* no raw descriptors */ 1071590Srgrimes .pPacketSize = &mouse_intr_mps, 1081590Srgrimes .pIntervals = &mouse_intr_interval, 1091590Srgrimes .bEndpointAddress = UE_DIR_IN, 1101590Srgrimes .bmAttributes = UE_INTERRUPT, 1111590Srgrimes}; 1121590Srgrimes 1131590Srgrimesstatic const struct usb_temp_endpoint_desc *mouse_endpoints[] = { 114 &mouse_ep_0, 115 NULL, 116}; 117 118static const uint8_t mouse_raw_desc[] = { 119 0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, sizeof(mouse_hid_descriptor), 120 0x00 121}; 122 123static const void *mouse_iface_0_desc[] = { 124 mouse_raw_desc, 125 NULL, 126}; 127 128static const struct usb_temp_interface_desc mouse_iface_0 = { 129 .ppRawDesc = mouse_iface_0_desc, 130 .ppEndpoints = mouse_endpoints, 131 .bInterfaceClass = 3, 132 .bInterfaceSubClass = 1, 133 .bInterfaceProtocol = 2, 134 .iInterface = INDEX_MOUSE, 135}; 136 137static const struct usb_temp_interface_desc *mouse_interfaces[] = { 138 &mouse_iface_0, 139 NULL, 140}; 141 142static const struct usb_temp_config_desc mouse_config_desc = { 143 .ppIfaceDesc = mouse_interfaces, 144 .bmAttributes = UC_BUS_POWERED, 145 .bMaxPower = 25, /* 50 mA */ 146 .iConfiguration = INDEX_PRODUCT, 147}; 148 149static const struct usb_temp_config_desc *mouse_configs[] = { 150 &mouse_config_desc, 151 NULL, 152}; 153 154static usb_temp_get_string_desc_t mouse_get_string_desc; 155static usb_temp_get_vendor_desc_t mouse_get_vendor_desc; 156 157const struct usb_temp_device_desc usb_template_mouse = { 158 .getStringDesc = &mouse_get_string_desc, 159 .getVendorDesc = &mouse_get_vendor_desc, 160 .ppConfigDesc = mouse_configs, 161 .idVendor = USB_TEMPLATE_VENDOR, 162 .idProduct = 0x00AE, 163 .bcdDevice = 0x0100, 164 .bDeviceClass = UDCLASS_COMM, 165 .bDeviceSubClass = 0, 166 .bDeviceProtocol = 0, 167 .iManufacturer = 0, 168 .iProduct = INDEX_PRODUCT, 169 .iSerialNumber = 0, 170}; 171 172/*------------------------------------------------------------------------* 173 * mouse_get_vendor_desc 174 * 175 * Return values: 176 * NULL: Failure. No such vendor descriptor. 177 * Else: Success. Pointer to vendor descriptor is returned. 178 *------------------------------------------------------------------------*/ 179static const void * 180mouse_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen) 181{ 182 if ((req->bmRequestType == 0x81) && (req->bRequest == 0x06) && 183 (req->wValue[0] == 0x00) && (req->wValue[1] == 0x22) && 184 (req->wIndex[1] == 0) && (req->wIndex[0] == 0)) { 185 186 *plen = sizeof(mouse_hid_descriptor); 187 return (mouse_hid_descriptor); 188 } 189 return (NULL); 190} 191 192/*------------------------------------------------------------------------* 193 * mouse_get_string_desc 194 * 195 * Return values: 196 * NULL: Failure. No such string. 197 * Else: Success. Pointer to string descriptor is returned. 198 *------------------------------------------------------------------------*/ 199static const void * 200mouse_get_string_desc(uint16_t lang_id, uint8_t string_index) 201{ 202 static const void *ptr[INDEX_MAX] = { 203 [INDEX_LANG] = &usb_string_lang_en, 204 [INDEX_MOUSE] = &string_mouse, 205 [INDEX_PRODUCT] = &string_product, 206 }; 207 208 if (string_index == 0) { 209 return (&usb_string_lang_en); 210 } 211 if (lang_id != 0x0409) { 212 return (NULL); 213 } 214 if (string_index < INDEX_MAX) { 215 return (ptr[string_index]); 216 } 217 return (NULL); 218} 219