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