1 /* $NetBSD: darwin_iohidsystem.c,v 1.42 2008/03/25 00:49:19 cube Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: darwin_iohidsystem.c,v 1.42 2008/03/25 00:49:19 cube Exp $");
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>
44 #include <sys/select.h>
45 #include <sys/signal.h>
46 #include <sys/mount.h>
49 #include <sys/device.h>
50 #include <sys/kthread.h>
51 #include <sys/ktrace.h>
53 #include <dev/wscons/wsconsio.h>
54 #include <dev/wscons/wseventvar.h>
55 #include <dev/wscons/wsmuxvar.h>
57 #include <uvm/uvm_extern.h>
58 #include <uvm/uvm_map.h>
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>
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>
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
*);
80 struct darwin_iohidsystem_thread_args
{
84 int *dita_hidsystem_finished
;
87 static char darwin_ioresources_properties
[] = "<dict ID=\"0\"><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>";
89 static char darwin_iokbd_properties
[] = "<dict ID=\"0\"><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>";
91 static char darwin_iomouse_properties
[] = "<dict ID=\"0\"><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>";
93 static char darwin_iohidsystem_properties
[] = "<dict ID=\"0\"><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>";
95 struct mach_iokit_devclass darwin_iokbd_devclass
= {
97 { &mach_ioroot_devclass
, NULL
},
98 darwin_iokbd_properties
,
109 struct mach_iokit_devclass darwin_iomouse_devclass
= {
111 { &mach_ioroot_devclass
, NULL
},
112 darwin_iomouse_properties
,
123 struct mach_iokit_devclass darwin_ioresources_devclass
= {
125 { &mach_ioroot_devclass
, NULL
},
126 darwin_ioresources_properties
,
137 struct mach_iokit_devclass darwin_iohidsystem_devclass
= {
138 "<dict ID=\"0\"><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
,
144 darwin_iohidsystem_connect_method_scalari_scalaro
,
146 darwin_iohidsystem_connect_method_structi_structo
,
148 darwin_iohidsystem_connect_map_memory
,
154 darwin_iohidsystem_connect_method_scalari_scalaro(struct mach_trap_args
*args
)
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
;
162 printf("darwin_iohidsystem_connect_method_scalari_scalaro()\n");
164 rep
->rep_outcount
= 0;
165 maxoutcount
= req
->req_in
[req
->req_incount
];
167 switch (req
->req_selector
) {
168 case DARWIN_IOHIDCREATESHMEM
: {
169 /* Create the shared memory for HID events */
175 struct darwin_iohidsystem_thread_args
*dita
;
176 struct darwin_emuldata
*ded
;
178 vers
= req
->req_in
[0]; /* 1 */
180 printf("DARWIN_IOHIDCREATESHMEM: version = %d\n", vers
);
182 memsize
= round_page(sizeof(struct darwin_iohidsystem_shmem
));
184 /* If it has not been used yet, initialize it */
185 if (darwin_iohidsystem_shmem
== NULL
) {
186 darwin_iohidsystem_shmem
= uao_create(memsize
, 0);
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));
193 uao_detach(darwin_iohidsystem_shmem
);
194 darwin_iohidsystem_shmem
= NULL
;
195 return mach_msg_error(args
, error
);
198 error
= uvm_map_pageable(kernel_map
, kvaddr
,
199 kvaddr
+ memsize
, FALSE
, 0);
201 uao_detach(darwin_iohidsystem_shmem
);
202 darwin_iohidsystem_shmem
= NULL
;
203 return mach_msg_error(args
, error
);
206 darwin_iohidsystem_shmeminit(kvaddr
);
209 ded
= (struct darwin_emuldata
*)p
->p_emuldata
;
211 dita
= malloc(sizeof(*dita
), M_TEMP
, M_WAITOK
);
212 dita
->dita_shmem
= kvaddr
;
215 kthread_create(PRI_NONE
, 0, NULL
,
216 darwin_iohidsystem_thread
,
217 (void *)dita
, &dita
->dita_l
,
221 * Make sure the thread got the informations
222 * before exitting and destroying dita.
224 while (!dita
->dita_done
)
225 (void)tsleep(&dita
->dita_done
,
226 PZERO
, "iohid_done", 0);
228 ded
->ded_hidsystem_finished
=
229 dita
->dita_hidsystem_finished
;
234 rep
->rep_outcount
= 0;
238 case DARWIN_IOHIDSETEVENTSENABLE
: {
239 /* Enable or disable events */
242 enable
= req
->req_in
[0];
244 printf("DARWIN_IOHIDSETEVENTSENABLE: enable = %d\n", enable
);
246 /* For now, this is a no-op */
247 rep
->rep_outcount
= 0;
251 case DARWIN_IOHIDSETCURSORENABLE
: {
252 /* Enable or disable the cursor */
255 enable
= req
->req_in
[0];
257 printf("DARWIN_IOHIDSETCURSORENABLE: enable = %d\n", enable
);
259 /* We don't support it */
260 rep
->rep_outcount
= 0;
264 case DARWIN_IOHIDPOSTEVENT
: {
265 darwin_nxll_event
*dne
;
267 dne
= (darwin_nxll_event
*)&req
->req_in
[0];
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
);
274 /* We don't support it yet */
275 rep
->rep_outcount
= 0;
281 printf("Unknown selector %d\n", req
->req_selector
);
283 return mach_msg_error(args
, EINVAL
);
287 *msglen
= sizeof(*rep
) - ((16 + rep
->rep_outcount
) * sizeof(int));
288 mach_set_header(rep
, req
, *msglen
);
289 mach_set_trailer(rep
, *msglen
);
295 darwin_iohidsystem_connect_method_structi_structo(struct mach_trap_args
*args
)
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
;
305 printf("darwin_iohidsystem_connect_method_structi_structo()\n");
307 rep
->rep_outcount
= 0;
308 /* maxoutcount is word aligned */
309 maxoutcount
= req
->req_in
[(req
->req_incount
& ~0x3UL
) + 4];
311 switch (req
->req_selector
) {
312 case DARWIN_IOHIDSETMOUSELOCATION
: {
313 struct wscons_event wsevt
;
315 darwin_iogpoint
*pt
= (darwin_iogpoint
*)&req
->req_in
[0];
318 printf("DARWIN_IOHIDSETMOUSELOCATION: %d,%d\n", pt
->x
, pt
->y
);
321 * Use the wsmux given by sysctl emul.darwin.iohidsystem_mux
323 error
= darwin_findwsmux(&dev
, darwin_iohidsystem_mux
);
325 return mach_msg_error(args
, error
);
327 wsevt
.type
= WSCONS_EVENT_MOUSE_ABSOLUTE_X
;
329 if ((error
= cdev_ioctl(dev
,
330 WSMUXIO_INJECTEVENT
, (void *)&wsevt
, 0, l
)) != 0)
331 return mach_msg_error(args
, error
);
333 wsevt
.type
= WSCONS_EVENT_MOUSE_ABSOLUTE_Y
;
335 if ((error
= cdev_ioctl(dev
,
336 WSMUXIO_INJECTEVENT
, (void *)&wsevt
, 0, l
)) != 0)
337 return mach_msg_error(args
, error
);
339 rep
->rep_outcount
= 0;
345 printf("Unknown selector %d\n", req
->req_selector
);
347 return mach_msg_error(args
, EINVAL
);
352 *msglen
= sizeof(*rep
) - (4096 - rep
->rep_outcount
);
353 mach_set_header(rep
, req
, *msglen
);
354 mach_set_trailer(rep
, *msglen
);
360 darwin_iohidsystem_connect_map_memory(struct mach_trap_args
*args
)
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
;
371 printf("darwin_iohidsystem_connect_map_memory()\n");
373 memsize
= round_page(sizeof(struct darwin_iohidsystem_shmem
));
375 if (darwin_iohidsystem_shmem
== NULL
)
376 return mach_msg_error(args
, ENOMEM
);
378 uao_reference(darwin_iohidsystem_shmem
);
379 pvaddr
= VM_DEFAULT_ADDRESS(p
->p_vmspace
->vm_daddr
, memsize
);
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
);
388 printf("pvaddr = 0x%08lx\n", (long)pvaddr
);
391 *msglen
= sizeof(*rep
);
392 mach_set_header(rep
, req
, *msglen
);
395 rep
->rep_addr
= pvaddr
;
396 rep
->rep_len
= sizeof(struct darwin_iohidsystem_shmem
);
398 mach_set_trailer(rep
, *msglen
);
403 darwin_iohidsystem_thread(void *args
)
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
;
413 struct wscons_event wsevt
;
415 struct mach_right
*mr
;
420 printf("darwin_iohidsystem_thread: start\n");
422 dita
= (struct darwin_iohidsystem_thread_args
*)args
;
423 shmem
= (struct darwin_iohidsystem_shmem
*)dita
->dita_shmem
;
425 dita
->dita_hidsystem_finished
= &finished
;
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()
435 wakeup(&dita
->dita_done
);
437 evg
= (struct darwin_iohidsystem_evglobals
*)&shmem
->dis_evglobals
;
440 * Use the wsmux given by sysctl emul.darwin.iohidsystem_mux
442 if ((error
= darwin_findwsmux(&dev
, darwin_iohidsystem_mux
)) != 0)
445 if ((error
= cdev_open(dev
, FREAD
|FWRITE
, 0, l
)) != 0)
449 auio
.uio_iov
= &aiov
;
451 aiov
.iov_base
= &wsevt
;
452 aiov
.iov_len
= sizeof(wsevt
);
453 auio
.uio_resid
= sizeof(wsevt
);
455 auio
.uio_rw
= UIO_READ
;
456 UIO_SETUP_SYSSPACE(&auio
);
458 if ((error
= cdev_read(dev
, &auio
, 0)) != 0) {
460 printf("iohidsystem: read error %d\n", error
);
465 diei
= &evg
->evg_evqueue
[evg
->evg_event_last
];
466 while (diei
->diei_sem
!= 0)
467 tsleep(&diei
->diei_sem
, PZERO
, "iohid_lock", 1);
470 * No need to take the lock since we will not
471 * yield control to the user process.
474 diei
->diei_next
= evg
->evg_event_tail
;
476 diei
= &evg
->evg_evqueue
[evg
->evg_event_tail
];
477 die
= (darwin_iohidsystem_event
*)&diei
->diei_event
;
479 darwin_wscons_to_iohidsystem(&wsevt
, die
);
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;
487 * Send a I/O notification if the process
488 * has consumed all available entries
490 if (evg
->evg_event_last
== evg
->evg_event_head
) {
491 mr
= darwin_iohidsystem_devclass
.mid_notify
;
493 mach_notify_iohidsystem(l
, mr
);
498 * If the queue is full, ie: the next event slot is not
499 * yet consumed, sleep until the process consumes it.
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);
509 cdev_close(dev
, FREAD
|FWRITE
, 0, l
);
513 tsleep((void *)&finished
, PZERO
, "iohid_exit", 0);
515 uao_detach(darwin_iohidsystem_shmem
);
516 darwin_iohidsystem_shmem
= NULL
;
522 darwin_iohidsystem_shmeminit(vaddr_t kvaddr
)
524 struct darwin_iohidsystem_shmem
*shmem
;
525 struct darwin_iohidsystem_evglobals
*evglobals
;
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
);
534 evglobals
= &shmem
->dis_evglobals
;
535 evglobals
->evg_struct_size
= sizeof(*evglobals
);
537 for (i
= 0; i
< DARWIN_IOHIDSYSTEM_EVENTQUEUE_LEN
; i
++)
538 evglobals
->evg_evqueue
[i
].diei_next
= i
+ 1;
540 evg_evqueue
[DARWIN_IOHIDSYSTEM_EVENTQUEUE_LEN
- 1].diei_next
= 0;
546 darwin_findwsmux(dev_t
*dev
, int mux
)
548 extern struct cdevsw wsmux_cdevsw
;
549 struct wsmux_softc
*wsm_sc
;
552 if ((wsm_sc
= wsmux_getmux(mux
)) == NULL
)
555 major
= cdevsw_lookup_major(&wsmux_cdevsw
);
556 minor
= device_unit(wsm_sc
->sc_base
.me_dv
);
557 *dev
= makedev(major
, minor
);
563 darwin_wscons_to_iohidsystem(struct wscons_event
*wsevt
, darwin_iohidsystem_event
*hidevt
)
566 static int px
= 0; /* Previous mouse location */
568 static int pf
= 0; /* previous kbd flags */
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
;
578 switch (wsevt
->type
) {
579 case WSCONS_EVENT_MOUSE_DELTA_X
:
580 hidevt
->die_type
= DARWIN_NX_MOUSEMOVED
;
582 hidevt
->die_data
.mouse_move
.dx
= wsevt
->value
;
583 hidevt
->die_location_x
= px
;
586 case WSCONS_EVENT_MOUSE_DELTA_Y
:
587 hidevt
->die_type
= DARWIN_NX_MOUSEMOVED
;
589 hidevt
->die_data
.mouse_move
.dy
= wsevt
->value
;
590 hidevt
->die_location_y
= py
;
593 case WSCONS_EVENT_MOUSE_ABSOLUTE_X
:
594 hidevt
->die_type
= DARWIN_NX_MOUSEMOVED
;
595 hidevt
->die_location_x
= wsevt
->value
;
599 case WSCONS_EVENT_MOUSE_ABSOLUTE_Y
:
600 hidevt
->die_type
= DARWIN_NX_MOUSEMOVED
;
601 hidevt
->die_location_y
= wsevt
->value
;
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
;
612 printf("Unknown mouse button %d\n", wsevt
->value
);
616 hidevt
->die_data
.mouse
.subx
= px
;
617 hidevt
->die_data
.mouse
.suby
= py
;
618 hidevt
->die_data
.mouse
.buttonid
= wsevt
->value
;
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
;
628 printf("Unknown mouse button %d\n", wsevt
->value
);
632 hidevt
->die_data
.mouse
.subx
= px
;
633 hidevt
->die_data
.mouse
.suby
= py
;
634 hidevt
->die_data
.mouse
.buttonid
= wsevt
->value
;
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 */
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 */
658 printf("Untranslated wsevt->type = %d, wsevt->value = %d\n",
659 wsevt
->type
, wsevt
->value
);
668 mach_notify_iohidsystem(struct lwp
*l
, struct mach_right
*mr
)
670 struct mach_port
*mp
;
671 mach_notify_iohidsystem_request_t
*req
;
677 printf("Warning: notification right without a port\n");
682 req
= malloc(sizeof(*req
), M_EMULDATA
, M_WAITOK
| M_ZERO
);
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;
690 mach_set_trailer(req
, sizeof(*req
));
692 ktruser("notify_iohidsystem", NULL
, 0, 0);
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.
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
);
707 wakeup(mp
->mp_recv
->mr_sethead
);
713 darwin_iohidsystem_postfake(struct lwp
*l
)
717 struct wscons_event wsevt
;
720 * Use the wsmux given by sysctl emul.darwin.iohidsystem_mux
722 if ((error
= darwin_findwsmux(&dev
, darwin_iohidsystem_mux
)) != 0)
727 cdev_ioctl(dev
, WSMUXIO_INJECTEVENT
, (void *)&wsevt
, 0, l
);