Bug Summary

File:dev/usb/ubcmtp.c
Warning:line 425, 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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ubcmtp.c -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 -ffp-contract=on -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 -target-feature +retpoline-external-thunk -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/llvm16/lib/clang/16 -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/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -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/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -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/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -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 SUSPEND -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 -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 -fcf-protection=branch -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 /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/usb/ubcmtp.c
1/* $OpenBSD: ubcmtp.c,v 1.25 2023/07/02 21:44:04 bru 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 const 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
312static struct wsmouse_param ubcmtp_wsmousecfg[] = {
313 { WSMOUSECFG_MTBTN_MAXDIST, 0 }, /* 0: Compute a default value. */
314};
315
316struct ubcmtp_softc {
317 struct device sc_dev; /* base device */
318
319 const struct ubcmtp_dev *dev_type;
320
321 struct usbd_device *sc_udev;
322 struct device *sc_wsmousedev;
323
324 struct usbd_interface *sc_tp_iface; /* trackpad interface */
325 struct usbd_pipe *sc_tp_pipe; /* trackpad pipe */
326 int sc_tp_epaddr; /* endpoint addr */
327 int tp_maxlen; /* max size of tp data */
328 int tp_offset; /* finger offset into data */
329 int tp_fingerpad; /* padding between finger data */
330 uint8_t *tp_pkt;
331
332 struct usbd_interface *sc_bt_iface; /* button interface */
333 struct usbd_pipe *sc_bt_pipe; /* button pipe */
334 int sc_bt_epaddr; /* endpoint addr */
335 int bt_maxlen; /* max size of button data */
336 uint8_t *bt_pkt;
337
338 uint32_t sc_status;
339#define UBCMTP_ENABLED1 1
340
341 struct mtpoint frame[UBCMTP_MAX_FINGERS16];
342 int contacts;
343 int btn;
344};
345
346int ubcmtp_enable(void *);
347void ubcmtp_disable(void *);
348int ubcmtp_ioctl(void *, unsigned long, caddr_t, int, struct proc *);
349int ubcmtp_raw_mode(struct ubcmtp_softc *, int);
350int ubcmtp_setup_pipes(struct ubcmtp_softc *);
351void ubcmtp_bt_intr(struct usbd_xfer *, void *, usbd_status);
352void ubcmtp_tp_intr(struct usbd_xfer *, void *, usbd_status);
353
354int ubcmtp_match(struct device *, void *, void *);
355void ubcmtp_attach(struct device *, struct device *, void *);
356int ubcmtp_detach(struct device *, int);
357int ubcmtp_activate(struct device *, int);
358int ubcmtp_configure(struct ubcmtp_softc *);
359
360const struct wsmouse_accessops ubcmtp_accessops = {
361 ubcmtp_enable,
362 ubcmtp_ioctl,
363 ubcmtp_disable,
364};
365
366struct cfdriver ubcmtp_cd = {
367 NULL((void *)0), "ubcmtp", DV_DULL
368};
369
370const struct cfattach ubcmtp_ca = {
371 sizeof(struct ubcmtp_softc), ubcmtp_match, ubcmtp_attach, ubcmtp_detach,
372 ubcmtp_activate,
373};
374
375int
376ubcmtp_match(struct device *parent, void *match, void *aux)
377{
378 struct usb_attach_arg *uaa = aux;
379 usb_interface_descriptor_t *id;
380 int i;
381
382 if (uaa->iface == NULL((void *)0))
383 return (UMATCH_NONE0);
384
385 for (i = 0; i < nitems(ubcmtp_devices)(sizeof((ubcmtp_devices)) / sizeof((ubcmtp_devices)[0])); i++) {
386 if (uaa->vendor == ubcmtp_devices[i].vendor && (
387 uaa->product == ubcmtp_devices[i].ansi ||
388 uaa->product == ubcmtp_devices[i].iso ||
389 uaa->product == ubcmtp_devices[i].jis)) {
390 if (uaa->nifaces < 2)
391 return (UMATCH_NONE0);
392 if ((ubcmtp_devices[i].type != UBCMTP_TYPE22) &&
393 (uaa->nifaces < 3))
394 return (UMATCH_NONE0);
395
396 /*
397 * The USB keyboard/mouse device will have one keyboard
398 * HID and two mouse HIDs, though only one will have a
399 * protocol of mouse -- we only want to take control of
400 * that one.
401 */
402 id = usbd_get_interface_descriptor(uaa->iface);
403 if (id->bInterfaceProtocol == UIPROTO_BOOT_MOUSE2)
404 return (UMATCH_VENDOR_PRODUCT_CONF_IFACE8);
405 }
406 }
407
408 return (UMATCH_NONE0);
409}
410
411void
412ubcmtp_attach(struct device *parent, struct device *self, void *aux)
413{
414 struct ubcmtp_softc *sc = (struct ubcmtp_softc *)self;
415 struct usb_attach_arg *uaa = aux;
416 struct usbd_device *dev = uaa->device;
417 struct wsmousedev_attach_args a;
418 usb_device_descriptor_t *udd;
419 int i;
420
421 sc->sc_udev = uaa->device;
422 sc->sc_status = 0;
423 sc->tp_fingerpad = 0;
424
425 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'
426 printf("ubcmtp: failed getting device descriptor\n");
427 return;
428 }
429
430 for (i = 0; i < nitems(ubcmtp_devices)(sizeof((ubcmtp_devices)) / sizeof((ubcmtp_devices)[0])); i++) {
431 if (uaa->vendor == ubcmtp_devices[i].vendor && (
432 uaa->product == ubcmtp_devices[i].ansi ||
433 uaa->product == ubcmtp_devices[i].iso ||
434 uaa->product == ubcmtp_devices[i].jis)) {
435 sc->dev_type = &ubcmtp_devices[i];
436 DPRINTF("%s: attached to 0x%x/0x%x type %d\n",
437 sc->sc_dev.dv_xname, uaa->vendor, uaa->product,
438 sc->dev_type->type);
439 break;
440 }
441 }
442
443 if (sc->dev_type == NULL((void *)0)) {
444 /* how did we match then? */
445 printf("%s: failed looking up device in table\n",
446 sc->sc_dev.dv_xname);
447 return;
448 }
449
450 switch (sc->dev_type->type) {
451 case UBCMTP_TYPE11:
452 sc->tp_maxlen = UBCMTP_TYPE1_TPLEN(13 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger));
453 sc->tp_offset = UBCMTP_TYPE1_TPOFF(13 * sizeof(uint16_t));
454 sc->sc_tp_iface = uaa->ifaces[UBCMTP_TYPE1_TPIFACE1];
455 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE1_TPIFACE1);
456
457 /* button offsets */
458 sc->bt_maxlen = sizeof(struct ubcmtp_button);
459 sc->sc_bt_iface = uaa->ifaces[UBCMTP_TYPE1_BTIFACE2];
460 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE1_BTIFACE2);
461 break;
462
463 case UBCMTP_TYPE22:
464 sc->tp_maxlen = UBCMTP_TYPE2_TPLEN(15 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger));
465 sc->tp_offset = UBCMTP_TYPE2_TPOFF(15 * sizeof(uint16_t));
466 sc->sc_tp_iface = uaa->ifaces[UBCMTP_TYPE2_TPIFACE1];
467 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE2_TPIFACE1);
468 break;
469
470 case UBCMTP_TYPE33:
471 sc->tp_maxlen = UBCMTP_TYPE3_TPLEN(19 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger));
472 sc->tp_offset = UBCMTP_TYPE3_TPOFF(19 * sizeof(uint16_t));
473 sc->sc_tp_iface = uaa->ifaces[UBCMTP_TYPE3_TPIFACE2];
474 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE3_TPIFACE2);
475 break;
476
477 case UBCMTP_TYPE44:
478 sc->tp_maxlen = UBCMTP_TYPE4_TPLEN(24 * sizeof(uint16_t)) + (16 * sizeof(struct ubcmtp_finger));
479 sc->tp_offset = UBCMTP_TYPE4_TPOFF(24 * sizeof(uint16_t));
480 sc->sc_tp_iface = uaa->ifaces[UBCMTP_TYPE4_TPIFACE2];
481 sc->tp_fingerpad = UBCMTP_TYPE4_FINGERPAD(1 * sizeof(uint16_t));
482 usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE4_TPIFACE2);
483 break;
484 }
485
486 a.accessops = &ubcmtp_accessops;
487 a.accesscookie = sc;
488
489 sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint)config_found_sm((self), (&a), (wsmousedevprint), ((void *
)0))
;
490 if (sc->sc_wsmousedev != NULL((void *)0) && ubcmtp_configure(sc))
491 ubcmtp_disable(sc);
492}
493
494int
495ubcmtp_detach(struct device *self, int flags)
496{
497 struct ubcmtp_softc *sc = (struct ubcmtp_softc *)self;
498 int ret = 0;
499
500 if (sc->sc_wsmousedev != NULL((void *)0))
501 ret = config_detach(sc->sc_wsmousedev, flags);
502
503 return (ret);
504}
505
506int
507ubcmtp_activate(struct device *self, int act)
508{
509 struct ubcmtp_softc *sc = (struct ubcmtp_softc *)self;
510 int rv = 0;
511
512 if (act == DVACT_DEACTIVATE1) {
513 if (sc->sc_wsmousedev != NULL((void *)0))
514 rv = config_deactivate(sc->sc_wsmousedev);
515 usbd_deactivate(sc->sc_udev);
516 }
517
518 return (rv);
519}
520
521int
522ubcmtp_configure(struct ubcmtp_softc *sc)
523{
524 struct wsmousehw *hw = wsmouse_get_hw(sc->sc_wsmousedev);
525
526 hw->type = WSMOUSE_TYPE_TOUCHPAD20;
527 hw->hw_type = (IS_CLICKPAD(sc->dev_type->type)(sc->dev_type->type != 1)
528 ? WSMOUSEHW_CLICKPAD : WSMOUSEHW_TOUCHPAD);
529 hw->x_min = sc->dev_type->l_x.min;
530 hw->x_max = sc->dev_type->l_x.max;
531 hw->y_min = sc->dev_type->l_y.min;
532 hw->y_max = sc->dev_type->l_y.max;
533 hw->mt_slots = UBCMTP_MAX_FINGERS16;
534 hw->flags = WSMOUSEHW_MT_TRACKING(1 << 1);
535
536 return wsmouse_configure(sc->sc_wsmousedev,
537 ubcmtp_wsmousecfg, nitems(ubcmtp_wsmousecfg)(sizeof((ubcmtp_wsmousecfg)) / sizeof((ubcmtp_wsmousecfg)[0])
)
);
538}
539
540int
541ubcmtp_enable(void *v)
542{
543 struct ubcmtp_softc *sc = v;
544
545 if (sc->sc_status & UBCMTP_ENABLED1)
546 return (EBUSY16);
547
548 if (usbd_is_dying(sc->sc_udev))
549 return (EIO5);
550
551 if (ubcmtp_raw_mode(sc, 1) != 0) {
552 printf("%s: failed to enter raw mode\n", sc->sc_dev.dv_xname);
553 return (1);
554 }
555
556 if (ubcmtp_setup_pipes(sc) == 0) {
557 sc->sc_status |= UBCMTP_ENABLED1;
558 return (0);
559 } else
560 return (1);
561}
562
563void
564ubcmtp_disable(void *v)
565{
566 struct ubcmtp_softc *sc = v;
567
568 if (usbd_is_dying(sc->sc_udev) || !(sc->sc_status & UBCMTP_ENABLED1))
569 return;
570
571 sc->sc_status &= ~UBCMTP_ENABLED1;
572
573 ubcmtp_raw_mode(sc, 0);
574
575 if (sc->sc_tp_pipe != NULL((void *)0)) {
576 usbd_close_pipe(sc->sc_tp_pipe);
577 sc->sc_tp_pipe = NULL((void *)0);
578 }
579 if (sc->sc_bt_pipe != NULL((void *)0)) {
580 usbd_close_pipe(sc->sc_bt_pipe);
581 sc->sc_bt_pipe = NULL((void *)0);
582 }
583
584 if (sc->tp_pkt != NULL((void *)0)) {
585 free(sc->tp_pkt, M_USBDEV102, sc->tp_maxlen);
586 sc->tp_pkt = NULL((void *)0);
587 }
588 if (sc->bt_pkt != NULL((void *)0)) {
589 free(sc->bt_pkt, M_USBDEV102, sc->bt_maxlen);
590 sc->bt_pkt = NULL((void *)0);
591 }
592}
593
594int
595ubcmtp_ioctl(void *v, unsigned long cmd, caddr_t data, int flag, struct proc *p)
596{
597 struct ubcmtp_softc *sc = v;
598 struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
599 int wsmode;
600
601 DPRINTF("%s: in %s with cmd 0x%lx\n", sc->sc_dev.dv_xname, __func__,
602 cmd);
603
604 switch (cmd) {
605 case WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
: {
606 struct wsmousehw *hw = wsmouse_get_hw(sc->sc_wsmousedev);
607 *(u_int *)data = hw->type;
608 break;
609 }
610
611 case WSMOUSEIO_GCALIBCOORDS((unsigned long)0x40000000 | ((sizeof(struct wsmouse_calibcoords
) & 0x1fff) << 16) | ((('W')) << 8) | ((37)))
:
612 wsmc->minx = sc->dev_type->l_x.min;
613 wsmc->maxx = sc->dev_type->l_x.max;
614 wsmc->miny = sc->dev_type->l_y.min;
615 wsmc->maxy = sc->dev_type->l_y.max;
616 wsmc->swapxy = 0;
617 wsmc->resx = 0;
618 wsmc->resy = 0;
619 break;
620
621 case WSMOUSEIO_SETMODE((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('W')) << 8) | ((38)))
:
622 wsmode = *(u_int *)data;
623 if (wsmode != WSMOUSE_COMPAT0 && wsmode != WSMOUSE_NATIVE1) {
624 printf("%s: invalid mode %d\n", sc->sc_dev.dv_xname,
625 wsmode);
626 return (EINVAL22);
627 }
628 wsmouse_set_mode(sc->sc_wsmousedev, wsmode);
629
630 DPRINTF("%s: changing mode to %s\n",
631 sc->sc_dev.dv_xname, (wsmode == WSMOUSE_COMPAT ? "compat" :
632 "native"));
633
634 break;
635
636 default:
637 return (-1);
638 }
639
640 return (0);
641}
642
643int
644ubcmtp_raw_mode(struct ubcmtp_softc *sc, int enable)
645{
646 usb_device_request_t r;
647 usbd_status err;
648 uint8_t buf[8];
649
650 /* type 3 has no raw mode */
651 if (sc->dev_type->type == UBCMTP_TYPE33)
652 return (0);
653
654 r.bRequest = UR_GET_REPORT0x01;
655 r.bmRequestType = UT_READ_CLASS_INTERFACE(0x80 | 0x20 | 0x01);
656 if (sc->dev_type->type < UBCMTP_TYPE44) {
657 USETW2(r.wValue, UHID_FEATURE_REPORT, 0)((r.wValue)[0] = (u_int8_t)(0), (r.wValue)[1] = (u_int8_t)(0x03
))
;
658 USETW(r.wIndex, 0)(*(u_int16_t *)(r.wIndex) = (0));
659 USETW(r.wLength, UBCMTP_WELLSPRING_MODE_LEN)(*(u_int16_t *)(r.wLength) = (8));
660 } else {
661 USETW2(r.wValue, UHID_FEATURE_REPORT, 2)((r.wValue)[0] = (u_int8_t)(2), (r.wValue)[1] = (u_int8_t)(0x03
))
;
662 USETW(r.wIndex, 2)(*(u_int16_t *)(r.wIndex) = (2));
663 USETW(r.wLength, UBCMTP_WELLSPRING9_MODE_LEN)(*(u_int16_t *)(r.wLength) = (2));
664 }
665
666 err = usbd_do_request(sc->sc_udev, &r, buf);
667 if (err != USBD_NORMAL_COMPLETION) {
668 printf("%s: %s: failed to get feature report\n",
669 sc->sc_dev.dv_xname, __func__);
670 return (err);
671 }
672
673 /* toggle magic byte and write everything back */
674 if (sc->dev_type->type < UBCMTP_TYPE44)
675 buf[0] = (enable ? UBCMTP_WELLSPRING_MODE_RAW0x01 :
676 UBCMTP_WELLSPRING_MODE_HID0x08);
677 else
678 buf[1] = (enable ? UBCMTP_WELLSPRING9_MODE_RAW0x01 :
679 UBCMTP_WELLSPRING9_MODE_HID0x00);
680
681 r.bRequest = UR_SET_REPORT0x09;
682 r.bmRequestType = UT_WRITE_CLASS_INTERFACE(0x00 | 0x20 | 0x01);
683 if (sc->dev_type->type < UBCMTP_TYPE44) {
684 USETW2(r.wValue, UHID_FEATURE_REPORT, 0)((r.wValue)[0] = (u_int8_t)(0), (r.wValue)[1] = (u_int8_t)(0x03
))
;
685 USETW(r.wIndex, 0)(*(u_int16_t *)(r.wIndex) = (0));
686 USETW(r.wLength, UBCMTP_WELLSPRING_MODE_LEN)(*(u_int16_t *)(r.wLength) = (8));
687 } else {
688 USETW2(r.wValue, UHID_FEATURE_REPORT, 2)((r.wValue)[0] = (u_int8_t)(2), (r.wValue)[1] = (u_int8_t)(0x03
))
;
689 USETW(r.wIndex, 2)(*(u_int16_t *)(r.wIndex) = (2));
690 USETW(r.wLength, UBCMTP_WELLSPRING9_MODE_LEN)(*(u_int16_t *)(r.wLength) = (2));
691 }
692
693 err = usbd_do_request(sc->sc_udev, &r, buf);
694 if (err != USBD_NORMAL_COMPLETION) {
695 printf("%s: %s: failed to toggle raw mode\n",
696 sc->sc_dev.dv_xname, __func__);
697 return (err);
698 }
699
700 return (0);
701}
702
703int
704ubcmtp_setup_pipes(struct ubcmtp_softc *sc)
705{
706 usbd_status err;
707 usb_endpoint_descriptor_t *ed;
708
709 if (sc->dev_type->type == UBCMTP_TYPE11) {
710 /* setup physical button pipe */
711
712 ed = usbd_interface2endpoint_descriptor(sc->sc_bt_iface, 0);
713 if (ed == NULL((void *)0)) {
714 printf("%s: failed getting button endpoint descriptor\n",
715 sc->sc_dev.dv_xname);
716 goto fail1;
717 }
718 sc->sc_bt_epaddr = ed->bEndpointAddress;
719 sc->bt_pkt = malloc(sc->bt_maxlen, M_USBDEV102, M_WAITOK0x0001);
720 if (sc->bt_pkt == NULL((void *)0))
721 goto fail1;
722
723 DPRINTF("%s: button iface at 0x%x, max size %d\n",
724 sc->sc_dev.dv_xname, sc->sc_bt_epaddr, sc->bt_maxlen);
725
726 err = usbd_open_pipe_intr(sc->sc_bt_iface, sc->sc_bt_epaddr,
727 USBD_SHORT_XFER_OK0x04, &sc->sc_bt_pipe, sc, sc->bt_pkt,
728 sc->bt_maxlen, ubcmtp_bt_intr, USBD_DEFAULT_INTERVAL(-1));
729 if (err != USBD_NORMAL_COMPLETION) {
730 printf("%s: failed opening button pipe\n",
731 sc->sc_dev.dv_xname);
732 goto fail1;
733 }
734 }
735
736 /* setup trackpad data pipe */
737
738 ed = usbd_interface2endpoint_descriptor(sc->sc_tp_iface, 0);
739 if (ed == NULL((void *)0)) {
740 printf("%s: failed getting trackpad data endpoint descriptor\n",
741 sc->sc_dev.dv_xname);
742 goto fail2;
743 }
744 sc->sc_tp_epaddr = ed->bEndpointAddress;
745 sc->tp_pkt = malloc(sc->tp_maxlen, M_USBDEV102, M_WAITOK0x0001);
746 if (sc->tp_pkt == NULL((void *)0))
747 goto fail2;
748
749 DPRINTF("%s: trackpad data iface at 0x%x, max size %d\n",
750 sc->sc_dev.dv_xname, sc->sc_tp_epaddr, sc->tp_maxlen);
751
752 err = usbd_open_pipe_intr(sc->sc_tp_iface, sc->sc_tp_epaddr,
753 USBD_SHORT_XFER_OK0x04, &sc->sc_tp_pipe, sc, sc->tp_pkt, sc->tp_maxlen,
754 ubcmtp_tp_intr, USBD_DEFAULT_INTERVAL(-1));
755 if (err != USBD_NORMAL_COMPLETION) {
756 printf("%s: error opening trackpad data pipe\n",
757 sc->sc_dev.dv_xname);
758 goto fail2;
759 }
760
761 return (0);
762
763fail2:
764 if (sc->sc_tp_pipe != NULL((void *)0))
765 usbd_close_pipe(sc->sc_tp_pipe);
766 if (sc->tp_pkt != NULL((void *)0))
767 free(sc->tp_pkt, M_USBDEV102, sc->tp_maxlen);
768fail1:
769 if (sc->sc_bt_pipe != NULL((void *)0))
770 usbd_close_pipe(sc->sc_bt_pipe);
771 if (sc->bt_pkt != NULL((void *)0))
772 free(sc->bt_pkt, M_USBDEV102, sc->bt_maxlen);
773
774 return (1);
775}
776
777void
778ubcmtp_tp_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
779{
780 struct ubcmtp_softc *sc = priv;
781 struct ubcmtp_finger *finger;
782 u_int32_t pktlen;
783 int off, s, btn, contacts = 0;
784
785 if (usbd_is_dying(sc->sc_udev) || !(sc->sc_status & UBCMTP_ENABLED1))
786 return;
787
788 if (status != USBD_NORMAL_COMPLETION) {
789 DPRINTF("%s: %s with status 0x%x\n", sc->sc_dev.dv_xname,
790 __func__, status);
791
792 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
793 return;
794 if (status == USBD_STALLED)
795 usbd_clear_endpoint_stall_async(sc->sc_tp_pipe);
796 return;
797 }
798
799 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &pktlen, NULL((void *)0));
800
801 if (sc->tp_pkt == NULL((void *)0) || pktlen < sc->tp_offset)
802 return;
803
804 contacts = 0;
805 for (off = sc->tp_offset; off < pktlen;
806 off += (sizeof(struct ubcmtp_finger) + sc->tp_fingerpad)) {
807 finger = (struct ubcmtp_finger *)(sc->tp_pkt + off);
808
809 if ((int16_t)letoh16(finger->touch_major)((__uint16_t)(finger->touch_major)) == 0)
810 continue; /* finger lifted */
811
812 sc->frame[contacts].x = (int16_t)letoh16(finger->abs_x)((__uint16_t)(finger->abs_x));
813 sc->frame[contacts].y = (int16_t)letoh16(finger->abs_y)((__uint16_t)(finger->abs_y));
814 sc->frame[contacts].pressure = DEFAULT_PRESSURE40;
815 contacts++;
816 }
817
818 btn = sc->btn;
819 if (sc->dev_type->type == UBCMTP_TYPE22)
820 sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE2_BTOFF])((__uint16_t)(sc->tp_pkt[15])));
821 else if (sc->dev_type->type == UBCMTP_TYPE33)
822 sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE3_BTOFF])((__uint16_t)(sc->tp_pkt[23])));
823 else if (sc->dev_type->type == UBCMTP_TYPE44)
824 sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE4_BTOFF])((__uint16_t)(sc->tp_pkt[31])));
825
826 if (contacts || sc->contacts || sc->btn != btn) {
827 sc->contacts = contacts;
828 s = spltty()splraise(0x9);
829 wsmouse_buttons(sc->sc_wsmousedev, sc->btn);
830 wsmouse_mtframe(sc->sc_wsmousedev, sc->frame, contacts);
831 wsmouse_input_sync(sc->sc_wsmousedev);
832 splx(s)spllower(s);
833 }
834}
835
836/* hardware button interrupt */
837void
838ubcmtp_bt_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
839{
840 struct ubcmtp_softc *sc = priv;
841 struct ubcmtp_button *pkt;
842 u_int32_t len;
843
844 if (usbd_is_dying(sc->sc_udev) || !(sc->sc_status & UBCMTP_ENABLED1))
845 return;
846
847 if (status != USBD_NORMAL_COMPLETION) {
848 DPRINTF("%s: %s with status 0x%x\n", sc->sc_dev.dv_xname,
849 __func__, status);
850 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
851 return;
852 if (status == USBD_STALLED)
853 usbd_clear_endpoint_stall_async(sc->sc_tp_pipe);
854 return;
855 }
856
857 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
858
859 if (sc->bt_pkt == NULL((void *)0) || len < sizeof(struct ubcmtp_button))
860 return;
861
862 pkt = (struct ubcmtp_button *)(sc->bt_pkt);
863
864 DPRINTF("%s: button interrupt (%d, %d, %d, %d)", sc->sc_dev.dv_xname,
865 pkt->unused, pkt->button, pkt->rel_x, pkt->rel_y);
866
867 if (pkt->button != sc->btn) {
868 sc->btn = pkt->button;
869 wsmouse_buttons(sc->sc_wsmousedev, sc->btn);
870 wsmouse_input_sync(sc->sc_wsmousedev);
871 }
872}