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