Date: Fri, 16 Jun 2006 20:36:44 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 99371 for review Message-ID: <200606162036.k5GKai1s035861@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=99371 Change 99371 by hselasky@hselasky_mini_itx on 2006/06/16 20:36:37 Abstracted scanning of USB config descriptors into the routine "usb_desc_foreach()". Added extra range checking in case the code is compiled on an embedded system without virtual memory adresses. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#6 edit .. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#10 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/usb_subr.c#6 (text+ko) ==== @@ -258,121 +258,125 @@ #define ADD_BYTES(ptr,len) ((void *)(((u_int8_t *)(ptr)) + (len))) +usb_descriptor_t * +usbd_desc_foreach(usb_config_descriptor_t *cd, usb_descriptor_t *desc) +{ + void *end; + + if (cd == NULL) { + return NULL; + } + + end = ADD_BYTES(cd, UGETW(cd->wTotalLength)); + + if (desc == NULL) { + desc = ADD_BYTES(cd, 0); + } else { + desc = ADD_BYTES(desc, desc->bLength); + } + return (((((void *)desc) >= ((void *)cd)) && + (((void *)desc) < end) && + (ADD_BYTES(desc,desc->bLength) >= ((void *)cd)) && + (ADD_BYTES(desc,desc->bLength) <= end) && + (desc->bLength >= sizeof(*desc))) ? desc : NULL); +} + usb_hid_descriptor_t * usbd_get_hdesc(usb_config_descriptor_t *cd, usb_interface_descriptor_t *id) { - void *end = ADD_BYTES(cd, UGETW(cd->wTotalLength)); + usb_descriptor_t *desc = (void *)id; - if((id == NULL) || - (((void *)id) < ((void *)cd)) || - (((void *)id) >= end)) - { - return NULL; + if(desc == NULL) { + return NULL; } - for(id = ADD_BYTES(id, id->bLength); - (((void *)id) < end) && - (ADD_BYTES(id, USB_HID_DESCRIPTOR_SIZE(0)) <= end) && - (ADD_BYTES(id, id->bLength) <= end); - id = ADD_BYTES(id, id->bLength)) + while ((desc = usbd_desc_foreach(cd, desc))) { - if(id->bDescriptorType == UDESC_HID) + if ((desc->bDescriptorType == UDESC_HID) && + (desc->bLength >= USB_HID_DESCRIPTOR_SIZE(0))) { - return (void *)id; + return (void *)desc; } - if(id->bDescriptorType == UDESC_INTERFACE) + + if (desc->bDescriptorType == UDESC_INTERFACE) { break; } } - return (0); + return NULL; } usb_interface_descriptor_t * -usbd_find_idesc(usb_config_descriptor_t *cd, int iface_index, int alt_index) +usbd_find_idesc(usb_config_descriptor_t *cd, u_int16_t iface_index, + u_int16_t alt_index) { - void *end = ADD_BYTES(cd, UGETW(cd->wTotalLength)); + usb_descriptor_t *desc = NULL; usb_interface_descriptor_t *id; - int curidx, lastidx, curaidx = 0; + u_int16_t curidx = 0xFFFF; + u_int16_t lastidx = 0xFFFF; + u_int16_t curaidx = 0; - curidx = lastidx = -1; - - for(id = ADD_BYTES(cd, 0); - (((void *)id) < end) && - (ADD_BYTES(id,USB_INTERFACE_DESCRIPTOR_SIZE) <= end) && - (ADD_BYTES(id,id->bLength) <= end); - id = ADD_BYTES(id, id->bLength)) + while ((desc = usbd_desc_foreach(cd, desc))) { - PRINTFN(4,("iface_index=%d(%d) alt_index=%d(%d) len=%d " - "type=%d\n", - iface_index, curidx, alt_index, curaidx, - id->bLength, id->bDescriptorType)); + if ((desc->bDescriptorType == UDESC_INTERFACE) && + (desc->bLength >= sizeof(*id))) + { + id = (void *)desc; - if(id->bLength == 0) + if(id->bInterfaceNumber != lastidx) + { + lastidx = id->bInterfaceNumber; + curidx++; + curaidx = 0; + } + else { - /* bad descriptor */ - break; + curaidx++; } - if(id->bDescriptorType == UDESC_INTERFACE) + if((iface_index == curidx) && (alt_index == curaidx)) { - if(id->bInterfaceNumber != lastidx) - { - lastidx = id->bInterfaceNumber; - curidx++; - curaidx = 0; - } - else - { - curaidx++; - } - if((iface_index == curidx) && (alt_index == curaidx)) - { - return (id); - } + return (id); } + } } return (NULL); } usb_endpoint_descriptor_t * -usbd_find_edesc(usb_config_descriptor_t *cd, int iface_index, int alt_index, - int endptidx) +usbd_find_edesc(usb_config_descriptor_t *cd, u_int16_t iface_index, + u_int16_t alt_index, u_int16_t endptidx) { - void *end = ADD_BYTES(cd, UGETW(cd->wTotalLength)); + usb_descriptor_t *desc = NULL; usb_interface_descriptor_t *d; - usb_endpoint_descriptor_t *ed; - int curidx; + u_int16_t curidx = 0; d = usbd_find_idesc(cd, iface_index, alt_index); if(d == NULL) { - return (NULL); + return NULL; } + if(endptidx >= d->bNumEndpoints) /* quick exit */ { - return (NULL); + return NULL; } - curidx = 0; - for(ed = ADD_BYTES(d, d->bLength); - (((void *)ed) < end) && - (ADD_BYTES(ed, USB_ENDPOINT_DESCRIPTOR_SIZE) <= end) && - (ADD_BYTES(ed, ed->bLength) <= end); - ed = ADD_BYTES(ed, ed->bLength)) - { - if((ed->bLength == 0) || - (ed->bDescriptorType == UDESC_INTERFACE)) - { - /* bad descriptor */ - break; + + desc = ((void *)d); + + while ((desc = usbd_desc_foreach(cd, desc))) { + + if(desc->bDescriptorType == UDESC_INTERFACE) { + break; + } + + if (desc->bDescriptorType == UDESC_ENDPOINT) { + + if (curidx == endptidx) { + return ((desc->bLength >= USB_ENDPOINT_DESCRIPTOR_SIZE) ? + ((void *)d) : NULL); } - if(ed->bDescriptorType == UDESC_ENDPOINT) - { - if(curidx == endptidx) - { - return (ed); - } - curidx++; - } + curidx++; + } } return (NULL); } @@ -380,20 +384,10 @@ usb_descriptor_t * usbd_find_descriptor(usb_config_descriptor_t *cd, int type, int subtype) { - void *end = ADD_BYTES(cd, UGETW(cd->wTotalLength)); - usb_descriptor_t *desc; + usb_descriptor_t *desc = NULL; + + while ((desc = usbd_desc_foreach(cd, desc))) { - for(desc = ADD_BYTES(cd, 0); - (((void *)desc) < end) && - (ADD_BYTES(desc, sizeof(usb_descriptor_t)) <= end) && - (ADD_BYTES(desc, desc->bLength) <= end); - desc = ADD_BYTES(desc, desc->bLength)) - { - if(desc->bLength == 0) - { - /* bad descriptor */ - break; - } if((desc->bDescriptorType == type) && ((subtype == USBD_SUBTYPE_ANY) || (subtype == desc->bDescriptorSubtype))) @@ -405,24 +399,23 @@ } int -usbd_get_no_alts(usb_config_descriptor_t *cd, int ifaceno) +usbd_get_no_alts(usb_config_descriptor_t *cd, u_int8_t ifaceno) { - void *end = ADD_BYTES(cd, UGETW(cd->wTotalLength)); - int n; + usb_descriptor_t *desc = NULL; + usb_interface_descriptor_t *id; + int n = 0; + + while ((desc = usbd_desc_foreach(cd, desc))) { - for(n = 0; - (((void *)cd) < end) && - (ADD_BYTES(cd,USB_INTERFACE_DESCRIPTOR_SIZE) <= end) && - (ADD_BYTES(cd,cd->bLength) <= end); - cd = ADD_BYTES(cd, cd->bLength)) - { - if((((usb_interface_descriptor_t *)cd)->bDescriptorType == UDESC_INTERFACE) && - (((usb_interface_descriptor_t *)cd)->bInterfaceNumber == ifaceno)) - { - n++; - } + if ((desc->bDescriptorType == UDESC_INTERFACE) && + (desc->bLength >= sizeof(*id))) { + id = (void *)desc; + if (id->bInterfaceNumber == ifaceno) { + n++; + } + } } - return (n); + return n; } static void @@ -473,8 +466,8 @@ struct usbd_pipe *pipe = &udev->pipes[0]; struct usbd_pipe *pipe_end = &udev->pipes_end[0]; usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - void *end; + usb_endpoint_descriptor_t *ed = NULL; + usb_descriptor_t *desc; u_int8_t nendpt; if(iface == NULL) @@ -521,36 +514,29 @@ nendpt = id->bNumEndpoints; PRINTFN(4,("found idesc nendpt=%d\n", nendpt)); - ed = ADD_BYTES(id, id->bLength); - end = ADD_BYTES(udev->cdesc, UGETW(udev->cdesc->wTotalLength)); + desc = (void *)id; while(nendpt--) { PRINTFN(10,("endpt=%d\n", nendpt)); - while(ADD_BYTES(ed,USB_ENDPOINT_DESCRIPTOR_SIZE) <= end) + while ((desc = usbd_desc_foreach(udev->cdesc, desc))) { - PRINTFN(10,("ed=%p end=%p " - "len=%d type=%d\n", - ed, end, ed->bLength, - ed->bDescriptorType)); - - if((ADD_BYTES(ed, ed->bLength) <= end) && - (ed->bLength != 0) && - (ed->bDescriptorType == UDESC_ENDPOINT)) + if ((desc->bDescriptorType == UDESC_ENDPOINT) && + (desc->bLength >= USB_ENDPOINT_DESCRIPTOR_SIZE)) { goto found; } - if((ed->bLength == 0) || - (ed->bDescriptorType == UDESC_INTERFACE)) + if (desc->bDescriptorType == UDESC_INTERFACE) { break; } - ed = ADD_BYTES(ed, ed->bLength); } goto error; found: + ed = (void *)desc; + if(udev->speed == USB_SPEED_HIGH) { u_int16_t mps; @@ -598,7 +584,6 @@ } pipe++; } - ed = ADD_BYTES(ed, ed->bLength); } return (USBD_NORMAL_COMPLETION); ==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#10 (text+ko) ==== @@ -531,16 +531,19 @@ void usbd_delay_ms(struct usbd_device *udev, u_int ms); +usb_descriptor_t * +usbd_desc_foreach(usb_config_descriptor_t *cd, usb_descriptor_t *desc); + struct usb_hid_descriptor; struct usb_hid_descriptor * usbd_get_hdesc(usb_config_descriptor_t *cd, usb_interface_descriptor_t *id); usb_interface_descriptor_t * -usbd_find_idesc(usb_config_descriptor_t *cd, int iface_index, int alt_index); +usbd_find_idesc(usb_config_descriptor_t *cd, u_int16_t iface_index, u_int16_t alt_index); usb_endpoint_descriptor_t * -usbd_find_edesc(usb_config_descriptor_t *cd, int iface_index, int alt_index, - int endptidx); +usbd_find_edesc(usb_config_descriptor_t *cd, u_int16_t iface_index, u_int16_t alt_index, + u_int16_t endptidx); usb_descriptor_t * usbd_find_descriptor(usb_config_descriptor_t *cd, int type, int subtype); @@ -548,7 +551,7 @@ #define USBD_SUBTYPE_ANY (-1) int -usbd_get_no_alts(usb_config_descriptor_t *cd, int ifaceno); +usbd_get_no_alts(usb_config_descriptor_t *cd, u_int8_t ifaceno); usbd_status usbd_search_and_set_config(struct usbd_device *udev, int no, int msg);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606162036.k5GKai1s035861>