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