The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

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

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: udsbr.c,v 1.7 2002/07/11 21:14:27 augustss Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Lennart Augustsson (lennart@augustsson.net).
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Driver for the D-Link DSB-R100 FM radio.
   41  * I apologize for the magic hex constants, but this is what happens
   42  * when you have to reverse engineer the driver.
   43  * Parts of the code borrowed from Linux and parts from Warner Losh's
   44  * FreeBSD driver.
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 __KERNEL_RCSID(0, "$NetBSD: udsbr.c,v 1.7 2002/07/11 21:14:27 augustss Exp $");
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/kernel.h>
   53 #include <sys/device.h>
   54 
   55 #include <sys/radioio.h>
   56 #include <dev/radio_if.h>
   57 
   58 #include <dev/usb/usb.h>
   59 #include <dev/usb/usbdi.h>
   60 #include <dev/usb/usbdi_util.h>
   61 
   62 #include <dev/usb/usbdevs.h>
   63 
   64 #ifdef UDSBR_DEBUG
   65 #define DPRINTF(x)      if (udsbrdebug) logprintf x
   66 #define DPRINTFN(n,x)   if (udsbrdebug>(n)) logprintf x
   67 int     udsbrdebug = 0;
   68 #else
   69 #define DPRINTF(x)
   70 #define DPRINTFN(n,x)
   71 #endif
   72 
   73 #define UDSBR_CONFIG_NO         1
   74 
   75 Static  int     udsbr_get_info(void *, struct radio_info *);
   76 Static  int     udsbr_set_info(void *, struct radio_info *);
   77 
   78 struct radio_hw_if udsbr_hw_if = {
   79         NULL, /* open */
   80         NULL, /* close */
   81         udsbr_get_info,
   82         udsbr_set_info,
   83         NULL
   84 };
   85 
   86 struct udsbr_softc {
   87         USBBASEDEVICE           sc_dev;
   88         usbd_device_handle      sc_udev;
   89 
   90         char                    sc_mute;
   91         char                    sc_vol;
   92         u_int32_t               sc_freq;
   93 
   94         struct device           *sc_child;
   95 
   96         char                    sc_dying;
   97 };
   98 
   99 Static  int     udsbr_req(struct udsbr_softc *sc, int ureq, int value,
  100                           int index);
  101 Static  void    udsbr_start(struct udsbr_softc *sc);
  102 Static  void    udsbr_stop(struct udsbr_softc *sc);
  103 Static  void    udsbr_setfreq(struct udsbr_softc *sc, int freq);
  104 Static  int     udsbr_status(struct udsbr_softc *sc);
  105 
  106 USB_DECLARE_DRIVER(udsbr);
  107 
  108 USB_MATCH(udsbr)
  109 {
  110         USB_MATCH_START(udsbr, uaa);
  111 
  112         DPRINTFN(50,("udsbr_match\n"));
  113 
  114         if (uaa->iface != NULL)
  115                 return (UMATCH_NONE);
  116 
  117         if (uaa->vendor != USB_VENDOR_CYPRESS ||
  118             uaa->product != USB_PRODUCT_CYPRESS_FMRADIO)
  119                 return (UMATCH_NONE);
  120         return (UMATCH_VENDOR_PRODUCT);
  121 }
  122 
  123 USB_ATTACH(udsbr)
  124 {
  125         USB_ATTACH_START(udsbr, sc, uaa);
  126         usbd_device_handle      dev = uaa->device;
  127         char                    devinfo[1024];
  128         usbd_status             err;
  129 
  130         DPRINTFN(10,("udsbr_attach: sc=%p\n", sc));
  131 
  132         usbd_devinfo(dev, 0, devinfo);
  133         USB_ATTACH_SETUP;
  134         printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
  135 
  136         err = usbd_set_config_no(dev, UDSBR_CONFIG_NO, 1);
  137         if (err) {
  138                 printf("%s: setting config no failed\n",
  139                     USBDEVNAME(sc->sc_dev));
  140                 USB_ATTACH_ERROR_RETURN;
  141         }
  142 
  143         sc->sc_udev = dev;
  144 
  145         DPRINTFN(10, ("udsbr_attach: %p\n", sc->sc_udev));
  146 
  147         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  148                            USBDEV(sc->sc_dev));
  149 
  150         sc->sc_child = radio_attach_mi(&udsbr_hw_if, sc, USBDEV(sc->sc_dev));
  151 
  152         USB_ATTACH_SUCCESS_RETURN;
  153 }
  154 
  155 USB_DETACH(udsbr)
  156 {
  157         USB_DETACH_START(udsbr, sc);
  158         int rv = 0;
  159 
  160         if (sc->sc_child != NULL)
  161                 rv = config_detach(sc->sc_child, flags);
  162 
  163         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  164                            USBDEV(sc->sc_dev));
  165 
  166         return (rv);
  167 }
  168 
  169 int
  170 udsbr_activate(device_ptr_t self, enum devact act)
  171 {
  172         struct udsbr_softc *sc = (struct udsbr_softc *)self;
  173         int rv = 0;
  174 
  175         switch (act) {
  176         case DVACT_ACTIVATE:
  177                 return (EOPNOTSUPP);
  178                 break;
  179 
  180         case DVACT_DEACTIVATE:
  181                 sc->sc_dying = 1;
  182                 if (sc->sc_child != NULL)
  183                         rv = config_deactivate(sc->sc_child);
  184                 break;
  185         }
  186         return (rv);
  187 }
  188 
  189 int
  190 udsbr_req(struct udsbr_softc *sc, int ureq, int value, int index)
  191 {
  192         usb_device_request_t req;
  193         usbd_status err;
  194         u_char data;
  195 
  196         DPRINTFN(1,("udsbr_req: ureq=0x%02x value=0x%04x index=0x%04x\n",
  197                     ureq, value, index));
  198         req.bmRequestType = UT_READ_VENDOR_DEVICE;
  199         req.bRequest = ureq;
  200         USETW(req.wValue, value);
  201         USETW(req.wIndex, index);
  202         USETW(req.wLength, 1);
  203         err = usbd_do_request(sc->sc_udev, &req, &data);
  204         if (err) {
  205                 printf("%s: request failed err=%d\n", USBDEVNAME(sc->sc_dev),
  206                        err);
  207         }
  208         return !(data & 1);
  209 }
  210 
  211 void
  212 udsbr_start(struct udsbr_softc *sc)
  213 {
  214         (void)udsbr_req(sc, 0x00, 0x0000, 0x00c7);
  215         (void)udsbr_req(sc, 0x02, 0x0001, 0x0000);
  216 }
  217 
  218 void
  219 udsbr_stop(struct udsbr_softc *sc)
  220 {
  221         (void)udsbr_req(sc, 0x00, 0x0016, 0x001c);
  222         (void)udsbr_req(sc, 0x02, 0x0000, 0x0000);
  223 }
  224 
  225 void
  226 udsbr_setfreq(struct udsbr_softc *sc, int freq)
  227 {
  228         DPRINTF(("udsbr_setfreq: setfreq=%d\n", freq));
  229         /*
  230          * Freq now is in Hz.  We need to convert it to the frequency
  231          * that the radio wants.  This frequency is 10.7MHz above
  232          * the actual frequency.  We then need to convert to
  233          * units of 12.5kHz.  We add one to the IFM to make rounding
  234          * easier.
  235          */
  236         freq = (freq * 1000 + 10700001) / 12500;
  237         (void)udsbr_req(sc, 0x01, (freq >> 8) & 0xff, freq & 0xff);
  238         (void)udsbr_req(sc, 0x00, 0x0096, 0x00b7);
  239         usbd_delay_ms(sc->sc_udev, 240); /* wait for signal to settle */
  240 }
  241 
  242 int
  243 udsbr_status(struct udsbr_softc *sc)
  244 {
  245         return (udsbr_req(sc, 0x00, 0x0000, 0x0024));
  246 }
  247 
  248 
  249 int
  250 udsbr_get_info(void *v, struct radio_info *ri)
  251 {
  252         struct udsbr_softc *sc = v;
  253 
  254         ri->mute = sc->sc_mute;
  255         ri->volume = sc->sc_vol ? 255 : 0;
  256         ri->caps = RADIO_CAPS_DETECT_STEREO;
  257         ri->rfreq = 0;
  258         ri->lock = 0;
  259         ri->freq = sc->sc_freq;
  260         ri->info = udsbr_status(sc) ? RADIO_INFO_STEREO : 0;
  261 
  262         return (0);
  263 }
  264 
  265 int
  266 udsbr_set_info(void *v, struct radio_info *ri)
  267 {
  268         struct udsbr_softc *sc = v;
  269 
  270         sc->sc_mute = ri->mute != 0;
  271         sc->sc_vol = ri->volume != 0;
  272         sc->sc_freq = ri->freq;
  273         udsbr_setfreq(sc, sc->sc_freq);
  274 
  275         if (sc->sc_mute || sc->sc_vol == 0)
  276                 udsbr_stop(sc);
  277         else
  278                 udsbr_start(sc);
  279 
  280         return (0);
  281 }

Cache object: 847f36eaacac11709b564c8426eb3782


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


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