boolean USBStandardHubConfigure (TUSBDevice *pUSBDevice)
{
	TUSBStandardHub *pThis = (TUSBStandardHub *) pUSBDevice;
	assert (pThis != 0);

	const TUSBDeviceDescriptor *pDeviceDesc = USBDeviceGetDeviceDescriptor (&pThis->m_USBDevice);
	assert (pDeviceDesc != 0);

	if (   pDeviceDesc->bDeviceClass       != USB_DEVICE_CLASS_HUB
	    || pDeviceDesc->bDeviceSubClass    != 0
	    || pDeviceDesc->bDeviceProtocol    != 2		// hub with multiple TTs
	    || pDeviceDesc->bNumConfigurations != 1)
	{
		LogWrite (FromHub, LOG_ERROR, "Unsupported hub (proto %u)",
			     (unsigned) pDeviceDesc->bDeviceProtocol);

		return FALSE;
	}

	const TUSBConfigurationDescriptor *pConfigDesc =
		(TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION);
	if (   pConfigDesc == 0
	    || pConfigDesc->bNumInterfaces != 1)
	{
		USBDeviceConfigurationError (&pThis->m_USBDevice, FromHub);

		return FALSE;
	}

	const TUSBInterfaceDescriptor *pInterfaceDesc;
	while ((pInterfaceDesc = (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE)) != 0)
	{
		if (   pInterfaceDesc->bInterfaceClass    != USB_DEVICE_CLASS_HUB
		    || pInterfaceDesc->bInterfaceSubClass != 0
		    || pInterfaceDesc->bInterfaceProtocol != 2)
		{
			continue;
		}

		if (pInterfaceDesc->bNumEndpoints != 1)
		{
			USBDeviceConfigurationError (&pThis->m_USBDevice, FromHub);

			return FALSE;
		}

		const TUSBEndpointDescriptor *pEndpointDesc =
			(TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT);
		if (   pEndpointDesc == 0
		    || (pEndpointDesc->bEndpointAddress & 0x80) != 0x80		// input EP
		    || (pEndpointDesc->bmAttributes     & 0x3F) != 0x03)	// interrupt EP
		{
			USBDeviceConfigurationError (&pThis->m_USBDevice, FromHub);

			return FALSE;
		}

		break;
	}

	if (pInterfaceDesc == 0)
	{
		USBDeviceConfigurationError (&pThis->m_USBDevice, FromHub);

		return FALSE;
	}

	if (!USBDeviceConfigure (&pThis->m_USBDevice))
	{
		LogWrite (FromHub, LOG_ERROR, "Cannot set configuration");

		return FALSE;
	}

	TUSBHostController *pHost = USBDeviceGetHost (&pThis->m_USBDevice);
	assert (pHost != 0);

	if (pInterfaceDesc->bAlternateSetting != 0)
	{
		if (DWHCIDeviceControlMessage (pHost, USBDeviceGetEndpoint0 (&pThis->m_USBDevice),
						REQUEST_OUT | REQUEST_TO_INTERFACE, SET_INTERFACE,
						pInterfaceDesc->bAlternateSetting,
						pInterfaceDesc->bInterfaceNumber, 0, 0) < 0)
		{
			LogWrite (FromHub, LOG_ERROR, "Cannot set interface");

			return FALSE;
		}
	}

	assert (pThis->m_pHubDesc == 0);
	pThis->m_pHubDesc = (TUSBHubDescriptor *) malloc (sizeof (TUSBHubDescriptor));
	assert (pThis->m_pHubDesc != 0);

	if (DWHCIDeviceGetDescriptor (pHost, USBDeviceGetEndpoint0 (&pThis->m_USBDevice),
					DESCRIPTOR_HUB, DESCRIPTOR_INDEX_DEFAULT,
					pThis->m_pHubDesc, sizeof *pThis->m_pHubDesc,
					REQUEST_IN | REQUEST_CLASS)
	   != (int) sizeof *pThis->m_pHubDesc)
	{
		LogWrite (FromHub, LOG_ERROR, "Cannot get hub descriptor");

		free (pThis->m_pHubDesc);
		pThis->m_pHubDesc = 0;

		return FALSE;
	}

#ifndef NDEBUG
	//DebugHexdump (pThis->m_pHubDesc, sizeof *pThis->m_pHubDesc, FromHub);
#endif

	pThis->m_nPorts = pThis->m_pHubDesc->bNbrPorts;
	if (pThis->m_nPorts > USB_HUB_MAX_PORTS)
	{
		LogWrite (FromHub, LOG_ERROR, "Too many ports (%u)", pThis->m_nPorts);

		free (pThis->m_pHubDesc);
		pThis->m_pHubDesc = 0;

		return FALSE;
	}

	if (!USBStandardHubEnumeratePorts (pThis))
	{
		LogWrite (FromHub, LOG_ERROR, "Port enumeration failed");

		return FALSE;
	}

	return TRUE;
}
Beispiel #2
0
int USPiDeviceGetInformation (unsigned nClass, unsigned nDeviceIndex, TUSPiDeviceInformation *pInfo)
{
	assert (s_pLibrary != 0);

	TUSBDevice *pUSBDevice = 0;

	switch (nClass)
	{
	case KEYBOARD_CLASS:
		if (nDeviceIndex == 0)
		{
			pUSBDevice = (TUSBDevice *) s_pLibrary->pUKBD1;
		}
		break;

	case MOUSE_CLASS:
		if (nDeviceIndex == 0)
		{
			pUSBDevice = (TUSBDevice *) s_pLibrary->pUMouse1;
		}
		break;

	case STORAGE_CLASS:
		if (nDeviceIndex < MAX_DEVICES)
		{
			pUSBDevice = (TUSBDevice *) s_pLibrary->pUMSD[nDeviceIndex];
		}
		break;

	case ETHERNET_CLASS:
		if (nDeviceIndex == 0)
		{
			pUSBDevice = (TUSBDevice *) s_pLibrary->pEth0;
		}
		break;

	case GAMEPAD_CLASS:
		if (nDeviceIndex < MAX_DEVICES)
		{
			pUSBDevice = (TUSBDevice *) s_pLibrary->pUPAD[nDeviceIndex];
		}
		break;

	case MIDI_CLASS:
		if (nDeviceIndex == 0)
		{
			pUSBDevice = (TUSBDevice *) s_pLibrary->pMIDI1;
		}
		break;

	default:
		break;
	}

	if (pUSBDevice == 0)
	{
		return 0;
	}

	const TUSBDeviceDescriptor *pDesc = USBDeviceGetDeviceDescriptor (pUSBDevice);
	assert (pDesc != 0);

	assert (pInfo != 0);
	pInfo->idVendor  = pDesc->idVendor;
	pInfo->idProduct = pDesc->idProduct;
	pInfo->bcdDevice = pDesc->bcdDevice;

	pInfo->pManufacturer = USBStringGet (&pUSBDevice->m_ManufacturerString);
	pInfo->pProduct      = USBStringGet (&pUSBDevice->m_ProductString);

	return 1;
}