The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/template/usb_template_kbd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 Keyboard 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 
   67 #include <dev/usb/template/usb_template.h>
   68 #endif                  /* USB_GLOBAL_INCLUDE_FILE */
   69 
   70 enum {
   71         KBD_LANG_INDEX,
   72         KBD_INTERFACE_INDEX,
   73         KBD_MANUFACTURER_INDEX,
   74         KBD_PRODUCT_INDEX,
   75         KBD_SERIAL_NUMBER_INDEX,
   76         KBD_MAX_INDEX,
   77 };
   78 
   79 #define KBD_DEFAULT_VENDOR_ID           USB_TEMPLATE_VENDOR
   80 #define KBD_DEFAULT_PRODUCT_ID          0x27db
   81 #define KBD_DEFAULT_INTERFACE           "Keyboard Interface"
   82 #define KBD_DEFAULT_MANUFACTURER        USB_TEMPLATE_MANUFACTURER
   83 #define KBD_DEFAULT_PRODUCT             "Keyboard Test Device"
   84 #define KBD_DEFAULT_SERIAL_NUMBER       "March 2008"
   85 
   86 static struct usb_string_descriptor     kbd_interface;
   87 static struct usb_string_descriptor     kbd_manufacturer;
   88 static struct usb_string_descriptor     kbd_product;
   89 static struct usb_string_descriptor     kbd_serial_number;
   90 
   91 static struct sysctl_ctx_list           kbd_ctx_list;
   92 
   93 /* prototypes */
   94 
   95 static const struct usb_temp_packet_size keyboard_intr_mps = {
   96         .mps[USB_SPEED_LOW] = 16,
   97         .mps[USB_SPEED_FULL] = 16,
   98         .mps[USB_SPEED_HIGH] = 16,
   99 };
  100 
  101 static const struct usb_temp_interval keyboard_intr_interval = {
  102         .bInterval[USB_SPEED_LOW] = 2,  /* 2 ms */
  103         .bInterval[USB_SPEED_FULL] = 2, /* 2 ms */
  104         .bInterval[USB_SPEED_HIGH] = 5, /* 2 ms */
  105 };
  106 
  107 /* The following HID descriptor was dumped from a HP keyboard. */
  108 
  109 static uint8_t keyboard_hid_descriptor[] = {
  110         0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07,
  111         0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01,
  112         0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01,
  113         0x75, 0x08, 0x81, 0x01, 0x95, 0x03, 0x75, 0x01,
  114         0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, 0x02,
  115         0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06,
  116         0x75, 0x08, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05,
  117         0x07, 0x19, 0x00, 0x2a, 0xff, 0x00, 0x81, 0x00,
  118         0xc0
  119 };
  120 
  121 static const struct usb_temp_endpoint_desc keyboard_ep_0 = {
  122         .ppRawDesc = NULL,              /* no raw descriptors */
  123         .pPacketSize = &keyboard_intr_mps,
  124         .pIntervals = &keyboard_intr_interval,
  125         .bEndpointAddress = UE_DIR_IN,
  126         .bmAttributes = UE_INTERRUPT,
  127 };
  128 
  129 static const struct usb_temp_endpoint_desc *keyboard_endpoints[] = {
  130         &keyboard_ep_0,
  131         NULL,
  132 };
  133 
  134 static const uint8_t keyboard_raw_desc[] = {
  135         0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, sizeof(keyboard_hid_descriptor),
  136         0x00
  137 };
  138 
  139 static const void *keyboard_iface_0_desc[] = {
  140         keyboard_raw_desc,
  141         NULL,
  142 };
  143 
  144 static const struct usb_temp_interface_desc keyboard_iface_0 = {
  145         .ppRawDesc = keyboard_iface_0_desc,
  146         .ppEndpoints = keyboard_endpoints,
  147         .bInterfaceClass = UICLASS_HID,
  148         .bInterfaceSubClass = UISUBCLASS_BOOT,
  149         .bInterfaceProtocol = UIPROTO_BOOT_KEYBOARD,
  150         .iInterface = KBD_INTERFACE_INDEX,
  151 };
  152 
  153 static const struct usb_temp_interface_desc *keyboard_interfaces[] = {
  154         &keyboard_iface_0,
  155         NULL,
  156 };
  157 
  158 static const struct usb_temp_config_desc keyboard_config_desc = {
  159         .ppIfaceDesc = keyboard_interfaces,
  160         .bmAttributes = 0,
  161         .bMaxPower = 0,
  162         .iConfiguration = KBD_PRODUCT_INDEX,
  163 };
  164 
  165 static const struct usb_temp_config_desc *keyboard_configs[] = {
  166         &keyboard_config_desc,
  167         NULL,
  168 };
  169 
  170 static usb_temp_get_string_desc_t keyboard_get_string_desc;
  171 static usb_temp_get_vendor_desc_t keyboard_get_vendor_desc;
  172 
  173 struct usb_temp_device_desc usb_template_kbd = {
  174         .getStringDesc = &keyboard_get_string_desc,
  175         .getVendorDesc = &keyboard_get_vendor_desc,
  176         .ppConfigDesc = keyboard_configs,
  177         .idVendor = KBD_DEFAULT_VENDOR_ID,
  178         .idProduct = KBD_DEFAULT_PRODUCT_ID,
  179         .bcdDevice = 0x0100,
  180         .bDeviceClass = UDCLASS_COMM,
  181         .bDeviceSubClass = 0,
  182         .bDeviceProtocol = 0,
  183         .iManufacturer = KBD_MANUFACTURER_INDEX,
  184         .iProduct = KBD_PRODUCT_INDEX,
  185         .iSerialNumber = KBD_SERIAL_NUMBER_INDEX,
  186 };
  187 
  188 /*------------------------------------------------------------------------*
  189  *      keyboard_get_vendor_desc
  190  *
  191  * Return values:
  192  * NULL: Failure. No such vendor descriptor.
  193  * Else: Success. Pointer to vendor descriptor is returned.
  194  *------------------------------------------------------------------------*/
  195 static const void *
  196 keyboard_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen)
  197 {
  198         if ((req->bmRequestType == 0x81) && (req->bRequest == 0x06) &&
  199             (req->wValue[0] == 0x00) && (req->wValue[1] == 0x22) &&
  200             (req->wIndex[1] == 0) && (req->wIndex[0] == 0)) {
  201                 *plen = sizeof(keyboard_hid_descriptor);
  202                 return (keyboard_hid_descriptor);
  203         }
  204         return (NULL);
  205 }
  206 
  207 /*------------------------------------------------------------------------*
  208  *      keyboard_get_string_desc
  209  *
  210  * Return values:
  211  * NULL: Failure. No such string.
  212  * Else: Success. Pointer to string descriptor is returned.
  213  *------------------------------------------------------------------------*/
  214 static const void *
  215 keyboard_get_string_desc(uint16_t lang_id, uint8_t string_index)
  216 {
  217         static const void *ptr[KBD_MAX_INDEX] = {
  218                 [KBD_LANG_INDEX] = &usb_string_lang_en,
  219                 [KBD_INTERFACE_INDEX] = &kbd_interface,
  220                 [KBD_MANUFACTURER_INDEX] = &kbd_manufacturer,
  221                 [KBD_PRODUCT_INDEX] = &kbd_product,
  222                 [KBD_SERIAL_NUMBER_INDEX] = &kbd_serial_number,
  223         };
  224 
  225         if (string_index == 0) {
  226                 return (&usb_string_lang_en);
  227         }
  228         if (lang_id != 0x0409) {
  229                 return (NULL);
  230         }
  231         if (string_index < KBD_MAX_INDEX) {
  232                 return (ptr[string_index]);
  233         }
  234         return (NULL);
  235 }
  236 
  237 static void
  238 kbd_init(void *arg __unused)
  239 {
  240         struct sysctl_oid *parent;
  241         char parent_name[3];
  242 
  243         usb_make_str_desc(&kbd_interface, sizeof(kbd_interface),
  244             KBD_DEFAULT_INTERFACE);
  245         usb_make_str_desc(&kbd_manufacturer, sizeof(kbd_manufacturer),
  246             KBD_DEFAULT_MANUFACTURER);
  247         usb_make_str_desc(&kbd_product, sizeof(kbd_product),
  248             KBD_DEFAULT_PRODUCT);
  249         usb_make_str_desc(&kbd_serial_number, sizeof(kbd_serial_number),
  250             KBD_DEFAULT_SERIAL_NUMBER);
  251 
  252         snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_KBD);
  253         sysctl_ctx_init(&kbd_ctx_list);
  254 
  255         parent = SYSCTL_ADD_NODE(&kbd_ctx_list,
  256             SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO,
  257             parent_name, CTLFLAG_RW | CTLFLAG_MPSAFE,
  258             0, "USB Keyboard device side template");
  259         SYSCTL_ADD_U16(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  260             "vendor_id", CTLFLAG_RWTUN,
  261             &usb_template_kbd.idVendor, 1, "Vendor identifier");
  262         SYSCTL_ADD_U16(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  263             "product_id", CTLFLAG_RWTUN,
  264             &usb_template_kbd.idProduct, 1, "Product identifier");
  265 #if 0
  266         SYSCTL_ADD_PROC(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  267             "interface", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  268             &kbd_interface, sizeof(kbd_interface), usb_temp_sysctl,
  269             "A", "Interface string");
  270 #endif
  271         SYSCTL_ADD_PROC(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  272             "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  273             &kbd_manufacturer, sizeof(kbd_manufacturer), usb_temp_sysctl,
  274             "A", "Manufacturer string");
  275         SYSCTL_ADD_PROC(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  276             "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  277             &kbd_product, sizeof(kbd_product), usb_temp_sysctl,
  278             "A", "Product string");
  279         SYSCTL_ADD_PROC(&kbd_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO,
  280             "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  281             &kbd_serial_number, sizeof(kbd_serial_number), usb_temp_sysctl,
  282             "A", "Serial number string");
  283 }
  284 
  285 static void
  286 kbd_uninit(void *arg __unused)
  287 {
  288 
  289         sysctl_ctx_free(&kbd_ctx_list);
  290 }
  291 
  292 SYSINIT(kbd_init, SI_SUB_LOCK, SI_ORDER_FIRST, kbd_init, NULL);
  293 SYSUNINIT(kbd_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, kbd_uninit, NULL);

Cache object: 4820c0e4bc13318afaa4a904bb65f267


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.