1 /* $NetBSD: j720tp.c,v 1.9 2008/04/28 20:23:21 martin 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.9 2008/04/28 20:23:21 martin 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) printf arg 77 #define DPRINTFN(n, arg) if (j720tp_debug >= (n)) printf arg 78 #else 79 #define DPRINTF(arg) /* nothing */ 80 #define DPRINTFN(n, arg) /* nothing */ 81 #endif 82 83 struct j720tp_softc { 84 struct device 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 struct device *sc_wsmousedev; 98 struct device *sc_wskbddev; 99 100 struct tpcalib_softc sc_tpcalib; 101 }; 102 103 static int j720tp_match(struct device *, struct cfdata *, void *); 104 static void j720tp_attach(struct device *, struct device *, 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(j720tp, sizeof(struct j720tp_softc), 198 j720tp_match, j720tp_attach, NULL, NULL); 199 200 201 static int 202 j720tp_match(struct device *parent, struct cfdata *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(struct device *parent, struct device *self, void *aux) 215 { 216 struct j720tp_softc *sc = (struct j720tp_softc *)self; 217 struct wsmousedev_attach_args wsma; 218 struct wskbddev_attach_args wska; 219 220 printf("\n"); 221 222 sc->sc_ssp = (struct j720ssp_softc *)parent; 223 sc->sc_enabled = 0; 224 sc->sc_hard_icon = 0; 225 sc->sc_rawkbd = 0; 226 227 /* Touch-panel as a pointing device. */ 228 wsma.accessops = &j720tp_wsmouse_accessops; 229 wsma.accesscookie = sc; 230 231 sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", &wsma, 232 wsmousedevprint); 233 if (sc->sc_wsmousedev == NULL) 234 return; 235 236 /* Initialize calibration, set default parameters. */ 237 tpcalib_init(&sc->sc_tpcalib); 238 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 239 __UNCONST(&j720tp_default_calib), 0, 0); 240 241 callout_init(&sc->sc_tpcallout, 0); 242 243 j720tp_wsmouse_disable(sc); 244 245 /* On-screen "hard icons" as a keyboard device. */ 246 wska.console = 0; 247 wska.keymap = &j720tp_wskbd_keymapdata; 248 wska.accessops = &j720tp_wskbd_accessops; 249 wska.accesscookie = sc; 250 251 sc->sc_wskbddev = config_found_ia(self, "wskbddev", &wska, 252 wskbddevprint); 253 254 /* Setup touch-panel interrupt. */ 255 sa11x0_intr_establish(0, 9, 1, IPL_TTY, j720tp_intr, sc); 256 } 257 258 static int 259 j720tp_wsmouse_enable(void *self) 260 { 261 struct j720tp_softc *sc = self; 262 int s; 263 264 s = spltty(); 265 266 j720tp_enable_intr(sc); 267 268 sc->sc_enabled |= J720TP_WSMOUSE_ENABLED; 269 270 splx(s); 271 return 0; 272 } 273 274 static int 275 j720tp_wsmouse_ioctl(void *self, u_long cmd, void *data, int flag, 276 struct lwp *l) 277 { 278 struct j720tp_softc *sc = self; 279 280 return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); 281 } 282 283 static void 284 j720tp_wsmouse_disable(void *self) 285 { 286 struct j720tp_softc *sc = self; 287 int s; 288 289 s = spltty(); 290 291 j720tp_disable_intr(sc); 292 callout_stop(&sc->sc_tpcallout); 293 294 sc->sc_enabled &= ~J720TP_WSMOUSE_ENABLED; 295 296 splx(s); 297 } 298 299 static int 300 j720tp_wskbd_enable(void *self, int on) 301 { 302 struct j720tp_softc *sc = self; 303 int s; 304 305 s = spltty(); 306 sc->sc_enabled |= J720TP_WSKBD_ENABLED; 307 splx(s); 308 309 return 0; 310 } 311 312 static void 313 j720tp_wskbd_set_leds(void *self, int leds) 314 { 315 /* nothing to do */ 316 } 317 318 static int 319 j720tp_wskbd_ioctl(void *self, u_long cmd, void *data, int flag, 320 struct lwp *l) 321 { 322 #ifdef WSDISPLAY_COMPAT_RAWKBD 323 struct j720tp_softc *sc = self; 324 #endif 325 326 switch (cmd) { 327 case WSKBDIO_GTYPE: 328 *(int *)data = WSKBD_TYPE_HPC_BTN; 329 return 0; 330 case WSKBDIO_GETLEDS: 331 *(int *)data = 0; 332 return 0; 333 #ifdef WSDISPLAY_COMPAT_RAWKBD 334 case WSKBDIO_SETMODE: 335 sc->sc_rawkbd = (*(int *)data == WSKBD_RAW); 336 return 0; 337 #endif 338 } 339 340 return EPASSTHROUGH; 341 } 342 343 /* 344 * Enable touch-panel interrupt. Must be called at spltty(). 345 */ 346 static void 347 j720tp_enable_intr(struct j720tp_softc *sc) 348 { 349 struct j720ssp_softc *ssp = sc->sc_ssp; 350 uint32_t er; 351 352 er = bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER); 353 er |= 1 << 9; 354 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, er); 355 } 356 357 /* 358 * Disable touch-panel interrupt. Must be called at spltty(). 359 */ 360 static void 361 j720tp_disable_intr(struct j720tp_softc *sc) 362 { 363 struct j720ssp_softc *ssp = sc->sc_ssp; 364 uint32_t er; 365 366 er = bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER); 367 er &= ~(1 << 9); 368 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, er); 369 } 370 371 static int 372 j720tp_intr(void *arg) 373 { 374 struct j720tp_softc *sc = arg; 375 struct j720ssp_softc *ssp = sc->sc_ssp; 376 int rawx, rawy; 377 378 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_EDR, 1 << 9); 379 380 if (!(sc->sc_enabled & J720TP_WSMOUSE_ENABLED)) { 381 DPRINTF(("j720tp_intr: !sc_enabled\n")); 382 return 0; 383 } 384 385 j720tp_disable_intr(sc); 386 387 if (j720tp_get_rawxy(sc, &rawx, &rawy)) { 388 sc->sc_hard_icon = j720tp_get_hard_icon(sc, rawx, rawy); 389 390 if (sc->sc_hard_icon > 0) { 391 j720tp_wskbd_input(sc, WSCONS_EVENT_KEY_DOWN); 392 callout_reset(&sc->sc_tpcallout, hz / 32, 393 j720tp_wskbd_callout, sc); 394 } else { 395 j720tp_wsmouse_input(sc, rawx, rawy); 396 callout_reset(&sc->sc_tpcallout, hz / 32, 397 j720tp_wsmouse_callout, sc); 398 } 399 } 400 401 return 1; 402 } 403 404 static int 405 j720tp_get_rawxy(struct j720tp_softc *sc, int *rawx, int *rawy) 406 { 407 struct j720ssp_softc *ssp = sc->sc_ssp; 408 int buf[8], data, i; 409 410 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PCR, 0x2000000); 411 412 /* Send read touch-panel command. */ 413 if (j720ssp_readwrite(ssp, 1, 0xa0, &data, 100) < 0 || data != 0x11) { 414 DPRINTF(("j720tp_get_rawxy: no dummy received\n")); 415 goto out; 416 } 417 418 for (i = 0; i < 8; i++) { 419 if (j720ssp_readwrite(ssp, 0, 0x11, &data, 100) < 0) 420 goto out; 421 buf[i] = data; 422 } 423 424 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 425 426 buf[6] <<= 8; 427 buf[7] <<= 8; 428 for (i = 0; i < 3; i++) { 429 buf[i] |= buf[6] & 0x300; 430 buf[6] >>= 2; 431 buf[i + 3] |= buf[7] & 0x300; 432 buf[7] >>= 2; 433 } 434 435 DPRINTFN(2, ("j720tp_get_rawxy: %d:%d:%d:%d:%d:%d:%d:%d\n", 436 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])); 437 438 *rawx = buf[1]; 439 *rawy = buf[4]; 440 441 return 1; 442 out: 443 bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000); 444 445 /* reset SSP */ 446 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x307); 447 delay(100); 448 bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x387); 449 450 DPRINTF(("j720tp_get_rawxy: error %x\n", data)); 451 return 0; 452 } 453 454 static int 455 j720tp_get_hard_icon(struct j720tp_softc *sc, int rawx, int rawy) 456 { 457 int icon = 0; 458 459 if (!(sc->sc_enabled & J720TP_WSKBD_ENABLED)) 460 return 0; 461 /* Check if the touch was in the hard icons area. */ 462 if (rawx > j720tp_hard_icon_left) 463 return 0; 464 465 if (rawy < J720TP_HARD_ICON_MAX_Y(1)) 466 icon = 1; 467 else if (rawy < J720TP_HARD_ICON_MAX_Y(2)) 468 icon = 2; 469 else if (rawy < J720TP_HARD_ICON_MAX_Y(3)) 470 icon = 3; 471 else if (rawy < J720TP_HARD_ICON_MAX_Y(4)) 472 icon = 4; 473 474 return icon; 475 } 476 477 static void 478 j720tp_wsmouse_input(struct j720tp_softc *sc, int rawx, int rawy) 479 { 480 int x, y; 481 482 tpcalib_trans(&sc->sc_tpcalib, rawx, rawy, &x, &y); 483 wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, 0, 484 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 485 } 486 487 static void 488 j720tp_wsmouse_callout(void *arg) 489 { 490 struct j720tp_softc *sc = arg; 491 struct j720ssp_softc *ssp = sc->sc_ssp; 492 int rawx, rawy, s; 493 494 s = spltty(); 495 496 if (!(sc->sc_enabled & J720TP_WSMOUSE_ENABLED)) { 497 DPRINTF(("j720tp_wsmouse_callout: !sc_enabled\n")); 498 splx(s); 499 return; 500 } 501 502 if (bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PLR) & (1<<9)) { 503 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0, 0); 504 j720tp_enable_intr(sc); 505 } else { 506 if (j720tp_get_rawxy(sc, &rawx, &rawy)) 507 j720tp_wsmouse_input(sc, rawx, rawy); 508 callout_schedule(&sc->sc_tpcallout, hz / 32); 509 } 510 511 splx(s); 512 } 513 514 static void 515 j720tp_wskbd_input(struct j720tp_softc *sc, u_int evtype) 516 { 517 int key = j720tp_wskbd_keys[sc->sc_hard_icon - 1]; 518 519 #ifdef WSDISPLAY_COMPAT_RAWKBD 520 if (sc->sc_rawkbd) { 521 int n; 522 u_char data[16]; 523 524 n = pckbd_encode(evtype, key, data); 525 wskbd_rawinput(sc->sc_wskbddev, data, n); 526 } else 527 #endif 528 wskbd_input(sc->sc_wskbddev, evtype, key); 529 } 530 531 static void 532 j720tp_wskbd_callout(void *arg) 533 { 534 struct j720tp_softc *sc = arg; 535 struct j720ssp_softc *ssp = sc->sc_ssp; 536 int s; 537 538 s = spltty(); 539 540 if (!sc->sc_enabled) { 541 DPRINTF(("j720tp_wskbd_callout: !sc_enabled\n")); 542 splx(s); 543 return; 544 } 545 546 if (bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PLR) & (1<<9)) { 547 j720tp_wskbd_input(sc, WSCONS_EVENT_KEY_UP); 548 j720tp_enable_intr(sc); 549 } else { 550 callout_schedule(&sc->sc_tpcallout, hz / 32); 551 } 552 553 splx(s); 554 } 555 556 SYSCTL_SETUP(sysctl_j720tp, "sysctl j720tp subtree setup") 557 { 558 const struct sysctlnode *rnode; 559 int rc; 560 561 if ((rc = sysctl_createv(clog, 0, NULL, &rnode, 562 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, 563 NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) 564 goto err; 565 566 if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, 567 CTLFLAG_PERMANENT, CTLTYPE_NODE, "j720tp", 568 SYSCTL_DESCR("Jornada 720 touch panel controls"), 569 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 570 goto err; 571 572 #ifdef J720TP_DEBUG 573 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 574 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 575 SYSCTL_DESCR("Verbosity of debugging messages"), 576 NULL, 0, &j720tp_debug, 0, CTL_CREATE, CTL_EOL)) != 0) 577 goto err; 578 #endif /* J720TP_DEBUG */ 579 580 if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, 581 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hard_icons", 582 SYSCTL_DESCR("Touch panel hard icons controls"), 583 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 584 goto err; 585 586 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 587 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "left", 588 SYSCTL_DESCR("Raw left X value of the hard icon area"), 589 NULL, 0, &j720tp_hard_icon_left, 0, CTL_CREATE, CTL_EOL)) != 0) 590 goto err; 591 592 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 593 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "right", 594 SYSCTL_DESCR("Raw right X value of the hard icon area"), 595 NULL, 0, &j720tp_hard_icon_right, 0, CTL_CREATE, CTL_EOL)) != 0) 596 goto err; 597 598 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 599 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "top", 600 SYSCTL_DESCR("Raw top Y value of the hard icon area"), 601 NULL, 0, &j720tp_hard_icon_top, 0, CTL_CREATE, CTL_EOL)) != 0) 602 goto err; 603 604 if ((rc = sysctl_createv(clog, 0, &rnode, NULL, 605 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "bottom", 606 SYSCTL_DESCR("Raw bottom Y value of the hard icon area"), 607 NULL, 0, &j720tp_hard_icon_bottom, 0, CTL_CREATE, CTL_EOL)) != 0) 608 goto err; 609 610 return; 611 err: 612 printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); 613 } 614