xref: /freebsd/sys/dev/usb/serial/uark.c (revision d2b2128a286a00ee53d79cb88b4e59bf42525cf9)
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$
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 "usbdevs.h"
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>
31 
32 #define	USB_DEBUG_VAR usb2_debug
33 
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>
40 
41 #include <dev/usb/serial/usb_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 
64 enum {
65 	UARK_BULK_DT_WR,
66 	UARK_BULK_DT_RD,
67 	UARK_N_TRANSFER,
68 };
69 
70 struct uark_softc {
71 	struct usb2_com_super_softc sc_super_ucom;
72 	struct usb2_com_softc sc_ucom;
73 
74 	struct usb2_xfer *sc_xfer[UARK_N_TRANSFER];
75 	struct usb2_device *sc_udev;
76 	struct mtx sc_mtx;
77 
78 	uint8_t	sc_msr;
79 	uint8_t	sc_lsr;
80 };
81 
82 /* prototypes */
83 
84 static device_probe_t uark_probe;
85 static device_attach_t uark_attach;
86 static device_detach_t uark_detach;
87 
88 static usb2_callback_t uark_bulk_write_callback;
89 static usb2_callback_t uark_bulk_read_callback;
90 
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 *,
98 		    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);
101 
102 static const struct usb2_config
103 	uark_xfer_config[UARK_N_TRANSFER] = {
104 
105 	[UARK_BULK_DT_WR] = {
106 		.type = UE_BULK,
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,
112 	},
113 
114 	[UARK_BULK_DT_RD] = {
115 		.type = UE_BULK,
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,
121 	},
122 };
123 
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,
133 };
134 
135 static device_method_t uark_methods[] = {
136 	/* Device methods */
137 	DEVMETHOD(device_probe, uark_probe),
138 	DEVMETHOD(device_attach, uark_attach),
139 	DEVMETHOD(device_detach, uark_detach),
140 	{0, 0}
141 };
142 
143 static devclass_t uark_devclass;
144 
145 static driver_t uark_driver = {
146 	.name = "uark",
147 	.methods = uark_methods,
148 	.size = sizeof(struct uark_softc),
149 };
150 
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);
154 
155 static const struct usb2_device_id uark_devs[] = {
156 	{USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)},
157 };
158 
159 static int
160 uark_probe(device_t dev)
161 {
162 	struct usb2_attach_arg *uaa = device_get_ivars(dev);
163 
164 	if (uaa->usb2_mode != USB_MODE_HOST) {
165 		return (ENXIO);
166 	}
167 	if (uaa->info.bConfigIndex != 0) {
168 		return (ENXIO);
169 	}
170 	if (uaa->info.bIfaceIndex != UARK_IFACE_INDEX) {
171 		return (ENXIO);
172 	}
173 	return (usb2_lookup_id_by_uaa(uark_devs, sizeof(uark_devs), uaa));
174 }
175 
176 static int
177 uark_attach(device_t dev)
178 {
179 	struct usb2_attach_arg *uaa = device_get_ivars(dev);
180 	struct uark_softc *sc = device_get_softc(dev);
181 	int32_t error;
182 	uint8_t iface_index;
183 
184 	device_set_usb2_desc(dev);
185 	mtx_init(&sc->sc_mtx, "uark", NULL, MTX_DEF);
186 
187 	sc->sc_udev = uaa->device;
188 
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);
193 
194 	if (error) {
195 		device_printf(dev, "allocating control USB "
196 		    "transfers failed!\n");
197 		goto detach;
198 	}
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);
204 
205 	error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
206 	    &uark_callback, &sc->sc_mtx);
207 	if (error) {
208 		DPRINTF("usb2_com_attach failed\n");
209 		goto detach;
210 	}
211 	return (0);			/* success */
212 
213 detach:
214 	uark_detach(dev);
215 	return (ENXIO);			/* failure */
216 }
217 
218 static int
219 uark_detach(device_t dev)
220 {
221 	struct uark_softc *sc = device_get_softc(dev);
222 
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);
226 
227 	return (0);
228 }
229 
230 static void
231 uark_bulk_write_callback(struct usb2_xfer *xfer)
232 {
233 	struct uark_softc *sc = xfer->priv_sc;
234 	uint32_t actlen;
235 
236 	switch (USB_GET_STATE(xfer)) {
237 	case USB_ST_SETUP:
238 	case USB_ST_TRANSFERRED:
239 tr_setup:
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);
244 		}
245 		return;
246 
247 	default:			/* Error */
248 		if (xfer->error != USB_ERR_CANCELLED) {
249 			/* try to clear stall first */
250 			xfer->flags.stall_pipe = 1;
251 			goto tr_setup;
252 		}
253 		return;
254 
255 	}
256 }
257 
258 static void
259 uark_bulk_read_callback(struct usb2_xfer *xfer)
260 {
261 	struct uark_softc *sc = xfer->priv_sc;
262 
263 	switch (USB_GET_STATE(xfer)) {
264 	case USB_ST_TRANSFERRED:
265 		usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0,
266 		    xfer->actlen);
267 
268 	case USB_ST_SETUP:
269 tr_setup:
270 		xfer->frlengths[0] = xfer->max_data_length;
271 		usb2_start_hardware(xfer);
272 		return;
273 
274 	default:			/* Error */
275 		if (xfer->error != USB_ERR_CANCELLED) {
276 			/* try to clear stall first */
277 			xfer->flags.stall_pipe = 1;
278 			goto tr_setup;
279 		}
280 		return;
281 	}
282 }
283 
284 static void
285 uark_start_read(struct usb2_com_softc *ucom)
286 {
287 	struct uark_softc *sc = ucom->sc_parent;
288 
289 	usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_RD]);
290 }
291 
292 static void
293 uark_stop_read(struct usb2_com_softc *ucom)
294 {
295 	struct uark_softc *sc = ucom->sc_parent;
296 
297 	usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_RD]);
298 }
299 
300 static void
301 uark_start_write(struct usb2_com_softc *ucom)
302 {
303 	struct uark_softc *sc = ucom->sc_parent;
304 
305 	usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_WR]);
306 }
307 
308 static void
309 uark_stop_write(struct usb2_com_softc *ucom)
310 {
311 	struct uark_softc *sc = ucom->sc_parent;
312 
313 	usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_WR]);
314 }
315 
316 static int
317 uark_pre_param(struct usb2_com_softc *ucom, struct termios *t)
318 {
319 	if ((t->c_ospeed < 300) || (t->c_ospeed > 115200))
320 		return (EINVAL);
321 	return (0);
322 }
323 
324 static void
325 uark_cfg_param(struct usb2_com_softc *ucom, struct termios *t)
326 {
327 	struct uark_softc *sc = ucom->sc_parent;
328 	uint32_t speed = t->c_ospeed;
329 	uint16_t data;
330 
331 	/*
332 	 * NOTE: When reverse computing the baud rate from the "data" all
333 	 * allowed baud rates are within 3% of the initial baud rate.
334 	 */
335 	data = (UARK_BAUD_REF + (speed / 2)) / speed;
336 
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);
341 
342 	if (t->c_cflag & CSTOPB)
343 		data = UARK_STOP_BITS_2;
344 	else
345 		data = UARK_STOP_BITS_1;
346 
347 	if (t->c_cflag & PARENB) {
348 		if (t->c_cflag & PARODD)
349 			data |= UARK_PARITY_ODD;
350 		else
351 			data |= UARK_PARITY_EVEN;
352 	} else
353 		data |= UARK_PARITY_NONE;
354 
355 	switch (t->c_cflag & CSIZE) {
356 	case CS5:
357 		data |= UARK_SET_DATA_BITS(5);
358 		break;
359 	case CS6:
360 		data |= UARK_SET_DATA_BITS(6);
361 		break;
362 	case CS7:
363 		data |= UARK_SET_DATA_BITS(7);
364 		break;
365 	default:
366 	case CS8:
367 		data |= UARK_SET_DATA_BITS(8);
368 		break;
369 	}
370 	uark_cfg_write(sc, 3, 0x00);
371 	uark_cfg_write(sc, 3, data);
372 }
373 
374 static void
375 uark_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr)
376 {
377 	struct uark_softc *sc = ucom->sc_parent;
378 
379 	*lsr = sc->sc_lsr;
380 	*msr = sc->sc_msr;
381 }
382 
383 static void
384 uark_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff)
385 {
386 	struct uark_softc *sc = ucom->sc_parent;
387 
388 	DPRINTF("onoff=%d\n", onoff);
389 
390 	uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00);
391 }
392 
393 static void
394 uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value)
395 {
396 	struct usb2_device_request req;
397 	usb2_error_t err;
398 
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);
404 
405 	err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
406 	    &req, NULL, 0, 1000);
407 	if (err) {
408 		DPRINTFN(0, "device request failed, err=%s "
409 		    "(ignored)\n", usb2_errstr(err));
410 	}
411 }
412