xref: /freebsd/sys/dev/usb/serial/uark.c (revision 39beb93c)
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 
77 	uint8_t	sc_msr;
78 	uint8_t	sc_lsr;
79 };
80 
81 /* prototypes */
82 
83 static device_probe_t uark_probe;
84 static device_attach_t uark_attach;
85 static device_detach_t uark_detach;
86 
87 static usb2_callback_t uark_bulk_write_callback;
88 static usb2_callback_t uark_bulk_read_callback;
89 
90 static void	uark_start_read(struct usb2_com_softc *);
91 static void	uark_stop_read(struct usb2_com_softc *);
92 static void	uark_start_write(struct usb2_com_softc *);
93 static void	uark_stop_write(struct usb2_com_softc *);
94 static int	uark_pre_param(struct usb2_com_softc *, struct termios *);
95 static void	uark_cfg_param(struct usb2_com_softc *, struct termios *);
96 static void	uark_cfg_get_status(struct usb2_com_softc *, uint8_t *,
97 		    uint8_t *);
98 static void	uark_cfg_set_break(struct usb2_com_softc *, uint8_t);
99 static void	uark_cfg_write(struct uark_softc *, uint16_t, uint16_t);
100 
101 static const struct usb2_config
102 	uark_xfer_config[UARK_N_TRANSFER] = {
103 
104 	[UARK_BULK_DT_WR] = {
105 		.type = UE_BULK,
106 		.endpoint = UE_ADDR_ANY,
107 		.direction = UE_DIR_OUT,
108 		.mh.bufsize = UARK_BUF_SIZE,
109 		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
110 		.mh.callback = &uark_bulk_write_callback,
111 	},
112 
113 	[UARK_BULK_DT_RD] = {
114 		.type = UE_BULK,
115 		.endpoint = UE_ADDR_ANY,
116 		.direction = UE_DIR_IN,
117 		.mh.bufsize = UARK_BUF_SIZE,
118 		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
119 		.mh.callback = &uark_bulk_read_callback,
120 	},
121 };
122 
123 static const struct usb2_com_callback uark_callback = {
124 	.usb2_com_cfg_get_status = &uark_cfg_get_status,
125 	.usb2_com_cfg_set_break = &uark_cfg_set_break,
126 	.usb2_com_cfg_param = &uark_cfg_param,
127 	.usb2_com_pre_param = &uark_pre_param,
128 	.usb2_com_start_read = &uark_start_read,
129 	.usb2_com_stop_read = &uark_stop_read,
130 	.usb2_com_start_write = &uark_start_write,
131 	.usb2_com_stop_write = &uark_stop_write,
132 };
133 
134 static device_method_t uark_methods[] = {
135 	/* Device methods */
136 	DEVMETHOD(device_probe, uark_probe),
137 	DEVMETHOD(device_attach, uark_attach),
138 	DEVMETHOD(device_detach, uark_detach),
139 	{0, 0}
140 };
141 
142 static devclass_t uark_devclass;
143 
144 static driver_t uark_driver = {
145 	.name = "uark",
146 	.methods = uark_methods,
147 	.size = sizeof(struct uark_softc),
148 };
149 
150 DRIVER_MODULE(uark, ushub, uark_driver, uark_devclass, NULL, 0);
151 MODULE_DEPEND(uark, ucom, 1, 1, 1);
152 MODULE_DEPEND(uark, usb, 1, 1, 1);
153 
154 static const struct usb2_device_id uark_devs[] = {
155 	{USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)},
156 };
157 
158 static int
159 uark_probe(device_t dev)
160 {
161 	struct usb2_attach_arg *uaa = device_get_ivars(dev);
162 
163 	if (uaa->usb2_mode != USB_MODE_HOST) {
164 		return (ENXIO);
165 	}
166 	if (uaa->info.bConfigIndex != 0) {
167 		return (ENXIO);
168 	}
169 	if (uaa->info.bIfaceIndex != UARK_IFACE_INDEX) {
170 		return (ENXIO);
171 	}
172 	return (usb2_lookup_id_by_uaa(uark_devs, sizeof(uark_devs), uaa));
173 }
174 
175 static int
176 uark_attach(device_t dev)
177 {
178 	struct usb2_attach_arg *uaa = device_get_ivars(dev);
179 	struct uark_softc *sc = device_get_softc(dev);
180 	int32_t error;
181 	uint8_t iface_index;
182 
183 	device_set_usb2_desc(dev);
184 
185 	sc->sc_udev = uaa->device;
186 
187 	iface_index = UARK_IFACE_INDEX;
188 	error = usb2_transfer_setup
189 	    (uaa->device, &iface_index, sc->sc_xfer,
190 	    uark_xfer_config, UARK_N_TRANSFER, sc, &Giant);
191 
192 	if (error) {
193 		device_printf(dev, "allocating control USB "
194 		    "transfers failed!\n");
195 		goto detach;
196 	}
197 	/* clear stall at first run */
198 	usb2_transfer_set_stall(sc->sc_xfer[UARK_BULK_DT_WR]);
199 	usb2_transfer_set_stall(sc->sc_xfer[UARK_BULK_DT_RD]);
200 
201 	error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
202 	    &uark_callback, &Giant);
203 	if (error) {
204 		DPRINTF("usb2_com_attach failed\n");
205 		goto detach;
206 	}
207 	return (0);			/* success */
208 
209 detach:
210 	uark_detach(dev);
211 	return (ENXIO);			/* failure */
212 }
213 
214 static int
215 uark_detach(device_t dev)
216 {
217 	struct uark_softc *sc = device_get_softc(dev);
218 
219 	usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1);
220 
221 	usb2_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER);
222 
223 	return (0);
224 }
225 
226 static void
227 uark_bulk_write_callback(struct usb2_xfer *xfer)
228 {
229 	struct uark_softc *sc = xfer->priv_sc;
230 	uint32_t actlen;
231 
232 	switch (USB_GET_STATE(xfer)) {
233 	case USB_ST_SETUP:
234 	case USB_ST_TRANSFERRED:
235 tr_setup:
236 		if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0,
237 		    UARK_BUF_SIZE, &actlen)) {
238 			xfer->frlengths[0] = actlen;
239 			usb2_start_hardware(xfer);
240 		}
241 		return;
242 
243 	default:			/* Error */
244 		if (xfer->error != USB_ERR_CANCELLED) {
245 			/* try to clear stall first */
246 			xfer->flags.stall_pipe = 1;
247 			goto tr_setup;
248 		}
249 		return;
250 
251 	}
252 }
253 
254 static void
255 uark_bulk_read_callback(struct usb2_xfer *xfer)
256 {
257 	struct uark_softc *sc = xfer->priv_sc;
258 
259 	switch (USB_GET_STATE(xfer)) {
260 	case USB_ST_TRANSFERRED:
261 		usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0,
262 		    xfer->actlen);
263 
264 	case USB_ST_SETUP:
265 tr_setup:
266 		xfer->frlengths[0] = xfer->max_data_length;
267 		usb2_start_hardware(xfer);
268 		return;
269 
270 	default:			/* Error */
271 		if (xfer->error != USB_ERR_CANCELLED) {
272 			/* try to clear stall first */
273 			xfer->flags.stall_pipe = 1;
274 			goto tr_setup;
275 		}
276 		return;
277 	}
278 }
279 
280 static void
281 uark_start_read(struct usb2_com_softc *ucom)
282 {
283 	struct uark_softc *sc = ucom->sc_parent;
284 
285 	usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_RD]);
286 }
287 
288 static void
289 uark_stop_read(struct usb2_com_softc *ucom)
290 {
291 	struct uark_softc *sc = ucom->sc_parent;
292 
293 	usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_RD]);
294 }
295 
296 static void
297 uark_start_write(struct usb2_com_softc *ucom)
298 {
299 	struct uark_softc *sc = ucom->sc_parent;
300 
301 	usb2_transfer_start(sc->sc_xfer[UARK_BULK_DT_WR]);
302 }
303 
304 static void
305 uark_stop_write(struct usb2_com_softc *ucom)
306 {
307 	struct uark_softc *sc = ucom->sc_parent;
308 
309 	usb2_transfer_stop(sc->sc_xfer[UARK_BULK_DT_WR]);
310 }
311 
312 static int
313 uark_pre_param(struct usb2_com_softc *ucom, struct termios *t)
314 {
315 	if ((t->c_ospeed < 300) || (t->c_ospeed > 115200))
316 		return (EINVAL);
317 	return (0);
318 }
319 
320 static void
321 uark_cfg_param(struct usb2_com_softc *ucom, struct termios *t)
322 {
323 	struct uark_softc *sc = ucom->sc_parent;
324 	uint32_t speed = t->c_ospeed;
325 	uint16_t data;
326 
327 	/*
328 	 * NOTE: When reverse computing the baud rate from the "data" all
329 	 * allowed baud rates are within 3% of the initial baud rate.
330 	 */
331 	data = (UARK_BAUD_REF + (speed / 2)) / speed;
332 
333 	uark_cfg_write(sc, 3, 0x83);
334 	uark_cfg_write(sc, 0, data & 0xFF);
335 	uark_cfg_write(sc, 1, data >> 8);
336 	uark_cfg_write(sc, 3, 0x03);
337 
338 	if (t->c_cflag & CSTOPB)
339 		data = UARK_STOP_BITS_2;
340 	else
341 		data = UARK_STOP_BITS_1;
342 
343 	if (t->c_cflag & PARENB) {
344 		if (t->c_cflag & PARODD)
345 			data |= UARK_PARITY_ODD;
346 		else
347 			data |= UARK_PARITY_EVEN;
348 	} else
349 		data |= UARK_PARITY_NONE;
350 
351 	switch (t->c_cflag & CSIZE) {
352 	case CS5:
353 		data |= UARK_SET_DATA_BITS(5);
354 		break;
355 	case CS6:
356 		data |= UARK_SET_DATA_BITS(6);
357 		break;
358 	case CS7:
359 		data |= UARK_SET_DATA_BITS(7);
360 		break;
361 	default:
362 	case CS8:
363 		data |= UARK_SET_DATA_BITS(8);
364 		break;
365 	}
366 	uark_cfg_write(sc, 3, 0x00);
367 	uark_cfg_write(sc, 3, data);
368 }
369 
370 static void
371 uark_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr)
372 {
373 	struct uark_softc *sc = ucom->sc_parent;
374 
375 	*lsr = sc->sc_lsr;
376 	*msr = sc->sc_msr;
377 }
378 
379 static void
380 uark_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff)
381 {
382 	struct uark_softc *sc = ucom->sc_parent;
383 
384 	DPRINTF("onoff=%d\n", onoff);
385 
386 	uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00);
387 }
388 
389 static void
390 uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value)
391 {
392 	struct usb2_device_request req;
393 	usb2_error_t err;
394 
395 	req.bmRequestType = UARK_WRITE;
396 	req.bRequest = UARK_REQUEST;
397 	USETW(req.wValue, value);
398 	USETW(req.wIndex, index);
399 	USETW(req.wLength, 0);
400 
401 	err = usb2_com_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
402 	    &req, NULL, 0, 1000);
403 	if (err) {
404 		DPRINTFN(0, "device request failed, err=%s "
405 		    "(ignored)\n", usb2_errstr(err));
406 	}
407 }
408