PERFORCE change 131607 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Tue Dec 25 11:45:23 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=131607
Change 131607 by hselasky at hselasky_laptop001 on 2007/12/25 19:45:00
Fixes for USB Device Side Mode.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#87 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#87 (text+ko) ====
@@ -1214,7 +1214,6 @@
} else {
mtx_unlock(info->usb_mtx);
}
-
}
}
}
@@ -1500,7 +1499,6 @@
/*
* This is not a valid operation!
*/
-
PRINTFN(-1, ("Invalid parameter "
"combination\n"));
goto error;
@@ -2756,6 +2754,7 @@
/* handle the request */
err = usbd_handle_request(xfer);
+ if (err) {
if (err == USBD_BAD_CONTEXT) {
/*
* Currently we get a "start" context by
@@ -2765,12 +2764,11 @@
USB_BUS_EXPLORE_TREE);
return;
}
- if ((!xfer->flags_int.control_act) || err) {
/*
* If no control transfer is active,
* receive the next SETUP message:
*/
- goto tr_start;
+ goto tr_restart;
}
usbd_start_hardware(xfer);
return;
@@ -2778,24 +2776,18 @@
default:
if (xfer->error != USBD_CANCELLED) {
/* should not happen - try stalling */
- err = USBD_STALLED;
- goto tr_start;
+ goto tr_restart;
}
break;
}
return;
-tr_start:
+tr_restart:
xfer->frlengths[0] = sizeof(usb_device_request_t);
xfer->nframes = 1;
xfer->flags.manual_status = 1;
xfer->flags.force_short_xfer = 0;
- xfer->flags.short_xfer_ok = 0;
- if (err) {
- xfer->flags.stall_pipe = 1;
- } else {
- xfer->flags.stall_pipe = 0;
- }
+ xfer->flags.stall_pipe = 1; /* cancel previous transfer, if any */
usbd_start_hardware(xfer);
return;
}
@@ -2821,64 +2813,20 @@
}
if (usbd_set_config_index(xfer->udev, conf_no, 0)) {
+ PRINTFN(0, ("set config %d failed\n", conf_no));
mtx_lock(xfer->priv_mtx);
return (USBD_STALLED);
}
if (usbd_probe_and_attach(xfer->udev, USB_IFACE_INDEX_ANY)) {
- mtx_lock(xfer->priv_mtx);
- return (USBD_STALLED);
- }
- mtx_lock(xfer->priv_mtx);
-
- return (0);
-}
-
-/*------------------------------------------------------------------------*
- * usbd_handle_set_alt_setting
- *------------------------------------------------------------------------*/
-static usbd_status_t
-usbd_handle_set_alt_setting(struct usbd_xfer *xfer,
- uint8_t iface_index, uint8_t alt_index)
-{
- if (iface_index >= USB_MAX_INTERFACES) {
- return (USBD_STALLED);
- }
- mtx_unlock(xfer->priv_mtx);
-
- usbd_detach_device(xfer->udev, iface_index, 1);
-
- if (usbd_set_alt_interface_index(xfer->udev,
- iface_index, alt_index)) {
- mtx_lock(xfer->priv_mtx);
- return (USBD_STALLED);
- }
- if (usbd_probe_and_attach(xfer->udev, iface_index)) {
+ PRINTFN(0, ("probe and attach failed\n"));
mtx_lock(xfer->priv_mtx);
return (USBD_STALLED);
}
mtx_lock(xfer->priv_mtx);
-
return (0);
}
/*------------------------------------------------------------------------*
- * usbd_handle_get_alt_setting
- *------------------------------------------------------------------------*/
-static usbd_status_t
-usbd_handle_get_alt_setting(struct usbd_xfer *xfer,
- uint8_t iface_index, uint8_t *ptr)
-{
- struct usbd_interface *iface;
-
- iface = usbd_get_iface(xfer->udev, iface_index);
- if (iface) {
- *ptr = iface->alt_index;
- return (0);
- }
- return (USBD_STALLED);
-}
-
-/*------------------------------------------------------------------------*
* usbd_handle_set_stall_sub
*
* This function is used to make a BULK or INTERRUPT endpoint
@@ -3005,24 +2953,33 @@
/*------------------------------------------------------------------------*
* usbd_handle_request
+ *
+ * Returns:
+ * 0: Ready to start hardware
+ * USBD_BAD_CONTEXT: Need to switch context
+ * Else: Stall current transfer, if any
*------------------------------------------------------------------------*/
static usbd_status_t
usbd_handle_request(struct usbd_xfer *xfer)
{
+/*
+ * USB handle request states
+ *
+ * Typical state sequence:
+ *
+ * ST_DATA [ -> ST_CONTEXT_START ] -> ST_POST_STATUS
+ */
enum {
ST_DATA,
ST_CONTEXT_START,
ST_POST_STATUS,
};
-
- /*
- * State sequence:
- *
- * ST_DATA [ -> ST_CONTEXT_START ] -> ST_POST_STATUS
- */
usb_device_request_t req;
struct usbd_device *udev;
- const void *ptr;
+ struct usbd_interface *iface;
+ const void *src_zcopy; /* zero-copy source pointer */
+ const void *src_mcopy; /* non zero-copy source pointer */
+ int error;
uint16_t off; /* data offset */
uint16_t rem; /* data remainder */
uint16_t max_len; /* max fragment length */
@@ -3041,15 +2998,17 @@
switch (USBD_GET_STATE(xfer)) {
case USBD_ST_SETUP:
+ state = ST_CONTEXT_START;
+
if (!xfer->flags_int.control_act) {
/* nothing to do */
- return (0);
+ goto tr_stalled;
}
+
if (xfer->flags_int.context != USBD_CONTEXT_START) {
- /* wrong context */
+ /* wrong context - should not happen */
goto tr_bad_context;
}
- state = ST_CONTEXT_START;
break;
default: /* USBD_ST_TRANSFERRED */
@@ -3085,7 +3044,8 @@
/* set some defaults */
max_len = 0;
- ptr = &temp;
+ src_zcopy = NULL;
+ src_mcopy = NULL;
udev = xfer->udev;
/* get some request fields decoded */
@@ -3093,9 +3053,9 @@
wValue = UGETW(req.wValue);
wIndex = UGETW(req.wIndex);
- PRINTFN(2, ("req 0x%02x 0x%02x 0x%04x 0x%04x "
- "off=0x%x rem=0x%x\n", req.bmRequestType,
- req.bRequest, wValue, wIndex, off, rem));
+ PRINTFN(0, ("req 0x%02x 0x%02x 0x%04x 0x%04x "
+ "off=0x%x rem=0x%x, state=%d\n", req.bmRequestType,
+ req.bRequest, wValue, wIndex, off, rem, state));
/* demultiplex the control request */
@@ -3130,7 +3090,7 @@
case UT_WRITE_ENDPOINT:
switch (req.bRequest) {
case UR_CLEAR_FEATURE:
- switch (UGETW(req.wValue)) {
+ switch (wValue) {
case UF_ENDPOINT_HALT:
goto tr_handle_clear_halt;
case UF_DEVICE_REMOTE_WAKEUP:
@@ -3141,7 +3101,7 @@
break;
case UR_SET_FEATURE:
- switch (UGETW(req.wValue)) {
+ switch (wValue) {
case UF_ENDPOINT_HALT:
goto tr_handle_set_halt;
case UF_DEVICE_REMOTE_WAKEUP:
@@ -3163,60 +3123,35 @@
goto tr_stalled;
}
break;
-
- case UT_WRITE_INTERFACE:
- switch (req.bRequest) {
- case UR_SET_INTERFACE:
- goto tr_handle_set_interface;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_INTERFACE:
- switch (req.bRequest) {
- case UR_GET_INTERFACE:
- goto tr_handle_get_interface;
- default:
- goto tr_stalled;
+ default:
+ if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
+ if (state == ST_DATA) {
+ goto tr_bad_context;
+ }
+ goto tr_handle_iface_request;
}
- break;
-
- case UT_WRITE_CLASS_INTERFACE:
- case UT_WRITE_VENDOR_INTERFACE:
- /* XXX forward */
- break;
-
- case UT_READ_CLASS_INTERFACE:
- case UT_READ_VENDOR_INTERFACE:
- /* XXX forward */
- break;
- default:
goto tr_stalled;
}
goto tr_valid;
tr_handle_get_descriptor:
- usbd_temp_get_desc(udev, &req, &ptr, &max_len);
- if (ptr == NULL) {
+ usbd_temp_get_desc(udev, &req, &src_zcopy, &max_len);
+ if (src_zcopy == NULL) {
goto tr_stalled;
}
- /* use zero copy */
- usbd_set_frame_data(xfer, USBD_ADD_BYTES(ptr, off), 1);
- ptr = NULL;
- /* adjust maximum length according to offset */
- max_len -= off;
goto tr_valid;
tr_handle_get_config:
+ temp.buf[0] = udev->curr_config_no;
+ src_mcopy = temp.buf;
max_len = 1;
- temp.buf[0] = udev->curr_config_no;
goto tr_valid;
tr_handle_get_status:
- max_len = sizeof(temp.wStatus);
/* XXX FIXME */
USETW(temp.wStatus, UDS_SELF_POWERED);
+ src_mcopy = temp.wStatus;
+ max_len = sizeof(temp.wStatus);
goto tr_valid;
tr_handle_set_address:
@@ -3238,7 +3173,7 @@
if (state == ST_DATA) {
goto tr_bad_context;
} else if (state == ST_CONTEXT_START) {
- if (usbd_handle_set_config(xfer, wValue)) {
+ if (usbd_handle_set_config(xfer, req.wValue[0])) {
goto tr_stalled;
}
}
@@ -3246,7 +3181,7 @@
tr_handle_clear_halt:
if (state == ST_DATA) {
- if (usbd_handle_set_stall(xfer, wIndex, 0)) {
+ if (usbd_handle_set_stall(xfer, req.wIndex[0], 0)) {
goto tr_stalled;
}
}
@@ -3264,7 +3199,7 @@
tr_handle_set_halt:
if (state == ST_DATA) {
- if (usbd_handle_set_stall(xfer, wIndex, 1)) {
+ if (usbd_handle_set_stall(xfer, req.wIndex[0], 1)) {
goto tr_stalled;
}
}
@@ -3282,32 +3217,80 @@
tr_handle_get_ep_status:
if (state == ST_DATA) {
+ temp.wStatus[0] =
+ usbd_handle_get_stall(udev, req.wIndex[0]);
+ temp.wStatus[1] = 0;
+ src_mcopy = temp.wStatus;
max_len = sizeof(temp.wStatus);
- temp.wStatus[0] = usbd_handle_get_stall(udev, req.wIndex[0]);
- temp.wStatus[1] = 0;
}
goto tr_valid;
-tr_handle_set_interface:
- if (state == ST_DATA) {
- goto tr_bad_context;
- } else if (state == ST_CONTEXT_START) {
- if (usbd_handle_set_alt_setting(xfer, wIndex - 1, wValue)) {
+tr_handle_iface_request:
+ iface = usbd_get_iface(udev, req.wIndex[0]);
+ if (iface == NULL) {
+ goto tr_stalled;
+ }
+ if (iface->subdev == NULL) {
+ goto tr_handle_iface_request_builtin;
+ }
+ if (device_is_attached(iface->subdev) == 0) {
+ goto tr_handle_iface_request_builtin;
+ }
+ mtx_unlock(xfer->priv_mtx);
+
+ /* We use "USBD_ADD_BYTES" to de-const the src_zcopy */
+
+ error = USB_HANDLE_REQUEST(iface->subdev,
+ &req, USBD_ADD_BYTES(&src_zcopy, 0), &max_len,
+ off, (state == ST_POST_STATUS));
+
+ mtx_lock(xfer->priv_mtx);
+
+ if (error == 0) {
+ /* negativly adjust pointer and length */
+ src_zcopy = ((const uint8_t *)src_zcopy) - off;
+ max_len += off;
+ goto tr_valid;
+ } else if (error == ENOTTY) {
+ goto tr_stalled;
+ }
+ goto tr_handle_iface_request_builtin;
+
+tr_handle_iface_request_builtin:
+ switch (req.bmRequestType) {
+ case UT_WRITE_INTERFACE:
+ switch (req.bRequest) {
+ case UR_SET_INTERFACE:
+ if (iface->alt_index != req.wValue[0]) {
+ goto tr_stalled;
+ }
+ break;
+ default:
goto tr_stalled;
}
- }
- goto tr_valid;
+ break;
+
+ case UT_READ_INTERFACE:
+ switch (req.bRequest) {
+ case UR_GET_INTERFACE:
+ src_mcopy = &(iface->alt_index);
+ max_len = 1;
+ break;
-tr_handle_get_interface:
- if (state == ST_DATA) {
- if (usbd_handle_get_alt_setting(xfer, wIndex, temp.buf)) {
+ default:
goto tr_stalled;
}
- max_len = 1;
+ break;
}
goto tr_valid;
tr_valid:
+ if (state == ST_POST_STATUS) {
+ goto tr_stalled;
+ }
+ /* subtract offset from length */
+
+ max_len -= off;
/* Compute the real maximum data length */
@@ -3340,8 +3323,13 @@
xfer->nframes = max_len ? 2 : 1;
}
if (max_len > 0) {
- if (ptr) {
- usbd_copy_in(xfer->frbuffers + 1, 0, ptr, max_len);
+ if (src_mcopy) {
+ src_mcopy = USBD_ADD_BYTES(src_mcopy, off);
+ usbd_copy_in(xfer->frbuffers + 1, 0,
+ src_mcopy, max_len);
+ } else {
+ usbd_set_frame_data(xfer,
+ USBD_ADD_BYTES(src_zcopy, off), 1);
}
xfer->frlengths[1] = max_len;
} else {
@@ -3350,12 +3338,16 @@
xfer->frlengths[1] = 0;
}
xfer->flags.stall_pipe = 0; /* do not stall pipe */
+ PRINTFN(0, ("success\n"));
return (0); /* success */
tr_stalled:
+ PRINTFN(0, ("%s\n", (state == ST_POST_STATUS) ?
+ "complete" : "stalled"));
return (USBD_STALLED);
tr_bad_context:
+ PRINTFN(0, ("bad context\n"));
return (USBD_BAD_CONTEXT);
}
@@ -3367,7 +3359,7 @@
.bufsize = 1024, /* bytes */
.mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
.mh.callback = &usbd_do_request_callback,
- .md.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
+ .md.flags = {.proxy_buffer = 1,.short_xfer_ok = 0,},
.md.callback = &usbd_handle_request_callback,
},
};
More information about the p4-projects
mailing list