Home | History | Annotate | Line # | Download | only in usb
uvisor.c revision 1.55.6.2
      1  1.55.6.2   thorpej /*	$NetBSD: uvisor.c,v 1.55.6.2 2021/03/22 16:23:46 thorpej Exp $	*/
      2       1.1  augustss 
      3       1.1  augustss /*
      4       1.1  augustss  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5       1.1  augustss  * All rights reserved.
      6       1.1  augustss  *
      7       1.1  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8       1.6  augustss  * by Lennart Augustsson (lennart (at) augustsson.net) at
      9       1.1  augustss  * Carlstedt Research & Technology.
     10       1.1  augustss  *
     11       1.1  augustss  * Redistribution and use in source and binary forms, with or without
     12       1.1  augustss  * modification, are permitted provided that the following conditions
     13       1.1  augustss  * are met:
     14       1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     15       1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     16       1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     17       1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     18       1.1  augustss  *    documentation and/or other materials provided with the distribution.
     19       1.1  augustss  *
     20       1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21       1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22       1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23       1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24       1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25       1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26       1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27       1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28       1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29       1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30       1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     31       1.1  augustss  */
     32       1.1  augustss 
     33       1.1  augustss /*
     34       1.2   hubertf  * Handspring Visor (Palmpilot compatible PDA) driver
     35       1.1  augustss  */
     36      1.12     lukem 
     37      1.12     lukem #include <sys/cdefs.h>
     38  1.55.6.2   thorpej __KERNEL_RCSID(0, "$NetBSD: uvisor.c,v 1.55.6.2 2021/03/22 16:23:46 thorpej Exp $");
     39      1.48     skrll 
     40      1.48     skrll #ifdef _KERNEL_OPT
     41      1.48     skrll #include "opt_usb.h"
     42      1.48     skrll #endif
     43       1.1  augustss 
     44       1.1  augustss #include <sys/param.h>
     45       1.1  augustss #include <sys/systm.h>
     46       1.1  augustss #include <sys/kernel.h>
     47       1.1  augustss #include <sys/device.h>
     48       1.1  augustss #include <sys/conf.h>
     49       1.1  augustss #include <sys/tty.h>
     50       1.1  augustss 
     51       1.1  augustss #include <dev/usb/usb.h>
     52       1.1  augustss 
     53       1.1  augustss #include <dev/usb/usbdi.h>
     54       1.1  augustss #include <dev/usb/usbdi_util.h>
     55       1.1  augustss #include <dev/usb/usbdevs.h>
     56       1.1  augustss 
     57       1.1  augustss #include <dev/usb/ucomvar.h>
     58       1.1  augustss 
     59       1.1  augustss #ifdef UVISOR_DEBUG
     60       1.1  augustss #define DPRINTF(x)	if (uvisordebug) printf x
     61       1.1  augustss #define DPRINTFN(n,x)	if (uvisordebug>(n)) printf x
     62       1.3  augustss int uvisordebug = 0;
     63       1.1  augustss #else
     64       1.1  augustss #define DPRINTF(x)
     65       1.1  augustss #define DPRINTFN(n,x)
     66       1.1  augustss #endif
     67       1.1  augustss 
     68       1.1  augustss #define UVISOR_CONFIG_INDEX	0
     69       1.1  augustss #define UVISOR_IFACE_INDEX	0
     70       1.1  augustss 
     71       1.1  augustss /* From the Linux driver */
     72       1.1  augustss /*
     73       1.1  augustss  * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
     74      1.53   msaitoh  * are available to be transferred to the host for the specified endpoint.
     75       1.1  augustss  * Currently this is not used, and always returns 0x0001
     76       1.1  augustss  */
     77       1.1  augustss #define UVISOR_REQUEST_BYTES_AVAILABLE		0x01
     78       1.1  augustss 
     79       1.1  augustss /*
     80       1.1  augustss  * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
     81       1.1  augustss  * is now closing the pipe. An empty packet is sent in response.
     82       1.1  augustss  */
     83       1.1  augustss #define UVISOR_CLOSE_NOTIFICATION		0x02
     84       1.1  augustss 
     85       1.1  augustss /*
     86       1.1  augustss  * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
     87       1.1  augustss  * get the endpoints used by the connection.
     88       1.1  augustss  */
     89       1.1  augustss #define UVISOR_GET_CONNECTION_INFORMATION	0x03
     90       1.1  augustss 
     91       1.1  augustss 
     92       1.1  augustss /*
     93       1.1  augustss  * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format
     94       1.1  augustss  */
     95      1.10  augustss #define UVISOR_MAX_CONN 8
     96       1.1  augustss struct uvisor_connection_info {
     97       1.1  augustss 	uWord	num_ports;
     98       1.1  augustss 	struct {
     99       1.1  augustss 		uByte	port_function_id;
    100       1.1  augustss 		uByte	port;
    101      1.10  augustss 	} connections[UVISOR_MAX_CONN];
    102       1.1  augustss };
    103       1.1  augustss #define UVISOR_CONNECTION_INFO_SIZE 18
    104       1.1  augustss 
    105       1.1  augustss /* struct uvisor_connection_info.connection[x].port_function_id defines: */
    106       1.1  augustss #define UVISOR_FUNCTION_GENERIC		0x00
    107       1.1  augustss #define UVISOR_FUNCTION_DEBUGGER	0x01
    108       1.1  augustss #define UVISOR_FUNCTION_HOTSYNC		0x02
    109       1.1  augustss #define UVISOR_FUNCTION_CONSOLE		0x03
    110       1.1  augustss #define UVISOR_FUNCTION_REMOTE_FILE_SYS	0x04
    111       1.1  augustss 
    112      1.14  augustss /*
    113      1.14  augustss  * Unknown PalmOS stuff.
    114      1.14  augustss  */
    115      1.14  augustss #define UVISOR_GET_PALM_INFORMATION		0x04
    116      1.21   nathanw #define UVISOR_GET_PALM_INFORMATION_LEN		0x44
    117      1.14  augustss 
    118      1.21   nathanw struct uvisor_palm_connection_info {
    119      1.21   nathanw 	uByte	num_ports;
    120      1.21   nathanw 	uByte	endpoint_numbers_different;
    121      1.21   nathanw 	uWord	reserved1;
    122      1.21   nathanw 	struct {
    123      1.21   nathanw 		uDWord	port_function_id;
    124      1.21   nathanw 		uByte	port;
    125      1.21   nathanw 		uByte	end_point_info;
    126      1.21   nathanw 		uWord	reserved;
    127      1.21   nathanw 	} connections[UVISOR_MAX_CONN];
    128      1.21   nathanw };
    129       1.1  augustss 
    130      1.21   nathanw 
    131      1.21   nathanw 
    132      1.21   nathanw #define UVISORIBUFSIZE 64
    133       1.4  augustss #define UVISOROBUFSIZE 1024
    134       1.4  augustss 
    135       1.1  augustss struct uvisor_softc {
    136      1.43    dyoung 	device_t		sc_dev;		/* base device */
    137      1.46     skrll 	struct usbd_device *	sc_udev;	/* device */
    138      1.46     skrll 	struct usbd_interface *	sc_iface;	/* interface */
    139       1.1  augustss 
    140      1.43    dyoung 	device_t		sc_subdevs[UVISOR_MAX_CONN];
    141      1.10  augustss 	int			sc_numcon;
    142       1.1  augustss 
    143      1.46     skrll 	uint16_t		sc_flags;
    144      1.14  augustss 
    145      1.51       mrg 	bool			sc_dying;
    146       1.1  augustss };
    147       1.1  augustss 
    148      1.51       mrg static usbd_status uvisor_init(struct uvisor_softc *,
    149      1.21   nathanw 			       struct uvisor_connection_info *,
    150      1.21   nathanw 			       struct uvisor_palm_connection_info *);
    151       1.1  augustss 
    152      1.51       mrg static int uvisor_open(void *, int);
    153      1.51       mrg static void uvisor_close(void *, int);
    154       1.1  augustss 
    155      1.54      maxv static const struct ucom_methods uvisor_methods = {
    156      1.51       mrg 	.ucom_open = uvisor_open,
    157      1.46     skrll 	.ucom_close = uvisor_close,
    158       1.1  augustss };
    159       1.1  augustss 
    160      1.14  augustss struct uvisor_type {
    161      1.14  augustss 	struct usb_devno	uv_dev;
    162      1.46     skrll 	uint16_t		uv_flags;
    163      1.14  augustss #define PALM4	0x0001
    164      1.21   nathanw #define VISOR	0x0002
    165      1.21   nathanw 
    166      1.14  augustss };
    167      1.14  augustss static const struct uvisor_type uvisor_devs[] = {
    168      1.21   nathanw 	{{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR }, VISOR },
    169      1.19  augustss 	{{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO }, PALM4 },
    170      1.23    carrel 	{{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO600 }, PALM4 },
    171      1.14  augustss 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M500 }, PALM4 },
    172      1.14  augustss 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M505 }, PALM4 },
    173      1.17  augustss 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M515 }, PALM4 },
    174      1.19  augustss 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_I705 }, PALM4 },
    175      1.14  augustss 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M125 }, PALM4 },
    176      1.19  augustss 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M130 }, PALM4 },
    177      1.19  augustss 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_Z }, PALM4 },
    178      1.20    simonb 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_T }, PALM4 },
    179      1.26   mycroft 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE31 }, PALM4 },
    180      1.18  augustss 	{{ USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE }, PALM4 },
    181      1.14  augustss 	{{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40 }, PALM4 },
    182      1.21   nathanw 	{{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41 }, PALM4 },
    183      1.19  augustss 	{{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_S360 }, PALM4 },
    184      1.19  augustss 	{{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_NX60 }, PALM4 },
    185      1.24  augustss 	{{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_35 }, 0 },
    186      1.14  augustss /*	{{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_25 }, PALM4 },*/
    187      1.14  augustss };
    188      1.30  christos #define uvisor_lookup(v, p) ((const struct uvisor_type *)usb_lookup(uvisor_devs, v, p))
    189      1.14  augustss 
    190      1.51       mrg static int	uvisor_match(device_t, cfdata_t, void *);
    191      1.51       mrg static void	uvisor_attach(device_t, device_t, void *);
    192      1.51       mrg static void	uvisor_childdet(device_t, device_t);
    193      1.51       mrg static int	uvisor_detach(device_t, int);
    194      1.50       mrg 
    195      1.40      cube CFATTACH_DECL2_NEW(uvisor, sizeof(struct uvisor_softc), uvisor_match,
    196      1.51       mrg     uvisor_attach, uvisor_detach, NULL, NULL, uvisor_childdet);
    197       1.1  augustss 
    198      1.51       mrg static int
    199      1.43    dyoung uvisor_match(device_t parent, cfdata_t match, void *aux)
    200       1.1  augustss {
    201      1.43    dyoung 	struct usb_attach_arg *uaa = aux;
    202      1.16  augustss 
    203      1.55  christos 	DPRINTFN(20,("uvisor: vendor=%#x, product=%#x\n",
    204      1.46     skrll 		     uaa->uaa_vendor, uaa->uaa_product));
    205       1.1  augustss 
    206      1.46     skrll 	return uvisor_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ?
    207      1.46     skrll 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
    208       1.1  augustss }
    209       1.1  augustss 
    210      1.51       mrg static void
    211      1.43    dyoung uvisor_attach(device_t parent, device_t self, void *aux)
    212       1.1  augustss {
    213      1.43    dyoung 	struct uvisor_softc *sc = device_private(self);
    214      1.43    dyoung 	struct usb_attach_arg *uaa = aux;
    215      1.46     skrll 	struct usbd_device *dev = uaa->uaa_device;
    216      1.46     skrll 	struct usbd_interface *iface;
    217       1.1  augustss 	usb_interface_descriptor_t *id;
    218      1.10  augustss 	struct uvisor_connection_info coninfo;
    219      1.21   nathanw 	struct uvisor_palm_connection_info palmconinfo;
    220       1.1  augustss 	usb_endpoint_descriptor_t *ed;
    221      1.29  augustss 	char *devinfop;
    222      1.40      cube 	const char *devname = device_xname(self);
    223      1.10  augustss 	int i, j, hasin, hasout, port;
    224       1.1  augustss 	usbd_status err;
    225      1.46     skrll 	struct ucom_attach_args ucaa;
    226       1.1  augustss 
    227       1.1  augustss 	DPRINTFN(10,("\nuvisor_attach: sc=%p\n", sc));
    228       1.1  augustss 
    229      1.40      cube 	sc->sc_dev = self;
    230      1.51       mrg 	sc->sc_dying = false;
    231      1.40      cube 
    232      1.41    plunky 	aprint_naive("\n");
    233      1.41    plunky 	aprint_normal("\n");
    234      1.41    plunky 
    235      1.41    plunky 	devinfop = usbd_devinfo_alloc(dev, 0);
    236      1.41    plunky 	aprint_normal_dev(self, "%s\n", devinfop);
    237      1.41    plunky 	usbd_devinfo_free(devinfop);
    238      1.41    plunky 
    239       1.1  augustss 	/* Move the device into the configured state. */
    240       1.1  augustss 	err = usbd_set_config_index(dev, UVISOR_CONFIG_INDEX, 1);
    241       1.1  augustss 	if (err) {
    242      1.40      cube 		aprint_error("\n%s: failed to set configuration, err=%s\n",
    243       1.1  augustss 		       devname, usbd_errstr(err));
    244       1.1  augustss 		goto bad;
    245       1.1  augustss 	}
    246       1.1  augustss 
    247       1.1  augustss 	err = usbd_device2interface_handle(dev, UVISOR_IFACE_INDEX, &iface);
    248       1.1  augustss 	if (err) {
    249      1.40      cube 		aprint_error("\n%s: failed to get interface, err=%s\n",
    250       1.1  augustss 		       devname, usbd_errstr(err));
    251       1.1  augustss 		goto bad;
    252       1.1  augustss 	}
    253       1.1  augustss 
    254      1.46     skrll 	sc->sc_flags = uvisor_lookup(uaa->uaa_vendor, uaa->uaa_product)->uv_flags;
    255      1.14  augustss 
    256      1.21   nathanw 	if ((sc->sc_flags & (VISOR | PALM4)) == 0) {
    257      1.40      cube 		aprint_error_dev(self,
    258      1.40      cube 		    "init failed, device type is neither visor nor palm\n");
    259      1.21   nathanw 		goto bad;
    260      1.21   nathanw 	}
    261      1.21   nathanw 
    262       1.1  augustss 	id = usbd_get_interface_descriptor(iface);
    263       1.3  augustss 
    264       1.3  augustss 	sc->sc_udev = dev;
    265       1.1  augustss 	sc->sc_iface = iface;
    266       1.1  augustss 
    267      1.46     skrll 	ucaa.ucaa_ibufsize = UVISORIBUFSIZE;
    268      1.46     skrll 	ucaa.ucaa_obufsize = UVISOROBUFSIZE;
    269      1.46     skrll 	ucaa.ucaa_ibufsizepad = UVISORIBUFSIZE;
    270      1.46     skrll 	ucaa.ucaa_opkthdrlen = 0;
    271      1.46     skrll 	ucaa.ucaa_device = dev;
    272      1.46     skrll 	ucaa.ucaa_iface = iface;
    273      1.46     skrll 	ucaa.ucaa_methods = &uvisor_methods;
    274      1.46     skrll 	ucaa.ucaa_arg = sc;
    275       1.4  augustss 
    276      1.21   nathanw 	err = uvisor_init(sc, &coninfo, &palmconinfo);
    277       1.1  augustss 	if (err) {
    278      1.40      cube 		aprint_error_dev(self, "init failed, %s\n", usbd_errstr(err));
    279       1.1  augustss 		goto bad;
    280       1.1  augustss 	}
    281       1.1  augustss 
    282      1.47   msaitoh 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
    283       1.9  augustss 
    284      1.21   nathanw 	if (sc->sc_flags & VISOR) {
    285      1.21   nathanw 		sc->sc_numcon = UGETW(coninfo.num_ports);
    286      1.21   nathanw 		if (sc->sc_numcon > UVISOR_MAX_CONN)
    287      1.21   nathanw 			sc->sc_numcon = UVISOR_MAX_CONN;
    288      1.21   nathanw 
    289      1.21   nathanw 		/* Attach a ucom for each connection. */
    290      1.21   nathanw 		for (i = 0; i < sc->sc_numcon; ++i) {
    291      1.21   nathanw 			switch (coninfo.connections[i].port_function_id) {
    292      1.21   nathanw 			case UVISOR_FUNCTION_GENERIC:
    293      1.46     skrll 				ucaa.ucaa_info = "Generic";
    294      1.21   nathanw 				break;
    295      1.21   nathanw 			case UVISOR_FUNCTION_DEBUGGER:
    296      1.46     skrll 				ucaa.ucaa_info = "Debugger";
    297      1.21   nathanw 				break;
    298      1.21   nathanw 			case UVISOR_FUNCTION_HOTSYNC:
    299      1.46     skrll 				ucaa.ucaa_info = "HotSync";
    300      1.21   nathanw 				break;
    301      1.21   nathanw 			case UVISOR_FUNCTION_REMOTE_FILE_SYS:
    302      1.46     skrll 				ucaa.ucaa_info = "Remote File System";
    303      1.21   nathanw 				break;
    304      1.21   nathanw 			default:
    305      1.46     skrll 				ucaa.ucaa_info = "unknown";
    306      1.10  augustss 				break;
    307      1.10  augustss 			}
    308      1.21   nathanw 			port = coninfo.connections[i].port;
    309      1.46     skrll 			ucaa.ucaa_portno = port;
    310      1.46     skrll 			ucaa.ucaa_bulkin = port | UE_DIR_IN;
    311      1.46     skrll 			ucaa.ucaa_bulkout = port | UE_DIR_OUT;
    312      1.21   nathanw 			/* Verify that endpoints exist. */
    313      1.21   nathanw 			hasin = 0;
    314      1.21   nathanw 			hasout = 0;
    315      1.21   nathanw 			for (j = 0; j < id->bNumEndpoints; j++) {
    316      1.21   nathanw 				ed = usbd_interface2endpoint_descriptor(iface, j);
    317      1.21   nathanw 				if (ed == NULL)
    318      1.21   nathanw 					break;
    319      1.21   nathanw 				if (UE_GET_ADDR(ed->bEndpointAddress) == port &&
    320      1.21   nathanw 				    (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
    321      1.21   nathanw 					if (UE_GET_DIR(ed->bEndpointAddress)
    322      1.21   nathanw 					    == UE_DIR_IN)
    323      1.21   nathanw 						hasin++;
    324      1.21   nathanw 					else
    325      1.21   nathanw 						hasout++;
    326      1.21   nathanw 				}
    327      1.21   nathanw 			}
    328      1.21   nathanw 			if (hasin == 1 && hasout == 1)
    329  1.55.6.1   thorpej 				sc->sc_subdevs[i] =
    330  1.55.6.1   thorpej 				    config_found(self, &ucaa, ucomprint,
    331  1.55.6.1   thorpej 						 CFARG_SUBMATCH, ucomsubmatch,
    332  1.55.6.1   thorpej 						 CFARG_EOL);
    333      1.21   nathanw 			else
    334      1.40      cube 				aprint_error_dev(self,
    335      1.40      cube 				    "no proper endpoints for port %d (%d,%d)\n",
    336      1.40      cube 				    port, hasin, hasout);
    337      1.10  augustss 		}
    338      1.21   nathanw 
    339      1.21   nathanw 	} else {
    340      1.21   nathanw 		sc->sc_numcon = palmconinfo.num_ports;
    341      1.21   nathanw 		if (sc->sc_numcon > UVISOR_MAX_CONN)
    342      1.21   nathanw 			sc->sc_numcon = UVISOR_MAX_CONN;
    343      1.21   nathanw 
    344      1.21   nathanw 		/* Attach a ucom for each connection. */
    345      1.21   nathanw 		for (i = 0; i < sc->sc_numcon; ++i) {
    346      1.28     perry 			/*
    347      1.28     perry 			 * XXX this should copy out 4-char string from the
    348      1.21   nathanw 			 * XXX port_function_id, but where would the string go?
    349      1.46     skrll 			 * XXX ucaa.ucaa_info is a const char *, not an array.
    350      1.21   nathanw 			 */
    351      1.46     skrll 			ucaa.ucaa_info = "sync";
    352      1.46     skrll 			ucaa.ucaa_portno = i;
    353      1.21   nathanw 			if (palmconinfo.endpoint_numbers_different) {
    354      1.21   nathanw 				port = palmconinfo.connections[i].end_point_info;
    355      1.46     skrll 				ucaa.ucaa_bulkin = (port >> 4) | UE_DIR_IN;
    356      1.46     skrll 				ucaa.ucaa_bulkout = (port & 0xf) | UE_DIR_OUT;
    357      1.21   nathanw 			} else {
    358      1.21   nathanw 				port = palmconinfo.connections[i].port;
    359      1.46     skrll 				ucaa.ucaa_bulkin = port | UE_DIR_IN;
    360      1.46     skrll 				ucaa.ucaa_bulkout = port | UE_DIR_OUT;
    361      1.21   nathanw 			}
    362  1.55.6.1   thorpej 			sc->sc_subdevs[i] =
    363  1.55.6.1   thorpej 			    config_found(self, &ucaa, ucomprint,
    364  1.55.6.1   thorpej 					 CFARG_SUBMATCH, ucomsubmatch,
    365  1.55.6.1   thorpej 					 CFARG_EOL);
    366      1.21   nathanw 		}
    367      1.10  augustss 	}
    368      1.16  augustss 
    369      1.43    dyoung 	return;
    370       1.1  augustss 
    371       1.1  augustss bad:
    372       1.1  augustss 	DPRINTF(("uvisor_attach: ATTACH ERROR\n"));
    373      1.51       mrg 	sc->sc_dying = true;
    374      1.43    dyoung 	return;
    375       1.1  augustss }
    376       1.1  augustss 
    377      1.51       mrg static void
    378      1.37    dyoung uvisor_childdet(device_t self, device_t child)
    379      1.37    dyoung {
    380      1.37    dyoung 	int i;
    381      1.37    dyoung 	struct uvisor_softc *sc = device_private(self);
    382      1.37    dyoung 
    383      1.37    dyoung 	for (i = 0; i < sc->sc_numcon; i++) {
    384      1.37    dyoung 		if (sc->sc_subdevs[i] == child)
    385      1.37    dyoung 			break;
    386      1.37    dyoung 	}
    387      1.37    dyoung 	KASSERT(i < sc->sc_numcon);
    388      1.37    dyoung 	sc->sc_subdevs[i] = NULL;
    389      1.37    dyoung }
    390      1.37    dyoung 
    391      1.51       mrg static int
    392      1.37    dyoung uvisor_detach(device_t self, int flags)
    393       1.1  augustss {
    394      1.37    dyoung 	struct uvisor_softc *sc = device_private(self);
    395       1.1  augustss 	int rv = 0;
    396      1.10  augustss 	int i;
    397       1.1  augustss 
    398       1.1  augustss 	DPRINTF(("uvisor_detach: sc=%p flags=%d\n", sc, flags));
    399      1.51       mrg 
    400      1.51       mrg 	sc->sc_dying = true;
    401      1.51       mrg 
    402      1.10  augustss 	for (i = 0; i < sc->sc_numcon; i++) {
    403      1.51       mrg 		if (sc->sc_subdevs[i] != NULL) {
    404      1.10  augustss 			rv |= config_detach(sc->sc_subdevs[i], flags);
    405      1.51       mrg 			sc->sc_subdevs[i] = NULL;
    406      1.51       mrg 		}
    407       1.1  augustss 	}
    408      1.52      maxv 	if (sc->sc_udev != NULL)
    409      1.52      maxv 		usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    410      1.52      maxv 		    sc->sc_dev);
    411       1.9  augustss 
    412      1.46     skrll 	return rv;
    413       1.1  augustss }
    414       1.1  augustss 
    415      1.51       mrg static usbd_status
    416      1.21   nathanw uvisor_init(struct uvisor_softc *sc, struct uvisor_connection_info *ci,
    417      1.21   nathanw     struct uvisor_palm_connection_info *cpi)
    418       1.1  augustss {
    419       1.1  augustss 	usbd_status err;
    420       1.1  augustss 	usb_device_request_t req;
    421       1.1  augustss 	int actlen;
    422       1.1  augustss 	uWord avail;
    423      1.14  augustss 
    424      1.21   nathanw 	if (sc->sc_flags & VISOR) {
    425      1.21   nathanw 		DPRINTF(("uvisor_init: getting Visor connection info\n"));
    426      1.14  augustss 		req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
    427      1.21   nathanw 		req.bRequest = UVISOR_GET_CONNECTION_INFORMATION;
    428      1.14  augustss 		USETW(req.wValue, 0);
    429      1.14  augustss 		USETW(req.wIndex, 0);
    430      1.21   nathanw 		USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
    431      1.21   nathanw 		err = usbd_do_request_flags(sc->sc_udev, &req, ci,
    432      1.21   nathanw 		    USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
    433      1.14  augustss 		if (err)
    434      1.46     skrll 			return err;
    435      1.21   nathanw 	}
    436      1.21   nathanw 
    437      1.21   nathanw 	if (sc->sc_flags & PALM4) {
    438      1.21   nathanw 		DPRINTF(("uvisor_init: getting Palm connection info\n"));
    439      1.14  augustss 		req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
    440      1.14  augustss 		req.bRequest = UVISOR_GET_PALM_INFORMATION;
    441      1.14  augustss 		USETW(req.wValue, 0);
    442      1.14  augustss 		USETW(req.wIndex, 0);
    443      1.14  augustss 		USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
    444      1.21   nathanw 		err = usbd_do_request_flags(sc->sc_udev, &req, cpi,
    445      1.21   nathanw 		    USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
    446      1.14  augustss 		if (err)
    447      1.46     skrll 			return err;
    448      1.14  augustss 	}
    449       1.1  augustss 
    450       1.1  augustss 	DPRINTF(("uvisor_init: getting available bytes\n"));
    451       1.1  augustss 	req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
    452       1.1  augustss 	req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE;
    453       1.1  augustss 	USETW(req.wValue, 0);
    454       1.1  augustss 	USETW(req.wIndex, 5);
    455      1.46     skrll 	USETW(req.wLength, sizeof(avail));
    456       1.1  augustss 	err = usbd_do_request(sc->sc_udev, &req, &avail);
    457       1.1  augustss 	if (err)
    458      1.46     skrll 		return err;
    459       1.1  augustss 	DPRINTF(("uvisor_init: avail=%d\n", UGETW(avail)));
    460       1.1  augustss 
    461       1.1  augustss 	DPRINTF(("uvisor_init: done\n"));
    462      1.46     skrll 	return err;
    463       1.1  augustss }
    464       1.1  augustss 
    465      1.51       mrg static int
    466      1.51       mrg uvisor_open(void *arg, int portno)
    467      1.51       mrg {
    468      1.51       mrg 	struct uvisor_softc *sc = arg;
    469      1.51       mrg 
    470      1.51       mrg 	if (sc->sc_dying)
    471      1.51       mrg 		return EIO;
    472      1.51       mrg 
    473      1.51       mrg 	return 0;
    474      1.51       mrg }
    475      1.51       mrg 
    476       1.1  augustss void
    477      1.33  christos uvisor_close(void *addr, int portno)
    478       1.1  augustss {
    479       1.1  augustss 	struct uvisor_softc *sc = addr;
    480       1.1  augustss 	usb_device_request_t req;
    481       1.1  augustss 	struct uvisor_connection_info coninfo; /* XXX ? */
    482       1.1  augustss 	int actlen;
    483       1.3  augustss 
    484       1.3  augustss 	if (sc->sc_dying)
    485       1.3  augustss 		return;
    486       1.1  augustss 
    487       1.1  augustss 	req.bmRequestType = UT_READ_VENDOR_ENDPOINT; /* XXX read? */
    488       1.1  augustss 	req.bRequest = UVISOR_CLOSE_NOTIFICATION;
    489       1.1  augustss 	USETW(req.wValue, 0);
    490       1.1  augustss 	USETW(req.wIndex, 0);
    491       1.1  augustss 	USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
    492      1.16  augustss 	(void)usbd_do_request_flags(sc->sc_udev, &req, &coninfo,
    493      1.13  augustss 		  USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
    494       1.1  augustss }
    495