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