Ejemplo n.º 1
0
Archivo: uhc.c Proyecto: InSoonPark/asf
/**
 * \brief Device enumeration step 17 (LPM only)
 * Check LPM support through the BOS descriptor received
 *
 * \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_step17_lpm(
		usb_add_t add,
		uhd_trans_status_t status,
		uint16_t payload_trans)
{
	UNUSED(add);

	if (status == UHD_TRANS_STALL) {
		free(uhc_dev_enum->lpm_desc);
		uhc_dev_enum->lpm_desc = NULL;
	} else if ((status != UHD_TRANS_NOERROR)
			|| (payload_trans < sizeof(usb_dev_lpm_desc_t))
			|| (uhc_dev_enum->lpm_desc->bos.bDescriptorType != USB_DT_BOS)
			|| (payload_trans != le16_to_cpu(uhc_dev_enum->lpm_desc->bos.wTotalLength))) {
		uhc_enumeration_error((status==UHD_TRANS_DISCONNECT)?
				UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
		return;
	} else if (status == UHD_TRANS_NOERROR) {
		// Check LPM support
		if ((uhc_dev_enum->lpm_desc->capa_ext.bDescriptorType != USB_DT_DEVICE_CAPABILITY)
				|| (uhc_dev_enum->lpm_desc->capa_ext.bDevCapabilityType != USB_DC_USB20_EXTENSION)
					|| (!(uhc_dev_enum->lpm_desc->capa_ext.bmAttributes & (USB_DC_EXT_LPM)))) {
			free(uhc_dev_enum->lpm_desc);
			uhc_dev_enum->lpm_desc = NULL;
		}
	}

	uhc_enum_try = 0;
	UHC_ENUM_EVENT(uhc_dev_enum, UHC_ENUM_SUCCESS);
}
Ejemplo n.º 2
0
Archivo: uhc.c Proyecto: InSoonPark/asf
/**
 * \brief Device enumeration step 15
 * Enables UHI interfaces
 *
 * \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_step15(
		usb_add_t add,
		uhd_trans_status_t status,
		uint16_t payload_trans)
{
	UNUSED(add);
	if ((status!=UHD_TRANS_NOERROR) || (payload_trans!=0)) {
		for(uint8_t i = 0; i < UHC_NB_UHI; i++) {
			uhc_uhis[i].uninstall(uhc_dev_enum);
		}
		uhc_enumeration_error((status == UHD_TRANS_DISCONNECT)?
				UHC_ENUM_DISCONNECT : UHC_ENUM_FAIL);
		return;
	}

	// Enable all UHIs supported
	for (uint8_t i = 0; i < UHC_NB_UHI; i++) {
		uhc_uhis[i].enable(uhc_dev_enum);
	}

#ifdef USB_HOST_LPM_SUPPORT
	// Check LPM support
	if (g_uhc_device_root.dev_desc.bcdUSB >= LE16(USB_V2_1)) {
		// Device can support LPM
		// Start LPM support check
		uhc_enumeration_step16_lpm();
		return;
	}
	uhc_dev_enum->lpm_desc = NULL;
#endif

	uhc_enum_try = 0;

	UHC_ENUM_EVENT(uhc_dev_enum, UHC_ENUM_SUCCESS);
}
Ejemplo n.º 3
0
Archivo: uhc.c Proyecto: dinchak/aleph
/**
 * \brief Device enumeration step 15
 * Enables UHI interfaces
 *
 * \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_step15(
				   usb_add_t add,
				   uhd_trans_status_t status,
				   uint16_t payload_trans)
{
  UNUSED(add);
  if ((status!=UHD_TRANS_NOERROR) || (payload_trans!=0)) {
    for(uint8_t i = 0; i < UHC_NB_UHI; i++) {
      uhc_uhis[i].uninstall(uhc_dev_enum);
    }
    uhc_enumeration_error((status == UHD_TRANS_DISCONNECT)?
			  UHC_ENUM_DISCONNECT : UHC_ENUM_FAIL);
    return;
  }

  // Enable all UHIs supported
  for (uint8_t i = 0; i < UHC_NB_UHI; i++) {
#if UHC_PRINT_DBG
    print_dbg("\r\n enabling UHI, idx: "); print_dbg_ulong(i); 
#endif
    uhc_uhis[i].enable(uhc_dev_enum);
  }
  uhc_enum_try = 0;
	
  UHC_ENUM_EVENT(uhc_dev_enum, UHC_ENUM_SUCCESS);
}
Ejemplo n.º 4
0
Archivo: uhc.c Proyecto: InSoonPark/asf
/**
 * \brief Manage error during device enumeration
 *
 * \param status        Enumeration error occurred
 */
static void uhc_enumeration_error(uhc_enum_status_t status)
{
	if (status == UHC_ENUM_DISCONNECT) {
		uhc_enum_try = 0;
		return; // Abort enumeration process
	}
	uhd_ep_free(uhc_dev_enum->address, 0xFF);

	// Free USB configuration descriptor buffer
	if (uhc_dev_enum->conf_desc != NULL) {
		free(uhc_dev_enum->conf_desc);
		uhc_dev_enum->conf_desc = NULL;
	}
	uhc_dev_enum->address = 0;
	if (uhc_enum_try++ < UHC_ENUM_NB_TRY) {
		// Restart enumeration at beginning
		uhc_enumeration_step1();
		return;
	}
	// Abort enumeration, set line in suspend mode
	uhc_enumeration_suspend();
	UHC_ENUM_EVENT(uhc_dev_enum, status);
	uhc_enum_try = 0;
}
Ejemplo n.º 5
0
Archivo: uhc.c Proyecto: 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;
	}
}
Ejemplo n.º 6
0
Archivo: uhc.c Proyecto: 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;
	}
}
Ejemplo n.º 7
0
Archivo: uhc.c Proyecto: 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;
  }
}