1 /* $NetBSD: uark.c,v 1.9 2016/07/11 11:31:51 msaitoh Exp $ */ 2 /* $OpenBSD: uark.c,v 1.13 2009/10/13 19:33:17 pirofti Exp $ */ 3 4 /* 5 * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/param.h> 21 #include <sys/systm.h> 22 #include <sys/kernel.h> 23 #include <sys/conf.h> 24 #include <sys/tty.h> 25 #include <sys/device.h> 26 27 #include <dev/usb/usb.h> 28 #include <dev/usb/usbdi.h> 29 #include <dev/usb/usbdi_util.h> 30 #include <dev/usb/usbdevs.h> 31 32 #include <dev/usb/ucomvar.h> 33 34 #ifdef UARK_DEBUG 35 #define DPRINTFN(n, x) do { if (uarkdebug > (n)) printf x; } while (0) 36 int uarkebug = 0; 37 #else 38 #define DPRINTFN(n, x) 39 #endif 40 #define DPRINTF(x) DPRINTFN(0, x) 41 42 #define UARKBUFSZ 256 43 #define UARK_CONFIG_NO 0 44 #define UARK_IFACE_NO 0 45 46 #define UARK_SET_DATA_BITS(x) (x - 5) 47 48 #define UARK_PARITY_NONE 0x00 49 #define UARK_PARITY_ODD 0x08 50 #define UARK_PARITY_EVEN 0x18 51 52 #define UARK_STOP_BITS_1 0x00 53 #define UARK_STOP_BITS_2 0x04 54 55 #define UARK_BAUD_REF 3000000 56 57 #define UARK_WRITE 0x40 58 #define UARK_READ 0xc0 59 60 #define UARK_REQUEST 0xfe 61 62 struct uark_softc { 63 device_t sc_dev; 64 struct usbd_device * sc_udev; 65 struct usbd_interface * sc_iface; 66 device_t sc_subdev; 67 68 u_char sc_msr; 69 u_char sc_lsr; 70 71 u_char sc_dying; 72 }; 73 74 void uark_get_status(void *, int portno, u_char *lsr, u_char *msr); 75 void uark_set(void *, int, int, int); 76 int uark_param(void *, int, struct termios *); 77 void uark_break(void *, int, int); 78 int uark_cmd(struct uark_softc *, uint16_t, uint16_t); 79 80 struct ucom_methods uark_methods = { 81 .ucom_get_status = uark_get_status, 82 .ucom_set = uark_set, 83 .ucom_param = uark_param, 84 .ucom_ioctl = NULL, 85 .ucom_open = NULL, 86 .ucom_close = NULL, 87 .ucom_read = NULL, 88 .ucom_write = NULL, 89 }; 90 91 static const struct usb_devno uark_devs[] = { 92 { USB_VENDOR_ARKMICROCHIPS, USB_PRODUCT_ARKMICROCHIPS_USBSERIAL }, 93 }; 94 95 int uark_match(device_t, cfdata_t, void *); 96 void uark_attach(device_t, device_t, void *); 97 int uark_detach(device_t, int); 98 int uark_activate(device_t, enum devact); 99 extern struct cfdriver uark_cd; 100 CFATTACH_DECL_NEW(uark, sizeof(struct uark_softc), uark_match, uark_attach, 101 uark_detach, uark_activate); 102 103 int 104 uark_match(device_t parent, cfdata_t match, void *aux) 105 { 106 struct usb_attach_arg *uaa = aux; 107 108 return (usb_lookup(uark_devs, uaa->uaa_vendor, uaa->uaa_product) 109 != NULL) ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 110 } 111 112 void 113 uark_attach(device_t parent, device_t self, void *aux) 114 { 115 struct uark_softc *sc = device_private(self); 116 struct usb_attach_arg *uaa = aux; 117 struct usbd_device *dev = uaa->uaa_device; 118 char *devinfop; 119 struct ucom_attach_args ucaa; 120 usb_interface_descriptor_t *id; 121 usb_endpoint_descriptor_t *ed; 122 usbd_status error; 123 int i; 124 125 memset(&ucaa, 0, sizeof(ucaa)); 126 sc->sc_dev = self; 127 128 devinfop = usbd_devinfo_alloc(dev, 0); 129 aprint_naive("\n"); 130 aprint_normal("\n"); 131 aprint_normal_dev(self, "%s\n", devinfop); 132 usbd_devinfo_free(devinfop); 133 134 sc->sc_udev = dev; 135 136 if (usbd_set_config_index(sc->sc_udev, UARK_CONFIG_NO, 1) != 0) { 137 aprint_error_dev(self, "could not set configuration no\n"); 138 sc->sc_dying = 1; 139 return; 140 } 141 142 /* get the first interface handle */ 143 error = usbd_device2interface_handle(sc->sc_udev, UARK_IFACE_NO, 144 &sc->sc_iface); 145 if (error != 0) { 146 aprint_error_dev(self, "could not get interface handle\n"); 147 sc->sc_dying = 1; 148 return; 149 } 150 151 id = usbd_get_interface_descriptor(sc->sc_iface); 152 153 ucaa.ucaa_bulkin = ucaa.ucaa_bulkout = -1; 154 for (i = 0; i < id->bNumEndpoints; i++) { 155 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); 156 if (ed == NULL) { 157 aprint_error_dev(self, 158 "no endpoint descriptor found for %d\n", i); 159 sc->sc_dying = 1; 160 return; 161 } 162 163 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 164 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) 165 ucaa.ucaa_bulkin = ed->bEndpointAddress; 166 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 167 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) 168 ucaa.ucaa_bulkout = ed->bEndpointAddress; 169 } 170 171 if (ucaa.ucaa_bulkin == -1 || ucaa.ucaa_bulkout == -1) { 172 aprint_error_dev(self, "missing endpoint\n"); 173 sc->sc_dying = 1; 174 return; 175 } 176 177 ucaa.ucaa_ibufsize = UARKBUFSZ; 178 ucaa.ucaa_obufsize = UARKBUFSZ; 179 ucaa.ucaa_ibufsizepad = UARKBUFSZ; 180 ucaa.ucaa_opkthdrlen = 0; 181 ucaa.ucaa_device = sc->sc_udev; 182 ucaa.ucaa_iface = sc->sc_iface; 183 ucaa.ucaa_methods = &uark_methods; 184 ucaa.ucaa_arg = sc; 185 ucaa.ucaa_info = NULL; 186 187 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 188 189 sc->sc_subdev = config_found_sm_loc(self, "ucombus", NULL, &ucaa, 190 ucomprint, ucomsubmatch); 191 192 return; 193 } 194 195 int 196 uark_detach(device_t self, int flags) 197 { 198 struct uark_softc *sc = device_private(self); 199 int rv = 0; 200 201 sc->sc_dying = 1; 202 if (sc->sc_subdev != NULL) { 203 rv = config_detach(sc->sc_subdev, flags); 204 sc->sc_subdev = NULL; 205 } 206 207 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 208 209 return rv; 210 } 211 212 int 213 uark_activate(device_t self, enum devact act) 214 { 215 struct uark_softc *sc = device_private(self); 216 int rv = 0; 217 218 switch (act) { 219 case DVACT_DEACTIVATE: 220 if (sc->sc_subdev != NULL) 221 rv = config_deactivate(sc->sc_subdev); 222 sc->sc_dying = 1; 223 break; 224 } 225 return (rv); 226 } 227 228 void 229 uark_set(void *vsc, int portno, int reg, int onoff) 230 { 231 struct uark_softc *sc = vsc; 232 233 switch (reg) { 234 case UCOM_SET_BREAK: 235 uark_break(sc, portno, onoff); 236 return; 237 case UCOM_SET_DTR: 238 case UCOM_SET_RTS: 239 default: 240 return; 241 } 242 } 243 244 int 245 uark_param(void *vsc, int portno, struct termios *t) 246 { 247 struct uark_softc *sc = (struct uark_softc *)vsc; 248 int data; 249 250 switch (t->c_ospeed) { 251 case 300: 252 case 600: 253 case 1200: 254 case 1800: 255 case 2400: 256 case 4800: 257 case 9600: 258 case 19200: 259 case 38400: 260 case 57600: 261 case 115200: 262 uark_cmd(sc, 3, 0x83); 263 uark_cmd(sc, 0, (UARK_BAUD_REF / t->c_ospeed) & 0xFF); 264 uark_cmd(sc, 1, (UARK_BAUD_REF / t->c_ospeed) >> 8); 265 uark_cmd(sc, 3, 0x03); 266 break; 267 default: 268 return (EINVAL); 269 } 270 271 if (ISSET(t->c_cflag, CSTOPB)) 272 data = UARK_STOP_BITS_2; 273 else 274 data = UARK_STOP_BITS_1; 275 276 if (ISSET(t->c_cflag, PARENB)) { 277 if (ISSET(t->c_cflag, PARODD)) 278 data |= UARK_PARITY_ODD; 279 else 280 data |= UARK_PARITY_EVEN; 281 } else 282 data |= UARK_PARITY_NONE; 283 284 switch (ISSET(t->c_cflag, CSIZE)) { 285 case CS5: 286 data |= UARK_SET_DATA_BITS(5); 287 break; 288 case CS6: 289 data |= UARK_SET_DATA_BITS(6); 290 break; 291 case CS7: 292 data |= UARK_SET_DATA_BITS(7); 293 break; 294 case CS8: 295 data |= UARK_SET_DATA_BITS(8); 296 break; 297 } 298 299 uark_cmd(sc, 3, 0x00); 300 uark_cmd(sc, 3, data); 301 302 #if 0 303 /* XXX flow control */ 304 if (ISSET(t->c_cflag, CRTSCTS)) 305 /* rts/cts flow ctl */ 306 } else if (ISSET(t->c_iflag, IXON|IXOFF)) { 307 /* xon/xoff flow ctl */ 308 } else { 309 /* disable flow ctl */ 310 } 311 #endif 312 313 return (0); 314 } 315 316 void 317 uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) 318 { 319 struct uark_softc *sc = vsc; 320 321 if (msr != NULL) 322 *msr = sc->sc_msr; 323 if (lsr != NULL) 324 *lsr = sc->sc_lsr; 325 } 326 327 void 328 uark_break(void *vsc, int portno, int onoff) 329 { 330 #if 0 331 struct uark_softc *sc = vsc; 332 333 #ifdef UARK_DEBUG 334 aprint_normal_dev(sc->sc_dev, "break %s!\n", onoff ? "on" : "off"); 335 #endif 336 337 if (onoff) 338 /* break on */ 339 uark_cmd(sc, 4, 0x01); 340 else 341 uark_cmd(sc, 4, 0x00); 342 #endif 343 } 344 345 int 346 uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value) 347 { 348 usb_device_request_t req; 349 usbd_status err; 350 351 req.bmRequestType = UARK_WRITE; 352 req.bRequest = UARK_REQUEST; 353 USETW(req.wValue, value); 354 USETW(req.wIndex, index); 355 USETW(req.wLength, 0); 356 err = usbd_do_request(sc->sc_udev, &req, NULL); 357 358 if (err) 359 return (EIO); 360 361 return (0); 362 } 363