LCOV - code coverage report
Current view: top level - dev/usb - uark.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 110 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13