Bug Summary

File:dev/usb/ubcmtp.c
Warning:line 421, column 7
Although the value stored to 'udd' is used in the enclosing expression, the value is never actually read from 'udd'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ubcmtp.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/ubcmtp.c
1/* $OpenBSD: ubcmtp.c,v 1.23 2021/11/22 22:12:37 jcs Exp $ */
2
3/*
4 * Copyright (c) 2013-2014, joshua stein <jcs@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * Apple USB multitouch trackpad (Broadcom BCM5974) driver
21 *
22 * Protocol info/magic from bcm5974 Linux driver by Henrik Rydberg, et al.
23 */
24
25#include <sys/param.h>
26#include <sys/device.h>
27#include <sys/errno.h>
28#include <sys/malloc.h>
29
30#include <sys/ioctl.h>
31#include <sys/systm.h>
32#include <sys/tty.h>
33
34#include <dev/usb/usb.h>
35#include <dev/usb/usbdi.h>
36#include <dev/usb/usbdevs.h>
37#include <dev/usb/usbhid.h>
38
39#include <dev/wscons/wsconsio.h>
40#include <dev/wscons/wsmousevar.h>
41
42/* #define UBCMTP_DEBUG */
43
44#ifdef UBCMTP_DEBUG
45#define DPRINTF(x...) do { printf(x); } while (0);
46#else
47#define DPRINTF(x...)
48#endif
49
50/* magic to switch device from HID (default) mode into raw */
51#define UBCMTP_WELLSPRING_MODE_RAW0x01 0x01
52#define UBCMTP_WELLSPRING_MODE_HID0x08 0x08
53#define UBCMTP_WELLSPRING_MODE_LEN8 8
54#define UBCMTP_WELLSPRING9_MODE_RAW0x01 0x01
55#define UBCMTP_WELLSPRING9_MODE_HID0x00 0x00
56#define UBCMTP_WELLSPRING9_MODE_LEN2 2
57
58struct ubcmtp_button {
59 uint8_t unused;
60 uint8_t button;
61 uint8_t rel_x;
62 uint8_t rel_y;
63};
64
65struct ubcmtp_finger {
66 uint16_t origin;
67 uint16_t abs_x;
68 uint16_t abs_y;
69 uint16_t rel_x;
70 uint16_t rel_y;
71 uint16_t tool_major;
72 uint16_t tool_minor;
73 uint16_t orientation;
74 uint16_t touch_major;
75 uint16_t touch_minor;
76 uint16_t unused[2];
77 uint16_t pressure;
78 uint16_t multi;
79} __packed__attribute__((__packed__)) __attribute((aligned(2)));
80
81#define UBCMTP_MAX_FINGERS16 16
82#define UBCMTP_ALL_FINGER_SIZE(16 * sizeof(struct ubcmtp_finger)) (UBCMTP_MAX_FINGERS16 * sizeof(struct ubcmtp_finger))
83
84#define UBCMTP_TYPE11 1
85#define UBCMTP_TYPE1_TPOFF(13 * sizeof(uint16_t)) (13 * sizeof(uint16_t))
86#define UBCMTP_TYPE1_TPLEN(13 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger)) UBCMTP_TYPE1_TPOFF(13 * sizeof(uint16_t)) + UBCMTP_ALL_FINGER_SIZE(16 * sizeof(struct ubcmtp_finger))
87#define UBCMTP_TYPE1_TPIFACE1 1
88#define UBCMTP_TYPE1_BTIFACE2 2
89
90#define UBCMTP_TYPE22 2
91#define UBCMTP_TYPE2_TPOFF(15 * sizeof(uint16_t)) (15 * sizeof(uint16_t))
92#define UBCMTP_TYPE2_TPLEN(15 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger)) UBCMTP_TYPE2_TPOFF(15 * sizeof(uint16_t)) + UBCMTP_ALL_FINGER_SIZE(16 * sizeof(struct ubcmtp_finger))
93#define UBCMTP_TYPE2_TPIFACE1 1
94#define UBCMTP_TYPE2_BTOFF15 15
95
96#define UBCMTP_TYPE33 3
97#define UBCMTP_TYPE3_TPOFF(19 * sizeof(uint16_t)) (19 * sizeof(uint16_t))
98#define UBCMTP_TYPE3_TPLEN(19 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger)) UBCMTP_TYPE3_TPOFF(19 * sizeof(uint16_t)) + UBCMTP_ALL_FINGER_SIZE(16 * sizeof(struct ubcmtp_finger))
99#define UBCMTP_TYPE3_TPIFACE2 2
100#define UBCMTP_TYPE3_BTOFF23 23
101
102#define UBCMTP_TYPE44 4
103#define UBCMTP_TYPE4_TPOFF(24 * sizeof(uint16_t)) (24 * sizeof(uint16_t))
104#define UBCMTP_TYPE4_TPLEN(24 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger)) UBCMTP_TYPE4_TPOFF(24 * sizeof(uint16_t)) + UBCMTP_ALL_FINGER_SIZE(16 * sizeof(struct ubcmtp_finger))
105#define UBCMTP_TYPE4_TPIFACE2 2
106#define UBCMTP_TYPE4_BTOFF31 31
107#define UBCMTP_TYPE4_FINGERPAD(1 * sizeof(uint16_t)) (1 * sizeof(uint16_t))
108
109#define UBCMTP_FINGER_ORIENT16384 16384
110#define UBCMTP_SN_PRESSURE45 45
111#define UBCMTP_SN_WIDTH25 25
112#define UBCMTP_SN_COORD250 250
113#define UBCMTP_SN_ORIENT10 10
114
115/* Identify clickpads in ubcmtp_configure. */
116#define IS_CLICKPAD(ubcmtp_type)(ubcmtp_type != 1) (ubcmtp_type != UBCMTP_TYPE11)
117
118/* Use a constant, synaptics-compatible pressure value for now. */
119#define DEFAULT_PRESSURE40 40
120
121struct ubcmtp_limit {
122 int limit;
123 int min;
124 int max;
125};
126
127struct ubcmtp_dev {
128 int vendor; /* vendor */
129 int ansi, iso, jis; /* 3 types of product */
130 int type; /* 1 (normal) or 2 (integrated btn) */
131 struct ubcmtp_limit l_pressure; /* finger pressure */
132 struct ubcmtp_limit l_width; /* finger width */
133 struct ubcmtp_limit l_x;
134 struct ubcmtp_limit l_y;
135 struct ubcmtp_limit l_orientation;
136};
137
138static struct ubcmtp_dev ubcmtp_devices[] = {
139 /* type 1 devices with separate buttons */
140 {
141 USB_VENDOR_APPLE0x05ac,
142 /* MacbookAir */
143 USB_PRODUCT_APPLE_WELLSPRING_ANSI0x0223,
144 USB_PRODUCT_APPLE_WELLSPRING_ISO0x0224,
145 USB_PRODUCT_APPLE_WELLSPRING_JIS0x0225,
146 UBCMTP_TYPE11,
147 { UBCMTP_SN_PRESSURE45, 0, 256 },
148 { UBCMTP_SN_WIDTH25, 0, 2048 },
149 { UBCMTP_SN_COORD250, -4824, 5342 },
150 { UBCMTP_SN_COORD250, -172, 5820 },
151 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
152 },
153 {
154 USB_VENDOR_APPLE0x05ac,
155 /* MacbookProPenryn */
156 USB_PRODUCT_APPLE_WELLSPRING2_ANSI0x0230,
157 USB_PRODUCT_APPLE_WELLSPRING2_ISO0x0231,
158 USB_PRODUCT_APPLE_WELLSPRING2_JIS0x0232,
159 UBCMTP_TYPE11,
160 { UBCMTP_SN_PRESSURE45, 0, 256 },
161 { UBCMTP_SN_WIDTH25, 0, 2048 },
162 { UBCMTP_SN_COORD250, -4824, 4824 },
163 { UBCMTP_SN_COORD250, -172, 4290 },
164 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
165 },
166 /* type 2 devices with integrated buttons */
167 {
168 USB_VENDOR_APPLE0x05ac,
169 /* Macbook5,1 */
170 USB_PRODUCT_APPLE_WELLSPRING3_ANSI0x0236,
171 USB_PRODUCT_APPLE_WELLSPRING3_ISO0x0237,
172 USB_PRODUCT_APPLE_WELLSPRING3_JIS0x0238,
173 UBCMTP_TYPE22,
174 { UBCMTP_SN_PRESSURE45, 0, 300 },
175 { UBCMTP_SN_WIDTH25, 0, 2048 },
176 { UBCMTP_SN_COORD250, -4460, 5166 },
177 { UBCMTP_SN_COORD250, -75, 6700 },
178 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
179 },
180 {
181 USB_VENDOR_APPLE0x05ac,
182 /* MacbookAir3,1 */
183 USB_PRODUCT_APPLE_WELLSPRING4A_ANSI0x0242,
184 USB_PRODUCT_APPLE_WELLSPRING4A_ISO0x0243,
185 USB_PRODUCT_APPLE_WELLSPRING4A_JIS0x0244,
186 UBCMTP_TYPE22,
187 { UBCMTP_SN_PRESSURE45, 0, 300 },
188 { UBCMTP_SN_WIDTH25, 0, 2048 },
189 { UBCMTP_SN_COORD250, -4616, 5112 },
190 { UBCMTP_SN_COORD250, -142, 5234 },
191 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
192 },
193 {
194 USB_VENDOR_APPLE0x05ac,
195 /* MacbookAir3,2 */
196 USB_PRODUCT_APPLE_WELLSPRING4_ANSI0x023f,
197 USB_PRODUCT_APPLE_WELLSPRING4_ISO0x0240,
198 USB_PRODUCT_APPLE_WELLSPRING4_JIS0x0241,
199 UBCMTP_TYPE22,
200 { UBCMTP_SN_PRESSURE45, 0, 300 },
201 { UBCMTP_SN_WIDTH25, 0, 2048 },
202 { UBCMTP_SN_COORD250, -4620, 5140 },
203 { UBCMTP_SN_COORD250, -150, 6600 },
204 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
205 },
206 {
207 USB_VENDOR_APPLE0x05ac,
208 /* Macbook8 */
209 USB_PRODUCT_APPLE_WELLSPRING5_ANSI0x0245,
210 USB_PRODUCT_APPLE_WELLSPRING5_ISO0x0246,
211 USB_PRODUCT_APPLE_WELLSPRING5_JIS0x0247,
212 UBCMTP_TYPE22,
213 { UBCMTP_SN_PRESSURE45, 0, 300 },
214 { UBCMTP_SN_WIDTH25, 0, 2048 },
215 { UBCMTP_SN_COORD250, -4415, 5050 },
216 { UBCMTP_SN_COORD250, -55, 6680 },
217 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
218 },
219 {
220 USB_VENDOR_APPLE0x05ac,
221 /* Macbook8,2 */
222 USB_PRODUCT_APPLE_WELLSPRING5A_ANSI0x0252,
223 USB_PRODUCT_APPLE_WELLSPRING5A_ISO0x0253,
224 USB_PRODUCT_APPLE_WELLSPRING5A_JIS0x0254,
225 UBCMTP_TYPE22,
226 { UBCMTP_SN_PRESSURE45, 0, 300 },
227 { UBCMTP_SN_WIDTH25, 0, 2048 },
228 { UBCMTP_SN_COORD250, -4750, 5280 },
229 { UBCMTP_SN_COORD250, -150, 6730 },
230 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
231 },
232 {
233 USB_VENDOR_APPLE0x05ac,
234 /* MacbookAir4,2 */
235 USB_PRODUCT_APPLE_WELLSPRING6_ANSI0x024c,
236 USB_PRODUCT_APPLE_WELLSPRING6_ISO0x024d,
237 USB_PRODUCT_APPLE_WELLSPRING6_JIS0x024e,
238 UBCMTP_TYPE22,
239 { UBCMTP_SN_PRESSURE45, 0, 300 },
240 { UBCMTP_SN_WIDTH25, 0, 2048 },
241 { UBCMTP_SN_COORD250, -4620, 5140 },
242 { UBCMTP_SN_COORD250, -150, 6600 },
243 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
244 },
245 {
246 USB_VENDOR_APPLE0x05ac,
247 /* MacbookAir4,1 */
248 USB_PRODUCT_APPLE_WELLSPRING6A_ANSI0x0249,
249 USB_PRODUCT_APPLE_WELLSPRING6A_ISO0x024a,
250 USB_PRODUCT_APPLE_WELLSPRING6A_JIS0x024b,
251 UBCMTP_TYPE22,
252 { UBCMTP_SN_PRESSURE45, 0, 300 },
253 { UBCMTP_SN_WIDTH25, 0, 2048 },
254 { UBCMTP_SN_COORD250, -4620, 5140 },
255 { UBCMTP_SN_COORD250, -150, 6600 },
256 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
257 },
258 {
259 USB_VENDOR_APPLE0x05ac,
260 /* MacbookPro10,1 */
261 USB_PRODUCT_APPLE_WELLSPRING7_ANSI0x0262,
262 USB_PRODUCT_APPLE_WELLSPRING7_ISO0x0263,
263 USB_PRODUCT_APPLE_WELLSPRING7_JIS0x0264,
264 UBCMTP_TYPE22,
265 { UBCMTP_SN_PRESSURE45, 0, 300 },
266 { UBCMTP_SN_WIDTH25, 0, 2048 },
267 { UBCMTP_SN_COORD250, -4750, 5280 },
268 { UBCMTP_SN_COORD250, -150, 6730 },
269 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
270 },
271 {
272 USB_VENDOR_APPLE0x05ac,
273 /* MacbookPro10,2 */
274 USB_PRODUCT_APPLE_WELLSPRING7A_ANSI0x0259,
275 USB_PRODUCT_APPLE_WELLSPRING7A_ISO0x025a,
276 USB_PRODUCT_APPLE_WELLSPRING7A_JIS0x025b,
277 UBCMTP_TYPE22,
278 { UBCMTP_SN_PRESSURE45, 0, 300 },
279 { UBCMTP_SN_WIDTH25, 0, 2048 },
280 { UBCMTP_SN_COORD250, -4750, 5280 },
281 { UBCMTP_SN_COORD250, -150, 6730 },
282 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
283 },
284 {
285 USB_VENDOR_APPLE0x05ac,
286 /* MacbookAir6,1 */
287 USB_PRODUCT_APPLE_WELLSPRING8_ANSI0x0290,
288 USB_PRODUCT_APPLE_WELLSPRING8_ISO0x0291,
289 USB_PRODUCT_APPLE_WELLSPRING8_JIS0x0292,
290 UBCMTP_TYPE33,
291 { UBCMTP_SN_PRESSURE45, 0, 300 },
292 { UBCMTP_SN_WIDTH25, 0, 2048 },
293 { UBCMTP_SN_COORD250, -4620, 5140 },
294 { UBCMTP_SN_COORD250, -150, 6600 },
295 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
296 },
297 {
298 USB_VENDOR_APPLE0x05ac,
299 /* MacbookPro12,1 */
300 USB_PRODUCT_APPLE_WELLSPRING9_ANSI0x0272,
301 USB_PRODUCT_APPLE_WELLSPRING9_ISO0x0273,
302 USB_PRODUCT_APPLE_WELLSPRING9_JIS0x0274,
303 UBCMTP_TYPE44,
304 { UBCMTP_SN_PRESSURE45, 0, 300 },
305 { UBCMTP_SN_WIDTH25, 0, 2048 },
306 { UBCMTP_SN_COORD250, -4828, 5345 },
307 { UBCMTP_SN_COORD250, -203, 6803 },
308 { UBCMTP_SN_ORIENT10, -UBCMTP_FINGER_ORIENT16384, UBCMTP_FINGER_ORIENT16384 },
309 },
310};
311
312struct ubcmtp_softc {
313 struct device sc_dev; /* base device */
314
315 struct ubcmtp_dev *dev_type;
316
317 struct usbd_device *sc_udev;
318 struct device *sc_wsmousedev;
319
320 struct usbd_interface *sc_tp_iface; /* trackpad interface */
321 struct usbd_pipe *sc_tp_pipe; /* trackpad pipe */
322 int sc_tp_epaddr; /* endpoint addr */
323 int tp_maxlen; /* max size of tp data */
324 int tp_offset; /* finger offset into data */
325 int tp_fingerpad; /* padding between finger data */
326 uint8_t *tp_pkt;
327
328 struct usbd_interface *sc_bt_iface; /* button interface */
329 struct usbd_pipe *sc_bt_pipe; /* button pipe */
330 int sc_bt_epaddr; /* endpoint addr */
331 int bt_maxlen; /* max size of button data */
332 uint8_t *bt_pkt;
333
334 uint32_t sc_status;
335#define UBCMTP_ENABLED1 1
336
337 struct mtpoint frame[UBCMTP_MAX_FINGERS16];
338 int contacts;
339 int btn;
340};
341
342int ubcmtp_enable(void *);
343void ubcmtp_disable(void *);
344int ubcmtp_ioctl(void *, unsigned long, caddr_t, int, struct proc *);
345int ubcmtp_raw_mode(struct ubcmtp_softc *, int);
346int ubcmtp_setup_pipes(struct ubcmtp_softc *);
347void ubcmtp_bt_intr(struct usbd_xfer *, void *, usbd_status);
348void ubcmtp_tp_intr(struct usbd_xfer *, void *, usbd_status);
349
350int ubcmtp_match(struct device *, void *, void *);
351void ubcmtp_attach(struct device *, struct device *, void *);
352int ubcmtp_detach(struct device *, int);
353int ubcmtp_activate(struct device *, int);
354int ubcmtp_configure(struct ubcmtp_softc *);
355
356const struct wsmouse_accessops ubcmtp_accessops = {
357 ubcmtp_enable,
358 ubcmtp_ioctl,
359 ubcmtp_disable,
360};
361
362struct cfdriver ubcmtp_cd = {
363 NULL((void *)0), "ubcmtp", DV_DULL
364};
365
366const struct cfattach ubcmtp_ca = {
367 sizeof(struct ubcmtp_softc), ubcmtp_match, ubcmtp_attach, ubcmtp_detach,
368 ubcmtp_activate,
369};
370
371int
372ubcmtp_match(struct device *parent, void *match, void *aux)
373{
374 struct usb_attach_arg *uaa = aux;
375 usb_interface_descriptor_t *id;
376 int i;
377
378 if (uaa->iface == NULL((void *)0))
379 return (UMATCH_NONE0);
380
381 for (i = 0; i < nitems(ubcmtp_devices)(sizeof((ubcmtp_devices)) / sizeof((ubcmtp_devices)[0])); i++) {
382 if (uaa->vendor == ubcmtp_devices[i].vendor && (
383 uaa->product == ubcmtp_devices[i].ansi ||
384 uaa->product == ubcmtp_devices[i].iso ||
385 uaa->product == ubcmtp_devices[i].jis)) {
386 if (uaa->nifaces < 2)
387 return (UMATCH_NONE0);
388 if ((ubcmtp_devices[i].type != UBCMTP_TYPE22) &&
389 (uaa->nifaces < 3))
390 return (UMATCH_NONE0);
391
392 /*
393 * The USB keyboard/mouse device will have one keyboard
394 * HID and two mouse HIDs, though only one will have a
395 * protocol of mouse -- we only want to take control of
396 * that one.
397 */
398 id = usbd_get_interface_descriptor(uaa->iface);
399 if (id->bInterfaceProtocol == UIPROTO_BOOT_MOUSE2)
400 return (UMATCH_VENDOR_PRODUCT_CONF_IFACE8);
401 }
402 }
403
404 return (UMATCH_NONE0);
405}
406
407void
408ubcmtp_attach(struct device *parent, struct device *self, void *aux)
409{
410 struct ubcmtp_softc *sc = (struct ubcmtp_softc *)self;
411 struct usb_attach_arg *uaa = aux;
412 struct usbd_device *dev = uaa->device;
413 struct wsmousedev_attach_args a;
414 usb_device_descriptor_t *udd;
415 int i;
416
417 sc->sc_udev = uaa->device;
418 sc->sc_status = 0;
419 sc->tp_fingerpad = 0;
420
421 if ((udd = usbd_get_device_descriptor(dev)) == NULL((void *)0)) {
Although the value stored to 'udd' is used in the enclosing expression, the value is never actually read from 'udd'
422 printf("ubcmtp: failed getting device descriptor\n");
423 return;
424 }
425
426 for (i = 0; i < nitems(ubcmtp_devices)(sizeof((ubcmtp_devices)) / sizeof((ubcmtp_devices)[0])); i++) {
427 if (uaa->vendor == ubcmtp_devices[i].vendor && (
428 uaa->product == ubcmtp_devices[i].ansi ||
429 uaa->product == ubcmtp_devices[i].iso ||
430 uaa->product == ubcmtp_devices[i].jis)) {
431 sc->dev_type = &ubcmtp_devices[i];
432 DPRINTF("%s: attached to 0x%x/0x%x type %d\n",
433 sc->sc_dev.dv_xname, uaa->vendor, uaa->product,
434 sc->dev_type->type);
435 break;
436 }
437 }
438
439 if (sc->dev_type == NULL((void *)0)) {
440 /* how did we match then? */
441 printf("%s: failed looking up device in table\n",
442 sc->sc_dev.dv_xname);
443 return;
444 }
445
446 switch (sc->dev_type->type) {
447 case UBCMTP_TYPE11:
448 sc->tp_maxlen = UBCMTP_TYPE1_TPLEN(13 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger));
449 sc->tp_offset = UBCMTP_TYPE1_TPOFF(13 * sizeof(uint16_t));
450 sc->sc_tp_iface = uaa->ifaces[UBCMTP_TYPE1_TPIFACE1];
451 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE1_TPIFACE1);
452
453 /* button offsets */
454 sc->bt_maxlen = sizeof(struct ubcmtp_button);
455 sc->sc_bt_iface = uaa->ifaces[UBCMTP_TYPE1_BTIFACE2];
456 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE1_BTIFACE2);
457 break;
458
459 case UBCMTP_TYPE22:
460 sc->tp_maxlen = UBCMTP_TYPE2_TPLEN(15 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger));
461 sc->tp_offset = UBCMTP_TYPE2_TPOFF(15 * sizeof(uint16_t));
462 sc->sc_tp_iface = uaa->ifaces[UBCMTP_TYPE2_TPIFACE1];
463 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE2_TPIFACE1);
464 break;
465
466 case UBCMTP_TYPE33:
467 sc->tp_maxlen = UBCMTP_TYPE3_TPLEN(19 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger));
468 sc->tp_offset = UBCMTP_TYPE3_TPOFF(19 * sizeof(uint16_t));
469 sc->sc_tp_iface = uaa->ifaces[UBCMTP_TYPE3_TPIFACE2];
470 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE3_TPIFACE2);
471 break;
472
473 case UBCMTP_TYPE44:
474 sc->tp_maxlen = UBCMTP_TYPE4_TPLEN(24 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger));
475 sc->tp_offset = UBCMTP_TYPE4_TPOFF(24 * sizeof(uint16_t));
476 sc->sc_tp_iface = uaa->ifaces[UBCMTP_TYPE4_TPIFACE2];
477 sc->tp_fingerpad = UBCMTP_TYPE4_FINGERPAD(1 * sizeof(uint16_t));
478 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE4_TPIFACE2);
479 break;
480 }
481
482 a.accessops = &ubcmtp_accessops;
483 a.accesscookie = sc;
484
485 sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint)config_found_sm((self), (&a), (wsmousedevprint), ((void *
)0))
;
486 if (sc->sc_wsmousedev != NULL((void *)0) && ubcmtp_configure(sc))
487 ubcmtp_disable(sc);
488}
489
490int
491ubcmtp_detach(struct device *self, int flags)
492{
493 struct ubcmtp_softc *sc = (struct ubcmtp_softc *)self;
494 int ret = 0;
495
496 if (sc->sc_wsmousedev != NULL((void *)0))
497 ret = config_detach(sc->sc_wsmousedev, flags);
498
499 return (ret);
500}
501
502int
503ubcmtp_activate(struct device *self, int act)
504{
505 struct ubcmtp_softc *sc = (struct ubcmtp_softc *)self;
506 int rv = 0;
507
508 if (act == DVACT_DEACTIVATE1) {
509 if (sc->sc_wsmousedev != NULL((void *)0))
510 rv = config_deactivate(sc->sc_wsmousedev);
511 usbd_deactivate(sc->sc_udev);
512 }
513
514 return (rv);
515}
516
517int
518ubcmtp_configure(struct ubcmtp_softc *sc)
519{
520 struct wsmousehw *hw = wsmouse_get_hw(sc->sc_wsmousedev);
521
522 hw->type = WSMOUSE_TYPE_TOUCHPAD20;
523 hw->hw_type = (IS_CLICKPAD(sc->dev_type->type)(sc->dev_type->type != 1)
524 ? WSMOUSEHW_CLICKPAD : WSMOUSEHW_TOUCHPAD);
525 hw->x_min = sc->dev_type->l_x.min;
526 hw->x_max = sc->dev_type->l_x.max;
527 hw->y_min = sc->dev_type->l_y.min;
528 hw->y_max = sc->dev_type->l_y.max;
529 hw->mt_slots = UBCMTP_MAX_FINGERS16;
530 hw->flags = WSMOUSEHW_MT_TRACKING(1 << 1);
531
532 return wsmouse_configure(sc->sc_wsmousedev, NULL((void *)0), 0);
533}
534
535int
536ubcmtp_enable(void *v)
537{
538 struct ubcmtp_softc *sc = v;
539
540 if (sc->sc_status & UBCMTP_ENABLED1)
541 return (EBUSY16);
542
543 if (usbd_is_dying(sc->sc_udev))
544 return (EIO5);
545
546 if (ubcmtp_raw_mode(sc, 1) != 0) {
547 printf("%s: failed to enter raw mode\n", sc->sc_dev.dv_xname);
548 return (1);
549 }
550
551 if (ubcmtp_setup_pipes(sc) == 0) {
552 sc->sc_status |= UBCMTP_ENABLED1;
553 return (0);
554 } else
555 return (1);
556}
557
558void
559ubcmtp_disable(void *v)
560{
561 struct ubcmtp_softc *sc = v;
562
563 if (usbd_is_dying(sc->sc_udev) || !(sc->sc_status & UBCMTP_ENABLED1))
564 return;
565
566 sc->sc_status &= ~UBCMTP_ENABLED1;
567
568 ubcmtp_raw_mode(sc, 0);
569
570 if (sc->sc_tp_pipe != NULL((void *)0)) {
571 usbd_close_pipe(sc->sc_tp_pipe);
572 sc->sc_tp_pipe = NULL((void *)0);
573 }
574 if (sc->sc_bt_pipe != NULL((void *)0)) {
575 usbd_close_pipe(sc->sc_bt_pipe);
576 sc->sc_bt_pipe = NULL((void *)0);
577 }
578
579 if (sc->tp_pkt != NULL((void *)0)) {
580 free(sc->tp_pkt, M_USBDEV102, sc->tp_maxlen);
581 sc->tp_pkt = NULL((void *)0);
582 }
583 if (sc->bt_pkt != NULL((void *)0)) {
584 free(sc->bt_pkt, M_USBDEV102, sc->bt_maxlen);
585 sc->bt_pkt = NULL((void *)0);
586 }
587}
588
589int
590ubcmtp_ioctl(void *v, unsigned long cmd, caddr_t data, int flag, struct proc *p)
591{
592 struct ubcmtp_softc *sc = v;
593 struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
594 int wsmode;
595
596 DPRINTF("%s: in %s with cmd 0x%lx\n", sc->sc_dev.dv_xname, __func__,
597 cmd);
598
599 switch (cmd) {
600 case WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
: {
601 struct wsmousehw *hw = wsmouse_get_hw(sc->sc_wsmousedev);
602 *(u_int *)data = hw->type;
603 break;
604 }
605
606 case WSMOUSEIO_GCALIBCOORDS((unsigned long)0x40000000 | ((sizeof(struct wsmouse_calibcoords
) & 0x1fff) << 16) | ((('W')) << 8) | ((37)))
:
607 wsmc->minx = sc->dev_type->l_x.min;
608 wsmc->maxx = sc->dev_type->l_x.max;
609 wsmc->miny = sc->dev_type->l_y.min;
610 wsmc->maxy = sc->dev_type->l_y.max;
611 wsmc->swapxy = 0;
612 wsmc->resx = 0;
613 wsmc->resy = 0;
614 break;
615
616 case WSMOUSEIO_SETMODE((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('W')) << 8) | ((38)))
:
617 wsmode = *(u_int *)data;
618 if (wsmode != WSMOUSE_COMPAT0 && wsmode != WSMOUSE_NATIVE1) {
619 printf("%s: invalid mode %d\n", sc->sc_dev.dv_xname,
620 wsmode);
621 return (EINVAL22);
622 }
623 wsmouse_set_mode(sc->sc_wsmousedev, wsmode);
624
625 DPRINTF("%s: changing mode to %s\n",
626 sc->sc_dev.dv_xname, (wsmode == WSMOUSE_COMPAT ? "compat" :
627 "native"));
628
629 break;
630
631 default:
632 return (-1);
633 }
634
635 return (0);
636}
637
638int
639ubcmtp_raw_mode(struct ubcmtp_softc *sc, int enable)
640{
641 usb_device_request_t r;
642 usbd_status err;
643 uint8_t buf[8];
644
645 /* type 3 has no raw mode */
646 if (sc->dev_type->type == UBCMTP_TYPE33)
647 return (0);
648
649 r.bRequest = UR_GET_REPORT0x01;
650 r.bmRequestType = UT_READ_CLASS_INTERFACE(0x80 | 0x20 | 0x01);
651 if (sc->dev_type->type < UBCMTP_TYPE44) {
652 USETW2(r.wValue, UHID_FEATURE_REPORT, 0)((r.wValue)[0] = (u_int8_t)(0), (r.wValue)[1] = (u_int8_t)(0x03
))
;
653 USETW(r.wIndex, 0)(*(u_int16_t *)(r.wIndex) = (0));
654 USETW(r.wLength, UBCMTP_WELLSPRING_MODE_LEN)(*(u_int16_t *)(r.wLength) = (8));
655 } else {
656 USETW2(r.wValue, UHID_FEATURE_REPORT, 2)((r.wValue)[0] = (u_int8_t)(2), (r.wValue)[1] = (u_int8_t)(0x03
))
;
657 USETW(r.wIndex, 2)(*(u_int16_t *)(r.wIndex) = (2));
658 USETW(r.wLength, UBCMTP_WELLSPRING9_MODE_LEN)(*(u_int16_t *)(r.wLength) = (2));
659 }
660
661 err = usbd_do_request(sc->sc_udev, &r, buf);
662 if (err != USBD_NORMAL_COMPLETION) {
663 printf("%s: %s: failed to get feature report\n",
664 sc->sc_dev.dv_xname, __func__);
665 return (err);
666 }
667
668 /* toggle magic byte and write everything back */
669 if (sc->dev_type->type < UBCMTP_TYPE44)
670 buf[0] = (enable ? UBCMTP_WELLSPRING_MODE_RAW0x01 :
671 UBCMTP_WELLSPRING_MODE_HID0x08);
672 else
673 buf[1] = (enable ? UBCMTP_WELLSPRING9_MODE_RAW0x01 :
674 UBCMTP_WELLSPRING9_MODE_HID0x00);
675
676 r.bRequest = UR_SET_REPORT0x09;
677 r.bmRequestType = UT_WRITE_CLASS_INTERFACE(0x00 | 0x20 | 0x01);
678 if (sc->dev_type->type < UBCMTP_TYPE44) {
679 USETW2(r.wValue, UHID_FEATURE_REPORT, 0)((r.wValue)[0] = (u_int8_t)(0), (r.wValue)[1] = (u_int8_t)(0x03
))
;
680 USETW(r.wIndex, 0)(*(u_int16_t *)(r.wIndex) = (0));
681 USETW(r.wLength, UBCMTP_WELLSPRING_MODE_LEN)(*(u_int16_t *)(r.wLength) = (8));
682 } else {
683 USETW2(r.wValue, UHID_FEATURE_REPORT, 2)((r.wValue)[0] = (u_int8_t)(2), (r.wValue)[1] = (u_int8_t)(0x03
))
;
684 USETW(r.wIndex, 2)(*(u_int16_t *)(r.wIndex) = (2));
685 USETW(r.wLength, UBCMTP_WELLSPRING9_MODE_LEN)(*(u_int16_t *)(r.wLength) = (2));
686 }
687
688 err = usbd_do_request(sc->sc_udev, &r, buf);
689 if (err != USBD_NORMAL_COMPLETION) {
690 printf("%s: %s: failed to toggle raw mode\n",
691 sc->sc_dev.dv_xname, __func__);
692 return (err);
693 }
694
695 return (0);
696}
697
698int
699ubcmtp_setup_pipes(struct ubcmtp_softc *sc)
700{
701 usbd_status err;
702 usb_endpoint_descriptor_t *ed;
703
704 if (sc->dev_type->type == UBCMTP_TYPE11) {
705 /* setup physical button pipe */
706
707 ed = usbd_interface2endpoint_descriptor(sc->sc_bt_iface, 0);
708 if (ed == NULL((void *)0)) {
709 printf("%s: failed getting button endpoint descriptor\n",
710 sc->sc_dev.dv_xname);
711 goto fail1;
712 }
713 sc->sc_bt_epaddr = ed->bEndpointAddress;
714 sc->bt_pkt = malloc(sc->bt_maxlen, M_USBDEV102, M_WAITOK0x0001);
715 if (sc->bt_pkt == NULL((void *)0))
716 goto fail1;
717
718 DPRINTF("%s: button iface at 0x%x, max size %d\n",
719 sc->sc_dev.dv_xname, sc->sc_bt_epaddr, sc->bt_maxlen);
720
721 err = usbd_open_pipe_intr(sc->sc_bt_iface, sc->sc_bt_epaddr,
722 USBD_SHORT_XFER_OK0x04, &sc->sc_bt_pipe, sc, sc->bt_pkt,
723 sc->bt_maxlen, ubcmtp_bt_intr, USBD_DEFAULT_INTERVAL(-1));
724 if (err != USBD_NORMAL_COMPLETION) {
725 printf("%s: failed opening button pipe\n",
726 sc->sc_dev.dv_xname);
727 goto fail1;
728 }
729 }
730
731 /* setup trackpad data pipe */
732
733 ed = usbd_interface2endpoint_descriptor(sc->sc_tp_iface, 0);
734 if (ed == NULL((void *)0)) {
735 printf("%s: failed getting trackpad data endpoint descriptor\n",
736 sc->sc_dev.dv_xname);
737 goto fail2;
738 }
739 sc->sc_tp_epaddr = ed->bEndpointAddress;
740 sc->tp_pkt = malloc(sc->tp_maxlen, M_USBDEV102, M_WAITOK0x0001);
741 if (sc->tp_pkt == NULL((void *)0))
742 goto fail2;
743
744 DPRINTF("%s: trackpad data iface at 0x%x, max size %d\n",
745 sc->sc_dev.dv_xname, sc->sc_tp_epaddr, sc->tp_maxlen);
746
747 err = usbd_open_pipe_intr(sc->sc_tp_iface, sc->sc_tp_epaddr,
748 USBD_SHORT_XFER_OK0x04, &sc->sc_tp_pipe, sc, sc->tp_pkt, sc->tp_maxlen,
749 ubcmtp_tp_intr, USBD_DEFAULT_INTERVAL(-1));
750 if (err != USBD_NORMAL_COMPLETION) {
751 printf("%s: error opening trackpad data pipe\n",
752 sc->sc_dev.dv_xname);
753 goto fail2;
754 }
755
756 return (0);
757
758fail2:
759 if (sc->sc_tp_pipe != NULL((void *)0))
760 usbd_close_pipe(sc->sc_tp_pipe);
761 if (sc->tp_pkt != NULL((void *)0))
762 free(sc->tp_pkt, M_USBDEV102, sc->tp_maxlen);
763fail1:
764 if (sc->sc_bt_pipe != NULL((void *)0))
765 usbd_close_pipe(sc->sc_bt_pipe);
766 if (sc->bt_pkt != NULL((void *)0))
767 free(sc->bt_pkt, M_USBDEV102, sc->bt_maxlen);
768
769 return (1);
770}
771
772void
773ubcmtp_tp_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
774{
775 struct ubcmtp_softc *sc = priv;
776 struct ubcmtp_finger *finger;
777 u_int32_t pktlen;
778 int off, s, btn, contacts = 0;
779
780 if (usbd_is_dying(sc->sc_udev) || !(sc->sc_status & UBCMTP_ENABLED1))
781 return;
782
783 if (status != USBD_NORMAL_COMPLETION) {
784 DPRINTF("%s: %s with status 0x%x\n", sc->sc_dev.dv_xname,
785 __func__, status);
786
787 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
788 return;
789 if (status == USBD_STALLED)
790 usbd_clear_endpoint_stall_async(sc->sc_tp_pipe);
791 return;
792 }
793
794 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &pktlen, NULL((void *)0));
795
796 if (sc->tp_pkt == NULL((void *)0) || pktlen < sc->tp_offset)
797 return;
798
799 contacts = 0;
800 for (off = sc->tp_offset; off < pktlen;
801 off += (sizeof(struct ubcmtp_finger) + sc->tp_fingerpad)) {
802 finger = (struct ubcmtp_finger *)(sc->tp_pkt + off);
803
804 if ((int16_t)letoh16(finger->touch_major)((__uint16_t)(finger->touch_major)) == 0)
805 continue; /* finger lifted */
806
807 sc->frame[contacts].x = (int16_t)letoh16(finger->abs_x)((__uint16_t)(finger->abs_x));
808 sc->frame[contacts].y = (int16_t)letoh16(finger->abs_y)((__uint16_t)(finger->abs_y));
809 sc->frame[contacts].pressure = DEFAULT_PRESSURE40;
810 contacts++;
811 }
812
813 btn = sc->btn;
814 if (sc->dev_type->type == UBCMTP_TYPE22)
815 sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE2_BTOFF])((__uint16_t)(sc->tp_pkt[15])));
816 else if (sc->dev_type->type == UBCMTP_TYPE33)
817 sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE3_BTOFF])((__uint16_t)(sc->tp_pkt[23])));
818 else if (sc->dev_type->type == UBCMTP_TYPE44)
819 sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE4_BTOFF])((__uint16_t)(sc->tp_pkt[31])));
820
821 if (contacts || sc->contacts || sc->btn != btn) {
822 sc->contacts = contacts;
823 s = spltty()splraise(0x9);
824 wsmouse_buttons(sc->sc_wsmousedev, sc->btn);
825 wsmouse_mtframe(sc->sc_wsmousedev, sc->frame, contacts);
826 wsmouse_input_sync(sc->sc_wsmousedev);
827 splx(s)spllower(s);
828 }
829}
830
831/* hardware button interrupt */
832void
833ubcmtp_bt_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
834{
835 struct ubcmtp_softc *sc = priv;
836 struct ubcmtp_button *pkt;
837 u_int32_t len;
838
839 if (usbd_is_dying(sc->sc_udev) || !(sc->sc_status & UBCMTP_ENABLED1))
840 return;
841
842 if (status != USBD_NORMAL_COMPLETION) {
843 DPRINTF("%s: %s with status 0x%x\n", sc->sc_dev.dv_xname,
844 __func__, status);
845 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
846 return;
847 if (status == USBD_STALLED)
848 usbd_clear_endpoint_stall_async(sc->sc_tp_pipe);
849 return;
850 }
851
852 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
853
854 if (sc->bt_pkt == NULL((void *)0) || len < sizeof(struct ubcmtp_button))
855 return;
856
857 pkt = (struct ubcmtp_button *)(sc->bt_pkt);
858
859 DPRINTF("%s: button interrupt (%d, %d, %d, %d)", sc->sc_dev.dv_xname,
860 pkt->unused, pkt->button, pkt->rel_x, pkt->rel_y);
861
862 if (pkt->button != sc->btn) {
863 sc->btn = pkt->button;
864 wsmouse_buttons(sc->sc_wsmousedev, sc->btn);
865 wsmouse_input_sync(sc->sc_wsmousedev);
866 }
867}