usb_template_mouse.c revision 256281
133965Sjdp/* $FreeBSD: stable/10/sys/dev/usb/template/usb_template_mouse.c 246125 2013-01-30 16:05:54Z hselasky $ */ 289857Sobrien/*- 360484Sobrien * Copyright (c) 2010 Hans Petter Selasky. All rights reserved. 433965Sjdp * 533965Sjdp * Redistribution and use in source and binary forms, with or without 633965Sjdp * modification, are permitted provided that the following conditions 733965Sjdp * are met: 833965Sjdp * 1. Redistributions of source code must retain the above copyright 933965Sjdp * notice, this list of conditions and the following disclaimer. 1033965Sjdp * 2. Redistributions in binary form must reproduce the above copyright 1133965Sjdp * notice, this list of conditions and the following disclaimer in the 1233965Sjdp * documentation and/or other materials provided with the distribution. 1333965Sjdp * 1433965Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1533965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1633965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1733965Sjdp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1860484Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1960484Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2060484Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2133965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2289857Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2389857Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2489857Sobrien * SUCH DAMAGE. 2589857Sobrien */ 2633965Sjdp 2733965Sjdp/* 2833965Sjdp * This file contains the USB template for an USB Mouse Device. 2933965Sjdp */ 3033965Sjdp 3189857Sobrien#ifdef USB_GLOBAL_INCLUDE_FILE 3233965Sjdp#include USB_GLOBAL_INCLUDE_FILE 3360484Sobrien#else 3433965Sjdp#include <sys/stdint.h> 3533965Sjdp#include <sys/stddef.h> 3689857Sobrien#include <sys/param.h> 3733965Sjdp#include <sys/queue.h> 3833965Sjdp#include <sys/types.h> 3989857Sobrien#include <sys/systm.h> 4089857Sobrien#include <sys/kernel.h> 4189857Sobrien#include <sys/bus.h> 4289857Sobrien#include <sys/module.h> 4389857Sobrien#include <sys/lock.h> 4433965Sjdp#include <sys/mutex.h> 4533965Sjdp#include <sys/condvar.h> 4633965Sjdp#include <sys/sysctl.h> 4789857Sobrien#include <sys/sx.h> 4833965Sjdp#include <sys/unistd.h> 4933965Sjdp#include <sys/callout.h> 5033965Sjdp#include <sys/malloc.h> 5133965Sjdp#include <sys/priv.h> 5233965Sjdp 5389857Sobrien#include <dev/usb/usb.h> 5489857Sobrien#include <dev/usb/usbdi.h> 5589857Sobrien#include <dev/usb/usb_core.h> 5689857Sobrien#include <dev/usb/usb_cdc.h> 5789857Sobrien 5889857Sobrien#include <dev/usb/template/usb_template.h> 5989857Sobrien#endif /* USB_GLOBAL_INCLUDE_FILE */ 6033965Sjdp 6177298Sobrienenum { 6233965Sjdp INDEX_LANG, 6377298Sobrien INDEX_MOUSE, 6433965Sjdp INDEX_PRODUCT, 6533965Sjdp INDEX_MAX, 6633965Sjdp}; 6733965Sjdp 6833965Sjdp#define STRING_PRODUCT \ 6977298Sobrien "M\0o\0u\0s\0e\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e" 7033965Sjdp 7133965Sjdp#define STRING_MOUSE \ 7233965Sjdp "M\0o\0u\0s\0e\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 7333965Sjdp 7477298Sobrien/* make the real string descriptors */ 7577298Sobrien 7633965SjdpUSB_MAKE_STRING_DESC(STRING_MOUSE, string_mouse); 7733965SjdpUSB_MAKE_STRING_DESC(STRING_PRODUCT, string_product); 7833965Sjdp 7933965Sjdp/* prototypes */ 8033965Sjdp 8177298Sobrien/* The following HID descriptor was dumped from a HP mouse. */ 8233965Sjdp 8333965Sjdpstatic uint8_t mouse_hid_descriptor[] = { 8433965Sjdp 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, 8533965Sjdp 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 8633965Sjdp 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 8733965Sjdp 0x81, 0x02, 0x95, 0x05, 0x81, 0x03, 0x05, 0x01, 8833965Sjdp 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, 0x15, 0x81, 8989857Sobrien 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03, 0x81, 0x06, 9033965Sjdp 0xc0, 0xc0 9133965Sjdp}; 9233965Sjdp 9333965Sjdpstatic const struct usb_temp_packet_size mouse_intr_mps = { 9433965Sjdp .mps[USB_SPEED_LOW] = 8, 9533965Sjdp .mps[USB_SPEED_FULL] = 8, 9633965Sjdp .mps[USB_SPEED_HIGH] = 8, 9733965Sjdp}; 9833965Sjdp 9933965Sjdpstatic const struct usb_temp_interval mouse_intr_interval = { 10033965Sjdp .bInterval[USB_SPEED_LOW] = 2, /* 2ms */ 10133965Sjdp .bInterval[USB_SPEED_FULL] = 2, /* 2ms */ 10233965Sjdp .bInterval[USB_SPEED_HIGH] = 5, /* 2ms */ 10389857Sobrien}; 10489857Sobrien 10533965Sjdpstatic const struct usb_temp_endpoint_desc mouse_ep_0 = { 10633965Sjdp .ppRawDesc = NULL, /* no raw descriptors */ 10733965Sjdp .pPacketSize = &mouse_intr_mps, 10833965Sjdp .pIntervals = &mouse_intr_interval, 10933965Sjdp .bEndpointAddress = UE_DIR_IN, 11033965Sjdp .bmAttributes = UE_INTERRUPT, 11133965Sjdp}; 11233965Sjdp 11333965Sjdpstatic const struct usb_temp_endpoint_desc *mouse_endpoints[] = { 11433965Sjdp &mouse_ep_0, 11589857Sobrien NULL, 11633965Sjdp}; 11733965Sjdp 11833965Sjdpstatic const uint8_t mouse_raw_desc[] = { 11933965Sjdp 0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, sizeof(mouse_hid_descriptor), 12033965Sjdp 0x00 12133965Sjdp}; 12233965Sjdp 12333965Sjdpstatic const void *mouse_iface_0_desc[] = { 12433965Sjdp mouse_raw_desc, 12533965Sjdp NULL, 12633965Sjdp}; 12733965Sjdp 12877298Sobrienstatic const struct usb_temp_interface_desc mouse_iface_0 = { 12933965Sjdp .ppRawDesc = mouse_iface_0_desc, 13033965Sjdp .ppEndpoints = mouse_endpoints, 13133965Sjdp .bInterfaceClass = 3, 13233965Sjdp .bInterfaceSubClass = 1, 13333965Sjdp .bInterfaceProtocol = 2, 13433965Sjdp .iInterface = INDEX_MOUSE, 13533965Sjdp}; 13677298Sobrien 13733965Sjdpstatic const struct usb_temp_interface_desc *mouse_interfaces[] = { 13877298Sobrien &mouse_iface_0, 13989857Sobrien NULL, 14033965Sjdp}; 14133965Sjdp 14233965Sjdpstatic const struct usb_temp_config_desc mouse_config_desc = { 14377298Sobrien .ppIfaceDesc = mouse_interfaces, 14433965Sjdp .bmAttributes = UC_BUS_POWERED, 14577298Sobrien .bMaxPower = 25, /* 50 mA */ 14633965Sjdp .iConfiguration = INDEX_PRODUCT, 14733965Sjdp}; 14833965Sjdp 14989857Sobrienstatic const struct usb_temp_config_desc *mouse_configs[] = { 15033965Sjdp &mouse_config_desc, 15133965Sjdp NULL, 15233965Sjdp}; 15333965Sjdp 15433965Sjdpstatic usb_temp_get_string_desc_t mouse_get_string_desc; 15533965Sjdpstatic usb_temp_get_vendor_desc_t mouse_get_vendor_desc; 15689857Sobrien 15789857Sobrienconst struct usb_temp_device_desc usb_template_mouse = { 15833965Sjdp .getStringDesc = &mouse_get_string_desc, 15933965Sjdp .getVendorDesc = &mouse_get_vendor_desc, 160104834Sobrien .ppConfigDesc = mouse_configs, 161104834Sobrien .idVendor = USB_TEMPLATE_VENDOR, 162104834Sobrien .idProduct = 0x00AE, 163104834Sobrien .bcdDevice = 0x0100, 164104834Sobrien .bDeviceClass = UDCLASS_COMM, 165104834Sobrien .bDeviceSubClass = 0, 166104834Sobrien .bDeviceProtocol = 0, 167104834Sobrien .iManufacturer = 0, 168104834Sobrien .iProduct = INDEX_PRODUCT, 16989857Sobrien .iSerialNumber = 0, 170104834Sobrien}; 171104834Sobrien 172104834Sobrien/*------------------------------------------------------------------------* 173104834Sobrien * mouse_get_vendor_desc 174104834Sobrien * 175104834Sobrien * Return values: 176104834Sobrien * NULL: Failure. No such vendor descriptor. 177104834Sobrien * Else: Success. Pointer to vendor descriptor is returned. 178104834Sobrien *------------------------------------------------------------------------*/ 17933965Sjdpstatic const void * 180104834Sobrienmouse_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen) 18133965Sjdp{ 182104834Sobrien if ((req->bmRequestType == 0x81) && (req->bRequest == 0x06) && 18333965Sjdp (req->wValue[0] == 0x00) && (req->wValue[1] == 0x22) && 18433965Sjdp (req->wIndex[1] == 0) && (req->wIndex[0] == 0)) { 18533965Sjdp 18633965Sjdp *plen = sizeof(mouse_hid_descriptor); 18733965Sjdp return (mouse_hid_descriptor); 18833965Sjdp } 18989857Sobrien return (NULL); 19077298Sobrien} 19133965Sjdp 19233965Sjdp/*------------------------------------------------------------------------* 19389857Sobrien * mouse_get_string_desc 19433965Sjdp * 19589857Sobrien * Return values: 19689857Sobrien * NULL: Failure. No such string. 19733965Sjdp * Else: Success. Pointer to string descriptor is returned. 19877298Sobrien *------------------------------------------------------------------------*/ 19933965Sjdpstatic const void * 20033965Sjdpmouse_get_string_desc(uint16_t lang_id, uint8_t string_index) 20133965Sjdp{ 20233965Sjdp static const void *ptr[INDEX_MAX] = { 20360484Sobrien [INDEX_LANG] = &usb_string_lang_en, 20460484Sobrien [INDEX_MOUSE] = &string_mouse, 20560484Sobrien [INDEX_PRODUCT] = &string_product, 20633965Sjdp }; 20733965Sjdp 20833965Sjdp if (string_index == 0) { 20960484Sobrien return (&usb_string_lang_en); 21033965Sjdp } 21133965Sjdp if (lang_id != 0x0409) { 21260484Sobrien return (NULL); 21333965Sjdp } 21433965Sjdp if (string_index < INDEX_MAX) { 21533965Sjdp return (ptr[string_index]); 21633965Sjdp } 21733965Sjdp return (NULL); 21833965Sjdp} 21933965Sjdp