/***************************************************************** * * 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); }
/***************************************************************** * * 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; }
/***************************************************************** * * 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); }
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; }
/*************************************************************************** * 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); }
/***************************************************************** * * 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; }
/************************************************************************ * 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; }
/************************************************************************ * 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; }
/***************************************************************** * * 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); }
/***************************************************************** * * 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); }
/***************************************************************** * * 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); } }
/***************************************************************** * * 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; }
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; }
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; }
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; }
/************************************************************************ * 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; }