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