コード例 #1
0
/*****************************************************************
 *
 * Function Name: hc_reset
 *
 * This function does register test and resets the SL811HS 
 * controller.
 *
 * Input:  hci = data structure for the host controller
 *
 * Return value  : 0
 *                
 *****************************************************************/
static int hc_reset (hci_t * hci)
{
	int attachFlag = 0;

	DBGFUNC ("Enter hc_reset\n");
	regTest (hci);
	attachFlag = USBReset (hci);
	if (attachFlag) {
		setPortChange (hci, PORT_CONNECT_CHANGE);
	}
	return (0);
}
コード例 #2
0
/***************************************************************************
 * Function Name : rh_submit_urb
 * 
 * This function handles all USB request to the the virtual root hub
 * 
 * Input: urb = USB request block 
 *
 * Return: 0  
 **************************************************************************/
static int rh_submit_urb (struct urb * urb)
{
	struct usb_device *usb_dev = urb->dev;
	hci_t *hci = usb_dev->bus->hcpriv;
	unsigned int pipe = urb->pipe;
	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
	void *data = urb->transfer_buffer;
	int leni = urb->transfer_buffer_length;
	int len = 0;
	int status = TD_CC_NOERROR;
	__u32 datab[4];
	__u8 *data_buf = (__u8 *) datab;

	__u16 bmRType_bReq;
	__u16 wValue;
	__u16 wIndex;
	__u16 wLength;

	DBGFUNC ("enter rh_submit_urb\n");
	if (usb_pipeint (pipe)) {
		hci->rh.urb = urb;
		hci->rh.send = 1;
		hci->rh.interval = urb->interval;
		rh_init_int_timer (urb);
		urb->status = cc_to_error (TD_CC_NOERROR);

		return 0;
	}

	bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8);
	wValue = le16_to_cpu (cmd->wValue);
	wIndex = le16_to_cpu (cmd->wIndex);
	wLength = le16_to_cpu (cmd->wLength);

	DBG ("rh_submit_urb, req = %d(%x) len=%d",
	     bmRType_bReq, bmRType_bReq, wLength);

	switch (bmRType_bReq) {
		/* Request Destination:
		   without flags: Device, 
		   RH_INTERFACE: interface, 
		   RH_ENDPOINT: endpoint,
		   RH_CLASS means HUB here, 
		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
		 */

	case RH_GET_STATUS:
		*(__u16 *) data_buf = cpu_to_le16 (1);
		OK (2);

	case RH_GET_STATUS | RH_INTERFACE:
		*(__u16 *) data_buf = cpu_to_le16 (0);
		OK (2);

	case RH_GET_STATUS | RH_ENDPOINT:
		*(__u16 *) data_buf = cpu_to_le16 (0);
		OK (2);

	case RH_GET_STATUS | RH_CLASS:
		*(__u32 *) data_buf = cpu_to_le32 (0);
		OK (4);

	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
		*(__u32 *) data_buf =
		    cpu_to_le32 (getPortStatusAndChange (hci));
		OK (4);

	case RH_CLEAR_FEATURE | RH_ENDPOINT:
		switch (wValue) {
		case (RH_ENDPOINT_STALL):
			OK (0);
		}
		break;

	case RH_CLEAR_FEATURE | RH_CLASS:
		switch (wValue) {
		case RH_C_HUB_LOCAL_POWER:
			OK (0);

		case (RH_C_HUB_OVER_CURRENT):
			/* Over Current Not Implemented */
			OK (0);
		}
		break;

	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
		switch (wValue) {
		case (RH_PORT_ENABLE):
			clrPortStatus (hci, PORT_ENABLE_STAT);
			OK (0);

		case (RH_PORT_SUSPEND):
			clrPortStatus (hci, PORT_SUSPEND_STAT);
			OK (0);

		case (RH_PORT_POWER):
			clrPortStatus (hci, PORT_POWER_STAT);
			OK (0);

		case (RH_C_PORT_CONNECTION):
			clrPortChange (hci, PORT_CONNECT_STAT);
			OK (0);

		case (RH_C_PORT_ENABLE):
			clrPortChange (hci, PORT_ENABLE_STAT);
			OK (0);

		case (RH_C_PORT_SUSPEND):
			clrPortChange (hci, PORT_SUSPEND_STAT);
			OK (0);

		case (RH_C_PORT_OVER_CURRENT):
			clrPortChange (hci, PORT_OVER_CURRENT_STAT);
			OK (0);

		case (RH_C_PORT_RESET):
			clrPortChange (hci, PORT_RESET_STAT);
			OK (0);
		}
		break;

	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
		switch (wValue) {
		case (RH_PORT_SUSPEND):
			setPortStatus (hci, PORT_SUSPEND_STAT);
			OK (0);

		case (RH_PORT_RESET):
			setPortStatus (hci, PORT_RESET_STAT);
			// USBReset(hci);
			clrPortChange (hci,
				       PORT_CONNECT_CHANGE | PORT_ENABLE_CHANGE
				       | PORT_SUSPEND_CHANGE |
				       PORT_OVER_CURRENT_CHANGE);
			setPortChange (hci, PORT_RESET_CHANGE);
			clrPortStatus (hci, PORT_RESET_STAT);
			setPortStatus (hci, PORT_ENABLE_STAT);

			OK (0);

		case (RH_PORT_POWER):
			setPortStatus (hci, PORT_POWER_STAT);
			OK (0);

		case (RH_PORT_ENABLE):
			setPortStatus (hci, PORT_ENABLE_STAT);
			OK (0);
		}
		break;

	case RH_SET_ADDRESS:
		hci->rh.devnum = wValue;
		OK (0);

	case RH_GET_DESCRIPTOR:
		DBGVERBOSE ("rh_submit_urb: RH_GET_DESCRIPTOR, wValue = 0x%x\n", wValue);
		switch ((wValue & 0xff00) >> 8) {
		case (0x01):	/* device descriptor */
			len = min (leni, min ((__u16)sizeof (root_hub_dev_des), wLength));
			data_buf = root_hub_dev_des;
			OK (len);

		case (0x02):	/* configuration descriptor */
			len = min (leni, min ((__u16)sizeof (root_hub_config_des), wLength));
			data_buf = root_hub_config_des;
			OK (len);

		case (0x03):	/* string descriptors */
			len = root_hub_string (wValue & 0xff, (int) (long) 0,
						   "SL811HS", data, wLength);
			if (len > 0) {
				data_buf = data;
				OK (min (leni, len));
			}

		default:
			status = SL11H_STATMASK_STALL;
		}
		break;

	case RH_GET_DESCRIPTOR | RH_CLASS:
		data_buf[0] = 9;	// min length;
		data_buf[1] = 0x29;
		data_buf[2] = 1;	// # of downstream port
		data_buf[3] = 0;
		datab[1] = 0;
		data_buf[5] = 50;	// 100 ms for port reset
		data_buf[7] = 0xfc;	// which port is attachable
		if (data_buf[2] < 7) {
			data_buf[8] = 0xff;
		} else {
		}

		len = min (leni, min ((__u16)data_buf[0], wLength));
		OK (len);

	case RH_GET_CONFIGURATION:
		*(__u8 *) data_buf = 0x01;
		OK (1);

	case RH_SET_CONFIGURATION:
		OK (0);

	default:
		DBGERR ("unsupported root hub command");
		status = SL11H_STATMASK_STALL;
	}

	len = min (len, leni);
	if (data != data_buf)
		memcpy (data, data_buf, len);
	urb->actual_length = len;
	urb->status = cc_to_error (status);

	urb->hcpriv = NULL;
	urb->dev = NULL;
	if (urb->complete) {
		urb->complete (urb, NULL);
	}

	return 0;
}