usbdi.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,320 行 · 第 1/2 页
C
1,320 行
/* $NetBSD: usbdi.c,v 1.20 1999/01/08 11:58:26 augustss Exp $ *//* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.8.2.1 1999/05/08 23:04:58 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) logprintf x#define DPRINTFN(n,x) if (usbdebug>(n)) logprintf xextern int usbdebug;#else#define DPRINTF(x)#define DPRINTFN(n,x)#endifstatic 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 108extern struct cdevsw usb_cdevsw;#endif#ifdef USB_DEBUGchar *usbd_error_strs[USBD_ERROR_MAX] = { "NORMAL_COMPLETION", "IN_PROGRESS", "PENDING_REQUESTS", "NOT_STARTED", "INVAL", "IS_IDLE", "NOMEM", "CANCELLED", "BAD_ADDRESS", "IN_USE", "INTERFACE_NOT_ACTIVE", "NO_ADDR", "SET_ADDR_FAILED", "NO_POWER", "TOO_DEEP", "IOERROR", "NOT_CONFIGURED", "TIMEOUT", "SHORT_XFER", "STALLED", "XXX",};#endifusbd_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_statususbd_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_statususbd_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)#if defined(__NetBSD__) SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);#elif defined(__FreeBSD__) SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, next);#endif 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->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->retries = 1; reqh->isreq = 0; 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->retries = 1; reqh->isreq = 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 0usb_descriptor_t *usbd_get_descriptor(iface, desc_type) usbd_interface_handle *iface; u_int8_t desc_type;XX#endifusb_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, state; if (pipe->iface->state != USBD_INTERFACE_ACTIVE) return (USBD_INTERFACE_NOT_ACTIVE); s = splusb(); state = pipe->state; r = usbd_ar_pipe(pipe); pipe->state = state; 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 0XXX 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 0usbd_status usbd_set_device_state(dev, state) usbd_device_handle dev; usbd_device_state state;X#endifusbd_status usbd_device_address(dev, address) usbd_device_handle dev; u_int8_t *address;{ *address = dev->address;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?