1 /* $NetBSD: btnmgr.c,v 1.24 2009/05/12 12:13:49 cegger Exp $ */
5 * Shin Takemura and PocketBSD Project. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the PocketBSD project
18 * and its contributors.
19 * 4. Neither the name of the project nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: btnmgr.c,v 1.24 2009/05/12 12:13:49 cegger Exp $");
41 #include "opt_btnmgr.h"
42 #include "opt_wsdisplay_compat.h"
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/ioctl.h>
49 #include <sys/device.h>
50 #include <sys/malloc.h>
51 #include <sys/kernel.h>
53 #include <dev/wscons/wsconsio.h>
54 #include <dev/wscons/wskbdvar.h>
55 #include <dev/wscons/wsksymdef.h>
56 #ifdef WSDISPLAY_COMPAT_RAWKBD
57 #include <dev/hpc/pckbd_encode.h>
61 #include <machine/autoconf.h>
62 #include <machine/config_hook.h>
65 #ifndef BTNMGRDEBUG_CONF
66 #define BTNMGRDEBUG_CONF 0
68 int btnmgr_debug
= BTNMGRDEBUG_CONF
;
69 #define DPRINTF(arg) if (btnmgr_debug) printf arg;
70 #define DPRINTFN(n, arg) if (btnmgr_debug > (n)) printf arg;
73 #define DPRINTFN(n, arg)
78 config_hook_tag sc_hook_tag
;
81 #ifdef WSDISPLAY_COMPAT_RAWKBD
86 int btnmgrmatch(device_t
, cfdata_t
, void *);
87 void btnmgrattach(device_t
, device_t
, void *);
88 const char *btnmgr_name(long);
89 static int btnmgr_hook(void *, int, long, void *);
94 CFATTACH_DECL(btnmgr
, sizeof(struct btnmgr_softc
),
95 btnmgrmatch
, btnmgrattach
, NULL
, NULL
);
98 dev_type_open(btnmgropen
);
99 dev_type_close(btnmgrclose
);
100 dev_type_read(btnmgrread
);
101 dev_type_write(btnmgrwrite
);
102 dev_type_ioctl(btnmgrioctl
);
104 const struct cdevsw btnmgr_cdevsw
= {
105 btnmgropen
, btnmgrclose
, btnmgrread
, btnmgrwrite
, btnmgrioctl
,
106 nostop
, notty
, nopoll
, nommap
, nokqfilter
,
110 /* wskbd accessopts */
111 int btnmgr_wskbd_enable(void *, int);
112 void btnmgr_wskbd_set_leds(void *, int);
113 int btnmgr_wskbd_ioctl(void *, u_long
, void *, int, struct lwp
*);
115 const struct wskbd_accessops btnmgr_wskbd_accessops
= {
117 btnmgr_wskbd_set_leds
,
121 /* button config: index by button event id */
122 static const struct {
126 } button_config
[] = {
127 /* id kevent keycode name */
128 [CONFIG_HOOK_BUTTONEVENT_POWER
] = { 0, 0, "Power" },
129 [CONFIG_HOOK_BUTTONEVENT_OK
] = { 1, 28, "OK" },
130 [CONFIG_HOOK_BUTTONEVENT_CANCEL
] = { 1, 1, "Cancel" },
131 [CONFIG_HOOK_BUTTONEVENT_UP
] = { 1, 72, "Up" },
132 [CONFIG_HOOK_BUTTONEVENT_DOWN
] = { 1, 80, "Down" },
133 [CONFIG_HOOK_BUTTONEVENT_REC
] = { 0, 0, "Rec" },
134 [CONFIG_HOOK_BUTTONEVENT_COVER
] = { 0, 0, "Cover" },
135 [CONFIG_HOOK_BUTTONEVENT_LIGHT
] = { 1, 57, "Light" },
136 [CONFIG_HOOK_BUTTONEVENT_CONTRAST
] = { 0, 0, "Contrast" },
137 [CONFIG_HOOK_BUTTONEVENT_APP0
] = { 1, 67, "Application 0" },
138 [CONFIG_HOOK_BUTTONEVENT_APP1
] = { 1, 68, "Application 1" },
139 [CONFIG_HOOK_BUTTONEVENT_APP2
] = { 1, 87, "Application 2" },
140 [CONFIG_HOOK_BUTTONEVENT_APP3
] = { 1, 88, "Application 3" },
142 static const int n_button_config
=
143 sizeof(button_config
) / sizeof(*button_config
);
145 #define KC(n) KS_KEYCODE(n)
146 static const keysym_t btnmgr_keydesc_default
[] = {
147 /* pos normal shifted */
150 KC(57), KS_Cmd
, KS_Cmd_BacklightToggle
,
159 #define KBD_MAP(name, base, map) \
160 { name, base, sizeof(map)/sizeof(keysym_t), map }
161 const struct wscons_keydesc btnmgr_keydesctab
[] = {
162 KBD_MAP(KB_US
, 0, btnmgr_keydesc_default
),
167 struct wskbd_mapdata btnmgr_keymapdata
= {
169 KB_US
, /* XXX, This is bad idea... */
176 btnmgrmatch(device_t parent
, cfdata_t match
, void *aux
)
178 struct mainbus_attach_args
*ma
= aux
;
180 if (strcmp(ma
->ma_name
, match
->cf_name
))
187 btnmgrattach(device_t parent
,
188 device_t self
, void *aux
)
191 struct btnmgr_softc
*sc
= device_private(self
);
192 struct wskbddev_attach_args wa
;
197 * install button event listener
199 for (id
= 0; id
<= n_button_config
; id
++)
200 if (button_config
[id
].name
!= NULL
)
201 sc
->sc_hook_tag
= config_hook(CONFIG_HOOK_BUTTONEVENT
,
202 id
, CONFIG_HOOK_SHARE
,
209 wa
.keymap
= &btnmgr_keymapdata
;
210 wa
.accessops
= &btnmgr_wskbd_accessops
;
211 wa
.accesscookie
= sc
;
213 sc
->sc_wskbddev
= config_found(self
, &wa
, wskbddevprint
);
215 if (!pmf_device_register(self
, NULL
, NULL
))
216 aprint_error_dev(self
, "unable to establish power handler\n");
220 btnmgr_hook(void *ctx
, int type
, long id
, void *msg
)
222 struct btnmgr_softc
*sc
= ctx
;
224 DPRINTF(("%s button: %s\n", btnmgr_name(id
), msg
? "ON" : "OFF"));
226 if (button_config
[id
].kevent
) {
228 evtype
= msg
? WSCONS_EVENT_KEY_DOWN
: WSCONS_EVENT_KEY_UP
;
229 #ifdef WSDISPLAY_COMPAT_RAWKBD
233 n
= pckbd_encode(evtype
, button_config
[id
].keycode
,
235 wskbd_rawinput(sc
->sc_wskbddev
, data
, n
);
238 wskbd_input(sc
->sc_wskbddev
, evtype
,
239 button_config
[id
].keycode
);
242 if (id
== CONFIG_HOOK_BUTTONEVENT_POWER
&& msg
)
243 config_hook_call(CONFIG_HOOK_PMEVENT
,
244 CONFIG_HOOK_PMEVENT_SUSPENDREQ
, NULL
);
245 else if (id
== CONFIG_HOOK_BUTTONEVENT_COVER
)
246 config_hook_call(CONFIG_HOOK_POWERCONTROL
,
247 CONFIG_HOOK_POWERCONTROL_LCDLIGHT
, (void*)(msg
? 0: 1));
255 if (id
< n_button_config
)
256 return (button_config
[id
].name
);
261 btnmgr_wskbd_enable(void *scx
, int on
)
263 struct btnmgr_softc
*sc
= scx
;
277 btnmgr_wskbd_set_leds(void *scx
, int leds
)
280 * We have nothing to do.
285 btnmgr_wskbd_ioctl(void *scx
, u_long cmd
, void *data
, int flag
,
288 #ifdef WSDISPLAY_COMPAT_RAWKBD
289 struct btnmgr_softc
*sc
= scx
;
293 *(int *)data
= WSKBD_TYPE_HPC_BTN
;
295 case WSKBDIO_SETLEDS
:
296 DPRINTF(("%s(%d): no LED\n", __FILE__
, __LINE__
));
298 case WSKBDIO_GETLEDS
:
299 DPRINTF(("%s(%d): no LED\n", __FILE__
, __LINE__
));
302 #ifdef WSDISPLAY_COMPAT_RAWKBD
303 case WSKBDIO_SETMODE
:
304 sc
->sc_rawkbd
= (*(int *)data
== WSKBD_RAW
);
305 DPRINTF(("%s(%d): rawkbd is %s\n", __FILE__
, __LINE__
,
306 sc
->sc_rawkbd
? "on" : "off"));
310 return (EPASSTHROUGH
);
315 btnmgropen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
321 btnmgrclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
327 btnmgrread(dev_t dev
, struct uio
*uio
, int flag
)
333 btnmgrwrite(dev_t dev
, struct uio
*uio
, int flag
)
339 btnmgrioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)