Exemplo n.º 1
0
static void
usb_parse_iface_sub(struct usb_parse_state *ps)
{
	struct libusb20_interface *aifc;
	struct usb_interface_descriptor *bifc;
	uint8_t x;

	aifc = ps->a.currifc;
	bifc = ps->b.currifc++;

	if (ps->preparse == 0) {
		/* copy descriptor fields */
		bifc->bLength = aifc->desc.bLength;
		bifc->bDescriptorType = aifc->desc.bDescriptorType;
		bifc->bInterfaceNumber = aifc->desc.bInterfaceNumber;
		bifc->bAlternateSetting = aifc->desc.bAlternateSetting;
		bifc->bNumEndpoints = aifc->num_endpoints;
		bifc->bInterfaceClass = aifc->desc.bInterfaceClass;
		bifc->bInterfaceSubClass = aifc->desc.bInterfaceSubClass;
		bifc->bInterfaceProtocol = aifc->desc.bInterfaceProtocol;
		bifc->iInterface = aifc->desc.iInterface;
		bifc->endpoint = ps->b.currep;
	}
	for (x = 0; x != aifc->num_endpoints; x++) {
		ps->a.currep = aifc->endpoints + x;
		usb_parse_endpoint(ps);
	}

	ps->a.currextra = &aifc->extra;
	usb_parse_extra(ps, &bifc->extra, &bifc->extralen);
	return;
}
Exemplo n.º 2
0
static int usb_parse_interface(struct device *ddev, int cfgno,
    struct usb_host_config *config, unsigned char *buffer, int size,
    u8 inums[], u8 nalts[])
{
	unsigned char *buffer0 = buffer;
	struct usb_interface_descriptor	*d;
	int inum, asnum;
	struct usb_interface_cache *intfc;
	struct usb_host_interface *alt;
	int i, n;
	int len, retval;
	int num_ep, num_ep_orig;

	d = (struct usb_interface_descriptor *) buffer;
	buffer += d->bLength;
	size -= d->bLength;

	if (d->bLength < USB_DT_INTERFACE_SIZE)
		goto skip_to_next_interface_descriptor;

	/* Which interface entry is this? */
	intfc = NULL;
	inum = d->bInterfaceNumber;
	for (i = 0; i < config->desc.bNumInterfaces; ++i) {
		if (inums[i] == inum) {
			intfc = config->intf_cache[i];
			break;
		}
	}
	if (!intfc || intfc->num_altsetting >= nalts[i])
		goto skip_to_next_interface_descriptor;

	/* Check for duplicate altsetting entries */
	asnum = d->bAlternateSetting;
	for ((i = 0, alt = &intfc->altsetting[0]);
	      i < intfc->num_altsetting;
	     (++i, ++alt)) {
		if (alt->desc.bAlternateSetting == asnum) {
			dev_warn(ddev, "Duplicate descriptor for config %d "
			    "interface %d altsetting %d, skipping\n",
			    cfgno, inum, asnum);
			goto skip_to_next_interface_descriptor;
		}
	}

	++intfc->num_altsetting;
	memcpy(&alt->desc, d, USB_DT_INTERFACE_SIZE);

	/* Skip over any Class Specific or Vendor Specific descriptors;
	 * find the first endpoint or interface descriptor */
	alt->extra = buffer;
	i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
	    USB_DT_INTERFACE, &n);
	alt->extralen = i;
	if (n > 0)
		dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
		    n, plural(n), "interface");
	buffer += i;
	size -= i;

	/* Allocate space for the right(?) number of endpoints */
	num_ep = num_ep_orig = alt->desc.bNumEndpoints;
	alt->desc.bNumEndpoints = 0;		// Use as a counter
	if (num_ep > USB_MAXENDPOINTS) {
		dev_warn(ddev, "too many endpoints for config %d interface %d "
		    "altsetting %d: %d, using maximum allowed: %d\n",
		    cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS);
		num_ep = USB_MAXENDPOINTS;
	}

	if (num_ep > 0) {	/* Can't allocate 0 bytes */
		len = sizeof(struct usb_host_endpoint) * num_ep;
		alt->endpoint = kzalloc(len, GFP_KERNEL);
		if (!alt->endpoint)
			return -ENOMEM;
	}

	/* Parse all the endpoint descriptors */
	n = 0;
	while (size > 0) {
		if (((struct usb_descriptor_header *) buffer)->bDescriptorType
		     == USB_DT_INTERFACE)
			break;
		retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
		    num_ep, buffer, size);
		if (retval < 0)
			return retval;
		++n;

		buffer += retval;
		size -= retval;
	}

	if (n != num_ep_orig)
		dev_warn(ddev, "config %d interface %d altsetting %d has %d "
		    "endpoint descriptor%s, different from the interface "
		    "descriptor's value: %d\n",
		    cfgno, inum, asnum, n, plural(n), num_ep_orig);
	return buffer - buffer0;

skip_to_next_interface_descriptor:
	i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
	    USB_DT_INTERFACE, NULL);
	return buffer - buffer0 + i;
}
Exemplo n.º 3
0
int         usb_parse_interface( usb_interface *interface,
                                 unsigned char *buffer, int size)
{
  int   i;
  int   retval;
  int   parsed = 0;
  usb_descriptor_header *header;
  usb_interface_descriptor *ifp;
  unsigned char *begin;

  interface->num_altsetting = 0;

  while (size > 0) {
    interface->altsetting = realloc(interface->altsetting, sizeof(usb_interface_descriptor) * (interface->num_altsetting + 1));
    if (!interface->altsetting) {
      printf( "malloc\n");
      return -1;
    }

    ifp = interface->altsetting + interface->num_altsetting;
    interface->num_altsetting++;

    memcpy( ifp, buffer, USB_DT_INTERFACE_SIZE);

    /* Skip over the interface */
    buffer += ifp->bLength;
    parsed += ifp->bLength;
    size -= ifp->bLength;

    begin = buffer;

    /* Skip over any interface, class or vendor descriptors */
    while (size >= sizeof(usb_descriptor_header)) {
      header = (usb_descriptor_header *)buffer;

      if (header->bLength < 2) {
        printf( "invalid descriptor length of %d\n", header->bLength);
        return -1;
      }

      /* If we find another "proper" descriptor then we're done */
      if ((header->bDescriptorType == USB_DT_INTERFACE) ||
          (header->bDescriptorType == USB_DT_ENDPOINT) ||
          (header->bDescriptorType == USB_DT_CONFIG) ||
          (header->bDescriptorType == USB_DT_DEVICE))
        break;

      buffer += header->bLength;
      parsed += header->bLength;
      size -= header->bLength;
    }

    // Did we hit an unexpected descriptor?
    header = (usb_descriptor_header *)buffer;
    if ((size >= sizeof(usb_descriptor_header)) &&
        ((header->bDescriptorType == USB_DT_CONFIG) ||
        (header->bDescriptorType == USB_DT_DEVICE)))
      return parsed;

    if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
      printf( "too many endpoints\n");
      return -1;
    }

    ifp->endpoint = (usb_endpoint_descriptor *)
                     malloc( ifp->bNumEndpoints * sizeof(usb_endpoint_descriptor));
    if (!ifp->endpoint) {
      printf( "malloc\n");
      return -1;      
    }

    memset( ifp->endpoint, 0, ifp->bNumEndpoints * sizeof(usb_endpoint_descriptor));

    for (i = 0; i < ifp->bNumEndpoints; i++) {
      header = (usb_descriptor_header *)buffer;

      if (header->bLength > size) {
        printf( "ran out of descriptors parsing\n");
        return -1;
      }
                
      retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
      if (retval < 0)
        return retval;

      buffer += retval;
      parsed += retval;
      size -= retval;
    }

    // We check to see if it's an alternate to this one
    ifp = (usb_interface_descriptor *)buffer;
    if (size < USB_DT_INTERFACE_SIZE ||
        ifp->bDescriptorType != USB_DT_INTERFACE ||
        !ifp->bAlternateSetting)
      return parsed;
  }

  return parsed;
}
Exemplo n.º 4
0
static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size)
{
	int i, len, numskipped, retval, parsed = 0;
	struct usb_descriptor_header *header;
	struct usb_host_interface *ifp;
	unsigned char *begin;

	interface->act_altsetting = 0;
	interface->num_altsetting = 0;
	interface->max_altsetting = USB_ALTSETTINGALLOC;
	device_initialize(&interface->dev);

	interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting,
					GFP_KERNEL);
	
	if (!interface->altsetting) {
		err("couldn't kmalloc interface->altsetting");
		return -1;
	}

	while (size > 0) {
		struct usb_interface_descriptor	*d;
	
		if (interface->num_altsetting >= interface->max_altsetting) {
			struct usb_host_interface *ptr;
			int oldmas;

			oldmas = interface->max_altsetting;
			interface->max_altsetting += USB_ALTSETTINGALLOC;
			if (interface->max_altsetting > USB_MAXALTSETTING) {
				warn("too many alternate settings (incr %d max %d)\n",
					USB_ALTSETTINGALLOC, USB_MAXALTSETTING);
				return -1;
			}

			ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL);
			if (ptr == NULL) {
				err("couldn't kmalloc interface->altsetting");
				return -1;
			}
			memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas);
			kfree(interface->altsetting);
			interface->altsetting = ptr;
		}

		ifp = interface->altsetting + interface->num_altsetting;
		ifp->endpoint = NULL;
		ifp->extra = NULL;
		ifp->extralen = 0;
		interface->num_altsetting++;

		memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);

		/* Skip over the interface */
		buffer += ifp->desc.bLength;
		parsed += ifp->desc.bLength;
		size -= ifp->desc.bLength;

		begin = buffer;
		numskipped = 0;

		/* Skip over any interface, class or vendor descriptors */
		while (size >= sizeof(struct usb_descriptor_header)) {
			header = (struct usb_descriptor_header *)buffer;

			if (header->bLength < 2) {
				err("invalid descriptor length of %d", header->bLength);
				return -1;
			}

			/* If we find another "proper" descriptor then we're done  */
			if ((header->bDescriptorType == USB_DT_INTERFACE) ||
			    (header->bDescriptorType == USB_DT_ENDPOINT) ||
			    (header->bDescriptorType == USB_DT_CONFIG) ||
			    (header->bDescriptorType == USB_DT_DEVICE))
				break;

			numskipped++;

			buffer += header->bLength;
			parsed += header->bLength;
			size -= header->bLength;
		}

		if (numskipped)
			dbg("skipped %d class/vendor specific interface descriptors", numskipped);

		/* Copy any unknown descriptors into a storage area for */
		/*  drivers to later parse */
		len = (int)(buffer - begin);
		if (len) {
			ifp->extra = kmalloc(len, GFP_KERNEL);

			if (!ifp->extra) {
				err("couldn't allocate memory for interface extra descriptors");
				ifp->extralen = 0;
				return -1;
			}
			memcpy(ifp->extra, begin, len);
			ifp->extralen = len;
		}

		/* Did we hit an unexpected descriptor? */
		header = (struct usb_descriptor_header *)buffer;
		if ((size >= sizeof(struct usb_descriptor_header)) &&
		    ((header->bDescriptorType == USB_DT_CONFIG) ||
		     (header->bDescriptorType == USB_DT_DEVICE)))
			return parsed;

		if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) {
			warn("too many endpoints");
			return -1;
		}

		ifp->endpoint = (struct usb_host_endpoint *)
			kmalloc(ifp->desc.bNumEndpoints *
			sizeof(struct usb_host_endpoint), GFP_KERNEL);
		if (!ifp->endpoint) {
			err("out of memory");
			return -1;	
		}

		memset(ifp->endpoint, 0, ifp->desc.bNumEndpoints *
			sizeof(struct usb_host_endpoint));
	
		for (i = 0; i < ifp->desc.bNumEndpoints; i++) {
			header = (struct usb_descriptor_header *)buffer;

			if (header->bLength > size) {
				err("ran out of descriptors parsing");
				return -1;
			}
		
			retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
			if (retval < 0)
				return retval;

			buffer += retval;
			parsed += retval;
			size -= retval;
		}

		/* We check to see if it's an alternate to this one */
		d = (struct usb_interface_descriptor *)buffer;
		if (size < USB_DT_INTERFACE_SIZE
				|| d->bDescriptorType != USB_DT_INTERFACE
				|| !d->bAlternateSetting)
			return parsed;
	}

	return parsed;
}
static int usb_parse_interface(struct usb_interface *interface,
	unsigned char *buffer, int size)
{
  int i, len, numskipped, retval, parsed = 0;
  struct usb_descriptor_header header;
  struct usb_interface_descriptor *ifp;
  unsigned char *begin;

  interface->num_altsetting = 0;

  while (size >= INTERFACE_DESC_LENGTH) {
    interface->altsetting = realloc(interface->altsetting, sizeof(struct usb_interface_descriptor) * (interface->num_altsetting + 1));
    if (!interface->altsetting) {
      if (usb_debug >= 1)
        fprintf(stderr, "couldn't malloc interface->altsetting\n");
      return -1;
    }

    ifp = interface->altsetting + interface->num_altsetting;
    interface->num_altsetting++;

    usb_parse_descriptor(buffer, "bbbbbbbbb", ifp);

    /* Skip over the interface */
    buffer += ifp->bLength;
    parsed += ifp->bLength;
    size -= ifp->bLength;

    begin = buffer;
    numskipped = 0;

    /* Skip over any interface, class or vendor descriptors */
    while (size >= DESC_HEADER_LENGTH) {
      usb_parse_descriptor(buffer, "bb", &header);

      if (header.bLength < 2) {
        if (usb_debug >= 1)
          fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
        return -1;
      }

      /* If we find another "proper" descriptor then we're done */
      if ((header.bDescriptorType == USB_DT_INTERFACE) ||
          (header.bDescriptorType == USB_DT_ENDPOINT) ||
          (header.bDescriptorType == USB_DT_CONFIG) ||
          (header.bDescriptorType == USB_DT_DEVICE))
        break;

      numskipped++;

      buffer += header.bLength;
      parsed += header.bLength;
      size -= header.bLength;
    }

    if (numskipped && usb_debug >= 2)
      fprintf(stderr, "skipped %d class/vendor specific interface descriptors\n", numskipped);

    /* Copy any unknown descriptors into a storage area for */
    /*  drivers to later parse */
    len = (int)(buffer - begin);
    if (!len) {
      ifp->extra = NULL;
      ifp->extralen = 0;
    } else {
      ifp->extra = malloc(len);
      if (!ifp->extra) {
        if (usb_debug >= 1)
          fprintf(stderr, "couldn't allocate memory for interface extra descriptors\n");
        ifp->extralen = 0;
        return -1;
      }
      memcpy(ifp->extra, begin, len);
      ifp->extralen = len;
    }

    /* Did we hit an unexpected descriptor? */
    usb_parse_descriptor(buffer, "bb", &header);
    if ((size >= DESC_HEADER_LENGTH) &&
        ((header.bDescriptorType == USB_DT_CONFIG) ||
        (header.bDescriptorType == USB_DT_DEVICE)))
      return parsed;

    if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
      if (usb_debug >= 1)
        fprintf(stderr, "too many endpoints\n");
      return -1;
    }

    if (ifp->bNumEndpoints > 0) {
      ifp->endpoint = (struct usb_endpoint_descriptor *)
                       malloc(ifp->bNumEndpoints *
                       sizeof(struct usb_endpoint_descriptor));
      if (!ifp->endpoint) {
        if (usb_debug >= 1)
          fprintf(stderr, "couldn't allocate memory for ifp->endpoint\n");
        return -1;      
      }

      memset(ifp->endpoint, 0, ifp->bNumEndpoints *
             sizeof(struct usb_endpoint_descriptor));

      for (i = 0; i < ifp->bNumEndpoints; i++) {
        usb_parse_descriptor(buffer, "bb", &header);
  
        if (header.bLength > size) {
          if (usb_debug >= 1)
            fprintf(stderr, "ran out of descriptors parsing\n");
          return -1;
        }
                
        retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
        if (retval < 0)
          return retval;

        buffer += retval;
        parsed += retval;
        size -= retval;
      }
    } else
      ifp->endpoint = NULL;

    /* We check to see if it's an alternate to this one */
    ifp = (struct usb_interface_descriptor *)buffer;
    if (size < USB_DT_INTERFACE_SIZE ||
        ifp->bDescriptorType != USB_DT_INTERFACE ||
        !ifp->bAlternateSetting)
      return parsed;
  }

  return parsed;
}