1 /* $NetBSD: uvisor.c,v 1.11 2001/01/23 21:56:17 augustss Exp $ */ 2 3 /* 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net) at 9 * Carlstedt Research & Technology. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Handspring Visor (Palmpilot compatible PDA) driver 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/device.h> 48 #include <sys/conf.h> 49 #include <sys/tty.h> 50 51 #include <dev/usb/usb.h> 52 #include <dev/usb/usbhid.h> 53 54 #include <dev/usb/usbdi.h> 55 #include <dev/usb/usbdi_util.h> 56 #include <dev/usb/usbdevs.h> 57 58 #include <dev/usb/ucomvar.h> 59 60 #ifdef UVISOR_DEBUG 61 #define DPRINTF(x) if (uvisordebug) printf x 62 #define DPRINTFN(n,x) if (uvisordebug>(n)) printf x 63 int uvisordebug = 0; 64 #else 65 #define DPRINTF(x) 66 #define DPRINTFN(n,x) 67 #endif 68 69 #define UVISOR_CONFIG_INDEX 0 70 #define UVISOR_IFACE_INDEX 0 71 72 /* From the Linux driver */ 73 /* 74 * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that 75 * are available to be transfered to the host for the specified endpoint. 76 * Currently this is not used, and always returns 0x0001 77 */ 78 #define UVISOR_REQUEST_BYTES_AVAILABLE 0x01 79 80 /* 81 * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host 82 * is now closing the pipe. An empty packet is sent in response. 83 */ 84 #define UVISOR_CLOSE_NOTIFICATION 0x02 85 86 /* 87 * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to 88 * get the endpoints used by the connection. 89 */ 90 #define UVISOR_GET_CONNECTION_INFORMATION 0x03 91 92 93 /* 94 * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format 95 */ 96 #define UVISOR_MAX_CONN 8 97 struct uvisor_connection_info { 98 uWord num_ports; 99 struct { 100 uByte port_function_id; 101 uByte port; 102 } connections[UVISOR_MAX_CONN]; 103 }; 104 #define UVISOR_CONNECTION_INFO_SIZE 18 105 106 107 /* struct uvisor_connection_info.connection[x].port_function_id defines: */ 108 #define UVISOR_FUNCTION_GENERIC 0x00 109 #define UVISOR_FUNCTION_DEBUGGER 0x01 110 #define UVISOR_FUNCTION_HOTSYNC 0x02 111 #define UVISOR_FUNCTION_CONSOLE 0x03 112 #define UVISOR_FUNCTION_REMOTE_FILE_SYS 0x04 113 114 115 #define UVISORIBUFSIZE 1024 116 #define UVISOROBUFSIZE 1024 117 118 struct uvisor_softc { 119 USBBASEDEVICE sc_dev; /* base device */ 120 usbd_device_handle sc_udev; /* device */ 121 usbd_interface_handle sc_iface; /* interface */ 122 123 device_ptr_t sc_subdevs[UVISOR_MAX_CONN]; 124 int sc_numcon; 125 126 u_char sc_dying; 127 }; 128 129 Static usbd_status uvisor_init(struct uvisor_softc *, 130 struct uvisor_connection_info *); 131 132 Static void uvisor_close(void *, int); 133 134 135 struct ucom_methods uvisor_methods = { 136 NULL, 137 NULL, 138 NULL, 139 NULL, 140 NULL, 141 uvisor_close, 142 NULL, 143 NULL, 144 }; 145 146 USB_DECLARE_DRIVER(uvisor); 147 148 USB_MATCH(uvisor) 149 { 150 USB_MATCH_START(uvisor, uaa); 151 152 if (uaa->iface != NULL) 153 return (UMATCH_NONE); 154 155 DPRINTFN(20,("uvisor: vendor=0x%x, product=0x%x\n", 156 uaa->vendor, uaa->product)); 157 158 if (uaa->vendor == USB_VENDOR_HANDSPRING && 159 uaa->product == USB_PRODUCT_HANDSPRING_VISOR) 160 return (UMATCH_VENDOR_PRODUCT); 161 162 return (UMATCH_NONE); 163 } 164 165 USB_ATTACH(uvisor) 166 { 167 USB_ATTACH_START(uvisor, sc, uaa); 168 usbd_device_handle dev = uaa->device; 169 usbd_interface_handle iface; 170 usb_interface_descriptor_t *id; 171 struct uvisor_connection_info coninfo; 172 usb_endpoint_descriptor_t *ed; 173 char devinfo[1024]; 174 char *devname = USBDEVNAME(sc->sc_dev); 175 int i, j, hasin, hasout, port; 176 usbd_status err; 177 struct ucom_attach_args uca; 178 179 DPRINTFN(10,("\nuvisor_attach: sc=%p\n", sc)); 180 181 /* Move the device into the configured state. */ 182 err = usbd_set_config_index(dev, UVISOR_CONFIG_INDEX, 1); 183 if (err) { 184 printf("\n%s: failed to set configuration, err=%s\n", 185 devname, usbd_errstr(err)); 186 goto bad; 187 } 188 189 err = usbd_device2interface_handle(dev, UVISOR_IFACE_INDEX, &iface); 190 if (err) { 191 printf("\n%s: failed to get interface, err=%s\n", 192 devname, usbd_errstr(err)); 193 goto bad; 194 } 195 196 usbd_devinfo(dev, 0, devinfo); 197 USB_ATTACH_SETUP; 198 printf("%s: %s\n", devname, devinfo); 199 200 id = usbd_get_interface_descriptor(iface); 201 202 sc->sc_udev = dev; 203 sc->sc_iface = iface; 204 205 uca.ibufsize = UVISORIBUFSIZE; 206 uca.obufsize = UVISOROBUFSIZE; 207 uca.ibufsizepad = UVISORIBUFSIZE; 208 uca.opkthdrlen = 0; 209 uca.device = dev; 210 uca.iface = iface; 211 uca.methods = &uvisor_methods; 212 uca.arg = sc; 213 214 err = uvisor_init(sc, &coninfo); 215 if (err) { 216 printf("%s: init failed, %s\n", USBDEVNAME(sc->sc_dev), 217 usbd_errstr(err)); 218 goto bad; 219 } 220 221 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 222 USBDEV(sc->sc_dev)); 223 224 sc->sc_numcon = UGETW(coninfo.num_ports); 225 if (sc->sc_numcon > UVISOR_MAX_CONN) 226 sc->sc_numcon = UVISOR_MAX_CONN; 227 228 /* Attach a ucom for each connection. */ 229 for (i = 0; i < sc->sc_numcon; ++i) { 230 switch (coninfo.connections[i].port_function_id) { 231 case UVISOR_FUNCTION_GENERIC: 232 uca.info = "Generic"; 233 break; 234 case UVISOR_FUNCTION_DEBUGGER: 235 uca.info = "Debugger"; 236 break; 237 case UVISOR_FUNCTION_HOTSYNC: 238 uca.info = "HotSync"; 239 break; 240 case UVISOR_FUNCTION_REMOTE_FILE_SYS: 241 uca.info = "Remote File System"; 242 break; 243 default: 244 uca.info = "unknown"; 245 break; 246 } 247 port = coninfo.connections[i].port; 248 uca.portno = port; 249 uca.bulkin = port | UE_DIR_IN; 250 uca.bulkout = port | UE_DIR_OUT; 251 /* Verify that endpoints exist. */ 252 for (hasin = hasout = j = 0; j < id->bNumEndpoints; j++) { 253 ed = usbd_interface2endpoint_descriptor(iface, j); 254 if (ed == NULL) 255 break; 256 if (UE_GET_ADDR(ed->bEndpointAddress) == port && 257 (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { 258 if (UE_GET_DIR(ed->bEndpointAddress) 259 == UE_DIR_IN) 260 hasin++; 261 else 262 hasout++; 263 } 264 } 265 if (hasin == 1 && hasout == 1) 266 sc->sc_subdevs[i] = config_found_sm(self, &uca, 267 ucomprint, ucomsubmatch); 268 else 269 printf("%s: no proper endpoints for port %d (%d,%d)\n", 270 USBDEVNAME(sc->sc_dev), port, hasin, hasout); 271 } 272 273 USB_ATTACH_SUCCESS_RETURN; 274 275 bad: 276 DPRINTF(("uvisor_attach: ATTACH ERROR\n")); 277 sc->sc_dying = 1; 278 USB_ATTACH_ERROR_RETURN; 279 } 280 281 int 282 uvisor_activate(device_ptr_t self, enum devact act) 283 { 284 struct uvisor_softc *sc = (struct uvisor_softc *)self; 285 int rv = 0; 286 int i; 287 288 switch (act) { 289 case DVACT_ACTIVATE: 290 return (EOPNOTSUPP); 291 break; 292 293 case DVACT_DEACTIVATE: 294 for (i = 0; i < sc->sc_numcon; i++) 295 if (sc->sc_subdevs[i] != NULL) 296 rv = config_deactivate(sc->sc_subdevs[i]); 297 sc->sc_dying = 1; 298 break; 299 } 300 return (rv); 301 } 302 303 int 304 uvisor_detach(device_ptr_t self, int flags) 305 { 306 struct uvisor_softc *sc = (struct uvisor_softc *)self; 307 int rv = 0; 308 int i; 309 310 DPRINTF(("uvisor_detach: sc=%p flags=%d\n", sc, flags)); 311 sc->sc_dying = 1; 312 for (i = 0; i < sc->sc_numcon; i++) { 313 if (sc->sc_subdevs[i] != NULL) { 314 rv |= config_detach(sc->sc_subdevs[i], flags); 315 sc->sc_subdevs[i] = NULL; 316 } 317 } 318 319 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 320 USBDEV(sc->sc_dev)); 321 322 323 return (rv); 324 } 325 326 usbd_status 327 uvisor_init(struct uvisor_softc *sc, struct uvisor_connection_info *ci) 328 { 329 usbd_status err; 330 usb_device_request_t req; 331 int actlen; 332 uWord avail; 333 334 DPRINTF(("uvisor_init: getting connection info\n")); 335 req.bmRequestType = UT_READ_VENDOR_ENDPOINT; 336 req.bRequest = UVISOR_GET_CONNECTION_INFORMATION; 337 USETW(req.wValue, 0); 338 USETW(req.wIndex, 0); 339 USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE); 340 err = usbd_do_request_flags(sc->sc_udev, &req, ci, 341 USBD_SHORT_XFER_OK, &actlen); 342 if (err) 343 return (err); 344 345 DPRINTF(("uvisor_init: getting available bytes\n")); 346 req.bmRequestType = UT_READ_VENDOR_ENDPOINT; 347 req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE; 348 USETW(req.wValue, 0); 349 USETW(req.wIndex, 5); 350 USETW(req.wLength, sizeof avail); 351 err = usbd_do_request(sc->sc_udev, &req, &avail); 352 if (err) 353 return (err); 354 DPRINTF(("uvisor_init: avail=%d\n", UGETW(avail))); 355 356 DPRINTF(("uvisor_init: done\n")); 357 return (err); 358 } 359 360 void 361 uvisor_close(void *addr, int portno) 362 { 363 struct uvisor_softc *sc = addr; 364 usb_device_request_t req; 365 struct uvisor_connection_info coninfo; /* XXX ? */ 366 int actlen; 367 368 if (sc->sc_dying) 369 return; 370 371 req.bmRequestType = UT_READ_VENDOR_ENDPOINT; /* XXX read? */ 372 req.bRequest = UVISOR_CLOSE_NOTIFICATION; 373 USETW(req.wValue, 0); 374 USETW(req.wIndex, 0); 375 USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE); 376 (void)usbd_do_request_flags(sc->sc_udev, &req, &coninfo, 377 USBD_SHORT_XFER_OK, &actlen); 378 } 379