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/compat/darwin/darwin_iohidsystem.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 /*      $NetBSD: darwin_iohidsystem.c,v 1.43 2008/04/28 20:23:41 martin Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Emmanuel Dreyfus.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: darwin_iohidsystem.c,v 1.43 2008/04/28 20:23:41 martin Exp $");
   34 
   35 #include "ioconf.h"
   36 #include "wsmux.h"
   37 
   38 #include <sys/types.h>
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/malloc.h>
   42 #include <sys/fcntl.h>
   43 #include <sys/uio.h>
   44 #include <sys/select.h>
   45 #include <sys/signal.h>
   46 #include <sys/mount.h>
   47 #include <sys/proc.h>
   48 #include <sys/conf.h>
   49 #include <sys/device.h>
   50 #include <sys/kthread.h>
   51 #include <sys/ktrace.h>
   52 
   53 #include <dev/wscons/wsconsio.h>
   54 #include <dev/wscons/wseventvar.h>
   55 #include <dev/wscons/wsmuxvar.h>
   56 
   57 #include <uvm/uvm_extern.h>
   58 #include <uvm/uvm_map.h>
   59 #include <uvm/uvm.h>
   60 
   61 #include <compat/mach/mach_types.h>
   62 #include <compat/mach/mach_message.h>
   63 #include <compat/mach/mach_port.h>
   64 #include <compat/mach/mach_errno.h>
   65 #include <compat/mach/mach_iokit.h>
   66 
   67 #include <compat/darwin/darwin_exec.h>
   68 #include <compat/darwin/darwin_iokit.h>
   69 #include <compat/darwin/darwin_sysctl.h>
   70 #include <compat/darwin/darwin_iohidsystem.h>
   71 
   72 static struct uvm_object *darwin_iohidsystem_shmem = NULL;
   73 static void darwin_iohidsystem_shmeminit(vaddr_t);
   74 static void darwin_iohidsystem_thread(void *);
   75 static int darwin_findwsmux(dev_t *, int);
   76 static void darwin_wscons_to_iohidsystem
   77     (struct wscons_event *, darwin_iohidsystem_event *);
   78 static void mach_notify_iohidsystem(struct lwp *, struct mach_right *);
   79 
   80 struct darwin_iohidsystem_thread_args {
   81         vaddr_t dita_shmem;
   82         struct lwp *dita_l;
   83         int dita_done;
   84         int *dita_hidsystem_finished;
   85 };
   86 
   87 static char darwin_ioresources_properties[] = "<dict ID=\"\"><key>IOKit</key><string ID=\"1\">IOService</string><key>AccessMPC106PerformanceRegister</key><string ID=\"2\">AppleGracklePCI is not serializable</string><key>IONVRAM</key><reference IDREF=\"1\"/><key>IOiic0</key><string ID=\"3\">AppleCuda is not serializable</string><key>IORTC</key><reference IDREF=\"3\"/><key>IOBSD</key><reference IDREF=\"1\"/></dict>";
   88 
   89 static char darwin_iokbd_properties[] = "<dict ID=\"\"><key>ADB Match</key><string ID=\"1\">2</string><key>ADBVirtualKeys</key><string ID=\"2\">0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x3B,0x37,0x38,0x39,0x3A,0x7B,0x7C,0x7D,0x7E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x3C,0x3D,0x3E,0x36,0x7F</string><key>CFBundleIdentifier</key><string ID=\"3\">com.apple.driver.AppleADBKeyboard</string><key>IOClass</key><string ID=\"4\">AppleADBKeyboard</string><key>IOProbeScore</key><integer size=\"32\" ID=\"5\">0x3e8</integer><key>IOProviderClass</key><string ID=\"6\">IOADBDevice</string><key>PowerBook fn Foward Delete</key><integer size=\"64\" ID=\"7\">0x1</integer><key>KeyboardReserved</key><data ID=\"8\">Ag4wAAAAAAA=</data><key>IOMatchCategory</key><string ID=\"9\">IODefaultMatchCategory</string><key>HIDKeyMapping</key><data ID=\"11\">AAAIAAE5AQE4AgE7AwE6BAE3BRVSQUxTVFVFWFdWW1xDS1F7fX58TlkGAXIHAT9/DQBhAEEAAQABAMoAxwABAAENAHMAUwATABMA+wCnABMAEw0AZABEAAQABAFEAbYABAAEDQBmAEYABgAGAKYBrAAGAAYNAGgASAAIAAgA4wDrAAAYAA0AZwBHAAcABwDxAOEABwAHDQB6AFoAGgAaAM8BVwAaABoNAHgAWAAYABgBtAHOABgAGA0AYwBDAAMAAwHjAdMAAwADDQB2AFYAFgAWAdYB4AAWABYCADwAPg0AYgBCAAIAAgHlAfIAAgACDQBxAFEAEQARAPoA6gARABENAHcAVwAXABcByAHHABcAFw0AZQBFAAUABQDCAMUABQAFDQByAFIAEgASAeIB0gASABINAHkAWQAZABkApQHbABkAGQ0AdABUABQAFAHkAdQAFAAUCgAxACEBrQChDgAyAEAAMgAAALIAswAAAAAKADMAIwCjAboKADQAJACiAKgOADYAXgA2AB4AtgDDAB4AHgoANQAlAaUAvQoAPQArAbkBsQoAOQAoAKwAqwoANwAmAbABqw4ALQBfAB8AHwCxANAAHwAfCgA4ACoAtwC0CgAwACkArQC7DgBdAH0AHQAdACcAugAdAB0NAG8ATwAPAA8A+QDpAA8ADw0AdQBVABUAFQDIAM0AFQAVDgBbAHsAGwAbAGAAqgAbABsNAGkASQAJAAkAwQD1AAkACQ0AcABQABAAEAFwAVAAEAAQEAANAAMNAGwATAAMAAwA+ADoAAwADA0AagBKAAoACgDGAK4ACgAKCgAnACIAqQGuDQBrAEsACwALAM4ArwALAAsKADsAOgGyAaIOAFwAfAAcABwA4wDrABwAHAoALAA8AMsBowoALwA/AbgAvw0AbgBOAA4ADgDEAa8ADgAODQBtAE0ADQANAW0B2AANAA0KAC4APgC8AbMCAAkAGQwAIAAAAIAAAAoAYAB+AGABuwIAfwAI/wIAGwB+///////////////8AAC7/AAAq/wAAK/8AABv///8OAC8AXAAvABwALwBcAAAKAAAADf8AAC3//w4APQB8AD0AHAA9AHwAABhGAAAwAAAxAAAyAAAzAAA0AAA1AAA2AAA3/wAAOAAAOf///wD+JAD+JQD+JgD+IgD+JwD+KP8A/ir/AP4y/wD+M/8A/in/AP4r/wD+NP8A/i4A/jAA/i0A/iMA/i8A/iEA/jEA/iAAAawAAa4AAa8AAa0PAv8EADEC/wQAMgL/BAAzAv8EADQC/wQANQL/BAA2Av8EADcC/wQAOAL/BAA5Av8EADAC/wQALQL/BAA9Av8EAHAC/wQAXQL/BABbBgVyBn8HSgg+CT0KRw==</data><key>HIDKind</key><integer size=\"32\" ID=\"12\">0x1</integer><key>HIDInterfaceID</key><integer size=\"32\" ID=\"13\">0x2</integer><key>HIDSubinterfaceID</key><integer size=\"32\" ID=\"14\">0x2</integer></dict>";
   90 
   91 static char darwin_iomouse_properties[] = "<dict ID=\"\"><key>dpi</key><integer size=\"64\" ID=\"1\">0xc8</integer><key>IOClass</key><string ID=\"2\">AppleADBMouseType2</string><key>IOProbeScore</key><integer size=\"32\" ID=\"3\">0x2710</integer><key>IOProviderClass</key><string ID=\"4\">IOADBDevice</string><key>CFBundleIdentifier</key><string ID=\"5\">com.apple.driver.AppleADBMouse</string><key>ADB Match</key><string ID=\"6\">3</string><key>IOMatchCategory</key><string ID=\"7\">IODefaultMatchCategory</string><key>HIDPointerAccelerationType</key><string ID=\"8\">HIDMouseAcceleration</string><key>HIDPointerAccelerationSettings</key><array ID=\"9\"><data ID=\"10\">AAAAAA==</data><data ID=\"11\">AAAgAA==</data><data ID=\"12\">AABQAA==</data><data ID=\"13\">AACAAA==</data><data ID=\"14\">AACwAA==</data><data ID=\"15\">AADgAA==</data><data ID=\"16\">AAEAAA==</data></array><key>HIDPointerResolution</key><data ID=\"17\">AMgAAA==</data><key>HIDPointerConvertAbsolute</key><data ID=\"18\">AAAAAA==</data><key>HIDPointerContactToMove</key><data ID=\"19\">AAAAAA==</data><key>HIDKind</key><integer size=\"32\" ID=\"20\">0x2</integer><key>HIDInterfaceID</key><integer size=\"32\" ID=\"21\">0x2</integer><key>HIDSubinterfaceID</key><integer size=\"32\" ID=\"22\">0x2</integer></dict>";
   92 
   93 static char darwin_iohidsystem_properties[] = "<dict ID=\"\"><key>CFBundleIdentifier</key><string ID=\"1\">com.apple.iokit.IOHIDSystem</string><key>IOClass</key><string ID=\"2\">IOHIDSystem</string><key>IOMatchCategory</key><string ID=\"3\">IOHID</string><key>IOProviderClass</key><string ID=\"4\">IOResources</string><key>IOResourceMatch</key><string ID=\"5\">IOKit</string><key>IOProbeScore</key><integer size=\"32\" ID=\"6\">0x0</integer><key>HIDParameters</key><dict ID=\"7\"><key>HIDClickTime</key><data ID=\"8\">AAAAAB3NZQA=</data><key>HIDAutoDimThreshold</key><data ID=\"9\">AAAARdlkuAA=</data><key>HIDAutoDimBrightness</key><data ID=\"10\">AAAAAA==</data><key>HIDClickSpace</key><data ID=\"11\">AAAAAA==</data><key>HIDKeyRepeat</key><data ID=\"12\">AAAAAAHJw4A=</data><key>HIDInitialKeyRepeat</key><data ID=\"13\">AAAAABZaC8A=</data><key>HIDPointerAcceleration</key><data ID=\"14\">AACAAA==</data><key>HIDScrollAcceleration</key><data ID=\"15\">AABQAA==</data><key>HIDPointerButtonMode</key><data ID=\"16\">AAAAAg==</data><key>HIDF12EjectDelay</key><data ID=\"17\">AAAA+g==</data><key>HIDSlowKeysDelay</key><data ID=\"18\">AAAAAA==</data><key>HIDStickyKeysDisabled</key><data ID=\"19\">AAAAAA==</data><key>HIDStickyKeysOn</key><data ID=\"20\">AAAAAA==</data><key>HIDStickyKeysShiftToggles</key><data ID=\"21\">AAAAAA==</data><key>HIDMouseAcceleration</key><data ID=\"22\">AAGzMw==</data><key>Clicking</key><data ID=\"23\">AA==</data><key>DragLock</key><reference IDREF=\"23\"/><key>Dragging</key><reference IDREF=\"23\"/><key>JitterNoMove</key><integer size=\"32\" ID=\"24\">0x1</integer><key>JitterNoClick</key><integer size=\"32\" ID=\"25\">0x1</integer><key>PalmNoAction When Typing</key><integer size=\"32\" ID=\"26\">0x1</integer><key>PalmNoAction Permanent</key><integer size=\"32\" ID=\"27\">0x1</integer><key>TwofingerNoAction</key><integer size=\"32\" ID=\"28\">0x1</integer><key>OutsidezoneNoAction When Typing</key><integer size=\"32\" ID=\"29\">0x1</integer><key>Use Panther Settings for W</key><integer size=\"32\" ID=\"30\">0x0</integer><key>Trackpad Jitter Milliseconds</key><integer size=\"32\" ID=\"31\">0xc0</integer><key>USBMouseStopsTrackpad</key><integer size=\"32\" ID=\"32\">0x0</integer><key>HIDWaitCursorFrameInterval</key><data ID=\"33\">AfygVw==</data></dict><key>HIDAutoDimTime</key><data ID=\"34\">AAAAAAAAAAA=</data><key>HIDIdleTime</key><data ID=\"35\">AAAjRKwYjsI=</data><key>HIDAutoDimState</key><data ID=\"36\">AAAAAQ==</data><key>HIDBrightness</key><data ID=\"37\">AAAAQA==</data></dict>";
   94 
   95 struct mach_iokit_devclass darwin_iokbd_devclass = {
   96         "(unknown)",
   97         { &mach_ioroot_devclass, NULL },
   98         darwin_iokbd_properties,
   99         NULL,
  100         NULL,
  101         NULL,
  102         NULL,
  103         NULL,
  104         NULL,
  105         "AppleADBKeyboard",
  106         NULL,
  107 };
  108 
  109 struct mach_iokit_devclass darwin_iomouse_devclass = {
  110         "(unknown)",
  111         { &mach_ioroot_devclass, NULL },
  112         darwin_iomouse_properties,
  113         NULL,
  114         NULL,
  115         NULL,
  116         NULL,
  117         NULL,
  118         NULL,
  119         "AppleADBMouse",
  120         NULL,
  121 };
  122 
  123 struct mach_iokit_devclass darwin_ioresources_devclass = {
  124         "(unknown)",
  125         { &mach_ioroot_devclass, NULL },
  126         darwin_ioresources_properties,
  127         NULL,
  128         NULL,
  129         NULL,
  130         NULL,
  131         NULL,
  132         NULL,
  133         "IOResources",
  134         NULL,
  135 };
  136 
  137 struct mach_iokit_devclass darwin_iohidsystem_devclass = {
  138         "<dict ID=\"\"><key>IOProviderClass</key>"
  139             "<string ID=\"1\">IOHIDSystem</string></dict>",
  140         { &darwin_ioresources_devclass, &darwin_iokbd_devclass,
  141             &darwin_iomouse_devclass, NULL },
  142         darwin_iohidsystem_properties,
  143         NULL,
  144         darwin_iohidsystem_connect_method_scalari_scalaro,
  145         NULL,
  146         darwin_iohidsystem_connect_method_structi_structo,
  147         NULL,
  148         darwin_iohidsystem_connect_map_memory,
  149         "IOHIDSystem",
  150         NULL,
  151 };
  152 
  153 int
  154 darwin_iohidsystem_connect_method_scalari_scalaro(struct mach_trap_args *args)
  155 {
  156         mach_io_connect_method_scalari_scalaro_request_t *req = args->smsg;
  157         mach_io_connect_method_scalari_scalaro_reply_t *rep = args->rmsg;
  158         size_t *msglen = args->rsize;
  159         int maxoutcount;
  160 
  161 #ifdef DEBUG_DARWIN
  162         printf("darwin_iohidsystem_connect_method_scalari_scalaro()\n");
  163 #endif
  164         rep->rep_outcount = 0;
  165         maxoutcount = req->req_in[req->req_incount];
  166 
  167         switch (req->req_selector) {
  168         case DARWIN_IOHIDCREATESHMEM: {
  169                 /* Create the shared memory for HID events */
  170                 int vers;
  171                 int error;
  172                 size_t memsize;
  173                 vaddr_t kvaddr;
  174                 struct proc *p;
  175                 struct darwin_iohidsystem_thread_args *dita;
  176                 struct darwin_emuldata *ded;
  177 
  178                 vers = req->req_in[0]; /* 1 */
  179 #ifdef DEBUG_DARWIN
  180                 printf("DARWIN_IOHIDCREATESHMEM: version = %d\n", vers);
  181 #endif
  182                 memsize = round_page(sizeof(struct darwin_iohidsystem_shmem));
  183 
  184                 /* If it has not been used yet, initialize it */
  185                 if (darwin_iohidsystem_shmem == NULL) {
  186                         darwin_iohidsystem_shmem = uao_create(memsize, 0);
  187 
  188                         error = uvm_map(kernel_map, &kvaddr, memsize,
  189                             darwin_iohidsystem_shmem, 0, PAGE_SIZE,
  190                             UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW,
  191                             UVM_INH_SHARE, UVM_ADV_RANDOM, 0));
  192                         if (error != 0) {
  193                                 uao_detach(darwin_iohidsystem_shmem);
  194                                 darwin_iohidsystem_shmem = NULL;
  195                                 return mach_msg_error(args, error);
  196                         }
  197 
  198                         error = uvm_map_pageable(kernel_map, kvaddr,
  199                             kvaddr + memsize, FALSE, 0);
  200                         if (error != 0) {
  201                                 uao_detach(darwin_iohidsystem_shmem);
  202                                 darwin_iohidsystem_shmem = NULL;
  203                                 return mach_msg_error(args, error);
  204                         }
  205 
  206                         darwin_iohidsystem_shmeminit(kvaddr);
  207 
  208                         p = args->l->l_proc;
  209                         ded = (struct darwin_emuldata *)p->p_emuldata;
  210 
  211                         dita = malloc(sizeof(*dita), M_TEMP, M_WAITOK);
  212                         dita->dita_shmem = kvaddr;
  213                         dita->dita_done = 0;
  214 
  215                         kthread_create(PRI_NONE, 0, NULL,
  216                             darwin_iohidsystem_thread,
  217                             (void *)dita, &dita->dita_l,
  218                             "iohidsystem");
  219 
  220                         /*
  221                          * Make sure the thread got the informations
  222                          * before exitting and destroying dita.
  223                          */
  224                         while (!dita->dita_done)
  225                                 (void)tsleep(&dita->dita_done,
  226                                     PZERO, "iohid_done", 0);
  227 
  228                         ded->ded_hidsystem_finished =
  229                             dita->dita_hidsystem_finished;
  230 
  231                         free(dita, M_TEMP);
  232 
  233                 }
  234                 rep->rep_outcount = 0;
  235                 break;
  236         }
  237 
  238         case DARWIN_IOHIDSETEVENTSENABLE: {
  239                 /* Enable or disable events */
  240                 int enable;
  241 
  242                 enable = req->req_in[0];
  243 #ifdef DEBUG_DARWIN
  244                 printf("DARWIN_IOHIDSETEVENTSENABLE: enable = %d\n", enable);
  245 #endif
  246                 /* For now, this is a no-op */
  247                 rep->rep_outcount = 0;
  248                 break;
  249         }
  250 
  251         case DARWIN_IOHIDSETCURSORENABLE: {
  252                 /* Enable or disable the cursor */
  253                 int enable;
  254 
  255                 enable = req->req_in[0];
  256 #ifdef DEBUG_DARWIN
  257                 printf("DARWIN_IOHIDSETCURSORENABLE: enable = %d\n", enable);
  258 #endif
  259                 /* We don't support it */
  260                 rep->rep_outcount = 0;
  261                 break;
  262         }
  263 
  264         case DARWIN_IOHIDPOSTEVENT: {
  265                 darwin_nxll_event *dne;
  266 
  267                 dne = (darwin_nxll_event *)&req->req_in[0];
  268 #ifdef DEBUG_DARWIN
  269                 printf("DARWIN_IOHIDPOSTEVENT: setcursor = %d, type = %d, "
  270                     " location = (%d, %d), setflags = %x, flags = %x\n",
  271                 dne->dne_setcursor, dne->dne_type, dne->dne_location.x,
  272                 dne->dne_location.y, dne->dne_setflags, dne->dne_flags);
  273 #endif
  274                 /* We don't support it yet */
  275                 rep->rep_outcount = 0;
  276                 break;
  277         }
  278 
  279         default:
  280 #ifdef DEBUG_DARWIN
  281                 printf("Unknown selector %d\n", req->req_selector);
  282 #endif
  283                 return mach_msg_error(args, EINVAL);
  284                 break;
  285         }
  286 
  287         *msglen = sizeof(*rep) - ((16 + rep->rep_outcount) * sizeof(int));
  288         mach_set_header(rep, req, *msglen);
  289         mach_set_trailer(rep, *msglen);
  290 
  291         return 0;
  292 }
  293 
  294 int
  295 darwin_iohidsystem_connect_method_structi_structo(struct mach_trap_args *args)
  296 {
  297         mach_io_connect_method_structi_structo_request_t *req = args->smsg;
  298         mach_io_connect_method_structi_structo_reply_t *rep = args->rmsg;
  299         size_t *msglen = args->rsize;
  300         struct lwp *l = args->l;
  301         int maxoutcount;
  302         int error;
  303 
  304 #ifdef DEBUG_DARWIN
  305         printf("darwin_iohidsystem_connect_method_structi_structo()\n");
  306 #endif
  307         rep->rep_outcount = 0;
  308         /* maxoutcount is word aligned */
  309         maxoutcount = req->req_in[(req->req_incount & ~0x3UL) + 4];
  310 
  311         switch (req->req_selector) {
  312         case DARWIN_IOHIDSETMOUSELOCATION: {
  313                 struct wscons_event wsevt;
  314                 dev_t dev;
  315                 darwin_iogpoint *pt = (darwin_iogpoint *)&req->req_in[0];
  316 
  317 #ifdef DEBUG_DARWIN
  318                 printf("DARWIN_IOHIDSETMOUSELOCATION: %d,%d\n", pt->x, pt->y);
  319 #endif
  320                 /*
  321                  * Use the wsmux given by sysctl emul.darwin.iohidsystem_mux
  322                  */
  323                 error = darwin_findwsmux(&dev, darwin_iohidsystem_mux);
  324                 if (error != 0)
  325                         return mach_msg_error(args, error);
  326 
  327                 wsevt.type = WSCONS_EVENT_MOUSE_ABSOLUTE_X;
  328                 wsevt.value = pt->x;
  329                 if ((error = cdev_ioctl(dev,
  330                     WSMUXIO_INJECTEVENT, (void *)&wsevt, 0,  l)) != 0)
  331                         return mach_msg_error(args, error);
  332 
  333                 wsevt.type = WSCONS_EVENT_MOUSE_ABSOLUTE_Y;
  334                 wsevt.value = pt->y;
  335                 if ((error = cdev_ioctl(dev,
  336                     WSMUXIO_INJECTEVENT, (void *)&wsevt, 0, l)) != 0)
  337                         return mach_msg_error(args, error);
  338 
  339                 rep->rep_outcount = 0;
  340                 break;
  341         }
  342 
  343         default:
  344 #ifdef DEBUG_DARWIN
  345                 printf("Unknown selector %d\n", req->req_selector);
  346 #endif
  347                 return mach_msg_error(args, EINVAL);
  348                 break;
  349         }
  350 
  351 
  352         *msglen = sizeof(*rep) - (4096 - rep->rep_outcount);
  353         mach_set_header(rep, req, *msglen);
  354         mach_set_trailer(rep, *msglen);
  355 
  356         return 0;
  357 }
  358 
  359 int
  360 darwin_iohidsystem_connect_map_memory(struct mach_trap_args *args)
  361 {
  362         mach_io_connect_map_memory_request_t *req = args->smsg;
  363         mach_io_connect_map_memory_reply_t *rep = args->rmsg;
  364         size_t *msglen = args->rsize;
  365         struct proc *p = args->l->l_proc;
  366         int error;
  367         size_t memsize;
  368         vaddr_t pvaddr;
  369 
  370 #ifdef DEBUG_DARWIN
  371         printf("darwin_iohidsystem_connect_map_memory()\n");
  372 #endif
  373         memsize = round_page(sizeof(struct darwin_iohidsystem_shmem));
  374 
  375         if (darwin_iohidsystem_shmem == NULL)
  376                 return mach_msg_error(args, ENOMEM);
  377 
  378         uao_reference(darwin_iohidsystem_shmem);
  379         pvaddr = VM_DEFAULT_ADDRESS(p->p_vmspace->vm_daddr, memsize);
  380 
  381         if ((error = uvm_map(&p->p_vmspace->vm_map, &pvaddr,
  382             memsize, darwin_iohidsystem_shmem, 0, PAGE_SIZE,
  383             UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW,
  384             UVM_INH_SHARE, UVM_ADV_RANDOM, 0))) != 0)
  385                 return mach_msg_error(args, error);
  386 
  387 #ifdef DEBUG_DARWIN
  388         printf("pvaddr = 0x%08lx\n", (long)pvaddr);
  389 #endif
  390 
  391         *msglen = sizeof(*rep);
  392         mach_set_header(rep, req, *msglen);
  393 
  394         rep->rep_retval = 0;
  395         rep->rep_addr = pvaddr;
  396         rep->rep_len = sizeof(struct darwin_iohidsystem_shmem);
  397 
  398         mach_set_trailer(rep, *msglen);
  399         return 0;
  400 }
  401 
  402 static void
  403 darwin_iohidsystem_thread(void *args)
  404 {
  405         struct darwin_iohidsystem_thread_args *dita;
  406         struct darwin_iohidsystem_shmem *shmem;
  407         struct darwin_iohidsystem_evglobals *evg;
  408         darwin_iohidsystem_event_item *diei = NULL; /* XXX: gcc */
  409         darwin_iohidsystem_event *die;
  410         dev_t dev;
  411         struct uio auio;
  412         struct iovec aiov;
  413         struct wscons_event wsevt;
  414         int error = 0;
  415         struct mach_right *mr;
  416         struct lwp *l;
  417         int finished = 0;
  418 
  419 #ifdef DEBUG_DARWIN
  420         printf("darwin_iohidsystem_thread: start\n");
  421 #endif
  422         dita = (struct darwin_iohidsystem_thread_args *)args;
  423         shmem = (struct darwin_iohidsystem_shmem *)dita->dita_shmem;
  424         l = dita->dita_l;
  425         dita->dita_hidsystem_finished = &finished;
  426 
  427         /*
  428          * Allow the parent to read dita_hidsystem_finished
  429          * and to get rid of dita. Once the parent is awaken,
  430          * it holds a reference to our on-stack finished flag,
  431          * hence we cannot exi before the parent sets this flag.
  432          * This is done in darwin_proc_exit()
  433          */
  434         dita->dita_done = 1;
  435         wakeup(&dita->dita_done);
  436 
  437         evg = (struct darwin_iohidsystem_evglobals *)&shmem->dis_evglobals;
  438 
  439         /*
  440          * Use the wsmux given by sysctl emul.darwin.iohidsystem_mux
  441          */
  442         if ((error = darwin_findwsmux(&dev, darwin_iohidsystem_mux)) != 0)
  443                 goto out2;
  444 
  445         if ((error = cdev_open(dev, FREAD|FWRITE, 0, l)) != 0)
  446                 goto out2;
  447 
  448         while(!finished) {
  449                 auio.uio_iov = &aiov;
  450                 auio.uio_iovcnt = 1;
  451                 aiov.iov_base = &wsevt;
  452                 aiov.iov_len = sizeof(wsevt);
  453                 auio.uio_resid = sizeof(wsevt);
  454                 auio.uio_offset = 0;
  455                 auio.uio_rw = UIO_READ;
  456                 UIO_SETUP_SYSSPACE(&auio);
  457 
  458                 if ((error = cdev_read(dev, &auio, 0)) != 0) {
  459 #ifdef DEBUG_DARWIN
  460                         printf("iohidsystem: read error %d\n", error);
  461 #endif
  462                         goto out1;
  463                 }
  464 
  465                 diei = &evg->evg_evqueue[evg->evg_event_last];
  466                 while (diei->diei_sem != 0)
  467                         tsleep(&diei->diei_sem, PZERO, "iohid_lock", 1);
  468 
  469                 /*
  470                  * No need to take the lock since we will not
  471                  * yield control to the user process.
  472                  */
  473 
  474                 diei->diei_next = evg->evg_event_tail;
  475 
  476                 diei = &evg->evg_evqueue[evg->evg_event_tail];
  477                 die = (darwin_iohidsystem_event *)&diei->diei_event;
  478 
  479                 darwin_wscons_to_iohidsystem(&wsevt, die);
  480 
  481                 evg->evg_event_last = evg->evg_event_tail;
  482                 evg->evg_event_tail++;
  483                 if (evg->evg_event_tail == DARWIN_IOHIDSYSTEM_EVENTQUEUE_LEN)
  484                         evg->evg_event_tail = 0;
  485 
  486                 /*
  487                  * Send a I/O notification if the process
  488                  * has consumed all available entries
  489                  */
  490                 if (evg->evg_event_last == evg->evg_event_head) {
  491                         mr = darwin_iohidsystem_devclass.mid_notify;
  492                         if (mr != NULL)
  493                                 mach_notify_iohidsystem(l, mr);
  494                 }
  495 
  496 
  497                 /*
  498                  * If the queue is full, ie: the next event slot is not
  499                  * yet consumed, sleep until the process consumes it.
  500                  */
  501                 diei = &evg->evg_evqueue[evg->evg_event_tail];
  502                 die = (darwin_iohidsystem_event *)&diei->diei_event;
  503                 while (die->die_type != 0)
  504                         tsleep(&die->die_type, PZERO, "iohid_full", 1);
  505 
  506         }
  507 
  508 out1:
  509         cdev_close(dev, FREAD|FWRITE, 0, l);
  510 
  511 out2:
  512         while (!finished)
  513                 tsleep((void *)&finished, PZERO, "iohid_exit", 0);
  514 
  515         uao_detach(darwin_iohidsystem_shmem);
  516         darwin_iohidsystem_shmem = NULL;
  517         kthread_exit(error);
  518         /* NOTREACHED */
  519 };
  520 
  521 static void
  522 darwin_iohidsystem_shmeminit(vaddr_t kvaddr)
  523 {
  524         struct darwin_iohidsystem_shmem *shmem;
  525         struct darwin_iohidsystem_evglobals *evglobals;
  526         int i;
  527 
  528         shmem = (struct darwin_iohidsystem_shmem *)kvaddr;
  529         shmem->dis_global_offset =
  530             (size_t)&shmem->dis_evglobals - (size_t)&shmem->dis_global_offset;
  531         shmem->dis_private_offset =
  532             shmem->dis_global_offset + sizeof(*evglobals);
  533 
  534         evglobals = &shmem->dis_evglobals;
  535         evglobals->evg_struct_size = sizeof(*evglobals);
  536 
  537         for (i = 0; i < DARWIN_IOHIDSYSTEM_EVENTQUEUE_LEN; i++)
  538                 evglobals->evg_evqueue[i].diei_next = i + 1;
  539         evglobals->
  540             evg_evqueue[DARWIN_IOHIDSYSTEM_EVENTQUEUE_LEN - 1].diei_next = 0;
  541 
  542         return;
  543 }
  544 
  545 static int
  546 darwin_findwsmux(dev_t *dev, int mux)
  547 {
  548         extern struct cdevsw wsmux_cdevsw;
  549         struct wsmux_softc *wsm_sc;
  550         int minor, major;
  551 
  552         if ((wsm_sc = wsmux_getmux(mux)) == NULL)
  553                 return ENODEV;
  554 
  555         major = cdevsw_lookup_major(&wsmux_cdevsw);
  556         minor = device_unit(wsm_sc->sc_base.me_dv);
  557         *dev = makedev(major, minor);
  558 
  559         return 0;
  560 }
  561 
  562 static void
  563 darwin_wscons_to_iohidsystem(struct wscons_event *wsevt, darwin_iohidsystem_event *hidevt)
  564 {
  565         struct timeval tv;
  566         static int px = 0; /* Previous mouse location */
  567         static int py = 0;
  568         static int pf = 0; /* previous kbd flags */
  569 
  570         microtime(&tv);
  571         (void)memset(hidevt, 0, sizeof(*hidevt));
  572         hidevt->die_time_hi = tv.tv_sec;
  573         hidevt->die_time_lo = tv.tv_usec;
  574         hidevt->die_location_x = px;
  575         hidevt->die_location_y = py;
  576         hidevt->die_flags = pf;
  577 
  578         switch (wsevt->type) {
  579         case WSCONS_EVENT_MOUSE_DELTA_X:
  580                 hidevt->die_type = DARWIN_NX_MOUSEMOVED;
  581                 px += wsevt->value;
  582                 hidevt->die_data.mouse_move.dx = wsevt->value;
  583                 hidevt->die_location_x = px;
  584                 break;
  585 
  586         case WSCONS_EVENT_MOUSE_DELTA_Y:
  587                 hidevt->die_type = DARWIN_NX_MOUSEMOVED;
  588                 py -= wsevt->value;
  589                 hidevt->die_data.mouse_move.dy = wsevt->value;
  590                 hidevt->die_location_y = py;
  591                 break;
  592 
  593         case WSCONS_EVENT_MOUSE_ABSOLUTE_X:
  594                 hidevt->die_type = DARWIN_NX_MOUSEMOVED;
  595                 hidevt->die_location_x = wsevt->value;
  596                 px = wsevt->value;
  597                 break;
  598 
  599         case WSCONS_EVENT_MOUSE_ABSOLUTE_Y:
  600                 hidevt->die_type = DARWIN_NX_MOUSEMOVED;
  601                 hidevt->die_location_y = wsevt->value;
  602                 py = wsevt->value;
  603                 break;
  604 
  605         case WSCONS_EVENT_MOUSE_DOWN:
  606                 if (wsevt->value == 0)
  607                         hidevt->die_type = DARWIN_NX_LMOUSEDOWN;
  608                 else if (wsevt->value == 1)
  609                         hidevt->die_type = DARWIN_NX_RMOUSEDOWN;
  610                 else {
  611 #ifdef DEBUG_DARWIN
  612                         printf("Unknown mouse button %d\n", wsevt->value);
  613 #endif
  614                         break;
  615                 }
  616                 hidevt->die_data.mouse.subx = px;
  617                 hidevt->die_data.mouse.suby = py;
  618                 hidevt->die_data.mouse.buttonid = wsevt->value;
  619                 break;
  620 
  621         case WSCONS_EVENT_MOUSE_UP:
  622                 if (wsevt->value == 0)
  623                         hidevt->die_type = DARWIN_NX_LMOUSEUP;
  624                 else if (wsevt->value == 1)
  625                         hidevt->die_type = DARWIN_NX_RMOUSEUP;
  626                 else {
  627 #ifdef DEBUG_DARWIN
  628                         printf("Unknown mouse button %d\n", wsevt->value);
  629 #endif
  630                         break;
  631                 }
  632                 hidevt->die_data.mouse.subx = px;
  633                 hidevt->die_data.mouse.suby = py;
  634                 hidevt->die_data.mouse.buttonid = wsevt->value;
  635                 break;
  636 
  637         case WSCONS_EVENT_KEY_DOWN:
  638                 hidevt->die_type = DARWIN_NX_KEYDOWN;
  639                 hidevt->die_data.key.charset = wsevt->value;
  640                 hidevt->die_data.key.charcode = wsevt->value;
  641                 hidevt->die_data.key.orig_charcode = wsevt->value;
  642                 hidevt->die_data.key.keycode = wsevt->value; /* Translate */
  643                 hidevt->die_data.key.keyboardtype = 0xcd; /* XXX */
  644                 break;
  645 
  646         case WSCONS_EVENT_KEY_UP:
  647                 hidevt->die_type = DARWIN_NX_KEYUP;
  648                 hidevt->die_data.key.charset = wsevt->value;
  649                 hidevt->die_data.key.charcode = wsevt->value;
  650                 hidevt->die_data.key.orig_charcode = wsevt->value;
  651                 hidevt->die_data.key.keycode = wsevt->value; /* Translate */
  652                 hidevt->die_data.key.keyboardtype = 0xcd; /* XXX */
  653                 break;
  654 
  655         default:
  656 
  657 #ifdef DEBUG_DARWIN
  658                 printf("Untranslated wsevt->type = %d, wsevt->value = %d\n",
  659                     wsevt->type, wsevt->value);
  660 #endif
  661                 break;
  662         }
  663 
  664         return;
  665 }
  666 
  667 static void
  668 mach_notify_iohidsystem(struct lwp *l, struct mach_right *mr)
  669 {
  670         struct mach_port *mp;
  671         mach_notify_iohidsystem_request_t *req;
  672 
  673         mp = mr->mr_port;
  674 
  675 #ifdef DEBUG_MACH
  676         if (mp == NULL) {
  677                 printf("Warning: notification right without a port\n");
  678                 return;
  679         }
  680 #endif
  681 
  682         req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO);
  683 
  684         req->req_msgh.msgh_bits =
  685             MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
  686         req->req_msgh.msgh_size = sizeof(*req) - sizeof(req->req_trailer);
  687         req->req_msgh.msgh_local_port = mr->mr_name;
  688         req->req_msgh.msgh_id = 0;
  689 
  690         mach_set_trailer(req, sizeof(*req));
  691 
  692         ktruser("notify_iohidsystem", NULL, 0, 0);
  693 
  694         mr->mr_refcount++;
  695 
  696         /*
  697          * Call mach_message_get with a NULL lwp: the message is sent
  698          * by the kernel, not a userprocess. If we do not do that,
  699          * we crash because iohidsystem thread has p->p_emuldata == NULL.
  700          */
  701         mach_message_get((mach_msg_header_t *)req, sizeof(*req), mp, NULL);
  702 #ifdef DEBUG_MACH_MSG
  703         printf("pid %d: message queued on port %p (%d) [%p]\n",
  704             l->l_proc->p_pid, mp, req->req_msgh.msgh_id,
  705             mp->mp_recv->mr_sethead);
  706 #endif
  707         wakeup(mp->mp_recv->mr_sethead);
  708 
  709         return;
  710 }
  711 
  712 void
  713 darwin_iohidsystem_postfake(struct lwp *l)
  714 {
  715         dev_t dev;
  716         int error;
  717         struct wscons_event wsevt;
  718 
  719         /*
  720          * Use the wsmux given by sysctl emul.darwin.iohidsystem_mux
  721          */
  722         if ((error = darwin_findwsmux(&dev, darwin_iohidsystem_mux)) != 0)
  723                 return;
  724 
  725         wsevt.type = 0;
  726         wsevt.value = 0;
  727         cdev_ioctl(dev, WSMUXIO_INJECTEVENT, (void *)&wsevt, 0,  l);
  728 
  729         return;
  730 }

Cache object: af83ca40b6b11205386b60e395f50815


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