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 modulesdiff -r1.28 -r1.29 src/sys/dev/usb/uatp.c
(riastradh)
--- 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 | |||
291 | static bool uatp_setup_sysctl_knob(struct uatp_softc *, int *, const char *, | 291 | static bool uatp_setup_sysctl_knob(struct uatp_softc *, int *, const char *, | |
292 | const char *); | 292 | const char *); | |
293 | static void uatp_childdet(device_t, device_t); | 293 | static void uatp_childdet(device_t, device_t); | |
294 | static int uatp_detach(device_t, int); | 294 | static int uatp_detach(device_t, int); | |
295 | static int uatp_activate(device_t, enum devact); | 295 | static int uatp_activate(device_t, enum devact); | |
296 | static int uatp_enable(void *); | 296 | static int uatp_enable(void *); | |
297 | static void uatp_disable(void *); | 297 | static void uatp_disable(void *); | |
298 | static int uatp_ioctl(void *, unsigned long, void *, int, struct lwp *); | 298 | static int uatp_ioctl(void *, unsigned long, void *, int, struct lwp *); | |
299 | static void geyser34_enable_raw_mode(struct uatp_softc *); | 299 | static void geyser34_enable_raw_mode(struct uatp_softc *); | |
300 | static void geyser34_initialize(struct uatp_softc *); | 300 | static void geyser34_initialize(struct uatp_softc *); | |
301 | static int geyser34_finalize(struct uatp_softc *); | 301 | static int geyser34_finalize(struct uatp_softc *); | |
302 | static void geyser34_deferred_reset(struct uatp_softc *); | 302 | static void geyser34_deferred_reset(struct uatp_softc *); | |
303 | static void geyser34_reset_task(void *); | 303 | static void geyser34_reset_task(void *); | |
304 | static void uatp_intr(struct uhidev *, void *, unsigned int); | 304 | static void uatp_intr(void *, void *, unsigned int); | |
305 | static bool base_sample_softc_flag(const struct uatp_softc *, const uint8_t *); | 305 | static bool base_sample_softc_flag(const struct uatp_softc *, const uint8_t *); | |
306 | static bool base_sample_input_flag(const struct uatp_softc *, const uint8_t *); | 306 | static bool base_sample_input_flag(const struct uatp_softc *, const uint8_t *); | |
307 | static void read_sample_1(uint8_t *, uint8_t *, const uint8_t *); | 307 | static void read_sample_1(uint8_t *, uint8_t *, const uint8_t *); | |
308 | static void read_sample_2(uint8_t *, uint8_t *, const uint8_t *); | 308 | static void read_sample_2(uint8_t *, uint8_t *, const uint8_t *); | |
309 | static void accumulate_sample_1(struct uatp_softc *); | 309 | static void accumulate_sample_1(struct uatp_softc *); | |
310 | static void accumulate_sample_2(struct uatp_softc *); | 310 | static void accumulate_sample_2(struct uatp_softc *); | |
311 | static void uatp_input(struct uatp_softc *, uint32_t, int, int, int, int); | 311 | static void uatp_input(struct uatp_softc *, uint32_t, int, int, int, int); | |
312 | static uint32_t uatp_tapped_buttons(struct uatp_softc *); | 312 | static uint32_t uatp_tapped_buttons(struct uatp_softc *); | |
313 | static bool interpret_input(struct uatp_softc *, int *, int *, int *, int *, | 313 | static bool interpret_input(struct uatp_softc *, int *, int *, int *, int *, | |
314 | uint32_t *); | 314 | uint32_t *); | |
315 | static unsigned int interpret_dimension(struct uatp_softc *, const int *, | 315 | static 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 *); | |
317 | static void tap_initialize(struct uatp_softc *); | 317 | static 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 | |||
488 | struct uatp_softc { | 488 | struct 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 | |||
691 | static device_t | 692 | static device_t | |
692 | uatp_dev(const struct uatp_softc *sc) | 693 | uatp_dev(const struct uatp_softc *sc) | |
693 | { | 694 | { | |
694 | return sc->sc_hdev.sc_dev; | 695 | return sc->sc_dev; | |
695 | } | 696 | } | |
696 | 697 | |||
697 | static uint8_t * | 698 | static uint8_t * | |
698 | uatp_x_sample(struct uatp_softc *sc) | 699 | uatp_x_sample(struct uatp_softc *sc) | |
699 | { | 700 | { | |
700 | return &sc->sc_sample[0]; | 701 | return &sc->sc_sample[0]; | |
701 | } | 702 | } | |
702 | 703 | |||
703 | static uint8_t * | 704 | static uint8_t * | |
704 | uatp_y_sample(struct uatp_softc *sc) | 705 | uatp_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 | |||
924 | static void | 925 | static void | |
925 | uatp_attach(device_t parent, device_t self, void *aux) | 926 | uatp_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 | |||
1258 | static void | 1255 | static void | |
1259 | uatp_disable(void *v) | 1256 | uatp_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 | |||
1277 | static int | 1274 | static int | |
1278 | uatp_ioctl(void *v, unsigned long cmd, void *data, int flag, struct lwp *p) | 1275 | uatp_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 | |||
1389 | geyser34_reset_task(void *arg) | 1386 | geyser34_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 | |||
1401 | static void | 1398 | static void | |
1402 | uatp_intr(struct uhidev *addr, void *ibuf, unsigned int len) | 1399 | uatp_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", |
--- 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 | |||
119 | struct ucycom_softc { | 119 | struct 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 | |||
175 | Static int ucycomparam(struct tty *, struct termios *); | 176 | Static int ucycomparam(struct tty *, struct termios *); | |
176 | Static void ucycomstart(struct tty *); | 177 | Static void ucycomstart(struct tty *); | |
177 | Static void ucycomstarttask(void *); | 178 | Static void ucycomstarttask(void *); | |
178 | Static void ucycomwritecb(struct usbd_xfer *, void *, usbd_status); | 179 | Static void ucycomwritecb(struct usbd_xfer *, void *, usbd_status); | |
179 | Static void ucycom_intr(struct uhidev *, void *, u_int); | 180 | Static void ucycom_intr(void *, void *, u_int); | |
180 | Static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t); | 181 | Static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t); | |
181 | Static void tiocm_to_ucycom(struct ucycom_softc *, u_long, int); | 182 | Static void tiocm_to_ucycom(struct ucycom_softc *, u_long, int); | |
182 | Static int ucycom_to_tiocm(struct ucycom_softc *); | 183 | Static int ucycom_to_tiocm(struct ucycom_softc *); | |
183 | Static void ucycom_set_status(struct ucycom_softc *); | 184 | Static void ucycom_set_status(struct ucycom_softc *); | |
184 | Static void ucycom_dtr(struct ucycom_softc *, int); | 185 | Static void ucycom_dtr(struct ucycom_softc *, int); | |
185 | #if 0 | 186 | #if 0 | |
186 | Static void ucycom_rts(struct ucycom_softc *, int); | 187 | Static void ucycom_rts(struct ucycom_softc *, int); | |
187 | #endif | 188 | #endif | |
188 | Static void ucycom_cleanup(struct ucycom_softc *); | 189 | Static void ucycom_cleanup(struct ucycom_softc *); | |
189 | 190 | |||
190 | #ifdef UCYCOM_DEBUG | 191 | #ifdef UCYCOM_DEBUG | |
191 | Static void ucycom_get_cfg(struct ucycom_softc *); | 192 | Static 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 | |||
217 | static void | 218 | static void | |
218 | ucycom_attach(device_t parent, device_t self, void *aux) | 219 | ucycom_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 | |||
609 | out: | 608 | out: | |
610 | splx(s); | 609 | splx(s); | |
611 | } | 610 | } | |
612 | 611 | |||
613 | Static void | 612 | Static void | |
614 | ucycomstarttask(void *cookie) | 613 | ucycomstarttask(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 | |||
631 | Static void | 630 | Static void | |
632 | ucycomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status) | 631 | ucycomwritecb(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 | |||
961 | Static void | 960 | Static void | |
962 | ucycom_intr(struct uhidev *addr, void *ibuf, u_int len) | 961 | ucycom_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 | |||
1022 | Static void | 1020 | Static 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 | |
1134 | Static void | 1132 | Static void | |
1135 | ucycom_get_cfg(struct ucycom_softc *sc) | 1133 | ucycom_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 | |||
1157 | Static void | 1155 | Static void | |
1158 | ucycom_cleanup(struct ucycom_softc *sc) | 1156 | ucycom_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 | } |
--- 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 | |
81 | int uhiddebug = 0; | 81 | int 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 | |||
87 | struct uhid_softc { | 87 | struct 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 | |||
147 | static void uhid_intr(struct uhidev *, void *, u_int); | 149 | static void uhid_intr(void *, void *, u_int); | |
148 | 150 | |||
149 | static int uhid_match(device_t, cfdata_t, void *); | 151 | static int uhid_match(device_t, cfdata_t, void *); | |
150 | static void uhid_attach(device_t, device_t, void *); | 152 | static void uhid_attach(device_t, device_t, void *); | |
151 | static int uhid_detach(device_t, int); | 153 | static int uhid_detach(device_t, int); | |
152 | 154 | |||
153 | CFATTACH_DECL_NEW(uhid, sizeof(struct uhid_softc), uhid_match, uhid_attach, | 155 | CFATTACH_DECL_NEW(uhid, sizeof(struct uhid_softc), uhid_match, uhid_attach, | |
154 | uhid_detach, NULL); | 156 | uhid_detach, NULL); | |
155 | 157 | |||
156 | static int | 158 | static int | |
157 | uhid_match(device_t parent, cfdata_t match, void *aux) | 159 | uhid_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 | |||
171 | static void | 173 | static void | |
172 | uhid_attach(device_t parent, device_t self, void *aux) | 174 | uhid_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 | |||
234 | static void | 235 | static void | |
235 | uhid_intr(struct uhidev *addr, void *data, u_int len) | 236 | uhid_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 | |||
321 | fail1: selnotify(&sc->sc_rsel, POLLHUP, 0); | 322 | fail1: 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 | |||
362 | static int | 363 | static int | |
363 | uhidclose(dev_t dev, int flag, int mode, struct lwp *l) | 364 | uhidclose(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) | |||
412 | static int | 413 | static int | |
413 | uhidread(dev_t dev, struct uio *uio, int flag) | 414 | uhidread(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 | |||
515 | static int | 516 | static int | |
516 | uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) | 517 | uhidioctl(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, |
--- 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 | |||
79 | struct uhidev_softc { | 79 | struct 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 | |||
162 | static void | 173 | static void | |
163 | uhidev_attach(device_t parent, device_t self, void *aux) | 174 | uhidev_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 | |||
449 | static int | 454 | static int | |
450 | uhidev_maxrepid(void *buf, int len) | 455 | uhidev_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 | |||
491 | static void | 496 | static void | |
492 | uhidev_childdet(device_t self, device_t child) | 497 | uhidev_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 | |||
505 | static int | 518 | static int | |
506 | uhidev_detach(device_t self, int flags) | 519 | uhidev_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 | |||
578 | static void | 574 | static void | |
579 | uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) | 575 | uhidev_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 | |||
644 | void | 636 | void | |
645 | uhidev_get_report_desc(struct uhidev_softc *sc, void **desc, int *size) | 637 | uhidev_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 | |||
651 | static int | 645 | static int | |
652 | uhidev_config_enter(struct uhidev_softc *sc) | 646 | uhidev_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 | |||
906 | int | 900 | int | |
907 | uhidev_open(struct uhidev *scd) | 901 | uhidev_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 | |||
936 | out: if (error) { | 933 | out: 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 | |||
1075 | usbd_status | 1082 | usbd_status | |
1076 | uhidev_set_report(struct uhidev *scd, int type, void *data, int len) | 1083 | uhidev_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); |
--- 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 | |||
41 | struct uhidev_softc; | 38 | struct uhidev; | |
42 | ||||
43 | struct 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 | |||
55 | struct uhidev_attach_arg { | 40 | struct 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 | |||
62 | void uhidev_get_report_desc(struct uhidev_softc *, void **, int *); | 46 | void uhidev_get_report_desc(struct uhidev *, void **, int *); | |
63 | int uhidev_open(struct uhidev *); | 47 | int uhidev_open(struct uhidev *, void (*)(void *, void *, unsigned), void *); | |
64 | void uhidev_stop(struct uhidev *); | 48 | void uhidev_stop(struct uhidev *); | |
65 | void uhidev_close(struct uhidev *); | 49 | void uhidev_close(struct uhidev *); | |
66 | usbd_status uhidev_set_report(struct uhidev *, int, void *, int); | 50 | usbd_status uhidev_set_report(struct uhidev *, int, void *, int); | |
67 | usbd_status uhidev_get_report(struct uhidev *, int, void *, int); | 51 | usbd_status uhidev_get_report(struct uhidev *, int, void *, int); | |
68 | usbd_status uhidev_write(struct uhidev *, void *, int); | 52 | usbd_status uhidev_write(struct uhidev *, void *, int); | |
69 | usbd_status uhidev_write_async(struct uhidev *, void *, int, int, int, | 53 | usbd_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_ */ |
--- 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 | |||
237 | struct ukbd_softc { | 237 | struct 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) | |||
330 | Static int ukbd_is_console; | 332 | Static int ukbd_is_console; | |
331 | 333 | |||
332 | Static void ukbd_cngetc(void *, u_int *, int *); | 334 | Static void ukbd_cngetc(void *, u_int *, int *); | |
333 | Static void ukbd_cnpollc(void *, int); | 335 | Static void ukbd_cnpollc(void *, int); | |
334 | 336 | |||
335 | const struct wskbd_consops ukbd_consops = { | 337 | const 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 | |||
341 | Static const char *ukbd_parse_desc(struct ukbd_softc *); | 343 | Static const char *ukbd_parse_desc(struct ukbd_softc *); | |
342 | 344 | |||
343 | Static void ukbd_intr(struct uhidev *, void *, u_int); | 345 | Static void ukbd_intr(void *, void *, u_int); | |
344 | Static void ukbd_decode(struct ukbd_softc *, struct ukbd_data *); | 346 | Static void ukbd_decode(struct ukbd_softc *, struct ukbd_data *); | |
345 | Static void ukbd_delayed_decode(void *); | 347 | Static void ukbd_delayed_decode(void *); | |
346 | 348 | |||
347 | Static int ukbd_enable(void *, int); | 349 | Static int ukbd_enable(void *, int); | |
348 | Static void ukbd_set_leds(void *, int); | 350 | Static void ukbd_set_leds(void *, int); | |
349 | Static void ukbd_set_leds_task(void *); | 351 | Static void ukbd_set_leds_task(void *); | |
350 | Static void ukbd_delayed_leds_off(void *); | 352 | Static void ukbd_delayed_leds_off(void *); | |
351 | 353 | |||
352 | Static int ukbd_ioctl(void *, u_long, void *, int, struct lwp *); | 354 | Static 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) | |
354 | Static void ukbd_rawrepeat(void *v); | 356 | Static 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 | |||
402 | void | 404 | void | |
403 | ukbd_attach(device_t parent, device_t self, void *aux) | 405 | ukbd_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 | |||
506 | int | 507 | int | |
507 | ukbd_enable(void *v, int on) | 508 | ukbd_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 | |||
534 | static void | 535 | static void | |
535 | ukbd_childdet(device_t self, device_t child) | 536 | ukbd_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 | |||
596 | static void | 597 | static void | |
597 | ukbd_translate_keycodes(struct ukbd_softc *sc, struct ukbd_data *ud, | 598 | ukbd_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 | |||
622 | static uint16_t | 622 | static uint16_t | |
623 | ukbd_translate_modifier(struct ukbd_softc *sc, uint16_t key) | 623 | ukbd_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 | |||
643 | void | 643 | void | |
644 | ukbd_intr(struct uhidev *addr, void *ibuf, u_int len) | 644 | ukbd_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) | |
930 | void | 930 | void | |
931 | ukbd_rawrepeat(void *v) | 931 | ukbd_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 | |||
1053 | const char * | 1053 | const char * | |
1054 | ukbd_parse_desc(struct ukbd_softc *sc) | 1054 | ukbd_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 | } |
--- 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 | |
69 | int umsdebug = 0; | 69 | int 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 | |||
77 | struct ums_softc { | 77 | struct 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 | |||
88 | Static void ums_intr(struct uhidev *, void *, u_int); | 88 | Static void ums_intr(void *, void *, u_int); | |
89 | 89 | |||
90 | Static int ums_enable(void *); | 90 | Static int ums_enable(void *); | |
91 | Static void ums_disable(void *); | 91 | Static void ums_disable(void *); | |
92 | Static int ums_ioctl(void *, u_long, void *, int, struct lwp *); | 92 | Static int ums_ioctl(void *, u_long, void *, int, struct lwp *); | |
93 | 93 | |||
94 | static const struct wsmouse_accessops ums_accessops = { | 94 | static 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 | |||
100 | static int ums_match(device_t, cfdata_t, void *); | 100 | static int ums_match(device_t, cfdata_t, void *); | |
101 | static void ums_attach(device_t, device_t, void *); | 101 | static 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 | |||
136 | static void | 136 | static void | |
137 | ums_attach(device_t parent, device_t self, void *aux) | 137 | ums_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 | |||
250 | static int | 247 | static int | |
251 | ums_activate(device_t self, enum devact act) | 248 | ums_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 | |||
273 | static int | 270 | static int | |
274 | ums_detach(device_t self, int flags) | 271 | ums_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 | |||
293 | Static void | 290 | Static void | |
294 | ums_intr(struct uhidev *addr, void *ibuf, u_int len) | 291 | ums_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 | |||
302 | Static int | 299 | Static int | |
303 | ums_enable(void *v) | 300 | ums_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 | |||
328 | Static void | 325 | Static void | |
329 | ums_disable(void *v) | 326 | ums_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 | |||
348 | Static int | 345 | Static int | |
349 | ums_ioctl(void *v, u_long cmd, void *data, int flag, | 346 | ums_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, |
--- 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] = | |||
64 | static const uint8_t cmd_end[8] = | 64 | static 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 | |||
76 | struct uthum_softc { | 76 | struct 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 | |||
101 | static int uthum_match(device_t, cfdata_t, void *); | 102 | static int uthum_match(device_t, cfdata_t, void *); | |
102 | static void uthum_attach(device_t, device_t, void *); | 103 | static void uthum_attach(device_t, device_t, void *); | |
103 | static int uthum_detach(device_t, int); | 104 | static int uthum_detach(device_t, int); | |
104 | static int uthum_activate(device_t, enum devact); | 105 | static int uthum_activate(device_t, enum devact); | |
105 | 106 | |||
106 | static int uthum_read_data(struct uthum_softc *, uint8_t, uint8_t *, size_t, int); | 107 | static int uthum_read_data(struct uthum_softc *, uint8_t, uint8_t *, size_t, int); | |
107 | static int uthum_check_sensortype(struct uthum_softc *); | 108 | static int uthum_check_sensortype(struct uthum_softc *); | |
108 | static int uthum_temper_temp(uint8_t, uint8_t); | 109 | static int uthum_temper_temp(uint8_t, uint8_t); | |
109 | static int uthum_sht1x_temp(uint8_t, uint8_t); | 110 | static int uthum_sht1x_temp(uint8_t, uint8_t); | |
110 | static int uthum_sht1x_rh(unsigned int, int); | 111 | static int uthum_sht1x_rh(unsigned int, int); | |
111 | 112 | |||
112 | static void uthum_intr(struct uhidev *, void *, u_int); | |||
113 | static void uthum_refresh(struct sysmon_envsys *, envsys_data_t *); | 113 | static void uthum_refresh(struct sysmon_envsys *, envsys_data_t *); | |
114 | 114 | |||
115 | 115 | |||
116 | CFATTACH_DECL_NEW(uthum, sizeof(struct uthum_softc), uthum_match, uthum_attach, | 116 | CFATTACH_DECL_NEW(uthum, sizeof(struct uthum_softc), uthum_match, uthum_attach, | |
117 | uthum_detach, uthum_activate); | 117 | uthum_detach, uthum_activate); | |
118 | 118 | |||
119 | static int | 119 | static int | |
120 | uthum_match(device_t parent, cfdata_t match, void *aux) | 120 | uthum_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 | |||
128 | static void | 128 | static void | |
129 | uthum_attach(device_t parent, device_t self, void *aux) | 129 | uthum_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 | |||
222 | static int | 219 | static int | |
223 | uthum_detach(device_t self, int flags) | 220 | uthum_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 | |||
239 | static int | 235 | static int | |
240 | uthum_activate(device_t self, enum devact act) | 236 | uthum_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 | |||
252 | static void | |||
253 | uthum_intr(struct uhidev *addr, void *ibuf, u_int len) | |||
254 | { | |||
255 | /* do nothing */ | |||
256 | } | |||
257 | ||||
258 | static int | 248 | static int | |
259 | uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf, | 249 | uthum_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 | |||
309 | static int | 299 | static int | |
310 | uthum_check_sensortype(struct uthum_softc *sc) | 300 | uthum_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[] = |
--- 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 | |
67 | int utsdebug = 0; | 67 | int 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 | |||
74 | struct uts_softc { | 74 | struct 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 | |||
95 | Static void uts_intr(struct uhidev *, void *, u_int); | 96 | Static void uts_intr(void *, void *, u_int); | |
96 | 97 | |||
97 | Static int uts_enable(void *); | 98 | Static int uts_enable(void *); | |
98 | Static void uts_disable(void *); | 99 | Static void uts_disable(void *); | |
99 | Static int uts_ioctl(void *, u_long, void *, int, struct lwp *); | 100 | Static int uts_ioctl(void *, u_long, void *, int, struct lwp *); | |
100 | 101 | |||
101 | Static const struct wsmouse_accessops uts_accessops = { | 102 | Static 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 | |||
107 | Static int uts_match(device_t, cfdata_t, void *); | 108 | Static int uts_match(device_t, cfdata_t, void *); | |
108 | Static void uts_attach(device_t, device_t, void *); | 109 | Static void uts_attach(device_t, device_t, void *); | |
@@ -136,95 +137,93 @@ Static void | @@ -136,95 +137,93 @@ Static void | |||
136 | uts_attach(device_t parent, device_t self, void *aux) | 137 | uts_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 | |||
328 | Static void | 327 | Static void | |
329 | uts_disable(void *v) | 328 | uts_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 | |||
345 | Static int | 344 | Static int | |
346 | uts_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) | 345 | uts_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 | |||
365 | Static void | 364 | Static void | |
366 | uts_intr(struct uhidev *addr, void *ibuf, u_int len) | 365 | uts_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); |