1/* $OpenBSD: uark.c,v 1.1 2006/08/14 08:30:22 jsg Exp $ */
2
3/*
4 * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
5 *
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.
9 *
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.
17 *
18 * $FreeBSD: head/sys/dev/usb2/serial/uark2.c 185948 2008-12-11 23:13:02Z thompsa $
19 */
20
21/*
22 * NOTE: all function names beginning like "uark_cfg_" can only
23 * be called from within the config thread function !
24 */
25
26#include <dev/usb2/include/usb2_devid.h>
27#include <dev/usb2/include/usb2_standard.h>
28#include <dev/usb2/include/usb2_mfunc.h>
29#include <dev/usb2/include/usb2_error.h>
30#include <dev/usb2/include/usb2_cdc.h>
31
32#define USB_DEBUG_VAR usb2_debug
33
34#include <dev/usb2/core/usb2_core.h>
35#include <dev/usb2/core/usb2_debug.h>
36#include <dev/usb2/core/usb2_process.h>
37#include <dev/usb2/core/usb2_config_td.h>
38#include <dev/usb2/core/usb2_request.h>
39#include <dev/usb2/core/usb2_lookup.h>
40#include <dev/usb2/core/usb2_util.h>
41
42#include <dev/usb2/serial/usb2_serial.h>
43
44#define UARK_BUF_SIZE 1024 /* bytes */
45
46#define UARK_N_TRANSFER 4 /* units */
47
48#define UARK_SET_DATA_BITS(x) ((x) - 5)
49
50#define UARK_PARITY_NONE 0x00
51#define UARK_PARITY_ODD 0x08
52#define UARK_PARITY_EVEN 0x18
53
54#define UARK_STOP_BITS_1 0x00
55#define UARK_STOP_BITS_2 0x04
56
57#define UARK_BAUD_REF 3000000
58
59#define UARK_WRITE 0x40
60#define UARK_READ 0xc0
61
62#define UARK_REQUEST 0xfe
63
64#define UARK_CONFIG_INDEX 0
65#define UARK_IFACE_INDEX 0
66
67struct uark_softc {
68 struct usb2_com_super_softc sc_super_ucom;
69 struct usb2_com_softc sc_ucom;
70
71 struct usb2_xfer *sc_xfer[UARK_N_TRANSFER];
72 struct usb2_device *sc_udev;
73
74 uint8_t sc_flags;
75#define UARK_FLAG_BULK_READ_STALL 0x01
76#define UARK_FLAG_BULK_WRITE_STALL 0x02
77 uint8_t sc_msr;
78 uint8_t sc_lsr;
79};
80
81/* prototypes */
82
83static device_probe_t uark_probe;
84static device_attach_t uark_attach;
85static device_detach_t uark_detach;
86
87static usb2_callback_t uark_bulk_write_callback;
88static usb2_callback_t uark_bulk_write_clear_stall_callback;
89static usb2_callback_t uark_bulk_read_callback;
90static usb2_callback_t uark_bulk_read_clear_stall_callback;
91
92static void uark_start_read(struct usb2_com_softc *);
93static void uark_stop_read(struct usb2_com_softc *);
94static void uark_start_write(struct usb2_com_softc *);
95static void uark_stop_write(struct usb2_com_softc *);
96static int uark_pre_param(struct usb2_com_softc *, struct termios *);
97static void uark_cfg_param(struct usb2_com_softc *, struct termios *);
98static void uark_cfg_get_status(struct usb2_com_softc *, uint8_t *,
99 uint8_t *);
100static void uark_cfg_set_break(struct usb2_com_softc *, uint8_t);
101static void uark_cfg_write(struct uark_softc *, uint16_t, uint16_t);
102
103static const struct usb2_config
104 uark_xfer_config[UARK_N_TRANSFER] = {
105
106 [0] = {
107 .type = UE_BULK,
108 .endpoint = UE_ADDR_ANY,
109 .direction = UE_DIR_OUT,
110 .mh.bufsize = UARK_BUF_SIZE,
111 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
112 .mh.callback = &uark_bulk_write_callback,
113 },
114
115 [1] = {
116 .type = UE_BULK,
117 .endpoint = UE_ADDR_ANY,
118 .direction = UE_DIR_IN,
119 .mh.bufsize = UARK_BUF_SIZE,
120 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
121 .mh.callback = &uark_bulk_read_callback,
122 },
123
124 [2] = {
125 .type = UE_CONTROL,
126 .endpoint = 0x00, /* Control pipe */
127 .direction = UE_DIR_ANY,
128 .mh.bufsize = sizeof(struct usb2_device_request),
129 .mh.flags = {},
130 .mh.callback = &uark_bulk_write_clear_stall_callback,
131 .mh.timeout = 1000, /* 1 second */
132 .mh.interval = 50, /* 50ms */
133 },
134
135 [3] = {
136 .type = UE_CONTROL,
137 .endpoint = 0x00, /* Control pipe */
138 .direction = UE_DIR_ANY,
139 .mh.bufsize = sizeof(struct usb2_device_request),
140 .mh.flags = {},
141 .mh.callback = &uark_bulk_read_clear_stall_callback,
142 .mh.timeout = 1000, /* 1 second */
143 .mh.interval = 50, /* 50ms */
144 },
145};
146
147static const struct usb2_com_callback uark_callback = {
148 .usb2_com_cfg_get_status = &uark_cfg_get_status,
149 .usb2_com_cfg_set_break = &uark_cfg_set_break,
150 .usb2_com_cfg_param = &uark_cfg_param,
151 .usb2_com_pre_param = &uark_pre_param,
152 .usb2_com_start_read = &uark_start_read,
153 .usb2_com_stop_read = &uark_stop_read,
154 .usb2_com_start_write = &uark_start_write,
155 .usb2_com_stop_write = &uark_stop_write,
156};
157
158static device_method_t uark_methods[] = {
159 /* Device methods */
160 DEVMETHOD(device_probe, uark_probe),
161 DEVMETHOD(device_attach, uark_attach),
162 DEVMETHOD(device_detach, uark_detach),
163 {0, 0}
164};
165
166static devclass_t uark_devclass;
167
168static driver_t uark_driver = {
169 .name = "uark",
170 .methods = uark_methods,
171 .size = sizeof(struct uark_softc),
172};
173
174DRIVER_MODULE(uark, ushub, uark_driver, uark_devclass, NULL, 0);
175MODULE_DEPEND(uark, usb2_serial, 1, 1, 1);
176MODULE_DEPEND(uark, usb2_core, 1, 1, 1);
177
178static const struct usb2_device_id uark_devs[] = {
179 {USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)},
180};
181
182static int
183uark_probe(device_t dev)
184{
185 struct usb2_attach_arg *uaa = device_get_ivars(dev);
186
187 if (uaa->usb2_mode != USB_MODE_HOST) {
188 return (ENXIO);
189 }
190 if (uaa->info.bConfigIndex != 0) {
191 return (ENXIO);
192 }
193 if (uaa->info.bIfaceIndex != UARK_IFACE_INDEX) {
194 return (ENXIO);
195 }
196 return (usb2_lookup_id_by_uaa(uark_devs, sizeof(uark_devs), uaa));
197}
198
199static int
200uark_attach(device_t dev)
201{
202 struct usb2_attach_arg *uaa = device_get_ivars(dev);
203 struct uark_softc *sc = device_get_softc(dev);
204 int32_t error;
205 uint8_t iface_index;
206
207 if (sc == NULL) {
208 return (ENOMEM);
209 }
210 device_set_usb2_desc(dev);
211
212 sc->sc_udev = uaa->device;
213
214 iface_index = UARK_IFACE_INDEX;
215 error = usb2_transfer_setup
216 (uaa->device, &iface_index, sc->sc_xfer,
217 uark_xfer_config, UARK_N_TRANSFER, sc, &Giant);
218
219 if (error) {
220 device_printf(dev, "allocating control USB "
221 "transfers failed!\n");
222 goto detach;
223 }
224 /* clear stall at first run */
225 sc->sc_flags |= (UARK_FLAG_BULK_WRITE_STALL |
226 UARK_FLAG_BULK_READ_STALL);
227
228 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
229 &uark_callback, &Giant);
230 if (error) {
231 DPRINTF("usb2_com_attach failed\n");
232 goto detach;
233 }
234 return (0); /* success */
235
236detach:
237 uark_detach(dev);
238 return (ENXIO); /* failure */
239}
240
241static int
242uark_detach(device_t dev)
243{
244 struct uark_softc *sc = device_get_softc(dev);
245
246 usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
247
248 usb2_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER);
249
250 return (0);
251}
252
253static void
254uark_bulk_write_callback(struct usb2_xfer *xfer)
255{
256 struct uark_softc *sc = xfer->priv_sc;
257 uint32_t actlen;
258
259 switch (USB_GET_STATE(xfer)) {
260 case USB_ST_SETUP:
261 case USB_ST_TRANSFERRED:
262 if (sc->sc_flags & UARK_FLAG_BULK_WRITE_STALL) {
263 usb2_transfer_start(sc->sc_xfer[2]);
264 return;
265 }
266 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0,
267 UARK_BUF_SIZE, &actlen)) {
268 xfer->frlengths[0] = actlen;
269 usb2_start_hardware(xfer);
270 }
271 return;
272
273 default: /* Error */
274 if (xfer->error != USB_ERR_CANCELLED) {
275 sc->sc_flags |= UARK_FLAG_BULK_WRITE_STALL;
276 usb2_transfer_start(sc->sc_xfer[2]);
277 }
278 return;
279
280 }
281}
282
283static void
284uark_bulk_write_clear_stall_callback(struct usb2_xfer *xfer)
285{
286 struct uark_softc *sc = xfer->priv_sc;
287 struct usb2_xfer *xfer_other = sc->sc_xfer[0];
288
289 if (usb2_clear_stall_callback(xfer, xfer_other)) {
290 DPRINTF("stall cleared\n");
291 sc->sc_flags &= ~UARK_FLAG_BULK_WRITE_STALL;
292 usb2_transfer_start(xfer_other);
293 }
294 return;
295}
296
297static void
298uark_bulk_read_callback(struct usb2_xfer *xfer)
299{
300 struct uark_softc *sc = xfer->priv_sc;
301
302 switch (USB_GET_STATE(xfer)) {
303 case USB_ST_TRANSFERRED:
304 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0,
305 xfer->actlen);
306
307 case USB_ST_SETUP:
308 if (sc->sc_flags & UARK_FLAG_BULK_READ_STALL) {
309 usb2_transfer_start(sc->sc_xfer[3]);
310 } else {
311 xfer->frlengths[0] = xfer->max_data_length;
312 usb2_start_hardware(xfer);
313 }
314 return;
315
316 default: /* Error */
317 if (xfer->error != USB_ERR_CANCELLED) {
318 sc->sc_flags |= UARK_FLAG_BULK_READ_STALL;
319 usb2_transfer_start(sc->sc_xfer[3]);
320 }
321 return;
322
323 }
324}
325
326static void
327uark_bulk_read_clear_stall_callback(struct usb2_xfer *xfer)
328{
329 struct uark_softc *sc = xfer->priv_sc;
330 struct usb2_xfer *xfer_other = sc->sc_xfer[1];
331
332 if (usb2_clear_stall_callback(xfer, xfer_other)) {
333 DPRINTF("stall cleared\n");
334 sc->sc_flags &= ~UARK_FLAG_BULK_READ_STALL;
335 usb2_transfer_start(xfer_other);
336 }
337 return;
338}
339
340static void
341uark_start_read(struct usb2_com_softc *ucom)
342{
343 struct uark_softc *sc = ucom->sc_parent;
344
345 usb2_transfer_start(sc->sc_xfer[1]);
346 return;
347}
348
349static void
350uark_stop_read(struct usb2_com_softc *ucom)
351{
352 struct uark_softc *sc = ucom->sc_parent;
353
354 usb2_transfer_stop(sc->sc_xfer[3]);
355 usb2_transfer_stop(sc->sc_xfer[1]);
356 return;
357}
358
359static void
360uark_start_write(struct usb2_com_softc *ucom)
361{
362 struct uark_softc *sc = ucom->sc_parent;
363
364 usb2_transfer_start(sc->sc_xfer[0]);
365 return;
366}
367
368static void
369uark_stop_write(struct usb2_com_softc *ucom)
370{
371 struct uark_softc *sc = ucom->sc_parent;
372
373 usb2_transfer_stop(sc->sc_xfer[2]);
374 usb2_transfer_stop(sc->sc_xfer[0]);
375 return;
376}
377
378static int
379uark_pre_param(struct usb2_com_softc *ucom, struct termios *t)
380{
381 if ((t->c_ospeed < 300) || (t->c_ospeed > 115200))
382 return (EINVAL);
383 return (0);
384}
385
386static void
387uark_cfg_param(struct usb2_com_softc *ucom, struct termios *t)
388{
389 struct uark_softc *sc = ucom->sc_parent;
390 uint32_t speed = t->c_ospeed;
391 uint16_t data;
392
393 /*
394 * NOTE: When reverse computing the baud rate from the "data" all
395 * allowed baud rates are within 3% of the initial baud rate.
396 */
397 data = (UARK_BAUD_REF + (speed / 2)) / speed;
398
399 uark_cfg_write(sc, 3, 0x83);
400 uark_cfg_write(sc, 0, data & 0xFF);
401 uark_cfg_write(sc, 1, data >> 8);
402 uark_cfg_write(sc, 3, 0x03);
403
404 if (t->c_cflag & CSTOPB)
405 data = UARK_STOP_BITS_2;
406 else
407 data = UARK_STOP_BITS_1;
408
409 if (t->c_cflag & PARENB) {
410 if (t->c_cflag & PARODD)
411 data |= UARK_PARITY_ODD;
412 else
413 data |= UARK_PARITY_EVEN;
414 } else
415 data |= UARK_PARITY_NONE;
416
417 switch (t->c_cflag & CSIZE) {
418 case CS5:
419 data |= UARK_SET_DATA_BITS(5);
420 break;
421 case CS6:
422 data |= UARK_SET_DATA_BITS(6);
423 break;
424 case CS7:
425 data |= UARK_SET_DATA_BITS(7);
426 break;
427 default:
428 case CS8:
429 data |= UARK_SET_DATA_BITS(8);
430 break;
431 }
432 uark_cfg_write(sc, 3, 0x00);
433 uark_cfg_write(sc, 3, data);
434 return;
435}
436
437static void
438uark_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr)
439{
440 struct uark_softc *sc = ucom->sc_parent;
441
442 *lsr = sc->sc_lsr;
443 *msr = sc->sc_msr;
444 return;
445}
446
447static void
448uark_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff)
449{
450 struct uark_softc *sc = ucom->sc_parent;
451
452 DPRINTF("onoff=%d\n", onoff);
453
454 uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00);
455 return;
456}
457
458static void
459uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value)
460{
461 struct usb2_device_request req;
462 usb2_error_t err;
463
464 if (usb2_com_cfg_is_gone(&sc->sc_ucom)) {
465 return;
466 }
467 req.bmRequestType = UARK_WRITE;
468 req.bRequest = UARK_REQUEST;
469 USETW(req.wValue, value);
470 USETW(req.wIndex, index);
471 USETW(req.wLength, 0);
472
473 err = usb2_do_request_flags
474 (sc->sc_udev, &Giant, &req, NULL, 0, NULL, 1000);
475
476 if (err) {
477 DPRINTFN(0, "device request failed, err=%s "
478 "(ignored)\n", usb2_errstr(err));
479 }
480 return;
481}
2
3/*
4 * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
5 *
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.
9 *
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.
17 *
18 * $FreeBSD: head/sys/dev/usb2/serial/uark2.c 185948 2008-12-11 23:13:02Z thompsa $
19 */
20
21/*
22 * NOTE: all function names beginning like "uark_cfg_" can only
23 * be called from within the config thread function !
24 */
25
26#include <dev/usb2/include/usb2_devid.h>
27#include <dev/usb2/include/usb2_standard.h>
28#include <dev/usb2/include/usb2_mfunc.h>
29#include <dev/usb2/include/usb2_error.h>
30#include <dev/usb2/include/usb2_cdc.h>
31
32#define USB_DEBUG_VAR usb2_debug
33
34#include <dev/usb2/core/usb2_core.h>
35#include <dev/usb2/core/usb2_debug.h>
36#include <dev/usb2/core/usb2_process.h>
37#include <dev/usb2/core/usb2_config_td.h>
38#include <dev/usb2/core/usb2_request.h>
39#include <dev/usb2/core/usb2_lookup.h>
40#include <dev/usb2/core/usb2_util.h>
41
42#include <dev/usb2/serial/usb2_serial.h>
43
44#define UARK_BUF_SIZE 1024 /* bytes */
45
46#define UARK_N_TRANSFER 4 /* units */
47
48#define UARK_SET_DATA_BITS(x) ((x) - 5)
49
50#define UARK_PARITY_NONE 0x00
51#define UARK_PARITY_ODD 0x08
52#define UARK_PARITY_EVEN 0x18
53
54#define UARK_STOP_BITS_1 0x00
55#define UARK_STOP_BITS_2 0x04
56
57#define UARK_BAUD_REF 3000000
58
59#define UARK_WRITE 0x40
60#define UARK_READ 0xc0
61
62#define UARK_REQUEST 0xfe
63
64#define UARK_CONFIG_INDEX 0
65#define UARK_IFACE_INDEX 0
66
67struct uark_softc {
68 struct usb2_com_super_softc sc_super_ucom;
69 struct usb2_com_softc sc_ucom;
70
71 struct usb2_xfer *sc_xfer[UARK_N_TRANSFER];
72 struct usb2_device *sc_udev;
73
74 uint8_t sc_flags;
75#define UARK_FLAG_BULK_READ_STALL 0x01
76#define UARK_FLAG_BULK_WRITE_STALL 0x02
77 uint8_t sc_msr;
78 uint8_t sc_lsr;
79};
80
81/* prototypes */
82
83static device_probe_t uark_probe;
84static device_attach_t uark_attach;
85static device_detach_t uark_detach;
86
87static usb2_callback_t uark_bulk_write_callback;
88static usb2_callback_t uark_bulk_write_clear_stall_callback;
89static usb2_callback_t uark_bulk_read_callback;
90static usb2_callback_t uark_bulk_read_clear_stall_callback;
91
92static void uark_start_read(struct usb2_com_softc *);
93static void uark_stop_read(struct usb2_com_softc *);
94static void uark_start_write(struct usb2_com_softc *);
95static void uark_stop_write(struct usb2_com_softc *);
96static int uark_pre_param(struct usb2_com_softc *, struct termios *);
97static void uark_cfg_param(struct usb2_com_softc *, struct termios *);
98static void uark_cfg_get_status(struct usb2_com_softc *, uint8_t *,
99 uint8_t *);
100static void uark_cfg_set_break(struct usb2_com_softc *, uint8_t);
101static void uark_cfg_write(struct uark_softc *, uint16_t, uint16_t);
102
103static const struct usb2_config
104 uark_xfer_config[UARK_N_TRANSFER] = {
105
106 [0] = {
107 .type = UE_BULK,
108 .endpoint = UE_ADDR_ANY,
109 .direction = UE_DIR_OUT,
110 .mh.bufsize = UARK_BUF_SIZE,
111 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
112 .mh.callback = &uark_bulk_write_callback,
113 },
114
115 [1] = {
116 .type = UE_BULK,
117 .endpoint = UE_ADDR_ANY,
118 .direction = UE_DIR_IN,
119 .mh.bufsize = UARK_BUF_SIZE,
120 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
121 .mh.callback = &uark_bulk_read_callback,
122 },
123
124 [2] = {
125 .type = UE_CONTROL,
126 .endpoint = 0x00, /* Control pipe */
127 .direction = UE_DIR_ANY,
128 .mh.bufsize = sizeof(struct usb2_device_request),
129 .mh.flags = {},
130 .mh.callback = &uark_bulk_write_clear_stall_callback,
131 .mh.timeout = 1000, /* 1 second */
132 .mh.interval = 50, /* 50ms */
133 },
134
135 [3] = {
136 .type = UE_CONTROL,
137 .endpoint = 0x00, /* Control pipe */
138 .direction = UE_DIR_ANY,
139 .mh.bufsize = sizeof(struct usb2_device_request),
140 .mh.flags = {},
141 .mh.callback = &uark_bulk_read_clear_stall_callback,
142 .mh.timeout = 1000, /* 1 second */
143 .mh.interval = 50, /* 50ms */
144 },
145};
146
147static const struct usb2_com_callback uark_callback = {
148 .usb2_com_cfg_get_status = &uark_cfg_get_status,
149 .usb2_com_cfg_set_break = &uark_cfg_set_break,
150 .usb2_com_cfg_param = &uark_cfg_param,
151 .usb2_com_pre_param = &uark_pre_param,
152 .usb2_com_start_read = &uark_start_read,
153 .usb2_com_stop_read = &uark_stop_read,
154 .usb2_com_start_write = &uark_start_write,
155 .usb2_com_stop_write = &uark_stop_write,
156};
157
158static device_method_t uark_methods[] = {
159 /* Device methods */
160 DEVMETHOD(device_probe, uark_probe),
161 DEVMETHOD(device_attach, uark_attach),
162 DEVMETHOD(device_detach, uark_detach),
163 {0, 0}
164};
165
166static devclass_t uark_devclass;
167
168static driver_t uark_driver = {
169 .name = "uark",
170 .methods = uark_methods,
171 .size = sizeof(struct uark_softc),
172};
173
174DRIVER_MODULE(uark, ushub, uark_driver, uark_devclass, NULL, 0);
175MODULE_DEPEND(uark, usb2_serial, 1, 1, 1);
176MODULE_DEPEND(uark, usb2_core, 1, 1, 1);
177
178static const struct usb2_device_id uark_devs[] = {
179 {USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)},
180};
181
182static int
183uark_probe(device_t dev)
184{
185 struct usb2_attach_arg *uaa = device_get_ivars(dev);
186
187 if (uaa->usb2_mode != USB_MODE_HOST) {
188 return (ENXIO);
189 }
190 if (uaa->info.bConfigIndex != 0) {
191 return (ENXIO);
192 }
193 if (uaa->info.bIfaceIndex != UARK_IFACE_INDEX) {
194 return (ENXIO);
195 }
196 return (usb2_lookup_id_by_uaa(uark_devs, sizeof(uark_devs), uaa));
197}
198
199static int
200uark_attach(device_t dev)
201{
202 struct usb2_attach_arg *uaa = device_get_ivars(dev);
203 struct uark_softc *sc = device_get_softc(dev);
204 int32_t error;
205 uint8_t iface_index;
206
207 if (sc == NULL) {
208 return (ENOMEM);
209 }
210 device_set_usb2_desc(dev);
211
212 sc->sc_udev = uaa->device;
213
214 iface_index = UARK_IFACE_INDEX;
215 error = usb2_transfer_setup
216 (uaa->device, &iface_index, sc->sc_xfer,
217 uark_xfer_config, UARK_N_TRANSFER, sc, &Giant);
218
219 if (error) {
220 device_printf(dev, "allocating control USB "
221 "transfers failed!\n");
222 goto detach;
223 }
224 /* clear stall at first run */
225 sc->sc_flags |= (UARK_FLAG_BULK_WRITE_STALL |
226 UARK_FLAG_BULK_READ_STALL);
227
228 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
229 &uark_callback, &Giant);
230 if (error) {
231 DPRINTF("usb2_com_attach failed\n");
232 goto detach;
233 }
234 return (0); /* success */
235
236detach:
237 uark_detach(dev);
238 return (ENXIO); /* failure */
239}
240
241static int
242uark_detach(device_t dev)
243{
244 struct uark_softc *sc = device_get_softc(dev);
245
246 usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
247
248 usb2_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER);
249
250 return (0);
251}
252
253static void
254uark_bulk_write_callback(struct usb2_xfer *xfer)
255{
256 struct uark_softc *sc = xfer->priv_sc;
257 uint32_t actlen;
258
259 switch (USB_GET_STATE(xfer)) {
260 case USB_ST_SETUP:
261 case USB_ST_TRANSFERRED:
262 if (sc->sc_flags & UARK_FLAG_BULK_WRITE_STALL) {
263 usb2_transfer_start(sc->sc_xfer[2]);
264 return;
265 }
266 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0,
267 UARK_BUF_SIZE, &actlen)) {
268 xfer->frlengths[0] = actlen;
269 usb2_start_hardware(xfer);
270 }
271 return;
272
273 default: /* Error */
274 if (xfer->error != USB_ERR_CANCELLED) {
275 sc->sc_flags |= UARK_FLAG_BULK_WRITE_STALL;
276 usb2_transfer_start(sc->sc_xfer[2]);
277 }
278 return;
279
280 }
281}
282
283static void
284uark_bulk_write_clear_stall_callback(struct usb2_xfer *xfer)
285{
286 struct uark_softc *sc = xfer->priv_sc;
287 struct usb2_xfer *xfer_other = sc->sc_xfer[0];
288
289 if (usb2_clear_stall_callback(xfer, xfer_other)) {
290 DPRINTF("stall cleared\n");
291 sc->sc_flags &= ~UARK_FLAG_BULK_WRITE_STALL;
292 usb2_transfer_start(xfer_other);
293 }
294 return;
295}
296
297static void
298uark_bulk_read_callback(struct usb2_xfer *xfer)
299{
300 struct uark_softc *sc = xfer->priv_sc;
301
302 switch (USB_GET_STATE(xfer)) {
303 case USB_ST_TRANSFERRED:
304 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0,
305 xfer->actlen);
306
307 case USB_ST_SETUP:
308 if (sc->sc_flags & UARK_FLAG_BULK_READ_STALL) {
309 usb2_transfer_start(sc->sc_xfer[3]);
310 } else {
311 xfer->frlengths[0] = xfer->max_data_length;
312 usb2_start_hardware(xfer);
313 }
314 return;
315
316 default: /* Error */
317 if (xfer->error != USB_ERR_CANCELLED) {
318 sc->sc_flags |= UARK_FLAG_BULK_READ_STALL;
319 usb2_transfer_start(sc->sc_xfer[3]);
320 }
321 return;
322
323 }
324}
325
326static void
327uark_bulk_read_clear_stall_callback(struct usb2_xfer *xfer)
328{
329 struct uark_softc *sc = xfer->priv_sc;
330 struct usb2_xfer *xfer_other = sc->sc_xfer[1];
331
332 if (usb2_clear_stall_callback(xfer, xfer_other)) {
333 DPRINTF("stall cleared\n");
334 sc->sc_flags &= ~UARK_FLAG_BULK_READ_STALL;
335 usb2_transfer_start(xfer_other);
336 }
337 return;
338}
339
340static void
341uark_start_read(struct usb2_com_softc *ucom)
342{
343 struct uark_softc *sc = ucom->sc_parent;
344
345 usb2_transfer_start(sc->sc_xfer[1]);
346 return;
347}
348
349static void
350uark_stop_read(struct usb2_com_softc *ucom)
351{
352 struct uark_softc *sc = ucom->sc_parent;
353
354 usb2_transfer_stop(sc->sc_xfer[3]);
355 usb2_transfer_stop(sc->sc_xfer[1]);
356 return;
357}
358
359static void
360uark_start_write(struct usb2_com_softc *ucom)
361{
362 struct uark_softc *sc = ucom->sc_parent;
363
364 usb2_transfer_start(sc->sc_xfer[0]);
365 return;
366}
367
368static void
369uark_stop_write(struct usb2_com_softc *ucom)
370{
371 struct uark_softc *sc = ucom->sc_parent;
372
373 usb2_transfer_stop(sc->sc_xfer[2]);
374 usb2_transfer_stop(sc->sc_xfer[0]);
375 return;
376}
377
378static int
379uark_pre_param(struct usb2_com_softc *ucom, struct termios *t)
380{
381 if ((t->c_ospeed < 300) || (t->c_ospeed > 115200))
382 return (EINVAL);
383 return (0);
384}
385
386static void
387uark_cfg_param(struct usb2_com_softc *ucom, struct termios *t)
388{
389 struct uark_softc *sc = ucom->sc_parent;
390 uint32_t speed = t->c_ospeed;
391 uint16_t data;
392
393 /*
394 * NOTE: When reverse computing the baud rate from the "data" all
395 * allowed baud rates are within 3% of the initial baud rate.
396 */
397 data = (UARK_BAUD_REF + (speed / 2)) / speed;
398
399 uark_cfg_write(sc, 3, 0x83);
400 uark_cfg_write(sc, 0, data & 0xFF);
401 uark_cfg_write(sc, 1, data >> 8);
402 uark_cfg_write(sc, 3, 0x03);
403
404 if (t->c_cflag & CSTOPB)
405 data = UARK_STOP_BITS_2;
406 else
407 data = UARK_STOP_BITS_1;
408
409 if (t->c_cflag & PARENB) {
410 if (t->c_cflag & PARODD)
411 data |= UARK_PARITY_ODD;
412 else
413 data |= UARK_PARITY_EVEN;
414 } else
415 data |= UARK_PARITY_NONE;
416
417 switch (t->c_cflag & CSIZE) {
418 case CS5:
419 data |= UARK_SET_DATA_BITS(5);
420 break;
421 case CS6:
422 data |= UARK_SET_DATA_BITS(6);
423 break;
424 case CS7:
425 data |= UARK_SET_DATA_BITS(7);
426 break;
427 default:
428 case CS8:
429 data |= UARK_SET_DATA_BITS(8);
430 break;
431 }
432 uark_cfg_write(sc, 3, 0x00);
433 uark_cfg_write(sc, 3, data);
434 return;
435}
436
437static void
438uark_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr)
439{
440 struct uark_softc *sc = ucom->sc_parent;
441
442 *lsr = sc->sc_lsr;
443 *msr = sc->sc_msr;
444 return;
445}
446
447static void
448uark_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff)
449{
450 struct uark_softc *sc = ucom->sc_parent;
451
452 DPRINTF("onoff=%d\n", onoff);
453
454 uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00);
455 return;
456}
457
458static void
459uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value)
460{
461 struct usb2_device_request req;
462 usb2_error_t err;
463
464 if (usb2_com_cfg_is_gone(&sc->sc_ucom)) {
465 return;
466 }
467 req.bmRequestType = UARK_WRITE;
468 req.bRequest = UARK_REQUEST;
469 USETW(req.wValue, value);
470 USETW(req.wIndex, index);
471 USETW(req.wLength, 0);
472
473 err = usb2_do_request_flags
474 (sc->sc_udev, &Giant, &req, NULL, 0, NULL, 1000);
475
476 if (err) {
477 DPRINTFN(0, "device request failed, err=%s "
478 "(ignored)\n", usb2_errstr(err));
479 }
480 return;
481}