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