Esempio n. 1
0
File: uhc.c Progetto: InSoonPark/asf
/**
 * \brief Device enumeration step 16 (LPM only)
 * Requests the USB structure of the USB BOS / LPM descriptor.
 */
static void uhc_enumeration_step16_lpm(void)
{
	usb_setup_req_t req;

	uhc_dev_enum->lpm_desc = malloc(sizeof(usb_dev_lpm_desc_t));
	if (uhc_dev_enum->lpm_desc == NULL) {
		Assert(false);
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
	// Send USB device descriptor request
	req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
	req.bRequest = USB_REQ_GET_DESCRIPTOR;
	req.wValue = USB_DT_BOS << 8;
	req.wIndex = 0;
	req.wLength = sizeof(usb_dev_lpm_desc_t);
	if (!uhd_setup_request(UHC_DEVICE_ENUM_ADD,
			&req,
			(uint8_t *) uhc_dev_enum->lpm_desc,
			sizeof(usb_dev_lpm_desc_t),
			NULL, uhc_enumeration_step17_lpm)) {
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
}
Esempio n. 2
0
File: uhc.c Progetto: InSoonPark/asf
/**
 * \brief Enables or disables the remote wakeup feature
 * of all devices connected
 *
 * \param b_enable   true to enable remote wakeup feature, else disable.
 */
static void uhc_remotewakeup(bool b_enable)
{
	usb_setup_req_t req;
	uhc_device_t *dev;

	dev = &g_uhc_device_root;
	while(1) {
		if (dev->conf_desc->bmAttributes & USB_CONFIG_ATTR_REMOTE_WAKEUP) {
			if (b_enable) {
				req.bRequest = USB_REQ_SET_FEATURE;
			} else {
				req.bRequest = USB_REQ_CLEAR_FEATURE;
			}
			req.bmRequestType = USB_REQ_RECIP_DEVICE
					|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_OUT;
			req.wValue = USB_DEV_FEATURE_REMOTE_WAKEUP;
			req.wIndex = 0;
			req.wLength = 0;
			uhd_setup_request(dev->address,&req,NULL,0,NULL,NULL);
		}
#ifdef USB_HOST_HUB_SUPPORT
		if (dev->next == NULL) {
			break;
		}
		dev = dev->next;
#else
		break;
#endif
	}
}
Esempio n. 3
0
File: uhc.c Progetto: InSoonPark/asf
/**
 * \brief Device enumeration step 11
 * Updates USB host pipe with the new USB address.
 * Requests a complete USB device descriptor.
 */
static void uhc_enumeration_step11(void)
{
	usb_setup_req_t req;

	// Free address 0 used to start enumeration
	uhd_ep_free(0, 0);

	// Alloc control endpoint with the new USB address
	if (!uhd_ep0_alloc(UHC_DEVICE_ENUM_ADD,
			uhc_dev_enum->dev_desc.bMaxPacketSize0)) {
		uhc_enumeration_error(UHC_ENUM_HARDWARE_LIMIT);
		return;
	}
	// Send USB device descriptor request
	req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
	req.bRequest = USB_REQ_GET_DESCRIPTOR;
	req.wValue = (USB_DT_DEVICE << 8);
	req.wIndex = 0;
	req.wLength = sizeof(usb_dev_desc_t);
	if (!uhd_setup_request(UHC_DEVICE_ENUM_ADD,
			&req,
			(uint8_t *) & uhc_dev_enum->dev_desc,
			sizeof(usb_dev_desc_t),
			NULL, uhc_enumeration_step12)) {
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
}
Esempio n. 4
0
File: uhc.c Progetto: InSoonPark/asf
/**
 * \brief Device enumeration step 5
 * Requests the USB device descriptor.
 * This setup request can be aborted
 * because the control endpoint size is unknown.
 */
static void uhc_enumeration_step5(void)
{
	usb_setup_req_t req;

	req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
	req.bRequest = USB_REQ_GET_DESCRIPTOR;
	req.wValue = (USB_DT_DEVICE << 8);
	req.wIndex = 0;
	req.wLength = offsetof(uhc_device_t, dev_desc.bMaxPacketSize0)
			+ sizeof(uhc_dev_enum->dev_desc.bMaxPacketSize0);

	// After a USB reset, the reallocation is required
	uhd_ep_free(0, 0);
	if (!uhd_ep0_alloc(0, 64)) {
		uhc_enumeration_error(UHC_ENUM_HARDWARE_LIMIT);
		return;
	}
	if (!uhd_setup_request(0,
			&req,
			(uint8_t*)&uhc_dev_enum->dev_desc,
			sizeof(usb_dev_desc_t),
			NULL,
			uhc_enumeration_step6)) {
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
}
Esempio n. 5
0
File: uhi_cdc.c Progetto: marekr/asf
static bool uhi_cdc_set_ctrl_line(uint8_t port, le16_t wValue)
{
	uhi_cdc_port_t *ptr_port;
	usb_setup_req_t req;

	// Select port
	ptr_port = uhi_cdc_get_port(port);
	if (ptr_port == NULL) {
		return false;
	}

	// Enable configuration
	req.bmRequestType = USB_REQ_RECIP_INTERFACE | USB_REQ_TYPE_CLASS | USB_REQ_DIR_OUT;
	req.bRequest = USB_REQ_CDC_SET_CONTROL_LINE_STATE;
	req.wValue = wValue;
	req.wIndex = ptr_port->iface_comm;
	req.wLength = 0;
	if (!uhd_setup_request(uhi_cdc_dev.dev->address,
			&req,
			NULL,
			0,
			NULL, NULL)) {
		return false;
	}
	return true;
}
Esempio n. 6
0
File: uhc.c Progetto: InSoonPark/asf
bool uhc_dev_is_high_speed_support(uhc_device_t* dev)
{
	usb_setup_req_t req;
	usb_dev_qual_desc_t qualifier;

	if (dev->speed == UHD_SPEED_HIGH) {
		return true;
	}
	if (dev->speed == UHD_SPEED_FULL) {
		req.bmRequestType = USB_REQ_RECIP_DEVICE
				| USB_REQ_TYPE_STANDARD | USB_REQ_DIR_IN;
		req.bRequest = USB_REQ_GET_DESCRIPTOR;
		req.wValue = (USB_DT_DEVICE_QUALIFIER << 8);
		req.wIndex = 0;
		req.wLength = sizeof(qualifier);

		// Get the size of string
		uhc_setup_request_finish = false;
		if (!uhd_setup_request(0,
				&req,
				(uint8_t*)&qualifier,
				sizeof(qualifier),
				NULL,
				uhc_setup_request_callback)) {
			return NULL;
		}
		while (!uhc_setup_request_finish);
		return uhc_setup_request_finish_status;
	}
	return false; // Low speed device
}
Esempio n. 7
0
File: uhi_cdc.c Progetto: marekr/asf
static bool uhi_cdc_set_conf(uint8_t port, usb_cdc_line_coding_t *configuration)
{
	uhi_cdc_port_t *ptr_port;
	usb_setup_req_t req;

	// Select port
	ptr_port = uhi_cdc_get_port(port);
	if (ptr_port == NULL) {
		return false;
	}
	memcpy(&ptr_port->conf, configuration, sizeof(usb_cdc_line_coding_t));

	// Enable configuration
	req.bmRequestType = USB_REQ_RECIP_INTERFACE | USB_REQ_TYPE_CLASS | USB_REQ_DIR_OUT;
	req.bRequest = USB_REQ_CDC_SET_LINE_CODING;
	req.wValue = 0;
	req.wIndex = ptr_port->iface_comm;
	req.wLength = sizeof(usb_cdc_line_coding_t);
	if (!uhd_setup_request(uhi_cdc_dev.dev->address,
			&req,
			(uint8_t *) &ptr_port->conf,
			sizeof(usb_cdc_line_coding_t),
			NULL, NULL)) {
		return false;
	}
	return true;
}
Esempio n. 8
0
File: uhc.c Progetto: InSoonPark/asf
/**
 * \brief Device enumeration step 9
 * Send a Set address setup request.
 */
static void uhc_enumeration_step9(void)
{
	usb_setup_req_t req;

	req.bmRequestType = USB_REQ_RECIP_DEVICE
			| USB_REQ_TYPE_STANDARD | USB_REQ_DIR_OUT;
	req.bRequest = USB_REQ_SET_ADDRESS;
#ifdef USB_HOST_HUB_SUPPORT
	uint8_t usb_addr_free = 0;
	uhc_device_t *dev;

	// Search free address
	dev = &g_uhc_device_root;
	while (usb_addr_free++) {
		if (dev->address == usb_addr_free) {
			continue;
		}
		if (dev->next != NULL) {
			dev = dev->next;
			continue;
		}
		break;
	}
	req.wValue = usb_addr_free;
	uhc_dev_enum->address = usb_addr_free;
#else
	req.wValue = UHC_DEVICE_ENUM_ADD;
	uhc_dev_enum->address = UHC_DEVICE_ENUM_ADD;
#endif
	req.wIndex = 0;
	req.wLength = 0;

	// After a USB reset, the reallocation is required
	uhd_ep_free(0, 0);
	if (!uhd_ep0_alloc(0, uhc_dev_enum->dev_desc.bMaxPacketSize0)) {
		uhc_enumeration_error(UHC_ENUM_HARDWARE_LIMIT);
		return;
	}

	if (!uhd_setup_request(0,
			&req,
			(uint8_t*)&uhc_dev_enum->dev_desc,
			sizeof(usb_dev_desc_t),
			NULL,
			uhc_enumeration_step10)) {
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
}
Esempio n. 9
0
File: uhc.c Progetto: InSoonPark/asf
/**
 * \brief Device enumeration step 12
 * Requests the first USB structure of the USB configuration descriptor.
 *
 * \param add           USB address of the setup request
 * \param status        Transfer status
 * \param payload_trans Number of data transfered during DATA phase
 */
static void uhc_enumeration_step12(
		usb_add_t add,
		uhd_trans_status_t status,
		uint16_t payload_trans)
{
	usb_setup_req_t req;
	uint8_t conf_num;
	UNUSED(add);

	if ((status != UHD_TRANS_NOERROR) || (payload_trans != sizeof(usb_dev_desc_t))
			|| (uhc_dev_enum->dev_desc.bDescriptorType != USB_DT_DEVICE)) {
		uhc_enumeration_error((status==UHD_TRANS_DISCONNECT)?
				UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
		return;
	}
	// Choose USB device configuration
	if (uhc_dev_enum->dev_desc.bNumConfigurations > 1) {
		conf_num = UHC_DEVICE_CONF(uhc_dev_enum);
	} else {
		conf_num = 1;
	}

	uhc_dev_enum->conf_desc = malloc(sizeof(usb_conf_desc_t));
	if (uhc_dev_enum->conf_desc == NULL) {
		Assert(false);
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
	// Send USB device descriptor request
	req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
	req.bRequest = USB_REQ_GET_DESCRIPTOR;
	req.wValue = (USB_DT_CONFIGURATION << 8) | (conf_num - 1);
	req.wIndex = 0;
	req.wLength = sizeof(usb_conf_desc_t);
	if (!uhd_setup_request(UHC_DEVICE_ENUM_ADD,
			&req,
			(uint8_t *) uhc_dev_enum->conf_desc,
			sizeof(usb_conf_desc_t),
			NULL, uhc_enumeration_step13)) {
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
}
Esempio n. 10
0
bool uhi_vendor_control_out_run(uint8_t * buf, iram_size_t buf_size,
		uhd_callback_setup_end_t callback)
{
	usb_setup_req_t req;

	if (uhi_vendor_dev.dev == NULL) {
		return false;
	}
	req.bmRequestType = USB_REQ_RECIP_INTERFACE|USB_REQ_TYPE_VENDOR;
	req.bRequest = 0;
	req.wValue = 0;
	req.wIndex = 0;
	req.wLength = buf_size;
	return uhd_setup_request(uhi_vendor_dev.dev->address,
			&req,
			buf,
			buf_size,
			NULL,
			callback);
}
Esempio n. 11
0
void uhi_vendor_enable(uhc_device_t* dev)
{
	usb_setup_req_t req;

	if (uhi_vendor_dev.dev != dev) {
		return;  // No interface to enable
	}

	// Choose the alternate setting 1 which contains all endpoints
	req.bmRequestType = USB_REQ_RECIP_INTERFACE;
	req.bRequest = USB_REQ_SET_INTERFACE;
	req.wValue = 1; // Alternate setting 1
	req.wIndex = uhi_vendor_dev.bInterfaceNumber;
	req.wLength = 0;
	uhd_setup_request(uhi_vendor_dev.dev->address,
			&req,
			NULL,
			0,
			NULL,
			NULL);

	UHI_VENDOR_CHANGE(dev, true);
}
Esempio n. 12
0
File: uhc.c Progetto: InSoonPark/asf
/**
 * \brief Device enumeration step 14
 * Enable USB configuration, if unless one USB interface is supported by UHIs.
 *
 * \param add           USB address of the setup request
 * \param status        Transfer status
 * \param payload_trans Number of data transfered during DATA phase
 */
static void uhc_enumeration_step14(
		usb_add_t add,
		uhd_trans_status_t status,
		uint16_t payload_trans)
{
	usb_setup_req_t req;
	bool b_conf_supported = false;
	UNUSED(add);

	if ((status != UHD_TRANS_NOERROR)
			|| (payload_trans < sizeof(usb_conf_desc_t))
			|| (uhc_dev_enum->conf_desc->bDescriptorType != USB_DT_CONFIGURATION)
			|| (payload_trans != le16_to_cpu(uhc_dev_enum->conf_desc->wTotalLength))) {
		uhc_enumeration_error((status==UHD_TRANS_DISCONNECT)?
				UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
		return;
	}
	// Check if unless one USB interface is supported by UHIs
	for (uint8_t i = 0; i < UHC_NB_UHI; i++) {
		switch (uhc_uhis[i].install(uhc_dev_enum)) {
		case UHC_ENUM_SUCCESS:
			b_conf_supported = true;
			break;

		case UHC_ENUM_UNSUPPORTED:
			break;

		default:
			// USB host hardware limitation
			// Free all endpoints
			uhd_ep_free(UHC_DEVICE_ENUM_ADD,0xFF);
			UHC_ENUM_EVENT(uhc_dev_enum,UHC_ENUM_HARDWARE_LIMIT);

			// Abort enumeration, set line in suspend mode
			uhc_enumeration_suspend();
			return;
		}
	}
	if (!b_conf_supported) {
		// No USB interface supported
		UHC_ENUM_EVENT(uhc_dev_enum, UHC_ENUM_UNSUPPORTED);

		// Abort enumeration, set line in suspend mode
		uhc_enumeration_suspend();
		return;
	}
	// Enable device configuration
	req.bmRequestType = USB_REQ_RECIP_DEVICE
			| USB_REQ_TYPE_STANDARD | USB_REQ_DIR_OUT;
	req.bRequest = USB_REQ_SET_CONFIGURATION;
	req.wValue = uhc_dev_enum->conf_desc->bConfigurationValue;
	req.wIndex = 0;
	req.wLength = 0;
	if (!uhd_setup_request(UHC_DEVICE_ENUM_ADD,
			&req,
			NULL,
			0,
			NULL, uhc_enumeration_step15)) {
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
}
Esempio n. 13
0
File: uhc.c Progetto: InSoonPark/asf
/**
 * \brief Device enumeration step 13
 * Requests a complete Get configuration descriptor.
 *
 * \param add           USB address of the setup request
 * \param status        Transfer status
 * \param payload_trans Number of data transfered during DATA phase
 */
static void uhc_enumeration_step13(
		usb_add_t add,
		uhd_trans_status_t status,
		uint16_t payload_trans)
{
	uint8_t conf_num;
	uint16_t conf_size;
	uint16_t bus_power = 0;
	usb_setup_req_t req;
	UNUSED(add);

	if ((status != UHD_TRANS_NOERROR) || (payload_trans != sizeof(usb_conf_desc_t))
			|| (uhc_dev_enum->conf_desc->bDescriptorType != USB_DT_CONFIGURATION)) {
		uhc_enumeration_error((status == UHD_TRANS_DISCONNECT)?
				UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
		return;
	}
#ifdef USB_HOST_HUB_SUPPORT
	uhc_device_t *dev;
	dev = uhc_dev_enum;
	while (1) {
		if (dev->conf_desc->bmAttributes & USB_CONFIG_ATTR_SELF_POWERED) {
			// The device or a parent HUB is SELF power, then no power on root
			break;
		}
		if (dev == (&g_uhc_device_root)) {
			bus_power = uhc_dev_enum->conf_desc->bMaxPower * 2;
			break; // End of USB tree
		}
		// Go to USB HUB parent
		dev = dev->hub;
	}
#else
	if (!(uhc_dev_enum->conf_desc->bmAttributes
			&USB_CONFIG_ATTR_SELF_POWERED)) {
		bus_power = uhc_dev_enum->conf_desc->bMaxPower * 2;
	}
#endif
	if ((bus_power + uhc_power_running) > USB_HOST_POWER_MAX) {
		// USB interfaces consumption too high
		UHC_ENUM_EVENT(uhc_dev_enum, UHC_ENUM_OVERCURRENT);

		// Abort enumeration, set line in suspend mode
		uhc_enumeration_suspend();
		return;
	}
#ifdef USB_HOST_HUB_SUPPORT
	uhc_dev_enum->power = bus_power;
	uhc_power_running += bus_power;
#endif

	// Save information about USB configuration descriptor size
	conf_size = le16_to_cpu(uhc_dev_enum->conf_desc->wTotalLength);
	conf_num = uhc_dev_enum->conf_desc->bConfigurationValue;
	Assert(conf_num);
	// Re alloc USB configuration descriptor
	free(uhc_dev_enum->conf_desc);
	uhc_dev_enum->conf_desc = malloc(conf_size);
	if (uhc_dev_enum->conf_desc == NULL) {
		Assert(false);
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
	// Send USB device descriptor request
	req.bmRequestType =
			USB_REQ_RECIP_DEVICE | USB_REQ_TYPE_STANDARD |
			USB_REQ_DIR_IN;
	req.bRequest = USB_REQ_GET_DESCRIPTOR;
	req.wValue = (USB_DT_CONFIGURATION << 8) | (conf_num - 1);
	req.wIndex = 0;
	req.wLength = conf_size;
	if (!uhd_setup_request(UHC_DEVICE_ENUM_ADD,
			&req,
			(uint8_t *) uhc_dev_enum->conf_desc,
			conf_size,
			NULL, uhc_enumeration_step14)) {
		uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
		return;
	}
}
Esempio n. 14
0
File: uhc.c Progetto: InSoonPark/asf
char *uhc_dev_get_string(uhc_device_t * dev, uint8_t str_id)
{
	usb_setup_req_t req;
	usb_str_desc_t str_header;
	usb_str_lgid_desc_t *str_desc;
	char *string;
	uint8_t i;
	UNUSED(dev);

	req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
	req.bRequest = USB_REQ_GET_DESCRIPTOR;
	req.wValue = (USB_DT_STRING << 8) | str_id;
	req.wIndex = 0;
	req.wLength = sizeof(usb_str_desc_t);

	// Get the size of string
	uhc_setup_request_finish = false;
	if (!uhd_setup_request(0,
			&req,
			(uint8_t*)&str_header,
			sizeof(usb_str_desc_t),
			NULL,
			uhc_setup_request_callback)) {
		return NULL;
	}
	while (!uhc_setup_request_finish);
	if (!uhc_setup_request_finish_status) {
		return NULL;
	}
	// Get the size of string
	str_desc = malloc(str_header.bLength);
	if (str_desc == NULL) {
		return NULL;
	}
	req.wLength = str_header.bLength;
	uhc_setup_request_finish = false;
	if (!uhd_setup_request(0,
			&req,
			(uint8_t*)str_desc,
			str_header.bLength,
			NULL,
			uhc_setup_request_callback)) {
		return NULL;
	}
	while (!uhc_setup_request_finish);
	if (!uhc_setup_request_finish_status) {
		free(str_desc);
		return NULL;
	}
	// The USB strings are "always" in ASCII format, then translate it.
	str_header.bLength = (str_header.bLength - 2) / 2; // Number of character
	string = malloc(str_header.bLength + 1); // +1 for NULL terminal
	if (string == NULL) {
		free(str_desc);
		return NULL;
	}
	for (i = 0; i < str_header.bLength; i++) {
		string[i] = le16_to_cpu(str_desc->string[i]) & 0xFF;
	}
	string[i] = 0;
	free(str_desc);

	return string;
}
Esempio n. 15
0
File: uhc.c Progetto: dinchak/aleph
/**
 * \brief Device enumeration step 14
 * Enable USB configuration, if unless one USB interface is supported by UHIs.
 *
 * \param add           USB address of the setup request
 * \param status        Transfer status
 * \param payload_trans Number of data transfered during DATA phase
 */
static void uhc_enumeration_step14(
				   usb_add_t add,
				   uhd_trans_status_t status,
				   uint16_t payload_trans)
{
  usb_setup_req_t req;
  bool b_conf_supported = false;
  UNUSED(add);

  /////////////////////////////////
  ///// TESTING
#if UHC_PRINT_DBG
  print_dbg("\r\n received device descriptor. ");

  print_dbg("\r\n address: ");
  print_dbg_hex(uhc_dev_enum -> address);
  print_dbg("\r\n speed: ");
  print_dbg_hex(uhc_dev_enum -> speed);
  print_dbg("\r\n\r\n");

  print_dbg("\r\n dev desc -> bLength : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.bLength);
  print_dbg("\r\n dev desc -> bDescriptorType : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.bDescriptorType);
  print_dbg("\r\n dev desc -> bcdUSB : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.bcdUSB);
  print_dbg("\r\n dev desc -> bDeviceClass : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.bDeviceClass);
  print_dbg("\r\n dev desc -> bDeviceSubClass : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.bDeviceSubClass);
  print_dbg("\r\n dev desc -> bDeviceProtocol : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.bDeviceProtocol);
  print_dbg("\r\n dev desc -> bMaxPacketSize0 : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.bMaxPacketSize0);
  print_dbg("\r\n dev desc -> idVendor : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.idVendor);
  print_dbg("\r\n dev desc -> idProduct : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.idProduct);
  print_dbg("\r\n dev desc -> bcdDevice : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.bcdDevice);
  print_dbg("\r\n dev desc -> iManufacturer : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.iManufacturer);
  print_dbg("\r\n dev desc -> iProduct : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.iProduct);
  print_dbg("\r\n dev desc -> iSerialNumber : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.iSerialNumber);
  print_dbg("\r\n dev desc -> bNumConfigurations : ");
  print_dbg_hex(uhc_dev_enum->dev_desc.bNumConfigurations);
  print_dbg("\r\n\r\n");
	
  print_dbg("\r\n conf desc -> bLength : ");
  print_dbg_hex(uhc_dev_enum->conf_desc->bLength);
  print_dbg("\r\n conf desc -> bDescriptorType : ");
  print_dbg_hex(uhc_dev_enum->conf_desc->bDescriptorType);
  print_dbg("\r\n conf desc -> wTotalLength : ");
  print_dbg_hex(uhc_dev_enum->conf_desc->wTotalLength);
  print_dbg("\r\n conf desc -> bNumInterfaces : ");
  print_dbg_hex(uhc_dev_enum->conf_desc->bNumInterfaces);
  print_dbg("\r\n conf desc -> bConfigurationValue : ");
  print_dbg_hex(uhc_dev_enum->conf_desc->bConfigurationValue);
  print_dbg("\r\n conf desc -> iConfiguration : ");
  print_dbg_hex(uhc_dev_enum->conf_desc->iConfiguration);
  print_dbg("\r\n conf desc -> bmAttributes : ");
  print_dbg_hex(uhc_dev_enum->conf_desc->bmAttributes);
  print_dbg("\r\n conf desc -> bMaxPower : ");
  print_dbg_hex(uhc_dev_enum->conf_desc->bMaxPower);
#endif
  /////////////////////////////////
  /////////////////////////////////

  if ((status != UHD_TRANS_NOERROR)
      || (payload_trans < sizeof(usb_conf_desc_t))
      || (uhc_dev_enum->conf_desc->bDescriptorType != USB_DT_CONFIGURATION)
      || (payload_trans != le16_to_cpu(uhc_dev_enum->conf_desc->wTotalLength))) {
    uhc_enumeration_error((status==UHD_TRANS_DISCONNECT)?
			  UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
    return;
  }
  // Check if unless one USB interface is supported by UHIs
  for (uint8_t i = 0; i < UHC_NB_UHI; i++) {
    switch (uhc_uhis[i].install(uhc_dev_enum)) {
    case UHC_ENUM_SUCCESS:
      b_conf_supported = true;
      break;
    case UHC_ENUM_UNSUPPORTED:
      break;
    default:
      // USB host hardware limitation
      // Free all endpoints
      uhd_ep_free(UHC_DEVICE_ENUM_ADD,0xFF);
      UHC_ENUM_EVENT(uhc_dev_enum,UHC_ENUM_HARDWARE_LIMIT);

      // Abort enumeration, set line in suspend mode
      uhc_enumeration_suspend();
      return;
    }
  }
  if (!b_conf_supported) {
    // No USB interface supported
    UHC_ENUM_EVENT(uhc_dev_enum, UHC_ENUM_UNSUPPORTED);

    // Abort enumeration, set line in suspend mode
    uhc_enumeration_suspend();
    return;
  }
  // Enable device configuration
  req.bmRequestType = USB_REQ_RECIP_DEVICE
    | USB_REQ_TYPE_STANDARD | USB_REQ_DIR_OUT;
  req.bRequest = USB_REQ_SET_CONFIGURATION;
  req.wValue = uhc_dev_enum->conf_desc->bConfigurationValue;
  req.wIndex = 0;
  req.wLength = 0;
  //  print_dbg("\r\n device enumeration successful; calling uhd_setup_request in uhc.c");
  if (!uhd_setup_request(UHC_DEVICE_ENUM_ADD,
			 &req,
			 NULL,
			 0,
			 NULL, uhc_enumeration_step15)) {
    uhc_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
    return;
  }
}