1 /* $NetBSD: j720tp.c,v 1.10 2009/05/29 14:15:45 rjs Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by IWAMOTO Toshihiro and Peter Postma. 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 /* Jornada 720 touch-panel driver. */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: j720tp.c,v 1.10 2009/05/29 14:15:45 rjs Exp $"); 36 37 #ifdef _KERNEL_OPT 38 #include "opt_j720tp.h" 39 #include "opt_wsdisplay_compat.h" 40 #endif 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 #include <sys/kernel.h> 46 #include <sys/malloc.h> 47 #include <sys/ioctl.h> 48 #include <sys/callout.h> 49 #include <sys/sysctl.h> 50 51 #include <machine/platid.h> 52 #include <machine/platid_mask.h> 53 54 #include <arm/sa11x0/sa11x0_var.h> 55 #include <arm/sa11x0/sa11x0_gpioreg.h> 56 #include <arm/sa11x0/sa11x0_ppcreg.h> 57 #include <arm/sa11x0/sa11x0_sspreg.h> 58 59 #include <dev/wscons/wsconsio.h> 60 #include <dev/wscons/wsmousevar.h> 61 #include <dev/wscons/wskbdvar.h> 62 #include <dev/wscons/wsksymvar.h> 63 #include <dev/wscons/wsksymdef.h> 64 #include <dev/hpc/hpctpanelvar.h> 65 66 #include <hpcarm/dev/j720sspvar.h> 67 68 #ifdef WSDISPLAY_COMPAT_RAWKBD 69 #include <dev/hpc/pckbd_encode.h> 70 #endif 71 72 #define arraysize(ary) (sizeof(ary) / sizeof(ary[0])) 73 74 #ifdef J720TP_DEBUG 75 int j720tp_debug = 0; 76 #define DPRINTF(arg) if (j720tp_debug) aprint_normal arg 77 #define DPRINTFN(n, arg) if (j720tp_debug >= (n)) aprint_normal arg 78 #else 79 #define DPRINTF(arg) /* nothing */ 80 #define DPRINTFN(n, arg) /* nothing */ 81 #endif 82 83 struct j720tp_softc { 84 device_t sc_dev; 85 86 #define J720TP_WSMOUSE_ENABLED 0x01 87 #define J720TP_WSKBD_ENABLED 0x02 88 int sc_enabled; 89 int sc_hard_icon; 90 #ifdef WSDISPLAY_COMPAT_RAWKBD 91 int sc_rawkbd; 92 #endif 93 94 struct callout sc_tpcallout; 95 struct j720ssp_softc *sc_ssp; 96 97 device_t sc_wsmousedev; 98 device_t sc_wskbddev; 99 100 struct tpcalib_softc sc_tpcalib; 101 }; 102 103 static int j720tp_match(device_t, cfdata_t, void *); 104 static void j720tp_attach(device_t, device_t, void *); 105 106 static int j720tp_wsmouse_enable(void *); 107 static int j720tp_wsmouse_ioctl(void *, u_long, void *, int, 108 struct lwp *); 109 static void j720tp_wsmouse_disable(void *); 110 111 static int j720tp_wskbd_enable(void *, int); 112 static void j720tp_wskbd_set_leds(void *, int); 113 static int j720tp_wskbd_ioctl(void *, u_long, void *, int, struct lwp *); 114 115 static void j720tp_enable_intr(struct j720tp_softc *); 116 static void j720tp_disable_intr(struct j720tp_softc *); 117 static int j720tp_intr(void *); 118 static int j720tp_get_rawxy(struct j720tp_softc *, int *, int *); 119 static int j720tp_get_hard_icon(struct j720tp_softc *, int, int); 120 static void j720tp_wsmouse_input(struct j720tp_softc *, int, int); 121 static void j720tp_wsmouse_callout(void *); 122 static void j720tp_wskbd_input(struct j720tp_softc *, u_int); 123 static void j720tp_wskbd_callout(void *); 124 125 const struct wsmouse_accessops j720tp_wsmouse_accessops = { 126 j720tp_wsmouse_enable, 127 j720tp_wsmouse_ioctl, 128 j720tp_wsmouse_disable 129 }; 130 131 static const struct wsmouse_calibcoords j720tp_default_calib = { 132 0, 0, 639, 239, 133 4, 134 {{ 988, 80, 0, 0 }, 135 { 88, 84, 639, 0 }, 136 { 988, 927, 0, 239 }, 137 { 88, 940, 639, 239 }} 138 }; 139 140 const struct wskbd_accessops j720tp_wskbd_accessops = { 141 j720tp_wskbd_enable, 142 j720tp_wskbd_set_leds, 143 j720tp_wskbd_ioctl 144 }; 145 146 #ifndef J720TP_SETTINGS_ICON_KEYSYM 147 #define J720TP_SETTINGS_ICON_KEYSYM KS_Home 148 #endif 149 #ifndef J720TP_BACKUP_ICON_KEYSYM 150 #define J720TP_BACKUP_ICON_KEYSYM KS_Prior 151 #endif 152 #ifndef J720TP_DIALUP_ICON_KEYSYM 153 #define J720TP_DIALUP_ICON_KEYSYM KS_Next 154 #endif 155 #ifndef J720TP_MEDIA_ICON_KEYSYM 156 #define J720TP_MEDIA_ICON_KEYSYM KS_End 157 #endif 158 159 /* Max Y value of the n'th hard icon. */ 160 #define J720TP_HARD_ICON_MAX_Y(n) \ 161 (((j720tp_hard_icon_bottom - j720tp_hard_icon_top) / 4) * (n)) + \ 162 j720tp_hard_icon_top 163 164 /* Default raw X/Y values of the hard icon area. */ 165 static int j720tp_hard_icon_left = 70; 166 static int j720tp_hard_icon_right = 20; 167 static int j720tp_hard_icon_top = 70; 168 static int j720tp_hard_icon_bottom = 940; 169 170 /* Maps the icon number to a raw keycode. */ 171 static const int j720tp_wskbd_keys[] = { 172 /* Icon 1 */ 199, 173 /* Icon 2 */ 201, 174 /* Icon 3 */ 209, 175 /* Icon 4 */ 207 176 }; 177 178 static const keysym_t j720tp_wskbd_keydesc[] = { 179 KS_KEYCODE(199), J720TP_SETTINGS_ICON_KEYSYM, 180 KS_KEYCODE(201), J720TP_BACKUP_ICON_KEYSYM, 181 KS_KEYCODE(209), J720TP_DIALUP_ICON_KEYSYM, 182 KS_KEYCODE(207), J720TP_MEDIA_ICON_KEYSYM 183 }; 184 185 const struct wscons_keydesc j720tp_wskbd_keydesctab[] = { 186 { KB_US, 0, 187 sizeof(j720tp_wskbd_keydesc) / sizeof(keysym_t), 188 j720tp_wskbd_keydesc 189 }, 190 { 0, 0, 0, 0 } 191 }; 192 193 const struct wskbd_mapdata j720tp_wskbd_keymapdata = { 194 j720tp_wskbd_keydesctab, KB_US 195 }; 196 197 CFATTACH_DECL_NEW(j720tp, sizeof(struct j720tp_softc), 198 j720tp_match, j720tp_attach, NULL, NULL); 199 200 201 static int 202 j720tp_match(device_t parent, cfdata_t cf, void *aux) 203 { 204 205 if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_7XX)) 206 return 0; 207 if (strcmp(cf->cf_name, "j720tp") != 0) 208 return 0; 209 210 return 1; 211 } 212 213 static void 214 j720tp_attach(device_t parent, device_t self, void *aux) 215 { 216 struct j720tp_softc *sc = device_private(self); 217 struct wsmousedev_attach_args wsma; 218 struct wskbddev_attach_args wska; 219 220 aprint_normal("\n"); 221 222 sc->sc_dev = self; 223 sc->sc_ssp = device_private(parent); 224 sc->sc_enabled = 0; 225 sc->sc_hard_icon = 0; 226 sc->sc_rawkbd = 0; 227 228 /* Touch-panel as a pointing device. */ 229 wsma.accessops = &j720tp_wsmouse_accessops; 230 wsma.accesscookie = sc; 231 232 sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", &wsma, 233 wsmousedevprint); 234 if (sc->sc_wsmousedev == NULL) 235 return; 236 237 /* Initialize calibration, set default parameters. */ 238 tpcalib_init(&sc->sc_tpcalib); 239 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 240 __UNCONST(&j720tp_default_calib), 0, 0); 241 242 callout_init(&sc->sc_tpcallout, 0); 243 244 j720tp_wsmouse_disable(sc); 245 246 /* On-screen "hard icons" as a keyboard device. */ 247 wska.console = 0; 248 wska.keymap = &j720tp_wskbd_keymapdata; 249 wska.accessops = &j720tp_wskbd_accessops; 250 wska.accesscookie = sc; 251 252 sc->sc_wskbddev = config_found_ia(self, "wskbddev", &wska, 253 wskbddevprint); 254 255 /* Setup touch-panel interrupt. */ 256 sa11x0_intr_establish(0, 9, 1, IPL_TTY, j720tp_intr, sc); 257 } 258 259 static int 260 j720tp_wsmouse_enable(void *self) 261 { 262 struct j720tp_softc *sc = self; 263 int s; 264 265 s = spltty(); 266 267 j720tp_enable_intr(sc); 268 269 sc->sc_enabled |= J720TP_WSMOUSE_ENABLED; 270 271 splx(s); 272 return 0; 273 } 274 275 static int 276 j720tp_wsmouse_ioctl(void *self, u_long cmd, void *data, int flag, 277 struct lwp *l) 278 { 279 struct j720tp_softc *sc = self; 280 281 return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); 282 } 283 284 static void 285 j720tp_wsmouse_disable(void *self) 286 { 287 struct j720tp_softc *sc = self; 288 int s; 289 290 s = spltty(); 291 292 j720tp_disable_intr(sc); 293 callout_stop(&sc->sc_tpcallout); 294 295 sc->sc_enabled &= ~J720TP_WSMOUSE_ENABLED; 296 297 splx(s); 298 } 299 300 static int 301 j720tp_wskbd_enable(void *self, int on) 302 { 303 struct j720tp_softc *sc = self; 304 int s; 305 306 s = spltty(); 307 sc->sc_enabled |= J720TP_WSKBD_ENABLED; 308 splx(s); 309 310 return 0; 311 } 312 313 static void 314 j720tp_wskbd_set_leds(void *self, int leds) 315 { 316 /* nothing to do */ 317 } 318 319 static int 320 j720tp_wskbd_ioctl(void *self, u_long cmd, void *data, int flag, 321 struct lwp *l) 322 { 323 #ifdef WSDISPLAY_COMPAT_RAWKBD 324 struct j720tp_softc *sc = self; 325 #endif 326 327 switch (cmd) { 328 case WSKBDIO_GTYPE: 329 *(int *)data = WSKBD_TYPE_HPC_BTN; 330 return 0; 331 case WSKBDIO_GETLEDS: 332 *(int *)data = 0; 333 return 0; 334 #ifdef WSDISPLAY_COMPAT_RAWKBD 335 case WSKBDIO_SETMODE: 336 sc->sc_rawkbd = (*(int *)data == WSKBD_RAW); 337 return 0; 338 #endif 339 } 340 341 return EPASSTHROUGH; 342 } 343 344 /* 345 * Enable touch-panel interrupt. Must be called at spltty(). 346 */ 347 static void 348 j720tp_enable_intr(struct j720tp_softc *sc) 349 { 350 struct j720ssp_softc *ssp = sc->sc_ssp; 351 uint32_t er; 352 353 er = bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER); 354 er |= 1 << 9; 355 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, er); 356 } 357 358 /* 359 * Disable touch-panel interrupt. Must be called at spltty(). 360 */ 361 static void 362 j720tp_disable_intr(struct j720tp_softc *sc) 363 { 364 struct j720ssp_softc *ssp = sc->sc_ssp; 365 uint32_t er; 366 367 er = bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER); 368 er &= ~(1 << 9); 369 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, er); 370 } 371 372 static int 373 j720tp_intr(void *arg) 374 { 375 struct j720tp_softc *sc = arg; 376 struct j720ssp_softc *ssp = sc->sc_ssp; 377 int rawx, rawy; 378 379 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_EDR, 1 << 9); 380 381 if (!(sc->sc_enabled & J720TP_WSMOUSE_ENABLED)) { 382 DPRINTF(("j720tp_intr: !sc_enabled\n")); 383 return 0; 384 } 385 386 j720tp_disable_intr(sc); 387 388 if (j720tp_get_rawxy(sc, &rawx, &rawy)) { 389 sc->sc_hard_icon = j720tp_get_hard_icon(sc, rawx, rawy); 390 391 if (sc->sc_hard_icon > 0) { 392 j720tp_wskbd_input(sc, WSCONS_EVENT_KEY_DOWN); 393 callout_reset(&sc->sc_tpcallout, hz / 32, 394 j720tp_wskbd_callout, sc); 395 } else { 396 j720tp_wsmouse_input(sc, rawx, rawy); 397 callout_reset(&sc->sc_tpcallout, hz / 32, 398 j720tp_wsmouse_callout, sc); 399 } 400 } 401 402 return 1; 403 } 404 405 static int 406 j720tp_get_rawxy(struct j720tp_softc *sc, int *rawx, int *rawy) 407 { 408 struct j720ssp_softc *ssp = sc->sc_ssp; 409 int buf[8], data, i; 410 411 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PCR, 0x2000000); 412 413 /* Send read touch-panel command. */ 414 if (j720ssp_readwrite(ssp, 1, 0xa0, &data, 100) < 0 || data != 0x11) { 415 DPRINTF(("j720tp_get_rawxy: no dummy received\n")); 416 goto out; 417 } 418 419 for (i = 0; i < 8; i++) { 420 if (j720ssp_readwrite(ssp, 0, 0x11, &data, 100) < 0) 421 goto out; 422 buf[i] = data; 423 } 424 425 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 426 427 buf[6] <<= 8; 428 buf[7] <<= 8; 429 for (i = 0; i < 3; i++) { 430 buf[i] |= buf[6] & 0x300; 431 buf[6] >>= 2; 432 buf[i + 3] |= buf[7] & 0x300; 433 buf[7] >>= 2; 434 } 435 436 DPRINTFN(2, ("j720tp_get_rawxy: %d:%d:%d:%d:%d:%d:%d:%d\n", 437 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])); 438 439 *rawx = buf[1]; 440 *rawy = buf[4]; 441 442 return 1; 443 out: 444 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 445 446 /* reset SSP */ 447 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x307); 448 delay(100); 449 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x387); 450 451 DPRINTF(("j720tp_get_rawxy: error %x\n", data)); 452 return 0; 453 } 454 455 static int 456 j720tp_get_hard_icon(struct j720tp_softc *sc, int rawx, int rawy) 457 { 458 int icon = 0; 459 460 if (!(sc->sc_enabled & J720TP_WSKBD_ENABLED)) 461 return 0; 462 /* Check if the touch was in the hard icons area. */ 463 if (rawx > j720tp_hard_icon_left) 464 return 0; 465 466 if (rawy < J720TP_HARD_ICON_MAX_Y(1)) 467 icon = 1; 468 else if (rawy < J720TP_HARD_ICON_MAX_Y(2)) 469 icon = 2; 470 else if (rawy < J720TP_HARD_ICON_MAX_Y(3)) 471 icon = 3; 472 else if (rawy < J720TP_HARD_ICON_MAX_Y(4)) 473 icon = 4; 474 475 return icon; 476 } 477 478 static void 479 j720tp_wsmouse_input(struct j720tp_softc *sc, int rawx, int rawy) 480 { 481 int x, y; 482 483 tpcalib_trans(&sc->sc_tpcalib, rawx, rawy, &x, &y); 484 wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, 0, 485 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 486 } 487 488 static void 489 j720tp_wsmouse_callout(void *arg) 490 { 491 struct j720tp_softc *sc = arg; 492 struct j720ssp_softc *ssp = sc->sc_ssp; 493 int rawx, rawy, s; 494 495 s = spltty(); 496 497 if (!(sc->sc_enabled & J720TP_WSMOUSE_ENABLED)) { 498 DPRINTF(("j720tp_wsmouse_callout: !sc_enabled\n")); 499 splx(s); 500 return; 501 } 502 503 if (bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PLR) & (1<<9)) { 504 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0, 0); 505 j720tp_enable_intr(sc); 506 } else { 507 if (j720tp_get_rawxy(sc, &rawx, &rawy)) 508 j720tp_wsmouse_input(sc, rawx, rawy); 509 callout_schedule(&sc->sc_tpcallout, hz / 32); 510 } 511 512 splx(s); 513 } 514 515 static void 516 j720tp_wskbd_input(struct j720tp_softc *sc, u_int evtype) 517 { 518 int key = j720tp_wskbd_keys[sc->sc_hard_icon - 1]; 519 520 #ifdef WSDISPLAY_COMPAT_RAWKBD 521 if (sc->sc_rawkbd) { 522 int n; 523 u_char data[16]; 524 525 n = pckbd_encode(evtype, key, data); 526 wskbd_rawinput(sc->sc_wskbddev, data, n); 527 } else 528 #endif 529 wskbd_input(sc->sc_wskbddev, evtype, key); 530 } 531 532 static void 533 j720tp_wskbd_callout(void *arg) 534 { 535 struct j720tp_softc *sc = arg; 536 struct j720ssp_softc *ssp = sc->sc_ssp; 537 int s; 538 539 s = spltty(); 540 541 if (!sc->sc_enabled) { 542 DPRINTF(("j720tp_wskbd_callout: !sc_enabled\n")); 543 splx(s); 544 return; 545 } 546 547 if (bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PLR) & (1<<9)) { 548 j720tp_wskbd_input(sc, WSCONS_EVENT_KEY_UP); 549 j720tp_enable_intr(sc); 550 } else { 551 callout_schedule(&sc->sc_tpcallout, hz / 32); 552 } 553 554 splx(s); 555 } 556 557 SYSCTL_SETUP(sysctl_j720tp, "sysctl j720tp subtree setup") 558 { 559 const struct sysctlnode *rnode; 560 int rc; 561 562 if ((rc = sysctl_createv(clog, 0, NULL, &rnode, 563 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, 564 NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) 565 goto err; 566 567 if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, 568 CTLFLAG_PERMANENT, CTLTYPE_NODE, "j720tp", 569 SYSCTL_DESCR("Jornada 720 touch panel controls"), 570 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 571 goto err; 572 573 #ifdef J720TP_DEBUG 574 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 575 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 576 SYSCTL_DESCR("Verbosity of debugging messages"), 577 NULL, 0, &j720tp_debug, 0, CTL_CREATE, CTL_EOL)) != 0) 578 goto err; 579 #endif /* J720TP_DEBUG */ 580 581 if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, 582 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hard_icons", 583 SYSCTL_DESCR("Touch panel hard icons controls"), 584 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 585 goto err; 586 587 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 588 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "left", 589 SYSCTL_DESCR("Raw left X value of the hard icon area"), 590 NULL, 0, &j720tp_hard_icon_left, 0, CTL_CREATE, CTL_EOL)) != 0) 591 goto err; 592 593 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 594 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "right", 595 SYSCTL_DESCR("Raw right X value of the hard icon area"), 596 NULL, 0, &j720tp_hard_icon_right, 0, CTL_CREATE, CTL_EOL)) != 0) 597 goto err; 598 599 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 600 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "top", 601 SYSCTL_DESCR("Raw top Y value of the hard icon area"), 602 NULL, 0, &j720tp_hard_icon_top, 0, CTL_CREATE, CTL_EOL)) != 0) 603 goto err; 604 605 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 606 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "bottom", 607 SYSCTL_DESCR("Raw bottom Y value of the hard icon area"), 608 NULL, 0, &j720tp_hard_icon_bottom, 0, CTL_CREATE, CTL_EOL)) != 0) 609 goto err; 610 611 return; 612 err: 613 aprint_normal("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); 614 } 615