[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/uark.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  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: src/sys/dev/usb/uark.c,v 1.9 2008/10/09 20:51:25 n_hibma Exp $
 19  */
 20 
 21 #include <sys/param.h>
 22 #include <sys/systm.h>
 23 #include <sys/kernel.h>
 24 #include <sys/malloc.h>
 25 #include <sys/module.h>
 26 #include <sys/bus.h>
 27 #include <sys/ioccom.h>
 28 #include <sys/fcntl.h>
 29 #include <sys/conf.h>
 30 #include <sys/tty.h>
 31 #include <sys/file.h>
 32 #include <sys/selinfo.h>
 33 #include <sys/sysctl.h>
 34 
 35 #include <dev/usb/usb.h>
 36 #include <dev/usb/usbdi.h>
 37 #include <dev/usb/usbdi_util.h>
 38 #include "usbdevs.h"
 39 
 40 #include <dev/usb/ucomvar.h>
 41 
 42 #ifdef UARK_DEBUG
 43 #define DPRINTFN(n, x)  do {    \
 44         if (uarkdebug > (n))    \
 45                 printf x;       \
 46 } while (0)
 47 int     uarkebug = 0;
 48 #else
 49 #define DPRINTFN(n, x)
 50 #endif
 51 #define DPRINTF(x) DPRINTFN(0, x)
 52 
 53 #define UARKBUFSZ               256
 54 #define UARK_CONFIG_NO          0
 55 #define UARK_IFACE_NO           0
 56 
 57 #define UARK_SET_DATA_BITS(x)   (x - 5)
 58 
 59 #define UARK_PARITY_NONE        0x00
 60 #define UARK_PARITY_ODD         0x08
 61 #define UARK_PARITY_EVEN        0x18
 62 
 63 #define UARK_STOP_BITS_1        0x00
 64 #define UARK_STOP_BITS_2        0x04
 65 
 66 #define UARK_BAUD_REF           3000000
 67 
 68 #define UARK_WRITE              0x40
 69 #define UARK_READ               0xc0
 70 
 71 #define UARK_REQUEST            0xfe
 72 
 73 #define UARK_CONFIG_INDEX       0
 74 #define UARK_IFACE_INDEX        0
 75 
 76 struct uark_softc {
 77         struct ucom_softc       sc_ucom;
 78         usbd_interface_handle   sc_iface;
 79 
 80         u_char                  sc_msr;
 81         u_char                  sc_lsr;
 82 };
 83 
 84 static void     uark_get_status(void *, int portno, u_char *lsr, u_char *msr);
 85 static void     uark_set(void *, int, int, int);
 86 static int      uark_param(void *, int, struct termios *);
 87 static void     uark_break(void *, int, int);
 88 static int      uark_cmd(struct uark_softc *, uint16_t, uint16_t);
 89 
 90 struct ucom_callback uark_callback = {
 91         uark_get_status,
 92         uark_set,
 93         uark_param,
 94         NULL,
 95         NULL,
 96         NULL,
 97         NULL,
 98         NULL,
 99 };
100 
101 static const struct usb_devno uark_devs[] = {
102         { USB_VENDOR_ARKMICRO,          USB_PRODUCT_ARKMICRO_ARK3116 }
103 };
104 
105 static int
106 uark_match(device_t self)
107 {
108         struct usb_attach_arg *uaa = device_get_ivars(self);
109 
110         if (uaa->iface != NULL)
111                 return (UMATCH_NONE);
112 
113         return (usb_lookup(uark_devs, uaa->vendor, uaa->product) != NULL) ?
114             UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
115 }
116 
117 static int
118 uark_attach(device_t self)
119 {
120         struct uark_softc *sc = device_get_softc(self);
121         struct usb_attach_arg *uaa = device_get_ivars(self);
122         usbd_device_handle dev = uaa->device;
123         usbd_interface_handle iface;
124         usb_interface_descriptor_t *id;
125         usb_endpoint_descriptor_t *ed;
126         usbd_status error;
127         int i;
128         struct ucom_softc *ucom = &sc->sc_ucom;
129 
130         ucom->sc_dev = self;
131         ucom->sc_udev = dev;
132 
133         if (uaa->iface == NULL) {
134                 /* Move the device into the configured state. */
135                 error = usbd_set_config_index(dev, UARK_CONFIG_INDEX, 1);
136                 if (error) {
137                         device_printf(ucom->sc_dev,
138                             "failed to set configuration, err=%s\n",
139                             usbd_errstr(error));
140                         goto bad;
141                 }
142                 error =
143                     usbd_device2interface_handle(dev, UARK_IFACE_INDEX, &iface);
144                 if (error) {
145                         device_printf(ucom->sc_dev,
146                             "failed to get interface, err=%s\n",
147                             usbd_errstr(error));
148                         goto bad;
149                 }
150         } else
151                 iface = uaa->iface;
152 
153         id = usbd_get_interface_descriptor(iface);
154         ucom->sc_iface = iface;
155 
156         ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
157         for (i = 0; i < id->bNumEndpoints; i++) {
158                 ed = usbd_interface2endpoint_descriptor(iface, i);
159                 if (ed == NULL) {
160                         device_printf(ucom->sc_dev,
161                             "could not read endpoint descriptor\n");
162                         goto bad;
163                 }
164                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
165                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
166                         ucom->sc_bulkin_no = ed->bEndpointAddress;
167                 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
168                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
169                         ucom->sc_bulkout_no = ed->bEndpointAddress;
170         }
171         if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) {
172                 device_printf(ucom->sc_dev, "missing endpoint\n");
173                 goto bad;
174         }
175         ucom->sc_parent = sc;
176         ucom->sc_ibufsize = UARKBUFSZ;
177         ucom->sc_obufsize = UARKBUFSZ;
178         ucom->sc_ibufsizepad = UARKBUFSZ;
179         ucom->sc_opkthdrlen = 0;
180 
181         ucom->sc_callback = &uark_callback;
182 
183         DPRINTF(("uark: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no));
184         ucom_attach(&sc->sc_ucom);
185         return 0;
186 
187 bad:
188         DPRINTF(("uark_attach: ATTACH ERROR\n"));
189         ucom->sc_dying = 1;
190         return ENXIO;
191 }
192 
193 static int
194 uark_detach(device_t self)
195 {
196         struct uark_softc *sc = device_get_softc(self);
197         int rv = 0;
198 
199         DPRINTF(("uark_detach: sc=%p\n", sc));
200         sc->sc_ucom.sc_dying = 1;
201         rv = ucom_detach(&sc->sc_ucom);
202 
203         return (rv);
204 }
205 
206 static void
207 uark_set(void *vsc, int portno, int reg, int onoff)
208 {
209         struct uark_softc *sc = vsc;
210 
211         switch (reg) {
212         case UCOM_SET_BREAK:
213                 uark_break(sc, portno, onoff);
214                 return;
215                 /* NOTREACHED */
216         case UCOM_SET_DTR:
217         case UCOM_SET_RTS:
218         default:
219                 return;
220                 /* NOTREACHED */
221         }
222 }
223 
224 static int
225 uark_param(void *vsc, int portno, struct termios *t)
226 {
227         struct uark_softc *sc = (struct uark_softc *)vsc;
228         int data, divisor;
229         speed_t speed = t->c_ospeed;
230 
231         if (speed < 300 || speed > 115200)
232                 return (EINVAL);
233         divisor = (UARK_BAUD_REF + speed / 2) / speed;
234         /* Check that we're within 3% of the requested rate. */
235         if (speed * divisor < UARK_BAUD_REF * 100 / 103 ||
236             speed * divisor > UARK_BAUD_REF * 100 / 97)
237                 return (EINVAL);
238         uark_cmd(sc, 3, 0x83);
239         uark_cmd(sc, 0, divisor & 0xFF);
240         uark_cmd(sc, 1, divisor >> 8);
241         uark_cmd(sc, 3, 0x03);
242 
243         if (ISSET(t->c_cflag, CSTOPB))
244                 data = UARK_STOP_BITS_2;
245         else
246                 data = UARK_STOP_BITS_1;
247 
248         if (ISSET(t->c_cflag, PARENB)) {
249                 if (ISSET(t->c_cflag, PARODD))
250                         data |= UARK_PARITY_ODD;
251                 else
252                         data |= UARK_PARITY_EVEN;
253         } else
254                 data |= UARK_PARITY_NONE;
255 
256         switch (ISSET(t->c_cflag, CSIZE)) {
257         case CS5:
258                 data |= UARK_SET_DATA_BITS(5);
259                 break;
260         case CS6:
261                 data |= UARK_SET_DATA_BITS(6);
262                 break;
263         case CS7:
264                 data |= UARK_SET_DATA_BITS(7);
265                 break;
266         case CS8:
267                 data |= UARK_SET_DATA_BITS(8);
268                 break;
269         }
270         uark_cmd(sc, 3, 0x00);
271         uark_cmd(sc, 3, data);
272 
273         return (0);
274 }
275 
276 void
277 uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr)
278 {
279         struct uark_softc *sc = vsc;
280 
281         if (msr != NULL)
282                 *msr = sc->sc_msr;
283         if (lsr != NULL)
284                 *lsr = sc->sc_lsr;
285 }
286 
287 void
288 uark_break(void *vsc, int portno, int onoff)
289 {
290 #ifdef UARK_DEBUG
291         struct uark_softc *sc = vsc;
292 
293         device_printf(sc->sc_dev, "%s: break %s!\n", onoff ? "on" : "off");
294         if (onoff)
295                 /* break on */
296                 uark_cmd(sc, 4, 0x01);
297         else
298                 uark_cmd(sc, 4, 0x00);
299 #endif
300 }
301 
302 int
303 uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value)
304 {
305         usb_device_request_t req;
306         usbd_status err;
307         struct ucom_softc *ucom = &sc->sc_ucom;
308 
309         req.bmRequestType = UARK_WRITE;
310         req.bRequest = UARK_REQUEST;
311         USETW(req.wValue, value);
312         USETW(req.wIndex, index);
313         USETW(req.wLength, 0);
314         err = usbd_do_request(ucom->sc_udev, &req, NULL);
315 
316         if (err)
317                 return (EIO);
318 
319         return (0);
320 }
321 
322 static device_method_t uark_methods[] = {
323         /* Device interface */
324         DEVMETHOD(device_probe, uark_match),
325         DEVMETHOD(device_attach, uark_attach),
326         DEVMETHOD(device_detach, uark_detach),
327 
328         { 0, 0 }
329 };
330 
331 static driver_t uark_driver = {
332         "ucom",
333         uark_methods,
334         sizeof (struct uark_softc)
335 };
336 
337 DRIVER_MODULE(uark, uhub, uark_driver, ucom_devclass, usbd_driver_load, 0);
338 MODULE_DEPEND(uark, usb, 1, 1, 1);
339 MODULE_DEPEND(uark, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
340 

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.