summaryrefslogtreecommitdiff
path: root/sys/dev/usb/usbdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/usbdi.c')
-rw-r--r--sys/dev/usb/usbdi.c1294
1 files changed, 0 insertions, 1294 deletions
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c
deleted file mode 100644
index e1ed20a0f8a7..000000000000
--- a/sys/dev/usb/usbdi.c
+++ /dev/null
@@ -1,1294 +0,0 @@
-/* $NetBSD: usbdi.c,v 1.20 1999/01/08 11:58:26 augustss Exp $ */
-/* FreeBSD $Id: usbdi.c,v 1.7 1999/01/07 23:31:42 n_hibma Exp $ */
-
-/*
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (augustss@carlstedt.se) at
- * Carlstedt Research & Technology.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#if defined(__NetBSD__)
-#include <sys/device.h>
-#else
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#endif
-#include <sys/malloc.h>
-#include <sys/proc.h>
-
-#include <dev/usb/usb.h>
-
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdivar.h>
-
-#if defined(__FreeBSD__)
-#include "usb_if.h"
-#endif
-
-#ifdef USB_DEBUG
-#define DPRINTF(x) if (usbdebug) printf x
-#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
-extern int usbdebug;
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n,x)
-#endif
-
-static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe));
-static usbd_status usbd_ar_iface __P((usbd_interface_handle iface));
-static void usbd_transfer_cb __P((usbd_request_handle reqh));
-static void usbd_sync_transfer_cb __P((usbd_request_handle reqh));
-static usbd_status usbd_do_transfer __P((usbd_request_handle reqh));
-void usbd_do_request_async_cb
- __P((usbd_request_handle, usbd_private_handle, usbd_status));
-
-static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests;
-
-#if defined(__FreeBSD__)
-#define USB_CDEV_MAJOR 108
-
-extern struct cdevsw usb_cdevsw;
-#endif
-
-usbd_status
-usbd_open_pipe(iface, address, flags, pipe)
- usbd_interface_handle iface;
- u_int8_t address;
- u_int8_t flags;
- usbd_pipe_handle *pipe;
-{
- usbd_pipe_handle p;
- struct usbd_endpoint *ep;
- usbd_status r;
- int i;
-
- if (iface->state != USBD_INTERFACE_ACTIVE)
- return (USBD_INTERFACE_NOT_ACTIVE);
- for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
- ep = &iface->endpoints[i];
- if (ep->edesc->bEndpointAddress == address)
- goto found;
- }
- return (USBD_BAD_ADDRESS);
- found:
- if ((flags & USBD_EXCLUSIVE_USE) &&
- ep->refcnt != 0)
- return (USBD_IN_USE);
- r = usbd_setup_pipe(iface->device, iface, ep, &p);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- LIST_INSERT_HEAD(&iface->pipes, p, next);
- *pipe = p;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
- usbd_interface_handle iface;
- u_int8_t address;
- u_int8_t flags;
- usbd_pipe_handle *pipe;
- usbd_private_handle priv;
- void *buffer;
- u_int32_t length;
- usbd_callback cb;
-{
- usbd_status r;
- usbd_request_handle reqh;
- usbd_pipe_handle ipipe;
-
- reqh = usbd_alloc_request();
- if (reqh == 0)
- return (USBD_NOMEM);
- r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe);
- if (r != USBD_NORMAL_COMPLETION)
- goto bad1;
- r = usbd_setup_request(reqh, ipipe, priv, buffer, length,
- USBD_XFER_IN | flags, USBD_NO_TIMEOUT, cb);
- if (r != USBD_NORMAL_COMPLETION)
- goto bad2;
- ipipe->intrreqh = reqh;
- r = usbd_transfer(reqh);
- *pipe = ipipe;
- if (r != USBD_IN_PROGRESS)
- goto bad3;
- return (USBD_NORMAL_COMPLETION);
-
- bad3:
- ipipe->intrreqh = 0;
- bad2:
- usbd_close_pipe(ipipe);
- bad1:
- usbd_free_request(reqh);
- return r;
-}
-
-usbd_status
-usbd_open_pipe_iso(iface, address, flags, pipe, priv, bufsize, nbuf, cb)
- usbd_interface_handle iface;
- u_int8_t address;
- u_int8_t flags;
- usbd_pipe_handle *pipe;
- usbd_private_handle priv;
- u_int32_t bufsize;
- u_int32_t nbuf;
- usbd_callback cb;
-{
- usbd_status r;
- usbd_pipe_handle p;
-
- r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &p);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- if (!p->methods->isobuf) {
- usbd_close_pipe(p);
- return (USBD_INVAL);
- }
- r = p->methods->isobuf(p, bufsize, nbuf);
- if (r != USBD_NORMAL_COMPLETION) {
- usbd_close_pipe(p);
- return (r);
- }
- *pipe = p;
- return r;
-}
-
-usbd_status
-usbd_close_pipe(pipe)
- usbd_pipe_handle pipe;
-{
- if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
- return (USBD_INTERFACE_NOT_ACTIVE);
- if (--pipe->refcnt != 0)
- return (USBD_NORMAL_COMPLETION);
- if (SIMPLEQ_FIRST(&pipe->queue) != 0)
- return (USBD_PENDING_REQUESTS);
- LIST_REMOVE(pipe, next);
- pipe->endpoint->refcnt--;
- pipe->methods->close(pipe);
- if (pipe->intrreqh)
- usbd_free_request(pipe->intrreqh);
- free(pipe, M_USB);
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_transfer(reqh)
- usbd_request_handle reqh;
-{
- reqh->xfercb = usbd_transfer_cb;
- return (usbd_do_transfer(reqh));
-}
-
-static usbd_status
-usbd_do_transfer(reqh)
- usbd_request_handle reqh;
-{
- usbd_pipe_handle pipe = reqh->pipe;
-
- DPRINTFN(10,("usbd_do_transfer: reqh=%p\n", reqh));
- reqh->done = 0;
- return (pipe->methods->transfer(reqh));
-}
-
-usbd_request_handle
-usbd_alloc_request()
-{
- usbd_request_handle reqh;
-
- reqh = SIMPLEQ_FIRST(&usbd_free_requests);
- if (reqh)
- SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);
- else
- reqh = malloc(sizeof(*reqh), M_USB, M_NOWAIT);
- if (!reqh)
- return (0);
- memset(reqh, 0, sizeof *reqh);
- return (reqh);
-}
-
-usbd_status
-usbd_free_request(reqh)
- usbd_request_handle reqh;
-{
- SIMPLEQ_INSERT_HEAD(&usbd_free_requests, reqh, next);
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
- usbd_request_handle reqh;
- usbd_pipe_handle pipe;
- usbd_private_handle priv;
- void *buffer;
- u_int32_t length;
- u_int16_t flags;
- u_int32_t timeout;
- void (*callback) __P((usbd_request_handle,
- usbd_private_handle,
- usbd_status));
-{
- reqh->pipe = pipe;
- reqh->isreq = 0;
- reqh->priv = priv;
- reqh->buffer = buffer;
- reqh->length = length;
- reqh->actlen = 0;
- reqh->flags = flags;
- reqh->callback = callback;
- reqh->status = USBD_NOT_STARTED;
- reqh->retries = 1;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_setup_device_request(reqh, req)
- usbd_request_handle reqh;
- usb_device_request_t *req;
-{
- reqh->isreq = 1;
- reqh->request = *req;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
- length, flags, callback)
- usbd_request_handle reqh;
- usbd_device_handle dev;
- usbd_private_handle priv;
- u_int32_t timeout;
- usb_device_request_t *req;
- void *buffer;
- u_int32_t length;
- u_int16_t flags;
- void (*callback) __P((usbd_request_handle,
- usbd_private_handle,
- usbd_status));
-{
- reqh->pipe = dev->default_pipe;
- reqh->priv = priv;
- reqh->buffer = buffer;
- reqh->length = length;
- reqh->actlen = 0;
- reqh->flags = flags;
- reqh->timeout = timeout;
- reqh->status = USBD_NOT_STARTED;
- reqh->callback = callback;
- reqh->request = *req;
- reqh->isreq = 1;
- reqh->retries = 1;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_set_request_timeout(reqh, timeout)
- usbd_request_handle reqh;
- u_int32_t timeout;
-{
- reqh->timeout = timeout;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_get_request_status(reqh, priv, buffer, count, status)
- usbd_request_handle reqh;
- usbd_private_handle *priv;
- void **buffer;
- u_int32_t *count;
- usbd_status *status;
-{
- *priv = reqh->priv;
- *buffer = reqh->buffer;
- *count = reqh->actlen;
- *status = reqh->status;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_request_device_data(reqh, req)
- usbd_request_handle reqh;
- usb_device_request_t *req;
-{
- if (!reqh->isreq)
- return (USBD_INVAL);
- *req = reqh->request;
- return (USBD_NORMAL_COMPLETION);
-}
-
-#if 0
-usb_descriptor_t *
-usbd_get_descriptor(iface, desc_type)
- usbd_interface_handle *iface;
- u_int8_t desc_type;
-XX
-#endif
-
-usb_config_descriptor_t *
-usbd_get_config_descriptor(dev)
- usbd_device_handle dev;
-{
- return (dev->cdesc);
-}
-
-usb_interface_descriptor_t *
-usbd_get_interface_descriptor(iface)
- usbd_interface_handle iface;
-{
- return (iface->idesc);
-}
-
-usb_device_descriptor_t *
-usbd_get_device_descriptor(dev)
- usbd_device_handle dev;
-{
- return (&dev->ddesc);
-}
-
-usb_endpoint_descriptor_t *
-usbd_interface2endpoint_descriptor(iface, index)
- usbd_interface_handle iface;
- u_int8_t index;
-{
- if (index >= iface->idesc->bNumEndpoints)
- return (0);
- return (iface->endpoints[index].edesc);
-}
-
-usbd_status
-usbd_set_configuration(dev, conf)
- usbd_device_handle dev;
- u_int8_t conf;
-{
- return usbd_set_config_no(dev, conf, 0);
-}
-
-usbd_status
-usbd_retry_request(reqh, retry_count)
- usbd_request_handle reqh;
- u_int32_t retry_count;
-{
- usbd_status r;
-
- r = usbd_set_pipe_state(reqh->pipe, USBD_PIPE_ACTIVE);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- reqh->retries = retry_count;
- return (usbd_transfer(reqh));
-}
-
-usbd_status
-usbd_abort_pipe(pipe)
- usbd_pipe_handle pipe;
-{
- usbd_status r;
- int s, st;
-
- if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
- return (USBD_INTERFACE_NOT_ACTIVE);
- s = splusb();
- st = pipe->state;
- r = usbd_ar_pipe(pipe);
- pipe->state = st;
- splx(s);
- return (r);
-}
-
-usbd_status
-usbd_abort_interface(iface)
- usbd_interface_handle iface;
-{
- usbd_status r;
- int s, st;
-
- s = splusb();
- st = iface->state;
- r = usbd_ar_iface(iface);
- iface->state = st;
- splx(s);
- return (r);
-}
-
-usbd_status
-usbd_reset_pipe(pipe)
- usbd_pipe_handle pipe;
-{
- usbd_status r;
- int s;
-
- if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
- return (USBD_INTERFACE_NOT_ACTIVE);
- s = splusb();
- r = usbd_ar_pipe(pipe);
- /* XXX anything else */
- pipe->state = USBD_PIPE_ACTIVE;
- splx(s);
- return (r);
-}
-
-usbd_status
-usbd_reset_interface(iface)
- usbd_interface_handle iface;
-{
- usbd_status r;
- int s;
-
- s = splusb();
- r = usbd_ar_iface(iface);
- /* XXX anything else */
- iface->state = USBD_INTERFACE_ACTIVE;
- splx(s);
- return (r);
-}
-
-usbd_status
-usbd_clear_endpoint_stall(pipe)
- usbd_pipe_handle pipe;
-{
- usbd_device_handle dev = pipe->device;
- usb_device_request_t req;
- usbd_status r;
-
- req.bmRequestType = UT_WRITE_ENDPOINT;
- req.bRequest = UR_CLEAR_FEATURE;
- USETW(req.wValue, UF_ENDPOINT_HALT);
- USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
- USETW(req.wLength, 0);
- r = usbd_do_request(dev, &req, 0);
-#if 0
-XXX should we do this?
- if (r == USBD_NORMAL_COMPLETION) {
- pipe->state = USBD_PIPE_ACTIVE;
- /* XXX activate pipe */
- }
-#endif
- return (r);
-}
-
-usbd_status
-usbd_clear_endpoint_stall_async(pipe)
- usbd_pipe_handle pipe;
-{
- usbd_device_handle dev = pipe->device;
- usb_device_request_t req;
- usbd_status r;
-
- req.bmRequestType = UT_WRITE_ENDPOINT;
- req.bRequest = UR_CLEAR_FEATURE;
- USETW(req.wValue, UF_ENDPOINT_HALT);
- USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
- USETW(req.wLength, 0);
- r = usbd_do_request_async(dev, &req, 0);
- return (r);
-}
-
-usbd_status
-usbd_set_pipe_state(pipe, state)
- usbd_pipe_handle pipe;
- usbd_pipe_state state;
-{
- int s;
- usbd_status r;
- usbd_request_handle reqh;
-
- if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
- return (USBD_INTERFACE_NOT_ACTIVE);
- if (state != USBD_PIPE_ACTIVE &&
- state != USBD_PIPE_STALLED &&
- state != USBD_PIPE_IDLE)
- return (USBD_INVAL);
- pipe->state = state;
- r = USBD_NORMAL_COMPLETION;
- if (state == USBD_PIPE_ACTIVE) {
- s = splusb();
- if (!pipe->running) {
- reqh = SIMPLEQ_FIRST(&pipe->queue);
- if (reqh != 0) {
- pipe->running = 1;
- splx(s);
- r = pipe->methods->start(reqh);
- } else
- splx(s);
- } else
- splx(s);
- }
- return (r);
-}
-
-usbd_status
-usbd_get_pipe_state(pipe, state, endpoint_state, request_count)
- usbd_pipe_handle pipe;
- usbd_pipe_state *state;
- u_int32_t *endpoint_state;
- u_int32_t *request_count;
-{
- int n;
- usbd_request_handle r;
-
- *state = pipe->state;
- *endpoint_state = pipe->endpoint->state;
- for (r = SIMPLEQ_FIRST(&pipe->queue), n = 0;
- r != 0;
- r = SIMPLEQ_NEXT(r, next), n++)
- ;
- *request_count = n;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_set_interface_state(iface, state)
- usbd_interface_handle iface;
- usbd_interface_state state;
-{
- int ps;
- usbd_pipe_handle p;
-
- if (state == USBD_INTERFACE_ACTIVE)
- ps = USBD_PIPE_ACTIVE;
- else if (state == USBD_INTERFACE_STALLED)
- ps = USBD_PIPE_STALLED;
- else if (state == USBD_INTERFACE_IDLE)
- ps = USBD_PIPE_IDLE;
- else
- return (USBD_INVAL);
- iface->state = USBD_INTERFACE_ACTIVE; /* to allow setting the pipe */
- for (p = LIST_FIRST(&iface->pipes); p != 0; p = LIST_NEXT(p, next))
- usbd_set_pipe_state(p, ps);
- iface->state = state;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_get_interface_state(iface, state)
- usbd_interface_handle iface;
- usbd_interface_state *state;
-{
- *state = iface->state;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_get_device_state(dev, state)
- usbd_device_handle dev;
- usbd_device_state *state;
-{
- *state = dev->state;
- return (USBD_NORMAL_COMPLETION);
-}
-
-#if 0
-usbd_status
-usbd_set_device_state(dev, state)
- usbd_device_handle dev;
- usbd_device_state state;
-X
-#endif
-
-usbd_status
-usbd_device_address(dev, address)
- usbd_device_handle dev;
- u_int8_t *address;
-{
- *address = dev->address;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_endpoint_address(pipe, address)
- usbd_pipe_handle pipe;
- u_int8_t *address;
-{
- *address = pipe->endpoint->edesc->bEndpointAddress;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_endpoint_count(iface, count)
- usbd_interface_handle iface;
- u_int8_t *count;
-{
- *count = iface->idesc->bNumEndpoints;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_interface_count(dev, count)
- usbd_device_handle dev;
- u_int8_t *count;
-{
- if (!dev->cdesc)
- return (USBD_NOT_CONFIGURED);
- *count = dev->cdesc->bNumInterface;
- return (USBD_NORMAL_COMPLETION);
-}
-
-#if 0
-u_int8_t
-usbd_bus_count()
-{
- return (usb_bus_count());
-}
-#endif
-
-#if defined(__NetBSD__)
-usbd_status
-usbd_get_bus_handle(index, bus)
- u_int8_t index;
- usbd_bus_handle *bus;
-{
- return (usb_get_bus_handle(index, bus));
-}
-#endif
-
-usbd_status
-usbd_get_root_hub(bus, dev)
- usbd_bus_handle bus;
- usbd_device_handle *dev;
-{
- *dev = bus->root_hub;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_port_count(dev, nports)
- usbd_device_handle dev;
- u_int8_t *nports;
-{
- if (dev->hub == 0)
- return (USBD_INVAL);
- *nports = dev->hub->hubdesc.bNbrPorts;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_hub2device_handle(dev, port, devp)
- usbd_device_handle dev;
- u_int8_t port;
- usbd_device_handle *devp;
-{
- if (dev->hub == 0 || port >= dev->hub->hubdesc.bNbrPorts ||
- dev->hub->ports[port].device == 0)
- return (USBD_INVAL);
- *devp = dev->hub->ports[port].device;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_request2pipe_handle(reqh, pipe)
- usbd_request_handle reqh;
- usbd_pipe_handle *pipe;
-{
- *pipe = reqh->pipe;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_pipe2interface_handle(pipe, iface)
- usbd_pipe_handle pipe;
- usbd_interface_handle *iface;
-{
- *iface = pipe->iface;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_interface2device_handle(iface, dev)
- usbd_interface_handle iface;
- usbd_device_handle *dev;
-{
- *dev = iface->device;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_device2bus_handle(dev, bus)
- usbd_device_handle dev;
- usbd_bus_handle *bus;
-{
- *bus = dev->bus;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_device2interface_handle(dev, ifaceno, iface)
- usbd_device_handle dev;
- u_int8_t ifaceno;
- usbd_interface_handle *iface;
-{
- if (!dev->cdesc)
- return (USBD_NOT_CONFIGURED);
- if (ifaceno >= dev->cdesc->bNumInterface)
- return (USBD_INVAL);
- *iface = &dev->ifaces[ifaceno];
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_set_interface_private_handle(iface, priv)
- usbd_interface_handle iface;
- usbd_private_handle priv;
-{
- iface->priv = priv;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_get_interface_private_handle(iface, priv)
- usbd_interface_handle iface;
- usbd_private_handle *priv;
-{
- *priv = iface->priv;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_reference_pipe(pipe)
- usbd_pipe_handle pipe;
-{
- pipe->refcnt++;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_status
-usbd_dereference_pipe(pipe)
- usbd_pipe_handle pipe;
-{
- pipe->refcnt--;
- return (USBD_NORMAL_COMPLETION);
-}
-
-usbd_lock_token
-usbd_lock()
-{
- return (splusb());
-}
-
-void
-usbd_unlock(tok)
- usbd_lock_token tok;
-{
- splx(tok);
-}
-
-/* XXXX use altno */
-usbd_status
-usbd_set_interface(iface, altidx)
- usbd_interface_handle iface;
- int altidx;
-{
- usb_device_request_t req;
- usbd_status r;
-
- if (LIST_FIRST(&iface->pipes) != 0)
- return (USBD_IN_USE);
-
- if (iface->endpoints)
- free(iface->endpoints, M_USB);
- iface->endpoints = 0;
- iface->idesc = 0;
- iface->state = USBD_INTERFACE_IDLE;
-
- r = usbd_fill_iface_data(iface->device, iface->index, altidx);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
-
- req.bmRequestType = UT_WRITE_INTERFACE;
- req.bRequest = UR_SET_INTERFACE;
- USETW(req.wValue, iface->idesc->bAlternateSetting);
- USETW(req.wIndex, iface->idesc->bInterfaceNumber);
- USETW(req.wLength, 0);
- return usbd_do_request(iface->device, &req, 0);
-}
-
-int
-usbd_get_no_alts(cdesc, ifaceno)
- usb_config_descriptor_t *cdesc;
- int ifaceno;
-{
- char *p = (char *)cdesc;
- char *end = p + UGETW(cdesc->wTotalLength);
- usb_interface_descriptor_t *d;
- int n;
-
- for (n = 0; p < end; p += d->bLength) {
- d = (usb_interface_descriptor_t *)p;
- if (p + d->bLength <= end &&
- d->bDescriptorType == UDESC_INTERFACE &&
- d->bInterfaceNumber == ifaceno)
- n++;
- }
- return (n);
-}
-
-int
-usbd_get_interface_altindex(iface)
- usbd_interface_handle iface;
-{
- return (iface->altindex);
-}
-
-usbd_status
-usbd_get_interface(iface, aiface)
- usbd_interface_handle iface;
- u_int8_t *aiface;
-{
- usb_device_request_t req;
-
- req.bmRequestType = UT_READ_INTERFACE;
- req.bRequest = UR_GET_INTERFACE;
- USETW(req.wValue, 0);
- USETW(req.wIndex, iface->idesc->bInterfaceNumber);
- USETW(req.wLength, 1);
- return usbd_do_request(iface->device, &req, aiface);
-}
-
-/*** Internal routines ***/
-
-/* Dequeue all pipe operations, called at splusb(). */
-static usbd_status
-usbd_ar_pipe(pipe)
- usbd_pipe_handle pipe;
-{
- usbd_request_handle reqh;
-
-#if 0
- for (;;) {
- reqh = SIMPLEQ_FIRST(&pipe->queue);
- if (reqh == 0)
- break;
- SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
- reqh->status = USBD_CANCELLED;
- if (reqh->callback)
- reqh->callback(reqh, reqh->priv, reqh->status);
- }
-#else
- while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) {
- pipe->methods->abort(reqh);
- SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
- }
-#endif
- return (USBD_NORMAL_COMPLETION);
-}
-
-/* Dequeue all interface operations, called at splusb(). */
-static usbd_status
-usbd_ar_iface(iface)
- usbd_interface_handle iface;
-{
- usbd_pipe_handle p;
- usbd_status r, ret = USBD_NORMAL_COMPLETION;
-
- for (p = LIST_FIRST(&iface->pipes); p != 0; p = LIST_NEXT(p, next)) {
- r = usbd_ar_pipe(p);
- if (r != USBD_NORMAL_COMPLETION)
- ret = r;
- }
- return (ret);
-}
-
-static int usbd_global_init_done = 0;
-
-void
-usbd_init()
-{
-#if defined(__FreeBSD__)
- dev_t dev;
-#endif
-
- if (!usbd_global_init_done) {
- usbd_global_init_done = 1;
- SIMPLEQ_INIT(&usbd_free_requests);
-
-#if defined(__FreeBSD__)
- dev = makedev(USB_CDEV_MAJOR, 0);
- cdevsw_add(&dev, &usb_cdevsw, NULL);
-#endif
- }
-}
-
-static void
-usbd_transfer_cb(reqh)
- usbd_request_handle reqh;
-{
- usbd_pipe_handle pipe = reqh->pipe;
-
- /* Count completed transfers. */
- ++pipe->device->bus->stats.requests
- [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
-
- /* XXX check retry count */
- reqh->done = 1;
- if (reqh->status == USBD_NORMAL_COMPLETION &&
- reqh->actlen < reqh->length &&
- !(reqh->flags & USBD_SHORT_XFER_OK)) {
- DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
- reqh->actlen, reqh->length));
- reqh->status = USBD_SHORT_XFER;
- }
- if (reqh->callback)
- reqh->callback(reqh, reqh->priv, reqh->status);
-}
-
-static void
-usbd_sync_transfer_cb(reqh)
- usbd_request_handle reqh;
-{
- usbd_transfer_cb(reqh);
- if (!reqh->pipe->device->bus->use_polling)
- wakeup(reqh);
-}
-
-/* Like usbd_transfer(), but waits for completion. */
-usbd_status
-usbd_sync_transfer(reqh)
- usbd_request_handle reqh;
-{
- usbd_status r;
- int s;
-
- reqh->xfercb = usbd_sync_transfer_cb;
- r = usbd_do_transfer(reqh);
- if (r != USBD_IN_PROGRESS)
- return (r);
- s = splusb();
- if (!reqh->done) {
- if (reqh->pipe->device->bus->use_polling)
- panic("usbd_sync_transfer: not done\n");
- tsleep(reqh, PRIBIO, "usbsyn", 0);
- }
- splx(s);
- return (reqh->status);
-}
-
-usbd_status
-usbd_do_request(dev, req, data)
- usbd_device_handle dev;
- usb_device_request_t *req;
- void *data;
-{
- return (usbd_do_request_flags(dev, req, data, 0, 0));
-}
-
-usbd_status
-usbd_do_request_flags(dev, req, data, flags, actlen)
- usbd_device_handle dev;
- usb_device_request_t *req;
- void *data;
- u_int16_t flags;
- int *actlen;
-{
- usbd_request_handle reqh;
- usbd_status r;
-
-#ifdef DIAGNOSTIC
- if (!curproc) {
- printf("usbd_do_request: not in process context\n");
- return (USBD_XXX);
- }
-#endif
-
- reqh = usbd_alloc_request();
- if (reqh == 0)
- return (USBD_NOMEM);
- r = usbd_setup_default_request(
- reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
- UGETW(req->wLength), flags, 0);
- if (r != USBD_NORMAL_COMPLETION)
- goto bad;
- r = usbd_sync_transfer(reqh);
-#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
- if (reqh->actlen > reqh->length)
- printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
- "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
- dev->address, reqh->request.bmRequestType,
- reqh->request.bRequest, UGETW(reqh->request.wValue),
- UGETW(reqh->request.wIndex),
- UGETW(reqh->request.wLength),
- reqh->length, reqh->actlen);
-#endif
- if (actlen)
- *actlen = reqh->actlen;
- if (r == USBD_STALLED) {
- /*
- * The control endpoint has stalled. Control endpoints
- * should not halt, but some may do so anyway so clear
- * any halt condition.
- */
- usb_device_request_t treq;
- usb_status_t status;
- u_int16_t s;
- usbd_status nr;
-
- treq.bmRequestType = UT_READ_ENDPOINT;
- treq.bRequest = UR_GET_STATUS;
- USETW(treq.wValue, 0);
- USETW(treq.wIndex, 0);
- USETW(treq.wLength, sizeof(usb_status_t));
- nr = usbd_setup_default_request(
- reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
- sizeof(usb_status_t), 0, 0);
- if (nr != USBD_NORMAL_COMPLETION)
- goto bad;
- nr = usbd_sync_transfer(reqh);
- if (nr != USBD_NORMAL_COMPLETION)
- goto bad;
- s = UGETW(status.wStatus);
- DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
- if (!(s & UES_HALT))
- goto bad;
- treq.bmRequestType = UT_WRITE_ENDPOINT;
- treq.bRequest = UR_CLEAR_FEATURE;
- USETW(treq.wValue, UF_ENDPOINT_HALT);
- USETW(treq.wIndex, 0);
- USETW(treq.wLength, 0);
- nr = usbd_setup_default_request(
- reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
- 0, 0, 0);
- if (nr != USBD_NORMAL_COMPLETION)
- goto bad;
- nr = usbd_sync_transfer(reqh);
- if (nr != USBD_NORMAL_COMPLETION)
- goto bad;
- }
-
- bad:
- usbd_free_request(reqh);
- return (r);
-}
-
-void
-usbd_do_request_async_cb(reqh, priv, status)
- usbd_request_handle reqh;
- usbd_private_handle priv;
- usbd_status status;
-{
-#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
- if (reqh->actlen > reqh->length)
- printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
- "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
- reqh->pipe->device->address,
- reqh->request.bmRequestType,
- reqh->request.bRequest, UGETW(reqh->request.wValue),
- UGETW(reqh->request.wIndex),
- UGETW(reqh->request.wLength),
- reqh->length, reqh->actlen);
-#endif
- usbd_free_request(reqh);
-}
-
-/*
- * Execute a request without waiting for completion.
- * Can be used from interrupt context.
- */
-usbd_status
-usbd_do_request_async(dev, req, data)
- usbd_device_handle dev;
- usb_device_request_t *req;
- void *data;
-{
- usbd_request_handle reqh;
- usbd_status r;
-
- reqh = usbd_alloc_request();
- if (reqh == 0)
- return (USBD_NOMEM);
- r = usbd_setup_default_request(
- reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
- UGETW(req->wLength), 0, usbd_do_request_async_cb);
- if (r != USBD_NORMAL_COMPLETION) {
- usbd_free_request(reqh);
- return (r);
- }
- r = usbd_transfer(reqh);
- if (r != USBD_IN_PROGRESS)
- return (r);
- return (USBD_NORMAL_COMPLETION);
-}
-
-struct usbd_quirks *
-usbd_get_quirks(dev)
- usbd_device_handle dev;
-{
- return (dev->quirks);
-}
-
-void
-usbd_set_disco(p, hdl, data)
- usbd_pipe_handle p;
- void (*hdl) __P((void *));
- void *data;
-{
- p->disco = hdl;
- p->discoarg = data;
-}
-
-/* XXX do periodic free() of free list */
-
-/*
- * Called from keyboard driver when in polling mode.
- */
-void
-usbd_dopoll(iface)
- usbd_interface_handle iface;
-{
- iface->device->bus->do_poll(iface->device->bus);
-}
-
-void
-usbd_set_polling(iface, on)
- usbd_interface_handle iface;
- int on;
-{
- iface->device->bus->use_polling = on;
-}
-
-
-usb_endpoint_descriptor_t *
-usbd_get_endpoint_descriptor(iface, address)
- usbd_interface_handle iface;
- u_int8_t address;
-{
- struct usbd_endpoint *ep;
- int i;
-
- for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
- ep = &iface->endpoints[i];
- if (ep->edesc->bEndpointAddress == address)
- return (iface->endpoints[i].edesc);
- }
- return (0);
-}
-
-#if defined(__FreeBSD__)
-void
-usbd_print_child(device_t parent, device_t child)
-{
- /*
- struct usb_softc *sc = device_get_softc(child);
- */
-
- printf(" at %s%d", device_get_name(parent), device_get_unit(parent));
-
- /* XXX How do we get to the usbd_device_handle???
- usbd_device_handle dev = invalidadosch;
-
- printf(" addr %d", dev->addr);
-
- if (bootverbose) {
- if (dev->lowspeed)
- printf(", lowspeed");
- if (dev->self_powered)
- printf(", self powered");
- else
- printf(", %dmA", dev->power);
- printf(", config %d", dev->config);
- }
- */
-}
-
-/* Reconfigure all the USB busses in the system. */
-int
-usbd_driver_load(module_t mod, int what, void *arg)
-{
- devclass_t usb_devclass = devclass_find("usb");
- devclass_t ugen_devclass = devclass_find("ugen");
- device_t *devlist;
- int devcount;
- int error;
-
- switch (what) {
- case MOD_LOAD:
- case MOD_UNLOAD:
- if (!usb_devclass)
- return 0; /* just ignore call */
-
- if (ugen_devclass) {
- /* detach devices from generic driver if possible */
- error = devclass_get_devices(ugen_devclass, &devlist,
- &devcount);
- if (!error)
- for (devcount--; devcount >= 0; devcount--)
- (void)DEVICE_DETACH(devlist[devcount]);
- }
-
- error = devclass_get_devices(usb_devclass, &devlist, &devcount);
- if (error)
- return 0; /* XXX maybe transient, or error? */
-
- for (devcount--; devcount >= 0; devcount--)
- USB_RECONFIGURE(devlist[devcount]);
-
- free(devlist, M_TEMP);
- return 0;
- }
-
- return 0; /* nothing to do by us */
-}
-
-/* Set the description of the device including a malloc and copy. */
-void
-usbd_device_set_desc(device_t device, char *devinfo)
-{
- size_t l;
- char *desc;
-
- if ( devinfo ) {
- l = strlen(devinfo);
- desc = malloc(l+1, M_USB, M_NOWAIT);
- if (desc)
- memcpy(desc, devinfo, l+1);
- } else
- desc = NULL;
-
- device_set_desc(device, desc);
-}
-
-char *
-usbd_devname(bdevice *bdev)
-{
- static char buf[20];
- /* XXX a static buffer is not exactly a good idea, but the only
- * thing that goes wrong is the string that is being printed
- */
-
- sprintf(buf, "%s%d", device_get_name(*bdev), device_get_unit(*bdev));
- return (buf);
-}
-
-#endif