Esempio n. 1
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. 2
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. 3
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. 4
0
File: uhc.c Progetto: InSoonPark/asf
/**
 * \brief Manage a device plug or unplug on the USB tree
 *
 * \param b_plug   true, if it is a device connection
 * \param dev      Information about device connected or disconnected
 */
static void uhc_connection_tree(bool b_plug, uhc_device_t* dev)
{
	if (b_plug) {
		uhc_enum_try = 1;
#ifdef USB_HOST_HUB_SUPPORT
		uhc_dev_enum = dev;
#endif
		uhc_dev_enum->conf_desc = NULL;
		uhc_dev_enum->address = 0;
		UHC_CONNECTION_EVENT(uhc_dev_enum, true);
		uhc_enumeration_step1();
	} else {
		if (uhc_dev_enum == dev) {
			// Eventually stop enumeration timeout on-going on this device
			uhc_sof_timeout = 0;
		}
		// Abort all transfers (endpoint control and other) and free pipe(s)
		uhd_ep_free(dev->address, 0xFF);

		// Disable all USB interfaces (this includes HUB interface)
		for (uint8_t i = 0; i < UHC_NB_UHI; i++) {
			uhc_uhis[i].uninstall(dev);
		}

		UHC_CONNECTION_EVENT(dev, false);
		dev->address = UHC_USB_ADD_NOT_VALID;
		// Free USB configuration descriptor buffer
		if (dev->conf_desc != NULL) {
			free(dev->conf_desc);
		}
#ifdef USB_HOST_HUB_SUPPORT
		uhc_power_running -= dev->power;
		if (&g_uhc_device_root != dev) {
			// It is on a USB hub
			dev->prev->next = dev->next;
			dev->next->prev = dev->prev;
			free(dev);
		}
#endif
	}
}
Esempio n. 5
0
File: uhc.c Progetto: 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;
}
Esempio n. 6
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. 7
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;
  }
}