1 1.94 hannken /* $NetBSD: uplcom.c,v 1.94 2022/07/06 15:24:14 hannken Exp $ */ 2 1.83 mrg 3 1.1 ichiro /* 4 1.3 ichiro * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 1.1 ichiro * All rights reserved. 6 1.1 ichiro * 7 1.1 ichiro * This code is derived from software contributed to The NetBSD Foundation 8 1.12 ichiro * by Ichiro FUKUHARA (ichiro (at) ichiro.org). 9 1.1 ichiro * 10 1.1 ichiro * Redistribution and use in source and binary forms, with or without 11 1.1 ichiro * modification, are permitted provided that the following conditions 12 1.1 ichiro * are met: 13 1.1 ichiro * 1. Redistributions of source code must retain the above copyright 14 1.1 ichiro * notice, this list of conditions and the following disclaimer. 15 1.1 ichiro * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 ichiro * notice, this list of conditions and the following disclaimer in the 17 1.1 ichiro * documentation and/or other materials provided with the distribution. 18 1.1 ichiro * 19 1.1 ichiro * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 ichiro * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 ichiro * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 ichiro * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 ichiro * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 ichiro * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 ichiro * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 ichiro * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 ichiro * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 ichiro * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 ichiro * POSSIBILITY OF SUCH DAMAGE. 30 1.1 ichiro */ 31 1.1 ichiro 32 1.1 ichiro /* 33 1.31 wiz * General information: http://www.prolific.com.tw/fr_pl2303.htm 34 1.31 wiz * http://www.hitachi-hitec.com/jyouhou/prolific/2303.pdf 35 1.1 ichiro */ 36 1.21 lukem 37 1.21 lukem #include <sys/cdefs.h> 38 1.94 hannken __KERNEL_RCSID(0, "$NetBSD: uplcom.c,v 1.94 2022/07/06 15:24:14 hannken Exp $"); 39 1.1 ichiro 40 1.78 skrll #ifdef _KERNEL_OPT 41 1.78 skrll #include "opt_usb.h" 42 1.78 skrll #endif 43 1.80 skrll 44 1.1 ichiro #include <sys/param.h> 45 1.1 ichiro #include <sys/systm.h> 46 1.1 ichiro #include <sys/kernel.h> 47 1.77 skrll #include <sys/kmem.h> 48 1.1 ichiro #include <sys/ioctl.h> 49 1.1 ichiro #include <sys/conf.h> 50 1.1 ichiro #include <sys/tty.h> 51 1.1 ichiro #include <sys/file.h> 52 1.1 ichiro #include <sys/select.h> 53 1.1 ichiro #include <sys/proc.h> 54 1.1 ichiro #include <sys/device.h> 55 1.1 ichiro #include <sys/poll.h> 56 1.83 mrg #include <sys/sysctl.h> 57 1.1 ichiro 58 1.1 ichiro #include <dev/usb/usb.h> 59 1.1 ichiro #include <dev/usb/usbcdc.h> 60 1.1 ichiro 61 1.1 ichiro #include <dev/usb/usbdi.h> 62 1.1 ichiro #include <dev/usb/usbdi_util.h> 63 1.1 ichiro #include <dev/usb/usbdevs.h> 64 1.1 ichiro #include <dev/usb/usb_quirks.h> 65 1.83 mrg #include <dev/usb/usbhist.h> 66 1.1 ichiro 67 1.1 ichiro #include <dev/usb/ucomvar.h> 68 1.1 ichiro 69 1.83 mrg #ifdef USB_DEBUG 70 1.83 mrg #ifndef UPLCOM_DEBUG 71 1.83 mrg #define uplcomdebug 0 72 1.83 mrg #else 73 1.12 ichiro int uplcomdebug = 0; 74 1.83 mrg 75 1.83 mrg SYSCTL_SETUP(sysctl_hw_uplcom_setup, "sysctl hw.uplcom setup") 76 1.83 mrg { 77 1.83 mrg int err; 78 1.83 mrg const struct sysctlnode *rnode; 79 1.83 mrg const struct sysctlnode *cnode; 80 1.83 mrg 81 1.83 mrg err = sysctl_createv(clog, 0, NULL, &rnode, 82 1.83 mrg CTLFLAG_PERMANENT, CTLTYPE_NODE, "uplcom", 83 1.83 mrg SYSCTL_DESCR("uplcom global controls"), 84 1.83 mrg NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL); 85 1.83 mrg 86 1.83 mrg if (err) 87 1.83 mrg goto fail; 88 1.83 mrg 89 1.83 mrg /* control debugging printfs */ 90 1.83 mrg err = sysctl_createv(clog, 0, &rnode, &cnode, 91 1.83 mrg CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, 92 1.83 mrg "debug", SYSCTL_DESCR("Enable debugging output"), 93 1.83 mrg NULL, 0, &uplcomdebug, sizeof(uplcomdebug), CTL_CREATE, CTL_EOL); 94 1.83 mrg if (err) 95 1.83 mrg goto fail; 96 1.83 mrg 97 1.83 mrg return; 98 1.83 mrg fail: 99 1.83 mrg aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err); 100 1.83 mrg } 101 1.83 mrg 102 1.83 mrg #endif /* UCOM_DEBUG */ 103 1.83 mrg #endif /* USB_DEBUG */ 104 1.83 mrg 105 1.83 mrg 106 1.83 mrg #define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(uplcomdebug,1,FMT,A,B,C,D) 107 1.83 mrg #define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(uplcomdebug,N,FMT,A,B,C,D) 108 1.83 mrg #define UPLCOMHIST_FUNC() USBHIST_FUNC() 109 1.83 mrg #define UPLCOMHIST_CALLED(name) USBHIST_CALLED(uplcomdebug) 110 1.1 ichiro 111 1.1 ichiro #define UPLCOM_CONFIG_INDEX 0 112 1.10 ichiro #define UPLCOM_IFACE_INDEX 0 113 1.10 ichiro #define UPLCOM_SECOND_IFACE_INDEX 1 114 1.1 ichiro 115 1.92 nat #define UPLCOM_SET_REQUEST 0x01 116 1.92 nat #define UPLCOM_SET_CRTSCTS_0 0x41 117 1.92 nat #define UPLCOM_SET_CRTSCTS_HX 0x61 118 1.93 nat #define UPLCOM_HX_STATUS_REG 0x8080 119 1.92 nat 120 1.92 nat #define UPLCOM_N_SERIAL_CTS 0x80 121 1.92 nat 122 1.92 nat #define UPLCOM_HXN_SET_REQUEST 0x80 123 1.92 nat #define UPLCOM_HXN_SET_CRTSCTS_REG 0x0A 124 1.92 nat #define UPLCOM_HXN_SET_CRTSCTS 0xFA 125 1.12 ichiro 126 1.43 augustss enum pl2303_type { 127 1.66 martin UPLCOM_TYPE_0, /* we use this for all non-HX variants */ 128 1.43 augustss UPLCOM_TYPE_HX, 129 1.92 nat UPLCOM_TYPE_HXN, 130 1.43 augustss }; 131 1.43 augustss 132 1.1 ichiro struct uplcom_softc { 133 1.71 dyoung device_t sc_dev; /* base device */ 134 1.77 skrll struct usbd_device * sc_udev; /* USB device */ 135 1.77 skrll struct usbd_interface * sc_iface; /* interface */ 136 1.1 ichiro int sc_iface_number; /* interface number */ 137 1.1 ichiro 138 1.77 skrll struct usbd_interface * sc_intr_iface; /* interrupt interface */ 139 1.12 ichiro int sc_intr_number; /* interrupt number */ 140 1.77 skrll struct usbd_pipe * sc_intr_pipe; /* interrupt pipe */ 141 1.12 ichiro u_char *sc_intr_buf; /* interrupt buffer */ 142 1.12 ichiro int sc_isize; 143 1.12 ichiro 144 1.1 ichiro usb_cdc_line_state_t sc_line_state; /* current line state */ 145 1.37 martin int sc_dtr; /* current DTR state */ 146 1.37 martin int sc_rts; /* current RTS state */ 147 1.1 ichiro 148 1.71 dyoung device_t sc_subdev; /* ucom device */ 149 1.1 ichiro 150 1.84 mrg bool sc_dying; /* disconnecting */ 151 1.12 ichiro 152 1.12 ichiro u_char sc_lsr; /* Local status register */ 153 1.12 ichiro u_char sc_msr; /* uplcom status register */ 154 1.43 augustss 155 1.43 augustss enum pl2303_type sc_type; /* PL2303 chip type */ 156 1.1 ichiro }; 157 1.1 ichiro 158 1.1 ichiro /* 159 1.1 ichiro * These are the maximum number of bytes transferred per frame. 160 1.1 ichiro * The output buffer size cannot be increased due to the size encoding. 161 1.1 ichiro */ 162 1.6 augustss #define UPLCOMIBUFSIZE 256 163 1.6 augustss #define UPLCOMOBUFSIZE 256 164 1.1 ichiro 165 1.84 mrg static usbd_status uplcom_reset(struct uplcom_softc *); 166 1.84 mrg static usbd_status uplcom_set_line_coding(struct uplcom_softc *, 167 1.77 skrll usb_cdc_line_state_t *); 168 1.84 mrg static usbd_status uplcom_set_crtscts(struct uplcom_softc *); 169 1.84 mrg static void uplcom_intr(struct usbd_xfer *, void *, usbd_status); 170 1.1 ichiro 171 1.84 mrg static void uplcom_set(void *, int, int, int); 172 1.84 mrg static void uplcom_dtr(struct uplcom_softc *, int); 173 1.84 mrg static void uplcom_rts(struct uplcom_softc *, int); 174 1.84 mrg static void uplcom_break(struct uplcom_softc *, int); 175 1.84 mrg static void uplcom_set_line_state(struct uplcom_softc *); 176 1.84 mrg static void uplcom_get_status(void *, int, u_char *, u_char *); 177 1.12 ichiro #if TODO 178 1.84 mrg static int uplcom_ioctl(void *, int, u_long, void *, int, proc_t *); 179 1.12 ichiro #endif 180 1.84 mrg static int uplcom_param(void *, int, struct termios *); 181 1.84 mrg static int uplcom_open(void *, int); 182 1.84 mrg static void uplcom_close(void *, int); 183 1.84 mrg static usbd_status uplcom_vendor_control_write(struct usbd_device *, uint16_t, uint16_t); 184 1.84 mrg static void uplcom_close_pipe(struct uplcom_softc *); 185 1.1 ichiro 186 1.86 maxv static const struct ucom_methods uplcom_methods = { 187 1.77 skrll .ucom_get_status = uplcom_get_status, 188 1.77 skrll .ucom_set = uplcom_set, 189 1.77 skrll .ucom_param = uplcom_param, 190 1.77 skrll .ucom_ioctl = NULL, /* TODO */ 191 1.77 skrll .ucom_open = uplcom_open, 192 1.77 skrll .ucom_close = uplcom_close, 193 1.1 ichiro }; 194 1.1 ichiro 195 1.66 martin static const struct usb_devno uplcom_devs[] = { 196 1.1 ichiro /* I/O DATA USB-RSAQ2 */ 197 1.66 martin { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2 }, 198 1.48 martin /* I/O DATA USB-RSAQ3 */ 199 1.66 martin { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ3 }, 200 1.13 ichiro /* I/O DATA USB-RSAQ */ 201 1.66 martin { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ }, 202 1.55 uebayasi /* I/O DATA USB-RSAQ5 */ 203 1.66 martin { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ5 }, 204 1.16 ichiro /* PLANEX USB-RS232 URS-03 */ 205 1.66 martin { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC232A }, 206 1.66 martin /* various */ 207 1.66 martin { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303 }, 208 1.58 sborrill /* SMART Technologies USB to serial */ 209 1.66 martin { USB_VENDOR_PROLIFIC2, USB_PRODUCT_PROLIFIC2_PL2303 }, 210 1.34 augustss /* IOGEAR/ATENTRIPPLITE */ 211 1.66 martin { USB_VENDOR_TRIPPLITE, USB_PRODUCT_TRIPPLITE_U209 }, 212 1.22 augustss /* ELECOM UC-SGT */ 213 1.66 martin { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT }, 214 1.46 sekiya /* ELECOM UC-SGT0 */ 215 1.66 martin { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT0 }, 216 1.44 pooka /* Panasonic 50" Touch Panel */ 217 1.66 martin { USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_TYTP50P6S }, 218 1.25 ichiro /* RATOC REX-USB60 */ 219 1.66 martin { USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60 }, 220 1.26 ichiro /* TDK USB-PHS Adapter UHA6400 */ 221 1.66 martin { USB_VENDOR_TDK, USB_PRODUCT_TDK_UHA6400 }, 222 1.27 ichiro /* TDK USB-PDC Adapter UPA9664 */ 223 1.66 martin { USB_VENDOR_TDK, USB_PRODUCT_TDK_UPA9664 }, 224 1.30 augustss /* Sony Ericsson USB Cable */ 225 1.66 martin { USB_VENDOR_SUSTEEN, USB_PRODUCT_SUSTEEN_DCU10 }, 226 1.32 augustss /* SOURCENEXT KeikaiDenwa 8 */ 227 1.66 martin { USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8 }, 228 1.32 augustss /* SOURCENEXT KeikaiDenwa 8 with charger */ 229 1.66 martin { USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8_CHG }, 230 1.32 augustss /* HAL Corporation Crossam2+USB */ 231 1.66 martin { USB_VENDOR_HAL, USB_PRODUCT_HAL_IMR001 }, 232 1.38 jdolecek /* Sitecom USB to serial cable */ 233 1.66 martin { USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_CN104 }, 234 1.41 augustss /* Pharos USB GPS - Microsoft version */ 235 1.66 martin { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303X }, 236 1.52 msaitoh /* Willcom WS002IN (DD) */ 237 1.66 martin { USB_VENDOR_NETINDEX, USB_PRODUCT_NETINDEX_WS002IN }, 238 1.67 jnemeth /* COREGA CG-USBRS232R */ 239 1.67 jnemeth { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGUSBRS232R }, 240 1.74 ryoon /* Sharp CE-175TU (USB to Zaurus option port 15 adapter) */ 241 1.74 ryoon { USB_VENDOR_SHARP, USB_PRODUCT_SHARP_CE175TU }, 242 1.92 nat /* Various */ 243 1.92 nat { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303GB }, 244 1.92 nat { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303GC }, 245 1.92 nat { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303GE }, 246 1.92 nat { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303GL }, 247 1.92 nat { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303GS }, 248 1.92 nat { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303GT }, 249 1.1 ichiro }; 250 1.23 augustss #define uplcom_lookup(v, p) usb_lookup(uplcom_devs, v, p) 251 1.32 augustss 252 1.86 maxv static int uplcom_match(device_t, cfdata_t, void *); 253 1.86 maxv static void uplcom_attach(device_t, device_t, void *); 254 1.86 maxv static void uplcom_childdet(device_t, device_t); 255 1.86 maxv static int uplcom_detach(device_t, int); 256 1.82 mrg 257 1.65 cube CFATTACH_DECL2_NEW(uplcom, sizeof(struct uplcom_softc), uplcom_match, 258 1.84 mrg uplcom_attach, uplcom_detach, NULL, NULL, uplcom_childdet); 259 1.1 ichiro 260 1.86 maxv static int 261 1.71 dyoung uplcom_match(device_t parent, cfdata_t match, void *aux) 262 1.1 ichiro { 263 1.71 dyoung struct usb_attach_arg *uaa = aux; 264 1.1 ichiro 265 1.77 skrll return uplcom_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? 266 1.77 skrll UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 267 1.1 ichiro } 268 1.1 ichiro 269 1.86 maxv static void 270 1.71 dyoung uplcom_attach(device_t parent, device_t self, void *aux) 271 1.1 ichiro { 272 1.71 dyoung struct uplcom_softc *sc = device_private(self); 273 1.71 dyoung struct usb_attach_arg *uaa = aux; 274 1.77 skrll struct usbd_device *dev = uaa->uaa_device; 275 1.66 martin usb_device_descriptor_t *ddesc; 276 1.10 ichiro usb_config_descriptor_t *cdesc; 277 1.1 ichiro usb_interface_descriptor_t *id; 278 1.1 ichiro usb_endpoint_descriptor_t *ed; 279 1.92 nat usb_device_request_t req; 280 1.42 augustss char *devinfop; 281 1.65 cube const char *devname = device_xname(self); 282 1.1 ichiro usbd_status err; 283 1.92 nat uint8_t val; 284 1.1 ichiro int i; 285 1.77 skrll struct ucom_attach_args ucaa; 286 1.1 ichiro 287 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 288 1.85 skrll DPRINTF("sc=%#jx", (uintptr_t)sc, 0, 0, 0); 289 1.83 mrg 290 1.65 cube sc->sc_dev = self; 291 1.84 mrg sc->sc_dying = false; 292 1.65 cube 293 1.68 plunky aprint_naive("\n"); 294 1.68 plunky aprint_normal("\n"); 295 1.68 plunky 296 1.42 augustss devinfop = usbd_devinfo_alloc(dev, 0); 297 1.65 cube aprint_normal_dev(self, "%s\n", devinfop); 298 1.42 augustss usbd_devinfo_free(devinfop); 299 1.10 ichiro 300 1.77 skrll sc->sc_udev = dev; 301 1.10 ichiro 302 1.28 augustss /* initialize endpoints */ 303 1.77 skrll ucaa.ucaa_bulkin = ucaa.ucaa_bulkout = -1; 304 1.13 ichiro sc->sc_intr_number = -1; 305 1.13 ichiro sc->sc_intr_pipe = NULL; 306 1.13 ichiro 307 1.6 augustss /* Move the device into the configured state. */ 308 1.1 ichiro err = usbd_set_config_index(dev, UPLCOM_CONFIG_INDEX, 1); 309 1.1 ichiro if (err) { 310 1.65 cube aprint_error("\n%s: failed to set configuration, err=%s\n", 311 1.1 ichiro devname, usbd_errstr(err)); 312 1.84 mrg sc->sc_dying = true; 313 1.71 dyoung return; 314 1.1 ichiro } 315 1.1 ichiro 316 1.48 martin /* determine chip type */ 317 1.66 martin ddesc = usbd_get_device_descriptor(dev); 318 1.66 martin if (ddesc->bDeviceClass != UDCLASS_COMM && 319 1.93 nat ddesc->bMaxPacketSize == 0x40) 320 1.66 martin sc->sc_type = UPLCOM_TYPE_HX; 321 1.92 nat 322 1.92 nat if (sc->sc_type == UPLCOM_TYPE_HX) { 323 1.92 nat req.bmRequestType = UT_READ_VENDOR_DEVICE; 324 1.92 nat req.bRequest = UPLCOM_SET_REQUEST; 325 1.92 nat USETW(req.wValue, UPLCOM_HX_STATUS_REG); 326 1.92 nat USETW(req.wIndex, sc->sc_iface_number); 327 1.92 nat USETW(req.wLength, 1); 328 1.92 nat 329 1.92 nat err = usbd_do_request(sc->sc_udev, &req, &val); 330 1.92 nat if (err) 331 1.92 nat sc->sc_type = UPLCOM_TYPE_HXN; 332 1.92 nat } 333 1.59 mlelstv 334 1.66 martin #ifdef UPLCOM_DEBUG 335 1.59 mlelstv /* print the chip type */ 336 1.92 nat if (sc->sc_type == UPLCOM_TYPE_HXN) { 337 1.92 nat DPRINTF("chiptype HXN", 0, 0, 0, 0); 338 1.94 hannken } else if (sc->sc_type == UPLCOM_TYPE_HX) { 339 1.83 mrg DPRINTF("chiptype HX", 0, 0, 0, 0); 340 1.59 mlelstv } else { 341 1.83 mrg DPRINTF("chiptype 0", 0, 0, 0, 0); 342 1.59 mlelstv } 343 1.59 mlelstv #endif 344 1.59 mlelstv 345 1.59 mlelstv /* Move the device into the configured state. */ 346 1.59 mlelstv err = usbd_set_config_index(dev, UPLCOM_CONFIG_INDEX, 1); 347 1.59 mlelstv if (err) { 348 1.65 cube aprint_error_dev(self, "failed to set configuration: %s\n", 349 1.65 cube usbd_errstr(err)); 350 1.84 mrg sc->sc_dying = true; 351 1.71 dyoung return; 352 1.59 mlelstv } 353 1.43 augustss 354 1.10 ichiro /* get the config descriptor */ 355 1.10 ichiro cdesc = usbd_get_config_descriptor(sc->sc_udev); 356 1.10 ichiro 357 1.10 ichiro if (cdesc == NULL) { 358 1.65 cube aprint_error_dev(self, 359 1.65 cube "failed to get configuration descriptor\n"); 360 1.84 mrg sc->sc_dying = true; 361 1.71 dyoung return; 362 1.10 ichiro } 363 1.10 ichiro 364 1.13 ichiro /* get the (first/common) interface */ 365 1.28 augustss err = usbd_device2interface_handle(dev, UPLCOM_IFACE_INDEX, 366 1.10 ichiro &sc->sc_iface); 367 1.1 ichiro if (err) { 368 1.65 cube aprint_error("\n%s: failed to get interface, err=%s\n", 369 1.1 ichiro devname, usbd_errstr(err)); 370 1.84 mrg sc->sc_dying = true; 371 1.71 dyoung return; 372 1.1 ichiro } 373 1.13 ichiro 374 1.13 ichiro /* Find the interrupt endpoints */ 375 1.13 ichiro 376 1.13 ichiro id = usbd_get_interface_descriptor(sc->sc_iface); 377 1.13 ichiro sc->sc_iface_number = id->bInterfaceNumber; 378 1.13 ichiro 379 1.13 ichiro for (i = 0; i < id->bNumEndpoints; i++) { 380 1.13 ichiro ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); 381 1.13 ichiro if (ed == NULL) { 382 1.65 cube aprint_error_dev(self, 383 1.65 cube "no endpoint descriptor for %d\n", i); 384 1.84 mrg sc->sc_dying = true; 385 1.71 dyoung return; 386 1.13 ichiro } 387 1.13 ichiro 388 1.13 ichiro if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 389 1.13 ichiro UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 390 1.13 ichiro sc->sc_intr_number = ed->bEndpointAddress; 391 1.13 ichiro sc->sc_isize = UGETW(ed->wMaxPacketSize); 392 1.28 augustss } 393 1.13 ichiro } 394 1.13 ichiro 395 1.13 ichiro if (sc->sc_intr_number== -1) { 396 1.65 cube aprint_error_dev(self, "Could not find interrupt in\n"); 397 1.84 mrg sc->sc_dying = true; 398 1.71 dyoung return; 399 1.13 ichiro } 400 1.13 ichiro 401 1.20 ichiro /* keep interface for interrupt */ 402 1.20 ichiro sc->sc_intr_iface = sc->sc_iface; 403 1.20 ichiro 404 1.10 ichiro /* 405 1.13 ichiro * USB-RSAQ1 has two interface 406 1.13 ichiro * 407 1.13 ichiro * USB-RSAQ1 | USB-RSAQ2 408 1.80 skrll * -----------------+----------------- 409 1.14 ichiro * Interface 0 |Interface 0 410 1.14 ichiro * Interrupt(0x81) | Interrupt(0x81) 411 1.13 ichiro * -----------------+ BulkIN(0x02) 412 1.14 ichiro * Interface 1 | BulkOUT(0x83) 413 1.28 augustss * BulkIN(0x02) | 414 1.13 ichiro * BulkOUT(0x83) | 415 1.10 ichiro */ 416 1.10 ichiro if (cdesc->bNumInterface == 2) { 417 1.28 augustss err = usbd_device2interface_handle(dev, 418 1.13 ichiro UPLCOM_SECOND_IFACE_INDEX, &sc->sc_iface); 419 1.10 ichiro if (err) { 420 1.79 msaitoh aprint_error("\n%s: failed to get second interface, " 421 1.79 msaitoh "err=%s\n", devname, usbd_errstr(err)); 422 1.84 mrg sc->sc_dying = true; 423 1.71 dyoung return; 424 1.10 ichiro } 425 1.28 augustss } 426 1.1 ichiro 427 1.13 ichiro /* Find the bulk{in,out} endpoints */ 428 1.1 ichiro 429 1.12 ichiro id = usbd_get_interface_descriptor(sc->sc_iface); 430 1.1 ichiro sc->sc_iface_number = id->bInterfaceNumber; 431 1.1 ichiro 432 1.1 ichiro for (i = 0; i < id->bNumEndpoints; i++) { 433 1.12 ichiro ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); 434 1.1 ichiro if (ed == NULL) { 435 1.65 cube aprint_error_dev(self, 436 1.65 cube "no endpoint descriptor for %d\n", i); 437 1.84 mrg sc->sc_dying = true; 438 1.71 dyoung return; 439 1.1 ichiro } 440 1.1 ichiro 441 1.1 ichiro if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 442 1.1 ichiro UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 443 1.77 skrll ucaa.ucaa_bulkin = ed->bEndpointAddress; 444 1.1 ichiro } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 445 1.1 ichiro UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 446 1.77 skrll ucaa.ucaa_bulkout = ed->bEndpointAddress; 447 1.1 ichiro } 448 1.1 ichiro } 449 1.1 ichiro 450 1.77 skrll if (ucaa.ucaa_bulkin == -1) { 451 1.65 cube aprint_error_dev(self, "Could not find data bulk in\n"); 452 1.84 mrg sc->sc_dying = true; 453 1.71 dyoung return; 454 1.1 ichiro } 455 1.1 ichiro 456 1.77 skrll if (ucaa.ucaa_bulkout == -1) { 457 1.65 cube aprint_error_dev(self, "Could not find data bulk out\n"); 458 1.84 mrg sc->sc_dying = true; 459 1.71 dyoung return; 460 1.12 ichiro } 461 1.12 ichiro 462 1.37 martin sc->sc_dtr = sc->sc_rts = -1; 463 1.77 skrll ucaa.ucaa_portno = UCOM_UNK_PORTNO; 464 1.77 skrll /* ucaa_bulkin, ucaa_bulkout set above */ 465 1.77 skrll ucaa.ucaa_ibufsize = UPLCOMIBUFSIZE; 466 1.77 skrll ucaa.ucaa_obufsize = UPLCOMOBUFSIZE; 467 1.77 skrll ucaa.ucaa_ibufsizepad = UPLCOMIBUFSIZE; 468 1.77 skrll ucaa.ucaa_opkthdrlen = 0; 469 1.77 skrll ucaa.ucaa_device = dev; 470 1.77 skrll ucaa.ucaa_iface = sc->sc_iface; 471 1.77 skrll ucaa.ucaa_methods = &uplcom_methods; 472 1.77 skrll ucaa.ucaa_arg = sc; 473 1.77 skrll ucaa.ucaa_info = NULL; 474 1.1 ichiro 475 1.11 ichiro err = uplcom_reset(sc); 476 1.11 ichiro 477 1.1 ichiro if (err) { 478 1.65 cube aprint_error_dev(self, "reset failed, %s\n", usbd_errstr(err)); 479 1.84 mrg sc->sc_dying = true; 480 1.71 dyoung return; 481 1.1 ichiro } 482 1.1 ichiro 483 1.79 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 484 1.7 augustss 485 1.89 christos DPRINTF("in=%#jx out=%#jx intr=%#jx", 486 1.83 mrg ucaa.ucaa_bulkin, ucaa.ucaa_bulkout, sc->sc_intr_number, 0); 487 1.90 thorpej sc->sc_subdev = config_found(self, &ucaa, ucomprint, 488 1.91 thorpej CFARGS(.submatch = ucomsubmatch)); 489 1.1 ichiro 490 1.75 riastrad if (!pmf_device_register(self, NULL, NULL)) 491 1.75 riastrad aprint_error_dev(self, "couldn't establish power handler\n"); 492 1.75 riastrad 493 1.71 dyoung return; 494 1.1 ichiro } 495 1.1 ichiro 496 1.86 maxv static void 497 1.60 dyoung uplcom_childdet(device_t self, device_t child) 498 1.60 dyoung { 499 1.60 dyoung struct uplcom_softc *sc = device_private(self); 500 1.60 dyoung 501 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 502 1.83 mrg 503 1.60 dyoung KASSERT(sc->sc_subdev == child); 504 1.60 dyoung sc->sc_subdev = NULL; 505 1.60 dyoung } 506 1.83 mrg 507 1.84 mrg static void 508 1.84 mrg uplcom_close_pipe(struct uplcom_softc *sc) 509 1.84 mrg { 510 1.84 mrg 511 1.84 mrg if (sc->sc_intr_pipe != NULL) { 512 1.84 mrg usbd_abort_pipe(sc->sc_intr_pipe); 513 1.84 mrg usbd_close_pipe(sc->sc_intr_pipe); 514 1.84 mrg sc->sc_intr_pipe = NULL; 515 1.84 mrg } 516 1.84 mrg if (sc->sc_intr_buf != NULL) { 517 1.84 mrg kmem_free(sc->sc_intr_buf, sc->sc_isize); 518 1.84 mrg sc->sc_intr_buf = NULL; 519 1.84 mrg } 520 1.84 mrg } 521 1.84 mrg 522 1.86 maxv static int 523 1.71 dyoung uplcom_detach(device_t self, int flags) 524 1.1 ichiro { 525 1.71 dyoung struct uplcom_softc *sc = device_private(self); 526 1.1 ichiro int rv = 0; 527 1.1 ichiro 528 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 529 1.89 christos DPRINTF("sc=%#jx flags=%jd", (uintptr_t)sc, flags, 0, 0); 530 1.12 ichiro 531 1.84 mrg sc->sc_dying = true; 532 1.84 mrg 533 1.84 mrg uplcom_close_pipe(sc); 534 1.12 ichiro 535 1.84 mrg if (sc->sc_subdev != NULL) { 536 1.1 ichiro rv = config_detach(sc->sc_subdev, flags); 537 1.84 mrg sc->sc_subdev = NULL; 538 1.84 mrg } 539 1.7 augustss 540 1.79 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 541 1.1 ichiro 542 1.84 mrg pmf_device_deregister(self); 543 1.75 riastrad 544 1.77 skrll return rv; 545 1.1 ichiro } 546 1.1 ichiro 547 1.1 ichiro usbd_status 548 1.11 ichiro uplcom_reset(struct uplcom_softc *sc) 549 1.1 ichiro { 550 1.66 martin usb_device_request_t req; 551 1.1 ichiro usbd_status err; 552 1.1 ichiro 553 1.92 nat if (sc->sc_type == UPLCOM_TYPE_HXN) 554 1.92 nat return 0; 555 1.92 nat 556 1.77 skrll req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 557 1.77 skrll req.bRequest = UPLCOM_SET_REQUEST; 558 1.77 skrll USETW(req.wValue, 0); 559 1.77 skrll USETW(req.wIndex, sc->sc_iface_number); 560 1.77 skrll USETW(req.wLength, 0); 561 1.28 augustss 562 1.77 skrll err = usbd_do_request(sc->sc_udev, &req, 0); 563 1.1 ichiro if (err) 564 1.77 skrll return EIO; 565 1.1 ichiro 566 1.77 skrll return 0; 567 1.1 ichiro } 568 1.1 ichiro 569 1.59 mlelstv struct pl2303x_init { 570 1.59 mlelstv uint8_t req_type; 571 1.59 mlelstv uint8_t request; 572 1.59 mlelstv uint16_t value; 573 1.59 mlelstv uint16_t index; 574 1.59 mlelstv }; 575 1.59 mlelstv 576 1.59 mlelstv static const struct pl2303x_init pl2303x[] = { 577 1.76 skrll { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0 }, 578 1.76 skrll { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0 }, 579 1.76 skrll { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0 }, 580 1.76 skrll { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0 }, 581 1.76 skrll { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0 }, 582 1.76 skrll { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 1 }, 583 1.76 skrll { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0 }, 584 1.76 skrll { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0 }, 585 1.76 skrll { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0, 1 }, 586 1.76 skrll { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0 }, 587 1.76 skrll { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44 } 588 1.59 mlelstv }; 589 1.59 mlelstv #define N_PL2302X_INIT (sizeof(pl2303x)/sizeof(pl2303x[0])) 590 1.59 mlelstv 591 1.59 mlelstv static usbd_status 592 1.59 mlelstv uplcom_pl2303x_init(struct uplcom_softc *sc) 593 1.59 mlelstv { 594 1.59 mlelstv usb_device_request_t req; 595 1.59 mlelstv usbd_status err; 596 1.59 mlelstv int i; 597 1.59 mlelstv 598 1.59 mlelstv for (i = 0; i < N_PL2302X_INIT; i++) { 599 1.76 skrll char buf[1]; 600 1.76 skrll void *b; 601 1.76 skrll 602 1.59 mlelstv req.bmRequestType = pl2303x[i].req_type; 603 1.59 mlelstv req.bRequest = pl2303x[i].request; 604 1.59 mlelstv USETW(req.wValue, pl2303x[i].value); 605 1.59 mlelstv USETW(req.wIndex, pl2303x[i].index); 606 1.76 skrll if (UT_GET_DIR(req.bmRequestType) == UT_READ) { 607 1.76 skrll b = buf; 608 1.76 skrll USETW(req.wLength, sizeof(buf)); 609 1.76 skrll } else { 610 1.76 skrll b = NULL; 611 1.76 skrll USETW(req.wLength, 0); 612 1.76 skrll } 613 1.59 mlelstv 614 1.76 skrll err = usbd_do_request(sc->sc_udev, &req, b); 615 1.59 mlelstv if (err) { 616 1.65 cube aprint_error_dev(sc->sc_dev, 617 1.65 cube "uplcom_pl2303x_init failed: %s\n", 618 1.65 cube usbd_errstr(err)); 619 1.77 skrll return EIO; 620 1.59 mlelstv } 621 1.59 mlelstv } 622 1.59 mlelstv 623 1.77 skrll return 0; 624 1.59 mlelstv } 625 1.59 mlelstv 626 1.84 mrg static void 627 1.1 ichiro uplcom_set_line_state(struct uplcom_softc *sc) 628 1.1 ichiro { 629 1.1 ichiro usb_device_request_t req; 630 1.1 ichiro int ls; 631 1.1 ichiro 632 1.37 martin /* make sure we have initialized state for sc_dtr and sc_rts */ 633 1.37 martin if (sc->sc_dtr == -1) 634 1.37 martin sc->sc_dtr = 0; 635 1.37 martin if (sc->sc_rts == -1) 636 1.37 martin sc->sc_rts = 0; 637 1.37 martin 638 1.45 martin ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) | 639 1.45 martin (sc->sc_rts ? UCDC_LINE_RTS : 0); 640 1.37 martin 641 1.1 ichiro req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 642 1.1 ichiro req.bRequest = UCDC_SET_CONTROL_LINE_STATE; 643 1.1 ichiro USETW(req.wValue, ls); 644 1.1 ichiro USETW(req.wIndex, sc->sc_iface_number); 645 1.1 ichiro USETW(req.wLength, 0); 646 1.1 ichiro 647 1.1 ichiro (void)usbd_do_request(sc->sc_udev, &req, 0); 648 1.1 ichiro } 649 1.1 ichiro 650 1.84 mrg static void 651 1.50 christos uplcom_set(void *addr, int portno, int reg, int onoff) 652 1.1 ichiro { 653 1.1 ichiro struct uplcom_softc *sc = addr; 654 1.1 ichiro 655 1.84 mrg if (sc->sc_dying) 656 1.84 mrg return; 657 1.84 mrg 658 1.1 ichiro switch (reg) { 659 1.1 ichiro case UCOM_SET_DTR: 660 1.1 ichiro uplcom_dtr(sc, onoff); 661 1.1 ichiro break; 662 1.1 ichiro case UCOM_SET_RTS: 663 1.1 ichiro uplcom_rts(sc, onoff); 664 1.1 ichiro break; 665 1.1 ichiro case UCOM_SET_BREAK: 666 1.1 ichiro uplcom_break(sc, onoff); 667 1.1 ichiro break; 668 1.1 ichiro default: 669 1.1 ichiro break; 670 1.1 ichiro } 671 1.1 ichiro } 672 1.1 ichiro 673 1.84 mrg static void 674 1.1 ichiro uplcom_dtr(struct uplcom_softc *sc, int onoff) 675 1.1 ichiro { 676 1.1 ichiro 677 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 678 1.89 christos DPRINTF("onoff=%jd", onoff, 0, 0, 0); 679 1.1 ichiro 680 1.37 martin if (sc->sc_dtr != -1 && !sc->sc_dtr == !onoff) 681 1.1 ichiro return; 682 1.37 martin 683 1.37 martin sc->sc_dtr = !!onoff; 684 1.1 ichiro 685 1.1 ichiro uplcom_set_line_state(sc); 686 1.1 ichiro } 687 1.1 ichiro 688 1.84 mrg static void 689 1.1 ichiro uplcom_rts(struct uplcom_softc *sc, int onoff) 690 1.1 ichiro { 691 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 692 1.89 christos DPRINTF("onoff=%jd", onoff, 0, 0, 0); 693 1.1 ichiro 694 1.37 martin if (sc->sc_rts != -1 && !sc->sc_rts == !onoff) 695 1.1 ichiro return; 696 1.37 martin 697 1.37 martin sc->sc_rts = !!onoff; 698 1.1 ichiro 699 1.1 ichiro uplcom_set_line_state(sc); 700 1.4 ichiro } 701 1.4 ichiro 702 1.84 mrg static void 703 1.4 ichiro uplcom_break(struct uplcom_softc *sc, int onoff) 704 1.4 ichiro { 705 1.4 ichiro usb_device_request_t req; 706 1.4 ichiro 707 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 708 1.89 christos DPRINTF("onoff=%jd", onoff, 0, 0, 0); 709 1.4 ichiro 710 1.4 ichiro req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 711 1.4 ichiro req.bRequest = UCDC_SEND_BREAK; 712 1.4 ichiro USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF); 713 1.4 ichiro USETW(req.wIndex, sc->sc_iface_number); 714 1.4 ichiro USETW(req.wLength, 0); 715 1.4 ichiro 716 1.4 ichiro (void)usbd_do_request(sc->sc_udev, &req, 0); 717 1.1 ichiro } 718 1.1 ichiro 719 1.84 mrg static usbd_status 720 1.19 ichiro uplcom_set_crtscts(struct uplcom_softc *sc) 721 1.19 ichiro { 722 1.19 ichiro usb_device_request_t req; 723 1.19 ichiro usbd_status err; 724 1.19 ichiro 725 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 726 1.19 ichiro 727 1.19 ichiro req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 728 1.92 nat if (sc->sc_type == UPLCOM_TYPE_HXN) { 729 1.92 nat req.bRequest = UPLCOM_HXN_SET_REQUEST; 730 1.92 nat USETW(req.wValue, UPLCOM_HXN_SET_CRTSCTS_REG); 731 1.92 nat } else { 732 1.92 nat req.bRequest = UPLCOM_SET_REQUEST; 733 1.92 nat USETW(req.wValue, 0); 734 1.92 nat } 735 1.92 nat 736 1.92 nat if (sc->sc_type == UPLCOM_TYPE_HXN) 737 1.92 nat USETW(req.wIndex, UPLCOM_HXN_SET_CRTSCTS); 738 1.92 nat else if (sc->sc_type == UPLCOM_TYPE_HX) 739 1.43 augustss USETW(req.wIndex, UPLCOM_SET_CRTSCTS_HX); 740 1.43 augustss else 741 1.43 augustss USETW(req.wIndex, UPLCOM_SET_CRTSCTS_0); 742 1.19 ichiro USETW(req.wLength, 0); 743 1.19 ichiro 744 1.19 ichiro err = usbd_do_request(sc->sc_udev, &req, 0); 745 1.19 ichiro if (err) { 746 1.89 christos DPRINTF("failed, err=%jd", err, 0, 0, 0); 747 1.77 skrll return err; 748 1.19 ichiro } 749 1.19 ichiro 750 1.77 skrll return USBD_NORMAL_COMPLETION; 751 1.19 ichiro } 752 1.19 ichiro 753 1.84 mrg static usbd_status 754 1.1 ichiro uplcom_set_line_coding(struct uplcom_softc *sc, usb_cdc_line_state_t *state) 755 1.1 ichiro { 756 1.1 ichiro usb_device_request_t req; 757 1.1 ichiro usbd_status err; 758 1.1 ichiro 759 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 760 1.83 mrg 761 1.89 christos DPRINTF("rate=%jd fmt=%jd parity=%jd bits=%jd", 762 1.1 ichiro UGETDW(state->dwDTERate), state->bCharFormat, 763 1.83 mrg state->bParityType, state->bDataBits); 764 1.1 ichiro 765 1.1 ichiro if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) { 766 1.83 mrg DPRINTF("already set", 0, 0, 0, 0); 767 1.77 skrll return USBD_NORMAL_COMPLETION; 768 1.1 ichiro } 769 1.1 ichiro 770 1.1 ichiro req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 771 1.1 ichiro req.bRequest = UCDC_SET_LINE_CODING; 772 1.1 ichiro USETW(req.wValue, 0); 773 1.1 ichiro USETW(req.wIndex, sc->sc_iface_number); 774 1.1 ichiro USETW(req.wLength, UCDC_LINE_STATE_LENGTH); 775 1.1 ichiro 776 1.1 ichiro err = usbd_do_request(sc->sc_udev, &req, state); 777 1.1 ichiro if (err) { 778 1.89 christos DPRINTF("failed, err=%ju", err, 0, 0, 0); 779 1.77 skrll return err; 780 1.1 ichiro } 781 1.1 ichiro 782 1.1 ichiro sc->sc_line_state = *state; 783 1.1 ichiro 784 1.77 skrll return USBD_NORMAL_COMPLETION; 785 1.1 ichiro } 786 1.1 ichiro 787 1.84 mrg static int 788 1.50 christos uplcom_param(void *addr, int portno, struct termios *t) 789 1.1 ichiro { 790 1.1 ichiro struct uplcom_softc *sc = addr; 791 1.1 ichiro usbd_status err; 792 1.1 ichiro usb_cdc_line_state_t ls; 793 1.1 ichiro 794 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 795 1.85 skrll DPRINTF("sc=%#jx", (uintptr_t)sc, 0, 0, 0); 796 1.1 ichiro 797 1.84 mrg if (sc->sc_dying) 798 1.84 mrg return EIO; 799 1.84 mrg 800 1.1 ichiro USETDW(ls.dwDTERate, t->c_ospeed); 801 1.1 ichiro if (ISSET(t->c_cflag, CSTOPB)) 802 1.1 ichiro ls.bCharFormat = UCDC_STOP_BIT_2; 803 1.1 ichiro else 804 1.1 ichiro ls.bCharFormat = UCDC_STOP_BIT_1; 805 1.1 ichiro if (ISSET(t->c_cflag, PARENB)) { 806 1.1 ichiro if (ISSET(t->c_cflag, PARODD)) 807 1.1 ichiro ls.bParityType = UCDC_PARITY_ODD; 808 1.1 ichiro else 809 1.1 ichiro ls.bParityType = UCDC_PARITY_EVEN; 810 1.1 ichiro } else 811 1.1 ichiro ls.bParityType = UCDC_PARITY_NONE; 812 1.1 ichiro switch (ISSET(t->c_cflag, CSIZE)) { 813 1.1 ichiro case CS5: 814 1.1 ichiro ls.bDataBits = 5; 815 1.1 ichiro break; 816 1.1 ichiro case CS6: 817 1.1 ichiro ls.bDataBits = 6; 818 1.1 ichiro break; 819 1.1 ichiro case CS7: 820 1.1 ichiro ls.bDataBits = 7; 821 1.1 ichiro break; 822 1.1 ichiro case CS8: 823 1.1 ichiro ls.bDataBits = 8; 824 1.1 ichiro break; 825 1.1 ichiro } 826 1.1 ichiro 827 1.1 ichiro err = uplcom_set_line_coding(sc, &ls); 828 1.1 ichiro if (err) { 829 1.89 christos DPRINTF("err=%jd", err, 0, 0, 0); 830 1.77 skrll return EIO; 831 1.1 ichiro } 832 1.19 ichiro 833 1.19 ichiro if (ISSET(t->c_cflag, CRTSCTS)) 834 1.19 ichiro uplcom_set_crtscts(sc); 835 1.19 ichiro 836 1.37 martin if (sc->sc_rts == -1 || sc->sc_dtr == -1) 837 1.37 martin uplcom_set_line_state(sc); 838 1.37 martin 839 1.19 ichiro if (err) { 840 1.89 christos DPRINTF("err=%jd", err, 0, 0, 0); 841 1.77 skrll return EIO; 842 1.19 ichiro } 843 1.19 ichiro 844 1.77 skrll return 0; 845 1.11 ichiro } 846 1.11 ichiro 847 1.84 mrg static usbd_status 848 1.79 msaitoh uplcom_vendor_control_write(struct usbd_device *dev, uint16_t value, 849 1.79 msaitoh uint16_t index) 850 1.43 augustss { 851 1.43 augustss usb_device_request_t req; 852 1.43 augustss usbd_status err; 853 1.43 augustss 854 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 855 1.83 mrg 856 1.43 augustss req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 857 1.43 augustss req.bRequest = UPLCOM_SET_REQUEST; 858 1.43 augustss USETW(req.wValue, value); 859 1.43 augustss USETW(req.wIndex, index); 860 1.43 augustss USETW(req.wLength, 0); 861 1.43 augustss 862 1.43 augustss err = usbd_do_request(dev, &req, NULL); 863 1.43 augustss 864 1.43 augustss if (err) { 865 1.89 christos DPRINTF("vendor write failed, err=%jd", err, 0, 0, 0); 866 1.43 augustss } 867 1.43 augustss 868 1.43 augustss return err; 869 1.43 augustss } 870 1.43 augustss 871 1.84 mrg static int 872 1.50 christos uplcom_open(void *addr, int portno) 873 1.11 ichiro { 874 1.11 ichiro struct uplcom_softc *sc = addr; 875 1.84 mrg usbd_status err = 0; 876 1.83 mrg 877 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 878 1.85 skrll DPRINTF("sc=%#jx", (uintptr_t)sc, 0, 0, 0); 879 1.28 augustss 880 1.11 ichiro if (sc->sc_dying) 881 1.77 skrll return EIO; 882 1.11 ichiro 883 1.43 augustss /* Some unknown device frobbing. */ 884 1.43 augustss if (sc->sc_type == UPLCOM_TYPE_HX) 885 1.43 augustss uplcom_vendor_control_write(sc->sc_udev, 2, 0x44); 886 1.43 augustss else 887 1.43 augustss uplcom_vendor_control_write(sc->sc_udev, 2, 0x24); 888 1.77 skrll 889 1.12 ichiro if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { 890 1.77 skrll sc->sc_intr_buf = kmem_alloc(sc->sc_isize, KM_SLEEP); 891 1.20 ichiro err = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number, 892 1.12 ichiro USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, 893 1.12 ichiro sc->sc_intr_buf, sc->sc_isize, 894 1.12 ichiro uplcom_intr, USBD_DEFAULT_INTERVAL); 895 1.12 ichiro if (err) { 896 1.89 christos DPRINTF("cannot open interrupt pipe (addr %jd)", 897 1.83 mrg sc->sc_intr_number, 0, 0, 0); 898 1.12 ichiro } 899 1.12 ichiro } 900 1.11 ichiro 901 1.84 mrg if (err == 0 && sc->sc_type == UPLCOM_TYPE_HX) 902 1.84 mrg err = uplcom_pl2303x_init(sc); 903 1.59 mlelstv 904 1.84 mrg return err; 905 1.11 ichiro } 906 1.11 ichiro 907 1.84 mrg static void 908 1.50 christos uplcom_close(void *addr, int portno) 909 1.11 ichiro { 910 1.11 ichiro struct uplcom_softc *sc = addr; 911 1.12 ichiro 912 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 913 1.85 skrll DPRINTF("sc=%#jx", (uintptr_t)sc, 0, 0, 0); 914 1.83 mrg 915 1.12 ichiro if (sc->sc_dying) 916 1.12 ichiro return; 917 1.12 ichiro 918 1.84 mrg uplcom_close_pipe(sc); 919 1.12 ichiro } 920 1.12 ichiro 921 1.84 mrg static void 922 1.79 msaitoh uplcom_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) 923 1.12 ichiro { 924 1.12 ichiro struct uplcom_softc *sc = priv; 925 1.12 ichiro u_char *buf = sc->sc_intr_buf; 926 1.12 ichiro u_char pstatus; 927 1.11 ichiro 928 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 929 1.83 mrg 930 1.11 ichiro if (sc->sc_dying) 931 1.11 ichiro return; 932 1.11 ichiro 933 1.12 ichiro if (status != USBD_NORMAL_COMPLETION) { 934 1.12 ichiro if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 935 1.12 ichiro return; 936 1.12 ichiro 937 1.89 christos DPRINTF("abnormal status: %ju", status, 0, 0, 0); 938 1.12 ichiro usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); 939 1.12 ichiro return; 940 1.12 ichiro } 941 1.12 ichiro 942 1.89 christos DPRINTF("uplcom status = %02jx", buf[8], 0, 0, 0); 943 1.12 ichiro 944 1.15 augustss sc->sc_lsr = sc->sc_msr = 0; 945 1.15 augustss pstatus = buf[8]; 946 1.70 jakllsch if (ISSET(pstatus, UPLCOM_N_SERIAL_CTS)) 947 1.70 jakllsch sc->sc_msr |= UMSR_CTS; 948 1.70 jakllsch if (ISSET(pstatus, UCDC_N_SERIAL_RI)) 949 1.70 jakllsch sc->sc_msr |= UMSR_RI; 950 1.70 jakllsch if (ISSET(pstatus, UCDC_N_SERIAL_DSR)) 951 1.15 augustss sc->sc_msr |= UMSR_DSR; 952 1.70 jakllsch if (ISSET(pstatus, UCDC_N_SERIAL_DCD)) 953 1.15 augustss sc->sc_msr |= UMSR_DCD; 954 1.65 cube ucom_status_change(device_private(sc->sc_subdev)); 955 1.12 ichiro } 956 1.12 ichiro 957 1.84 mrg static void 958 1.50 christos uplcom_get_status(void *addr, int portno, u_char *lsr, u_char *msr) 959 1.12 ichiro { 960 1.12 ichiro struct uplcom_softc *sc = addr; 961 1.12 ichiro 962 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 963 1.12 ichiro 964 1.84 mrg if (sc->sc_dying) 965 1.84 mrg return; 966 1.84 mrg 967 1.81 mrg *lsr = sc->sc_lsr; 968 1.81 mrg *msr = sc->sc_msr; 969 1.12 ichiro } 970 1.12 ichiro 971 1.12 ichiro #if TODO 972 1.84 mrg static int 973 1.53 christos uplcom_ioctl(void *addr, int portno, u_long cmd, void *data, int flag, 974 1.71 dyoung proc_t *p) 975 1.12 ichiro { 976 1.12 ichiro struct uplcom_softc *sc = addr; 977 1.12 ichiro int error = 0; 978 1.12 ichiro 979 1.83 mrg UPLCOMHIST_FUNC(); UPLCOMHIST_CALLED(); 980 1.83 mrg 981 1.12 ichiro if (sc->sc_dying) 982 1.77 skrll return EIO; 983 1.12 ichiro 984 1.88 christos DPRINTF("cmd=0x%08lx", cmd, 0, 0, 0); 985 1.12 ichiro 986 1.12 ichiro switch (cmd) { 987 1.12 ichiro case TIOCNOTTY: 988 1.12 ichiro case TIOCMGET: 989 1.12 ichiro case TIOCMSET: 990 1.12 ichiro case USB_GET_CM_OVER_DATA: 991 1.12 ichiro case USB_SET_CM_OVER_DATA: 992 1.12 ichiro break; 993 1.12 ichiro 994 1.12 ichiro default: 995 1.83 mrg DPRINTF("unknown", 0, 0, 0, 0); 996 1.12 ichiro error = ENOTTY; 997 1.12 ichiro break; 998 1.11 ichiro } 999 1.11 ichiro 1000 1.77 skrll return error; 1001 1.1 ichiro } 1002 1.12 ichiro #endif 1003