1 /* $OpenBSD: uark.c,v 1.1 2006/08/14 08:30:22 jsg Exp $ */
4 * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * NOTE: all function names beginning like "uark_cfg_" can only
23 * be called from within the config thread function !
27 #include <dev/usb/usb.h>
28 #include <dev/usb/usb_mfunc.h>
29 #include <dev/usb/usb_error.h>
30 #include <dev/usb/usb_cdc.h>
32 #define USB_DEBUG_VAR usb2_debug
34 #include <dev/usb/usb_core.h>
35 #include <dev/usb/usb_debug.h>
36 #include <dev/usb/usb_process.h>
37 #include <dev/usb/usb_request.h>
38 #include <dev/usb/usb_lookup.h>
39 #include <dev/usb/usb_util.h>
41 #include <dev/usb/serial/usb_serial.h>
43 #define UARK_BUF_SIZE 1024 /* bytes */
45 #define UARK_SET_DATA_BITS(x) ((x) - 5)
47 #define UARK_PARITY_NONE 0x00
48 #define UARK_PARITY_ODD 0x08
49 #define UARK_PARITY_EVEN 0x18
51 #define UARK_STOP_BITS_1 0x00
52 #define UARK_STOP_BITS_2 0x04
54 #define UARK_BAUD_REF 3000000
56 #define UARK_WRITE 0x40
57 #define UARK_READ 0xc0
59 #define UARK_REQUEST 0xfe
61 #define UARK_CONFIG_INDEX 0
62 #define UARK_IFACE_INDEX 0
71 struct usb2_com_super_softc sc_super_ucom;
72 struct usb2_com_softc sc_ucom;
74 struct usb2_xfer *sc_xfer[UARK_N_TRANSFER];
75 struct usb2_device *sc_udev;
84 static device_probe_t uark_probe;
85 static device_attach_t uark_attach;
86 static device_detach_t uark_detach;
88 static usb2_callback_t uark_bulk_write_callback;
89 static usb2_callback_t uark_bulk_read_callback;
91 static void uark_start_read(struct usb2_com_softc *);
92 static void uark_stop_read(struct usb2_com_softc *);
93 static void uark_start_write(struct usb2_com_softc *);
94 static void uark_stop_write(struct usb2_com_softc *);
95 static int uark_pre_param(struct usb2_com_softc *, struct termios *);
96 static void uark_cfg_param(struct usb2_com_softc *, struct termios *);
97 static void uark_cfg_get_status(struct usb2_com_softc *, uint8_t *,
99 static void uark_cfg_set_break(struct usb2_com_softc *, uint8_t);
100 static void uark_cfg_write(struct uark_softc *, uint16_t, uint16_t);
102 static const struct usb2_config
103 uark_xfer_config[UARK_N_TRANSFER] = {
105 [UARK_BULK_DT_WR] = {
107 .endpoint = UE_ADDR_ANY,
108 .direction = UE_DIR_OUT,
109 .mh.bufsize = UARK_BUF_SIZE,
110 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
111 .mh.callback = &uark_bulk_write_callback,
114 [UARK_BULK_DT_RD] = {
116 .endpoint = UE_ADDR_ANY,
117 .direction = UE_DIR_IN,
118 .mh.bufsize = UARK_BUF_SIZE,
119 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
120 .mh.callback = &uark_bulk_read_callback,
124 static const struct usb2_com_callback uark_callback = {
125 .usb2_com_cfg_get_status = &uark_cfg_get_status,
126 .usb2_com_cfg_set_break = &uark_cfg_set_break,
127 .usb2_com_cfg_param = &uark_cfg_param,
128 .usb2_com_pre_param = &uark_pre_param,
129 .usb2_com_start_read = &uark_start_read,
130 .usb2_com_stop_read = &uark_stop_read,
131 .usb2_com_start_write = &uark_start_write,
132 .usb2_com_stop_write = &uark_stop_write,
135 static device_method_t uark_methods[] = {
137 DEVMETHOD(device_probe, uark_probe),
138 DEVMETHOD(device_attach, uark_attach),
139 DEVMETHOD(device_detach, uark_detach),
143 static devclass_t uark_devclass;
145 static driver_t uark_driver = {
147 .methods = uark_methods,
148 .size = sizeof(struct uark_softc),
151 DRIVER_MODULE(uark, uhub, uark_driver, uark_devclass, NULL, 0);
152 MODULE_DEPEND(uark, ucom, 1, 1, 1);
153 MODULE_DEPEND(uark, usb, 1, 1, 1);
155 static const struct usb2_device_id uark_devs[] = {
156 {USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)},
160 uark_probe(device_t dev)
162 struct usb2_attach_arg *uaa = device_get_ivars(dev);
164 if (uaa->usb2_mode != USB_MODE_HOST) {
167 if (uaa->info.bConfigIndex != 0) {
170 if (uaa->info.bIfaceIndex != UARK_IFACE_INDEX) {
173 return (usb2_lookup_id_by_uaa(uark_devs, sizeof(uark_devs), uaa));
177 uark_attach(device_t dev)
179 struct usb2_attach_arg *uaa = device_get_ivars(dev);
180 struct uark_softc *sc = device_get_softc(dev);
184 device_set_usb2_desc(dev);
185 mtx_init(&sc->sc_mtx, "uark", NULL, MTX_DEF);
187 sc->sc_udev = uaa->device;
189 iface_index = UARK_IFACE_INDEX;
190 error = usb2_transfer_setup
191 (uaa->device, &iface_index, sc->sc_xfer,
192 uark_xfer_config, UARK_N_TRANSFER, sc, &sc->sc_mtx);
195 device_printf(dev, "allocating control USB "
196 "transfers failed!\n");
199 /* clear stall at first run */
200 mtx_lock(&sc->sc_mtx);
201 usb2_transfer_set_stall(sc->sc_xfer[UARK_BULK_DT_WR]);
202 usb2_transfer_set_stall(sc->sc_xfer[UARK_BULK_DT_RD]);
203 mtx_unlock(&sc->sc_mtx);
205 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
206 &uark_callback, &sc->sc_mtx);
208 DPRINTF("usb2_com_attach failed\n");
211 return (0); /* success */
215 return (ENXIO); /* failure */
219 uark_detach(device_t dev)
221 struct uark_softc *sc = device_get_softc(dev);
223 usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
224 usb2_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER);
225 mtx_destroy(&sc->sc_mtx);
231 uark_bulk_write_callback(struct usb2_xfer *xfer)
233 struct uark_softc *sc = xfer->priv_sc;
236 switch (USB_GET_STATE(xfer)) {
238 case USB_ST_TRANSFERRED:
240 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0,
241 UARK_BUF_SIZE, &actlen)) {
242 xfer->frlengths[0] = actlen;
243 usb2_start_hardware(xfer);
248 if (xfer->error != USB_ERR_CANCELLED) {
249 /* try to clear stall first */
250 xfer->flags.stall_pipe = 1;
259 uark_bulk_read_callback(struct usb2_xfer *xfer)
261 struct uark_softc *sc = xfer->priv_sc;
263 switch (USB_GET_STATE(xfer)) {
264 case USB_ST_TRANSFERRED:
265 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0,
270 xfer->frlengths[0] = xfer->max_data_length;
271 usb2_start_hardware(xfer);
275 if (xfer->error != USB_ERR_CANCELLED) {
276 /* try to clear stall first */
277 xfer->flags.stall_pipe = 1;
285 uark_start_read(struct usb2_com_softc *ucom)
287 struct uark_softc *sc = ucom->sc_parent;
289 usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_RD]);
293 uark_stop_read(struct usb2_com_softc *ucom)
295 struct uark_softc *sc = ucom->sc_parent;
297 usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_RD]);
301 uark_start_write(struct usb2_com_softc *ucom)
303 struct uark_softc *sc = ucom->sc_parent;
305 usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_WR]);
309 uark_stop_write(struct usb2_com_softc *ucom)
311 struct uark_softc *sc = ucom->sc_parent;
313 usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_WR]);
317 uark_pre_param(struct usb2_com_softc *ucom, struct termios *t)
319 if ((t->c_ospeed < 300) || (t->c_ospeed > 115200))
325 uark_cfg_param(struct usb2_com_softc *ucom, struct termios *t)
327 struct uark_softc *sc = ucom->sc_parent;
328 uint32_t speed = t->c_ospeed;
332 * NOTE: When reverse computing the baud rate from the "data" all
333 * allowed baud rates are within 3% of the initial baud rate.
335 data = (UARK_BAUD_REF + (speed / 2)) / speed;
337 uark_cfg_write(sc, 3, 0x83);
338 uark_cfg_write(sc, 0, data & 0xFF);
339 uark_cfg_write(sc, 1, data >> 8);
340 uark_cfg_write(sc, 3, 0x03);
342 if (t->c_cflag & CSTOPB)
343 data = UARK_STOP_BITS_2;
345 data = UARK_STOP_BITS_1;
347 if (t->c_cflag & PARENB) {
348 if (t->c_cflag & PARODD)
349 data |= UARK_PARITY_ODD;
351 data |= UARK_PARITY_EVEN;
353 data |= UARK_PARITY_NONE;
355 switch (t->c_cflag & CSIZE) {
357 data |= UARK_SET_DATA_BITS(5);
360 data |= UARK_SET_DATA_BITS(6);
363 data |= UARK_SET_DATA_BITS(7);
367 data |= UARK_SET_DATA_BITS(8);
370 uark_cfg_write(sc, 3, 0x00);
371 uark_cfg_write(sc, 3, data);
375 uark_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr)
377 struct uark_softc *sc = ucom->sc_parent;
384 uark_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff)
386 struct uark_softc *sc = ucom->sc_parent;
388 DPRINTF("onoff=%d\n", onoff);
390 uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00);
394 uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value)
396 struct usb2_device_request req;
399 req.bmRequestType = UARK_WRITE;
400 req.bRequest = UARK_REQUEST;
401 USETW(req.wValue, value);
402 USETW(req.wIndex, index);
403 USETW(req.wLength, 0);
405 err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
406 &req, NULL, 0, 1000);
408 DPRINTFN(0, "device request failed, err=%s "
409 "(ignored)\n", usb2_errstr(err));