uvisor.c revision 190581
118334Speter/*	$NetBSD: uvisor.c,v 1.9 2001/01/23 14:04:14 augustss Exp $	*/
218334Speter/*      $FreeBSD: head/sys/dev/usb/serial/uvisor.c 190581 2009-03-30 22:18:38Z mav $ */
390075Sobrien
4169689Skan/* Also already merged from NetBSD:
518334Speter *	$NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $
690075Sobrien *	$NetBSD: uvisor.c,v 1.13 2002/02/11 15:11:49 augustss Exp $
718334Speter *	$NetBSD: uvisor.c,v 1.14 2002/02/27 23:00:03 augustss Exp $
890075Sobrien *	$NetBSD: uvisor.c,v 1.15 2002/06/16 15:01:31 augustss Exp $
990075Sobrien *	$NetBSD: uvisor.c,v 1.16 2002/07/11 21:14:36 augustss Exp $
1090075Sobrien *	$NetBSD: uvisor.c,v 1.17 2002/08/13 11:38:15 augustss Exp $
1190075Sobrien *	$NetBSD: uvisor.c,v 1.18 2003/02/05 00:50:14 augustss Exp $
1218334Speter *	$NetBSD: uvisor.c,v 1.19 2003/02/07 18:12:37 augustss Exp $
1390075Sobrien *	$NetBSD: uvisor.c,v 1.20 2003/04/11 01:30:10 simonb Exp $
1490075Sobrien */
1590075Sobrien
1690075Sobrien/*-
1718334Speter * Copyright (c) 2000 The NetBSD Foundation, Inc.
1818334Speter * All rights reserved.
1990075Sobrien *
20169689Skan * This code is derived from software contributed to The NetBSD Foundation
21169689Skan * by Lennart Augustsson (lennart@augustsson.net) at
2218334Speter * Carlstedt Research & Technology.
23132718Skan *
24132718Skan * Redistribution and use in source and binary forms, with or without
25132718Skan * modification, are permitted provided that the following conditions
2618334Speter * are met:
27132718Skan * 1. Redistributions of source code must retain the above copyright
2818334Speter *    notice, this list of conditions and the following disclaimer.
2918334Speter * 2. Redistributions in binary form must reproduce the above copyright
3018334Speter *    notice, this list of conditions and the following disclaimer in the
31132718Skan *    documentation and/or other materials provided with the distribution.
3218334Speter * 3. All advertising materials mentioning features or use of this software
3318334Speter *    must display the following acknowledgement:
3418334Speter *        This product includes software developed by the NetBSD
35132718Skan *        Foundation, Inc. and its contributors.
3618334Speter * 4. Neither the name of The NetBSD Foundation nor the names of its
3790075Sobrien *    contributors may be used to endorse or promote products derived
3818334Speter *    from this software without specific prior written permission.
3918334Speter *
40132718Skan * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
4118334Speter * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
4218334Speter * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43132718Skan * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
4418334Speter * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
4518334Speter * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
4618334Speter * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47132718Skan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
4818334Speter * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49169689Skan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50169689Skan * POSSIBILITY OF SUCH DAMAGE.
51169689Skan */
52169689Skan
5318334Speter/*
5418334Speter * Handspring Visor (Palmpilot compatible PDA) driver
55132718Skan */
5618334Speter
5718334Speter#include "usbdevs.h"
5818334Speter#include <dev/usb/usb.h>
5918334Speter#include <dev/usb/usb_mfunc.h>
6018334Speter#include <dev/usb/usb_error.h>
6118334Speter#include <dev/usb/usb_cdc.h>
62132718Skan#include <dev/usb/usb_ioctl.h>
6318334Speter
6418334Speter#define	USB_DEBUG_VAR uvisor_debug
6518334Speter
6618334Speter#include <dev/usb/usb_core.h>
67132718Skan#include <dev/usb/usb_debug.h>
6818334Speter#include <dev/usb/usb_process.h>
6918334Speter#include <dev/usb/usb_request.h>
70169689Skan#include <dev/usb/usb_lookup.h>
7118334Speter#include <dev/usb/usb_util.h>
7218334Speter#include <dev/usb/usb_busdma.h>
7318334Speter
7418334Speter#include <dev/usb/serial/usb_serial.h>
75169689Skan
7618334Speter#if USB_DEBUG
7718334Speterstatic int uvisor_debug = 0;
7818334Speter
79132718SkanSYSCTL_NODE(_hw_usb2, OID_AUTO, uvisor, CTLFLAG_RW, 0, "USB uvisor");
8018334SpeterSYSCTL_INT(_hw_usb2_uvisor, OID_AUTO, debug, CTLFLAG_RW,
8118334Speter    &uvisor_debug, 0, "Debug level");
8218334Speter#endif
83132718Skan
8418334Speter#define	UVISOR_CONFIG_INDEX	0
8518334Speter#define	UVISOR_IFACE_INDEX	0
8618334Speter#define	UVISOR_BUFSIZE       1024	/* bytes */
87132718Skan
8818334Speter/* From the Linux driver */
8950397Sobrien/*
9050397Sobrien * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
9150397Sobrien * are available to be transfered to the host for the specified endpoint.
92132718Skan * Currently this is not used, and always returns 0x0001
9350397Sobrien */
9452284Sobrien#define	UVISOR_REQUEST_BYTES_AVAILABLE		0x01
9552284Sobrien
96132718Skan/*
9752284Sobrien * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
9818334Speter * is now closing the pipe. An empty packet is sent in response.
99132718Skan */
10018334Speter#define	UVISOR_CLOSE_NOTIFICATION		0x02
10118334Speter
10218334Speter/*
103132718Skan * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
10418334Speter * get the endpoints used by the connection.
10518334Speter */
10618334Speter#define	UVISOR_GET_CONNECTION_INFORMATION	0x03
10718334Speter
108132718Skan/*
10918334Speter * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format
11018334Speter */
11118334Speter#define	UVISOR_MAX_CONN 8
112223262Sbenlstruct uvisor_connection_info {
113132718Skan	uWord	num_ports;
114132718Skan	struct {
115132718Skan		uByte	port_function_id;
116132718Skan		uByte	port;
117132718Skan	} __packed connections[UVISOR_MAX_CONN];
118132718Skan} __packed;
119223262Sbenl
120132718Skan#define	UVISOR_CONNECTION_INFO_SIZE 18
121132718Skan
12218334Speter/* struct uvisor_connection_info.connection[x].port defines: */
123132718Skan#define	UVISOR_ENDPOINT_1		0x01
124132718Skan#define	UVISOR_ENDPOINT_2		0x02
125132718Skan
12618334Speter/* struct uvisor_connection_info.connection[x].port_function_id defines: */
12718334Speter#define	UVISOR_FUNCTION_GENERIC		0x00
128132718Skan#define	UVISOR_FUNCTION_DEBUGGER	0x01
12918334Speter#define	UVISOR_FUNCTION_HOTSYNC		0x02
13018334Speter#define	UVISOR_FUNCTION_CONSOLE		0x03
131132718Skan#define	UVISOR_FUNCTION_REMOTE_FILE_SYS	0x04
13218334Speter
133117395Skan/*
13490075Sobrien * Unknown PalmOS stuff.
13590075Sobrien */
136132718Skan#define	UVISOR_GET_PALM_INFORMATION		0x04
13790075Sobrien#define	UVISOR_GET_PALM_INFORMATION_LEN		0x44
13818334Speter
13918334Speterstruct uvisor_palm_connection_info {
140132718Skan	uByte	num_ports;
14118334Speter	uByte	endpoint_numbers_different;
14218334Speter	uWord	reserved1;
14318334Speter	struct {
144132718Skan		uDWord	port_function_id;
14550397Sobrien		uByte	port;
14690075Sobrien		uByte	end_point_info;
147132718Skan		uWord	reserved;
14890075Sobrien	} __packed connections[UVISOR_MAX_CONN];
14950397Sobrien} __packed;
150132718Skan
15118334Speterenum {
15218334Speter	UVISOR_BULK_DT_WR,
15318334Speter	UVISOR_BULK_DT_RD,
15450397Sobrien	UVISOR_N_TRANSFER,
155132718Skan};
15696263Sobrien
157132718Skanstruct uvisor_softc {
15850397Sobrien	struct usb2_com_super_softc sc_super_ucom;
15950397Sobrien	struct usb2_com_softc sc_ucom;
160132718Skan
16150397Sobrien	struct usb2_xfer *sc_xfer[UVISOR_N_TRANSFER];
16218334Speter	struct usb2_device *sc_udev;
16318334Speter	struct mtx sc_mtx;
16418334Speter
16518334Speter	uint16_t sc_flag;
16618334Speter#define	UVISOR_FLAG_PALM4       0x0001
16718334Speter#define	UVISOR_FLAG_VISOR       0x0002
16818334Speter#define	UVISOR_FLAG_PALM35      0x0004
169132718Skan#define	UVISOR_FLAG_SEND_NOTIFY 0x0008
17018334Speter
171132718Skan	uint8_t	sc_iface_no;
17218334Speter	uint8_t	sc_iface_index;
173132718Skan};
17450397Sobrien
17518334Speter/* prototypes */
17618334Speter
177132718Skanstatic device_probe_t uvisor_probe;
17818334Speterstatic device_attach_t uvisor_attach;
17918334Speterstatic device_detach_t uvisor_detach;
18018334Speter
18118334Speterstatic usb2_callback_t uvisor_write_callback;
18218334Speterstatic usb2_callback_t uvisor_read_callback;
183132718Skan
18418334Speterstatic usb2_error_t uvisor_init(struct uvisor_softc *, struct usb2_device *,
18518334Speter		    struct usb2_config *);
18618334Speterstatic void	uvisor_cfg_open(struct usb2_com_softc *);
187132718Skanstatic void	uvisor_cfg_close(struct usb2_com_softc *);
18818334Speterstatic void	uvisor_start_read(struct usb2_com_softc *);
18918334Speterstatic void	uvisor_stop_read(struct usb2_com_softc *);
19018334Speterstatic void	uvisor_start_write(struct usb2_com_softc *);
19118334Speterstatic void	uvisor_stop_write(struct usb2_com_softc *);
19218334Speter
19318334Speterstatic const struct usb2_config uvisor_config[UVISOR_N_TRANSFER] = {
19418334Speter
19518334Speter	[UVISOR_BULK_DT_WR] = {
19618334Speter		.type = UE_BULK,
19718334Speter		.endpoint = UE_ADDR_ANY,
198132718Skan		.direction = UE_DIR_OUT,
19918334Speter		.mh.bufsize = UVISOR_BUFSIZE,	/* bytes */
200169689Skan		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
201169689Skan		.mh.callback = &uvisor_write_callback,
202169689Skan	},
203169689Skan
204215840Sdim	[UVISOR_BULK_DT_RD] = {
205215840Sdim		.type = UE_BULK,
206215840Sdim		.endpoint = UE_ADDR_ANY,
207132718Skan		.direction = UE_DIR_IN,
20818334Speter		.mh.bufsize = UVISOR_BUFSIZE,	/* bytes */
20990075Sobrien		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
210132718Skan		.mh.callback = &uvisor_read_callback,
21190075Sobrien	},
21290075Sobrien};
213132718Skan
21490075Sobrienstatic const struct usb2_com_callback uvisor_callback = {
21590075Sobrien	.usb2_com_cfg_open = &uvisor_cfg_open,
216132718Skan	.usb2_com_cfg_close = &uvisor_cfg_close,
21790075Sobrien	.usb2_com_start_read = &uvisor_start_read,
21818334Speter	.usb2_com_stop_read = &uvisor_stop_read,
219132718Skan	.usb2_com_start_write = &uvisor_start_write,
22018334Speter	.usb2_com_stop_write = &uvisor_stop_write,
22118334Speter};
222132718Skan
22318334Speterstatic device_method_t uvisor_methods[] = {
224169689Skan	DEVMETHOD(device_probe, uvisor_probe),
225169689Skan	DEVMETHOD(device_attach, uvisor_attach),
226169689Skan	DEVMETHOD(device_detach, uvisor_detach),
227169689Skan	{0, 0}
228169689Skan};
229169689Skan
230169689Skanstatic devclass_t uvisor_devclass;
231169689Skan
232169689Skanstatic driver_t uvisor_driver = {
233169689Skan	.name = "uvisor",
234132718Skan	.methods = uvisor_methods,
23518334Speter	.size = sizeof(struct uvisor_softc),
23690075Sobrien};
23790075Sobrien
23890075SobrienDRIVER_MODULE(uvisor, uhub, uvisor_driver, uvisor_devclass, NULL, 0);
23990075SobrienMODULE_DEPEND(uvisor, ucom, 1, 1, 1);
24090075SobrienMODULE_DEPEND(uvisor, usb, 1, 1, 1);
24190075Sobrien
24290075Sobrienstatic const struct usb2_device_id uvisor_devs[] = {
243132718Skan	{USB_VPI(USB_VENDOR_ACEECA, USB_PRODUCT_ACEECA_MEZ1000, UVISOR_FLAG_PALM4)},
24490075Sobrien	{USB_VPI(USB_VENDOR_GARMIN, USB_PRODUCT_GARMIN_IQUE_3600, UVISOR_FLAG_PALM4)},
24590075Sobrien	{USB_VPI(USB_VENDOR_FOSSIL, USB_PRODUCT_FOSSIL_WRISTPDA, UVISOR_FLAG_PALM4)},
24690075Sobrien	{USB_VPI(USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR, UVISOR_FLAG_VISOR)},
247132718Skan	{USB_VPI(USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO, UVISOR_FLAG_PALM4)},
24818334Speter	{USB_VPI(USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO600, UVISOR_FLAG_PALM4)},
24990075Sobrien	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M500, UVISOR_FLAG_PALM4)},
250132718Skan	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M505, UVISOR_FLAG_PALM4)},
25118334Speter	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M515, UVISOR_FLAG_PALM4)},
25290075Sobrien	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_I705, UVISOR_FLAG_PALM4)},
25390075Sobrien	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M125, UVISOR_FLAG_PALM4)},
254169689Skan	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_M130, UVISOR_FLAG_PALM4)},
255169689Skan	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_Z, UVISOR_FLAG_PALM4)},
256132718Skan	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_T, UVISOR_FLAG_PALM4)},
25790075Sobrien	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE, UVISOR_FLAG_PALM4)},
25890075Sobrien	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE31, UVISOR_FLAG_PALM4)},
25990075Sobrien	{USB_VPI(USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_I500, UVISOR_FLAG_PALM4)},
26090075Sobrien	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40, 0)},
26190075Sobrien	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41, UVISOR_FLAG_PALM4)},
26290075Sobrien	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_S360, UVISOR_FLAG_PALM4)},
26390075Sobrien	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_NX60, UVISOR_FLAG_PALM4)},
264117395Skan	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_35, UVISOR_FLAG_PALM35)},
26518334Speter/*  {USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_25, UVISOR_FLAG_PALM4 )}, */
266132718Skan	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_TJ37, UVISOR_FLAG_PALM4)},
26718334Speter/*  {USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_TH55, UVISOR_FLAG_PALM4 )}, See PR 80935 */
26818334Speter	{USB_VPI(USB_VENDOR_TAPWAVE, USB_PRODUCT_TAPWAVE_ZODIAC, UVISOR_FLAG_PALM4)},
26918334Speter};
270132718Skan
27118334Speterstatic int
27290075Sobrienuvisor_probe(device_t dev)
273132718Skan{
27490075Sobrien	struct usb2_attach_arg *uaa = device_get_ivars(dev);
27590075Sobrien
276169689Skan	if (uaa->usb2_mode != USB_MODE_HOST) {
27718334Speter		return (ENXIO);
278169689Skan	}
279169689Skan	if (uaa->info.bConfigIndex != UVISOR_CONFIG_INDEX) {
280169689Skan		return (ENXIO);
281169689Skan	}
282169689Skan	if (uaa->info.bIfaceIndex != UVISOR_IFACE_INDEX) {
283169689Skan		return (ENXIO);
284169689Skan	}
285169689Skan	return (usb2_lookup_id_by_uaa(uvisor_devs, sizeof(uvisor_devs), uaa));
286169689Skan}
28790075Sobrien
28890075Sobrienstatic int
28990075Sobrienuvisor_attach(device_t dev)
29090075Sobrien{
29190075Sobrien	struct usb2_attach_arg *uaa = device_get_ivars(dev);
29290075Sobrien	struct uvisor_softc *sc = device_get_softc(dev);
29390075Sobrien	struct usb2_config uvisor_config_copy[UVISOR_N_TRANSFER];
29490075Sobrien	int error;
29590075Sobrien
296132718Skan	DPRINTF("sc=%p\n", sc);
29790075Sobrien	bcopy(uvisor_config, uvisor_config_copy,
29818334Speter	    sizeof(uvisor_config_copy));
29918334Speter	device_set_usb2_desc(dev);
30018334Speter
30118334Speter	mtx_init(&sc->sc_mtx, "uvisor", NULL, MTX_DEF);
30218334Speter
30390075Sobrien	sc->sc_udev = uaa->device;
30490075Sobrien
30590075Sobrien	/* configure the device */
306132718Skan
30718334Speter	sc->sc_flag = USB_GET_DRIVER_INFO(uaa);
30818334Speter	sc->sc_iface_no = uaa->info.bIfaceNum;
30918334Speter	sc->sc_iface_index = UVISOR_IFACE_INDEX;
31018334Speter
31118334Speter	error = uvisor_init(sc, uaa->device, uvisor_config_copy);
31218334Speter
31318334Speter	if (error) {
31418334Speter		DPRINTF("init failed, error=%s\n",
31518334Speter		    usb2_errstr(error));
31690075Sobrien		goto detach;
31790075Sobrien	}
31818334Speter	error = usb2_transfer_setup(uaa->device, &sc->sc_iface_index,
31990075Sobrien	    sc->sc_xfer, uvisor_config_copy, UVISOR_N_TRANSFER,
32090075Sobrien	    sc, &sc->sc_mtx);
32190075Sobrien	if (error) {
32218334Speter		DPRINTF("could not allocate all pipes\n");
32390075Sobrien		goto detach;
32418334Speter	}
32590075Sobrien	/* clear stall at first run */
32690075Sobrien	mtx_lock(&sc->sc_mtx);
32790075Sobrien	usb2_transfer_set_stall(sc->sc_xfer[UVISOR_BULK_DT_WR]);
32818334Speter	usb2_transfer_set_stall(sc->sc_xfer[UVISOR_BULK_DT_RD]);
32990075Sobrien	mtx_unlock(&sc->sc_mtx);
33090075Sobrien
33118334Speter	error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
33290075Sobrien	    &uvisor_callback, &sc->sc_mtx);
33390075Sobrien	if (error) {
33418334Speter		DPRINTF("usb2_com_attach failed\n");
33552284Sobrien		goto detach;
33652284Sobrien	}
33752284Sobrien	return (0);
33890075Sobrien
33952284Sobriendetach:
34052284Sobrien	uvisor_detach(dev);
34152284Sobrien	return (ENXIO);
34252284Sobrien}
34352284Sobrien
34490075Sobrienstatic int
34552284Sobrienuvisor_detach(device_t dev)
34652284Sobrien{
34752284Sobrien	struct uvisor_softc *sc = device_get_softc(dev);
34852284Sobrien
34952284Sobrien	DPRINTF("sc=%p\n", sc);
35052284Sobrien
35152284Sobrien	usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
35252284Sobrien	usb2_transfer_unsetup(sc->sc_xfer, UVISOR_N_TRANSFER);
35352284Sobrien	mtx_destroy(&sc->sc_mtx);
35452284Sobrien
35552284Sobrien	return (0);
35652284Sobrien}
357169689Skan
35852284Sobrienstatic usb2_error_t
35952284Sobrienuvisor_init(struct uvisor_softc *sc, struct usb2_device *udev, struct usb2_config *config)
36090075Sobrien{
361132718Skan	usb2_error_t err = 0;
36290075Sobrien	struct usb2_device_request req;
36390075Sobrien	struct uvisor_connection_info coninfo;
364132718Skan	struct uvisor_palm_connection_info pconinfo;
36590075Sobrien	uint16_t actlen;
366117395Skan	uWord wAvail;
367169689Skan	uint8_t buffer[256];
368117395Skan
369117395Skan	if (sc->sc_flag & UVISOR_FLAG_VISOR) {
37050397Sobrien		DPRINTF("getting connection info\n");
371169689Skan		req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
372169689Skan		req.bRequest = UVISOR_GET_CONNECTION_INFORMATION;
373169689Skan		USETW(req.wValue, 0);
374169689Skan		USETW(req.wIndex, 0);
375169689Skan		USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
376169689Skan		err = usb2_do_request_flags(udev, NULL,
377169689Skan		    &req, &coninfo, USB_SHORT_XFER_OK,
378117395Skan		    &actlen, USB_DEFAULT_TIMEOUT);
379117395Skan
380132718Skan		if (err) {
38152284Sobrien			goto done;
382132718Skan		}
383132718Skan	}
384132718Skan#if USB_DEBUG
385132718Skan	if (sc->sc_flag & UVISOR_FLAG_VISOR) {
38652284Sobrien		uint16_t i, np;
38752284Sobrien		const char *desc;
38852284Sobrien
38990075Sobrien		np = UGETW(coninfo.num_ports);
390132718Skan		if (np > UVISOR_MAX_CONN) {
39190075Sobrien			np = UVISOR_MAX_CONN;
39290075Sobrien		}
393132718Skan		DPRINTF("Number of ports: %d\n", np);
39490075Sobrien
395132718Skan		for (i = 0; i < np; ++i) {
39690075Sobrien			switch (coninfo.connections[i].port_function_id) {
39790075Sobrien			case UVISOR_FUNCTION_GENERIC:
39890075Sobrien				desc = "Generic";
39990075Sobrien				break;
40090075Sobrien			case UVISOR_FUNCTION_DEBUGGER:
40190075Sobrien				desc = "Debugger";
40290075Sobrien				break;
40390075Sobrien			case UVISOR_FUNCTION_HOTSYNC:
40490075Sobrien				desc = "HotSync";
40590075Sobrien				break;
40690075Sobrien			case UVISOR_FUNCTION_REMOTE_FILE_SYS:
40796263Sobrien				desc = "Remote File System";
408117395Skan				break;
409117395Skan			default:
410169689Skan				desc = "unknown";
411169689Skan				break;
412169689Skan			}
413169689Skan			DPRINTF("Port %d is for %s\n",
41490075Sobrien			    coninfo.connections[i].port, desc);
415169689Skan		}
416169689Skan	}
417169689Skan#endif
418169689Skan
419169689Skan	if (sc->sc_flag & UVISOR_FLAG_PALM4) {
420169689Skan		uint8_t port;
421169689Skan
422169689Skan		/* Palm OS 4.0 Hack */
423169689Skan		req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
424169689Skan		req.bRequest = UVISOR_GET_PALM_INFORMATION;
425169689Skan		USETW(req.wValue, 0);
426169689Skan		USETW(req.wIndex, 0);
427169689Skan		USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
428169689Skan
429169689Skan		err = usb2_do_request_flags
430169689Skan		    (udev, NULL, &req, &pconinfo, USB_SHORT_XFER_OK,
431169689Skan		    &actlen, USB_DEFAULT_TIMEOUT);
432169689Skan
433169689Skan		if (err) {
434169689Skan			goto done;
435169689Skan		}
436169689Skan		if (actlen < 12) {
437169689Skan			DPRINTF("too little data\n");
438169689Skan			err = USB_ERR_INVAL;
439169689Skan			goto done;
440169689Skan		}
441169689Skan		if (pconinfo.endpoint_numbers_different) {
442169689Skan			port = pconinfo.connections[0].end_point_info;
443169689Skan			config[0].endpoint = (port & 0xF);	/* output */
444169689Skan			config[1].endpoint = (port >> 4);	/* input */
445169689Skan		} else {
446169689Skan			port = pconinfo.connections[0].port;
447169689Skan			config[0].endpoint = (port & 0xF);	/* output */
448169689Skan			config[1].endpoint = (port & 0xF);	/* input */
449169689Skan		}
450169689Skan#if 0
451169689Skan		req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
452169689Skan		req.bRequest = UVISOR_GET_PALM_INFORMATION;
453169689Skan		USETW(req.wValue, 0);
454169689Skan		USETW(req.wIndex, 0);
455169689Skan		USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
456169689Skan		err = usb2_do_request(udev, &req, buffer);
457169689Skan		if (err) {
458169689Skan			goto done;
459169689Skan		}
460169689Skan#endif
461169689Skan	}
462169689Skan	if (sc->sc_flag & UVISOR_FLAG_PALM35) {
463169689Skan		/* get the config number */
464169689Skan		DPRINTF("getting config info\n");
465169689Skan		req.bmRequestType = UT_READ;
466169689Skan		req.bRequest = UR_GET_CONFIG;
467169689Skan		USETW(req.wValue, 0);
468169689Skan		USETW(req.wIndex, 0);
469169689Skan		USETW(req.wLength, 1);
470169689Skan
471169689Skan		err = usb2_do_request(udev, NULL, &req, buffer);
472169689Skan		if (err) {
473169689Skan			goto done;
474169689Skan		}
475169689Skan		/* get the interface number */
476169689Skan		DPRINTF("get the interface number\n");
477169689Skan		req.bmRequestType = UT_READ_DEVICE;
478169689Skan		req.bRequest = UR_GET_INTERFACE;
479169689Skan		USETW(req.wValue, 0);
480169689Skan		USETW(req.wIndex, 0);
481169689Skan		USETW(req.wLength, 1);
482169689Skan		err = usb2_do_request(udev, NULL, &req, buffer);
483169689Skan		if (err) {
484169689Skan			goto done;
485169689Skan		}
486169689Skan	}
487169689Skan	DPRINTF("getting available bytes\n");
488169689Skan	req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
489169689Skan	req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE;
490169689Skan	USETW(req.wValue, 0);
491169689Skan	USETW(req.wIndex, 5);
492169689Skan	USETW(req.wLength, sizeof(wAvail));
493169689Skan	err = usb2_do_request(udev, NULL, &req, &wAvail);
494169689Skan	if (err) {
495169689Skan		goto done;
496169689Skan	}
497169689Skan	DPRINTF("avail=%d\n", UGETW(wAvail));
498169689Skan
499169689Skan	DPRINTF("done\n");
500169689Skandone:
501169689Skan	return (err);
502169689Skan}
503169689Skan
504169689Skanstatic void
505169689Skanuvisor_cfg_open(struct usb2_com_softc *ucom)
506169689Skan{
507169689Skan	return;
508169689Skan}
509169689Skan
510169689Skanstatic void
511169689Skanuvisor_cfg_close(struct usb2_com_softc *ucom)
512169689Skan{
513169689Skan	struct uvisor_softc *sc = ucom->sc_parent;
514169689Skan	uint8_t buffer[UVISOR_CONNECTION_INFO_SIZE];
515169689Skan	struct usb2_device_request req;
516169689Skan	usb2_error_t err;
517169689Skan
518169689Skan	req.bmRequestType = UT_READ_VENDOR_ENDPOINT;	/* XXX read? */
519169689Skan	req.bRequest = UVISOR_CLOSE_NOTIFICATION;
520169689Skan	USETW(req.wValue, 0);
521169689Skan	USETW(req.wIndex, 0);
522169689Skan	USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
523169689Skan
524169689Skan	err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
525169689Skan	    &req, buffer, 0, 1000);
526169689Skan	if (err) {
527169689Skan		DPRINTFN(0, "close notification failed, error=%s\n",
528169689Skan		    usb2_errstr(err));
529169689Skan	}
530169689Skan}
531169689Skan
532169689Skanstatic void
533169689Skanuvisor_start_read(struct usb2_com_softc *ucom)
534169689Skan{
535169689Skan	struct uvisor_softc *sc = ucom->sc_parent;
536169689Skan
537169689Skan	usb2_transfer_start(sc->sc_xfer[UVISOR_BULK_DT_RD]);
538169689Skan}
539169689Skan
540169689Skanstatic void
541169689Skanuvisor_stop_read(struct usb2_com_softc *ucom)
542169689Skan{
543169689Skan	struct uvisor_softc *sc = ucom->sc_parent;
544169689Skan
545169689Skan	usb2_transfer_stop(sc->sc_xfer[UVISOR_BULK_DT_RD]);
546169689Skan}
547169689Skan
548169689Skanstatic void
549169689Skanuvisor_start_write(struct usb2_com_softc *ucom)
550169689Skan{
551169689Skan	struct uvisor_softc *sc = ucom->sc_parent;
552169689Skan
553169689Skan	usb2_transfer_start(sc->sc_xfer[UVISOR_BULK_DT_WR]);
554169689Skan}
555169689Skan
556169689Skanstatic void
557169689Skanuvisor_stop_write(struct usb2_com_softc *ucom)
558169689Skan{
559169689Skan	struct uvisor_softc *sc = ucom->sc_parent;
560169689Skan
561169689Skan	usb2_transfer_stop(sc->sc_xfer[UVISOR_BULK_DT_WR]);
562169689Skan}
563169689Skan
564169689Skanstatic void
565169689Skanuvisor_write_callback(struct usb2_xfer *xfer)
566169689Skan{
567169689Skan	struct uvisor_softc *sc = xfer->priv_sc;
568169689Skan	uint32_t actlen;
569169689Skan
570169689Skan	switch (USB_GET_STATE(xfer)) {
571169689Skan	case USB_ST_SETUP:
572132718Skan	case USB_ST_TRANSFERRED:
57390075Sobrientr_setup:
574169689Skan		if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0,
575169689Skan		    UVISOR_BUFSIZE, &actlen)) {
576169689Skan
577169689Skan			xfer->frlengths[0] = actlen;
578169689Skan			usb2_start_hardware(xfer);
579169689Skan		}
58090075Sobrien		return;
581132718Skan
582132718Skan	default:			/* Error */
583132718Skan		if (xfer->error != USB_ERR_CANCELLED) {
584132718Skan			/* try to clear stall first */
585132718Skan			xfer->flags.stall_pipe = 1;
586132718Skan			goto tr_setup;
58790075Sobrien		}
588169689Skan		return;
589169689Skan	}
590132718Skan}
591169689Skan
592169689Skanstatic void
593169689Skanuvisor_read_callback(struct usb2_xfer *xfer)
594132718Skan{
595169689Skan	struct uvisor_softc *sc = xfer->priv_sc;
596169689Skan
597132718Skan	switch (USB_GET_STATE(xfer)) {
598132718Skan	case USB_ST_TRANSFERRED:
599169689Skan		usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0, xfer->actlen);
600169689Skan
601132718Skan	case USB_ST_SETUP:
602132718Skantr_setup:
603132718Skan		xfer->frlengths[0] = xfer->max_data_length;
604169689Skan		usb2_start_hardware(xfer);
605169689Skan		return;
606132718Skan
607132718Skan	default:			/* Error */
608132718Skan		if (xfer->error != USB_ERR_CANCELLED) {
609132718Skan			/* try to clear stall first */
61090075Sobrien			xfer->flags.stall_pipe = 1;
611215840Sdim			goto tr_setup;
612215840Sdim		}
613215840Sdim		return;
614215840Sdim	}
615132718Skan}
616117395Skan