Mon Mar 28 12:44:17 2022 UTC ()
uhidev(9): Make uhidev state opaque.

This makes the API simpler and clearer and gives us more latitude to
fix bugs in the state management without breaking the ABI.

XXX kernel ABI change to signature of uhidev_get_report_desc and
uhidev_open, and to struct uhidev_attach_arg, requires bump for
uhidev driver modules


(riastradh)
diff -r1.28 -r1.29 src/sys/dev/usb/uatp.c
diff -r1.54 -r1.55 src/sys/dev/usb/ucycom.c
diff -r1.122 -r1.123 src/sys/dev/usb/uhid.c
diff -r1.89 -r1.90 src/sys/dev/usb/uhidev.c
diff -r1.25 -r1.26 src/sys/dev/usb/uhidev.h
diff -r1.158 -r1.159 src/sys/dev/usb/ukbd.c
diff -r1.102 -r1.103 src/sys/dev/usb/ums.c
diff -r1.22 -r1.23 src/sys/dev/usb/uthum.c
diff -r1.14 -r1.15 src/sys/dev/usb/uts.c

cvs diff -r1.28 -r1.29 src/sys/dev/usb/uatp.c (expand / switch to unified diff)

--- src/sys/dev/usb/uatp.c 2022/03/28 12:43:12 1.28
+++ src/sys/dev/usb/uatp.c 2022/03/28 12:44:17 1.29
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $ */ 1/* $NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. 4 * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Taylor R. Campbell. 8 * by Taylor R. Campbell.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -136,27 +136,27 @@ @@ -136,27 +136,27 @@
136 * - What devices split packets in chunks? 136 * - What devices split packets in chunks?
137 * `partial packet: ... bytes' 137 * `partial packet: ... bytes'
138 * 138 *
139 * - What devices develop large sensor readouts? 139 * - What devices develop large sensor readouts?
140 * `large sensor readout: ...' 140 * `large sensor readout: ...'
141 * 141 *
142 * - What devices have the wrong number of sensors? Are there parts of 142 * - What devices have the wrong number of sensors? Are there parts of
143 * your trackpad that the system doesn't seem to notice? You can 143 * your trackpad that the system doesn't seem to notice? You can
144 * tweak hw.uatp0.x_sensors and hw.uatp0.y_sensors, up to a maximum 144 * tweak hw.uatp0.x_sensors and hw.uatp0.y_sensors, up to a maximum
145 * of 32 for each value. 145 * of 32 for each value.
146 */ 146 */
147 147
148#include <sys/cdefs.h> 148#include <sys/cdefs.h>
149__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $"); 149__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $");
150 150
151#ifdef _KERNEL_OPT 151#ifdef _KERNEL_OPT
152#include "opt_usb.h" 152#include "opt_usb.h"
153#endif 153#endif
154 154
155#include <sys/types.h> 155#include <sys/types.h>
156#include <sys/param.h> 156#include <sys/param.h>
157#include <sys/atomic.h> 157#include <sys/atomic.h>
158#include <sys/device.h> 158#include <sys/device.h>
159#include <sys/errno.h> 159#include <sys/errno.h>
160#include <sys/ioctl.h> 160#include <sys/ioctl.h>
161#include <sys/kernel.h> 161#include <sys/kernel.h>
162#include <sys/module.h> 162#include <sys/module.h>
@@ -291,27 +291,27 @@ static void uatp_setup_sysctl(struct uat @@ -291,27 +291,27 @@ static void uatp_setup_sysctl(struct uat
291static bool uatp_setup_sysctl_knob(struct uatp_softc *, int *, const char *, 291static bool uatp_setup_sysctl_knob(struct uatp_softc *, int *, const char *,
292 const char *); 292 const char *);
293static void uatp_childdet(device_t, device_t); 293static void uatp_childdet(device_t, device_t);
294static int uatp_detach(device_t, int); 294static int uatp_detach(device_t, int);
295static int uatp_activate(device_t, enum devact); 295static int uatp_activate(device_t, enum devact);
296static int uatp_enable(void *); 296static int uatp_enable(void *);
297static void uatp_disable(void *); 297static void uatp_disable(void *);
298static int uatp_ioctl(void *, unsigned long, void *, int, struct lwp *); 298static int uatp_ioctl(void *, unsigned long, void *, int, struct lwp *);
299static void geyser34_enable_raw_mode(struct uatp_softc *); 299static void geyser34_enable_raw_mode(struct uatp_softc *);
300static void geyser34_initialize(struct uatp_softc *); 300static void geyser34_initialize(struct uatp_softc *);
301static int geyser34_finalize(struct uatp_softc *); 301static int geyser34_finalize(struct uatp_softc *);
302static void geyser34_deferred_reset(struct uatp_softc *); 302static void geyser34_deferred_reset(struct uatp_softc *);
303static void geyser34_reset_task(void *); 303static void geyser34_reset_task(void *);
304static void uatp_intr(struct uhidev *, void *, unsigned int); 304static void uatp_intr(void *, void *, unsigned int);
305static bool base_sample_softc_flag(const struct uatp_softc *, const uint8_t *); 305static bool base_sample_softc_flag(const struct uatp_softc *, const uint8_t *);
306static bool base_sample_input_flag(const struct uatp_softc *, const uint8_t *); 306static bool base_sample_input_flag(const struct uatp_softc *, const uint8_t *);
307static void read_sample_1(uint8_t *, uint8_t *, const uint8_t *); 307static void read_sample_1(uint8_t *, uint8_t *, const uint8_t *);
308static void read_sample_2(uint8_t *, uint8_t *, const uint8_t *); 308static void read_sample_2(uint8_t *, uint8_t *, const uint8_t *);
309static void accumulate_sample_1(struct uatp_softc *); 309static void accumulate_sample_1(struct uatp_softc *);
310static void accumulate_sample_2(struct uatp_softc *); 310static void accumulate_sample_2(struct uatp_softc *);
311static void uatp_input(struct uatp_softc *, uint32_t, int, int, int, int); 311static void uatp_input(struct uatp_softc *, uint32_t, int, int, int, int);
312static uint32_t uatp_tapped_buttons(struct uatp_softc *); 312static uint32_t uatp_tapped_buttons(struct uatp_softc *);
313static bool interpret_input(struct uatp_softc *, int *, int *, int *, int *, 313static bool interpret_input(struct uatp_softc *, int *, int *, int *, int *,
314 uint32_t *); 314 uint32_t *);
315static unsigned int interpret_dimension(struct uatp_softc *, const int *, 315static unsigned int interpret_dimension(struct uatp_softc *, const int *,
316 unsigned int, unsigned int, unsigned int *, unsigned int *); 316 unsigned int, unsigned int, unsigned int *, unsigned int *);
317static void tap_initialize(struct uatp_softc *); 317static void tap_initialize(struct uatp_softc *);
@@ -476,27 +476,28 @@ static const struct uatp_knobs default_k @@ -476,27 +476,28 @@ static const struct uatp_knobs default_k
476 * Tapping. Disabled by default, with a reasonable time set 476 * Tapping. Disabled by default, with a reasonable time set
477 * nevertheless so that you can just set the buttons to enable 477 * nevertheless so that you can just set the buttons to enable
478 * it. 478 * it.
479 */ 479 */
480 .tap_limit_msec = 100, 480 .tap_limit_msec = 100,
481 .double_tap_limit_msec = 200, 481 .double_tap_limit_msec = 200,
482 .one_finger_tap_buttons = 0, 482 .one_finger_tap_buttons = 0,
483 .two_finger_tap_buttons = 0, 483 .two_finger_tap_buttons = 0,
484 .three_finger_tap_buttons = 0, 484 .three_finger_tap_buttons = 0,
485 .tap_track_distance_limit = 200, 485 .tap_track_distance_limit = 200,
486}; 486};
487 487
488struct uatp_softc { 488struct uatp_softc {
489 struct uhidev sc_hdev; /* uhidev(9) parent. */ 489 device_t sc_dev;
 490 struct uhidev *sc_hdev; /* uhidev(9) parent. */
490 struct usbd_device *sc_udev; /* USB device. */ 491 struct usbd_device *sc_udev; /* USB device. */
491 device_t sc_wsmousedev; /* Attached wsmouse device. */ 492 device_t sc_wsmousedev; /* Attached wsmouse device. */
492 const struct uatp_parameters *sc_parameters; 493 const struct uatp_parameters *sc_parameters;
493 struct uatp_knobs sc_knobs; 494 struct uatp_knobs sc_knobs;
494 struct sysctllog *sc_log; /* Log for sysctl knobs. */ 495 struct sysctllog *sc_log; /* Log for sysctl knobs. */
495 const struct sysctlnode *sc_node; /* Our sysctl node. */ 496 const struct sysctlnode *sc_node; /* Our sysctl node. */
496 unsigned int sc_input_size; /* Input packet size. */ 497 unsigned int sc_input_size; /* Input packet size. */
497 uint8_t sc_input[UATP_MAX_INPUT_SIZE]; /* Buffer for a packet. */ 498 uint8_t sc_input[UATP_MAX_INPUT_SIZE]; /* Buffer for a packet. */
498 unsigned int sc_input_index; /* Current index into sc_input. */ 499 unsigned int sc_input_index; /* Current index into sc_input. */
499 int sc_acc[UATP_SENSORS]; /* Accumulated sensor state. */ 500 int sc_acc[UATP_SENSORS]; /* Accumulated sensor state. */
500 uint8_t sc_base[UATP_SENSORS]; /* Base sample. */ 501 uint8_t sc_base[UATP_SENSORS]; /* Base sample. */
501 uint8_t sc_sample[UATP_SENSORS];/* Current sample. */ 502 uint8_t sc_sample[UATP_SENSORS];/* Current sample. */
502 unsigned int sc_motion_timer; /* XXX describe; motion_delay */ 503 unsigned int sc_motion_timer; /* XXX describe; motion_delay */
@@ -681,27 +682,27 @@ find_uatp_descriptor(const struct uhidev @@ -681,27 +682,27 @@ find_uatp_descriptor(const struct uhidev
681 unsigned int i; 682 unsigned int i;
682 683
683 for (i = 0; i < __arraycount(uatp_descriptors); i++) 684 for (i = 0; i < __arraycount(uatp_descriptors); i++)
684 if ((uha->uiaa->uiaa_vendor == uatp_descriptors[i].vendor) && 685 if ((uha->uiaa->uiaa_vendor == uatp_descriptors[i].vendor) &&
685 (uha->uiaa->uiaa_product == uatp_descriptors[i].product)) 686 (uha->uiaa->uiaa_product == uatp_descriptors[i].product))
686 return &uatp_descriptors[i]; 687 return &uatp_descriptors[i];
687 688
688 return NULL; 689 return NULL;
689} 690}
690 691
691static device_t 692static device_t
692uatp_dev(const struct uatp_softc *sc) 693uatp_dev(const struct uatp_softc *sc)
693{ 694{
694 return sc->sc_hdev.sc_dev; 695 return sc->sc_dev;
695} 696}
696 697
697static uint8_t * 698static uint8_t *
698uatp_x_sample(struct uatp_softc *sc) 699uatp_x_sample(struct uatp_softc *sc)
699{ 700{
700 return &sc->sc_sample[0]; 701 return &sc->sc_sample[0];
701} 702}
702 703
703static uint8_t * 704static uint8_t *
704uatp_y_sample(struct uatp_softc *sc) 705uatp_y_sample(struct uatp_softc *sc)
705{ 706{
706 return &sc->sc_sample[UATP_MAX_X_SENSORS]; 707 return &sc->sc_sample[UATP_MAX_X_SENSORS];
707} 708}
@@ -921,44 +922,40 @@ uatp_match(device_t parent, cfdata_t mat @@ -921,44 +922,40 @@ uatp_match(device_t parent, cfdata_t mat
921 return UMATCH_VENDOR_PRODUCT_CONF_IFACE; 922 return UMATCH_VENDOR_PRODUCT_CONF_IFACE;
922} 923}
923 924
924static void 925static void
925uatp_attach(device_t parent, device_t self, void *aux) 926uatp_attach(device_t parent, device_t self, void *aux)
926{ 927{
927 struct uatp_softc *sc = device_private(self); 928 struct uatp_softc *sc = device_private(self);
928 const struct uhidev_attach_arg *uha = aux; 929 const struct uhidev_attach_arg *uha = aux;
929 const struct uatp_descriptor *uatp_descriptor; 930 const struct uatp_descriptor *uatp_descriptor;
930 void *report_descriptor; 931 void *report_descriptor;
931 int report_size, input_size; 932 int report_size, input_size;
932 struct wsmousedev_attach_args a; 933 struct wsmousedev_attach_args a;
933 934
934 /* Set up uhidev state. (Why doesn't uhidev do most of this?) */ 935 sc->sc_dev = self;
935 sc->sc_hdev.sc_dev = self; 936 sc->sc_hdev = uha->parent;
936 sc->sc_hdev.sc_intr = uatp_intr; 
937 sc->sc_hdev.sc_parent = uha->parent; 
938 sc->sc_hdev.sc_report_id = uha->reportid; 
939 
940 sc->sc_udev = uha->uiaa->uiaa_device; 937 sc->sc_udev = uha->uiaa->uiaa_device;
941 938
942 /* Identify ourselves to dmesg. */ 939 /* Identify ourselves to dmesg. */
943 uatp_descriptor = find_uatp_descriptor(uha); 940 uatp_descriptor = find_uatp_descriptor(uha);
944 KASSERT(uatp_descriptor != NULL); 941 KASSERT(uatp_descriptor != NULL);
945 aprint_normal(": %s\n", uatp_descriptor->description); 942 aprint_normal(": %s\n", uatp_descriptor->description);
946 aprint_naive(": %s\n", uatp_descriptor->description); 943 aprint_naive(": %s\n", uatp_descriptor->description);
947 aprint_verbose_dev(self, 944 aprint_verbose_dev(self,
948 "vendor 0x%04x, product 0x%04x, report id %d\n", 945 "vendor 0x%04x, product 0x%04x, report id %d\n",
949 (unsigned int)uha->uiaa->uiaa_vendor, 946 (unsigned int)uha->uiaa->uiaa_vendor,
950 (unsigned int)uha->uiaa->uiaa_product, 947 (unsigned int)uha->uiaa->uiaa_product,
951 (int)uha->reportid); 948 uha->reportid);
952 949
953 uhidev_get_report_desc(uha->parent, &report_descriptor, &report_size); 950 uhidev_get_report_desc(uha->parent, &report_descriptor, &report_size);
954 input_size = hid_report_size(report_descriptor, report_size, hid_input, 951 input_size = hid_report_size(report_descriptor, report_size, hid_input,
955 uha->reportid); 952 uha->reportid);
956 KASSERT(0 < input_size); 953 KASSERT(0 < input_size);
957 sc->sc_input_size = input_size; 954 sc->sc_input_size = input_size;
958 955
959 /* Initialize model-specific parameters. */ 956 /* Initialize model-specific parameters. */
960 sc->sc_parameters = uatp_descriptor->parameters; 957 sc->sc_parameters = uatp_descriptor->parameters;
961 KASSERT((int)sc->sc_parameters->input_size == input_size); 958 KASSERT((int)sc->sc_parameters->input_size == input_size);
962 KASSERT(sc->sc_parameters->x_sensors <= UATP_MAX_X_SENSORS); 959 KASSERT(sc->sc_parameters->x_sensors <= UATP_MAX_X_SENSORS);
963 KASSERT(sc->sc_parameters->x_ratio <= UATP_MAX_X_RATIO); 960 KASSERT(sc->sc_parameters->x_ratio <= UATP_MAX_X_RATIO);
964 KASSERT(sc->sc_parameters->y_sensors <= UATP_MAX_Y_SENSORS); 961 KASSERT(sc->sc_parameters->y_sensors <= UATP_MAX_Y_SENSORS);
@@ -1241,47 +1238,47 @@ uatp_enable(void *v) @@ -1241,47 +1238,47 @@ uatp_enable(void *v)
1241 1238
1242 /* Refuse to enable if we already are enabled. */ 1239 /* Refuse to enable if we already are enabled. */
1243 if (sc->sc_status & UATP_ENABLED) { 1240 if (sc->sc_status & UATP_ENABLED) {
1244 DPRINTF(sc, UATP_DEBUG_WSMOUSE, ("already enabled\n")); 1241 DPRINTF(sc, UATP_DEBUG_WSMOUSE, ("already enabled\n"));
1245 return EBUSY; 1242 return EBUSY;
1246 } 1243 }
1247 1244
1248 sc->sc_status |= UATP_ENABLED; 1245 sc->sc_status |= UATP_ENABLED;
1249 sc->sc_status &=~ UATP_VALID; 1246 sc->sc_status &=~ UATP_VALID;
1250 sc->sc_input_index = 0; 1247 sc->sc_input_index = 0;
1251 tap_enable(sc); 1248 tap_enable(sc);
1252 uatp_clear_position(sc); 1249 uatp_clear_position(sc);
1253 1250
1254 DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_open(%p)\n", &sc->sc_hdev)); 1251 DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_open(%p)\n", sc->sc_hdev));
1255 return uhidev_open(&sc->sc_hdev); 1252 return uhidev_open(sc->sc_hdev, &uatp_intr, sc);
1256} 1253}
1257 1254
1258static void 1255static void
1259uatp_disable(void *v) 1256uatp_disable(void *v)
1260{ 1257{
1261 struct uatp_softc *sc = v; 1258 struct uatp_softc *sc = v;
1262 1259
1263 DPRINTF(sc, UATP_DEBUG_WSMOUSE, ("disabling wsmouse\n")); 1260 DPRINTF(sc, UATP_DEBUG_WSMOUSE, ("disabling wsmouse\n"));
1264 1261
1265 if (!(sc->sc_status & UATP_ENABLED)) { 1262 if (!(sc->sc_status & UATP_ENABLED)) {
1266 DPRINTF(sc, UATP_DEBUG_WSMOUSE, ("not enabled\n")); 1263 DPRINTF(sc, UATP_DEBUG_WSMOUSE, ("not enabled\n"));
1267 return; 1264 return;
1268 } 1265 }
1269 1266
1270 tap_disable(sc); 1267 tap_disable(sc);
1271 sc->sc_status &=~ UATP_ENABLED; 1268 sc->sc_status &=~ UATP_ENABLED;
1272 1269
1273 DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_close(%p)\n", &sc->sc_hdev)); 1270 DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_close(%p)\n", sc->sc_hdev));
1274 uhidev_close(&sc->sc_hdev); 1271 uhidev_close(sc->sc_hdev);
1275} 1272}
1276 1273
1277static int 1274static int
1278uatp_ioctl(void *v, unsigned long cmd, void *data, int flag, struct lwp *p) 1275uatp_ioctl(void *v, unsigned long cmd, void *data, int flag, struct lwp *p)
1279{ 1276{
1280 1277
1281 DPRINTF((struct uatp_softc*)v, UATP_DEBUG_IOCTL, 1278 DPRINTF((struct uatp_softc*)v, UATP_DEBUG_IOCTL,
1282 ("cmd %lx, data %p, flag %x, lwp %p\n", cmd, data, flag, p)); 1279 ("cmd %lx, data %p, flag %x, lwp %p\n", cmd, data, flag, p));
1283 1280
1284 /* XXX Implement any relevant wsmouse(4) ioctls. */ 1281 /* XXX Implement any relevant wsmouse(4) ioctls. */
1285 return EPASSTHROUGH; 1282 return EPASSTHROUGH;
1286} 1283}
1287 1284
@@ -1389,35 +1386,35 @@ static void @@ -1389,35 +1386,35 @@ static void
1389geyser34_reset_task(void *arg) 1386geyser34_reset_task(void *arg)
1390{ 1387{
1391 struct uatp_softc *sc = arg; 1388 struct uatp_softc *sc = arg;
1392 1389
1393 DPRINTF(sc, UATP_DEBUG_RESET, ("resetting\n")); 1390 DPRINTF(sc, UATP_DEBUG_RESET, ("resetting\n"));
1394 1391
1395 /* Reset by putting it into raw mode. Not sure why. */ 1392 /* Reset by putting it into raw mode. Not sure why. */
1396 geyser34_enable_raw_mode(sc); 1393 geyser34_enable_raw_mode(sc);
1397} 1394}
1398 1395
1399/* Interrupt handler */ 1396/* Interrupt handler */
1400 1397
1401static void 1398static void
1402uatp_intr(struct uhidev *addr, void *ibuf, unsigned int len) 1399uatp_intr(void *cookie, void *ibuf, unsigned int len)
1403{ 1400{
1404 struct uatp_softc *sc = (struct uatp_softc *)addr; 1401 struct uatp_softc *sc = cookie;
1405 uint8_t *input; 1402 uint8_t *input;
1406 int dx, dy, dz, dw; 1403 int dx, dy, dz, dw;
1407 uint32_t buttons; 1404 uint32_t buttons;
1408 1405
1409 DPRINTF(sc, UATP_DEBUG_INTR, ("softc %p, ibuf %p, len %u\n", 1406 DPRINTF(sc, UATP_DEBUG_INTR, ("softc %p, ibuf %p, len %u\n",
1410 addr, ibuf, len)); 1407 sc, ibuf, len));
1411 1408
1412 /* 1409 /*
1413 * Some devices break packets up into chunks, so we accumulate 1410 * Some devices break packets up into chunks, so we accumulate
1414 * input up to the expected packet length, or if it would 1411 * input up to the expected packet length, or if it would
1415 * overflow, discard the whole packet and start over. 1412 * overflow, discard the whole packet and start over.
1416 */ 1413 */
1417 if (sc->sc_input_size < len) { 1414 if (sc->sc_input_size < len) {
1418 aprint_error_dev(uatp_dev(sc), 1415 aprint_error_dev(uatp_dev(sc),
1419 "discarding %u-byte input packet\n", len); 1416 "discarding %u-byte input packet\n", len);
1420 sc->sc_input_index = 0; 1417 sc->sc_input_index = 0;
1421 return; 1418 return;
1422 } else if (sc->sc_input_size < (sc->sc_input_index + len)) { 1419 } else if (sc->sc_input_size < (sc->sc_input_index + len)) {
1423 aprint_error_dev(uatp_dev(sc), "discarding %u-byte input\n", 1420 aprint_error_dev(uatp_dev(sc), "discarding %u-byte input\n",

cvs diff -r1.54 -r1.55 src/sys/dev/usb/ucycom.c (expand / switch to unified diff)

--- src/sys/dev/usb/ucycom.c 2022/03/28 12:43:30 1.54
+++ src/sys/dev/usb/ucycom.c 2022/03/28 12:44:17 1.55
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ucycom.c,v 1.54 2022/03/28 12:43:30 riastradh Exp $ */ 1/* $NetBSD: ucycom.c,v 1.55 2022/03/28 12:44:17 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005 The NetBSD Foundation, Inc. 4 * Copyright (c) 2005 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Nick Hudson 8 * by Nick Hudson
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -28,27 +28,27 @@ @@ -28,27 +28,27 @@
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31/* 31/*
32 * This code is based on the ucom driver. 32 * This code is based on the ucom driver.
33 */ 33 */
34 34
35/* 35/*
36 * Device driver for Cypress CY7C637xx and CY7C640/1xx series USB to 36 * Device driver for Cypress CY7C637xx and CY7C640/1xx series USB to
37 * RS232 bridges. 37 * RS232 bridges.
38 */ 38 */
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.54 2022/03/28 12:43:30 riastradh Exp $"); 41__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.55 2022/03/28 12:44:17 riastradh Exp $");
42 42
43#ifdef _KERNEL_OPT 43#ifdef _KERNEL_OPT
44#include "opt_usb.h" 44#include "opt_usb.h"
45#endif 45#endif
46 46
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/systm.h> 48#include <sys/systm.h>
49#include <sys/conf.h> 49#include <sys/conf.h>
50#include <sys/kernel.h> 50#include <sys/kernel.h>
51#include <sys/kmem.h> 51#include <sys/kmem.h>
52#include <sys/device.h> 52#include <sys/device.h>
53#include <sys/sysctl.h> 53#include <sys/sysctl.h>
54#include <sys/tty.h> 54#include <sys/tty.h>
@@ -107,27 +107,28 @@ int ucycomdebug = 20; @@ -107,27 +107,28 @@ int ucycomdebug = 20;
107#define UCYCOM_RI 0x80 107#define UCYCOM_RI 0x80
108#define UCYCOM_DCD 0x40 108#define UCYCOM_DCD 0x40
109#define UCYCOM_DSR 0x20 109#define UCYCOM_DSR 0x20
110#define UCYCOM_CTS 0x10 110#define UCYCOM_CTS 0x10
111#define UCYCOM_ERROR 0x08 111#define UCYCOM_ERROR 0x08
112#define UCYCOM_LMASK 0x07 112#define UCYCOM_LMASK 0x07
113 113
114/* Modem (Output) control byte */ 114/* Modem (Output) control byte */
115#define UCYCOM_DTR 0x20 115#define UCYCOM_DTR 0x20
116#define UCYCOM_RTS 0x10 116#define UCYCOM_RTS 0x10
117#define UCYCOM_ORESET 0x08 117#define UCYCOM_ORESET 0x08
118 118
119struct ucycom_softc { 119struct ucycom_softc {
120 struct uhidev sc_hdev; 120 device_t sc_dev;
 121 struct uhidev *sc_hdev;
121 struct usbd_device *sc_udev; 122 struct usbd_device *sc_udev;
122 123
123 struct usb_task sc_task; 124 struct usb_task sc_task;
124 struct tty *sc_tty; 125 struct tty *sc_tty;
125 126
126 enum { 127 enum {
127 UCYCOM_INIT_NONE, 128 UCYCOM_INIT_NONE,
128 UCYCOM_INIT_INITED 129 UCYCOM_INIT_INITED
129 } sc_init_state; 130 } sc_init_state;
130 131
131 kmutex_t sc_lock; /* protects refcnt, others */ 132 kmutex_t sc_lock; /* protects refcnt, others */
132 133
133 /* uhidev parameters */ 134 /* uhidev parameters */
@@ -166,27 +167,27 @@ const struct cdevsw ucycom_cdevsw = { @@ -166,27 +167,27 @@ const struct cdevsw ucycom_cdevsw = {
166 .d_stop = ucycomstop, 167 .d_stop = ucycomstop,
167 .d_tty = ucycomtty, 168 .d_tty = ucycomtty,
168 .d_poll = ucycompoll, 169 .d_poll = ucycompoll,
169 .d_mmap = nommap, 170 .d_mmap = nommap,
170 .d_kqfilter = ttykqfilter, 171 .d_kqfilter = ttykqfilter,
171 .d_discard = nodiscard, 172 .d_discard = nodiscard,
172 .d_flag = D_TTY 173 .d_flag = D_TTY
173}; 174};
174 175
175Static int ucycomparam(struct tty *, struct termios *); 176Static int ucycomparam(struct tty *, struct termios *);
176Static void ucycomstart(struct tty *); 177Static void ucycomstart(struct tty *);
177Static void ucycomstarttask(void *); 178Static void ucycomstarttask(void *);
178Static void ucycomwritecb(struct usbd_xfer *, void *, usbd_status); 179Static void ucycomwritecb(struct usbd_xfer *, void *, usbd_status);
179Static void ucycom_intr(struct uhidev *, void *, u_int); 180Static void ucycom_intr(void *, void *, u_int);
180Static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t); 181Static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t);
181Static void tiocm_to_ucycom(struct ucycom_softc *, u_long, int); 182Static void tiocm_to_ucycom(struct ucycom_softc *, u_long, int);
182Static int ucycom_to_tiocm(struct ucycom_softc *); 183Static int ucycom_to_tiocm(struct ucycom_softc *);
183Static void ucycom_set_status(struct ucycom_softc *); 184Static void ucycom_set_status(struct ucycom_softc *);
184Static void ucycom_dtr(struct ucycom_softc *, int); 185Static void ucycom_dtr(struct ucycom_softc *, int);
185#if 0 186#if 0
186Static void ucycom_rts(struct ucycom_softc *, int); 187Static void ucycom_rts(struct ucycom_softc *, int);
187#endif 188#endif
188Static void ucycom_cleanup(struct ucycom_softc *); 189Static void ucycom_cleanup(struct ucycom_softc *);
189 190
190#ifdef UCYCOM_DEBUG 191#ifdef UCYCOM_DEBUG
191Static void ucycom_get_cfg(struct ucycom_softc *); 192Static void ucycom_get_cfg(struct ucycom_softc *);
192#endif 193#endif
@@ -212,30 +213,28 @@ ucycom_match(device_t parent, cfdata_t m @@ -212,30 +213,28 @@ ucycom_match(device_t parent, cfdata_t m
212 213
213 return ucycom_lookup(uha->uiaa->uiaa_vendor, uha->uiaa->uiaa_product) 214 return ucycom_lookup(uha->uiaa->uiaa_vendor, uha->uiaa->uiaa_product)
214 != NULL ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 215 != NULL ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
215} 216}
216 217
217static void 218static void
218ucycom_attach(device_t parent, device_t self, void *aux) 219ucycom_attach(device_t parent, device_t self, void *aux)
219{ 220{
220 struct ucycom_softc *sc = device_private(self); 221 struct ucycom_softc *sc = device_private(self);
221 struct uhidev_attach_arg *uha = aux; 222 struct uhidev_attach_arg *uha = aux;
222 int size, repid; 223 int size, repid;
223 void *desc; 224 void *desc;
224 225
225 sc->sc_hdev.sc_dev = self; 226 sc->sc_dev = self;
226 sc->sc_hdev.sc_intr = ucycom_intr; 227 sc->sc_hdev = uha->parent;
227 sc->sc_hdev.sc_parent = uha->parent; 
228 sc->sc_hdev.sc_report_id = uha->reportid; 
229 sc->sc_udev = uha->uiaa->uiaa_device; 228 sc->sc_udev = uha->uiaa->uiaa_device;
230 sc->sc_init_state = UCYCOM_INIT_NONE; 229 sc->sc_init_state = UCYCOM_INIT_NONE;
231 230
232 uhidev_get_report_desc(uha->parent, &desc, &size); 231 uhidev_get_report_desc(uha->parent, &desc, &size);
233 repid = uha->reportid; 232 repid = uha->reportid;
234 sc->sc_olen = hid_report_size(desc, size, hid_output, repid); 233 sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
235 sc->sc_flen = hid_report_size(desc, size, hid_feature, repid); 234 sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);
236 235
237 if (sc->sc_olen != 8 && sc->sc_olen != 32) 236 if (sc->sc_olen != 8 && sc->sc_olen != 32)
238 return; 237 return;
239 if (sc->sc_flen != 5) 238 if (sc->sc_flen != 5)
240 return; 239 return;
241 240
@@ -270,27 +269,27 @@ ucycom_detach(device_t self, int flags) @@ -270,27 +269,27 @@ ucycom_detach(device_t self, int flags)
270 DPRINTF(("ucycom_detach: sc=%p flags=%d tp=%p\n", sc, flags, tp)); 269 DPRINTF(("ucycom_detach: sc=%p flags=%d tp=%p\n", sc, flags, tp));
271 270
272 sc->sc_dying = 1; 271 sc->sc_dying = 1;
273 272
274 s = splusb(); 273 s = splusb();
275 if (tp != NULL) { 274 if (tp != NULL) {
276 mutex_spin_enter(&tty_lock); 275 mutex_spin_enter(&tty_lock);
277 CLR(tp->t_state, TS_CARR_ON); 276 CLR(tp->t_state, TS_CARR_ON);
278 CLR(tp->t_cflag, CLOCAL | MDMBUF); 277 CLR(tp->t_cflag, CLOCAL | MDMBUF);
279 ttyflush(tp, FREAD|FWRITE); 278 ttyflush(tp, FREAD|FWRITE);
280 mutex_spin_exit(&tty_lock); 279 mutex_spin_exit(&tty_lock);
281 } 280 }
282 /* Wait for processes to go away. */ 281 /* Wait for processes to go away. */
283 usb_detach_waitold(sc->sc_hdev.sc_dev); 282 usb_detach_waitold(sc->sc_dev);
284 splx(s); 283 splx(s);
285 284
286 /* locate the major number */ 285 /* locate the major number */
287 maj = cdevsw_lookup_major(&ucycom_cdevsw); 286 maj = cdevsw_lookup_major(&ucycom_cdevsw);
288 287
289 /* Nuke the vnodes for any open instances. */ 288 /* Nuke the vnodes for any open instances. */
290 mn = device_unit(self); 289 mn = device_unit(self);
291 290
292 DPRINTFN(2, ("ucycom_detach: maj=%d mn=%d\n", maj, mn)); 291 DPRINTFN(2, ("ucycom_detach: maj=%d mn=%d\n", maj, mn));
293 vdevgone(maj, mn, mn, VCHR); 292 vdevgone(maj, mn, mn, VCHR);
294 vdevgone(maj, mn | UCYCOMDIALOUT_MASK, mn | UCYCOMDIALOUT_MASK, VCHR); 293 vdevgone(maj, mn | UCYCOMDIALOUT_MASK, mn | UCYCOMDIALOUT_MASK, VCHR);
295 vdevgone(maj, mn | UCYCOMCALLUNIT_MASK, mn | UCYCOMCALLUNIT_MASK, VCHR); 294 vdevgone(maj, mn | UCYCOMCALLUNIT_MASK, mn | UCYCOMCALLUNIT_MASK, VCHR);
296 295
@@ -348,44 +347,44 @@ ucycomopen(dev_t dev, int flag, int mode @@ -348,44 +347,44 @@ ucycomopen(dev_t dev, int flag, int mode
348 device_lookup_private(&ucycom_cd, UCYCOMUNIT(dev)); 347 device_lookup_private(&ucycom_cd, UCYCOMUNIT(dev));
349 struct tty *tp; 348 struct tty *tp;
350 int s, err; 349 int s, err;
351 350
352 DPRINTF(("ucycomopen: unit=%d\n", UCYCOMUNIT(dev))); 351 DPRINTF(("ucycomopen: unit=%d\n", UCYCOMUNIT(dev)));
353 DPRINTF(("ucycomopen: sc=%p\n", sc)); 352 DPRINTF(("ucycomopen: sc=%p\n", sc));
354 353
355 if (sc == NULL) 354 if (sc == NULL)
356 return ENXIO; 355 return ENXIO;
357 if (sc->sc_dying) 356 if (sc->sc_dying)
358 return EIO; 357 return EIO;
359 if (sc->sc_init_state != UCYCOM_INIT_INITED) 358 if (sc->sc_init_state != UCYCOM_INIT_INITED)
360 return ENXIO; 359 return ENXIO;
361 if (!device_is_active(sc->sc_hdev.sc_dev)) 360 if (!device_is_active(sc->sc_dev))
362 return ENXIO; 361 return ENXIO;
363 362
364 tp = sc->sc_tty; 363 tp = sc->sc_tty;
365 364
366 DPRINTF(("ucycomopen: tp=%p\n", tp)); 365 DPRINTF(("ucycomopen: tp=%p\n", tp));
367 366
368 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 367 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
369 return EBUSY; 368 return EBUSY;
370 369
371 s = spltty(); 370 s = spltty();
372 371
373 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 372 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
374 struct termios t; 373 struct termios t;
375 374
376 tp->t_dev = dev; 375 tp->t_dev = dev;
377 376
378 err = uhidev_open(&sc->sc_hdev); 377 err = uhidev_open(sc->sc_hdev, &ucycom_intr, sc);
379 if (err) { 378 if (err) {
380 /* Any cleanup? */ 379 /* Any cleanup? */
381 splx(s); 380 splx(s);
382 return err; 381 return err;
383 } 382 }
384 383
385 /* 384 /*
386 * Initialize the termios status to the defaults. Add in the 385 * Initialize the termios status to the defaults. Add in the
387 * sticky bits from TIOCSFLAGS. 386 * sticky bits from TIOCSFLAGS.
388 */ 387 */
389 t.c_ispeed = 0; 388 t.c_ispeed = 0;
390 t.c_ospeed = TTYDEF_SPEED; 389 t.c_ospeed = TTYDEF_SPEED;
391 t.c_cflag = TTYDEF_CFLAG; 390 t.c_cflag = TTYDEF_CFLAG;
@@ -607,27 +606,27 @@ ucycomstart(struct tty *tp) @@ -607,27 +606,27 @@ ucycomstart(struct tty *tp)
607 return; 606 return;
608 607
609out: 608out:
610 splx(s); 609 splx(s);
611} 610}
612 611
613Static void 612Static void
614ucycomstarttask(void *cookie) 613ucycomstarttask(void *cookie)
615{ 614{
616 struct ucycom_softc *sc = cookie; 615 struct ucycom_softc *sc = cookie;
617 usbd_status err; 616 usbd_status err;
618 617
619 /* What can we do on error? */ 618 /* What can we do on error? */
620 err = uhidev_write_async(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen, 0, 619 err = uhidev_write_async(sc->sc_hdev, sc->sc_obuf, sc->sc_olen, 0,
621 USBD_NO_TIMEOUT, ucycomwritecb, sc); 620 USBD_NO_TIMEOUT, ucycomwritecb, sc);
622 621
623#ifdef UCYCOM_DEBUG 622#ifdef UCYCOM_DEBUG
624 if (err != USBD_IN_PROGRESS) 623 if (err != USBD_IN_PROGRESS)
625 DPRINTF(("ucycomstart: err=%s\n", usbd_errstr(err))); 624 DPRINTF(("ucycomstart: err=%s\n", usbd_errstr(err)));
626#else 625#else
627 __USE(err); 626 __USE(err);
628#endif 627#endif
629} 628}
630 629
631Static void 630Static void
632ucycomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status) 631ucycomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status)
633{ 632{
@@ -932,46 +931,46 @@ ucycom_configure(struct ucycom_softc *sc @@ -932,46 +931,46 @@ ucycom_configure(struct ucycom_softc *sc
932 } 931 }
933 932
934 DPRINTF(("ucycom_configure: setting %d baud, %d-%c-%d (%d)\n", baud, 933 DPRINTF(("ucycom_configure: setting %d baud, %d-%c-%d (%d)\n", baud,
935 5 + (cfg & UCYCOM_DATA_MASK), 934 5 + (cfg & UCYCOM_DATA_MASK),
936 (cfg & UCYCOM_PARITY_MASK) ? 935 (cfg & UCYCOM_PARITY_MASK) ?
937 ((cfg & UCYCOM_PARITY_TYPE_MASK) ? 'O' : 'E') : 'N', 936 ((cfg & UCYCOM_PARITY_TYPE_MASK) ? 'O' : 'E') : 'N',
938 (cfg & UCYCOM_STOP_MASK) ? 2 : 1, cfg)); 937 (cfg & UCYCOM_STOP_MASK) ? 2 : 1, cfg));
939 938
940 report[0] = baud & 0xff; 939 report[0] = baud & 0xff;
941 report[1] = (baud >> 8) & 0xff; 940 report[1] = (baud >> 8) & 0xff;
942 report[2] = (baud >> 16) & 0xff; 941 report[2] = (baud >> 16) & 0xff;
943 report[3] = (baud >> 24) & 0xff; 942 report[3] = (baud >> 24) & 0xff;
944 report[4] = cfg; 943 report[4] = cfg;
945 err = uhidev_set_report(&sc->sc_hdev, UHID_FEATURE_REPORT, 944 err = uhidev_set_report(sc->sc_hdev, UHID_FEATURE_REPORT,
946 report, sc->sc_flen); 945 report, sc->sc_flen);
947 if (err != 0) { 946 if (err != 0) {
948 DPRINTF(("%s\n", usbd_errstr(err))); 947 DPRINTF(("%s\n", usbd_errstr(err)));
949 return EIO; 948 return EIO;
950 } 949 }
951 sc->sc_baud = baud; 950 sc->sc_baud = baud;
952 sc->sc_cfg = cfg; 951 sc->sc_cfg = cfg;
953 952
954#ifdef UCYCOM_DEBUG 953#ifdef UCYCOM_DEBUG
955 ucycom_get_cfg(sc); 954 ucycom_get_cfg(sc);
956#endif 955#endif
957 956
958 return 0; 957 return 0;
959} 958}
960 959
961Static void 960Static void
962ucycom_intr(struct uhidev *addr, void *ibuf, u_int len) 961ucycom_intr(void *cookie, void *ibuf, u_int len)
963{ 962{
964 struct ucycom_softc *sc = (struct ucycom_softc *)addr; 963 struct ucycom_softc *sc = cookie;
965 struct tty *tp = sc->sc_tty; 964 struct tty *tp = sc->sc_tty;
966 int (*rint)(int , struct tty *) = tp->t_linesw->l_rint; 965 int (*rint)(int , struct tty *) = tp->t_linesw->l_rint;
967 uint8_t *cp = ibuf; 966 uint8_t *cp = ibuf;
968 int s, n, st, chg; 967 int s, n, st, chg;
969 968
970 /* We understand 8 byte and 32 byte input records */ 969 /* We understand 8 byte and 32 byte input records */
971 switch (len) { 970 switch (len) {
972 case 8: 971 case 8:
973 n = cp[0] & UCYCOM_LMASK; 972 n = cp[0] & UCYCOM_LMASK;
974 st = cp[0] & ~UCYCOM_LMASK; 973 st = cp[0] & ~UCYCOM_LMASK;
975 cp++; 974 cp++;
976 break; 975 break;
977 976
@@ -995,28 +994,27 @@ ucycom_intr(struct uhidev *addr, void *i @@ -995,28 +994,27 @@ ucycom_intr(struct uhidev *addr, void *i
995 for (i = 0; i < n; i++) 994 for (i = 0; i < n; i++)
996 DPRINTF((" %02x", cp[i])); 995 DPRINTF((" %02x", cp[i]));
997 DPRINTF(("\n")); 996 DPRINTF(("\n"));
998 } 997 }
999 } 998 }
1000#endif 999#endif
1001 1000
1002 /* Give characters to tty layer. */ 1001 /* Give characters to tty layer. */
1003 s = spltty(); 1002 s = spltty();
1004 while (n-- > 0) { 1003 while (n-- > 0) {
1005 DPRINTFN(7,("ucycom_intr: char=0x%02x\n", *cp)); 1004 DPRINTFN(7,("ucycom_intr: char=0x%02x\n", *cp));
1006 if ((*rint)(*cp++, tp) == -1) { 1005 if ((*rint)(*cp++, tp) == -1) {
1007 /* XXX what should we do? */ 1006 /* XXX what should we do? */
1008 aprint_error_dev(sc->sc_hdev.sc_dev, 1007 aprint_error_dev(sc->sc_dev, "lost a character\n");
1009 "lost a character\n"); 
1010 break; 1008 break;
1011 } 1009 }
1012 } 1010 }
1013 splx(s); 1011 splx(s);
1014 chg = st ^ sc->sc_msr; 1012 chg = st ^ sc->sc_msr;
1015 sc->sc_msr = st; 1013 sc->sc_msr = st;
1016 if (ISSET(chg, UCYCOM_DCD)) 1014 if (ISSET(chg, UCYCOM_DCD))
1017 (*tp->t_linesw->l_modem)(tp, 1015 (*tp->t_linesw->l_modem)(tp,
1018 ISSET(sc->sc_msr, UCYCOM_DCD)); 1016 ISSET(sc->sc_msr, UCYCOM_DCD));
1019 1017
1020} 1018}
1021 1019
1022Static void 1020Static void
@@ -1114,57 +1112,57 @@ ucycom_set_status(struct ucycom_softc *s @@ -1114,57 +1112,57 @@ ucycom_set_status(struct ucycom_softc *s
1114 int err; 1112 int err;
1115 1113
1116 if (sc->sc_olen != 8 && sc->sc_olen != 32) { 1114 if (sc->sc_olen != 8 && sc->sc_olen != 32) {
1117 DPRINTFN(2,("ucycom_set_status: unknown output report " 1115 DPRINTFN(2,("ucycom_set_status: unknown output report "
1118 "size (%zd)\n", sc->sc_olen)); 1116 "size (%zd)\n", sc->sc_olen));
1119 return; 1117 return;
1120 } 1118 }
1121 1119
1122 DPRINTF(("ucycom_set_status: %d\n", sc->sc_mcr)); 1120 DPRINTF(("ucycom_set_status: %d\n", sc->sc_mcr));
1123 1121
1124 memset(sc->sc_obuf, 0, sc->sc_olen); 1122 memset(sc->sc_obuf, 0, sc->sc_olen);
1125 sc->sc_obuf[0] = sc->sc_mcr; 1123 sc->sc_obuf[0] = sc->sc_mcr;
1126 1124
1127 err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen); 1125 err = uhidev_write(sc->sc_hdev, sc->sc_obuf, sc->sc_olen);
1128 if (err) { 1126 if (err) {
1129 DPRINTF(("ucycom_set_status: err=%d\n", err)); 1127 DPRINTF(("ucycom_set_status: err=%d\n", err));
1130 } 1128 }
1131} 1129}
1132 1130
1133#ifdef UCYCOM_DEBUG 1131#ifdef UCYCOM_DEBUG
1134Static void 1132Static void
1135ucycom_get_cfg(struct ucycom_softc *sc) 1133ucycom_get_cfg(struct ucycom_softc *sc)
1136{ 1134{
1137 int err, cfg, baud; 1135 int err, cfg, baud;
1138 uint8_t report[5]; 1136 uint8_t report[5];
1139 1137
1140 err = uhidev_get_report(&sc->sc_hdev, UHID_FEATURE_REPORT, 1138 err = uhidev_get_report(sc->sc_hdev, UHID_FEATURE_REPORT,
1141 report, sc->sc_flen); 1139 report, sc->sc_flen);
1142 if (err) { 1140 if (err) {
1143 DPRINTF(("%s: failed\n", __func__)); 1141 DPRINTF(("%s: failed\n", __func__));
1144 return; 1142 return;
1145 } 1143 }
1146 cfg = report[4]; 1144 cfg = report[4];
1147 baud = (report[3] << 24) + (report[2] << 16) + (report[1] << 8) + 1145 baud = (report[3] << 24) + (report[2] << 16) + (report[1] << 8) +
1148 report[0]; 1146 report[0];
1149 DPRINTF(("ucycom_get_cfg: device reports %d baud, %d-%c-%d (%d)\n", 1147 DPRINTF(("ucycom_get_cfg: device reports %d baud, %d-%c-%d (%d)\n",
1150 baud, 5 + (cfg & UCYCOM_DATA_MASK), 1148 baud, 5 + (cfg & UCYCOM_DATA_MASK),
1151 (cfg & UCYCOM_PARITY_MASK) ? 1149 (cfg & UCYCOM_PARITY_MASK) ?
1152 ((cfg & UCYCOM_PARITY_TYPE_MASK) ? 'O' : 'E') : 'N', 1150 ((cfg & UCYCOM_PARITY_TYPE_MASK) ? 'O' : 'E') : 'N',
1153 (cfg & UCYCOM_STOP_MASK) ? 2 : 1, cfg)); 1151 (cfg & UCYCOM_STOP_MASK) ? 2 : 1, cfg));
1154} 1152}
1155#endif 1153#endif
1156 1154
1157Static void 1155Static void
1158ucycom_cleanup(struct ucycom_softc *sc) 1156ucycom_cleanup(struct ucycom_softc *sc)
1159{ 1157{
1160 uint8_t *obuf; 1158 uint8_t *obuf;
1161 1159
1162 DPRINTF(("ucycom_cleanup: closing uhidev\n")); 1160 DPRINTF(("ucycom_cleanup: closing uhidev\n"));
1163 1161
1164 obuf = sc->sc_obuf; 1162 obuf = sc->sc_obuf;
1165 sc->sc_obuf = NULL; 1163 sc->sc_obuf = NULL;
1166 uhidev_close(&sc->sc_hdev); 1164 uhidev_close(sc->sc_hdev);
1167 1165
1168 if (obuf != NULL) 1166 if (obuf != NULL)
1169 kmem_free(obuf, sc->sc_olen); 1167 kmem_free(obuf, sc->sc_olen);
1170} 1168}

cvs diff -r1.122 -r1.123 src/sys/dev/usb/uhid.c (expand / switch to unified diff)

--- src/sys/dev/usb/uhid.c 2022/03/28 12:43:12 1.122
+++ src/sys/dev/usb/uhid.c 2022/03/28 12:44:17 1.123
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uhid.c,v 1.122 2022/03/28 12:43:12 riastradh Exp $ */ 1/* $NetBSD: uhid.c,v 1.123 2022/03/28 12:44:17 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc. 4 * Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net) at 8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au). 9 * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au).
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.122 2022/03/28 12:43:12 riastradh Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.123 2022/03/28 12:44:17 riastradh Exp $");
39 39
40#ifdef _KERNEL_OPT 40#ifdef _KERNEL_OPT
41#include "opt_compat_netbsd.h" 41#include "opt_compat_netbsd.h"
42#include "opt_usb.h" 42#include "opt_usb.h"
43#endif 43#endif
44 44
45#include <sys/param.h> 45#include <sys/param.h>
46#include <sys/types.h> 46#include <sys/types.h>
47 47
48#include <sys/atomic.h> 48#include <sys/atomic.h>
49#include <sys/compat_stub.h> 49#include <sys/compat_stub.h>
50#include <sys/conf.h> 50#include <sys/conf.h>
51#include <sys/device.h> 51#include <sys/device.h>
@@ -75,28 +75,30 @@ __KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.1 @@ -75,28 +75,30 @@ __KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.1
75 75
76#include "ioconf.h" 76#include "ioconf.h"
77 77
78#ifdef UHID_DEBUG 78#ifdef UHID_DEBUG
79#define DPRINTF(x) if (uhiddebug) printf x 79#define DPRINTF(x) if (uhiddebug) printf x
80#define DPRINTFN(n,x) if (uhiddebug>(n)) printf x 80#define DPRINTFN(n,x) if (uhiddebug>(n)) printf x
81int uhiddebug = 0; 81int uhiddebug = 0;
82#else 82#else
83#define DPRINTF(x) 83#define DPRINTF(x)
84#define DPRINTFN(n,x) 84#define DPRINTFN(n,x)
85#endif 85#endif
86 86
87struct uhid_softc { 87struct uhid_softc {
88 struct uhidev sc_hdev; 88 device_t sc_dev;
 89 struct uhidev *sc_hdev;
89 struct usbd_device *sc_udev; 90 struct usbd_device *sc_udev;
 91 uint8_t sc_report_id;
90 92
91 kmutex_t sc_lock; 93 kmutex_t sc_lock;
92 kcondvar_t sc_cv; 94 kcondvar_t sc_cv;
93 95
94 int sc_isize; 96 int sc_isize;
95 int sc_osize; 97 int sc_osize;
96 int sc_fsize; 98 int sc_fsize;
97 99
98 u_char *sc_obuf; 100 u_char *sc_obuf;
99 101
100 struct clist sc_q; /* protected by sc_lock */ 102 struct clist sc_q; /* protected by sc_lock */
101 struct selinfo sc_rsel; 103 struct selinfo sc_rsel;
102 proc_t *sc_async; /* process that wants SIGIO */ 104 proc_t *sc_async; /* process that wants SIGIO */
@@ -134,27 +136,27 @@ const struct cdevsw uhid_cdevsw = { @@ -134,27 +136,27 @@ const struct cdevsw uhid_cdevsw = {
134 .d_write = uhidwrite, 136 .d_write = uhidwrite,
135 .d_ioctl = uhidioctl, 137 .d_ioctl = uhidioctl,
136 .d_stop = nostop, 138 .d_stop = nostop,
137 .d_tty = notty, 139 .d_tty = notty,
138 .d_poll = uhidpoll, 140 .d_poll = uhidpoll,
139 .d_mmap = nommap, 141 .d_mmap = nommap,
140 .d_kqfilter = uhidkqfilter, 142 .d_kqfilter = uhidkqfilter,
141 .d_discard = nodiscard, 143 .d_discard = nodiscard,
142 .d_cfdriver = &uhid_cd, 144 .d_cfdriver = &uhid_cd,
143 .d_devtounit = dev_minor_unit, 145 .d_devtounit = dev_minor_unit,
144 .d_flag = D_OTHER 146 .d_flag = D_OTHER
145}; 147};
146 148
147static void uhid_intr(struct uhidev *, void *, u_int); 149static void uhid_intr(void *, void *, u_int);
148 150
149static int uhid_match(device_t, cfdata_t, void *); 151static int uhid_match(device_t, cfdata_t, void *);
150static void uhid_attach(device_t, device_t, void *); 152static void uhid_attach(device_t, device_t, void *);
151static int uhid_detach(device_t, int); 153static int uhid_detach(device_t, int);
152 154
153CFATTACH_DECL_NEW(uhid, sizeof(struct uhid_softc), uhid_match, uhid_attach, 155CFATTACH_DECL_NEW(uhid, sizeof(struct uhid_softc), uhid_match, uhid_attach,
154 uhid_detach, NULL); 156 uhid_detach, NULL);
155 157
156static int 158static int
157uhid_match(device_t parent, cfdata_t match, void *aux) 159uhid_match(device_t parent, cfdata_t match, void *aux)
158{ 160{
159#ifdef UHID_DEBUG 161#ifdef UHID_DEBUG
160 struct uhidev_attach_arg *uha = aux; 162 struct uhidev_attach_arg *uha = aux;
@@ -166,33 +168,32 @@ uhid_match(device_t parent, cfdata_t mat @@ -166,33 +168,32 @@ uhid_match(device_t parent, cfdata_t mat
166 return UMATCH_HIGHEST; 168 return UMATCH_HIGHEST;
167 else 169 else
168 return UMATCH_IFACECLASS_GENERIC; 170 return UMATCH_IFACECLASS_GENERIC;
169} 171}
170 172
171static void 173static void
172uhid_attach(device_t parent, device_t self, void *aux) 174uhid_attach(device_t parent, device_t self, void *aux)
173{ 175{
174 struct uhid_softc *sc = device_private(self); 176 struct uhid_softc *sc = device_private(self);
175 struct uhidev_attach_arg *uha = aux; 177 struct uhidev_attach_arg *uha = aux;
176 int size, repid; 178 int size, repid;
177 void *desc; 179 void *desc;
178 180
179 sc->sc_hdev.sc_dev = self; 181 sc->sc_dev = self;
180 selinit(&sc->sc_rsel); 182 sc->sc_hdev = uha->parent;
181 sc->sc_hdev.sc_intr = uhid_intr; 
182 sc->sc_hdev.sc_parent = uha->parent; 
183 sc->sc_hdev.sc_report_id = uha->reportid; 
184 
185 sc->sc_udev = uha->uiaa->uiaa_device; 183 sc->sc_udev = uha->uiaa->uiaa_device;
 184 sc->sc_report_id = uha->reportid;
 185
 186 selinit(&sc->sc_rsel);
186 187
187 uhidev_get_report_desc(uha->parent, &desc, &size); 188 uhidev_get_report_desc(uha->parent, &desc, &size);
188 repid = uha->reportid; 189 repid = uha->reportid;
189 sc->sc_isize = hid_report_size(desc, size, hid_input, repid); 190 sc->sc_isize = hid_report_size(desc, size, hid_input, repid);
190 sc->sc_osize = hid_report_size(desc, size, hid_output, repid); 191 sc->sc_osize = hid_report_size(desc, size, hid_output, repid);
191 sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid); 192 sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid);
192 sc->sc_raw = hid_is_collection(desc, size, uha->reportid, 193 sc->sc_raw = hid_is_collection(desc, size, uha->reportid,
193 HID_USAGE2(HUP_FIDO, HUF_U2FHID)); 194 HID_USAGE2(HUP_FIDO, HUF_U2FHID));
194 195
195 aprint_naive("\n"); 196 aprint_naive("\n");
196 aprint_normal(": input=%d, output=%d, feature=%d\n", 197 aprint_normal(": input=%d, output=%d, feature=%d\n",
197 sc->sc_isize, sc->sc_osize, sc->sc_fsize); 198 sc->sc_isize, sc->sc_osize, sc->sc_fsize);
198 199
@@ -222,29 +223,29 @@ uhid_detach(device_t self, int flags) @@ -222,29 +223,29 @@ uhid_detach(device_t self, int flags)
222 mn = device_unit(self); 223 mn = device_unit(self);
223 vdevgone(maj, mn, mn, VCHR); 224 vdevgone(maj, mn, mn, VCHR);
224 225
225 KASSERTMSG(sc->sc_open == UHID_CLOSED, "open=%d", (int)sc->sc_open); 226 KASSERTMSG(sc->sc_open == UHID_CLOSED, "open=%d", (int)sc->sc_open);
226 227
227 cv_destroy(&sc->sc_cv); 228 cv_destroy(&sc->sc_cv);
228 mutex_destroy(&sc->sc_lock); 229 mutex_destroy(&sc->sc_lock);
229 seldestroy(&sc->sc_rsel); 230 seldestroy(&sc->sc_rsel);
230 231
231 return 0; 232 return 0;
232} 233}
233 234
234static void 235static void
235uhid_intr(struct uhidev *addr, void *data, u_int len) 236uhid_intr(void *cookie, void *data, u_int len)
236{ 237{
237 struct uhid_softc *sc = (struct uhid_softc *)addr; 238 struct uhid_softc *sc = cookie;
238 239
239#ifdef UHID_DEBUG 240#ifdef UHID_DEBUG
240 if (uhiddebug > 5) { 241 if (uhiddebug > 5) {
241 uint32_t i; 242 uint32_t i;
242 243
243 DPRINTF(("uhid_intr: data =")); 244 DPRINTF(("uhid_intr: data ="));
244 for (i = 0; i < len; i++) 245 for (i = 0; i < len; i++)
245 DPRINTF((" %02x", ((u_char *)data)[i])); 246 DPRINTF((" %02x", ((u_char *)data)[i]));
246 DPRINTF(("\n")); 247 DPRINTF(("\n"));
247 } 248 }
248#endif 249#endif
249 250
250 mutex_enter(&sc->sc_lock); 251 mutex_enter(&sc->sc_lock);
@@ -296,27 +297,27 @@ uhidopen(dev_t dev, int flag, int mode,  @@ -296,27 +297,27 @@ uhidopen(dev_t dev, int flag, int mode,
296 297
297 /* Allocate an output buffer if needed. */ 298 /* Allocate an output buffer if needed. */
298 if (sc->sc_osize > 0) 299 if (sc->sc_osize > 0)
299 sc->sc_obuf = kmem_alloc(sc->sc_osize, KM_SLEEP); 300 sc->sc_obuf = kmem_alloc(sc->sc_osize, KM_SLEEP);
300 else 301 else
301 sc->sc_obuf = NULL; 302 sc->sc_obuf = NULL;
302 303
303 /* Paranoia: reset SIGIO before enabling interrputs. */ 304 /* Paranoia: reset SIGIO before enabling interrputs. */
304 mutex_enter(&proc_lock); 305 mutex_enter(&proc_lock);
305 atomic_store_relaxed(&sc->sc_async, NULL); 306 atomic_store_relaxed(&sc->sc_async, NULL);
306 mutex_exit(&proc_lock); 307 mutex_exit(&proc_lock);
307 308
308 /* Open the uhidev -- after this point we can get interrupts. */ 309 /* Open the uhidev -- after this point we can get interrupts. */
309 error = uhidev_open(&sc->sc_hdev); 310 error = uhidev_open(sc->sc_hdev, &uhid_intr, sc);
310 if (error) 311 if (error)
311 goto fail1; 312 goto fail1;
312 313
313 /* We are open for business. */ 314 /* We are open for business. */
314 mutex_enter(&sc->sc_lock); 315 mutex_enter(&sc->sc_lock);
315 sc->sc_open = UHID_OPEN; 316 sc->sc_open = UHID_OPEN;
316 cv_broadcast(&sc->sc_cv); 317 cv_broadcast(&sc->sc_cv);
317 mutex_exit(&sc->sc_lock); 318 mutex_exit(&sc->sc_lock);
318 319
319 return 0; 320 return 0;
320 321
321fail1: selnotify(&sc->sc_rsel, POLLHUP, 0); 322fail1: selnotify(&sc->sc_rsel, POLLHUP, 0);
322 mutex_enter(&proc_lock); 323 mutex_enter(&proc_lock);
@@ -344,52 +345,52 @@ uhidcancel(dev_t dev, int flag, int mode @@ -344,52 +345,52 @@ uhidcancel(dev_t dev, int flag, int mode
344 DPRINTF(("uhidcancel: sc=%p\n", sc)); 345 DPRINTF(("uhidcancel: sc=%p\n", sc));
345 if (sc == NULL) 346 if (sc == NULL)
346 return 0; 347 return 0;
347 348
348 /* 349 /*
349 * Mark it closing, wake any waiters, and suspend output. 350 * Mark it closing, wake any waiters, and suspend output.
350 * After this point, no new xfers can be submitted. 351 * After this point, no new xfers can be submitted.
351 */ 352 */
352 mutex_enter(&sc->sc_lock); 353 mutex_enter(&sc->sc_lock);
353 sc->sc_closing = true; 354 sc->sc_closing = true;
354 cv_broadcast(&sc->sc_cv); 355 cv_broadcast(&sc->sc_cv);
355 mutex_exit(&sc->sc_lock); 356 mutex_exit(&sc->sc_lock);
356 357
357 uhidev_stop(&sc->sc_hdev); 358 uhidev_stop(sc->sc_hdev);
358 359
359 return 0; 360 return 0;
360} 361}
361 362
362static int 363static int
363uhidclose(dev_t dev, int flag, int mode, struct lwp *l) 364uhidclose(dev_t dev, int flag, int mode, struct lwp *l)
364{ 365{
365 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 366 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
366 367
367 DPRINTF(("uhidclose: sc=%p\n", sc)); 368 DPRINTF(("uhidclose: sc=%p\n", sc));
368 if (sc == NULL) 369 if (sc == NULL)
369 return 0; 370 return 0;
370 371
371 mutex_enter(&sc->sc_lock); 372 mutex_enter(&sc->sc_lock);
372 KASSERT(sc->sc_closing); 373 KASSERT(sc->sc_closing);
373 KASSERTMSG(sc->sc_open == UHID_OPEN || sc->sc_open == UHID_CLOSED, 374 KASSERTMSG(sc->sc_open == UHID_OPEN || sc->sc_open == UHID_CLOSED,
374 "sc_open=%d", sc->sc_open); 375 "sc_open=%d", sc->sc_open);
375 if (sc->sc_open == UHID_CLOSED) 376 if (sc->sc_open == UHID_CLOSED)
376 goto out; 377 goto out;
377 378
378 /* Release the lock while we free things. */ 379 /* Release the lock while we free things. */
379 mutex_exit(&sc->sc_lock); 380 mutex_exit(&sc->sc_lock);
380 381
381 /* Prevent further interrupts. */ 382 /* Prevent further interrupts. */
382 uhidev_close(&sc->sc_hdev); 383 uhidev_close(sc->sc_hdev);
383 384
384 /* Hang up all select/poll. */ 385 /* Hang up all select/poll. */
385 selnotify(&sc->sc_rsel, POLLHUP, 0); 386 selnotify(&sc->sc_rsel, POLLHUP, 0);
386 387
387 /* Reset SIGIO. */ 388 /* Reset SIGIO. */
388 mutex_enter(&proc_lock); 389 mutex_enter(&proc_lock);
389 atomic_store_relaxed(&sc->sc_async, NULL); 390 atomic_store_relaxed(&sc->sc_async, NULL);
390 mutex_exit(&proc_lock); 391 mutex_exit(&proc_lock);
391 392
392 /* Free the buffer and queue. */ 393 /* Free the buffer and queue. */
393 if (sc->sc_osize > 0) { 394 if (sc->sc_osize > 0) {
394 kmem_free(sc->sc_obuf, sc->sc_osize); 395 kmem_free(sc->sc_obuf, sc->sc_osize);
395 sc->sc_obuf = NULL; 396 sc->sc_obuf = NULL;
@@ -412,30 +413,30 @@ out: KASSERT(sc->sc_open == UHID_CLOSED) @@ -412,30 +413,30 @@ out: KASSERT(sc->sc_open == UHID_CLOSED)
412static int 413static int
413uhidread(dev_t dev, struct uio *uio, int flag) 414uhidread(dev_t dev, struct uio *uio, int flag)
414{ 415{
415 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 416 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
416 int error = 0; 417 int error = 0;
417 int extra; 418 int extra;
418 size_t length; 419 size_t length;
419 u_char buffer[UHID_CHUNK]; 420 u_char buffer[UHID_CHUNK];
420 usbd_status err; 421 usbd_status err;
421 422
422 DPRINTFN(1, ("uhidread\n")); 423 DPRINTFN(1, ("uhidread\n"));
423 if (atomic_load_relaxed(&sc->sc_state) & UHID_IMMED) { 424 if (atomic_load_relaxed(&sc->sc_state) & UHID_IMMED) {
424 DPRINTFN(1, ("uhidread immed\n")); 425 DPRINTFN(1, ("uhidread immed\n"));
425 extra = sc->sc_hdev.sc_report_id != 0; 426 extra = sc->sc_report_id != 0;
426 if (sc->sc_isize + extra > sizeof(buffer)) 427 if (sc->sc_isize + extra > sizeof(buffer))
427 return ENOBUFS; 428 return ENOBUFS;
428 err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT, 429 err = uhidev_get_report(sc->sc_hdev, UHID_INPUT_REPORT,
429 buffer, sc->sc_isize + extra); 430 buffer, sc->sc_isize + extra);
430 if (err) 431 if (err)
431 return EIO; 432 return EIO;
432 return uiomove(buffer+extra, sc->sc_isize, uio); 433 return uiomove(buffer+extra, sc->sc_isize, uio);
433 } 434 }
434 435
435 mutex_enter(&sc->sc_lock); 436 mutex_enter(&sc->sc_lock);
436 while (sc->sc_q.c_cc == 0) { 437 while (sc->sc_q.c_cc == 0) {
437 if (flag & IO_NDELAY) { 438 if (flag & IO_NDELAY) {
438 mutex_exit(&sc->sc_lock); 439 mutex_exit(&sc->sc_lock);
439 return EWOULDBLOCK; 440 return EWOULDBLOCK;
440 } 441 }
441 if (sc->sc_closing) { 442 if (sc->sc_closing) {
@@ -479,42 +480,42 @@ uhidwrite(dev_t dev, struct uio *uio, in @@ -479,42 +480,42 @@ uhidwrite(dev_t dev, struct uio *uio, in
479 int size; 480 int size;
480 usbd_status err; 481 usbd_status err;
481 482
482 DPRINTFN(1, ("uhidwrite\n")); 483 DPRINTFN(1, ("uhidwrite\n"));
483 484
484 size = sc->sc_osize; 485 size = sc->sc_osize;
485 if (uio->uio_resid != size || size == 0) 486 if (uio->uio_resid != size || size == 0)
486 return EINVAL; 487 return EINVAL;
487 error = uiomove(sc->sc_obuf, size, uio); 488 error = uiomove(sc->sc_obuf, size, uio);
488#ifdef UHID_DEBUG 489#ifdef UHID_DEBUG
489 if (uhiddebug > 5) { 490 if (uhiddebug > 5) {
490 uint32_t i; 491 uint32_t i;
491 492
492 DPRINTF(("%s: outdata[%d] =", device_xname(sc->sc_hdev.sc_dev), 493 DPRINTF(("%s: outdata[%d] =", device_xname(sc->sc_dev),
493 error)); 494 error));
494 for (i = 0; i < size; i++) 495 for (i = 0; i < size; i++)
495 DPRINTF((" %02x", sc->sc_obuf[i])); 496 DPRINTF((" %02x", sc->sc_obuf[i]));
496 DPRINTF(("\n")); 497 DPRINTF(("\n"));
497 } 498 }
498#endif 499#endif
499 if (!error) { 500 if (!error) {
500 if (sc->sc_raw) 501 if (sc->sc_raw)
501 err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, size); 502 err = uhidev_write(sc->sc_hdev, sc->sc_obuf, size);
502 else 503 else
503 err = uhidev_set_report(&sc->sc_hdev, 504 err = uhidev_set_report(sc->sc_hdev,
504 UHID_OUTPUT_REPORT, sc->sc_obuf, size); 505 UHID_OUTPUT_REPORT, sc->sc_obuf, size);
505 if (err) { 506 if (err) {
506 DPRINTF(("%s: err = %d\n", 507 DPRINTF(("%s: err = %d\n",
507 device_xname(sc->sc_hdev.sc_dev), err)); 508 device_xname(sc->sc_dev), err));
508 error = EIO; 509 error = EIO;
509 } 510 }
510 } 511 }
511 512
512 return error; 513 return error;
513} 514}
514 515
515static int 516static int
516uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 517uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
517{ 518{
518 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 519 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
519 struct usb_ctl_report_desc *rd; 520 struct usb_ctl_report_desc *rd;
520 struct usb_ctl_report *re; 521 struct usb_ctl_report *re;
@@ -571,99 +572,99 @@ uhidioctl(dev_t dev, u_long cmd, void *a @@ -571,99 +572,99 @@ uhidioctl(dev_t dev, u_long cmd, void *a
571 } 572 }
572 mutex_exit(&proc_lock); 573 mutex_exit(&proc_lock);
573 break; 574 break;
574 575
575 case USB_HID_GET_RAW: 576 case USB_HID_GET_RAW:
576 *(int *)addr = sc->sc_raw; 577 *(int *)addr = sc->sc_raw;
577 break; 578 break;
578 579
579 case USB_HID_SET_RAW: 580 case USB_HID_SET_RAW:
580 sc->sc_raw = *(int *)addr; 581 sc->sc_raw = *(int *)addr;
581 break; 582 break;
582 583
583 case USB_GET_REPORT_DESC: 584 case USB_GET_REPORT_DESC:
584 uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size); 585 uhidev_get_report_desc(sc->sc_hdev, &desc, &size);
585 rd = (struct usb_ctl_report_desc *)addr; 586 rd = (struct usb_ctl_report_desc *)addr;
586 size = uimin(size, sizeof(rd->ucrd_data)); 587 size = uimin(size, sizeof(rd->ucrd_data));
587 rd->ucrd_size = size; 588 rd->ucrd_size = size;
588 memcpy(rd->ucrd_data, desc, size); 589 memcpy(rd->ucrd_data, desc, size);
589 break; 590 break;
590 591
591 case USB_SET_IMMED: 592 case USB_SET_IMMED:
592 if (*(int *)addr) { 593 if (*(int *)addr) {
593 extra = sc->sc_hdev.sc_report_id != 0; 594 extra = sc->sc_report_id != 0;
594 if (sc->sc_isize + extra > sizeof(buffer)) 595 if (sc->sc_isize + extra > sizeof(buffer))
595 return ENOBUFS; 596 return ENOBUFS;
596 err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT, 597 err = uhidev_get_report(sc->sc_hdev, UHID_INPUT_REPORT,
597 buffer, sc->sc_isize + extra); 598 buffer, sc->sc_isize + extra);
598 if (err) 599 if (err)
599 return EOPNOTSUPP; 600 return EOPNOTSUPP;
600 601
601 atomic_or_32(&sc->sc_state, UHID_IMMED); 602 atomic_or_32(&sc->sc_state, UHID_IMMED);
602 } else 603 } else
603 atomic_and_32(&sc->sc_state, ~UHID_IMMED); 604 atomic_and_32(&sc->sc_state, ~UHID_IMMED);
604 break; 605 break;
605 606
606 case USB_GET_REPORT: 607 case USB_GET_REPORT:
607 re = (struct usb_ctl_report *)addr; 608 re = (struct usb_ctl_report *)addr;
608 switch (re->ucr_report) { 609 switch (re->ucr_report) {
609 case UHID_INPUT_REPORT: 610 case UHID_INPUT_REPORT:
610 size = sc->sc_isize; 611 size = sc->sc_isize;
611 break; 612 break;
612 case UHID_OUTPUT_REPORT: 613 case UHID_OUTPUT_REPORT:
613 size = sc->sc_osize; 614 size = sc->sc_osize;
614 break; 615 break;
615 case UHID_FEATURE_REPORT: 616 case UHID_FEATURE_REPORT:
616 size = sc->sc_fsize; 617 size = sc->sc_fsize;
617 break; 618 break;
618 default: 619 default:
619 return EINVAL; 620 return EINVAL;
620 } 621 }
621 extra = sc->sc_hdev.sc_report_id != 0; 622 extra = sc->sc_report_id != 0;
622 if (size + extra > sizeof(re->ucr_data)) 623 if (size + extra > sizeof(re->ucr_data))
623 return ENOBUFS; 624 return ENOBUFS;
624 err = uhidev_get_report(&sc->sc_hdev, re->ucr_report, 625 err = uhidev_get_report(sc->sc_hdev, re->ucr_report,
625 re->ucr_data, size + extra); 626 re->ucr_data, size + extra);
626 if (extra) 627 if (extra)
627 memmove(re->ucr_data, re->ucr_data+1, size); 628 memmove(re->ucr_data, re->ucr_data+1, size);
628 if (err) 629 if (err)
629 return EIO; 630 return EIO;
630 break; 631 break;
631 632
632 case USB_SET_REPORT: 633 case USB_SET_REPORT:
633 re = (struct usb_ctl_report *)addr; 634 re = (struct usb_ctl_report *)addr;
634 switch (re->ucr_report) { 635 switch (re->ucr_report) {
635 case UHID_INPUT_REPORT: 636 case UHID_INPUT_REPORT:
636 size = sc->sc_isize; 637 size = sc->sc_isize;
637 break; 638 break;
638 case UHID_OUTPUT_REPORT: 639 case UHID_OUTPUT_REPORT:
639 size = sc->sc_osize; 640 size = sc->sc_osize;
640 break; 641 break;
641 case UHID_FEATURE_REPORT: 642 case UHID_FEATURE_REPORT:
642 size = sc->sc_fsize; 643 size = sc->sc_fsize;
643 break; 644 break;
644 default: 645 default:
645 return EINVAL; 646 return EINVAL;
646 } 647 }
647 if (size > sizeof(re->ucr_data)) 648 if (size > sizeof(re->ucr_data))
648 return ENOBUFS; 649 return ENOBUFS;
649 err = uhidev_set_report(&sc->sc_hdev, re->ucr_report, 650 err = uhidev_set_report(sc->sc_hdev, re->ucr_report,
650 re->ucr_data, size); 651 re->ucr_data, size);
651 if (err) 652 if (err)
652 return EIO; 653 return EIO;
653 break; 654 break;
654 655
655 case USB_GET_REPORT_ID: 656 case USB_GET_REPORT_ID:
656 *(int *)addr = sc->sc_hdev.sc_report_id; 657 *(int *)addr = sc->sc_report_id;
657 break; 658 break;
658 659
659 case USB_GET_DEVICE_DESC: 660 case USB_GET_DEVICE_DESC:
660 *(usb_device_descriptor_t *)addr = 661 *(usb_device_descriptor_t *)addr =
661 *usbd_get_device_descriptor(sc->sc_udev); 662 *usbd_get_device_descriptor(sc->sc_udev);
662 break; 663 break;
663 664
664 case USB_GET_DEVICEINFO: 665 case USB_GET_DEVICEINFO:
665 usbd_fill_deviceinfo(sc->sc_udev, 666 usbd_fill_deviceinfo(sc->sc_udev,
666 (struct usb_device_info *)addr, 0); 667 (struct usb_device_info *)addr, 0);
667 break; 668 break;
668 case USB_GET_DEVICEINFO_OLD: 669 case USB_GET_DEVICEINFO_OLD:
669 MODULE_HOOK_CALL(usb_subr_fill_30_hook, 670 MODULE_HOOK_CALL(usb_subr_fill_30_hook,

cvs diff -r1.89 -r1.90 src/sys/dev/usb/uhidev.c (expand / switch to unified diff)

--- src/sys/dev/usb/uhidev.c 2022/03/28 12:44:06 1.89
+++ src/sys/dev/usb/uhidev.c 2022/03/28 12:44:17 1.90
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uhidev.c,v 1.89 2022/03/28 12:44:06 riastradh Exp $ */ 1/* $NetBSD: uhidev.c,v 1.90 2022/03/28 12:44:17 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. 4 * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net) at 8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au). 9 * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au).
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.89 2022/03/28 12:44:06 riastradh Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.90 2022/03/28 12:44:17 riastradh Exp $");
39 39
40#ifdef _KERNEL_OPT 40#ifdef _KERNEL_OPT
41#include "opt_usb.h" 41#include "opt_usb.h"
42#endif 42#endif
43 43
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/types.h> 45#include <sys/types.h>
46 46
47#include <sys/atomic.h> 47#include <sys/atomic.h>
48#include <sys/conf.h> 48#include <sys/conf.h>
49#include <sys/device.h> 49#include <sys/device.h>
50#include <sys/ioctl.h> 50#include <sys/ioctl.h>
51#include <sys/kernel.h> 51#include <sys/kernel.h>
@@ -78,27 +78,38 @@ __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1 @@ -78,27 +78,38 @@ __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1
78 78
79struct uhidev_softc { 79struct uhidev_softc {
80 device_t sc_dev; /* base device */ 80 device_t sc_dev; /* base device */
81 struct usbd_device *sc_udev; 81 struct usbd_device *sc_udev;
82 struct usbd_interface *sc_iface; /* interface */ 82 struct usbd_interface *sc_iface; /* interface */
83 int sc_iep_addr; 83 int sc_iep_addr;
84 int sc_oep_addr; 84 int sc_oep_addr;
85 u_int sc_isize; 85 u_int sc_isize;
86 86
87 int sc_repdesc_size; 87 int sc_repdesc_size;
88 void *sc_repdesc; 88 void *sc_repdesc;
89 89
90 u_int sc_nrepid; 90 u_int sc_nrepid;
91 device_t *sc_subdevs; 91 struct uhidev {
 92 struct uhidev_softc *sc_parent;
 93 device_t sc_dev;
 94 void (*sc_intr)(void *, void *, u_int);
 95 void *sc_cookie;
 96 krndsource_t sc_rndsource;
 97 int sc_in_rep_size;
 98 uint8_t sc_report_id;
 99 uint8_t sc_state;
 100#define UHIDEV_OPEN 0x01 /* device is open */
 101#define UHIDEV_STOPPED 0x02 /* xfers are stopped */
 102 } *sc_subdevs;
92 103
93 kmutex_t sc_lock; 104 kmutex_t sc_lock;
94 kcondvar_t sc_cv; 105 kcondvar_t sc_cv;
95 106
96 /* Read/written under sc_lock. */ 107 /* Read/written under sc_lock. */
97 struct lwp *sc_writelock; 108 struct lwp *sc_writelock;
98 struct lwp *sc_configlock; 109 struct lwp *sc_configlock;
99 int sc_refcnt; 110 int sc_refcnt;
100 int sc_writereportid; 111 int sc_writereportid;
101 int sc_stopreportid; 112 int sc_stopreportid;
102 u_char sc_dying; 113 u_char sc_dying;
103 114
104 /* 115 /*
@@ -159,27 +170,26 @@ uhidev_match(device_t parent, cfdata_t m @@ -159,27 +170,26 @@ uhidev_match(device_t parent, cfdata_t m
159 return UMATCH_IFACECLASS_GENERIC; 170 return UMATCH_IFACECLASS_GENERIC;
160} 171}
161 172
162static void 173static void
163uhidev_attach(device_t parent, device_t self, void *aux) 174uhidev_attach(device_t parent, device_t self, void *aux)
164{ 175{
165 struct uhidev_softc *sc = device_private(self); 176 struct uhidev_softc *sc = device_private(self);
166 struct usbif_attach_arg *uiaa = aux; 177 struct usbif_attach_arg *uiaa = aux;
167 struct usbd_interface *iface = uiaa->uiaa_iface; 178 struct usbd_interface *iface = uiaa->uiaa_iface;
168 usb_interface_descriptor_t *id; 179 usb_interface_descriptor_t *id;
169 usb_endpoint_descriptor_t *ed; 180 usb_endpoint_descriptor_t *ed;
170 struct uhidev_attach_arg uha; 181 struct uhidev_attach_arg uha;
171 device_t dev; 182 device_t dev;
172 struct uhidev *csc; 
173 int maxinpktsize, size, nrepid, repid, repsz; 183 int maxinpktsize, size, nrepid, repid, repsz;
174 int *repsizes; 184 int *repsizes;
175 int i; 185 int i;
176 void *desc; 186 void *desc;
177 const void *descptr; 187 const void *descptr;
178 usbd_status err; 188 usbd_status err;
179 char *devinfop; 189 char *devinfop;
180 int locs[UHIDBUSCF_NLOCS]; 190 int locs[UHIDBUSCF_NLOCS];
181 191
182 sc->sc_dev = self; 192 sc->sc_dev = self;
183 sc->sc_udev = uiaa->uiaa_device; 193 sc->sc_udev = uiaa->uiaa_device;
184 sc->sc_iface = iface; 194 sc->sc_iface = iface;
185 195
@@ -395,60 +405,55 @@ uhidev_attach(device_t parent, device_t  @@ -395,60 +405,55 @@ uhidev_attach(device_t parent, device_t
395 sc->sc_isize = maxinpktsize; 405 sc->sc_isize = maxinpktsize;
396 sc->sc_nrepid = nrepid; 406 sc->sc_nrepid = nrepid;
397 407
398 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 408 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
399 409
400 for (repid = 0; repid < nrepid; repid++) { 410 for (repid = 0; repid < nrepid; repid++) {
401 repsz = hid_report_size(desc, size, hid_input, repid); 411 repsz = hid_report_size(desc, size, hid_input, repid);
402 DPRINTF(("uhidev_match: repid=%d, repsz=%d\n", repid, repsz)); 412 DPRINTF(("uhidev_match: repid=%d, repsz=%d\n", repid, repsz));
403 repsizes[repid] = repsz; 413 repsizes[repid] = repsz;
404 } 414 }
405 415
406 DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize)); 416 DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize));
407 417
408 uha.parent = sc; 
409 for (repid = 0; repid < nrepid; repid++) { 418 for (repid = 0; repid < nrepid; repid++) {
 419 struct uhidev *scd = &sc->sc_subdevs[repid];
 420
 421 scd->sc_parent = sc;
 422 scd->sc_report_id = repid;
 423 scd->sc_in_rep_size = repsizes[repid];
 424
410 DPRINTF(("uhidev_match: try repid=%d\n", repid)); 425 DPRINTF(("uhidev_match: try repid=%d\n", repid));
411 if (hid_report_size(desc, size, hid_input, repid) == 0 && 426 if (hid_report_size(desc, size, hid_input, repid) == 0 &&
412 hid_report_size(desc, size, hid_output, repid) == 0 && 427 hid_report_size(desc, size, hid_output, repid) == 0 &&
413 hid_report_size(desc, size, hid_feature, repid) == 0) { 428 hid_report_size(desc, size, hid_feature, repid) == 0) {
414 ; /* already NULL in sc->sc_subdevs[repid] */ 429 ; /* already NULL in sc->sc_subdevs[repid] */
415 } else { 430 } else {
 431 uha.parent = scd;
416 uha.reportid = repid; 432 uha.reportid = repid;
417 locs[UHIDBUSCF_REPORTID] = repid; 433 locs[UHIDBUSCF_REPORTID] = repid;
418 434
419 dev = config_found(self, &uha, uhidevprint, 435 dev = config_found(self, &uha, uhidevprint,
420 CFARGS(.submatch = config_stdsubmatch, 436 CFARGS(.submatch = config_stdsubmatch,
421 .locators = locs)); 437 .locators = locs));
422 sc->sc_subdevs[repid] = dev; 438 sc->sc_subdevs[repid].sc_dev = dev;
423 if (dev != NULL) { 439 if (dev == NULL)
424 csc = device_private(dev); 440 continue;
425 csc->sc_in_rep_size = repsizes[repid]; 441 /*
426#ifdef DIAGNOSTIC 442 * XXXSMP -- could be detached in the middle of
427 DPRINTF(("uhidev_match: repid=%d dev=%p\n", 443 * sleeping for allocation in rnd_attach_source
428 repid, dev)); 444 */
429 if (csc->sc_intr == NULL) { 445 rnd_attach_source(&scd->sc_rndsource,
430 kmem_free(repsizes, 446 device_xname(dev), RND_TYPE_TTY, RND_FLAG_DEFAULT);
431 nrepid * sizeof(*repsizes)); 
432 aprint_error_dev(self, 
433 "sc_intr == NULL\n"); 
434 return; 
435 } 
436#endif 
437 rnd_attach_source(&csc->rnd_source, 
438 device_xname(dev), 
439 RND_TYPE_TTY, 
440 RND_FLAG_DEFAULT); 
441 } 
442 } 447 }
443 } 448 }
444 kmem_free(repsizes, nrepid * sizeof(*repsizes)); 449 kmem_free(repsizes, nrepid * sizeof(*repsizes));
445 450
446 return; 451 return;
447} 452}
448 453
449static int 454static int
450uhidev_maxrepid(void *buf, int len) 455uhidev_maxrepid(void *buf, int len)
451{ 456{
452 struct hid_data *d; 457 struct hid_data *d;
453 struct hid_item h; 458 struct hid_item h;
454 int maxid; 459 int maxid;
@@ -485,77 +490,68 @@ uhidev_activate(device_t self, enum deva @@ -485,77 +490,68 @@ uhidev_activate(device_t self, enum deva
485 return 0; 490 return 0;
486 default: 491 default:
487 return EOPNOTSUPP; 492 return EOPNOTSUPP;
488 } 493 }
489} 494}
490 495
491static void 496static void
492uhidev_childdet(device_t self, device_t child) 497uhidev_childdet(device_t self, device_t child)
493{ 498{
494 int i; 499 int i;
495 struct uhidev_softc *sc = device_private(self); 500 struct uhidev_softc *sc = device_private(self);
496 501
497 for (i = 0; i < sc->sc_nrepid; i++) { 502 for (i = 0; i < sc->sc_nrepid; i++) {
498 if (sc->sc_subdevs[i] == child) 503 if (sc->sc_subdevs[i].sc_dev == child)
499 break; 504 break;
500 } 505 }
501 KASSERT(i < sc->sc_nrepid); 506 KASSERT(i < sc->sc_nrepid);
502 sc->sc_subdevs[i] = NULL; 507 sc->sc_subdevs[i].sc_dev = NULL;
 508 /*
 509 * XXXSMP -- could be reattached in the middle of sleeping for
 510 * lock on sources to delete this in rnd_attach_source
 511 *
 512 * (Actually this can't happen right now because there's no
 513 * rescan method, but if there were, it could.)
 514 */
 515 rnd_detach_source(&sc->sc_subdevs[i].sc_rndsource);
503} 516}
504 517
505static int 518static int
506uhidev_detach(device_t self, int flags) 519uhidev_detach(device_t self, int flags)
507{ 520{
508 struct uhidev_softc *sc = device_private(self); 521 struct uhidev_softc *sc = device_private(self);
509 int i, rv; 522 int rv;
510 struct uhidev *csc; 
511 523
512 DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags)); 524 DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags));
513 525
514 /* Notify that we are going away. */ 526 /* Notify that we are going away. */
515 mutex_enter(&sc->sc_lock); 527 mutex_enter(&sc->sc_lock);
516 sc->sc_dying = 1; 528 sc->sc_dying = 1;
517 cv_broadcast(&sc->sc_cv); 529 cv_broadcast(&sc->sc_cv);
518 mutex_exit(&sc->sc_lock); 530 mutex_exit(&sc->sc_lock);
519 531
520 /* 532 /*
521 * Try to detach all our children. If anything fails, bail. 533 * Try to detach all our children. If anything fails, bail.
522 * Failure can happen if this is from drvctl -d; of course, if 534 * Failure can happen if this is from drvctl -d; of course, if
523 * this is a USB device being yanked, flags will have 535 * this is a USB device being yanked, flags will have
524 * DETACH_FORCE and the children will not have the option of 536 * DETACH_FORCE and the children will not have the option of
525 * refusing detachment. 537 * refusing detachment.
526 */ 538 */
527 for (i = 0; i < sc->sc_nrepid; i++) { 539 rv = config_detach_children(self, flags);
528 if (sc->sc_subdevs[i] == NULL) 540 if (rv) {
529 continue; 541 mutex_enter(&sc->sc_lock);
530 /* 542 sc->sc_dying = 0;
531 * XXX rnd_detach_source should go in uhidev_childdet, 543 mutex_exit(&sc->sc_lock);
532 * but the struct krndsource lives in the child's 544 return rv;
533 * softc, which is gone by the time of childdet. The 
534 * parent uhidev_softc should be changed to allocate 
535 * the struct krndsource, not the child. 
536 */ 
537 csc = device_private(sc->sc_subdevs[i]); 
538 rnd_detach_source(&csc->rnd_source); 
539 rv = config_detach(sc->sc_subdevs[i], flags); 
540 if (rv) { 
541 rnd_attach_source(&csc->rnd_source, 
542 device_xname(sc->sc_dev), 
543 RND_TYPE_TTY, RND_FLAG_DEFAULT); 
544 mutex_enter(&sc->sc_lock); 
545 sc->sc_dying = 0; 
546 mutex_exit(&sc->sc_lock); 
547 return rv; 
548 } 
549 } 545 }
550 546
551 KASSERTMSG(sc->sc_refcnt == 0, 547 KASSERTMSG(sc->sc_refcnt == 0,
552 "%s: %d refs remain", device_xname(sc->sc_dev), sc->sc_refcnt); 548 "%s: %d refs remain", device_xname(sc->sc_dev), sc->sc_refcnt);
553 KASSERT(sc->sc_opipe == NULL); 549 KASSERT(sc->sc_opipe == NULL);
554 KASSERT(sc->sc_ipipe == NULL); 550 KASSERT(sc->sc_ipipe == NULL);
555 KASSERT(sc->sc_ibuf == NULL); 551 KASSERT(sc->sc_ibuf == NULL);
556 552
557 if (sc->sc_repdesc != NULL) { 553 if (sc->sc_repdesc != NULL) {
558 kmem_free(sc->sc_repdesc, sc->sc_repdesc_size); 554 kmem_free(sc->sc_repdesc, sc->sc_repdesc_size);
559 sc->sc_repdesc = NULL; 555 sc->sc_repdesc = NULL;
560 } 556 }
561 if (sc->sc_subdevs != NULL) { 557 if (sc->sc_subdevs != NULL) {
@@ -569,27 +565,26 @@ uhidev_detach(device_t self, int flags) @@ -569,27 +565,26 @@ uhidev_detach(device_t self, int flags)
569 pmf_device_deregister(self); 565 pmf_device_deregister(self);
570 KASSERT(sc->sc_configlock == NULL); 566 KASSERT(sc->sc_configlock == NULL);
571 KASSERT(sc->sc_writelock == NULL); 567 KASSERT(sc->sc_writelock == NULL);
572 cv_destroy(&sc->sc_cv); 568 cv_destroy(&sc->sc_cv);
573 mutex_destroy(&sc->sc_lock); 569 mutex_destroy(&sc->sc_lock);
574 570
575 return rv; 571 return rv;
576} 572}
577 573
578static void 574static void
579uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) 575uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status)
580{ 576{
581 struct uhidev_softc *sc = addr; 577 struct uhidev_softc *sc = addr;
582 device_t cdev; 
583 struct uhidev *scd; 578 struct uhidev *scd;
584 u_char *p; 579 u_char *p;
585 u_int rep; 580 u_int rep;
586 uint32_t cc; 581 uint32_t cc;
587 582
588 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 583 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
589 584
590#ifdef UHIDEV_DEBUG 585#ifdef UHIDEV_DEBUG
591 if (uhidevdebug > 5) { 586 if (uhidevdebug > 5) {
592 uint32_t i; 587 uint32_t i;
593 588
594 DPRINTF(("uhidev_intr: status=%d cc=%d\n", status, cc)); 589 DPRINTF(("uhidev_intr: status=%d cc=%d\n", status, cc));
595 DPRINTF(("uhidev_intr: data =")); 590 DPRINTF(("uhidev_intr: data ="));
@@ -608,52 +603,51 @@ uhidev_intr(struct usbd_xfer *xfer, void @@ -608,52 +603,51 @@ uhidev_intr(struct usbd_xfer *xfer, void
608 usbd_clear_endpoint_stall_async(sc->sc_ipipe); 603 usbd_clear_endpoint_stall_async(sc->sc_ipipe);
609 return; 604 return;
610 } 605 }
611 606
612 p = sc->sc_ibuf; 607 p = sc->sc_ibuf;
613 if (sc->sc_nrepid != 1) 608 if (sc->sc_nrepid != 1)
614 rep = *p++, cc--; 609 rep = *p++, cc--;
615 else 610 else
616 rep = 0; 611 rep = 0;
617 if (rep >= sc->sc_nrepid) { 612 if (rep >= sc->sc_nrepid) {
618 printf("uhidev_intr: bad repid %d\n", rep); 613 printf("uhidev_intr: bad repid %d\n", rep);
619 return; 614 return;
620 } 615 }
621 cdev = sc->sc_subdevs[rep]; 616 scd = &sc->sc_subdevs[rep];
622 if (!cdev) 
623 return; 
624 scd = device_private(cdev); 
625 DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=%#x\n", 617 DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=%#x\n",
626 rep, scd, scd ? scd->sc_state : 0)); 618 rep, scd, scd->sc_state));
627 if (!(atomic_load_acquire(&scd->sc_state) & UHIDEV_OPEN)) 619 if (!(atomic_load_acquire(&scd->sc_state) & UHIDEV_OPEN))
628 return; 620 return;
629#ifdef UHIDEV_DEBUG 621#ifdef UHIDEV_DEBUG
630 if (scd->sc_in_rep_size != cc) { 622 if (scd->sc_in_rep_size != cc) {
631 DPRINTF(("%s: expected %d bytes, got %d\n", 623 DPRINTF(("%s: expected %d bytes, got %d\n",
632 device_xname(sc->sc_dev), scd->sc_in_rep_size, cc)); 624 device_xname(sc->sc_dev), scd->sc_in_rep_size, cc));
633 } 625 }
634#endif 626#endif
635 if (cc == 0) { 627 if (cc == 0) {
636 DPRINTF(("%s: 0-length input ignored\n", 628 DPRINTF(("%s: 0-length input ignored\n",
637 device_xname(sc->sc_dev))); 629 device_xname(sc->sc_dev)));
638 return; 630 return;
639 } 631 }
640 rnd_add_uint32(&scd->rnd_source, (uintptr_t)(sc->sc_ibuf)); 632 rnd_add_uint32(&scd->sc_rndsource, (uintptr_t)(sc->sc_ibuf));
641 scd->sc_intr(scd, p, cc); 633 scd->sc_intr(scd->sc_cookie, p, cc);
642} 634}
643 635
644void 636void
645uhidev_get_report_desc(struct uhidev_softc *sc, void **desc, int *size) 637uhidev_get_report_desc(struct uhidev *scd, void **desc, int *size)
646{ 638{
 639 struct uhidev_softc *sc = scd->sc_parent;
 640
647 *desc = sc->sc_repdesc; 641 *desc = sc->sc_repdesc;
648 *size = sc->sc_repdesc_size; 642 *size = sc->sc_repdesc_size;
649} 643}
650 644
651static int 645static int
652uhidev_config_enter(struct uhidev_softc *sc) 646uhidev_config_enter(struct uhidev_softc *sc)
653{ 647{
654 int error; 648 int error;
655 649
656 KASSERT(mutex_owned(&sc->sc_lock)); 650 KASSERT(mutex_owned(&sc->sc_lock));
657 651
658 for (;;) { 652 for (;;) {
659 if (sc->sc_dying) 653 if (sc->sc_dying)
@@ -894,45 +888,48 @@ uhidev_close_pipes(struct uhidev_softc * @@ -894,45 +888,48 @@ uhidev_close_pipes(struct uhidev_softc *
894 usbd_close_pipe(sc->sc_ipipe); 888 usbd_close_pipe(sc->sc_ipipe);
895 sc->sc_ipipe = NULL; 889 sc->sc_ipipe = NULL;
896 } 890 }
897 kmem_free(sc->sc_ibuf, sc->sc_isize); 891 kmem_free(sc->sc_ibuf, sc->sc_isize);
898 sc->sc_ibuf = NULL; 892 sc->sc_ibuf = NULL;
899 893
900 mutex_enter(&sc->sc_lock); 894 mutex_enter(&sc->sc_lock);
901 uhidev_config_exit(sc); 895 uhidev_config_exit(sc);
902 KASSERTMSG(sc->sc_refcnt == 0, "%s: refcnt fouled: %d", 896 KASSERTMSG(sc->sc_refcnt == 0, "%s: refcnt fouled: %d",
903 device_xname(sc->sc_dev), sc->sc_refcnt); 897 device_xname(sc->sc_dev), sc->sc_refcnt);
904} 898}
905 899
906int 900int
907uhidev_open(struct uhidev *scd) 901uhidev_open(struct uhidev *scd, void (*intr)(void *, void *, u_int),
 902 void *cookie)
908{ 903{
909 struct uhidev_softc *sc = scd->sc_parent; 904 struct uhidev_softc *sc = scd->sc_parent;
910 int error; 905 int error;
911 906
912 mutex_enter(&sc->sc_lock); 907 mutex_enter(&sc->sc_lock);
913 908
914 DPRINTF(("uhidev_open(%s, report %d = %s): state=%x refcnt=%d\n", 909 DPRINTF(("uhidev_open(%s, report %d = %s): state=%x refcnt=%d\n",
915 device_xname(sc->sc_dev), 910 device_xname(sc->sc_dev),
916 scd->sc_report_id, 911 scd->sc_report_id,
917 device_xname(scd->sc_dev), 912 device_xname(scd->sc_dev),
918 scd->sc_state, 913 scd->sc_state,
919 sc->sc_refcnt)); 914 sc->sc_refcnt));
920 915
921 /* Mark the report id open. This is an exclusive lock. */ 916 /* Mark the report id open. This is an exclusive lock. */
922 if (scd->sc_state & UHIDEV_OPEN) { 917 if (scd->sc_state & UHIDEV_OPEN) {
923 error = EBUSY; 918 error = EBUSY;
924 goto out; 919 goto out;
925 } 920 }
 921 scd->sc_intr = intr;
 922 scd->sc_cookie = cookie;
926 atomic_store_release(&scd->sc_state, scd->sc_state | UHIDEV_OPEN); 923 atomic_store_release(&scd->sc_state, scd->sc_state | UHIDEV_OPEN);
927 924
928 /* Open the pipes which are shared by all report ids. */ 925 /* Open the pipes which are shared by all report ids. */
929 error = uhidev_open_pipes(sc); 926 error = uhidev_open_pipes(sc);
930 if (error) 927 if (error)
931 goto out; 928 goto out;
932 929
933 /* Success! */ 930 /* Success! */
934 error = 0; 931 error = 0;
935 932
936out: if (error) { 933out: if (error) {
937 KASSERTMSG(scd->sc_state & UHIDEV_OPEN, 934 KASSERTMSG(scd->sc_state & UHIDEV_OPEN,
938 "%s: report id %d: closed while opening", 935 "%s: report id %d: closed while opening",
@@ -1057,29 +1054,39 @@ uhidev_close(struct uhidev *scd) @@ -1057,29 +1054,39 @@ uhidev_close(struct uhidev *scd)
1057 KASSERT(scd->sc_state & UHIDEV_OPEN); 1054 KASSERT(scd->sc_state & UHIDEV_OPEN);
1058 atomic_store_relaxed(&scd->sc_state, 1055 atomic_store_relaxed(&scd->sc_state,
1059 scd->sc_state & ~(UHIDEV_OPEN | UHIDEV_STOPPED)); 1056 scd->sc_state & ~(UHIDEV_OPEN | UHIDEV_STOPPED));
1060 1057
1061 /* 1058 /*
1062 * Make sure the next uhidev_intr (which runs in softint, like 1059 * Make sure the next uhidev_intr (which runs in softint, like
1063 * XC_HIGHPRI) notices that UHIDEV_OPEN is cleared, and wait 1060 * XC_HIGHPRI) notices that UHIDEV_OPEN is cleared, and wait
1064 * for any current one to finish, in case the pipe is still 1061 * for any current one to finish, in case the pipe is still
1065 * open for other report ids. 1062 * open for other report ids.
1066 * 1063 *
1067 * We must drop the lock while doing this, because 1064 * We must drop the lock while doing this, because
1068 * uhidev_write_callback takes the lock in softint context and 1065 * uhidev_write_callback takes the lock in softint context and
1069 * it could deadlock with the xcall softint. 1066 * it could deadlock with the xcall softint.
 1067 *
 1068 * It is safe to drop the lock now before zeroing sc_intr and
 1069 * sc_cookie because the driver is obligated not to reopen
 1070 * until after uhidev_close returns.
1070 */ 1071 */
1071 mutex_exit(&sc->sc_lock); 1072 mutex_exit(&sc->sc_lock);
1072 xc_barrier(XC_HIGHPRI); 1073 xc_barrier(XC_HIGHPRI);
 1074 mutex_enter(&sc->sc_lock);
 1075 KASSERT((scd->sc_state & UHIDEV_OPEN) == 0);
 1076 scd->sc_intr = NULL;
 1077 scd->sc_cookie = NULL;
 1078
 1079 mutex_exit(&sc->sc_lock);
1073} 1080}
1074 1081
1075usbd_status 1082usbd_status
1076uhidev_set_report(struct uhidev *scd, int type, void *data, int len) 1083uhidev_set_report(struct uhidev *scd, int type, void *data, int len)
1077{ 1084{
1078 char *buf; 1085 char *buf;
1079 usbd_status retstat; 1086 usbd_status retstat;
1080 1087
1081 if (scd->sc_report_id == 0) 1088 if (scd->sc_report_id == 0)
1082 return usbd_set_report(scd->sc_parent->sc_iface, type, 1089 return usbd_set_report(scd->sc_parent->sc_iface, type,
1083 scd->sc_report_id, data, len); 1090 scd->sc_report_id, data, len);
1084 1091
1085 buf = kmem_alloc(len + 1, KM_SLEEP); 1092 buf = kmem_alloc(len + 1, KM_SLEEP);

cvs diff -r1.25 -r1.26 src/sys/dev/usb/uhidev.h (expand / switch to unified diff)

--- src/sys/dev/usb/uhidev.h 2022/03/28 12:43:39 1.25
+++ src/sys/dev/usb/uhidev.h 2022/03/28 12:44:17 1.26
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uhidev.h,v 1.25 2022/03/28 12:43:39 riastradh Exp $ */ 1/* $NetBSD: uhidev.h,v 1.26 2022/03/28 12:44:17 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net) at 8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology. 9 * Carlstedt Research & Technology.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -23,52 +23,36 @@ @@ -23,52 +23,36 @@
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33#ifndef _DEV_USB_UHIDEV_H_ 33#ifndef _DEV_USB_UHIDEV_H_
34#define _DEV_USB_UHIDEV_H_ 34#define _DEV_USB_UHIDEV_H_
35 35
36#include <sys/device.h> 
37#include <sys/rndsource.h> 
38 
39#include <dev/usb/usbdi.h> 36#include <dev/usb/usbdi.h>
40 37
41struct uhidev_softc; 38struct uhidev;
42 
43struct uhidev { 
44 device_t sc_dev; /* base device */ 
45 struct uhidev_softc *sc_parent; 
46 uByte sc_report_id; 
47 uint8_t sc_state; /* read/written under sc_parent->sc_lock */ 
48#define UHIDEV_OPEN 0x01 /* device is open */ 
49#define UHIDEV_STOPPED 0x02 /* xfers are stopped */ 
50 int sc_in_rep_size; 
51 void (*sc_intr)(struct uhidev *, void *, u_int); 
52 krndsource_t rnd_source; 
53}; 
54 39
55struct uhidev_attach_arg { 40struct uhidev_attach_arg {
56 struct usbif_attach_arg *uiaa; 41 struct usbif_attach_arg *uiaa;
57 struct uhidev_softc *parent; 42 struct uhidev *parent;
58 int reportid; 43 int reportid;
59 int reportsize; 
60}; 44};
61 45
62void uhidev_get_report_desc(struct uhidev_softc *, void **, int *); 46void uhidev_get_report_desc(struct uhidev *, void **, int *);
63int uhidev_open(struct uhidev *); 47int uhidev_open(struct uhidev *, void (*)(void *, void *, unsigned), void *);
64void uhidev_stop(struct uhidev *); 48void uhidev_stop(struct uhidev *);
65void uhidev_close(struct uhidev *); 49void uhidev_close(struct uhidev *);
66usbd_status uhidev_set_report(struct uhidev *, int, void *, int); 50usbd_status uhidev_set_report(struct uhidev *, int, void *, int);
67usbd_status uhidev_get_report(struct uhidev *, int, void *, int); 51usbd_status uhidev_get_report(struct uhidev *, int, void *, int);
68usbd_status uhidev_write(struct uhidev *, void *, int); 52usbd_status uhidev_write(struct uhidev *, void *, int);
69usbd_status uhidev_write_async(struct uhidev *, void *, int, int, int, 53usbd_status uhidev_write_async(struct uhidev *, void *, int, int, int,
70 usbd_callback, void *); 54 usbd_callback, void *);
71 55
72#define UHIDEV_OSIZE 64 56#define UHIDEV_OSIZE 64
73 57
74#endif /* _DEV_USB_UHIDEV_H_ */ 58#endif /* _DEV_USB_UHIDEV_H_ */

cvs diff -r1.158 -r1.159 src/sys/dev/usb/ukbd.c (expand / switch to unified diff)

--- src/sys/dev/usb/ukbd.c 2022/03/28 12:43:12 1.158
+++ src/sys/dev/usb/ukbd.c 2022/03/28 12:44:17 1.159
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ukbd.c,v 1.158 2022/03/28 12:43:12 riastradh Exp $ */ 1/* $NetBSD: ukbd.c,v 1.159 2022/03/28 12:44:17 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net) at 8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology. 9 * Carlstedt Research & Technology.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.158 2022/03/28 12:43:12 riastradh Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.159 2022/03/28 12:44:17 riastradh Exp $");
39 39
40#ifdef _KERNEL_OPT 40#ifdef _KERNEL_OPT
41#include "opt_ddb.h" 41#include "opt_ddb.h"
42#include "opt_ukbd.h" 42#include "opt_ukbd.h"
43#include "opt_ukbd_layout.h" 43#include "opt_ukbd_layout.h"
44#include "opt_usb.h" 44#include "opt_usb.h"
45#include "opt_usbverbose.h" 45#include "opt_usbverbose.h"
46#include "opt_wsdisplay_compat.h" 46#include "opt_wsdisplay_compat.h"
47#endif /* _KERNEL_OPT */ 47#endif /* _KERNEL_OPT */
48 48
49#include <sys/param.h> 49#include <sys/param.h>
50#include <sys/systm.h> 50#include <sys/systm.h>
51#include <sys/callout.h> 51#include <sys/callout.h>
@@ -225,29 +225,31 @@ Static const uint8_t ukbd_trtab[256] = { @@ -225,29 +225,31 @@ Static const uint8_t ukbd_trtab[256] = {
225 NN, NN, NN, NN, NN, NN, NN, NN, /* c8 - cf */ 225 NN, NN, NN, NN, NN, NN, NN, NN, /* c8 - cf */
226 NN, NN, NN, NN, NN, NN, NN, NN, /* d0 - d7 */ 226 NN, NN, NN, NN, NN, NN, NN, NN, /* d0 - d7 */
227 NN, NN, NN, NN, NN, NN, NN, NN, /* d8 - df */ 227 NN, NN, NN, NN, NN, NN, NN, NN, /* d8 - df */
228 0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, /* e0 - e7 */ 228 0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, /* e0 - e7 */
229 NN, NN, NN, NN, NN, NN, NN, NN, /* e8 - ef */ 229 NN, NN, NN, NN, NN, NN, NN, NN, /* e8 - ef */
230 NN, NN, NN, NN, NN, NN, NN, NN, /* f0 - f7 */ 230 NN, NN, NN, NN, NN, NN, NN, NN, /* f0 - f7 */
231 NN, NN, NN, NN, NN, NN, NN, NN, /* f8 - ff */ 231 NN, NN, NN, NN, NN, NN, NN, NN, /* f8 - ff */
232}; 232};
233#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */ 233#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
234 234
235#define KEY_ERROR 0x01 235#define KEY_ERROR 0x01
236 236
237struct ukbd_softc { 237struct ukbd_softc {
238 struct uhidev sc_hdev; 238 device_t sc_dev;
 239 struct uhidev *sc_hdev;
239 struct usbd_device *sc_udev; 240 struct usbd_device *sc_udev;
240 struct usbd_interface *sc_iface; 241 struct usbd_interface *sc_iface;
 242 int sc_report_id;
241 243
242 struct ukbd_data sc_ndata; 244 struct ukbd_data sc_ndata;
243 struct ukbd_data sc_odata; 245 struct ukbd_data sc_odata;
244 struct hid_location sc_keyloc[MAXKEYS]; 246 struct hid_location sc_keyloc[MAXKEYS];
245 uint8_t sc_keyuse[MAXKEYS]; 247 uint8_t sc_keyuse[MAXKEYS];
246 u_int sc_nkeyloc; 248 u_int sc_nkeyloc;
247 249
248 struct hid_location sc_keycodeloc; 250 struct hid_location sc_keycodeloc;
249 u_int sc_nkeycode; 251 u_int sc_nkeycode;
250 252
251 u_int sc_flags; /* flags */ 253 u_int sc_flags; /* flags */
252#define FLAG_ENABLED 0x0001 254#define FLAG_ENABLED 0x0001
253#define FLAG_POLLING 0x0002 255#define FLAG_POLLING 0x0002
@@ -330,27 +332,27 @@ ukbdtracedump(void) @@ -330,27 +332,27 @@ ukbdtracedump(void)
330Static int ukbd_is_console; 332Static int ukbd_is_console;
331 333
332Static void ukbd_cngetc(void *, u_int *, int *); 334Static void ukbd_cngetc(void *, u_int *, int *);
333Static void ukbd_cnpollc(void *, int); 335Static void ukbd_cnpollc(void *, int);
334 336
335const struct wskbd_consops ukbd_consops = { 337const struct wskbd_consops ukbd_consops = {
336 .getc = ukbd_cngetc, 338 .getc = ukbd_cngetc,
337 .pollc = ukbd_cnpollc, 339 .pollc = ukbd_cnpollc,
338 .bell = NULL, 340 .bell = NULL,
339}; 341};
340 342
341Static const char *ukbd_parse_desc(struct ukbd_softc *); 343Static const char *ukbd_parse_desc(struct ukbd_softc *);
342 344
343Static void ukbd_intr(struct uhidev *, void *, u_int); 345Static void ukbd_intr(void *, void *, u_int);
344Static void ukbd_decode(struct ukbd_softc *, struct ukbd_data *); 346Static void ukbd_decode(struct ukbd_softc *, struct ukbd_data *);
345Static void ukbd_delayed_decode(void *); 347Static void ukbd_delayed_decode(void *);
346 348
347Static int ukbd_enable(void *, int); 349Static int ukbd_enable(void *, int);
348Static void ukbd_set_leds(void *, int); 350Static void ukbd_set_leds(void *, int);
349Static void ukbd_set_leds_task(void *); 351Static void ukbd_set_leds_task(void *);
350Static void ukbd_delayed_leds_off(void *); 352Static void ukbd_delayed_leds_off(void *);
351 353
352Static int ukbd_ioctl(void *, u_long, void *, int, struct lwp *); 354Static int ukbd_ioctl(void *, u_long, void *, int, struct lwp *);
353#if defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT) 355#if defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT)
354Static void ukbd_rawrepeat(void *v); 356Static void ukbd_rawrepeat(void *v);
355#endif 357#endif
356 358
@@ -398,32 +400,31 @@ ukbd_match(device_t parent, cfdata_t mat @@ -398,32 +400,31 @@ ukbd_match(device_t parent, cfdata_t mat
398 400
399 return UMATCH_IFACECLASS; 401 return UMATCH_IFACECLASS;
400} 402}
401 403
402void 404void
403ukbd_attach(device_t parent, device_t self, void *aux) 405ukbd_attach(device_t parent, device_t self, void *aux)
404{ 406{
405 struct ukbd_softc *sc = device_private(self); 407 struct ukbd_softc *sc = device_private(self);
406 struct uhidev_attach_arg *uha = aux; 408 struct uhidev_attach_arg *uha = aux;
407 uint32_t qflags; 409 uint32_t qflags;
408 const char *parseerr; 410 const char *parseerr;
409 struct wskbddev_attach_args a; 411 struct wskbddev_attach_args a;
410 412
411 sc->sc_hdev.sc_dev = self; 413 sc->sc_dev = self;
412 sc->sc_hdev.sc_intr = ukbd_intr; 414 sc->sc_hdev = uha->parent;
413 sc->sc_hdev.sc_parent = uha->parent; 
414 sc->sc_hdev.sc_report_id = uha->reportid; 
415 sc->sc_udev = uha->uiaa->uiaa_device; 415 sc->sc_udev = uha->uiaa->uiaa_device;
416 sc->sc_iface = uha->uiaa->uiaa_iface; 416 sc->sc_iface = uha->uiaa->uiaa_iface;
 417 sc->sc_report_id = uha->reportid;
417 sc->sc_flags = 0; 418 sc->sc_flags = 0;
418 419
419 aprint_naive("\n"); 420 aprint_naive("\n");
420 421
421 if (!pmf_device_register(self, NULL, NULL)) { 422 if (!pmf_device_register(self, NULL, NULL)) {
422 aprint_normal("\n"); 423 aprint_normal("\n");
423 aprint_error_dev(self, "couldn't establish power handler\n"); 424 aprint_error_dev(self, "couldn't establish power handler\n");
424 } 425 }
425 426
426 parseerr = ukbd_parse_desc(sc); 427 parseerr = ukbd_parse_desc(sc);
427 if (parseerr != NULL) { 428 if (parseerr != NULL) {
428 aprint_normal("\n"); 429 aprint_normal("\n");
429 aprint_error_dev(self, "attach failed, %s\n", parseerr); 430 aprint_error_dev(self, "attach failed, %s\n", parseerr);
@@ -504,38 +505,38 @@ ukbd_attach(device_t parent, device_t se @@ -504,38 +505,38 @@ ukbd_attach(device_t parent, device_t se
504} 505}
505 506
506int 507int
507ukbd_enable(void *v, int on) 508ukbd_enable(void *v, int on)
508{ 509{
509 struct ukbd_softc *sc = v; 510 struct ukbd_softc *sc = v;
510 511
511 if (on && sc->sc_dying) 512 if (on && sc->sc_dying)
512 return EIO; 513 return EIO;
513 514
514 /* Should only be called to change state */ 515 /* Should only be called to change state */
515 if ((sc->sc_flags & FLAG_ENABLED) != 0 && on != 0) { 516 if ((sc->sc_flags & FLAG_ENABLED) != 0 && on != 0) {
516#ifdef DIAGNOSTIC 517#ifdef DIAGNOSTIC
517 aprint_error_dev(sc->sc_hdev.sc_dev, "bad call on=%d\n", on); 518 aprint_error_dev(sc->sc_dev, "bad call on=%d\n", on);
518#endif 519#endif
519 return EBUSY; 520 return EBUSY;
520 } 521 }
521 522
522 DPRINTF(("%s: sc=%p on=%d\n", __func__, sc, on)); 523 DPRINTF(("%s: sc=%p on=%d\n", __func__, sc, on));
523 if (on) { 524 if (on) {
524 sc->sc_flags |= FLAG_ENABLED; 525 sc->sc_flags |= FLAG_ENABLED;
525 return uhidev_open(&sc->sc_hdev); 526 return uhidev_open(sc->sc_hdev, &ukbd_intr, sc);
526 } else { 527 } else {
527 sc->sc_flags &= ~FLAG_ENABLED; 528 sc->sc_flags &= ~FLAG_ENABLED;
528 uhidev_close(&sc->sc_hdev); 529 uhidev_close(sc->sc_hdev);
529 return 0; 530 return 0;
530 } 531 }
531} 532}
532 533
533 534
534static void 535static void
535ukbd_childdet(device_t self, device_t child) 536ukbd_childdet(device_t self, device_t child)
536{ 537{
537 struct ukbd_softc *sc = device_private(self); 538 struct ukbd_softc *sc = device_private(self);
538 539
539 KASSERT(sc->sc_wskbddev == child); 540 KASSERT(sc->sc_wskbddev == child);
540 sc->sc_wskbddev = NULL; 541 sc->sc_wskbddev = NULL;
541} 542}
@@ -563,63 +564,62 @@ ukbd_detach(device_t self, int flags) @@ -563,63 +564,62 @@ ukbd_detach(device_t self, int flags)
563 DPRINTF(("%s: sc=%p flags=%d\n", __func__, sc, flags)); 564 DPRINTF(("%s: sc=%p flags=%d\n", __func__, sc, flags));
564 565
565 pmf_device_deregister(self); 566 pmf_device_deregister(self);
566 567
567 if (sc->sc_console_keyboard) { 568 if (sc->sc_console_keyboard) {
568 /* 569 /*
569 * Disconnect our consops and set ukbd_is_console 570 * Disconnect our consops and set ukbd_is_console
570 * back to 1 so that the next USB keyboard attached 571 * back to 1 so that the next USB keyboard attached
571 * to the system will get it. 572 * to the system will get it.
572 * XXX Should notify some other keyboard that it can be 573 * XXX Should notify some other keyboard that it can be
573 * XXX console, if there are any other keyboards. 574 * XXX console, if there are any other keyboards.
574 */ 575 */
575 printf("%s: was console keyboard\n", 576 printf("%s: was console keyboard\n",
576 device_xname(sc->sc_hdev.sc_dev)); 577 device_xname(sc->sc_dev));
577 wskbd_cndetach(); 578 wskbd_cndetach();
578 ukbd_is_console = 1; 579 ukbd_is_console = 1;
579 } 580 }
580 /* No need to do reference counting of ukbd, wskbd has all the goo. */ 581 /* No need to do reference counting of ukbd, wskbd has all the goo. */
581 if (sc->sc_wskbddev != NULL) 582 if (sc->sc_wskbddev != NULL)
582 rv = config_detach(sc->sc_wskbddev, flags); 583 rv = config_detach(sc->sc_wskbddev, flags);
583 584
584 callout_halt(&sc->sc_delay, NULL); 585 callout_halt(&sc->sc_delay, NULL);
585 callout_halt(&sc->sc_ledreset, NULL); 586 callout_halt(&sc->sc_ledreset, NULL);
586 usb_rem_task_wait(sc->sc_udev, &sc->sc_ledtask, 587 usb_rem_task_wait(sc->sc_udev, &sc->sc_ledtask,
587 USB_TASKQ_DRIVER, NULL); 588 USB_TASKQ_DRIVER, NULL);
588 589
589 /* The console keyboard does not get a disable call, so check pipe. */ 590 /* The console keyboard does not get a disable call, so check pipe. */
590 if (sc->sc_hdev.sc_state & UHIDEV_OPEN) 591 if (sc->sc_flags & FLAG_ENABLED)
591 uhidev_close(&sc->sc_hdev); 592 uhidev_close(sc->sc_hdev);
592 593
593 return rv; 594 return rv;
594} 595}
595 596
596static void 597static void
597ukbd_translate_keycodes(struct ukbd_softc *sc, struct ukbd_data *ud, 598ukbd_translate_keycodes(struct ukbd_softc *sc, struct ukbd_data *ud,
598 const struct ukbd_keycodetrans *tab) 599 const struct ukbd_keycodetrans *tab)
599{ 600{
600 const struct ukbd_keycodetrans *tp; 601 const struct ukbd_keycodetrans *tp;
601 struct ukbd_data oud; 602 struct ukbd_data oud;
602 int i; 603 int i;
603 604
604 oud = *ud; 605 oud = *ud;
605 606
606 for (i = 4; i < MAXKEYS; i++) { 607 for (i = 4; i < MAXKEYS; i++) {
607 if (isset(oud.keys, i)) 608 if (isset(oud.keys, i))
608 for (tp = tab; tp->from; tp++) 609 for (tp = tab; tp->from; tp++)
609 if (tp->from == i) { 610 if (tp->from == i) {
610 if (tp->to & IS_PMF) { 611 if (tp->to & IS_PMF) {
611 pmf_event_inject( 612 pmf_event_inject(sc->sc_dev,
612 sc->sc_hdev.sc_dev, 
613 tp->to & 0xff); 613 tp->to & 0xff);
614 } else 614 } else
615 setbit(ud->keys, tp->to); 615 setbit(ud->keys, tp->to);
616 clrbit(ud->keys, i); 616 clrbit(ud->keys, i);
617 break; 617 break;
618 } 618 }
619 } 619 }
620} 620}
621 621
622static uint16_t 622static uint16_t
623ukbd_translate_modifier(struct ukbd_softc *sc, uint16_t key) 623ukbd_translate_modifier(struct ukbd_softc *sc, uint16_t key)
624{ 624{
625 if ((sc->sc_flags & FLAG_APPLE_FN) && (key & CODEMASK) == 0x00e2) { 625 if ((sc->sc_flags & FLAG_APPLE_FN) && (key & CODEMASK) == 0x00e2) {
@@ -631,29 +631,29 @@ ukbd_translate_modifier(struct ukbd_soft @@ -631,29 +631,29 @@ ukbd_translate_modifier(struct ukbd_soft
631 } 631 }
632 } else { 632 } else {
633 if (sc->sc_flags & FLAG_FN_ALT) { 633 if (sc->sc_flags & FLAG_FN_ALT) {
634 /* released Alt, which was treated as FN-Alt */ 634 /* released Alt, which was treated as FN-Alt */
635 key = 0x00e6 | RELEASE; 635 key = 0x00e6 | RELEASE;
636 sc->sc_flags &= ~FLAG_FN_ALT; 636 sc->sc_flags &= ~FLAG_FN_ALT;
637 } 637 }
638 } 638 }
639 } 639 }
640 return key; 640 return key;
641} 641}
642 642
643void 643void
644ukbd_intr(struct uhidev *addr, void *ibuf, u_int len) 644ukbd_intr(void *cookie, void *ibuf, u_int len)
645{ 645{
646 struct ukbd_softc *sc = (struct ukbd_softc *)addr; 646 struct ukbd_softc *sc = cookie;
647 struct ukbd_data *ud = &sc->sc_ndata; 647 struct ukbd_data *ud = &sc->sc_ndata;
648 int i; 648 int i;
649 649
650#ifdef UKBD_DEBUG 650#ifdef UKBD_DEBUG
651 if (ukbddebug > 5) { 651 if (ukbddebug > 5) {
652 printf("ukbd_intr: data"); 652 printf("ukbd_intr: data");
653 for (i = 0; i < len; i++) 653 for (i = 0; i < len; i++)
654 printf(" 0x%02x", ((u_char *)ibuf)[i]); 654 printf(" 0x%02x", ((u_char *)ibuf)[i]);
655 printf("\n"); 655 printf("\n");
656 } 656 }
657#endif 657#endif
658 658
659 memset(ud->keys, 0, sizeof(ud->keys)); 659 memset(ud->keys, 0, sizeof(ud->keys));
@@ -758,27 +758,27 @@ ukbd_decode(struct ukbd_softc *sc, struc @@ -758,27 +758,27 @@ ukbd_decode(struct ukbd_softc *sc, struc
758 int key; 758 int key;
759#define ADDKEY(c) do { \ 759#define ADDKEY(c) do { \
760 KASSERT(nkeys < MAXKEYS); \ 760 KASSERT(nkeys < MAXKEYS); \
761 ibuf[nkeys++] = (c); \ 761 ibuf[nkeys++] = (c); \
762} while (0) 762} while (0)
763 763
764#ifdef UKBD_DEBUG 764#ifdef UKBD_DEBUG
765 /* 765 /*
766 * Keep a trace of the last events. Using printf changes the 766 * Keep a trace of the last events. Using printf changes the
767 * timing, so this can be useful sometimes. 767 * timing, so this can be useful sometimes.
768 */ 768 */
769 if (ukbdtrace) { 769 if (ukbdtrace) {
770 struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex]; 770 struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
771 p->unit = device_unit(sc->sc_hdev.sc_dev); 771 p->unit = device_unit(sc->sc_dev);
772 microtime(&p->tv); 772 microtime(&p->tv);
773 p->ud = *ud; 773 p->ud = *ud;
774 if (++ukbdtraceindex >= UKBDTRACESIZE) 774 if (++ukbdtraceindex >= UKBDTRACESIZE)
775 ukbdtraceindex = 0; 775 ukbdtraceindex = 0;
776 } 776 }
777 if (ukbddebug > 5) { 777 if (ukbddebug > 5) {
778 struct timeval tv; 778 struct timeval tv;
779 microtime(&tv); 779 microtime(&tv);
780 DPRINTF((" at %"PRIu64".%06"PRIu64":", tv.tv_sec, 780 DPRINTF((" at %"PRIu64".%06"PRIu64":", tv.tv_sec,
781 (uint64_t)tv.tv_usec)); 781 (uint64_t)tv.tv_usec));
782 for (size_t k = 0; k < MAXKEYS; k++) { 782 for (size_t k = 0; k < MAXKEYS; k++) {
783 if (isset(ud->keys, k)) 783 if (isset(ud->keys, k))
784 DPRINTF((" %zu", k)); 784 DPRINTF((" %zu", k));
@@ -913,27 +913,27 @@ ukbd_set_leds_task(void *v) @@ -913,27 +913,27 @@ ukbd_set_leds_task(void *v)
913 int leds = sc->sc_leds; 913 int leds = sc->sc_leds;
914 uint8_t res = 0; 914 uint8_t res = 0;
915 915
916 /* XXX not really right */ 916 /* XXX not really right */
917 if ((leds & WSKBD_LED_COMPOSE) && sc->sc_compose.size == 1) 917 if ((leds & WSKBD_LED_COMPOSE) && sc->sc_compose.size == 1)
918 res |= 1 << sc->sc_compose.pos; 918 res |= 1 << sc->sc_compose.pos;
919 if ((leds & WSKBD_LED_SCROLL) && sc->sc_scroloc.size == 1) 919 if ((leds & WSKBD_LED_SCROLL) && sc->sc_scroloc.size == 1)
920 res |= 1 << sc->sc_scroloc.pos; 920 res |= 1 << sc->sc_scroloc.pos;
921 if ((leds & WSKBD_LED_NUM) && sc->sc_numloc.size == 1) 921 if ((leds & WSKBD_LED_NUM) && sc->sc_numloc.size == 1)
922 res |= 1 << sc->sc_numloc.pos; 922 res |= 1 << sc->sc_numloc.pos;
923 if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1) 923 if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1)
924 res |= 1 << sc->sc_capsloc.pos; 924 res |= 1 << sc->sc_capsloc.pos;
925 925
926 uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1); 926 uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1);
927} 927}
928 928
929#if defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT) 929#if defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT)
930void 930void
931ukbd_rawrepeat(void *v) 931ukbd_rawrepeat(void *v)
932{ 932{
933 struct ukbd_softc *sc = v; 933 struct ukbd_softc *sc = v;
934 int s; 934 int s;
935 935
936 s = spltty(); 936 s = spltty();
937 wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep); 937 wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
938 splx(s); 938 splx(s);
939 callout_reset(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000, 939 callout_reset(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000,
@@ -1049,45 +1049,45 @@ ukbd_cnattach(void) @@ -1049,45 +1049,45 @@ ukbd_cnattach(void)
1049 ukbd_is_console = 1; 1049 ukbd_is_console = 1;
1050 return 0; 1050 return 0;
1051} 1051}
1052 1052
1053const char * 1053const char *
1054ukbd_parse_desc(struct ukbd_softc *sc) 1054ukbd_parse_desc(struct ukbd_softc *sc)
1055{ 1055{
1056 struct hid_data *d; 1056 struct hid_data *d;
1057 struct hid_item h; 1057 struct hid_item h;
1058 int size; 1058 int size;
1059 void *desc; 1059 void *desc;
1060 int ikey; 1060 int ikey;
1061 1061
1062 uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size); 1062 uhidev_get_report_desc(sc->sc_hdev, &desc, &size);
1063 ikey = 0; 1063 ikey = 0;
1064 sc->sc_nkeycode = 0; 1064 sc->sc_nkeycode = 0;
1065 d = hid_start_parse(desc, size, hid_input); 1065 d = hid_start_parse(desc, size, hid_input);
1066 while (hid_get_item(d, &h)) { 1066 while (hid_get_item(d, &h)) {
1067 /*printf("ukbd: id=%d kind=%d usage=%#x flags=%#x pos=%d size=%d cnt=%d\n", 1067 /*printf("ukbd: id=%d kind=%d usage=%#x flags=%#x pos=%d size=%d cnt=%d\n",
1068 h.report_ID, h.kind, h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count);*/ 1068 h.report_ID, h.kind, h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count);*/
1069 1069
1070 /* Check for special Apple notebook FN key */ 1070 /* Check for special Apple notebook FN key */
1071 if (HID_GET_USAGE_PAGE(h.usage) == 0x00ff && 1071 if (HID_GET_USAGE_PAGE(h.usage) == 0x00ff &&
1072 HID_GET_USAGE(h.usage) == 0x0003 && 1072 HID_GET_USAGE(h.usage) == 0x0003 &&
1073 h.kind == hid_input && (h.flags & HIO_VARIABLE)) { 1073 h.kind == hid_input && (h.flags & HIO_VARIABLE)) {
1074 sc->sc_flags |= FLAG_APPLE_FN; 1074 sc->sc_flags |= FLAG_APPLE_FN;
1075 sc->sc_apple_fn = h.loc; 1075 sc->sc_apple_fn = h.loc;
1076 } 1076 }
1077 1077
1078 if (h.kind != hid_input || (h.flags & HIO_CONST) || 1078 if (h.kind != hid_input || (h.flags & HIO_CONST) ||
1079 HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD || 1079 HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
1080 h.report_ID != sc->sc_hdev.sc_report_id) 1080 h.report_ID != sc->sc_report_id)
1081 continue; 1081 continue;
1082 DPRINTF(("%s: ikey=%d usage=%#x flags=%#x pos=%d size=%d " 1082 DPRINTF(("%s: ikey=%d usage=%#x flags=%#x pos=%d size=%d "
1083 "cnt=%d\n", __func__, ikey, h.usage, h.flags, h.loc.pos, 1083 "cnt=%d\n", __func__, ikey, h.usage, h.flags, h.loc.pos,
1084 h.loc.size, h.loc.count)); 1084 h.loc.size, h.loc.count));
1085 if (h.flags & HIO_VARIABLE) { 1085 if (h.flags & HIO_VARIABLE) {
1086 if (h.loc.size != 1) { 1086 if (h.loc.size != 1) {
1087 hid_end_parse(d); 1087 hid_end_parse(d);
1088 return "bad modifier size"; 1088 return "bad modifier size";
1089 } 1089 }
1090 /* Single item */ 1090 /* Single item */
1091 if (ikey < MAXKEYS) { 1091 if (ikey < MAXKEYS) {
1092 sc->sc_keyloc[ikey] = h.loc; 1092 sc->sc_keyloc[ikey] = h.loc;
1093 sc->sc_keyuse[ikey] = HID_GET_USAGE(h.usage); 1093 sc->sc_keyuse[ikey] = HID_GET_USAGE(h.usage);
@@ -1110,23 +1110,23 @@ ukbd_parse_desc(struct ukbd_softc *sc) @@ -1110,23 +1110,23 @@ ukbd_parse_desc(struct ukbd_softc *sc)
1110 } 1110 }
1111 if (sc->sc_nkeycode != 0) { 1111 if (sc->sc_nkeycode != 0) {
1112 hid_end_parse(d); 1112 hid_end_parse(d);
1113 return "multiple key code arrays"; 1113 return "multiple key code arrays";
1114 } 1114 }
1115 sc->sc_keycodeloc = h.loc; 1115 sc->sc_keycodeloc = h.loc;
1116 sc->sc_nkeycode = h.loc.count; 1116 sc->sc_nkeycode = h.loc.count;
1117 } 1117 }
1118 } 1118 }
1119 sc->sc_nkeyloc = ikey; 1119 sc->sc_nkeyloc = ikey;
1120 hid_end_parse(d); 1120 hid_end_parse(d);
1121 1121
1122 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK), 1122 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
1123 sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL); 1123 sc->sc_report_id, hid_output, &sc->sc_numloc, NULL);
1124 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK), 1124 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
1125 sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL); 1125 sc->sc_report_id, hid_output, &sc->sc_capsloc, NULL);
1126 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK), 1126 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
1127 sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL); 1127 sc->sc_report_id, hid_output, &sc->sc_scroloc, NULL);
1128 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_COMPOSE), 1128 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_COMPOSE),
1129 sc->sc_hdev.sc_report_id, hid_output, &sc->sc_compose, NULL); 1129 sc->sc_report_id, hid_output, &sc->sc_compose, NULL);
1130 1130
1131 return NULL; 1131 return NULL;
1132} 1132}

cvs diff -r1.102 -r1.103 src/sys/dev/usb/ums.c (expand / switch to unified diff)

--- src/sys/dev/usb/ums.c 2022/03/28 12:43:12 1.102
+++ src/sys/dev/usb/ums.c 2022/03/28 12:44:17 1.103
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ums.c,v 1.102 2022/03/28 12:43:12 riastradh Exp $ */ 1/* $NetBSD: ums.c,v 1.103 2022/03/28 12:44:17 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1998, 2017 The NetBSD Foundation, Inc. 4 * Copyright (c) 1998, 2017 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net) at 8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology. 9 * Carlstedt Research & Technology.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: ums.c,v 1.102 2022/03/28 12:43:12 riastradh Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: ums.c,v 1.103 2022/03/28 12:44:17 riastradh Exp $");
39 39
40#ifdef _KERNEL_OPT 40#ifdef _KERNEL_OPT
41#include "opt_usb.h" 41#include "opt_usb.h"
42#endif 42#endif
43 43
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/systm.h> 45#include <sys/systm.h>
46#include <sys/kernel.h> 46#include <sys/kernel.h>
47#include <sys/device.h> 47#include <sys/device.h>
48#include <sys/ioctl.h> 48#include <sys/ioctl.h>
49#include <sys/file.h> 49#include <sys/file.h>
50#include <sys/select.h> 50#include <sys/select.h>
51#include <sys/proc.h> 51#include <sys/proc.h>
@@ -65,37 +65,37 @@ __KERNEL_RCSID(0, "$NetBSD: ums.c,v 1.10 @@ -65,37 +65,37 @@ __KERNEL_RCSID(0, "$NetBSD: ums.c,v 1.10
65 65
66#ifdef UMS_DEBUG 66#ifdef UMS_DEBUG
67#define DPRINTF(x) if (umsdebug) printf x 67#define DPRINTF(x) if (umsdebug) printf x
68#define DPRINTFN(n,x) if (umsdebug>(n)) printf x 68#define DPRINTFN(n,x) if (umsdebug>(n)) printf x
69int umsdebug = 0; 69int umsdebug = 0;
70#else 70#else
71#define DPRINTF(x) 71#define DPRINTF(x)
72#define DPRINTFN(n,x) 72#define DPRINTFN(n,x)
73#endif 73#endif
74 74
75#define UMSUNIT(s) (minor(s)) 75#define UMSUNIT(s) (minor(s))
76 76
77struct ums_softc { 77struct ums_softc {
78 struct uhidev sc_hdev; 78 struct uhidev *sc_hdev;
79 struct usbd_device *sc_udev; 79 struct usbd_device *sc_udev;
80 struct hidms sc_ms; 80 struct hidms sc_ms;
81 81
82 bool sc_alwayson; 82 bool sc_alwayson;
83 83
84 int sc_enabled; 84 int sc_enabled;
85 char sc_dying; 85 char sc_dying;
86}; 86};
87 87
88Static void ums_intr(struct uhidev *, void *, u_int); 88Static void ums_intr(void *, void *, u_int);
89 89
90Static int ums_enable(void *); 90Static int ums_enable(void *);
91Static void ums_disable(void *); 91Static void ums_disable(void *);
92Static int ums_ioctl(void *, u_long, void *, int, struct lwp *); 92Static int ums_ioctl(void *, u_long, void *, int, struct lwp *);
93 93
94static const struct wsmouse_accessops ums_accessops = { 94static const struct wsmouse_accessops ums_accessops = {
95 ums_enable, 95 ums_enable,
96 ums_ioctl, 96 ums_ioctl,
97 ums_disable, 97 ums_disable,
98}; 98};
99 99
100static int ums_match(device_t, cfdata_t, void *); 100static int ums_match(device_t, cfdata_t, void *);
101static void ums_attach(device_t, device_t, void *); 101static void ums_attach(device_t, device_t, void *);
@@ -136,30 +136,27 @@ ums_match(device_t parent, cfdata_t matc @@ -136,30 +136,27 @@ ums_match(device_t parent, cfdata_t matc
136static void 136static void
137ums_attach(device_t parent, device_t self, void *aux) 137ums_attach(device_t parent, device_t self, void *aux)
138{ 138{
139 struct ums_softc *sc = device_private(self); 139 struct ums_softc *sc = device_private(self);
140 struct uhidev_attach_arg *uha = aux; 140 struct uhidev_attach_arg *uha = aux;
141 struct hid_data *d; 141 struct hid_data *d;
142 struct hid_item item; 142 struct hid_item item;
143 int size, error; 143 int size, error;
144 void *desc; 144 void *desc;
145 uint32_t quirks; 145 uint32_t quirks;
146 146
147 aprint_naive("\n"); 147 aprint_naive("\n");
148 148
149 sc->sc_hdev.sc_dev = self; 149 sc->sc_hdev = uha->parent;
150 sc->sc_hdev.sc_intr = ums_intr; 
151 sc->sc_hdev.sc_parent = uha->parent; 
152 sc->sc_hdev.sc_report_id = uha->reportid; 
153 sc->sc_udev = uha->uiaa->uiaa_device; 150 sc->sc_udev = uha->uiaa->uiaa_device;
154 151
155 quirks = usbd_get_quirks(sc->sc_udev)->uq_flags; 152 quirks = usbd_get_quirks(sc->sc_udev)->uq_flags;
156 if (quirks & UQ_MS_REVZ) 153 if (quirks & UQ_MS_REVZ)
157 sc->sc_ms.flags |= HIDMS_REVZ; 154 sc->sc_ms.flags |= HIDMS_REVZ;
158 if (quirks & UQ_SPUR_BUT_UP) 155 if (quirks & UQ_SPUR_BUT_UP)
159 sc->sc_ms.flags |= HIDMS_SPUR_BUT_UP; 156 sc->sc_ms.flags |= HIDMS_SPUR_BUT_UP;
160 if (quirks & UQ_ALWAYS_ON) 157 if (quirks & UQ_ALWAYS_ON)
161 sc->sc_alwayson = true; 158 sc->sc_alwayson = true;
162 159
163 if (!pmf_device_register(self, NULL, NULL)) 160 if (!pmf_device_register(self, NULL, NULL))
164 aprint_error_dev(self, "couldn't establish power handler\n"); 161 aprint_error_dev(self, "couldn't establish power handler\n");
165 162
@@ -208,47 +205,47 @@ ums_attach(device_t parent, device_t sel @@ -208,47 +205,47 @@ ums_attach(device_t parent, device_t sel
208 tpcalib_init(&sc->sc_ms.sc_tpcalib); 205 tpcalib_init(&sc->sc_ms.sc_tpcalib);
209 206
210 /* calibrate the pointer if it reports absolute events */ 207 /* calibrate the pointer if it reports absolute events */
211 if (sc->sc_ms.flags & HIDMS_ABS) { 208 if (sc->sc_ms.flags & HIDMS_ABS) {
212 memset(&sc->sc_ms.sc_calibcoords, 0, sizeof(sc->sc_ms.sc_calibcoords)); 209 memset(&sc->sc_ms.sc_calibcoords, 0, sizeof(sc->sc_ms.sc_calibcoords));
213 sc->sc_ms.sc_calibcoords.maxx = 0; 210 sc->sc_ms.sc_calibcoords.maxx = 0;
214 sc->sc_ms.sc_calibcoords.maxy = 0; 211 sc->sc_ms.sc_calibcoords.maxy = 0;
215 sc->sc_ms.sc_calibcoords.samplelen = WSMOUSE_CALIBCOORDS_RESET; 212 sc->sc_ms.sc_calibcoords.samplelen = WSMOUSE_CALIBCOORDS_RESET;
216 d = hid_start_parse(desc, size, hid_input); 213 d = hid_start_parse(desc, size, hid_input);
217 if (d != NULL) { 214 if (d != NULL) {
218 while (hid_get_item(d, &item)) { 215 while (hid_get_item(d, &item)) {
219 if (item.kind != hid_input 216 if (item.kind != hid_input
220 || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP 217 || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP
221 || item.report_ID != sc->sc_hdev.sc_report_id) 218 || item.report_ID != uha->reportid)
222 continue; 219 continue;
223 if (HID_GET_USAGE(item.usage) == HUG_X) { 220 if (HID_GET_USAGE(item.usage) == HUG_X) {
224 sc->sc_ms.sc_calibcoords.minx = item.logical_minimum; 221 sc->sc_ms.sc_calibcoords.minx = item.logical_minimum;
225 sc->sc_ms.sc_calibcoords.maxx = item.logical_maximum; 222 sc->sc_ms.sc_calibcoords.maxx = item.logical_maximum;
226 } 223 }
227 if (HID_GET_USAGE(item.usage) == HUG_Y) { 224 if (HID_GET_USAGE(item.usage) == HUG_Y) {
228 sc->sc_ms.sc_calibcoords.miny = item.logical_minimum; 225 sc->sc_ms.sc_calibcoords.miny = item.logical_minimum;
229 sc->sc_ms.sc_calibcoords.maxy = item.logical_maximum; 226 sc->sc_ms.sc_calibcoords.maxy = item.logical_maximum;
230 } 227 }
231 } 228 }
232 hid_end_parse(d); 229 hid_end_parse(d);
233 } 230 }
234 tpcalib_ioctl(&sc->sc_ms.sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 231 tpcalib_ioctl(&sc->sc_ms.sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
235 (void *)&sc->sc_ms.sc_calibcoords, 0, 0); 232 (void *)&sc->sc_ms.sc_calibcoords, 0, 0);
236 } 233 }
237 234
238 hidms_attach(self, &sc->sc_ms, &ums_accessops); 235 hidms_attach(self, &sc->sc_ms, &ums_accessops);
239 236
240 if (sc->sc_alwayson) { 237 if (sc->sc_alwayson) {
241 error = uhidev_open(&sc->sc_hdev); 238 error = uhidev_open(sc->sc_hdev, &ums_intr, sc);
242 if (error != 0) { 239 if (error != 0) {
243 aprint_error_dev(self, 240 aprint_error_dev(self,
244 "WARNING: couldn't open always-on device\n"); 241 "WARNING: couldn't open always-on device\n");
245 sc->sc_alwayson = false; 242 sc->sc_alwayson = false;
246 } 243 }
247 } 244 }
248} 245}
249 246
250static int 247static int
251ums_activate(device_t self, enum devact act) 248ums_activate(device_t self, enum devact act)
252{ 249{
253 struct ums_softc *sc = device_private(self); 250 struct ums_softc *sc = device_private(self);
254 251
@@ -269,89 +266,89 @@ ums_childdet(device_t self, device_t chi @@ -269,89 +266,89 @@ ums_childdet(device_t self, device_t chi
269 KASSERT(sc->sc_ms.hidms_wsmousedev == child); 266 KASSERT(sc->sc_ms.hidms_wsmousedev == child);
270 sc->sc_ms.hidms_wsmousedev = NULL; 267 sc->sc_ms.hidms_wsmousedev = NULL;
271} 268}
272 269
273static int 270static int
274ums_detach(device_t self, int flags) 271ums_detach(device_t self, int flags)
275{ 272{
276 struct ums_softc *sc = device_private(self); 273 struct ums_softc *sc = device_private(self);
277 int rv = 0; 274 int rv = 0;
278 275
279 DPRINTF(("ums_detach: sc=%p flags=%d\n", sc, flags)); 276 DPRINTF(("ums_detach: sc=%p flags=%d\n", sc, flags));
280 277
281 if (sc->sc_alwayson) 278 if (sc->sc_alwayson)
282 uhidev_close(&sc->sc_hdev); 279 uhidev_close(sc->sc_hdev);
283 280
284 /* No need to do reference counting of ums, wsmouse has all the goo. */ 281 /* No need to do reference counting of ums, wsmouse has all the goo. */
285 if (sc->sc_ms.hidms_wsmousedev != NULL) 282 if (sc->sc_ms.hidms_wsmousedev != NULL)
286 rv = config_detach(sc->sc_ms.hidms_wsmousedev, flags); 283 rv = config_detach(sc->sc_ms.hidms_wsmousedev, flags);
287 284
288 pmf_device_deregister(self); 285 pmf_device_deregister(self);
289 286
290 return rv; 287 return rv;
291} 288}
292 289
293Static void 290Static void
294ums_intr(struct uhidev *addr, void *ibuf, u_int len) 291ums_intr(void *cookie, void *ibuf, u_int len)
295{ 292{
296 struct ums_softc *sc = (struct ums_softc *)addr; 293 struct ums_softc *sc = cookie;
297 294
298 if (sc->sc_enabled) 295 if (sc->sc_enabled)
299 hidms_intr(&sc->sc_ms, ibuf, len); 296 hidms_intr(&sc->sc_ms, ibuf, len);
300} 297}
301 298
302Static int 299Static int
303ums_enable(void *v) 300ums_enable(void *v)
304{ 301{
305 struct ums_softc *sc = v; 302 struct ums_softc *sc = v;
306 int error = 0; 303 int error = 0;
307 304
308 DPRINTFN(1,("ums_enable: sc=%p\n", sc)); 305 DPRINTFN(1,("ums_enable: sc=%p\n", sc));
309 306
310 if (sc->sc_dying) 307 if (sc->sc_dying)
311 return EIO; 308 return EIO;
312 309
313 if (sc->sc_enabled) 310 if (sc->sc_enabled)
314 return EBUSY; 311 return EBUSY;
315 312
316 sc->sc_enabled = 1; 313 sc->sc_enabled = 1;
317 sc->sc_ms.hidms_buttons = 0; 314 sc->sc_ms.hidms_buttons = 0;
318 315
319 if (!sc->sc_alwayson) { 316 if (!sc->sc_alwayson) {
320 error = uhidev_open(&sc->sc_hdev); 317 error = uhidev_open(sc->sc_hdev, &ums_intr, sc);
321 if (error) 318 if (error)
322 sc->sc_enabled = 0; 319 sc->sc_enabled = 0;
323 } 320 }
324 321
325 return error; 322 return error;
326} 323}
327 324
328Static void 325Static void
329ums_disable(void *v) 326ums_disable(void *v)
330{ 327{
331 struct ums_softc *sc = v; 328 struct ums_softc *sc = v;
332 329
333 DPRINTFN(1,("ums_disable: sc=%p\n", sc)); 330 DPRINTFN(1,("ums_disable: sc=%p\n", sc));
334#ifdef DIAGNOSTIC 331#ifdef DIAGNOSTIC
335 if (!sc->sc_enabled) { 332 if (!sc->sc_enabled) {
336 printf("ums_disable: not enabled\n"); 333 printf("ums_disable: not enabled\n");
337 return; 334 return;
338 } 335 }
339#endif 336#endif
340 337
341 if (sc->sc_enabled) { 338 if (sc->sc_enabled) {
342 sc->sc_enabled = 0; 339 sc->sc_enabled = 0;
343 if (!sc->sc_alwayson) 340 if (!sc->sc_alwayson)
344 uhidev_close(&sc->sc_hdev); 341 uhidev_close(sc->sc_hdev);
345 } 342 }
346} 343}
347 344
348Static int 345Static int
349ums_ioctl(void *v, u_long cmd, void *data, int flag, 346ums_ioctl(void *v, u_long cmd, void *data, int flag,
350 struct lwp *l) 347 struct lwp *l)
351 348
352{ 349{
353 struct ums_softc *sc = v; 350 struct ums_softc *sc = v;
354 int error; 351 int error;
355 352
356 if (sc->sc_ms.flags & HIDMS_ABS) { 353 if (sc->sc_ms.flags & HIDMS_ABS) {
357 error = tpcalib_ioctl(&sc->sc_ms.sc_tpcalib, cmd, data, 354 error = tpcalib_ioctl(&sc->sc_ms.sc_tpcalib, cmd, data,

cvs diff -r1.22 -r1.23 src/sys/dev/usb/uthum.c (expand / switch to unified diff)

--- src/sys/dev/usb/uthum.c 2022/03/28 12:43:12 1.22
+++ src/sys/dev/usb/uthum.c 2022/03/28 12:44:17 1.23
@@ -1,38 +1,38 @@ @@ -1,38 +1,38 @@
1/* $NetBSD: uthum.c,v 1.22 2022/03/28 12:43:12 riastradh Exp $ */ 1/* $NetBSD: uthum.c,v 1.23 2022/03/28 12:44:17 riastradh Exp $ */
2/* $OpenBSD: uthum.c,v 1.6 2010/01/03 18:43:02 deraadt Exp $ */ 2/* $OpenBSD: uthum.c,v 1.6 2010/01/03 18:43:02 deraadt Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2009 Yojiro UO <yuo@nui.org> 5 * Copyright (c) 2009 Yojiro UO <yuo@nui.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */ 18 */
19 19
20/* 20/*
21 * Driver for TEMPer and TEMPerHUM HID 21 * Driver for TEMPer and TEMPerHUM HID
22 */ 22 */
23 23
24#include <sys/cdefs.h> 24#include <sys/cdefs.h>
25__KERNEL_RCSID(0, "$NetBSD: uthum.c,v 1.22 2022/03/28 12:43:12 riastradh Exp $"); 25__KERNEL_RCSID(0, "$NetBSD: uthum.c,v 1.23 2022/03/28 12:44:17 riastradh Exp $");
26 26
27#ifdef _KERNEL_OPT 27#ifdef _KERNEL_OPT
28#include "opt_usb.h" 28#include "opt_usb.h"
29#endif 29#endif
30 30
31#include <sys/param.h> 31#include <sys/param.h>
32#include <sys/proc.h> 32#include <sys/proc.h>
33#include <sys/systm.h> 33#include <sys/systm.h>
34#include <sys/kernel.h> 34#include <sys/kernel.h>
35#include <sys/device.h> 35#include <sys/device.h>
36#include <sys/conf.h> 36#include <sys/conf.h>
37 37
38#include <dev/sysmon/sysmonvar.h> 38#include <dev/sysmon/sysmonvar.h>
@@ -64,27 +64,28 @@ static const uint8_t cmd_start[8] = @@ -64,27 +64,28 @@ static const uint8_t cmd_start[8] =
64static const uint8_t cmd_end[8] = 64static const uint8_t cmd_end[8] =
65 { 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x00, 0x01, 0x00 }; 65 { 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x00, 0x01, 0x00 };
66 66
67/* sensors */ 67/* sensors */
68#define UTHUM_TEMP 0 68#define UTHUM_TEMP 0
69#define UTHUM_HUMIDITY 1 69#define UTHUM_HUMIDITY 1
70#define UTHUM_MAX_SENSORS 2 70#define UTHUM_MAX_SENSORS 2
71 71
72#define UTHUM_TYPE_UNKNOWN 0 72#define UTHUM_TYPE_UNKNOWN 0
73#define UTHUM_TYPE_SHT1x 1 73#define UTHUM_TYPE_SHT1x 1
74#define UTHUM_TYPE_TEMPER 2 74#define UTHUM_TYPE_TEMPER 2
75 75
76struct uthum_softc { 76struct uthum_softc {
77 struct uhidev sc_hdev; 77 device_t sc_dev;
 78 struct uhidev * sc_hdev;
78 struct usbd_device * sc_udev; 79 struct usbd_device * sc_udev;
79 u_char sc_dying; 80 u_char sc_dying;
80 uint16_t sc_flag; 81 uint16_t sc_flag;
81 int sc_sensortype; 82 int sc_sensortype;
82 83
83 /* uhidev parameters */ 84 /* uhidev parameters */
84 size_t sc_flen; /* feature report length */ 85 size_t sc_flen; /* feature report length */
85 size_t sc_olen; /* output report length */ 86 size_t sc_olen; /* output report length */
86 87
87 /* sensor framework */ 88 /* sensor framework */
88 struct sysmon_envsys *sc_sme; 89 struct sysmon_envsys *sc_sme;
89 envsys_data_t sc_sensor[UTHUM_MAX_SENSORS]; 90 envsys_data_t sc_sensor[UTHUM_MAX_SENSORS];
90 91
@@ -99,68 +100,64 @@ static const struct usb_devno uthum_devs @@ -99,68 +100,64 @@ static const struct usb_devno uthum_devs
99#define uthum_lookup(v, p) usb_lookup(uthum_devs, v, p) 100#define uthum_lookup(v, p) usb_lookup(uthum_devs, v, p)
100 101
101static int uthum_match(device_t, cfdata_t, void *); 102static int uthum_match(device_t, cfdata_t, void *);
102static void uthum_attach(device_t, device_t, void *); 103static void uthum_attach(device_t, device_t, void *);
103static int uthum_detach(device_t, int); 104static int uthum_detach(device_t, int);
104static int uthum_activate(device_t, enum devact); 105static int uthum_activate(device_t, enum devact);
105 106
106static int uthum_read_data(struct uthum_softc *, uint8_t, uint8_t *, size_t, int); 107static int uthum_read_data(struct uthum_softc *, uint8_t, uint8_t *, size_t, int);
107static int uthum_check_sensortype(struct uthum_softc *); 108static int uthum_check_sensortype(struct uthum_softc *);
108static int uthum_temper_temp(uint8_t, uint8_t); 109static int uthum_temper_temp(uint8_t, uint8_t);
109static int uthum_sht1x_temp(uint8_t, uint8_t); 110static int uthum_sht1x_temp(uint8_t, uint8_t);
110static int uthum_sht1x_rh(unsigned int, int); 111static int uthum_sht1x_rh(unsigned int, int);
111 112
112static void uthum_intr(struct uhidev *, void *, u_int); 
113static void uthum_refresh(struct sysmon_envsys *, envsys_data_t *); 113static void uthum_refresh(struct sysmon_envsys *, envsys_data_t *);
114 114
115 115
116CFATTACH_DECL_NEW(uthum, sizeof(struct uthum_softc), uthum_match, uthum_attach, 116CFATTACH_DECL_NEW(uthum, sizeof(struct uthum_softc), uthum_match, uthum_attach,
117 uthum_detach, uthum_activate); 117 uthum_detach, uthum_activate);
118 118
119static int 119static int
120uthum_match(device_t parent, cfdata_t match, void *aux) 120uthum_match(device_t parent, cfdata_t match, void *aux)
121{ 121{
122 struct uhidev_attach_arg *uha = aux; 122 struct uhidev_attach_arg *uha = aux;
123 123
124 return uthum_lookup(uha->uiaa->uiaa_vendor, uha->uiaa->uiaa_product) 124 return uthum_lookup(uha->uiaa->uiaa_vendor, uha->uiaa->uiaa_product)
125 != NULL ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 125 != NULL ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
126} 126}
127 127
128static void 128static void
129uthum_attach(device_t parent, device_t self, void *aux) 129uthum_attach(device_t parent, device_t self, void *aux)
130{ 130{
131 struct uthum_softc *sc = device_private(self); 131 struct uthum_softc *sc = device_private(self);
132 struct uhidev_attach_arg *uha = aux; 132 struct uhidev_attach_arg *uha = aux;
133 struct usbd_device *dev = uha->uiaa->uiaa_device; 133 struct usbd_device *dev = uha->uiaa->uiaa_device;
134 int size, repid; 134 int size, repid;
135 void *desc; 135 void *desc;
136 136
 137 sc->sc_dev = self;
 138 sc->sc_hdev = uha->parent;
137 sc->sc_udev = dev; 139 sc->sc_udev = dev;
138 sc->sc_hdev.sc_dev = self; 
139 sc->sc_hdev.sc_intr = uthum_intr; 
140 sc->sc_hdev.sc_parent = uha->parent; 
141 sc->sc_hdev.sc_report_id = uha->reportid; 
142 sc->sc_num_sensors = 0; 140 sc->sc_num_sensors = 0;
143 141
144 aprint_normal("\n"); 142 aprint_normal("\n");
145 aprint_naive("\n"); 143 aprint_naive("\n");
146 144
147 uhidev_get_report_desc(uha->parent, &desc, &size); 145 uhidev_get_report_desc(uha->parent, &desc, &size);
148 repid = uha->reportid; 146 repid = uha->reportid;
149 sc->sc_olen = hid_report_size(desc, size, hid_output, repid); 147 sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
150 sc->sc_flen = hid_report_size(desc, size, hid_feature, repid); 148 sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);
151 149
152 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 150 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
153 sc->sc_hdev.sc_dev); 
154 151
155 if (sc->sc_flen < 32) { 152 if (sc->sc_flen < 32) {
156 /* not sensor interface, just attach */ 153 /* not sensor interface, just attach */
157 return; 154 return;
158 } 155 }
159 156
160 sc->sc_sensortype = uthum_check_sensortype(sc); 157 sc->sc_sensortype = uthum_check_sensortype(sc);
161 158
162 /* attach sensor */ 159 /* attach sensor */
163 sc->sc_sme = sysmon_envsys_create(); 160 sc->sc_sme = sysmon_envsys_create();
164 sc->sc_sme->sme_name = device_xname(self); 161 sc->sc_sme->sme_name = device_xname(self);
165 162
166 switch (sc->sc_sensortype) { 163 switch (sc->sc_sensortype) {
@@ -220,96 +217,89 @@ uthum_attach(device_t parent, device_t s @@ -220,96 +217,89 @@ uthum_attach(device_t parent, device_t s
220} 217}
221 218
222static int 219static int
223uthum_detach(device_t self, int flags) 220uthum_detach(device_t self, int flags)
224{ 221{
225 struct uthum_softc *sc = device_private(self); 222 struct uthum_softc *sc = device_private(self);
226 int rv = 0; 223 int rv = 0;
227 224
228 sc->sc_dying = 1; 225 sc->sc_dying = 1;
229 226
230 if (sc->sc_sme != NULL) 227 if (sc->sc_sme != NULL)
231 sysmon_envsys_unregister(sc->sc_sme); 228 sysmon_envsys_unregister(sc->sc_sme);
232 229
233 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 230 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
234 sc->sc_hdev.sc_dev); 
235 231
236 return rv; 232 return rv;
237} 233}
238 234
239static int 235static int
240uthum_activate(device_t self, enum devact act) 236uthum_activate(device_t self, enum devact act)
241{ 237{
242 struct uthum_softc *sc = device_private(self); 238 struct uthum_softc *sc = device_private(self);
243 239
244 switch (act) { 240 switch (act) {
245 case DVACT_DEACTIVATE: 241 case DVACT_DEACTIVATE:
246 sc->sc_dying = 1; 242 sc->sc_dying = 1;
247 break; 243 break;
248 } 244 }
249 return 0; 245 return 0;
250} 246}
251 247
252static void 
253uthum_intr(struct uhidev *addr, void *ibuf, u_int len) 
254{ 
255 /* do nothing */ 
256} 
257 
258static int 248static int
259uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf, 249uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf,
260 size_t len, int need_delay) 250 size_t len, int need_delay)
261{ 251{
262 int i; 252 int i;
263 uint8_t cmdbuf[32], report[256]; 253 uint8_t cmdbuf[32], report[256];
264 size_t olen, flen; 254 size_t olen, flen;
265 255
266 /* if return buffer is null, do nothing */ 256 /* if return buffer is null, do nothing */
267 if ((buf == NULL) || len == 0) 257 if ((buf == NULL) || len == 0)
268 return 0; 258 return 0;
269 259
270 olen = uimin(sc->sc_olen, sizeof(cmdbuf)); 260 olen = uimin(sc->sc_olen, sizeof(cmdbuf));
271 261
272 /* issue query */ 262 /* issue query */
273 memset(cmdbuf, 0, sizeof(cmdbuf)); 263 memset(cmdbuf, 0, sizeof(cmdbuf));
274 memcpy(cmdbuf, cmd_start, sizeof(cmd_start)); 264 memcpy(cmdbuf, cmd_start, sizeof(cmd_start));
275 if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, 265 if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
276 cmdbuf, olen)) 266 cmdbuf, olen))
277 return EIO; 267 return EIO;
278 268
279 memset(cmdbuf, 0, sizeof(cmdbuf)); 269 memset(cmdbuf, 0, sizeof(cmdbuf));
280 cmdbuf[0] = target_cmd; 270 cmdbuf[0] = target_cmd;
281 if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, 271 if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
282 cmdbuf, olen)) 272 cmdbuf, olen))
283 return EIO; 273 return EIO;
284 274
285 memset(cmdbuf, 0, sizeof(cmdbuf)); 275 memset(cmdbuf, 0, sizeof(cmdbuf));
286 for (i = 0; i < 7; i++) { 276 for (i = 0; i < 7; i++) {
287 if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, 277 if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
288 cmdbuf, olen)) 278 cmdbuf, olen))
289 return EIO; 279 return EIO;
290 } 280 }
291 memcpy(cmdbuf, cmd_end, sizeof(cmd_end)); 281 memcpy(cmdbuf, cmd_end, sizeof(cmd_end));
292 if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, 282 if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
293 cmdbuf, olen)) 283 cmdbuf, olen))
294 return EIO; 284 return EIO;
295 285
296 /* wait if required */ 286 /* wait if required */
297 if (need_delay > 1) 287 if (need_delay > 1)
298 kpause("uthum", false, (need_delay*hz+999)/1000 + 1, NULL); 288 kpause("uthum", false, (need_delay*hz+999)/1000 + 1, NULL);
299 289
300 /* get answer */ 290 /* get answer */
301 flen = uimin(sc->sc_flen, sizeof(report)); 291 flen = uimin(sc->sc_flen, sizeof(report));
302 if (uhidev_get_report(&sc->sc_hdev, UHID_FEATURE_REPORT, 292 if (uhidev_get_report(sc->sc_hdev, UHID_FEATURE_REPORT,
303 report, flen)) 293 report, flen))
304 return EIO; 294 return EIO;
305 memcpy(buf, report, len); 295 memcpy(buf, report, len);
306 return 0; 296 return 0;
307} 297}
308 298
309static int 299static int
310uthum_check_sensortype(struct uthum_softc *sc) 300uthum_check_sensortype(struct uthum_softc *sc)
311{ 301{
312 uint8_t buf[8]; 302 uint8_t buf[8];
313 static uint8_t sht1x_sig0[] = 303 static uint8_t sht1x_sig0[] =
314 { 0x57, 0x5a, 0x13, 0x00, 0x14, 0x00, 0x53, 0x00 }; 304 { 0x57, 0x5a, 0x13, 0x00, 0x14, 0x00, 0x53, 0x00 };
315 static uint8_t sht1x_sig1[] = 305 static uint8_t sht1x_sig1[] =

cvs diff -r1.14 -r1.15 src/sys/dev/usb/uts.c (expand / switch to unified diff)

--- src/sys/dev/usb/uts.c 2021/08/07 16:19:17 1.14
+++ src/sys/dev/usb/uts.c 2022/03/28 12:44:17 1.15
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uts.c,v 1.14 2021/08/07 16:19:17 thorpej Exp $ */ 1/* $NetBSD: uts.c,v 1.15 2022/03/28 12:44:17 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2012 The NetBSD Foundation, Inc. 4 * Copyright (c) 2012 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Pierre Pronchery (khorben@defora.org). 8 * by Pierre Pronchery (khorben@defora.org).
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -24,27 +24,27 @@ @@ -24,27 +24,27 @@
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * USB generic Touch Screen driver. 33 * USB generic Touch Screen driver.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: uts.c,v 1.14 2021/08/07 16:19:17 thorpej Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: uts.c,v 1.15 2022/03/28 12:44:17 riastradh Exp $");
38 38
39#ifdef _KERNEL_OPT 39#ifdef _KERNEL_OPT
40#include "opt_usb.h" 40#include "opt_usb.h"
41#endif 41#endif
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/systm.h> 44#include <sys/systm.h>
45#include <sys/kernel.h> 45#include <sys/kernel.h>
46#include <sys/device.h> 46#include <sys/device.h>
47#include <sys/ioctl.h> 47#include <sys/ioctl.h>
48#include <sys/vnode.h> 48#include <sys/vnode.h>
49 49
50#include <dev/usb/usb.h> 50#include <dev/usb/usb.h>
@@ -62,47 +62,48 @@ __KERNEL_RCSID(0, "$NetBSD: uts.c,v 1.14 @@ -62,47 +62,48 @@ __KERNEL_RCSID(0, "$NetBSD: uts.c,v 1.14
62#include <dev/wscons/tpcalibvar.h> 62#include <dev/wscons/tpcalibvar.h>
63 63
64#ifdef UTS_DEBUG 64#ifdef UTS_DEBUG
65#define DPRINTF(x) if (utsdebug) printf x 65#define DPRINTF(x) if (utsdebug) printf x
66#define DPRINTFN(n,x) if (utsdebug>(n)) printf x 66#define DPRINTFN(n,x) if (utsdebug>(n)) printf x
67int utsdebug = 0; 67int utsdebug = 0;
68#else 68#else
69#define DPRINTF(x) 69#define DPRINTF(x)
70#define DPRINTFN(n,x) 70#define DPRINTFN(n,x)
71#endif 71#endif
72 72
73 73
74struct uts_softc { 74struct uts_softc {
75 struct uhidev sc_hdev; 75 device_t sc_dev;
 76 struct uhidev *sc_hdev;
76 77
77 struct hid_location sc_loc_x, sc_loc_y, sc_loc_z; 78 struct hid_location sc_loc_x, sc_loc_y, sc_loc_z;
78 struct hid_location sc_loc_btn; 79 struct hid_location sc_loc_btn;
79 80
80 int sc_enabled; 81 int sc_enabled;
81 82
82 int flags; /* device configuration */ 83 int flags; /* device configuration */
83#define UTS_ABS 0x1 /* absolute position */ 84#define UTS_ABS 0x1 /* absolute position */
84 85
85 uint32_t sc_buttons; /* touchscreen button status */ 86 uint32_t sc_buttons; /* touchscreen button status */
86 device_t sc_wsmousedev; 87 device_t sc_wsmousedev;
87 struct tpcalib_softc sc_tpcalib; /* calibration */ 88 struct tpcalib_softc sc_tpcalib; /* calibration */
88 struct wsmouse_calibcoords sc_calibcoords; 89 struct wsmouse_calibcoords sc_calibcoords;
89 90
90 char sc_dying; 91 char sc_dying;
91}; 92};
92 93
93#define TSCREEN_FLAGS_MASK (HIO_CONST|HIO_RELATIVE) 94#define TSCREEN_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
94 95
95Static void uts_intr(struct uhidev *, void *, u_int); 96Static void uts_intr(void *, void *, u_int);
96 97
97Static int uts_enable(void *); 98Static int uts_enable(void *);
98Static void uts_disable(void *); 99Static void uts_disable(void *);
99Static int uts_ioctl(void *, u_long, void *, int, struct lwp *); 100Static int uts_ioctl(void *, u_long, void *, int, struct lwp *);
100 101
101Static const struct wsmouse_accessops uts_accessops = { 102Static const struct wsmouse_accessops uts_accessops = {
102 uts_enable, 103 uts_enable,
103 uts_ioctl, 104 uts_ioctl,
104 uts_disable, 105 uts_disable,
105}; 106};
106 107
107Static int uts_match(device_t, cfdata_t, void *); 108Static int uts_match(device_t, cfdata_t, void *);
108Static void uts_attach(device_t, device_t, void *); 109Static void uts_attach(device_t, device_t, void *);
@@ -136,95 +137,93 @@ Static void @@ -136,95 +137,93 @@ Static void
136uts_attach(device_t parent, device_t self, void *aux) 137uts_attach(device_t parent, device_t self, void *aux)
137{ 138{
138 struct uts_softc *sc = device_private(self); 139 struct uts_softc *sc = device_private(self);
139 struct uhidev_attach_arg *uha = aux; 140 struct uhidev_attach_arg *uha = aux;
140 struct wsmousedev_attach_args a; 141 struct wsmousedev_attach_args a;
141 int size; 142 int size;
142 void *desc; 143 void *desc;
143 uint32_t flags; 144 uint32_t flags;
144 struct hid_data * d; 145 struct hid_data * d;
145 struct hid_item item; 146 struct hid_item item;
146 147
147 aprint_normal("\n"); 148 aprint_normal("\n");
148 149
149 sc->sc_hdev.sc_dev = self; 150 sc->sc_dev = self;
150 sc->sc_hdev.sc_intr = uts_intr; 151 sc->sc_hdev = uha->parent;
151 sc->sc_hdev.sc_parent = uha->parent; 
152 sc->sc_hdev.sc_report_id = uha->reportid; 
153 152
154 uhidev_get_report_desc(uha->parent, &desc, &size); 153 uhidev_get_report_desc(uha->parent, &desc, &size);
155 154
156 if (!pmf_device_register(self, NULL, NULL)) 155 if (!pmf_device_register(self, NULL, NULL))
157 aprint_error_dev(self, "couldn't establish power handler\n"); 156 aprint_error_dev(self, "couldn't establish power handler\n");
158 157
159 /* requires HID usage Generic_Desktop:X */ 158 /* requires HID usage Generic_Desktop:X */
160 if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), 159 if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
161 uha->reportid, hid_input, &sc->sc_loc_x, &flags)) { 160 uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
162 aprint_error_dev(sc->sc_hdev.sc_dev, 161 aprint_error_dev(sc->sc_dev,
163 "touchscreen has no X report\n"); 162 "touchscreen has no X report\n");
164 return; 163 return;
165 } 164 }
166 switch (flags & TSCREEN_FLAGS_MASK) { 165 switch (flags & TSCREEN_FLAGS_MASK) {
167 case 0: 166 case 0:
168 sc->flags |= UTS_ABS; 167 sc->flags |= UTS_ABS;
169 break; 168 break;
170 case HIO_RELATIVE: 169 case HIO_RELATIVE:
171 break; 170 break;
172 default: 171 default:
173 aprint_error_dev(sc->sc_hdev.sc_dev, 172 aprint_error_dev(sc->sc_dev,
174 "X report 0x%04x not supported\n", flags); 173 "X report 0x%04x not supported\n", flags);
175 return; 174 return;
176 } 175 }
177 176
178 /* requires HID usage Generic_Desktop:Y */ 177 /* requires HID usage Generic_Desktop:Y */
179 if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), 178 if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
180 uha->reportid, hid_input, &sc->sc_loc_y, &flags)) { 179 uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
181 aprint_error_dev(sc->sc_hdev.sc_dev, 180 aprint_error_dev(sc->sc_dev,
182 "touchscreen has no Y report\n"); 181 "touchscreen has no Y report\n");
183 return; 182 return;
184 } 183 }
185 switch (flags & TSCREEN_FLAGS_MASK) { 184 switch (flags & TSCREEN_FLAGS_MASK) {
186 case 0: 185 case 0:
187 sc->flags |= UTS_ABS; 186 sc->flags |= UTS_ABS;
188 break; 187 break;
189 case HIO_RELATIVE: 188 case HIO_RELATIVE:
190 break; 189 break;
191 default: 190 default:
192 aprint_error_dev(sc->sc_hdev.sc_dev, 191 aprint_error_dev(sc->sc_dev,
193 "Y report 0x%04x not supported\n", flags); 192 "Y report 0x%04x not supported\n", flags);
194 return; 193 return;
195 } 194 }
196 195
197 /* requires HID usage Digitizer:Tip_Switch */ 196 /* requires HID usage Digitizer:Tip_Switch */
198 if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH), 197 if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH),
199 uha->reportid, hid_input, &sc->sc_loc_btn, 0)) { 198 uha->reportid, hid_input, &sc->sc_loc_btn, 0)) {
200 aprint_error_dev(sc->sc_hdev.sc_dev, 199 aprint_error_dev(sc->sc_dev,
201 "touchscreen has no tip switch report\n"); 200 "touchscreen has no tip switch report\n");
202 return; 201 return;
203 } 202 }
204 203
205 /* requires HID usage Digitizer:In_Range */ 204 /* requires HID usage Digitizer:In_Range */
206 if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_IN_RANGE), 205 if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_IN_RANGE),
207 uha->reportid, hid_input, &sc->sc_loc_z, &flags)) { 206 uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
208 if (uha->uiaa->uiaa_vendor == USB_VENDOR_ELAN) { 207 if (uha->uiaa->uiaa_vendor == USB_VENDOR_ELAN) {
209 /* 208 /*
210 * XXX 209 * XXX
211 * ELAN touchscreens error out here but still return 210 * ELAN touchscreens error out here but still return
212 * valid data 211 * valid data
213 */ 212 */
214 aprint_debug_dev(sc->sc_hdev.sc_dev, 213 aprint_debug_dev(sc->sc_dev,
215 "ELAN touchscreen found, working around bug.\n"); 214 "ELAN touchscreen found, working around bug.\n");
216 } else { 215 } else {
217 aprint_error_dev(sc->sc_hdev.sc_dev, 216 aprint_error_dev(sc->sc_dev,
218 "touchscreen has no range report\n"); 217 "touchscreen has no range report\n");
219 return; 218 return;
220 } 219 }
221 } 220 }
222 221
223 /* multi-touch support would need HUD_CONTACTID and HUD_CONTACTMAX */ 222 /* multi-touch support would need HUD_CONTACTID and HUD_CONTACTMAX */
224 223
225#ifdef UTS_DEBUG 224#ifdef UTS_DEBUG
226 DPRINTF(("uts_attach: sc=%p\n", sc)); 225 DPRINTF(("uts_attach: sc=%p\n", sc));
227 DPRINTF(("uts_attach: X\t%d/%d\n", 226 DPRINTF(("uts_attach: X\t%d/%d\n",
228 sc->sc_loc_x.pos, sc->sc_loc_x.size)); 227 sc->sc_loc_x.pos, sc->sc_loc_x.size));
229 DPRINTF(("uts_attach: Y\t%d/%d\n", 228 DPRINTF(("uts_attach: Y\t%d/%d\n",
230 sc->sc_loc_y.pos, sc->sc_loc_y.size)); 229 sc->sc_loc_y.pos, sc->sc_loc_y.size));
@@ -237,27 +236,27 @@ uts_attach(device_t parent, device_t sel @@ -237,27 +236,27 @@ uts_attach(device_t parent, device_t sel
237 236
238 sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint, CFARGS_NONE); 237 sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint, CFARGS_NONE);
239 238
240 /* calibrate the touchscreen */ 239 /* calibrate the touchscreen */
241 memset(&sc->sc_calibcoords, 0, sizeof(sc->sc_calibcoords)); 240 memset(&sc->sc_calibcoords, 0, sizeof(sc->sc_calibcoords));
242 sc->sc_calibcoords.maxx = 4095; 241 sc->sc_calibcoords.maxx = 4095;
243 sc->sc_calibcoords.maxy = 4095; 242 sc->sc_calibcoords.maxy = 4095;
244 sc->sc_calibcoords.samplelen = WSMOUSE_CALIBCOORDS_RESET; 243 sc->sc_calibcoords.samplelen = WSMOUSE_CALIBCOORDS_RESET;
245 d = hid_start_parse(desc, size, hid_input); 244 d = hid_start_parse(desc, size, hid_input);
246 if (d != NULL) { 245 if (d != NULL) {
247 while (hid_get_item(d, &item)) { 246 while (hid_get_item(d, &item)) {
248 if (item.kind != hid_input 247 if (item.kind != hid_input
249 || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP 248 || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP
250 || item.report_ID != sc->sc_hdev.sc_report_id) 249 || item.report_ID != uha->reportid)
251 continue; 250 continue;
252 if (HID_GET_USAGE(item.usage) == HUG_X) { 251 if (HID_GET_USAGE(item.usage) == HUG_X) {
253 sc->sc_calibcoords.minx = item.logical_minimum; 252 sc->sc_calibcoords.minx = item.logical_minimum;
254 sc->sc_calibcoords.maxx = item.logical_maximum; 253 sc->sc_calibcoords.maxx = item.logical_maximum;
255 } 254 }
256 if (HID_GET_USAGE(item.usage) == HUG_Y) { 255 if (HID_GET_USAGE(item.usage) == HUG_Y) {
257 sc->sc_calibcoords.miny = item.logical_minimum; 256 sc->sc_calibcoords.miny = item.logical_minimum;
258 sc->sc_calibcoords.maxy = item.logical_maximum; 257 sc->sc_calibcoords.maxy = item.logical_maximum;
259 } 258 }
260 } 259 }
261 hid_end_parse(d); 260 hid_end_parse(d);
262 } 261 }
263 tpcalib_init(&sc->sc_tpcalib); 262 tpcalib_init(&sc->sc_tpcalib);
@@ -312,70 +311,70 @@ uts_enable(void *v) @@ -312,70 +311,70 @@ uts_enable(void *v)
312 struct uts_softc *sc = v; 311 struct uts_softc *sc = v;
313 312
314 DPRINTFN(1,("uts_enable: sc=%p\n", sc)); 313 DPRINTFN(1,("uts_enable: sc=%p\n", sc));
315 314
316 if (sc->sc_dying) 315 if (sc->sc_dying)
317 return EIO; 316 return EIO;
318 317
319 if (sc->sc_enabled) 318 if (sc->sc_enabled)
320 return EBUSY; 319 return EBUSY;
321 320
322 sc->sc_enabled = 1; 321 sc->sc_enabled = 1;
323 sc->sc_buttons = 0; 322 sc->sc_buttons = 0;
324 323
325 return uhidev_open(&sc->sc_hdev); 324 return uhidev_open(sc->sc_hdev, &uts_intr, sc);
326} 325}
327 326
328Static void 327Static void
329uts_disable(void *v) 328uts_disable(void *v)
330{ 329{
331 struct uts_softc *sc = v; 330 struct uts_softc *sc = v;
332 331
333 DPRINTFN(1,("uts_disable: sc=%p\n", sc)); 332 DPRINTFN(1,("uts_disable: sc=%p\n", sc));
334#ifdef DIAGNOSTIC 333#ifdef DIAGNOSTIC
335 if (!sc->sc_enabled) { 334 if (!sc->sc_enabled) {
336 printf("uts_disable: not enabled\n"); 335 printf("uts_disable: not enabled\n");
337 return; 336 return;
338 } 337 }
339#endif 338#endif
340 339
341 sc->sc_enabled = 0; 340 sc->sc_enabled = 0;
342 uhidev_close(&sc->sc_hdev); 341 uhidev_close(sc->sc_hdev);
343} 342}
344 343
345Static int 344Static int
346uts_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 345uts_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
347{ 346{
348 struct uts_softc *sc = v; 347 struct uts_softc *sc = v;
349 348
350 switch (cmd) { 349 switch (cmd) {
351 case WSMOUSEIO_GTYPE: 350 case WSMOUSEIO_GTYPE:
352 if (sc->flags & UTS_ABS) 351 if (sc->flags & UTS_ABS)
353 *(u_int *)data = WSMOUSE_TYPE_TPANEL; 352 *(u_int *)data = WSMOUSE_TYPE_TPANEL;
354 else 353 else
355 *(u_int *)data = WSMOUSE_TYPE_USB; 354 *(u_int *)data = WSMOUSE_TYPE_USB;
356 return 0; 355 return 0;
357 case WSMOUSEIO_SCALIBCOORDS: 356 case WSMOUSEIO_SCALIBCOORDS:
358 case WSMOUSEIO_GCALIBCOORDS: 357 case WSMOUSEIO_GCALIBCOORDS:
359 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); 358 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l);
360 } 359 }
361 360
362 return EPASSTHROUGH; 361 return EPASSTHROUGH;
363} 362}
364 363
365Static void 364Static void
366uts_intr(struct uhidev *addr, void *ibuf, u_int len) 365uts_intr(void *cookie, void *ibuf, u_int len)
367{ 366{
368 struct uts_softc *sc = (struct uts_softc *)addr; 367 struct uts_softc *sc = cookie;
369 int dx, dy, dz; 368 int dx, dy, dz;
370 uint32_t buttons = 0; 369 uint32_t buttons = 0;
371 int flags, s; 370 int flags, s;
372 371
373 DPRINTFN(5,("uts_intr: len=%d\n", len)); 372 DPRINTFN(5,("uts_intr: len=%d\n", len));
374 373
375 flags = WSMOUSE_INPUT_DELTA | WSMOUSE_INPUT_ABSOLUTE_Z; 374 flags = WSMOUSE_INPUT_DELTA | WSMOUSE_INPUT_ABSOLUTE_Z;
376 375
377 dx = hid_get_data(ibuf, &sc->sc_loc_x); 376 dx = hid_get_data(ibuf, &sc->sc_loc_x);
378 if (sc->flags & UTS_ABS) { 377 if (sc->flags & UTS_ABS) {
379 flags |= (WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 378 flags |= (WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
380 dy = hid_get_data(ibuf, &sc->sc_loc_y); 379 dy = hid_get_data(ibuf, &sc->sc_loc_y);
381 tpcalib_trans(&sc->sc_tpcalib, dx, dy, &dx, &dy); 380 tpcalib_trans(&sc->sc_tpcalib, dx, dy, &dx, &dy);