Add functions to execute asynchronous requests and use these from

interrupt context.
[I had some feline debugging help here.  I noticed that every time Kem,
our kitty, jumped onto the USB keyboard the machine crashed.]
This commit is contained in:
augustss 1998-07-29 20:50:11 +00:00
parent f453d02883
commit a0803787f7
6 changed files with 125 additions and 19 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ukbd.c,v 1.3 1998/07/26 17:42:49 augustss Exp $ */
/* $NetBSD: ukbd.c,v 1.4 1998/07/29 20:50:11 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -141,8 +141,6 @@ struct ukbd_softc {
struct ukbd_data sc_ndata;
struct ukbd_data sc_odata;
int sc_state;
#define UKBD_NEEDCLEAR 0x01 /* needs clearing endpoint stall */
int sc_disconnected; /* device is gone */
int sc_leds;
@ -308,7 +306,7 @@ ukbd_intr(reqh, addr, status)
if (status != USBD_NORMAL_COMPLETION) {
DPRINTF(("ukbd_intr: status=%d\n", status));
sc->sc_state |= UKBD_NEEDCLEAR;
usbd_clear_endpoint_stall_async(sc->sc_intrpipe);
return;
}
@ -391,7 +389,7 @@ ukbd_set_leds(v, leds)
res |= NUM_LOCK;
if (leds & WSKBD_LED_CAPS)
res |= CAPS_LOCK;
usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1);
usbd_set_report_async(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1);
}
int
@ -432,7 +430,9 @@ ukbd_cngetc(v, type, data)
struct ukbd_softc *sc = v;
usbd_lock_token s;
extern int usbd_use_polling;
int c;
DPRINTFN(1,("ukbd_cngetc: enter\n"));
s = usbd_lock();
usbd_use_polling = 1;
sc->sc_polling = 1;
@ -441,9 +441,11 @@ ukbd_cngetc(v, type, data)
usbd_dopoll(sc->sc_iface);
sc->sc_polling = 0;
usbd_use_polling = 0;
*type = sc->sc_pollchar&0x80?WSCONS_EVENT_KEY_UP:WSCONS_EVENT_KEY_DOWN;
*data = sc->sc_pollchar & 0x7f;
c = sc->sc_pollchar;
*type = c & 0x80 ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
*data = c & 0x7f;
usbd_unlock(s);
DPRINTFN(1,("ukbd_cngetc: return 0x%02x\n", c));
}
void
@ -451,5 +453,5 @@ ukbd_cnpollc(v, on)
void *v;
int on;
{
DPRINTF(("ukbd_cnpollc: sc=%p on=%d\n", v, on));
DPRINTFN(1,("ukbd_cnpollc: sc=%p on=%d\n", v, on));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ums.c,v 1.6 1998/07/28 21:21:47 augustss Exp $ */
/* $NetBSD: ums.c,v 1.7 1998/07/29 20:50:12 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -91,8 +91,6 @@ struct ums_softc {
struct hid_location sc_loc_x, sc_loc_y, sc_loc_z,
sc_loc_btn1, sc_loc_btn2, sc_loc_btn3;
u_char sc_state; /* mouse driver state */
#define UMS_NEEDCLEAR 0x04 /* needs clearing endpoint stall */
u_char sc_buttons; /* mouse button status */
int sc_disconnected; /* device is gone */
@ -294,7 +292,7 @@ ums_intr(reqh, addr, status)
if (status != USBD_NORMAL_COMPLETION) {
DPRINTF(("ums_intr: status=%d\n", status));
sc->sc_state |= UMS_NEEDCLEAR;
usbd_clear_endpoint_stall_async(sc->sc_intrpipe);
return;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi.c,v 1.6 1998/07/26 17:42:49 augustss Exp $ */
/* $NetBSD: usbdi.c,v 1.7 1998/07/29 20:50:12 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -66,6 +66,8 @@ 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));
static usbd_status usbd_start __P((usbd_pipe_handle pipe));
void usbd_do_request_async_cb
__P((usbd_request_handle, usbd_private_handle, usbd_status));
static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests;
@ -479,7 +481,7 @@ usbd_clear_endpoint_stall(pipe)
req.bmRequestType = UT_WRITE_ENDPOINT;
req.bRequest = UR_CLEAR_FEATURE;
USETW(req.wValue, UF_ENDPOINT_STALL);
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); /* XXX mask/ */
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
USETW(req.wLength, 0);
r = usbd_do_request(dev, &req, 0);
#if 0
@ -492,6 +494,23 @@ XXX should we do this?
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_STALL);
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;
@ -914,6 +933,13 @@ usbd_do_request(dev, req, data)
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);
@ -938,6 +964,54 @@ usbd_do_request(dev, req, data)
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;

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi.h,v 1.3 1998/07/26 17:42:49 augustss Exp $ */
/* $NetBSD: usbdi.h,v 1.4 1998/07/29 20:50:12 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -150,6 +150,7 @@ usbd_status usbd_abort_interface __P((usbd_interface_handle iface));
usbd_status usbd_reset_pipe __P((usbd_pipe_handle pipe));
usbd_status usbd_reset_interface __P((usbd_interface_handle iface));
usbd_status usbd_clear_endpoint_stall __P((usbd_pipe_handle pipe));
usbd_status usbd_clear_endpoint_stall_async __P((usbd_pipe_handle pipe));
usbd_status usbd_set_pipe_state
__P((usbd_pipe_handle pipe, usbd_pipe_state state));
usbd_status usbd_get_pipe_state
@ -207,6 +208,8 @@ usbd_status usbd_open_pipe_intr
u_int32_t length, usbd_callback));
usbd_status usbd_do_request
__P((usbd_device_handle pipe, usb_device_request_t *req, void *data));
usbd_status usbd_do_request_async
__P((usbd_device_handle pipe, usb_device_request_t *req, void *data));
usb_interface_descriptor_t *usbd_get_interface_descriptor
__P((usbd_interface_handle iface));
usb_config_descriptor_t *usbd_get_config_descriptor

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi_util.c,v 1.2 1998/07/13 10:49:42 augustss Exp $ */
/* $NetBSD: usbdi_util.c,v 1.3 1998/07/29 20:50:12 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -258,6 +258,33 @@ usbd_set_report(iface, type, id, data, len)
return (usbd_do_request(dev, &req, data));
}
usbd_status
usbd_set_report_async(iface, type, id, data, len)
usbd_interface_handle iface;
int type;
int id;
void *data;
int len;
{
usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
usbd_device_handle dev;
usb_device_request_t req;
usbd_status r;
DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len));
r = usbd_interface2device_handle(iface, &dev);
if (r != USBD_NORMAL_COMPLETION)
return (r);
if (!ifd)
return (USBD_INVAL);
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
req.bRequest = UR_SET_REPORT;
USETW2(req.wValue, type, id);
USETW(req.wIndex, ifd->bInterfaceNumber);
USETW(req.wLength, len);
return (usbd_do_request_async(dev, &req, data));
}
usbd_status
usbd_get_report(iface, type, id, data, len)
usbd_interface_handle iface;

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi_util.h,v 1.2 1998/07/13 10:49:42 augustss Exp $ */
/* $NetBSD: usbdi_util.h,v 1.3 1998/07/29 20:50:12 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -57,9 +57,11 @@ usbd_status usbd_get_report_descriptor
struct usb_hid_descriptor *usbd_get_hid_descriptor
__P((usbd_interface_handle ifc));
usbd_status usbd_set_report
__P((usbd_interface_handle iface, int type, int id, void *data, int len));
__P((usbd_interface_handle iface,int type,int id,void *data,int len));
usbd_status usbd_set_report_async
__P((usbd_interface_handle iface,int type,int id,void *data,int len));
usbd_status usbd_get_report
__P((usbd_interface_handle iface, int type, int id, void *data, int len));
__P((usbd_interface_handle iface,int type,int id,void *data,int len));
usbd_status usbd_set_idle
__P((usbd_interface_handle iface, int duration, int id));
usbd_status usbd_alloc_report_desc