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/hid/hidcc.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 /*      $OpenBSD: hidcc.c,v 1.5 2022/11/14 00:16:44 deraadt Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2022 Anton Lindqvist <anton@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/param.h>
   20 #include <sys/systm.h>
   21 #include <sys/malloc.h>
   22 #include <sys/device.h>
   23 
   24 #include <dev/hid/hidccvar.h>
   25 #include <dev/hid/hid.h>
   26 
   27 #include <dev/wscons/wsconsio.h>
   28 #include <dev/wscons/wskbdvar.h>
   29 #include <dev/wscons/wsksymdef.h>
   30 #include <dev/wscons/wsksymvar.h>
   31 
   32 #define DEVNAME(sc)     ((sc)->sc_dev->dv_xname)
   33 
   34 /* #define HIDCC_DEBUG */
   35 #ifdef HIDCC_DEBUG
   36 #define DPRINTF(x...)   do { if (hidcc_debug) printf(x); } while (0)
   37 struct hidcc;
   38 void    hidcc_dump(struct hidcc *, const char *, uint8_t *, u_int);
   39 int     hidcc_debug = 1;
   40 #else
   41 #define DPRINTF(x...)
   42 #define hidcc_dump(sc, prefix, data, len)
   43 #endif
   44 
   45 struct hidcc {
   46         struct device                    *sc_dev;
   47         struct device                    *sc_wskbddev;
   48 
   49         /* Key mappings used in translating mode. */
   50         keysym_t                         *sc_map;
   51         u_int                             sc_maplen;
   52         u_int                             sc_mapsiz;
   53 
   54         /* Key mappings used in raw mode. */
   55         const struct hidcc_keysym       **sc_raw;
   56         u_int                             sc_rawsiz;
   57 
   58         u_int                             sc_nusages;
   59         int                               sc_isarray;
   60         int                               sc_mode;
   61 
   62         /*
   63          * Slice of the interrupt buffer which represents a pressed key.
   64          * See section 8 (Report Protocol) of the HID specification v1.11.
   65          */
   66         struct {
   67                 uint8_t *i_buf;
   68                 uint32_t i_bufsiz;
   69                 uint32_t i_off;         /* offset in bits */
   70                 uint32_t i_len;         /* length in bits */
   71         } sc_input;
   72 
   73         struct {
   74                 uint32_t        v_inc;  /* volume increment bit offset */
   75                 uint32_t        v_dec;  /* volume decrement bit offset */
   76                 uint32_t        v_off;  /* offset in bits */
   77                 uint32_t        v_len;  /* length in bits */
   78         } sc_volume;
   79 
   80         /* Last pressed key. */
   81         union {
   82                 int     sc_last_translate;
   83                 u_char  sc_last_raw;
   84         };
   85 
   86         /*
   87          * Only the first element is populated whereas the second remains zeroed
   88          * out since such trailing sentinel is required by wskbd_load_keymap().
   89          */
   90         struct wscons_keydesc             sc_keydesc[2];
   91         struct wskbd_mapdata              sc_keymap;
   92 
   93         int                               (*sc_enable)(void *, int);
   94         void                             *sc_arg;
   95 };
   96 
   97 struct hidcc_keysym {
   98 #ifdef HIDCC_DEBUG
   99         const char      *ks_name;
  100 #endif
  101         int32_t          ks_usage;
  102         keysym_t         ks_key;
  103         u_char           ks_raw;
  104 };
  105 
  106 /*
  107  * Mapping of HID Consumer Control usages to key symbols based on the HID Usage
  108  * Tables 1.21 specification. The same usages can also be found at
  109  * /usr/share/misc/usb_hid_usages.
  110  * The raw scan codes are taken from X11, see the media_nav_acpi_common symbols
  111  * in dist/xkeyboard-config/symbols/inet.
  112  * Then use dist/xkeyboard-config/keycodes/xfree86 to resolve keys to the
  113  * corresponding raw scan code.
  114  */
  115 static const struct hidcc_keysym hidcc_keysyms[] = {
  116 #ifdef HIDCC_DEBUG
  117 #define Y(usage, name, key, raw)        { name, usage, key, raw },
  118 #else
  119 #define Y(usage, name, key, raw)        { usage, key, raw },
  120 #endif
  121 #define N(usage, name, key, raw)
  122         /* 0x0000 Unassigned */
  123         N(0x0001,       "Consumer Control",                             0,              0)
  124         N(0x0002,       "Numeric Key Pad",                              0,              0)
  125         N(0x0003,       "Programmable Buttons",                         0,              0)
  126         N(0x0004,       "Microphone",                                   0,              0)
  127         N(0x0005,       "Headphone",                                    0,              0)
  128         N(0x0006,       "Graphic Equalizer",                            0,              0)
  129         /* 0x0007-0x001F Reserved */
  130         N(0x0020,       "+10",                                          0,              0)
  131         N(0x0021,       "+100",                                         0,              0)
  132         N(0x0022,       "AM/PM",                                        0,              0)
  133         /* 0x0023-0x002F Reserved */
  134         Y(0x0030,       "Power",                                        0,              222 /* I5E = XF86PowerOff */)
  135         N(0x0031,       "Reset",                                        0,              0)
  136         Y(0x0032,       "Sleep",                                        0,              150 /* I16 = XF86Sleep */)
  137         N(0x0033,       "Sleep After",                                  0,              0)
  138         N(0x0034,       "Sleep Mode",                                   0,              0)
  139         N(0x0035,       "Illumination",                                 0,              0)
  140         N(0x0036,       "Function Buttons",                             0,              0)
  141         /* 0x0037-0x003F Reserved */
  142         N(0x0040,       "Menu",                                         0,              0)
  143         N(0x0041,       "Menu Pick",                                    0,              0)
  144         N(0x0042,       "Menu Up",                                      0,              0)
  145         N(0x0043,       "Menu Down",                                    0,              0)
  146         N(0x0044,       "Menu Left",                                    0,              0)
  147         N(0x0045,       "Menu Right",                                   0,              0)
  148         N(0x0046,       "Menu Escape",                                  0,              0)
  149         N(0x0047,       "Menu Value Increase",                          0,              0)
  150         N(0x0048,       "Menu Value Decrease",                          0,              0)
  151         /* 0x0049-0x005F Reserved */
  152         N(0x0060,       "Data On Screen",                               0,              0)
  153         N(0x0061,       "Closed Caption",                               0,              0)
  154         N(0x0062,       "Closed Caption Select",                        0,              0)
  155         N(0x0063,       "VCR/TV",                                       0,              0)
  156         N(0x0064,       "Broadcast Mode",                               0,              0)
  157         N(0x0065,       "Snapshot",                                     0,              0)
  158         N(0x0066,       "Still",                                        0,              0)
  159         N(0x0067,       "Picture-in-Picture Toggle",                    0,              0)
  160         N(0x0068,       "Picture-in-Picture Swap",                      0,              0)
  161         N(0x0069,       "Red Menu Button",                              0,              0)
  162         N(0x006A,       "Green Menu Button",                            0,              0)
  163         N(0x006B,       "Blue Menu Button",                             0,              0)
  164         N(0x006C,       "Yellow Menu Button",                           0,              0)
  165         N(0x006D,       "Aspect",                                       0,              0)
  166         N(0x006E,       "3D Mode Select",                               0,              0)
  167         Y(0x006F,       "Display Brightness Increment",                 KS_Cmd_BrightnessUp,            0)
  168         Y(0x0070,       "Display Brightness Decrement",                 KS_Cmd_BrightnessDown,          0)
  169         N(0x0071,       "Display Brightness",                           0,              0)
  170         N(0x0072,       "Display Backlight Toggle",                     0,              0)
  171         N(0x0073,       "Display Set Brightness to Minimum",            0,              0)
  172         N(0x0074,       "Display Set Brightness to Maximum",            0,              0)
  173         N(0x0075,       "Display Set Auto Brightness",                  0,              0)
  174         N(0x0076,       "Camera Access Enabled",                        0,              0)
  175         N(0x0077,       "Camera Access Disabled",                       0,              0)
  176         N(0x0078,       "Camera Access Toggle",                         0,              0)
  177         N(0x0079,       "Keyboard Brightness Increment",                0,              0)
  178         N(0x007A,       "Keyboard Brightness Decrement",                0,              0)
  179         N(0x007B,       "Keyboard Backlight Set Level",                 0,              0)
  180         N(0x007C,       "Keyboard Backlight OOC",                       0,              0)
  181         N(0x007D,       "Keyboard Backlight Set Minimum",               0,              0)
  182         N(0x007E,       "Keyboard Backlight Set Maximum",               0,              0)
  183         N(0x007F,       "Keyboard Backlight Auto",                      0,              0)
  184         N(0x0080,       "Selection",                                    0,              0)
  185         N(0x0081,       "Assign Selection",                             0,              0)
  186         N(0x0082,       "Mode Step",                                    0,              0)
  187         N(0x0083,       "Recall Last",                                  0,              0)
  188         N(0x0084,       "Enter Channel",                                0,              0)
  189         N(0x0085,       "Order Movie",                                  0,              0)
  190         N(0x0086,       "Channel",                                      0,              0)
  191         N(0x0087,       "Media Selection",                              0,              0)
  192         N(0x0088,       "Media Select Computer",                        0,              0)
  193         N(0x0089,       "Media Select TV",                              0,              0)
  194         N(0x008A,       "Media Select WWW",                             0,              0)
  195         N(0x008B,       "Media Select DVD",                             0,              0)
  196         N(0x008C,       "Media Select Telephone",                       0,              0)
  197         N(0x008D,       "Media Select Program Guide",                   0,              0)
  198         N(0x008E,       "Media Select Video Phone",                     0,              0)
  199         N(0x008F,       "Media Select Games",                           0,              0)
  200         N(0x0090,       "Media Select Messages",                        0,              0)
  201         N(0x0091,       "Media Select CD",                              0,              0)
  202         N(0x0092,       "Media Select VCR",                             0,              0)
  203         N(0x0093,       "Media Select Tuner",                           0,              0)
  204         N(0x0094,       "Quit",                                         0,              0)
  205         N(0x0095,       "Help",                                         0,              0)
  206         N(0x0096,       "Media Select Tape",                            0,              0)
  207         N(0x0097,       "Media Select Cable",                           0,              0)
  208         N(0x0098,       "Media Select Satellite",                       0,              0)
  209         N(0x0099,       "Media Select Security",                        0,              0)
  210         N(0x009A,       "Media Select Home",                            0,              0)
  211         N(0x009B,       "Media Select Call",                            0,              0)
  212         N(0x009C,       "Channel Increment",                            0,              0)
  213         N(0x009D,       "Channel Decrement",                            0,              0)
  214         N(0x009E,       "Media Select SAP",                             0,              0)
  215         /* 0x009F-0x009F Reserved */
  216         N(0x00A0,       "VCR Plus",                                     0,              0)
  217         N(0x00A1,       "Once",                                         0,              0)
  218         N(0x00A2,       "Daily",                                        0,              0)
  219         N(0x00A3,       "Weekly",                                       0,              0)
  220         N(0x00A4,       "Monthly",                                      0,              0)
  221         /* 0x00A5-0x00AF Reserved */
  222         N(0x00B0,       "Play",                                         0,              0)
  223         N(0x00B1,       "Pause",                                        0,              0)
  224         N(0x00B2,       "Record",                                       0,              0)
  225         N(0x00B3,       "Fast Forward",                                 0,              0)
  226         N(0x00B4,       "Rewind",                                       0,              0)
  227         Y(0x00B5,       "Scan Next Track",                              0,              153 /* I19 = XF86AudioNext */)
  228         Y(0x00B6,       "Scan Previous Track",                          0,              144 /* I10 = XF86AudioPrev */)
  229         Y(0x00B7,       "Stop",                                         0,              164 /* I24 = XF86AudioStop */)
  230         Y(0x00B8,       "Eject",                                        0,              170 /* K5A = XF86Eject */)
  231         N(0x00B9,       "Random Play",                                  0,              0)
  232         N(0x00BA,       "Select Disc",                                  0,              0)
  233         N(0x00BB,       "Enter Disc",                                   0,              0)
  234         N(0x00BC,       "Repeat",                                       0,              0)
  235         N(0x00BD,       "Tracking",                                     0,              0)
  236         N(0x00BE,       "Track Normal",                                 0,              0)
  237         N(0x00BF,       "Slow Tracking",                                0,              0)
  238         N(0x00C0,       "Frame Forward",                                0,              0)
  239         N(0x00C1,       "Frame Back",                                   0,              0)
  240         N(0x00C2,       "Mark",                                         0,              0)
  241         N(0x00C3,       "Clear Mark",                                   0,              0)
  242         N(0x00C4,       "Repeat From Mark",                             0,              0)
  243         N(0x00C5,       "Return To Mark",                               0,              0)
  244         N(0x00C6,       "Search Mark Forward",                          0,              0)
  245         N(0x00C7,       "Search Mark Backwards",                        0,              0)
  246         N(0x00C8,       "Counter Reset",                                0,              0)
  247         N(0x00C9,       "Show Counter",                                 0,              0)
  248         N(0x00CA,       "Tracking Increment",                           0,              0)
  249         N(0x00CB,       "Tracking Decrement",                           0,              0)
  250         N(0x00CC,       "Stop/Eject",                                   0,              0)
  251         Y(0x00CD,       "Play/Pause",                                   0,              162 /* I22 = XF86AudioPlay */)
  252         N(0x00CE,       "Play/Skip",                                    0,              0)
  253         N(0x00CF,       "Voice Command",                                0,              0)
  254         N(0x00D0,       "Invoke Capture Interface",                     0,              0)
  255         N(0x00D1,       "Start or Stop Game Recording",                 0,              0)
  256         N(0x00D2,       "Historical Game Capture",                      0,              0)
  257         N(0x00D3,       "Capture Game Screenshot",                      0,              0)
  258         N(0x00D4,       "Show or Hide Recording Indicator",             0,              0)
  259         N(0x00D5,       "Start or Stop Microphone Capture",             0,              0)
  260         N(0x00D6,       "Start or Stop Camera Capture",                 0,              0)
  261         N(0x00D7,       "Start or Stop Game Broadcast",                 0,              0)
  262         /* 0x00D8-0x00DF Reserved */
  263         N(0x00E0,       "Volume",                                       0,              0)
  264         N(0x00E1,       "Balance",                                      0,              0)
  265         Y(0x00E2,       "Mute",                                         KS_AudioMute,   160 /* I20 = XF86AudioMute */)
  266         N(0x00E3,       "Bass",                                         0,              0)
  267         N(0x00E4,       "Treble",                                       0,              0)
  268         N(0x00E5,       "Bass Boost",                                   0,              0)
  269         N(0x00E6,       "Surround Mode",                                0,              0)
  270         N(0x00E7,       "Loudness",                                     0,              0)
  271         N(0x00E8,       "MPX",                                          0,              0)
  272         Y(0x00E9,       "Volume Increment",                             KS_AudioRaise,  176 /* I30 = XF86AudioRaiseVolume */)
  273         Y(0x00EA,       "Volume Decrement",                             KS_AudioLower,  174 /* I2E = XF86AudioLowerVolume */)
  274         /* 0x00EB-0x00EF Reserved */
  275         N(0x00F0,       "Speed Select",                                 0,              0)
  276         N(0x00F1,       "Playback Speed",                               0,              0)
  277         N(0x00F2,       "Standard Play",                                0,              0)
  278         N(0x00F3,       "Long Play",                                    0,              0)
  279         N(0x00F4,       "Extended Play",                                0,              0)
  280         N(0x00F5,       "Slow",                                         0,              0)
  281         /* 0x00F6-0x00FF Reserved */
  282         N(0x0100,       "Fan Enable",                                   0,              0)
  283         N(0x0101,       "Fan Speed",                                    0,              0)
  284         N(0x0102,       "Light Enable",                                 0,              0)
  285         N(0x0103,       "Light Illumination Level",                     0,              0)
  286         N(0x0104,       "Climate Control Enable",                       0,              0)
  287         N(0x0105,       "Room Temperature",                             0,              0)
  288         N(0x0106,       "Security Enable",                              0,              0)
  289         N(0x0107,       "Fire Alarm",                                   0,              0)
  290         N(0x0108,       "Police Alarm",                                 0,              0)
  291         N(0x0109,       "Proximity",                                    0,              0)
  292         N(0x010A,       "Motion",                                       0,              0)
  293         N(0x010B,       "Duress Alarm",                                 0,              0)
  294         N(0x010C,       "Holdup Alarm",                                 0,              0)
  295         N(0x010D,       "Medical Alarm",                                0,              0)
  296         /* 0x010E-0x014F Reserved */
  297         N(0x0150,       "Balance Right",                                0,              0)
  298         N(0x0151,       "Balance Left",                                 0,              0)
  299         N(0x0152,       "Bass Increment",                               0,              0)
  300         N(0x0153,       "Bass Decrement",                               0,              0)
  301         N(0x0154,       "Treble Increment",                             0,              0)
  302         N(0x0155,       "Treble Decrement",                             0,              0)
  303         /* 0x0156-0x015F Reserved */
  304         N(0x0160,       "Speaker System",                               0,              0)
  305         N(0x0161,       "Channel Left",                                 0,              0)
  306         N(0x0162,       "Channel Right",                                0,              0)
  307         N(0x0163,       "Channel Center",                               0,              0)
  308         N(0x0164,       "Channel Front",                                0,              0)
  309         N(0x0165,       "Channel Center Front",                         0,              0)
  310         N(0x0166,       "Channel Side",                                 0,              0)
  311         N(0x0167,       "Channel Surround",                             0,              0)
  312         N(0x0168,       "Channel Low Frequency Enhancement",            0,              0)
  313         N(0x0169,       "Channel Top",                                  0,              0)
  314         N(0x016A,       "Channel Unknown",                              0,              0)
  315         /* 0x016B-0x016F Reserved */
  316         N(0x0170,       "Sub-channel",                                  0,              0)
  317         N(0x0171,       "Sub-channel Increment",                        0,              0)
  318         N(0x0172,       "Sub-channel Decrement",                        0,              0)
  319         N(0x0173,       "Alternate Audio Increment",                    0,              0)
  320         N(0x0174,       "Alternate Audio Decrement",                    0,              0)
  321         /* 0x0175-0x017F Reserved */
  322         N(0x0180,       "Application Launch Buttons",                   0,              0)
  323         N(0x0181,       "AL Launch Button Configuration Tool",          0,              0)
  324         N(0x0182,       "AL Programmable Button Configuration",         0,              0)
  325         N(0x0183,       "AL Consumer Control Configuration",            0,              0)
  326         N(0x0184,       "AL Word Processor",                            0,              0)
  327         N(0x0185,       "AL Text Editor",                               0,              0)
  328         N(0x0186,       "AL Spreadsheet",                               0,              0)
  329         N(0x0187,       "AL Graphics Editor",                           0,              0)
  330         N(0x0188,       "AL Presentation App",                          0,              0)
  331         N(0x0189,       "AL Database App",                              0,              0)
  332         Y(0x018A,       "AL Email Reader",                              0,              235 /* I6C = XF86Mail */)
  333         N(0x018B,       "AL Newsreader",                                0,              0)
  334         N(0x018C,       "AL Voicemail",                                 0,              0)
  335         N(0x018D,       "AL Contacts/Address Book",                     0,              0)
  336         N(0x018E,       "AL Calendar/Schedule",                         0,              0)
  337         N(0x018F,       "AL Task/Project Manager",                      0,              0)
  338         N(0x0190,       "AL Log/Journal/Timecard",                      0,              0)
  339         N(0x0191,       "AL Checkbook/Finance",                         0,              0)
  340         Y(0x0192,       "AL Calculator",                                0,              161 /* I21 = XF86Calculator */)
  341         N(0x0193,       "AL A/V Capture/Playback",                      0,              0)
  342         N(0x0194,       "AL Local Machine Browser",                     0,              0)
  343         N(0x0195,       "AL LAN/WAN Browser",                           0,              0)
  344         Y(0x0196,       "AL Internet Browser",                          0,              178 /* I32 = XF86WWW */)
  345         N(0x0197,       "AL Remote Networking/ISP Connect",             0,              0)
  346         N(0x0198,       "AL Network Conference",                        0,              0)
  347         N(0x0199,       "AL Network Chat",                              0,              0)
  348         N(0x019A,       "AL Telephony/Dialer",                          0,              0)
  349         N(0x019B,       "AL Logon",                                     0,              0)
  350         N(0x019C,       "AL Logoff",                                    0,              0)
  351         N(0x019D,       "AL Logon/Logoff",                              0,              0)
  352         N(0x019E,       "AL Terminal Lock/Screensaver",                 0,              0)
  353         N(0x019F,       "AL Control Panel",                             0,              0)
  354         N(0x01A0,       "AL Command Line Processor/Run",                0,              0)
  355         N(0x01A1,       "AL Process/Task Manager",                      0,              0)
  356         N(0x01A2,       "AL Select Task/Application",                   0,              0)
  357         N(0x01A3,       "AL Next Task/Application",                     0,              0)
  358         N(0x01A4,       "AL Previous Task/Application",                 0,              0)
  359         N(0x01A5,       "AL Preemptive Halt Task/Application",          0,              0)
  360         N(0x01A6,       "AL Integrated Help Center",                    0,              0)
  361         N(0x01A7,       "AL My Documents",                              0,              0)
  362         N(0x01A8,       "AL Thesaurus",                                 0,              0)
  363         N(0x01A9,       "AL Dictionary",                                0,              0)
  364         N(0x01AA,       "AL Desktop",                                   0,              0)
  365         N(0x01AB,       "AC Spell",                                     0,              0)
  366         N(0x01AC,       "AL Grammar Check",                             0,              0)
  367         N(0x01AD,       "AL Wireless Status",                           0,              0)
  368         N(0x01AE,       "AL Keyboard Layout",                           0,              0)
  369         N(0x01AF,       "AL Virus Protection",                          0,              0)
  370         N(0x01B0,       "AL Encryption",                                0,              0)
  371         N(0x01B1,       "AL Screen Saver",                              0,              0)
  372         N(0x01B2,       "AL Alarms",                                    0,              0)
  373         N(0x01B3,       "AL Clock",                                     0,              0)
  374         N(0x01B4,       "AL File Browser",                              0,              0)
  375         N(0x01B5,       "AL Power Status",                              0,              0)
  376         N(0x01B6,       "AL My Pictures",                               0,              0)
  377         N(0x01B7,       "AL My Music",                                  0,              0)
  378         N(0x01B8,       "AL Movie Browser",                             0,              0)
  379         N(0x01B9,       "AL Digital Rights Manager",                    0,              0)
  380         N(0x01BA,       "AL Digital Wallet",                            0,              0)
  381         /* 0x01BB-0x01BB Reserved */
  382         N(0x01BC,       "AL Instant Messaging",                         0,              0)
  383         N(0x01BD,       "AL OEM Feature/Tips/Tutorial Browser",         0,              0)
  384         N(0x01BE,       "AL OEM Help",                                  0,              0)
  385         N(0x01BF,       "AL Online Community",                          0,              0)
  386         N(0x01C0,       "AL Entertainment Content Browser",             0,              0)
  387         N(0x01C1,       "AL Online Shopping Browser",                   0,              0)
  388         N(0x01C2,       "AL SmartCard Information/Help",                0,              0)
  389         N(0x01C3,       "AL Market Monitor/Finance Browser",            0,              0)
  390         N(0x01C4,       "AL Customized Corporate News Browser",         0,              0)
  391         N(0x01C5,       "AL Online Activity Browser",                   0,              0)
  392         Y(0x01C6,       "AL Research/Search Browser",                   0,              229 /* I65 = XF86Search */)
  393         N(0x01C7,       "AL Audio Player",                              0,              0)
  394         N(0x01C8,       "AL Message Status",                            0,              0)
  395         N(0x01C9,       "AL Contact Sync",                              0,              0)
  396         N(0x01CA,       "AL Navigation",                                0,              0)
  397         N(0x01CB,       "AL Context-aware Desktop Assistant",           0,              0)
  398         /* 0x01CC-0x01FF Reserved */
  399         N(0x0200,       "Generic GUI Application Controls",             0,              0)
  400         N(0x0201,       "AC New",                                       0,              0)
  401         N(0x0202,       "AC Open",                                      0,              0)
  402         N(0x0203,       "AC Close",                                     0,              0)
  403         N(0x0204,       "AC Exit",                                      0,              0)
  404         N(0x0205,       "AC Maximize",                                  0,              0)
  405         N(0x0206,       "AC Minimize",                                  0,              0)
  406         N(0x0207,       "AC Save",                                      0,              0)
  407         N(0x0208,       "AC Print",                                     0,              0)
  408         N(0x0209,       "AC Properties",                                0,              0)
  409         /* 0x020A-0x0219 Reserved */
  410         N(0x021A,       "AC Undo",                                      0,              0)
  411         N(0x021B,       "AC Copy",                                      0,              0)
  412         N(0x021C,       "AC Cut",                                       0,              0)
  413         N(0x021D,       "AC Paste",                                     0,              0)
  414         N(0x021E,       "AC Select All",                                0,              0)
  415         N(0x021F,       "AC Find",                                      0,              0)
  416         N(0x0220,       "AC Find and Replace",                          0,              0)
  417         N(0x0221,       "AC Search",                                    0,              0)
  418         N(0x0222,       "AC Go To",                                     0,              0)
  419         N(0x0223,       "AC Home",                                      0,              0)
  420         Y(0x0224,       "AC Back",                                      0,              234 /* I6A = XF86Back */)
  421         Y(0x0225,       "AC Forward",                                   0,              233 /* I69 = XF86Forward */)
  422         Y(0x0226,       "AC Stop",                                      0,              232 /* I68 = XF86Stop */)
  423         Y(0x0227,       "AC Refresh",                                   0,              231 /* I67 = XF86Reload */)
  424         N(0x0228,       "AC Previous Link",                             0,              0)
  425         N(0x0229,       "AC Next Link",                                 0,              0)
  426         N(0x022A,       "AC Bookmarks",                                 0,              0)
  427         N(0x022B,       "AC History",                                   0,              0)
  428         N(0x022C,       "AC Subscriptions",                             0,              0)
  429         N(0x022D,       "AC Zoom In",                                   0,              0)
  430         N(0x022E,       "AC Zoom Out",                                  0,              0)
  431         N(0x022F,       "AC Zoom",                                      0,              0)
  432         N(0x0230,       "AC Full Screen View",                          0,              0)
  433         N(0x0231,       "AC Normal View",                               0,              0)
  434         N(0x0232,       "AC View Toggle",                               0,              0)
  435         N(0x0233,       "AC Scroll Up",                                 0,              0)
  436         N(0x0234,       "AC Scroll Down",                               0,              0)
  437         N(0x0235,       "AC Scroll",                                    0,              0)
  438         N(0x0236,       "AC Pan Left",                                  0,              0)
  439         N(0x0237,       "AC Pan Right",                                 0,              0)
  440         N(0x0238,       "AC Pan",                                       0,              0)
  441         N(0x0239,       "AC New Window",                                0,              0)
  442         N(0x023A,       "AC Tile Horizontally",                         0,              0)
  443         N(0x023B,       "AC Tile Vertically",                           0,              0)
  444         N(0x023C,       "AC Format",                                    0,              0)
  445         N(0x023D,       "AC Edit",                                      0,              0)
  446         N(0x023E,       "AC Bold",                                      0,              0)
  447         N(0x023F,       "AC Italics",                                   0,              0)
  448         N(0x0240,       "AC Underline",                                 0,              0)
  449         N(0x0241,       "AC Strikethrough",                             0,              0)
  450         N(0x0242,       "AC Subscript",                                 0,              0)
  451         N(0x0243,       "AC Superscript",                               0,              0)
  452         N(0x0244,       "AC All Caps",                                  0,              0)
  453         N(0x0245,       "AC Rotate",                                    0,              0)
  454         N(0x0246,       "AC Resize",                                    0,              0)
  455         N(0x0247,       "AC Flip Horizontal",                           0,              0)
  456         N(0x0248,       "AC Flip Vertical",                             0,              0)
  457         N(0x0249,       "AC Mirror Horizontal",                         0,              0)
  458         N(0x024A,       "AC Mirror Vertical",                           0,              0)
  459         N(0x024B,       "AC Font Select",                               0,              0)
  460         N(0x024C,       "AC Font Color",                                0,              0)
  461         N(0x024D,       "AC Font Size",                                 0,              0)
  462         N(0x024E,       "AC Justify Left",                              0,              0)
  463         N(0x024F,       "AC Justify Center H",                          0,              0)
  464         N(0x0250,       "AC Justify Right",                             0,              0)
  465         N(0x0251,       "AC Justify Block H",                           0,              0)
  466         N(0x0252,       "AC Justify Top",                               0,              0)
  467         N(0x0253,       "AC Justify Center V",                          0,              0)
  468         N(0x0254,       "AC Justify Bottom",                            0,              0)
  469         N(0x0255,       "AC Justify Block V",                           0,              0)
  470         N(0x0256,       "AC Justify Decrease",                          0,              0)
  471         N(0x0257,       "AC Justify Increase",                          0,              0)
  472         N(0x0258,       "AC Numbered List",                             0,              0)
  473         N(0x0259,       "AC Restart Numbering",                         0,              0)
  474         N(0x025A,       "AC Bulleted List",                             0,              0)
  475         N(0x025B,       "AC Promote",                                   0,              0)
  476         N(0x025C,       "AC Demote",                                    0,              0)
  477         N(0x025D,       "AC Yes",                                       0,              0)
  478         N(0x025E,       "AC No",                                        0,              0)
  479         N(0x025F,       "AC Cancel",                                    0,              0)
  480         N(0x0260,       "AC Catalog",                                   0,              0)
  481         N(0x0261,       "AC Buy/Checkout",                              0,              0)
  482         N(0x0262,       "AC Add to Cart",                               0,              0)
  483         N(0x0263,       "AC Expand",                                    0,              0)
  484         N(0x0264,       "AC Expand All",                                0,              0)
  485         N(0x0265,       "AC Collapse",                                  0,              0)
  486         N(0x0266,       "AC Collapse All",                              0,              0)
  487         N(0x0267,       "AC Print Preview",                             0,              0)
  488         N(0x0268,       "AC Paste Special",                             0,              0)
  489         N(0x0269,       "AC Insert Mode",                               0,              0)
  490         N(0x026A,       "AC Delete",                                    0,              0)
  491         N(0x026B,       "AC Lock",                                      0,              0)
  492         N(0x026C,       "AC Unlock",                                    0,              0)
  493         N(0x026D,       "AC Protect",                                   0,              0)
  494         N(0x026E,       "AC Unprotect",                                 0,              0)
  495         N(0x026F,       "AC Attach Comment",                            0,              0)
  496         N(0x0270,       "AC Delete Comment",                            0,              0)
  497         N(0x0271,       "AC View Comment",                              0,              0)
  498         N(0x0272,       "AC Select Word",                               0,              0)
  499         N(0x0273,       "AC Select Sentence",                           0,              0)
  500         N(0x0274,       "AC Select Paragraph",                          0,              0)
  501         N(0x0275,       "AC Select Column",                             0,              0)
  502         N(0x0276,       "AC Select Row",                                0,              0)
  503         N(0x0277,       "AC Select Table",                              0,              0)
  504         N(0x0278,       "AC Select Object",                             0,              0)
  505         N(0x0279,       "AC Redo/Repeat",                               0,              0)
  506         N(0x027A,       "AC Sort",                                      0,              0)
  507         N(0x027B,       "AC Sort Ascending",                            0,              0)
  508         N(0x027C,       "AC Sort Descending",                           0,              0)
  509         N(0x027D,       "AC Filter",                                    0,              0)
  510         N(0x027E,       "AC Set Clock",                                 0,              0)
  511         N(0x027F,       "AC View Clock",                                0,              0)
  512         N(0x0280,       "AC Select Time Zone",                          0,              0)
  513         N(0x0281,       "AC Edit Time Zones",                           0,              0)
  514         N(0x0282,       "AC Set Alarm",                                 0,              0)
  515         N(0x0283,       "AC Clear Alarm",                               0,              0)
  516         N(0x0284,       "AC Snooze Alarm",                              0,              0)
  517         N(0x0285,       "AC Reset Alarm",                               0,              0)
  518         N(0x0286,       "AC Synchronize",                               0,              0)
  519         N(0x0287,       "AC Send/Receive",                              0,              0)
  520         N(0x0288,       "AC Send To",                                   0,              0)
  521         N(0x0289,       "AC Reply",                                     0,              0)
  522         N(0x028A,       "AC Reply All",                                 0,              0)
  523         N(0x028B,       "AC Forward Message",                           0,              0)
  524         N(0x028C,       "AC Send",                                      0,              0)
  525         N(0x028D,       "AC Attach File",                               0,              0)
  526         N(0x028E,       "AC Upload",                                    0,              0)
  527         N(0x028F,       "AC Download (Save Target As)",                 0,              0)
  528         N(0x0290,       "AC Set Borders",                               0,              0)
  529         N(0x0291,       "AC Insert Row",                                0,              0)
  530         N(0x0292,       "AC Insert Column",                             0,              0)
  531         N(0x0293,       "AC Insert File",                               0,              0)
  532         N(0x0294,       "AC Insert Picture",                            0,              0)
  533         N(0x0295,       "AC Insert Object",                             0,              0)
  534         N(0x0296,       "AC Insert Symbol",                             0,              0)
  535         N(0x0297,       "AC Save and Close",                            0,              0)
  536         N(0x0298,       "AC Rename",                                    0,              0)
  537         N(0x0299,       "AC Merge",                                     0,              0)
  538         N(0x029A,       "AC Split",                                     0,              0)
  539         N(0x029B,       "AC Distribute Horizontally",                   0,              0)
  540         N(0x029C,       "AC Distribute Vertically",                     0,              0)
  541         N(0x029D,       "AC Next Keyboard Layout Select",               0,              0)
  542         N(0x029E,       "AC Navigation Guidance",                       0,              0)
  543         N(0x029F,       "AC Desktop Show All Windows",                  0,              0)
  544         N(0x02A0,       "AC Soft Key Left",                             0,              0)
  545         N(0x02A1,       "AC Soft Key Right",                            0,              0)
  546         N(0x02A2,       "AC Desktop Show All Applications",             0,              0)
  547         /* 0x02A3-0x02AF Reserved */
  548         N(0x02B0,       "AC Idle Keep Alive",                           0,              0)
  549         /* 0x02B1-0x02BF Reserved */
  550         N(0x02C0,       "Extended Keyboard Attributes Collection",      0,              0)
  551         N(0x02C1,       "Keyboard Form Factor",                         0,              0)
  552         N(0x02C2,       "Keyboard Key Type",                            0,              0)
  553         N(0x02C3,       "Keyboard Physical Layout",                     0,              0)
  554         N(0x02C4,       "Vendor-Specific Keyboard Physical Layout",     0,              0)
  555         N(0x02C5,       "Keyboard IETF Language Tag Index",             0,              0)
  556         N(0x02C6,       "Implemented Keyboard Input Assist Controls",   0,              0)
  557         N(0x02C7,       "Keyboard Input Assist Previous",               0,              0)
  558         N(0x02C8,       "Keyboard Input Assist Next",                   0,              0)
  559         N(0x02C9,       "Keyboard Input Assist Previous Group",         0,              0)
  560         N(0x02CA,       "Keyboard Input Assist Next Group",             0,              0)
  561         N(0x02CB,       "Keyboard Input Assist Accept",                 0,              0)
  562         N(0x02CC,       "Keyboard Input Assist Cancel",                 0,              0)
  563         /* 0x02CD-0x02CF Reserved */
  564         N(0x02D0,       "Privacy Screen Toggle",                        0,              0)
  565         N(0x02D1,       "Privacy Screen Level Decrement",               0,              0)
  566         N(0x02D2,       "Privacy Screen Level Increment",               0,              0)
  567         N(0x02D3,       "Privacy Screen Level Minimum",                 0,              0)
  568         N(0x02D4,       "Privacy Screen Level Maximum",                 0,              0)
  569         /* 0x02D5-0x04FF Reserved */
  570         N(0x0500,       "Contact Edited",                               0,              0)
  571         N(0x0501,       "Contact Added",                                0,              0)
  572         N(0x0502,       "Contact Record Active",                        0,              0)
  573         N(0x0503,       "Contact Index",                                0,              0)
  574         N(0x0504,       "Contact Nickname",                             0,              0)
  575         N(0x0505,       "Contact First Name",                           0,              0)
  576         N(0x0506,       "Contact Last Name",                            0,              0)
  577         N(0x0507,       "Contact Full Name",                            0,              0)
  578         N(0x0508,       "Contact Phone Number Personal",                0,              0)
  579         N(0x0509,       "Contact Phone Number Business",                0,              0)
  580         N(0x050A,       "Contact Phone Number Mobile",                  0,              0)
  581         N(0x050B,       "Contact Phone Number Pager",                   0,              0)
  582         N(0x050C,       "Contact Phone Number Fax",                     0,              0)
  583         N(0x050D,       "Contact Phone Number Other",                   0,              0)
  584         N(0x050E,       "Contact Email Personal",                       0,              0)
  585         N(0x050F,       "Contact Email Business",                       0,              0)
  586         N(0x0510,       "Contact Email Other",                          0,              0)
  587         N(0x0511,       "Contact Email Main",                           0,              0)
  588         N(0x0512,       "Contact Speed Dial Number",                    0,              0)
  589         N(0x0513,       "Contact Status Flag",                          0,              0)
  590         N(0x0514,       "Contact Misc.",                                0,              0)
  591         /* 0x0515-0xFFFF Reserved */
  592 #undef Y
  593 #undef N
  594 };
  595 
  596 void    hidcc_attach_wskbd(struct hidcc *);
  597 int     hidcc_enable(void *, int);
  598 void    hidcc_set_leds(void *, int);
  599 int     hidcc_ioctl(void *, u_long, caddr_t, int, struct proc *);
  600 
  601 int     hidcc_parse(struct hidcc *, void *, int, int, int);
  602 int     hidcc_parse_array(struct hidcc *, const struct hid_item *);
  603 int     hidcc_is_array(const struct hid_item *);
  604 int     hidcc_add_key(struct hidcc *, int32_t, u_int);
  605 int     hidcc_add_key_volume(struct hidcc *, const struct hid_item *, uint32_t,
  606     u_int);
  607 int     hidcc_bit_to_sym(struct hidcc *, u_int, const struct hidcc_keysym **);
  608 int     hidcc_usage_to_sym(int32_t, const struct hidcc_keysym **);
  609 int     hidcc_bits_to_int(uint8_t *, u_int, int32_t *);
  610 int     hidcc_bits_to_volume(struct hidcc *, uint8_t *, int, u_int *);
  611 int     hidcc_intr_slice(struct hidcc *, uint8_t *, uint8_t *, int *);
  612 void    hidcc_input(struct hidcc *, u_int, int);
  613 void    hidcc_rawinput(struct hidcc *, u_char, int);
  614 int     hidcc_setbits(struct hidcc *, uint8_t *, int, u_int *);
  615 
  616 /*
  617  * Returns non-zero if the given report ID has at least one Consumer Control
  618  * usage.
  619  */
  620 int
  621 hidcc_match(void *desc, int descsiz, uint8_t repid)
  622 {
  623         struct hid_item hi;
  624         struct hid_data *hd;
  625         int32_t maxusage = 0;
  626 
  627         hd = hid_start_parse(desc, descsiz, hid_input);
  628         while (hid_get_item(hd, &hi)) {
  629                 if (hi.report_ID == repid &&
  630                     hi.kind == hid_input &&
  631                     HID_GET_USAGE_PAGE(hi.usage) == HUP_CONSUMER) {
  632                         if (HID_GET_USAGE(hi.usage_maximum) > maxusage)
  633                                 maxusage = HID_GET_USAGE(hi.usage_maximum);
  634                         else if (HID_GET_USAGE(hi.usage) > maxusage)
  635                                 maxusage = HID_GET_USAGE(hi.usage);
  636                 }
  637         }
  638         hid_end_parse(hd);
  639         return maxusage > 0;
  640 }
  641 
  642 struct hidcc *
  643 hidcc_attach(const struct hidcc_attach_arg *hca)
  644 {
  645         struct hidcc *sc;
  646         int error;
  647 
  648         sc = malloc(sizeof(*sc), M_USBDEV, M_WAITOK | M_ZERO);
  649         sc->sc_dev = hca->device;
  650         sc->sc_mode = WSKBD_TRANSLATED;
  651         sc->sc_last_translate = -1;
  652         sc->sc_enable = hca->enable;
  653         sc->sc_arg = hca->arg;
  654 
  655         error = hidcc_parse(sc, hca->desc, hca->descsiz, hca->repid,
  656             hca->isize);
  657         if (error) {
  658                 printf(": hid error %d\n", error);
  659                 free(sc, M_USBDEV, sizeof(*sc));
  660                 return NULL;
  661         }
  662 
  663         printf(": %d usage%s, %d key%s, %s\n",
  664             sc->sc_nusages, sc->sc_nusages == 1 ? "" : "s",
  665             sc->sc_maplen / 2, sc->sc_maplen / 2 == 1 ? "" : "s",
  666             sc->sc_isarray ? "array" : "enum");
  667 
  668         /* Cannot load an empty map. */
  669         if (sc->sc_maplen > 0)
  670                 hidcc_attach_wskbd(sc);
  671 
  672         return sc;
  673 }
  674 
  675 int
  676 hidcc_detach(struct hidcc *sc, int flags)
  677 {
  678         int error = 0;
  679 
  680         if (sc->sc_wskbddev != NULL)
  681                 error = config_detach(sc->sc_wskbddev, flags);
  682         free(sc->sc_input.i_buf, M_USBDEV, sc->sc_input.i_bufsiz);
  683         free(sc->sc_map, M_USBDEV, sc->sc_mapsiz * sizeof(*sc->sc_map));
  684         free(sc->sc_raw, M_USBDEV, sc->sc_rawsiz * sizeof(*sc->sc_raw));
  685         free(sc, M_USBDEV, sizeof(*sc));
  686         return error;
  687 }
  688 
  689 void
  690 hidcc_intr(struct hidcc *sc, void *data, u_int len)
  691 {
  692         const struct hidcc_keysym *ks;
  693         uint8_t *buf = sc->sc_input.i_buf;
  694         int raw = sc->sc_mode == WSKBD_RAW;
  695         int error;
  696         u_int bit = 0;
  697 
  698         hidcc_dump(sc, __func__, data, len);
  699 
  700         if (len > sc->sc_input.i_bufsiz)
  701                 len = sc->sc_input.i_bufsiz;
  702         error = hidcc_intr_slice(sc, data, buf, &len);
  703         if (error) {
  704                 DPRINTF("%s: slice failure: error %d\n", DEVNAME(sc), error);
  705                 return;
  706         }
  707 
  708         /* Dump the buffer again after slicing. */
  709         hidcc_dump(sc, __func__, buf, len);
  710 
  711         if (hidcc_setbits(sc, buf, len, &bit)) {
  712                 /* All zeroes, assume key up event. */
  713                 if (raw) {
  714                         if (sc->sc_last_raw != 0) {
  715                                 hidcc_rawinput(sc, sc->sc_last_raw, 1);
  716                                 sc->sc_last_raw = 0;
  717                         }
  718                 } else {
  719                         if (sc->sc_last_translate != -1) {
  720                                 hidcc_input(sc, sc->sc_last_translate, 1);
  721                                 sc->sc_last_translate = -1;
  722                         }
  723                 }
  724                 return;
  725         } else if (sc->sc_isarray) {
  726                 int32_t usage;
  727 
  728                 if (hidcc_bits_to_int(buf, len, &usage) ||
  729                     hidcc_usage_to_sym(usage, &ks))
  730                         goto unknown;
  731                 bit = ks->ks_usage;
  732         } else if (raw) {
  733                 if (hidcc_bit_to_sym(sc, bit, &ks))
  734                         goto unknown;
  735         }
  736 
  737         if (raw) {
  738                 hidcc_rawinput(sc, ks->ks_raw, 0);
  739                 sc->sc_last_raw = ks->ks_raw;
  740                 /*
  741                  * Feed both raw and translating input for keys that have both
  742                  * defined. This is only the case for volume related keys.
  743                  */
  744                 if (ks->ks_key == 0)
  745                         return;
  746         }
  747 
  748         hidcc_input(sc, bit, 0);
  749         if (!raw)
  750                 sc->sc_last_translate = bit;
  751         return;
  752 
  753 unknown:
  754         DPRINTF("%s: unknown key: bit %d\n", DEVNAME(sc), bit);
  755 }
  756 
  757 void
  758 hidcc_attach_wskbd(struct hidcc *sc)
  759 {
  760         static const struct wskbd_accessops accessops = {
  761                 .enable         = hidcc_enable,
  762                 .set_leds       = hidcc_set_leds,
  763                 .ioctl          = hidcc_ioctl,
  764         };
  765         struct wskbddev_attach_args a = {
  766                 .console        = 0,
  767                 .keymap         = &sc->sc_keymap,
  768                 .accessops      = &accessops,
  769                 .accesscookie   = sc,
  770                 .audiocookie    = NULL, /* XXX audio_cookie */
  771         };
  772 
  773         sc->sc_keydesc[0].name = KB_US;
  774         sc->sc_keydesc[0].base = 0;
  775         sc->sc_keydesc[0].map_size = sc->sc_maplen;
  776         sc->sc_keydesc[0].map = sc->sc_map;
  777         sc->sc_keymap.keydesc = sc->sc_keydesc;
  778         sc->sc_keymap.layout = KB_US | KB_NOENCODING;
  779         sc->sc_wskbddev = config_found(sc->sc_dev, &a, wskbddevprint);
  780 }
  781 
  782 int
  783 hidcc_enable(void *v, int on)
  784 {
  785         struct hidcc *sc = (struct hidcc *)v;
  786 
  787         return sc->sc_enable(sc->sc_arg, on);
  788 }
  789 
  790 void
  791 hidcc_set_leds(void *v, int leds)
  792 {
  793 }
  794 
  795 int
  796 hidcc_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  797 {
  798         switch (cmd) {
  799         /* wsconsctl(8) stub */
  800         case WSKBDIO_GTYPE:
  801                 *(int *)data = WSKBD_TYPE_USB;
  802                 return 0;
  803 
  804         /* wsconsctl(8) stub */
  805         case WSKBDIO_GETLEDS:
  806                 *(int *)data = 0;
  807                 return 0;
  808 
  809 #ifdef WSDISPLAY_COMPAT_RAWKBD
  810         case WSKBDIO_SETMODE: {
  811                 struct hidcc *sc = (struct hidcc *)v;
  812 
  813                 sc->sc_mode = *(int *)data;
  814                 return 0;
  815         }
  816 #endif
  817         }
  818 
  819         return -1;
  820 }
  821 
  822 /*
  823  * Parse the HID report and construct a mapping between the bits in the input
  824  * report and the corresponding pressed key.
  825  */
  826 int
  827 hidcc_parse(struct hidcc *sc, void *desc, int descsiz, int repid, int isize)
  828 {
  829         enum { OFFSET, LENGTH } istate = OFFSET;
  830         struct hid_item hi;
  831         struct hid_data *hd;
  832         u_int bit = 0;
  833         int error = 0;
  834         int nsyms = nitems(hidcc_keysyms);
  835         int nbits;
  836 
  837         /*
  838          * The size of the input report is expressed in bytes where each bit in
  839          * turn represents a pressed key. It's likely that the number of keys is
  840          * less than this generous estimate.
  841          */
  842         nbits = isize * 8;
  843         if (nbits == 0)
  844                 return ENXIO;
  845 
  846         /* Allocate buffer used to slice interrupt data. */
  847         sc->sc_input.i_bufsiz = isize;
  848         sc->sc_input.i_buf = malloc(sc->sc_input.i_bufsiz, M_USBDEV, M_WAITOK);
  849 
  850         /*
  851          * Create mapping between each input bit and the corresponding usage,
  852          * used in translating mode. Two entries are needed per bit in order
  853          * construct a mapping. Note that at most all known usages as given by
  854          * hidcc_keysyms can be inserted into this map.
  855          */
  856         sc->sc_mapsiz = nsyms * 2;
  857         sc->sc_map = mallocarray(nsyms, 2 * sizeof(*sc->sc_map), M_USBDEV,
  858             M_WAITOK | M_ZERO);
  859 
  860         /*
  861          * Create mapping between each input bit and the corresponding usage,
  862          * used in raw mode.
  863          */
  864         sc->sc_rawsiz = nbits;
  865         sc->sc_raw = mallocarray(nbits, sizeof(*sc->sc_raw), M_USBDEV,
  866             M_WAITOK | M_ZERO);
  867 
  868         hd = hid_start_parse(desc, descsiz, hid_input);
  869         while (hid_get_item(hd, &hi)) {
  870                 uint32_t off;
  871                 int32_t usage;
  872 
  873                 if (hi.report_ID != repid || hi.kind != hid_input)
  874                         continue;
  875 
  876                 if (HID_GET_USAGE_PAGE(hi.usage) != HUP_CONSUMER) {
  877                         uint32_t len = hi.loc.size * hi.loc.count;
  878 
  879                         switch (istate) {
  880                         case OFFSET:
  881                                 sc->sc_input.i_off = hi.loc.pos + len;
  882                                 break;
  883                         case LENGTH:
  884                                 /* Constant padding. */
  885                                 if (hi.flags & HIO_CONST)
  886                                         sc->sc_input.i_len += len;
  887                                 break;
  888                         }
  889                         continue;
  890                 }
  891 
  892                 /* Signal that the input offset is reached. */
  893                 istate = LENGTH;
  894                 off = sc->sc_input.i_len;
  895                 sc->sc_input.i_len += hi.loc.size * hi.loc.count;
  896 
  897                 /*
  898                  * The usages could be expressed as an array instead of
  899                  * enumerating all supported ones.
  900                  */
  901                 if (hidcc_is_array(&hi)) {
  902                         error = hidcc_parse_array(sc, &hi);
  903                         break;
  904                 }
  905 
  906                 usage = HID_GET_USAGE(hi.usage);
  907                 if (usage == HUC_VOLUME)
  908                         error = hidcc_add_key_volume(sc, &hi, off, bit);
  909                 else
  910                         error = hidcc_add_key(sc, usage, bit);
  911                 if (error)
  912                         break;
  913                 sc->sc_nusages++;
  914                 bit += hi.loc.size * hi.loc.count;
  915         }
  916         hid_end_parse(hd);
  917 
  918         DPRINTF("%s: input: off %d, len %d\n", DEVNAME(sc),
  919             sc->sc_input.i_off, sc->sc_input.i_len);
  920 
  921         return error;
  922 }
  923 
  924 int
  925 hidcc_parse_array(struct hidcc *sc, const struct hid_item *hi)
  926 {
  927         int32_t max, min, usage;
  928 
  929         min = HID_GET_USAGE(hi->usage_minimum);
  930         max = HID_GET_USAGE(hi->usage_maximum);
  931 
  932         sc->sc_nusages = (max - min) + 1;
  933         sc->sc_isarray = 1;
  934 
  935         for (usage = min; usage <= max; usage++) {
  936                 int error;
  937 
  938                 error = hidcc_add_key(sc, usage, 0);
  939                 if (error)
  940                         return error;
  941         }
  942 
  943         return 0;
  944 }
  945 
  946 int
  947 hidcc_is_array(const struct hid_item *hi)
  948 {
  949         int32_t max, min;
  950 
  951         min = HID_GET_USAGE(hi->usage_minimum);
  952         max = HID_GET_USAGE(hi->usage_maximum);
  953         return min >= 0 && max > 0 && min < max;
  954 }
  955 
  956 int
  957 hidcc_add_key(struct hidcc *sc, int32_t usage, u_int bit)
  958 {
  959         const struct hidcc_keysym *ks;
  960 
  961         if (hidcc_usage_to_sym(usage, &ks))
  962                 return 0;
  963 
  964         if (sc->sc_maplen + 2 > sc->sc_mapsiz)
  965                 return ENOMEM;
  966         sc->sc_map[sc->sc_maplen++] = KS_KEYCODE(sc->sc_isarray ? usage : bit);
  967         sc->sc_map[sc->sc_maplen++] = ks->ks_key;
  968 
  969         if (!sc->sc_isarray) {
  970                 if (bit >= sc->sc_rawsiz)
  971                         return ENOMEM;
  972                 sc->sc_raw[bit] = ks;
  973         }
  974 
  975         DPRINTF("%s: bit %d, usage \"%s\"\n", DEVNAME(sc),
  976             bit, ks->ks_name);
  977         return 0;
  978 }
  979 
  980 /*
  981  * Add key mappings for the volume usage which differs compared to the volume
  982  * increment/decrement usages in which each volume change direction is
  983  * represented using a distinct usage. The volume usage instead uses bits of the
  984  * interrupt buffer to represent the wanted volume. The same bits should be
  985  * within the bounds given by the logical min/max associated with the HID item.
  986  */
  987 int
  988 hidcc_add_key_volume(struct hidcc *sc, const struct hid_item *hi,
  989     uint32_t off, u_int bit)
  990 {
  991         uint32_t len;
  992         int error;
  993 
  994         /*
  995          * Since the volume usage is internally represented using two key
  996          * mappings, make sure enough bits are available to avoid any ambiguity.
  997          */
  998         len = hi->loc.size * hi->loc.count;
  999         if (len <= 1)
 1000                 return 1;
 1001 
 1002         sc->sc_volume.v_inc = bit;
 1003         sc->sc_volume.v_dec = bit + 1;
 1004         sc->sc_volume.v_off = off;
 1005         sc->sc_volume.v_len = len;
 1006 
 1007         DPRINTF("%s: inc %d, dec %d, off %d, len %d, min %d, max %d\n",
 1008             DEVNAME(sc), sc->sc_volume.v_inc, sc->sc_volume.v_dec,
 1009             sc->sc_volume.v_off, sc->sc_volume.v_len,
 1010             hi->logical_minimum, hi->logical_maximum);
 1011 
 1012         error = hidcc_add_key(sc, HUC_VOL_INC, sc->sc_volume.v_inc);
 1013         if (error)
 1014                 return error;
 1015         error = hidcc_add_key(sc, HUC_VOL_DEC, sc->sc_volume.v_dec);
 1016         if (error)
 1017                 return error;
 1018         return 0;
 1019 }
 1020 
 1021 int
 1022 hidcc_bit_to_sym(struct hidcc *sc, u_int bit, const struct hidcc_keysym **ks)
 1023 {
 1024         if (bit >= sc->sc_rawsiz || sc->sc_raw[bit] == NULL)
 1025                 return 1;
 1026         *ks = sc->sc_raw[bit];
 1027         return 0;
 1028 }
 1029 
 1030 int
 1031 hidcc_usage_to_sym(int32_t usage, const struct hidcc_keysym **ks)
 1032 {
 1033         int len = nitems(hidcc_keysyms);
 1034         int i;
 1035 
 1036         for (i = 0; i < len; i++) {
 1037                 if (hidcc_keysyms[i].ks_usage == usage) {
 1038                         *ks = &hidcc_keysyms[i];
 1039                         return 0;
 1040                 }
 1041         }
 1042         return 1;
 1043 }
 1044 
 1045 int
 1046 hidcc_bits_to_int(uint8_t *buf, u_int buflen, int32_t *usage)
 1047 {
 1048         int32_t x = 0;
 1049         int i;
 1050 
 1051         if (buflen == 0 || buflen > sizeof(*usage))
 1052                 return 1;
 1053 
 1054         for (i = buflen - 1; i >= 0; i--) {
 1055                 x |= buf[i];
 1056                 if (i > 0)
 1057                         x <<= 8;
 1058         }
 1059         *usage = x;
 1060         return 0;
 1061 }
 1062 
 1063 int
 1064 hidcc_bits_to_volume(struct hidcc *sc, uint8_t *buf, int buflen, u_int *bit)
 1065 {
 1066         uint32_t vlen = sc->sc_volume.v_len;
 1067         uint32_t voff = sc->sc_volume.v_off;
 1068         int32_t vol;
 1069         int sign;
 1070 
 1071         if (vlen == 0)
 1072                 return 1;
 1073         if (hidcc_bits_to_int(buf, buflen, &vol))
 1074                 return 1;
 1075         vol = (vol >> voff) & ((1 << vlen) - 1);
 1076         if (vol == 0)
 1077                 return 1;
 1078 
 1079         /*
 1080          * Interpret the volume as a relative change by only looking at the sign
 1081          * in order to determine the change direction.
 1082          */
 1083         sign = vol & (1 << (vlen - 1)) ? -1 : 1;
 1084         if (sign < 0)
 1085                 vol = (1 << vlen) - vol;
 1086         vol *= sign;
 1087         if (vol > 0)
 1088                 *bit = sc->sc_volume.v_inc;
 1089         else
 1090                 *bit = sc->sc_volume.v_dec;
 1091         return 0;
 1092 }
 1093 
 1094 int
 1095 hidcc_intr_slice(struct hidcc *sc, uint8_t *src, uint8_t *dst, int *len)
 1096 {
 1097         int ilen = sc->sc_input.i_len;
 1098         int ioff = sc->sc_input.i_off;
 1099         int di, si;
 1100         int maxlen = *len;
 1101 
 1102         if (maxlen == 0)
 1103                 return 1;
 1104 
 1105         memset(dst, 0, maxlen);
 1106         si = ioff;
 1107         di = 0;
 1108         for (; ilen > 0; ilen--) {
 1109                 int db, sb;
 1110 
 1111                 sb = si / 8;
 1112                 db = di / 8;
 1113                 if (sb >= maxlen || db >= maxlen)
 1114                         return 1;
 1115 
 1116                 if (src[sb] & (1 << (si % 8)))
 1117                         dst[db] |= 1 << (di % 8);
 1118                 si++;
 1119                 di++;
 1120         }
 1121 
 1122         *len = (sc->sc_input.i_len + 7) / 8;
 1123         return 0;
 1124 }
 1125 
 1126 void
 1127 hidcc_input(struct hidcc *sc, u_int bit, int release)
 1128 {
 1129         int s;
 1130 
 1131         s = spltty();
 1132         wskbd_input(sc->sc_wskbddev,
 1133             release ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN, bit);
 1134         splx(s);
 1135 }
 1136 
 1137 void
 1138 hidcc_rawinput(struct hidcc *sc, u_char c, int release)
 1139 {
 1140 #ifdef WSDISPLAY_COMPAT_RAWKBD
 1141         u_char buf[2];
 1142         int len = 0;
 1143         int s;
 1144 
 1145         if (c & 0x80)
 1146                 buf[len++] = 0xe0;
 1147         buf[len++] = c & 0x7f;
 1148         if (release)
 1149                 buf[len - 1] |= 0x80;
 1150 
 1151         s = spltty();
 1152         wskbd_rawinput(sc->sc_wskbddev, buf, len);
 1153         splx(s);
 1154 #endif
 1155 }
 1156 
 1157 int
 1158 hidcc_setbits(struct hidcc *sc, uint8_t *data, int len, u_int *bit)
 1159 {
 1160         int i, j;
 1161 
 1162         if (hidcc_bits_to_volume(sc, data, len, bit) == 0)
 1163                 return 0;
 1164 
 1165         for (i = 0; i < len; i++) {
 1166                 if (data[i] == 0)
 1167                         continue;
 1168 
 1169                 for (j = 0; j < 8; j++) {
 1170                         if (data[i] & (1 << j)) {
 1171                                 *bit = (i * 8) + j;
 1172                                 return 0;
 1173                         }
 1174                 }
 1175         }
 1176 
 1177         return 1;
 1178 }
 1179 
 1180 #ifdef HIDCC_DEBUG
 1181 
 1182 void
 1183 hidcc_dump(struct hidcc *sc, const char *prefix, uint8_t *data, u_int len)
 1184 {
 1185         u_int i;
 1186 
 1187         if (hidcc_debug == 0)
 1188                 return;
 1189 
 1190         printf("%s: %s:", DEVNAME(sc), prefix);
 1191         for (i = 0; i < len; i++)
 1192                 printf(" %02x", data[i]);
 1193         printf("\n");
 1194 }
 1195 
 1196 #endif

Cache object: 73b5844914ab86af3cea5f532add4108


[ 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.