Beispiel #1
0
/*****************************************************************
 *
 * Function Name: hc_found_hci
 *
 * This function request IO memory regions, request IRQ, and
 * allocate all other resources. 
 *
 * Input: addr = first IO address
 *        addr2 = second IO address
 *        irq = interrupt number 
 *
 * Return: 0 = success or error condition 
 *                
 *****************************************************************/
static int __devinit hc_found_hci (int addr, int addr2, int irq)
{
	hci_t *hci;
	hcipriv_t *hp;

	DBGFUNC ("Enter hc_found_hci\n");
	hci = hc_alloc_hci ();
	if (!hci) {
		return -ENOMEM;
	}

	init_irq ();
	hp = &hci->hp;

	if (!request_region (addr, 256, "SL811 USB HOST")) {
		DBGERR ("request address %d failed", addr);
		hc_release_hci (hci);
		return -EBUSY;
	}
	hp->hcport = addr;
	if (!hp->hcport) {
		DBGERR ("Error mapping SL811 Memory 0x%x", hp->hcport);
	}

	if (!request_region (addr2, 256, "SL811 USB HOST")) {
		DBGERR ("request address %d failed", addr2);
		hc_release_hci (hci);
		return -EBUSY;
	}
	hp->hcport2 = addr2;
	if (!hp->hcport2) {
		DBGERR ("Error mapping SL811 Memory 0x%x", hp->hcport2);
	}

	if (hc_alloc_trans_buffer (hci)) {
		hc_release_hci (hci);
		return -ENOMEM;
	}

	usb_register_bus (hci->bus);

	if (request_irq (irq, hc_interrupt, 0, "SL811", hci) != 0) {
		DBGERR ("request interrupt %d failed", irq);
		hc_release_hci (hci);
		return -EBUSY;
	}
	hp->irq = irq;

	printk (KERN_INFO __FILE__ ": USB SL811 at %x, addr2 = %x, IRQ %d\n",
		addr, addr2, irq);
	hc_reset (hci);

	if (hc_start (hci) < 0) {
		DBGERR ("can't start usb-%x", addr);
		hc_release_hci (hci);
		return -EBUSY;
	}

	return 0;
}
/***************************************************************************
 * Function Name : rh_int_timer_do
 * 
 * This function is called when the timer expires.  It gets the the port 
 * change data and pass along to the upper protocol.
 * 
 * Note:  The virtual root hub interrupt pipe are polled by the timer
 *        every "interval" ms
 *
 * Input:  ptr = ptr to the urb
 *
 * Return: none  
 **************************************************************************/
static void rh_int_timer_do (unsigned long ptr)
{
	int len;
	struct urb *urb = (struct urb *) ptr;
	hci_t *hci = urb->dev->bus->hcpriv;

	DBGFUNC ("enter rh_int_timer_do\n");

	if (hci->rh.send) {
		len = rh_send_irq (hci, urb->transfer_buffer,
				   urb->transfer_buffer_length);
		if (len > 0) {
			urb->actual_length = len;
			if (urb_debug == 2)
				urb_print (urb, "RET-t(rh)",
					   usb_pipeout (urb->pipe));

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

	/* re-activate the timer */
	rh_init_int_timer (urb);
}
Beispiel #3
0
/*****************************************************************
 *
 * Function Name: hc_alloc_hci
 *
 * This function allocates all data structure and store in the 
 * private data structure. 
 *
 * Input:  hci = data structure for the host controller
 *
 * Return value  : 0 
 *                
 *****************************************************************/
static hci_t *__devinit hc_alloc_hci (void)
{
	hci_t *hci;
	hcipriv_t *hp;
	portstat_t *ps;
	struct usb_bus *bus;

	DBGFUNC ("Enter hc_alloc_hci\n");
	hci = (hci_t *) kmalloc (sizeof (hci_t), GFP_KERNEL);
	if (!hci)
		return NULL;

	memset (hci, 0, sizeof (hci_t));

	hp = &hci->hp;

	hp->irq = -1;
	hp->hcport = -1;

	/* setup root hub port status */

	ps = (portstat_t *) kmalloc (sizeof (portstat_t), GFP_KERNEL);

	if (!ps)
		return NULL;
	ps->portStatus = PORT_STAT_DEFAULT;
	ps->portChange = PORT_CHANGE_DEFAULT;
	hp->RHportStatus = ps;

	hci->nakCnt = 0;
	hci->last_packet_nak = 0;

	hci->a_td_array.len = 0;
	hci->i_td_array[0].len = 0;
	hci->i_td_array[1].len = 0;
	hci->td_array = &hci->a_td_array;
	hci->active_urbs = 0;
	hci->active_trans = 0;
	INIT_LIST_HEAD (&hci->hci_hcd_list);
	list_add (&hci->hci_hcd_list, &hci_hcd_list);
	init_waitqueue_head (&hci->waitq);

	INIT_LIST_HEAD (&hci->ctrl_list);
	INIT_LIST_HEAD (&hci->bulk_list);
	INIT_LIST_HEAD (&hci->iso_list);
	INIT_LIST_HEAD (&hci->intr_list);
	INIT_LIST_HEAD (&hci->del_list);

	bus = usb_alloc_bus (&hci_device_operations);
	if (!bus) {
		kfree (hci);
		kfree (ps);
		return NULL;
	}

	hci->bus = bus;
	bus->hcpriv = (void *) hci;

	return hci;
}
Beispiel #4
0
/*****************************************************************
 *
 * Function Name: hc_release_hci
 *
 * This function De-allocate all resources  
 *
 * Input:  hci = data structure for the host controller
 *
 * Return value  : 0 
 *                
 *****************************************************************/
static void hc_release_hci (hci_t * hci)
{
	hcipriv_t *hp = &hci->hp;

	DBGFUNC ("Enter hc_release_hci\n");

	/* disconnect all devices */
	if (hci->bus->root_hub)
		usb_disconnect (&hci->bus->root_hub);

	hc_reset (hci);

	if (hp->tl)
		kfree (hp->tl);

	if (hp->hcport > 0) {
		release_region (hp->hcport, 2);
		hp->hcport = 0;
	}

	if (hp->irq >= 0) {
		free_irq (hp->irq, hci);
		hp->irq = -1;
	}

	usb_deregister_bus (hci->bus);
	usb_put_bus (hci->bus);

	list_del_init (&hci->hci_hcd_list);

	kfree (hci);
}
Beispiel #5
0
static int sendSegment(Connection *conn, Segment sgm) {
	char ssgm[RUSP_SGMS + 1];
	size_t ssgmsize;

	if (!(sgm.hdr.ctrl & RUSP_SACK) & !(sgm.hdr.ctrl & RUSP_CACK)) {

		sgm.hdr.ctrl |= RUSP_SACK;

		sgm.hdr.ackn = getWindowBase(&(conn->rcvwnd));
	}

	ssgmsize = serializeSegment(sgm, ssgm);

	if (pthread_mutex_lock(&(conn->sock.mtx)) > 0)
		ERREXIT("Cannot lock sock mutex for write.");

	if (writeCSocket(conn->sock.fd, ssgm, ssgmsize) == -1) {
		DBGPRINT(RUSP_DEBUG, "Cannot write connected socket: peer disconnected.");
		if (pthread_mutex_unlock(&(conn->sock.mtx)) > 0)
			ERREXIT("Cannot unlock mutex.");
		return -1;
	}

	if (pthread_mutex_unlock(&(conn->sock.mtx)) > 0)
		ERREXIT("Cannot unlock mutex.");

	DBGFUNC(RUSP_DEBUG, printOutSegment(getSocketPeer(conn->sock.fd), sgm));

	return 1;
}
Beispiel #6
0
/***************************************************************************
 * Function Name : regTest
 *
 * This routine test the Read/Write functionality of SL811HS registers  
 *
 * 1) Store original register value into a buffer
 * 2) Write to registers with a RAMP pattern. (10, 11, 12, ..., 255)
 * 3) Read from register
 * 4) Compare the written value with the read value and make sure they are 
 *    equivalent
 * 5) Restore the original register value 
 *
 * Input:  hci = data structure for the host controller
 *   
 *
 * Return: TRUE = passed; FALSE = failed 
 **************************************************************************/
int regTest (hci_t * hci)
{
	int i, data, result = TRUE;
	char buf[256];

	DBGFUNC ("Enter regTest\n");
	for (i = 0x10; i < 256; i++) {
		/* save the original buffer */
		buf[i] = (char) SL811Read (hci, i);

		/* Write the new data to the buffer */
		SL811Write (hci, i, i);
	}

	/* compare the written data */
	for (i = 0x10; i < 256; i++) {
		data = SL811Read (hci, i);
		if (data != i) {
			DBGERR ("Pattern test failed!! value = 0x%x, s/b 0x%x\n",
				data, i);
			result = FALSE;
		}
	}

	/* restore the data */
	for (i = 0x10; i < 256; i++) {
		SL811Write (hci, i, buf[i]);
	}

	return (result);
}
Beispiel #7
0
/*****************************************************************
 *
 * Function Name: hc_start
 *
 * This function starts the root hub functionality. 
 *
 * Input:  hci = data structure for the host controller
 *
 * Return value  : 0 
 *                
 *****************************************************************/
static int hc_start (hci_t * hci)
{
	DBGFUNC ("Enter hc_start\n");

	rh_connect_rh (hci);

	return 0;
}
Beispiel #8
0
/************************************************************************
 * Function Name : hc_parse_trans
 *  
 * This function checks the status of the transmitted or received packet
 * and copy the data from the SL811HS register into a buffer.
 *
 * 1) Check the status of the packet 
 * 2) If successful, and IN packet then copy the data from the SL811HS register
 *    into a buffer
 *
 * Input:  hci = data structure for the host controller
 *         actbytes = pointer to actual number of bytes
 *         data = data buffer
 *         cc = packet status
 *         length = the urb transmit length
 *         pid = packet ID
 *         urb_state = the current stage of USB transaction
 *       
 * Return: 0 
 ***********************************************************************/
static inline int hc_parse_trans (hci_t * hci, int *actbytes, __u8 * data,
				  int *cc, int *toggle, int length, int pid,
				  int urb_state)
{
	__u8 addr;
	__u8 len;

	DBGFUNC ("enter hc_parse_trans\n");

	/* get packet status; convert ack rcvd to ack-not-rcvd */

	*cc = (int) SL811Read (hci, SL11H_PKTSTATREG);

	if (*cc &
	    (SL11H_STATMASK_ERROR | SL11H_STATMASK_TMOUT | SL11H_STATMASK_OVF |
	     SL11H_STATMASK_NAK | SL11H_STATMASK_STALL)) {
		if (*cc & SL11H_STATMASK_OVF)
			DBGERR ("parse trans: error recv ack, cc = 0x%x, TX_BASE_Len = "
				"0x%x, TX_count=0x%x\n", *cc,
				SL811Read (hci, SL11H_BUFLNTHREG),
				SL811Read (hci, SL11H_XFERCNTREG));

	} else {
		DBGVERBOSE ("parse trans: recv ack, cc = 0x%x, len = 0x%x, \n",
			    *cc, length);

		/* Successful data */
		if ((pid == PID_IN) && (urb_state != US_CTRL_SETUP)) {

			/* Find the base address */
			addr = SL811Read (hci, SL11H_BUFADDRREG);

			/* Find the Transmit Length */
			len = SL811Read (hci, SL11H_BUFLNTHREG);

			/* The actual data length = xmit length reg - xfer count reg */
			*actbytes = len - SL811Read (hci, SL11H_XFERCNTREG);

			if ((data != NULL) && (*actbytes > 0)) {
				SL811BufRead (hci, addr, data, *actbytes);

			} else if ((data == NULL) && (*actbytes <= 0)) {
				DBGERR ("hc_parse_trans: data = NULL or actbyte = 0x%x\n",
					*actbytes);
				return 0;
			}
		} else if (pid == PID_OUT) {
			*actbytes = length;
		} else {
			// printk ("ERR:parse_trans, pid != IN or OUT, pid = 0x%x\n", pid);
		}
		*toggle = !*toggle;
	}

	return 0;
}
Beispiel #9
0
/************************************************************************
 * Function Name : hc_add_trans
 *  
 * This function sets up the SL811HS register and transmit the USB packets.
 * 
 * 1) Determine if enough time within the current frame to send the packet
 * 2) Load the data into the SL811HS register
 * 3) Set the appropriate command to the register and trigger the transmit
 *
 * Input:  hci = data structure for the host controller
 *         len = data length
 *         data = transmitting data
 *         toggle = USB toggle bit, either 0 or 1
 *         maxps = maximum packet size for this endpoint
 *         slow = speed of the device
 *         endpoint = endpoint number
 *         address = USB address of the device
 *         pid = packet ID
 *         format = 
 *         urb_state = the current stage of USB transaction
 *       
 * Return: 0 = no time left to schedule the transfer
 *         1 = success 
 *                
 ***********************************************************************/
static inline int hc_add_trans (hci_t * hci, int len, void *data, int toggle,
				int maxps, int slow, int endpoint, int address,
				int pid, int format, int urb_state)
{
	hcipriv_t *hp = &hci->hp;
	__u16 speed;
	int ii, jj, kk;

	DBGFUNC ("enter hc_addr_trans: len =0x%x, toggle:0x%x, endpoing:0x%x,"
		 " addr:0x%x, pid:0x%x,format:0x%x\n", len, toggle, endpoint,
		 i address, pid, format);

	if (len > maxps) {
		len = maxps;
	}

	speed = hp->RHportStatus->portStatus;
	if (speed & PORT_LOW_SPEED_DEV_ATTACH_STAT) {
//      ii = (8*7*8 + 6*3) * len + 800; 
		ii = 8 * 8 * len + 1024;
	} else {
		if (slow) {
//          ii = (8*7*8 + 6*3) * len + 800; 
			ii = 8 * 8 * len + 2048;
		} else
//          ii = (8*7 + 6*3)*len + 110;
			ii = 8 * len + 256;
	}

	ii += 2 * 10 * len;

	jj = SL811Read (hci, SL11H_SOFTMRREG);
	kk = (jj & 0xFF) * 64 - ii;

	if (kk < 0) {
		DBGVERBOSE
		    ("hc_add_trans: no bandwidth for schedule, ii = 0x%x,"
		     "jj = 0x%x, len =0x%x, active_trans = 0x%x\n", ii, jj, len,
		     hci->active_trans);
		return (-1);
	}

	if (pid != PID_IN) {
		/* Load data into hc */

		SL811BufWrite (hci, SL11H_DATA_START, (__u8 *) data, len);
	}

	/* transmit */

	SL11StartXaction (hci, (__u8) address, (__u8) endpoint, (__u8) pid, len,
			  toggle, slow, urb_state);

	return len;
}
Beispiel #10
0
/*****************************************************************
 *
 * Function Name: getPortStatusAndChange
 *
 * This function gets the ports status from SL811 and format it 
 * to a USB request format
 *
 * Input:  hci = data structure for the host controller
 *
 * Return value  : port status and change
 *                
 *****************************************************************/
static __u32 getPortStatusAndChange (hci_t * hci)
{
	hcipriv_t *hp = &hci->hp;
	__u32 portstatus;

	DBGFUNC ("enter getPorStatusAndChange\n");

	portstatus = hp->RHportStatus->portChange << 16 | hp->RHportStatus->portStatus;

	return (portstatus);
}
Beispiel #11
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);
}
Beispiel #12
0
/*****************************************************************
 *
 * Function Name: hci_hcd_cleanup
 *
 * This is a cleanup function, and it is called when module is 
 * unloaded. 
 *
 * Input: none 
 *
 * Return: none 
 *                
 *****************************************************************/
static void __exit hci_hcd_cleanup (void)
{
	struct list_head *hci_l;
	hci_t *hci;

	DBGFUNC ("Enter hci_hcd_cleanup\n");
	for (hci_l = hci_hcd_list.next; hci_l != &hci_hcd_list;) {
		hci = list_entry (hci_l, hci_t, hci_hcd_list);
		hci_l = hci_l->next;
		hc_release_hci (hci);
	}
}
Beispiel #13
0
/*****************************************************************
 *
 * Function Name: hci_hcd_init
 *
 * This is an init function, and it is the first function being called
 *
 * Input: none 
 *
 * Return: 0 = success or error condition 
 *                
 *****************************************************************/
static int __init hci_hcd_init (void)
{
	int ret;

	DBGFUNC ("Enter hci_hcd_init\n");
	if (usb_disabled())
		return -ENODEV;

	ret = hc_found_hci (base_addr, data_reg_addr, irq);

	return ret;
}
/***************************************************************************
 * Function Name : rh_send_irq
 * 
 * This function examine the port change in the virtual root hub.
 * 
 * Note: This function assumes only one port exist in the root hub.
 *
 * Input:  hci = data structure for the host controller
 *         rh_data = The pointer to port change data
 *         rh_len = length of the data in bytes
 *
 * Return: length of data  
 **************************************************************************/
static int rh_send_irq (hci_t * hci, void *rh_data, int rh_len)
{
	int num_ports;
	int i;
	int ret;
	int len;
	__u8 data[8];

	DBGFUNC ("enter rh_send_irq: \n");

	/* Assuming the root hub has one port.  This value need to change if
	 * there are more than one port for the root hub
	 */

	num_ports = 1;

	/* The root hub status is not implemented, it basically has two fields:
	 *     -- Local Power Status
	 *     -- Over Current Indicator
	 *     -- Local Power Change
	 *     -- Over Current Indicator
	 *
	 * Right now, It is assume the power is good and no changes 
	 */

	*(__u8 *) data = 0;

	ret = *(__u8 *) data;

	/* Has the port status change within the root hub: It checks for
	 *      -- Port Connect Status change
	 *      -- Port Enable Change
	 */

	for (i = 0; i < num_ports; i++) {
		*(__u8 *) (data + (i + 1) / 8) |=
		    (((getPortStatusAndChange (hci) >> 16) & (PORT_CONNECT_STAT | PORT_ENABLE_STAT)) ? 1 : 0) << ((i + 1) % 8);
		ret += *(__u8 *) (data + (i + 1) / 8);

		/* After the port change is read, it should be reset so the next time 
		 * is it doesn't trigger a change again */

	}
	len = i / 8 + 1;

	if (ret > 0) {
		memcpy (rh_data, data, min (len, min (rh_len, (int)sizeof (data))));
		return len;
	}
	return 0;
}
/***************************************************************************
 * Function Name : rh_unlink_urb
 * 
 * This function unlinks the URB 
 * 
 * Input: urb = USB request block 
 *
 * Return: 0  
 **************************************************************************/
static int rh_unlink_urb (struct urb * urb)
{
	hci_t *hci = urb->dev->bus->hcpriv;

	DBGFUNC ("enter rh_unlink_urb\n");
	if (hci->rh.urb == urb) {
		hci->rh.send = 0;
		del_timer (&hci->rh.rh_int_timer);
		hci->rh.urb = NULL;

		urb->hcpriv = NULL;
		usb_put_dev (urb->dev);
		urb->dev = NULL;
		if (urb->transfer_flags & URB_ASYNC_UNLINK) {
			urb->status = -ECONNRESET;
			if (urb->complete) {
				urb->complete (urb, NULL);
			}
		} else
			urb->status = -ENOENT;
	}
	return 0;
}
Beispiel #16
0
static int receiveSegment(Connection *conn, Segment *sgm) {
	char ssgm[RUSP_SGMS];
	long double timeout;

	timeout = getTimeoutValue(&(conn->timeout));

	if (selectSocket(conn->sock.fd, timeout) == 0)
		return 0;

	if (pthread_mutex_lock(&(conn->sock.mtx)) > 0)
		ERREXIT("Cannot lock sock mutex for read.");

	if (readCSocket(conn->sock.fd, ssgm, RUSP_SGMS) == -1) {
		if (pthread_mutex_unlock(&(conn->sock.mtx)) > 0)
			ERREXIT("Cannot unlock sock mutex for read.");
		DBGPRINT(RUSP_DEBUG, "Cannot read connected socket: peer disconnected.");
		return -1;
	}

	if (pthread_mutex_unlock(&(conn->sock.mtx)) > 0)
		ERREXIT("Cannot unlock sock mutex for read.");

	deserializeSegment(ssgm, sgm);

	if (getRandomBit(RUSP_DROP)) {
		char strsgm[RUSP_SGM_STR+1];
		segmentToString(*sgm, strsgm);
		DBGPRINT(RUSP_DEBUG, "SEGMENT DROPPPED: %s", strsgm);

		return 0;
	}

	DBGFUNC(RUSP_DEBUG, printInSegment(getSocketPeer(conn->sock.fd), *sgm));

	return 1;
}
/***************************************************************************
 * 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;
}
Beispiel #18
0
ConnectionId passiveOpen(Connection *lconn) {
	Connection *aconn = NULL;
	Segment syn, synack, acksynack;
	char ssyn[RUSP_SGMS + 1], ssynack[RUSP_SGMS + 1], sacksynack[RUSP_SGMS + 1];
	int asock, synackretrans;
	struct sockaddr_in caddr;
	struct timespec start, end;
	long double sampleRTT;

	while (getConnectionState(lconn) == RUSP_LISTEN) {

		readUSocket(lconn->sock.fd, &caddr, ssyn, RUSP_SGMS);

		deserializeSegment(ssyn, &syn);

		DBGFUNC(RUSP_DEBUG, printInSegment(caddr, syn));

		if (syn.hdr.ctrl != RUSP_SYN)
			continue;

		setConnectionState(lconn, RUSP_SYNRCV);

		asock = openSocket();

		synack = createSegment(RUSP_SYN | RUSP_SACK, 0, 10, RUSP_NXTSEQN(syn.hdr.seqn, 1), NULL);

		serializeSegment(synack, ssynack);

		for (synackretrans = 0; synackretrans < RUSP_RETR; synackretrans++) {

			clock_gettime(CLOCK_MONOTONIC, &start);

			writeUSocket(asock, caddr, ssynack, strlen(ssynack));

			DBGFUNC(RUSP_DEBUG, printOutSegment(caddr, synack));

			setConnectionState(lconn, RUSP_SYNSND);

			if (!selectSocket(asock, RUSP_SAMPLRTT))
				continue;

			readUSocket(asock, &caddr, sacksynack, RUSP_SGMS);

			clock_gettime(CLOCK_MONOTONIC, &end);

			sampleRTT = getElapsed(start, end);

			deserializeSegment(sacksynack, &acksynack);

			DBGFUNC(RUSP_DEBUG, printInSegment(caddr, acksynack));

			if ((acksynack.hdr.ctrl == RUSP_SACK) &
				(acksynack.hdr.seqn == synack.hdr.ackn) &
				(acksynack.hdr.ackn == RUSP_NXTSEQN(synack.hdr.seqn, 1))) {

				aconn = createConnection();

				setConnectionState(aconn, RUSP_SYNSND);

				setupConnection(aconn, asock, caddr, acksynack.hdr.ackn, acksynack.hdr.seqn, sampleRTT);

				setConnectionState(lconn, RUSP_LISTEN);

				return aconn->connid;
			}
		}

		closeSocket(asock);

		setConnectionState(lconn, RUSP_LISTEN);
	}

	return -1;
}
Beispiel #19
0
int activeOpen(Connection *conn, const struct sockaddr_in laddr) {
	Segment syn, synack, acksynack;
	char ssyn[RUSP_SGMS + 1], ssynack[RUSP_SGMS + 1], sacksynack[RUSP_SGMS + 1];
	int asock, synretrans;
	struct sockaddr_in aaddr;
	struct timespec start, end;
	long double sampleRTT;

	if (getConnectionState(conn) != RUSP_CLOSED)
		ERREXIT("Cannot synchronize connection: connection not closed.");

	asock = openSocket();

	syn = createSegment(RUSP_SYN, 0, 0, 0, NULL);

	serializeSegment(syn, ssyn);

	for (synretrans = 0; synretrans < RUSP_SYN_RETR; synretrans++) {

		clock_gettime(CLOCK_MONOTONIC, &start);

		writeUSocket(asock, laddr, ssyn, strlen(ssyn));

		DBGFUNC(RUSP_DEBUG, printOutSegment(laddr, syn));

		setConnectionState(conn, RUSP_SYNSND);

		if (!selectSocket(asock, RUSP_SAMPLRTT))
			continue;

		readUSocket(asock, &aaddr, ssynack, RUSP_SGMS);

		clock_gettime(CLOCK_MONOTONIC, &end);

		sampleRTT = getElapsed(start, end);

		deserializeSegment(ssynack, &synack);

		DBGFUNC(RUSP_DEBUG, printInSegment(aaddr, synack));

		if ((synack.hdr.ctrl == (RUSP_SYN | RUSP_SACK)) &
			(synack.hdr.ackn == RUSP_NXTSEQN(syn.hdr.seqn, 1))) {

			setConnectionState(conn, RUSP_SYNRCV);

			acksynack = createSegment(RUSP_SACK, 0, RUSP_NXTSEQN(syn.hdr.seqn, 1), RUSP_NXTSEQN(synack.hdr.seqn, 1), NULL);

			serializeSegment(acksynack, sacksynack);

			writeUSocket(asock, aaddr, sacksynack, strlen(sacksynack));

			DBGFUNC(RUSP_DEBUG, printOutSegment(aaddr, acksynack));

			setupConnection(conn, asock, aaddr, acksynack.hdr.seqn, acksynack.hdr.ackn, sampleRTT);

			return conn->connid;
		}
	}

	closeSocket(asock);

	setConnectionState(conn, RUSP_CLOSED);

	return -1;
}
Beispiel #20
0
/************************************************************************
 * Function Name : USBReset
 *  
 * This function resets SL811HS controller and detects the speed of
 * the connecting device				  
 *
 * Input:  hci = data structure for the host controller
 *                
 * Return: 0 = no device attached; 1 = USB device attached
 *                
 ***********************************************************************/
static int USBReset (hci_t * hci)
{
	int status;
	hcipriv_t *hp = &hci->hp;

	DBGFUNC ("enter USBReset\n");

	SL811Write (hci, SL11H_CTLREG2, 0xae);

	// setup master and full speed

	SL811Write (hci, SL11H_CTLREG1, 0x08);	// reset USB
	mdelay (20);		// 20ms                             
	SL811Write (hci, SL11H_CTLREG1, 0);	// remove SE0        

	for (status = 0; status < 100; status++)
		SL811Write (hci, SL11H_INTSTATREG, 0xff);	// clear all interrupt bits

	status = SL811Read (hci, SL11H_INTSTATREG);

	if (status & 0x40)	// Check if device is removed
	{
		DBG ("USBReset: Device removed\n");
		SL811Write (hci, SL11H_INTENBLREG,
			    SL11H_INTMASK_XFERDONE | SL11H_INTMASK_SOFINTR |
			    SL11H_INTMASK_INSRMV);
		hp->RHportStatus->portStatus &=
		    ~(PORT_CONNECT_STAT | PORT_ENABLE_STAT);

		return 0;
	}

	SL811Write (hci, SL11H_BUFLNTHREG_B, 0);	//zero lenth
	SL811Write (hci, SL11H_PIDEPREG_B, 0x50);	//send SOF to EP0       
	SL811Write (hci, SL11H_DEVADDRREG_B, 0x01);	//address0
	SL811Write (hci, SL11H_SOFLOWREG, 0xe0);

	if (!(status & 0x80)) {
		/* slow speed device connect directly to root-hub */

		DBG ("USBReset: low speed Device attached\n");
		SL811Write (hci, SL11H_CTLREG1, 0x8);
		mdelay (20);
		SL811Write (hci, SL11H_SOFTMRREG, 0xee);
		SL811Write (hci, SL11H_CTLREG1, 0x21);

		/* start the SOF or EOP */

		SL811Write (hci, SL11H_HOSTCTLREG_B, 0x01);
		hp->RHportStatus->portStatus |=
		    (PORT_CONNECT_STAT | PORT_LOW_SPEED_DEV_ATTACH_STAT);

		/* clear all interrupt bits */

		for (status = 0; status < 20; status++)
			SL811Write (hci, SL11H_INTSTATREG, 0xff);
	} else {
		/* full speed device connect directly to root hub */

		DBG ("USBReset: full speed Device attached\n");
		SL811Write (hci, SL11H_CTLREG1, 0x8);
		mdelay (20);
		SL811Write (hci, SL11H_SOFTMRREG, 0xae);
		SL811Write (hci, SL11H_CTLREG1, 0x01);

		/* start the SOF or EOP */

		SL811Write (hci, SL11H_HOSTCTLREG_B, 0x01);
		hp->RHportStatus->portStatus |= (PORT_CONNECT_STAT);
		hp->RHportStatus->portStatus &= ~PORT_LOW_SPEED_DEV_ATTACH_STAT;

		/* clear all interrupt bits */

		SL811Write (hci, SL11H_INTSTATREG, 0xff);

	}

	/* enable all interrupts */
	SL811Write (hci, SL11H_INTENBLREG,
		    SL11H_INTMASK_XFERDONE | SL11H_INTMASK_SOFINTR |
		    SL11H_INTMASK_INSRMV);

	return 1;
}