Annotation of sys/dev/usb/uark.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: uark.c,v 1.10 2007/06/14 10:11:15 mbalmer 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:
19: #include <sys/param.h>
20: #include <sys/systm.h>
21: #include <sys/kernel.h>
22: #include <sys/conf.h>
23: #include <sys/tty.h>
24: #include <sys/device.h>
25:
26: #include <dev/usb/usb.h>
27: #include <dev/usb/usbdi.h>
28: #include <dev/usb/usbdi_util.h>
29: #include <dev/usb/usbdevs.h>
30:
31: #include <dev/usb/usbdevs.h>
32: #include <dev/usb/ucomvar.h>
33:
34: #ifdef UARK_DEBUG
35: #define DPRINTFN(n, x) do { if (uarkdebug > (n)) printf x; } while (0)
36: int uarkebug = 0;
37: #else
38: #define DPRINTFN(n, x)
39: #endif
40: #define DPRINTF(x) DPRINTFN(0, x)
41:
42: #define UARKBUFSZ 256
43: #define UARK_CONFIG_NO 0
44: #define UARK_IFACE_NO 0
45:
46: #define UARK_SET_DATA_BITS(x) (x - 5)
47:
48: #define UARK_PARITY_NONE 0x00
49: #define UARK_PARITY_ODD 0x08
50: #define UARK_PARITY_EVEN 0x18
51:
52: #define UARK_STOP_BITS_1 0x00
53: #define UARK_STOP_BITS_2 0x04
54:
55: #define UARK_BAUD_REF 3000000
56:
57: #define UARK_WRITE 0x40
58: #define UARK_READ 0xc0
59:
60: #define UARK_REQUEST 0xfe
61:
62: struct uark_softc {
63: struct device sc_dev;
64: usbd_device_handle sc_udev;
65: usbd_interface_handle sc_iface;
66: struct device *sc_subdev;
67:
68: u_char sc_msr;
69: u_char sc_lsr;
70:
71: u_char sc_dying;
72: };
73:
74: void uark_get_status(void *, int portno, u_char *lsr, u_char *msr);
75: void uark_set(void *, int, int, int);
76: int uark_param(void *, int, struct termios *);
77: int uark_open(void *sc, int);
78: void uark_break(void *, int, int);
79: int uark_cmd(struct uark_softc *, uint16_t, uint16_t);
80:
81: struct ucom_methods uark_methods = {
82: uark_get_status,
83: uark_set,
84: uark_param,
85: NULL,
86: NULL,
87: NULL,
88: NULL,
89: NULL,
90: };
91:
92: static const struct usb_devno uark_devs[] = {
93: { USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116 }
94: };
95:
96: int uark_match(struct device *, void *, void *);
97: void uark_attach(struct device *, struct device *, void *);
98: int uark_detach(struct device *, int);
99: int uark_activate(struct device *, enum devact);
100:
101: struct cfdriver uark_cd = {
102: NULL, "uark", DV_DULL
103: };
104:
105: const struct cfattach uark_ca = {
106: sizeof(struct uark_softc),
107: uark_match,
108: uark_attach,
109: uark_detach,
110: uark_activate,
111: };
112:
113: int
114: uark_match(struct device *parent, void *match, void *aux)
115: {
116: struct usb_attach_arg *uaa = aux;
117:
118: if (uaa->iface != NULL)
119: return UMATCH_NONE;
120:
121: return (usb_lookup(uark_devs, uaa->vendor, uaa->product) != NULL) ?
122: UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
123: }
124:
125: void
126: uark_attach(struct device *parent, struct device *self, void *aux)
127: {
128: struct uark_softc *sc = (struct uark_softc *)self;
129: struct usb_attach_arg *uaa = aux;
130: struct ucom_attach_args uca;
131: usb_interface_descriptor_t *id;
132: usb_endpoint_descriptor_t *ed;
133: usbd_status error;
134: char *devinfop;
135: int i;
136:
137: bzero(&uca, sizeof(uca));
138: sc->sc_udev = uaa->device;
139: devinfop = usbd_devinfo_alloc(uaa->device, 0);
140: printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
141: usbd_devinfo_free(devinfop);
142:
143: if (usbd_set_config_index(sc->sc_udev, UARK_CONFIG_NO, 1) != 0) {
144: printf("%s: could not set configuration no\n",
145: sc->sc_dev.dv_xname);
146: sc->sc_dying = 1;
147: return;
148: }
149:
150: /* get the first interface handle */
151: error = usbd_device2interface_handle(sc->sc_udev, UARK_IFACE_NO,
152: &sc->sc_iface);
153: if (error != 0) {
154: printf("%s: could not get interface handle\n",
155: sc->sc_dev.dv_xname);
156: sc->sc_dying = 1;
157: return;
158: }
159:
160: id = usbd_get_interface_descriptor(sc->sc_iface);
161:
162: uca.bulkin = uca.bulkout = -1;
163: for (i = 0; i < id->bNumEndpoints; i++) {
164: ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
165: if (ed == NULL) {
166: printf("%s: no endpoint descriptor found for %d\n",
167: sc->sc_dev.dv_xname, i);
168: sc->sc_dying = 1;
169: return;
170: }
171:
172: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
173: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
174: uca.bulkin = ed->bEndpointAddress;
175: else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
176: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
177: uca.bulkout = ed->bEndpointAddress;
178: }
179:
180: if (uca.bulkin == -1 || uca.bulkout == -1) {
181: printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
182: sc->sc_dying = 1;
183: return;
184: }
185:
186: uca.ibufsize = UARKBUFSZ;
187: uca.obufsize = UARKBUFSZ;
188: uca.ibufsizepad = UARKBUFSZ;
189: uca.opkthdrlen = 0;
190: uca.device = sc->sc_udev;
191: uca.iface = sc->sc_iface;
192: uca.methods = &uark_methods;
193: uca.arg = sc;
194: uca.info = NULL;
195:
196: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
197: &sc->sc_dev);
198:
199: sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
200: }
201:
202: int
203: uark_detach(struct device *self, int flags)
204: {
205: struct uark_softc *sc = (struct uark_softc *)self;
206: int rv = 0;
207:
208: sc->sc_dying = 1;
209: if (sc->sc_subdev != NULL) {
210: rv = config_detach(sc->sc_subdev, flags);
211: sc->sc_subdev = NULL;
212: }
213:
214: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
215: &sc->sc_dev);
216:
217: return (rv);
218: }
219:
220: int
221: uark_activate(struct device *self, enum devact act)
222: {
223: struct uark_softc *sc = (struct uark_softc *)self;
224: int rv = 0;
225:
226: switch (act) {
227: case DVACT_ACTIVATE:
228: break;
229:
230: case DVACT_DEACTIVATE:
231: if (sc->sc_subdev != NULL)
232: rv = config_deactivate(sc->sc_subdev);
233: sc->sc_dying = 1;
234: break;
235: }
236: return (rv);
237: }
238:
239: void
240: uark_set(void *vsc, int portno, int reg, int onoff)
241: {
242: struct uark_softc *sc = vsc;
243:
244: switch (reg) {
245: case UCOM_SET_BREAK:
246: uark_break(sc, portno, onoff);
247: return;
248: case UCOM_SET_DTR:
249: case UCOM_SET_RTS:
250: default:
251: return;
252: }
253: }
254:
255: int
256: uark_param(void *vsc, int portno, struct termios *t)
257: {
258: struct uark_softc *sc = (struct uark_softc *)vsc;
259: int data;
260:
261: switch (t->c_ospeed) {
262: case 300:
263: case 600:
264: case 1200:
265: case 1800:
266: case 2400:
267: case 4800:
268: case 9600:
269: case 19200:
270: case 38400:
271: case 57600:
272: case 115200:
273: uark_cmd(sc, 3, 0x83);
274: uark_cmd(sc, 0, (UARK_BAUD_REF / t->c_ospeed) & 0xFF);
275: uark_cmd(sc, 1, (UARK_BAUD_REF / t->c_ospeed) >> 8);
276: uark_cmd(sc, 3, 0x03);
277: break;
278: default:
279: return (EINVAL);
280: }
281:
282: if (ISSET(t->c_cflag, CSTOPB))
283: data = UARK_STOP_BITS_2;
284: else
285: data = UARK_STOP_BITS_1;
286:
287: if (ISSET(t->c_cflag, PARENB)) {
288: if (ISSET(t->c_cflag, PARODD))
289: data |= UARK_PARITY_ODD;
290: else
291: data |= UARK_PARITY_EVEN;
292: } else
293: data |= UARK_PARITY_NONE;
294:
295: switch (ISSET(t->c_cflag, CSIZE)) {
296: case CS5:
297: data |= UARK_SET_DATA_BITS(5);
298: break;
299: case CS6:
300: data |= UARK_SET_DATA_BITS(6);
301: break;
302: case CS7:
303: data |= UARK_SET_DATA_BITS(7);
304: break;
305: case CS8:
306: data |= UARK_SET_DATA_BITS(8);
307: break;
308: }
309:
310: uark_cmd(sc, 3, 0x00);
311: uark_cmd(sc, 3, data);
312:
313: #if 0
314: /* XXX flow control */
315: if (ISSET(t->c_cflag, CRTSCTS))
316: /* rts/cts flow ctl */
317: } else if (ISSET(t->c_iflag, IXON|IXOFF)) {
318: /* xon/xoff flow ctl */
319: } else {
320: /* disable flow ctl */
321: }
322: #endif
323:
324: return (0);
325: }
326:
327: void
328: uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr)
329: {
330: struct uark_softc *sc = vsc;
331:
332: if (msr != NULL)
333: *msr = sc->sc_msr;
334: if (lsr != NULL)
335: *lsr = sc->sc_lsr;
336: }
337:
338: void
339: uark_break(void *vsc, int portno, int onoff)
340: {
341: #ifdef UARK_DEBUG
342: struct uark_softc *sc = vsc;
343:
344: printf("%s: break %s!\n", sc->sc_dev.dv_xname,
345: onoff ? "on" : "off");
346:
347: if (onoff)
348: /* break on */
349: uark_cmd(sc, 4, 0x01);
350: else
351: uark_cmd(sc, 4, 0x00);
352: #endif
353: }
354:
355: int
356: uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value)
357: {
358: usb_device_request_t req;
359: usbd_status err;
360:
361: req.bmRequestType = UARK_WRITE;
362: req.bRequest = UARK_REQUEST;
363: USETW(req.wValue, value);
364: USETW(req.wIndex, index);
365: USETW(req.wLength, 0);
366: err = usbd_do_request(sc->sc_udev, &req, NULL);
367:
368: if (err)
369: return (EIO);
370:
371: return (0);
372: }
CVSweb