1 /* $NetBSD: uark.c,v 1.3 2010/11/04 01:58:07 dyoung 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 struct device *sc_dev; 64 usbd_device_handle sc_udev; 65 usbd_interface_handle sc_iface; 66 struct device *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 uark_get_status, 82 uark_set, 83 uark_param, 84 NULL, 85 NULL, 86 NULL, 87 NULL, 88 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, uark_detach, uark_activate); 101 102 int 103 uark_match(device_t parent, cfdata_t match, void *aux) 104 { 105 struct usb_attach_arg *uaa = aux; 106 107 return (usb_lookup(uark_devs, uaa->vendor, uaa->product) != NULL) ? 108 UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 109 } 110 111 void 112 uark_attach(device_t parent, device_t self, void *aux) 113 { 114 struct uark_softc *sc = device_private(self); 115 struct usb_attach_arg *uaa = aux; 116 usbd_device_handle dev = uaa->device; 117 char *devinfop; 118 struct ucom_attach_args uca; 119 usb_interface_descriptor_t *id; 120 usb_endpoint_descriptor_t *ed; 121 usbd_status error; 122 int i; 123 124 memset(&uca, 0, sizeof(uca)); 125 sc->sc_dev = self; 126 127 devinfop = usbd_devinfo_alloc(dev, 0); 128 aprint_naive("\n"); 129 aprint_normal("\n"); 130 aprint_normal_dev(self, "%s\n", devinfop); 131 usbd_devinfo_free(devinfop); 132 133 sc->sc_udev = dev; 134 135 if (usbd_set_config_index(sc->sc_udev, UARK_CONFIG_NO, 1) != 0) { 136 aprint_error_dev(self, "could not set configuration no\n"); 137 sc->sc_dying = 1; 138 return; 139 } 140 141 /* get the first interface handle */ 142 error = usbd_device2interface_handle(sc->sc_udev, UARK_IFACE_NO, 143 &sc->sc_iface); 144 if (error != 0) { 145 aprint_error_dev(self, "could not get interface handle\n"); 146 sc->sc_dying = 1; 147 return; 148 } 149 150 id = usbd_get_interface_descriptor(sc->sc_iface); 151 152 uca.bulkin = uca.bulkout = -1; 153 for (i = 0; i < id->bNumEndpoints; i++) { 154 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); 155 if (ed == NULL) { 156 aprint_error_dev(self, "no endpoint descriptor found for %d\n", 157 i); 158 sc->sc_dying = 1; 159 return; 160 } 161 162 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 163 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) 164 uca.bulkin = ed->bEndpointAddress; 165 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 166 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) 167 uca.bulkout = ed->bEndpointAddress; 168 } 169 170 if (uca.bulkin == -1 || uca.bulkout == -1) { 171 aprint_error_dev(self, "missing endpoint\n"); 172 sc->sc_dying = 1; 173 return; 174 } 175 176 uca.ibufsize = UARKBUFSZ; 177 uca.obufsize = UARKBUFSZ; 178 uca.ibufsizepad = UARKBUFSZ; 179 uca.opkthdrlen = 0; 180 uca.device = sc->sc_udev; 181 uca.iface = sc->sc_iface; 182 uca.methods = &uark_methods; 183 uca.arg = sc; 184 uca.info = NULL; 185 186 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 187 sc->sc_dev); 188 189 sc->sc_subdev = config_found_sm_loc(self, "ucombus", NULL, &uca, 190 ucomprint, ucomsubmatch); 191 192 return; 193 } 194 195 int 196 uark_detach(struct device *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, 208 sc->sc_dev); 209 210 return rv; 211 } 212 213 int 214 uark_activate(struct device* self, enum devact act) 215 { 216 struct uark_softc *sc = device_private(self); 217 int rv = 0; 218 219 switch (act) { 220 case DVACT_DEACTIVATE: 221 if (sc->sc_subdev != NULL) 222 rv = config_deactivate(sc->sc_subdev); 223 sc->sc_dying = 1; 224 break; 225 } 226 return (rv); 227 } 228 229 void 230 uark_set(void *vsc, int portno, int reg, int onoff) 231 { 232 struct uark_softc *sc = vsc; 233 234 switch (reg) { 235 case UCOM_SET_BREAK: 236 uark_break(sc, portno, onoff); 237 return; 238 case UCOM_SET_DTR: 239 case UCOM_SET_RTS: 240 default: 241 return; 242 } 243 } 244 245 int 246 uark_param(void *vsc, int portno, struct termios *t) 247 { 248 struct uark_softc *sc = (struct uark_softc *)vsc; 249 int data; 250 251 switch (t->c_ospeed) { 252 case 300: 253 case 600: 254 case 1200: 255 case 1800: 256 case 2400: 257 case 4800: 258 case 9600: 259 case 19200: 260 case 38400: 261 case 57600: 262 case 115200: 263 uark_cmd(sc, 3, 0x83); 264 uark_cmd(sc, 0, (UARK_BAUD_REF / t->c_ospeed) & 0xFF); 265 uark_cmd(sc, 1, (UARK_BAUD_REF / t->c_ospeed) >> 8); 266 uark_cmd(sc, 3, 0x03); 267 break; 268 default: 269 return (EINVAL); 270 } 271 272 if (ISSET(t->c_cflag, CSTOPB)) 273 data = UARK_STOP_BITS_2; 274 else 275 data = UARK_STOP_BITS_1; 276 277 if (ISSET(t->c_cflag, PARENB)) { 278 if (ISSET(t->c_cflag, PARODD)) 279 data |= UARK_PARITY_ODD; 280 else 281 data |= UARK_PARITY_EVEN; 282 } else 283 data |= UARK_PARITY_NONE; 284 285 switch (ISSET(t->c_cflag, CSIZE)) { 286 case CS5: 287 data |= UARK_SET_DATA_BITS(5); 288 break; 289 case CS6: 290 data |= UARK_SET_DATA_BITS(6); 291 break; 292 case CS7: 293 data |= UARK_SET_DATA_BITS(7); 294 break; 295 case CS8: 296 data |= UARK_SET_DATA_BITS(8); 297 break; 298 } 299 300 uark_cmd(sc, 3, 0x00); 301 uark_cmd(sc, 3, data); 302 303 #if 0 304 /* XXX flow control */ 305 if (ISSET(t->c_cflag, CRTSCTS)) 306 /* rts/cts flow ctl */ 307 } else if (ISSET(t->c_iflag, IXON|IXOFF)) { 308 /* xon/xoff flow ctl */ 309 } else { 310 /* disable flow ctl */ 311 } 312 #endif 313 314 return (0); 315 } 316 317 void 318 uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) 319 { 320 struct uark_softc *sc = vsc; 321 322 if (msr != NULL) 323 *msr = sc->sc_msr; 324 if (lsr != NULL) 325 *lsr = sc->sc_lsr; 326 } 327 328 void 329 uark_break(void *vsc, int portno, int onoff) 330 { 331 #if 0 332 struct uark_softc *sc = vsc; 333 334 #ifdef UARK_DEBUG 335 aprint_normal_dev(sc->sc_dev, "break %s!\n", onoff ? "on" : "off"); 336 #endif 337 338 if (onoff) 339 /* break on */ 340 uark_cmd(sc, 4, 0x01); 341 else 342 uark_cmd(sc, 4, 0x00); 343 #endif 344 } 345 346 int 347 uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value) 348 { 349 usb_device_request_t req; 350 usbd_status err; 351 352 req.bmRequestType = UARK_WRITE; 353 req.bRequest = UARK_REQUEST; 354 USETW(req.wValue, value); 355 USETW(req.wIndex, index); 356 USETW(req.wLength, 0); 357 err = usbd_do_request(sc->sc_udev, &req, NULL); 358 359 if (err) 360 return (EIO); 361 362 return (0); 363 } 364