PERFORCE change 145314 for review
Weongyo Jeong
weongyo at FreeBSD.org
Wed Jul 16 10:41:23 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=145314
Change 145314 by weongyo at weongyo_ws on 2008/07/16 10:40:51
When we're handling URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE, we should
set a actual value which is responsed by the USB device not the status
value. This was a critical bug.
Affected files ...
.. //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#9 edit
Differences ...
==== //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#9 (text+ko) ====
@@ -79,6 +79,8 @@
static int32_t usbd_func_vendorclass(irp *);
static int32_t usbd_func_selconf(irp *);
static int32_t usbd_func_getdesc(irp *);
+static usbd_status usbd_get_desc_ndis(usbd_device_handle, int, int, int,
+ void *, int *);
static union usbd_urb *usbd_geturb(irp *);
static usbd_status usbd_init_ndispipe(irp *, usb_endpoint_descriptor_t *);
static usbd_xfer_handle usbd_init_ndisxfer(irp *, usb_endpoint_descriptor_t *,
@@ -354,70 +356,61 @@
irp *ip;
{
device_t dev = IRP_NDIS_DEV(ip);
- int i;
+ int actlen, i;
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct usbd_urb_control_descriptor_request *ctldesc;
- uint32_t len;
union usbd_urb *urb;
- usb_config_descriptor_t cd, *cdp;
usbd_status status;
urb = usbd_geturb(ip);
ctldesc = &urb->uu_ctldesc;
- if (ctldesc->ucd_desctype == UDESC_CONFIG) {
- /* Get the short config descriptor. */
- status = usbd_get_config_desc(uaa->device, ctldesc->ucd_idx,
- &cd);
- if (status != USBD_NORMAL_COMPLETION) {
- ctldesc->ucd_trans_buflen = 0;
- return usbd_usb2urb(status);
- }
- len = MIN(UGETW(cd.wTotalLength), ctldesc->ucd_trans_buflen);
- /* Get the full descriptor. Try a few times for slow devices. */
- for (i = 0; i < 3; i++) {
- status = usbd_get_desc(uaa->device,
- ctldesc->ucd_desctype, ctldesc->ucd_idx,
- len, ctldesc->ucd_trans_buf);
- if (status == USBD_NORMAL_COMPLETION)
- break;
- usbd_delay_ms(uaa->device, 200);
- }
- if (status != USBD_NORMAL_COMPLETION) {
- ctldesc->ucd_trans_buflen = 0;
- return usbd_usb2urb(status);
- }
-
- cdp = (usb_config_descriptor_t *)ctldesc->ucd_trans_buf;
- if (cdp->bDescriptorType != UDESC_CONFIG) {
- device_printf(dev, "bad desc %d\n",
- cdp->bDescriptorType);
- status = USBD_INVAL;
- }
- } else if (ctldesc->ucd_desctype == UDESC_STRING) {
+ if (ctldesc->ucd_desctype == UDESC_STRING) {
/* Try a few times for slow devices. */
for (i = 0; i < 3; i++) {
- status = usbd_get_string(uaa->device,
+ status = usbd_get_string_desc(uaa->device,
(UDESC_STRING << 8) + ctldesc->ucd_idx,
- ctldesc->ucd_trans_buf, ctldesc->ucd_trans_buflen);
- if (status != USBD_NORMAL_COMPLETION)
+ ctldesc->ucd_langid, ctldesc->ucd_trans_buf,
+ &actlen);
+ if (actlen > ctldesc->ucd_trans_buflen)
+ panic("small string buffer for UDESC_STRING");
+ if (status == USBD_NORMAL_COMPLETION)
break;
usbd_delay_ms(uaa->device, 200);
}
} else
- status = usbd_get_desc(uaa->device, ctldesc->ucd_desctype,
+ status = usbd_get_desc_ndis(uaa->device, ctldesc->ucd_desctype,
ctldesc->ucd_idx, ctldesc->ucd_trans_buflen,
- ctldesc->ucd_trans_buf);
+ ctldesc->ucd_trans_buf, &actlen);
if (status != USBD_NORMAL_COMPLETION) {
ctldesc->ucd_trans_buflen = 0;
return usbd_usb2urb(status);
}
- ctldesc->ucd_trans_buflen = status;
- ip->irp_iostat.isb_info = status;
+ ctldesc->ucd_trans_buflen = actlen;
+ ip->irp_iostat.isb_info = actlen;
return (USBD_STATUS_SUCCESS);
}
+/*
+ * FIXME: at USB1, not USB2, framework, there's no a interface to get `actlen'.
+ * However, we need it!!!
+ */
+static usbd_status
+usbd_get_desc_ndis(usbd_device_handle dev, int type, int index, int len,
+ void *desc, int *actlen)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_READ_DEVICE;
+ req.bRequest = UR_GET_DESCRIPTOR;
+ USETW2(req.wValue, type, index);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, len);
+ return usbd_do_request_flags_pipe(dev, dev->default_pipe, &req, desc,
+ 0, actlen, USBD_DEFAULT_TIMEOUT);
+}
+
static int32_t
usbd_func_selconf(ip)
irp *ip;
More information about the p4-projects
mailing list