xref: /freebsd/sys/dev/usb/serial/uvisor.c (revision b3aaa0cc21c63d388230c7ef2a80abd631ff20d5)
1 /*	$NetBSD: uvisor.c,v 1.9 2001/01/23 14:04:14 augustss Exp $	*/
2 /*      $FreeBSD$ */
3 
4 /* Also already merged from NetBSD:
5  *	$NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $
6  *	$NetBSD: uvisor.c,v 1.13 2002/02/11 15:11:49 augustss Exp $
7  *	$NetBSD: uvisor.c,v 1.14 2002/02/27 23:00:03 augustss Exp $
8  *	$NetBSD: uvisor.c,v 1.15 2002/06/16 15:01:31 augustss Exp $
9  *	$NetBSD: uvisor.c,v 1.16 2002/07/11 21:14:36 augustss Exp $
10  *	$NetBSD: uvisor.c,v 1.17 2002/08/13 11:38:15 augustss Exp $
11  *	$NetBSD: uvisor.c,v 1.18 2003/02/05 00:50:14 augustss Exp $
12  *	$NetBSD: uvisor.c,v 1.19 2003/02/07 18:12:37 augustss Exp $
13  *	$NetBSD: uvisor.c,v 1.20 2003/04/11 01:30:10 simonb Exp $
14  */
15 
16 /*-
17  * Copyright (c) 2000 The NetBSD Foundation, Inc.
18  * All rights reserved.
19  *
20  * This code is derived from software contributed to The NetBSD Foundation
21  * by Lennart Augustsson (lennart@augustsson.net) at
22  * Carlstedt Research & Technology.
23  *
24  * Redistribution and use in source and binary forms, with or without
25  * modification, are permitted provided that the following conditions
26  * are met:
27  * 1. Redistributions of source code must retain the above copyright
28  *    notice, this list of conditions and the following disclaimer.
29  * 2. Redistributions in binary form must reproduce the above copyright
30  *    notice, this list of conditions and the following disclaimer in the
31  *    documentation and/or other materials provided with the distribution.
32  * 3. All advertising materials mentioning features or use of this software
33  *    must display the following acknowledgement:
34  *        This product includes software developed by the NetBSD
35  *        Foundation, Inc. and its contributors.
36  * 4. Neither the name of The NetBSD Foundation nor the names of its
37  *    contributors may be used to endorse or promote products derived
38  *    from this software without specific prior written permission.
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
41  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
42  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
45  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
46  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50  * POSSIBILITY OF SUCH DAMAGE.
51  */
52 
53 /*
54  * Handspring Visor (Palmpilot compatible PDA) driver
55  */
56 
57 #include "usbdevs.h"
58 #include <dev/usb/usb.h>
59 #include <dev/usb/usb_mfunc.h>
60 #include <dev/usb/usb_error.h>
61 #include <dev/usb/usb_cdc.h>
62 #include <dev/usb/usb_ioctl.h>
63 
64 #define	USB_DEBUG_VAR uvisor_debug
65 
66 #include <dev/usb/usb_core.h>
67 #include <dev/usb/usb_debug.h>
68 #include <dev/usb/usb_process.h>
69 #include <dev/usb/usb_request.h>
70 #include <dev/usb/usb_lookup.h>
71 #include <dev/usb/usb_util.h>
72 #include <dev/usb/usb_busdma.h>
73 
74 #include <dev/usb/serial/usb_serial.h>
75 
76 #if USB_DEBUG
77 static int uvisor_debug = 0;
78 
79 SYSCTL_NODE(_hw_usb2, OID_AUTO, uvisor, CTLFLAG_RW, 0, "USB uvisor");
80 SYSCTL_INT(_hw_usb2_uvisor, OID_AUTO, debug, CTLFLAG_RW,
81     &uvisor_debug, 0, "Debug level");
82 #endif
83 
84 #define	UVISOR_CONFIG_INDEX	0
85 #define	UVISOR_IFACE_INDEX	0
86 #define	UVISOR_BUFSIZE       1024	/* bytes */
87 
88 /* From the Linux driver */
89 /*
90  * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
91  * are available to be transfered to the host for the specified endpoint.
92  * Currently this is not used, and always returns 0x0001
93  */
94 #define	UVISOR_REQUEST_BYTES_AVAILABLE		0x01
95 
96 /*
97  * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
98  * is now closing the pipe. An empty packet is sent in response.
99  */
100 #define	UVISOR_CLOSE_NOTIFICATION		0x02
101 
102 /*
103  * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
104  * get the endpoints used by the connection.
105  */
106 #define	UVISOR_GET_CONNECTION_INFORMATION	0x03
107 
108 /*
109  * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format
110  */
111 #define	UVISOR_MAX_CONN 8
112 struct uvisor_connection_info {
113 	uWord	num_ports;
114 	struct {
115 		uByte	port_function_id;
116 		uByte	port;
117 	} __packed connections[UVISOR_MAX_CONN];
118 } __packed;
119 
120 #define	UVISOR_CONNECTION_INFO_SIZE 18
121 
122 /* struct uvisor_connection_info.connection[x].port defines: */
123 #define	UVISOR_ENDPOINT_1		0x01
124 #define	UVISOR_ENDPOINT_2		0x02
125 
126 /* struct uvisor_connection_info.connection[x].port_function_id defines: */
127 #define	UVISOR_FUNCTION_GENERIC		0x00
128 #define	UVISOR_FUNCTION_DEBUGGER	0x01
129 #define	UVISOR_FUNCTION_HOTSYNC		0x02
130 #define	UVISOR_FUNCTION_CONSOLE		0x03
131 #define	UVISOR_FUNCTION_REMOTE_FILE_SYS	0x04
132 
133 /*
134  * Unknown PalmOS stuff.
135  */
136 #define	UVISOR_GET_PALM_INFORMATION		0x04
137 #define	UVISOR_GET_PALM_INFORMATION_LEN		0x44
138 
139 struct uvisor_palm_connection_info {
140 	uByte	num_ports;
141 	uByte	endpoint_numbers_different;
142 	uWord	reserved1;
143 	struct {
144 		uDWord	port_function_id;
145 		uByte	port;
146 		uByte	end_point_info;
147 		uWord	reserved;
148 	} __packed connections[UVISOR_MAX_CONN];
149 } __packed;
150 
151 enum {
152 	UVISOR_BULK_DT_WR,
153 	UVISOR_BULK_DT_RD,
154 	UVISOR_N_TRANSFER,
155 };
156 
157 struct uvisor_softc {
158 	struct usb2_com_super_softc sc_super_ucom;
159 	struct usb2_com_softc sc_ucom;
160 
161 	struct usb2_xfer *sc_xfer[UVISOR_N_TRANSFER];
162 	struct usb2_device *sc_udev;
163 
164 	uint16_t sc_flag;
165 #define	UVISOR_FLAG_PALM4       0x0001
166 #define	UVISOR_FLAG_VISOR       0x0002
167 #define	UVISOR_FLAG_PALM35      0x0004
168 #define	UVISOR_FLAG_SEND_NOTIFY 0x0008
169 
170 	uint8_t	sc_iface_no;
171 	uint8_t	sc_iface_index;
172 };
173 
174 /* prototypes */
175 
176 static device_probe_t uvisor_probe;
177 static device_attach_t uvisor_attach;
178 static device_detach_t uvisor_detach;
179 
180 static usb2_callback_t uvisor_write_callback;
181 static usb2_callback_t uvisor_read_callback;
182 
183 static usb2_error_t uvisor_init(struct uvisor_softc *, struct usb2_device *,
184 		    struct usb2_config *);
185 static void	uvisor_cfg_open(struct usb2_com_softc *);
186 static void	uvisor_cfg_close(struct usb2_com_softc *);
187 static void	uvisor_start_read(struct usb2_com_softc *);
188 static void	uvisor_stop_read(struct usb2_com_softc *);
189 static void	uvisor_start_write(struct usb2_com_softc *);
190 static void	uvisor_stop_write(struct usb2_com_softc *);
191 
192 static const struct usb2_config uvisor_config[UVISOR_N_TRANSFER] = {
193 
194 	[UVISOR_BULK_DT_WR] = {
195 		.type = UE_BULK,
196 		.endpoint = UE_ADDR_ANY,
197 		.direction = UE_DIR_OUT,
198 		.mh.bufsize = UVISOR_BUFSIZE,	/* bytes */
199 		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
200 		.mh.callback = &uvisor_write_callback,
201 	},
202 
203 	[UVISOR_BULK_DT_RD] = {
204 		.type = UE_BULK,
205 		.endpoint = UE_ADDR_ANY,
206 		.direction = UE_DIR_IN,
207 		.mh.bufsize = UVISOR_BUFSIZE,	/* bytes */
208 		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
209 		.mh.callback = &uvisor_read_callback,
210 	},
211 };
212 
213 static const struct usb2_com_callback uvisor_callback = {
214 	.usb2_com_cfg_open = &uvisor_cfg_open,
215 	.usb2_com_cfg_close = &uvisor_cfg_close,
216 	.usb2_com_start_read = &uvisor_start_read,
217 	.usb2_com_stop_read = &uvisor_stop_read,
218 	.usb2_com_start_write = &uvisor_start_write,
219 	.usb2_com_stop_write = &uvisor_stop_write,
220 };
221 
222 static device_method_t uvisor_methods[] = {
223 	DEVMETHOD(device_probe, uvisor_probe),
224 	DEVMETHOD(device_attach, uvisor_attach),
225 	DEVMETHOD(device_detach, uvisor_detach),
226 	{0, 0}
227 };
228 
229 static devclass_t uvisor_devclass;
230 
231 static driver_t uvisor_driver = {
232 	.name = "uvisor",
233 	.methods = uvisor_methods,
234 	.size = sizeof(struct uvisor_softc),
235 };
236 
237 DRIVER_MODULE(uvisor, ushub, uvisor_driver, uvisor_devclass, NULL, 0);
238 MODULE_DEPEND(uvisor, ucom, 1, 1, 1);
239 MODULE_DEPEND(uvisor, usb, 1, 1, 1);
240 
241 static const struct usb2_device_id uvisor_devs[] = {
242 	{USB_VPI(USB_VENDOR_ACEECA, USB_PRODUCT_ACEECA_MEZ1000, UVISOR_FLAG_PALM4)},
243 	{USB_VPI(USB_VENDOR_GARMIN, USB_PRODUCT_GARMIN_IQUE_3600, UVISOR_FLAG_PALM4)},
244 	{USB_VPI(USB_VENDOR_FOSSIL, USB_PRODUCT_FOSSIL_WRISTPDA, UVISOR_FLAG_PALM4)},
245 	{USB_VPI(USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR, UVISOR_FLAG_VISOR)},
246 	{USB_VPI(USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO, UVISOR_FLAG_PALM4)},
247 	{USB_VPI(USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO600, UVISOR_FLAG_PALM4)},
248 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M500, UVISOR_FLAG_PALM4)},
249 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M505, UVISOR_FLAG_PALM4)},
250 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M515, UVISOR_FLAG_PALM4)},
251 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_I705, UVISOR_FLAG_PALM4)},
252 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M125, UVISOR_FLAG_PALM4)},
253 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M130, UVISOR_FLAG_PALM4)},
254 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_Z, UVISOR_FLAG_PALM4)},
255 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_T, UVISOR_FLAG_PALM4)},
256 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE, UVISOR_FLAG_PALM4)},
257 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE31, UVISOR_FLAG_PALM4)},
258 	{USB_VPI(USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_I500, UVISOR_FLAG_PALM4)},
259 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40, 0)},
260 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41, UVISOR_FLAG_PALM4)},
261 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_S360, UVISOR_FLAG_PALM4)},
262 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_NX60, UVISOR_FLAG_PALM4)},
263 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_35, UVISOR_FLAG_PALM35)},
264 /*  {USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_25, UVISOR_FLAG_PALM4 )}, */
265 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_TJ37, UVISOR_FLAG_PALM4)},
266 /*  {USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_TH55, UVISOR_FLAG_PALM4 )}, See PR 80935 */
267 	{USB_VPI(USB_VENDOR_TAPWAVE, USB_PRODUCT_TAPWAVE_ZODIAC, UVISOR_FLAG_PALM4)},
268 };
269 
270 static int
271 uvisor_probe(device_t dev)
272 {
273 	struct usb2_attach_arg *uaa = device_get_ivars(dev);
274 
275 	if (uaa->usb2_mode != USB_MODE_HOST) {
276 		return (ENXIO);
277 	}
278 	if (uaa->info.bConfigIndex != UVISOR_CONFIG_INDEX) {
279 		return (ENXIO);
280 	}
281 	if (uaa->info.bIfaceIndex != UVISOR_IFACE_INDEX) {
282 		return (ENXIO);
283 	}
284 	return (usb2_lookup_id_by_uaa(uvisor_devs, sizeof(uvisor_devs), uaa));
285 }
286 
287 static int
288 uvisor_attach(device_t dev)
289 {
290 	struct usb2_attach_arg *uaa = device_get_ivars(dev);
291 	struct uvisor_softc *sc = device_get_softc(dev);
292 	struct usb2_config uvisor_config_copy[UVISOR_N_TRANSFER];
293 	int error;
294 
295 	DPRINTF("sc=%p\n", sc);
296 	bcopy(uvisor_config, uvisor_config_copy,
297 	    sizeof(uvisor_config_copy));
298 	device_set_usb2_desc(dev);
299 
300 	sc->sc_udev = uaa->device;
301 
302 	/* configure the device */
303 
304 	sc->sc_flag = USB_GET_DRIVER_INFO(uaa);
305 	sc->sc_iface_no = uaa->info.bIfaceNum;
306 	sc->sc_iface_index = UVISOR_IFACE_INDEX;
307 
308 	error = uvisor_init(sc, uaa->device, uvisor_config_copy);
309 
310 	if (error) {
311 		DPRINTF("init failed, error=%s\n",
312 		    usb2_errstr(error));
313 		goto detach;
314 	}
315 	error = usb2_transfer_setup(uaa->device, &sc->sc_iface_index,
316 	    sc->sc_xfer, uvisor_config_copy, UVISOR_N_TRANSFER,
317 	    sc, &Giant);
318 	if (error) {
319 		DPRINTF("could not allocate all pipes\n");
320 		goto detach;
321 	}
322 	/* clear stall at first run */
323 	usb2_transfer_set_stall(sc->sc_xfer[UVISOR_BULK_DT_WR]);
324 	usb2_transfer_set_stall(sc->sc_xfer[UVISOR_BULK_DT_RD]);
325 
326 	error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
327 	    &uvisor_callback, &Giant);
328 	if (error) {
329 		DPRINTF("usb2_com_attach failed\n");
330 		goto detach;
331 	}
332 	return (0);
333 
334 detach:
335 	uvisor_detach(dev);
336 	return (ENXIO);
337 }
338 
339 static int
340 uvisor_detach(device_t dev)
341 {
342 	struct uvisor_softc *sc = device_get_softc(dev);
343 
344 	DPRINTF("sc=%p\n", sc);
345 
346 	usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
347 
348 	usb2_transfer_unsetup(sc->sc_xfer, UVISOR_N_TRANSFER);
349 
350 	return (0);
351 }
352 
353 static usb2_error_t
354 uvisor_init(struct uvisor_softc *sc, struct usb2_device *udev, struct usb2_config *config)
355 {
356 	usb2_error_t err = 0;
357 	struct usb2_device_request req;
358 	struct uvisor_connection_info coninfo;
359 	struct uvisor_palm_connection_info pconinfo;
360 	uint16_t actlen;
361 	uWord wAvail;
362 	uint8_t buffer[256];
363 
364 	if (sc->sc_flag & UVISOR_FLAG_VISOR) {
365 		DPRINTF("getting connection info\n");
366 		req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
367 		req.bRequest = UVISOR_GET_CONNECTION_INFORMATION;
368 		USETW(req.wValue, 0);
369 		USETW(req.wIndex, 0);
370 		USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
371 		err = usb2_do_request_flags
372 		    (udev, &Giant, &req, &coninfo, USB_SHORT_XFER_OK,
373 		    &actlen, USB_DEFAULT_TIMEOUT);
374 
375 		if (err) {
376 			goto done;
377 		}
378 	}
379 #if USB_DEBUG
380 	if (sc->sc_flag & UVISOR_FLAG_VISOR) {
381 		uint16_t i, np;
382 		const char *desc;
383 
384 		np = UGETW(coninfo.num_ports);
385 		if (np > UVISOR_MAX_CONN) {
386 			np = UVISOR_MAX_CONN;
387 		}
388 		DPRINTF("Number of ports: %d\n", np);
389 
390 		for (i = 0; i < np; ++i) {
391 			switch (coninfo.connections[i].port_function_id) {
392 			case UVISOR_FUNCTION_GENERIC:
393 				desc = "Generic";
394 				break;
395 			case UVISOR_FUNCTION_DEBUGGER:
396 				desc = "Debugger";
397 				break;
398 			case UVISOR_FUNCTION_HOTSYNC:
399 				desc = "HotSync";
400 				break;
401 			case UVISOR_FUNCTION_REMOTE_FILE_SYS:
402 				desc = "Remote File System";
403 				break;
404 			default:
405 				desc = "unknown";
406 				break;
407 			}
408 			DPRINTF("Port %d is for %s\n",
409 			    coninfo.connections[i].port, desc);
410 		}
411 	}
412 #endif
413 
414 	if (sc->sc_flag & UVISOR_FLAG_PALM4) {
415 		uint8_t port;
416 
417 		/* Palm OS 4.0 Hack */
418 		req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
419 		req.bRequest = UVISOR_GET_PALM_INFORMATION;
420 		USETW(req.wValue, 0);
421 		USETW(req.wIndex, 0);
422 		USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
423 
424 		err = usb2_do_request_flags
425 		    (udev, &Giant, &req, &pconinfo, USB_SHORT_XFER_OK,
426 		    &actlen, USB_DEFAULT_TIMEOUT);
427 
428 		if (err) {
429 			goto done;
430 		}
431 		if (actlen < 12) {
432 			DPRINTF("too little data\n");
433 			err = USB_ERR_INVAL;
434 			goto done;
435 		}
436 		if (pconinfo.endpoint_numbers_different) {
437 			port = pconinfo.connections[0].end_point_info;
438 			config[0].endpoint = (port & 0xF);	/* output */
439 			config[1].endpoint = (port >> 4);	/* input */
440 		} else {
441 			port = pconinfo.connections[0].port;
442 			config[0].endpoint = (port & 0xF);	/* output */
443 			config[1].endpoint = (port & 0xF);	/* input */
444 		}
445 #if 0
446 		req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
447 		req.bRequest = UVISOR_GET_PALM_INFORMATION;
448 		USETW(req.wValue, 0);
449 		USETW(req.wIndex, 0);
450 		USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
451 		err = usb2_do_request(udev, &req, buffer);
452 		if (err) {
453 			goto done;
454 		}
455 #endif
456 	}
457 	if (sc->sc_flag & UVISOR_FLAG_PALM35) {
458 		/* get the config number */
459 		DPRINTF("getting config info\n");
460 		req.bmRequestType = UT_READ;
461 		req.bRequest = UR_GET_CONFIG;
462 		USETW(req.wValue, 0);
463 		USETW(req.wIndex, 0);
464 		USETW(req.wLength, 1);
465 
466 		err = usb2_do_request(udev, &Giant, &req, buffer);
467 		if (err) {
468 			goto done;
469 		}
470 		/* get the interface number */
471 		DPRINTF("get the interface number\n");
472 		req.bmRequestType = UT_READ_DEVICE;
473 		req.bRequest = UR_GET_INTERFACE;
474 		USETW(req.wValue, 0);
475 		USETW(req.wIndex, 0);
476 		USETW(req.wLength, 1);
477 		err = usb2_do_request(udev, &Giant, &req, buffer);
478 		if (err) {
479 			goto done;
480 		}
481 	}
482 	DPRINTF("getting available bytes\n");
483 	req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
484 	req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE;
485 	USETW(req.wValue, 0);
486 	USETW(req.wIndex, 5);
487 	USETW(req.wLength, sizeof(wAvail));
488 	err = usb2_do_request(udev, &Giant, &req, &wAvail);
489 	if (err) {
490 		goto done;
491 	}
492 	DPRINTF("avail=%d\n", UGETW(wAvail));
493 
494 	DPRINTF("done\n");
495 done:
496 	return (err);
497 }
498 
499 static void
500 uvisor_cfg_open(struct usb2_com_softc *ucom)
501 {
502 	return;
503 }
504 
505 static void
506 uvisor_cfg_close(struct usb2_com_softc *ucom)
507 {
508 	struct uvisor_softc *sc = ucom->sc_parent;
509 	uint8_t buffer[UVISOR_CONNECTION_INFO_SIZE];
510 	struct usb2_device_request req;
511 	usb2_error_t err;
512 
513 	req.bmRequestType = UT_READ_VENDOR_ENDPOINT;	/* XXX read? */
514 	req.bRequest = UVISOR_CLOSE_NOTIFICATION;
515 	USETW(req.wValue, 0);
516 	USETW(req.wIndex, 0);
517 	USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
518 
519 	err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
520 	    &req, buffer, 0, 1000);
521 	if (err) {
522 		DPRINTFN(0, "close notification failed, error=%s\n",
523 		    usb2_errstr(err));
524 	}
525 }
526 
527 static void
528 uvisor_start_read(struct usb2_com_softc *ucom)
529 {
530 	struct uvisor_softc *sc = ucom->sc_parent;
531 
532 	usb2_transfer_start(sc->sc_xfer[UVISOR_BULK_DT_RD]);
533 }
534 
535 static void
536 uvisor_stop_read(struct usb2_com_softc *ucom)
537 {
538 	struct uvisor_softc *sc = ucom->sc_parent;
539 
540 	usb2_transfer_stop(sc->sc_xfer[UVISOR_BULK_DT_RD]);
541 }
542 
543 static void
544 uvisor_start_write(struct usb2_com_softc *ucom)
545 {
546 	struct uvisor_softc *sc = ucom->sc_parent;
547 
548 	usb2_transfer_start(sc->sc_xfer[UVISOR_BULK_DT_WR]);
549 }
550 
551 static void
552 uvisor_stop_write(struct usb2_com_softc *ucom)
553 {
554 	struct uvisor_softc *sc = ucom->sc_parent;
555 
556 	usb2_transfer_stop(sc->sc_xfer[UVISOR_BULK_DT_WR]);
557 }
558 
559 static void
560 uvisor_write_callback(struct usb2_xfer *xfer)
561 {
562 	struct uvisor_softc *sc = xfer->priv_sc;
563 	uint32_t actlen;
564 
565 	switch (USB_GET_STATE(xfer)) {
566 	case USB_ST_SETUP:
567 	case USB_ST_TRANSFERRED:
568 tr_setup:
569 		if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0,
570 		    UVISOR_BUFSIZE, &actlen)) {
571 
572 			xfer->frlengths[0] = actlen;
573 			usb2_start_hardware(xfer);
574 		}
575 		return;
576 
577 	default:			/* Error */
578 		if (xfer->error != USB_ERR_CANCELLED) {
579 			/* try to clear stall first */
580 			xfer->flags.stall_pipe = 1;
581 			goto tr_setup;
582 		}
583 		return;
584 	}
585 }
586 
587 static void
588 uvisor_read_callback(struct usb2_xfer *xfer)
589 {
590 	struct uvisor_softc *sc = xfer->priv_sc;
591 
592 	switch (USB_GET_STATE(xfer)) {
593 	case USB_ST_TRANSFERRED:
594 		usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0, xfer->actlen);
595 
596 	case USB_ST_SETUP:
597 tr_setup:
598 		xfer->frlengths[0] = xfer->max_data_length;
599 		usb2_start_hardware(xfer);
600 		return;
601 
602 	default:			/* Error */
603 		if (xfer->error != USB_ERR_CANCELLED) {
604 			/* try to clear stall first */
605 			xfer->flags.stall_pipe = 1;
606 			goto tr_setup;
607 		}
608 		return;
609 	}
610 }
611