void zmq::stream_engine_t::in_event () { zmq_assert (!io_error); // If still handshaking, receive and process the greeting message. if (unlikely (handshaking)) if (!handshake ()) return; zmq_assert (decoder); // If there has been an I/O error, stop polling. if (input_stopped) { rm_fd (handle); io_error = true; return; } // If there's no data to process in the buffer... if (!insize) { // Retrieve the buffer and read as much data as possible. // Note that buffer can be arbitrarily large. However, we assume // the underlying TCP layer has fixed buffer size and thus the // number of bytes read will be always limited. size_t bufsize = 0; decoder->get_buffer (&inpos, &bufsize); const int rc = tcp_read (s, inpos, bufsize); if (rc == 0) { error (connection_error); return; } if (rc == -1) { if (errno != EAGAIN) error (connection_error); return; } // Adjust input size insize = static_cast <size_t> (rc); // Adjust buffer size to received bytes decoder->resize_buffer(insize); } int rc = 0; size_t processed = 0; while (insize > 0) { rc = decoder->decode (inpos, insize, processed); zmq_assert (processed <= insize); inpos += processed; insize -= processed; if (rc == 0 || rc == -1) break; rc = (this->*process_msg) (decoder->msg ()); if (rc == -1) break; } // Tear down the connection if we have failed to decode input data // or the session has rejected the message. if (rc == -1) { if (errno != EAGAIN) { error (protocol_error); return; } input_stopped = true; reset_pollin (handle); } session->flush (); }
/* * This function is called after the TCP connect has completed. Setup the TLS * layer and do all necessary magic. */ CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex) { static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; struct SessionHandle *data = conn->data; gnutls_session session; int rc; unsigned int cert_list_size; const gnutls_datum *chainp; unsigned int verify_status; gnutls_x509_crt x509_cert; char certbuf[256]; /* big enough? */ size_t size; unsigned int algo; unsigned int bits; time_t clock; const char *ptr; void *ssl_sessionid; size_t ssl_idsize; if (!gtls_inited) _Curl_gtls_init(); /* GnuTLS only supports TLSv1 (and SSLv3?) */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } /* allocate a cred struct */ rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred); if(rc < 0) { failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } if(data->set.ssl.CAfile) { /* set the trusted CA cert bundle file */ gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, data->set.ssl.CAfile, GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", data->set.ssl.CAfile, gnutls_strerror(rc)); if (data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } else infof(data, "found %d certificates in %s\n", rc, data->set.ssl.CAfile); } /* Initialize TLS session as a client */ rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT); if(rc) { failf(data, "gnutls_init() failed: %d", rc); return CURLE_SSL_CONNECT_ERROR; } /* convenient assign */ session = conn->ssl[sockindex].session; /* Use default priorities */ rc = gnutls_set_default_priority(session); if(rc < 0) return CURLE_SSL_CONNECT_ERROR; /* Sets the priority on the certificate types supported by gnutls. Priority is higher for types specified before others. After specifying the types you want, you must append a 0. */ rc = gnutls_certificate_type_set_priority(session, cert_type_priority); if(rc < 0) return CURLE_SSL_CONNECT_ERROR; if(data->set.str[STRING_CERT]) { if( gnutls_certificate_set_x509_key_file( conn->ssl[sockindex].cred, data->set.str[STRING_CERT], data->set.str[STRING_KEY] ? data->set.str[STRING_KEY] : data->set.str[STRING_CERT], do_file_type(data->set.str[STRING_CERT_TYPE]) ) ) { failf(data, "error reading X.509 key or certificate file"); return CURLE_SSL_CONNECT_ERROR; } } /* put the credentials to the current session */ rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, conn->ssl[sockindex].cred); /* set the connection handle (file descriptor for the socket) */ gnutls_transport_set_ptr(session, (gnutls_transport_ptr)conn->sock[sockindex]); /* register callback functions to send and receive data. */ gnutls_transport_set_push_function(session, Curl_gtls_push); gnutls_transport_set_pull_function(session, Curl_gtls_pull); /* lowat must be set to zero when using custom push and pull functions. */ gnutls_transport_set_lowat(session, 0); /* This might be a reconnect, so we check for a session ID in the cache to speed up things */ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { /* we got a session id, use it! */ gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); /* Informational message */ infof (data, "SSL re-using session ID\n"); } rc = handshake(conn, session, sockindex, TRUE); if(rc) /* handshake() sets its own error message with failf() */ return rc; /* This function will return the peer's raw certificate (chain) as sent by the peer. These certificates are in raw format (DER encoded for X.509). In case of a X.509 then a certificate list may be present. The first certificate in the list is the peer's certificate, following the issuer's certificate, then the issuer's issuer etc. */ chainp = gnutls_certificate_get_peers(session, &cert_list_size); if(!chainp) { if(data->set.ssl.verifyhost) { failf(data, "failed to get server cert"); return CURLE_PEER_FAILED_VERIFICATION; } infof(data, "\t common name: WARNING couldn't obtain\n"); } /* This function will try to verify the peer's certificate and return its status (trusted, invalid etc.). The value of status should be one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd. To avoid denial of service attacks some default upper limits regarding the certificate key size and chain size are set. To override them use gnutls_certificate_set_verify_limits(). */ rc = gnutls_certificate_verify_peers2(session, &verify_status); if (rc < 0) { failf(data, "server cert verify failed: %d", rc); return CURLE_SSL_CONNECT_ERROR; } /* verify_status is a bitmask of gnutls_certificate_status bits */ if(verify_status & GNUTLS_CERT_INVALID) { if (data->set.ssl.verifypeer) { failf(data, "server certificate verification failed. CAfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none"); return CURLE_SSL_CACERT; } else infof(data, "\t server certificate verification FAILED\n"); } else infof(data, "\t server certificate verification OK\n"); /* initialize an X.509 certificate structure. */ gnutls_x509_crt_init(&x509_cert); /* convert the given DER or PEM encoded Certificate to the native gnutls_x509_crt_t format */ gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); size=sizeof(certbuf); rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME, 0, /* the first and only one */ FALSE, certbuf, &size); if(rc) { infof(data, "error fetching CN from cert:%s\n", gnutls_strerror(rc)); } /* This function will check if the given certificate's subject matches the given hostname. This is a basic implementation of the matching described in RFC2818 (HTTPS), which takes into account wildcards, and the subject alternative name PKIX extension. Returns non zero on success, and zero on failure. */ rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name); if(!rc) { if (data->set.ssl.verifyhost > 1) { failf(data, "SSL: certificate subject name (%s) does not match " "target host name '%s'", certbuf, conn->host.dispname); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\t common name: %s (does not match '%s')\n", certbuf, conn->host.dispname); } else infof(data, "\t common name: %s (matched)\n", certbuf); /* Check for time-based validity */ clock = gnutls_x509_crt_get_expiration_time(x509_cert); if(clock == (time_t)-1) { failf(data, "server cert expiration date verify failed"); return CURLE_SSL_CONNECT_ERROR; } if(clock < time(NULL)) { if (data->set.ssl.verifypeer) { failf(data, "server certificate expiration date has passed."); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\t server certificate expiration date FAILED\n"); } else infof(data, "\t server certificate expiration date OK\n"); clock = gnutls_x509_crt_get_activation_time(x509_cert); if(clock == (time_t)-1) { failf(data, "server cert activation date verify failed"); return CURLE_SSL_CONNECT_ERROR; } if(clock > time(NULL)) { if (data->set.ssl.verifypeer) { failf(data, "server certificate not activated yet."); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\t server certificate activation date FAILED\n"); } else infof(data, "\t server certificate activation date OK\n"); /* Show: - ciphers used - subject - start date - expire date - common name - issuer */ /* public key algorithm's parameters */ algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits); infof(data, "\t certificate public key: %s\n", gnutls_pk_algorithm_get_name(algo)); /* version of the X.509 certificate. */ infof(data, "\t certificate version: #%d\n", gnutls_x509_crt_get_version(x509_cert)); size = sizeof(certbuf); gnutls_x509_crt_get_dn(x509_cert, certbuf, &size); infof(data, "\t subject: %s\n", certbuf); clock = gnutls_x509_crt_get_activation_time(x509_cert); showtime(data, "start date", clock); clock = gnutls_x509_crt_get_expiration_time(x509_cert); showtime(data, "expire date", clock); size = sizeof(certbuf); gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); infof(data, "\t issuer: %s\n", certbuf); gnutls_x509_crt_deinit(x509_cert); /* compression algorithm (if any) */ ptr = gnutls_compression_get_name(gnutls_compression_get(session)); /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ infof(data, "\t compression: %s\n", ptr); /* the name of the cipher used. ie 3DES. */ ptr = gnutls_cipher_get_name(gnutls_cipher_get(session)); infof(data, "\t cipher: %s\n", ptr); /* the MAC algorithms name. ie SHA1 */ ptr = gnutls_mac_get_name(gnutls_mac_get(session)); infof(data, "\t MAC: %s\n", ptr); if(!ssl_sessionid) { /* this session was not previously in the cache, add it now */ /* get the session ID data size */ gnutls_session_get_data(session, NULL, &ssl_idsize); ssl_sessionid = malloc(ssl_idsize); /* get a buffer for it */ if(ssl_sessionid) { /* extract session ID to the allocated buffer */ gnutls_session_get_data(session, ssl_sessionid, &ssl_idsize); /* store this session id */ return Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_idsize); } } return CURLE_OK; }
void RTMPSession::dataReceived() { static uint8_t buffer[4096] = {0}; bool stop1 = false; bool stop2 = false; do { size_t maxlen = m_streamInBuffer->total() - m_streamInBuffer->size(); size_t len = m_streamSession->read(buffer, maxlen); m_streamInBuffer->put(&buffer[0], len); while(m_streamInBuffer->size() > 0 && !stop1) { switch(m_state) { case kClientStateHandshake1s0: { uint8_t s0 ; m_streamInBuffer->get(&s0, 1); if(s0 == 0x03) { setClientState(kClientStateHandshake1s1); } } break; case kClientStateHandshake1s1: { if(m_streamInBuffer->size() >= kRTMPSignatureSize) { uint8_t buf[kRTMPSignatureSize]; size_t size = m_streamInBuffer->get(buf, kRTMPSignatureSize); m_s1.resize(size); m_s1.put(buf, size); handshake(); } else { stop1 = true; } } break; case kClientStateHandshake2: { if(m_streamInBuffer->size() >= kRTMPSignatureSize) { uint8_t buf[kRTMPSignatureSize]; m_streamInBuffer->get(buf, kRTMPSignatureSize); setClientState(kClientStateHandshakeComplete); handshake(); sendConnectPacket(); } else { stop1 = true; } } break; default: { if(!parseCurrentData()) { // the buffer seems corrupted. stop1 = stop2 = true; } } } } } while((m_streamSession->status() & kStreamStatusReadBufferHasBytes) && !stop2); }
static jdwpTransportError JNICALL socketTransport_attach(jdwpTransportEnv* env, const char* addressString, jlong attachTimeout, jlong handshakeTimeout) { struct sockaddr_in sa; int err; if (addressString == NULL || addressString[0] == '\0') { RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "address is missing"); } err = parseAddress(addressString, &sa, 0x7f000001); if (err != JDWPTRANSPORT_ERROR_NONE) { return err; } socketFD = dbgsysSocket(AF_INET, SOCK_STREAM, 0); if (socketFD < 0) { RETURN_IO_ERROR("unable to create socket"); } err = setOptions(socketFD); if (err) { return err; } /* * To do a timed connect we make the socket non-blocking * and poll with a timeout; */ if (attachTimeout > 0) { dbgsysConfigureBlocking(socketFD, JNI_FALSE); } err = dbgsysConnect(socketFD, (struct sockaddr *)&sa, sizeof(sa)); if (err == DBG_EINPROGRESS && attachTimeout > 0) { err = dbgsysFinishConnect(socketFD, (long)attachTimeout); if (err == DBG_ETIMEOUT) { dbgsysConfigureBlocking(socketFD, JNI_TRUE); RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "connect timed out"); } } if (err < 0) { RETURN_IO_ERROR("connect failed"); } if (attachTimeout > 0) { dbgsysConfigureBlocking(socketFD, JNI_TRUE); } err = handshake(socketFD, handshakeTimeout); if (err) { dbgsysSocketClose(socketFD); socketFD = -1; return err; } return JDWPTRANSPORT_ERROR_NONE; }
static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; int dev = MINOR(inode->i_rdev) & 0x0f; switch(dev) { case DSP56K_DEV_56001: { long n; /* Don't do anything if nothing is to be done */ if (!count) return 0; n = 0; switch (dsp56k.tx_wsize) { case 1: /* 8 bit */ { handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, get_user(dsp56k_host_interface.data.b[3], buf+n++)); return n; } case 2: /* 16 bit */ { short *data; count /= 2; data = (short*) buf; handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, get_user(dsp56k_host_interface.data.w[1], data+n++)); return 2*n; } case 3: /* 24 bit */ { count /= 3; handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, get_user(dsp56k_host_interface.data.b[1], buf+n++); get_user(dsp56k_host_interface.data.b[2], buf+n++); get_user(dsp56k_host_interface.data.b[3], buf+n++)); return 3*n; } case 4: /* 32 bit */ { long *data; count /= 4; data = (long*) buf; handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, get_user(dsp56k_host_interface.data.l, data+n++)); return 4*n; } } return -EFAULT; } default: printk("DSP56k driver: Unknown minor device: %d\n", dev); return -ENXIO; } }
static int tegra_ehci_hub_control( struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength ) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); int ports = HCS_N_PORTS(ehci->hcs_params); u32 temp, status; u32 __iomem *status_reg; u32 usbsts_reg; unsigned long flags; int retval = 0; unsigned selector; struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); bool hsic = false; bool do_post_resume = false; //mutex_lock(&tegra->tegra_ehci_hcd_mutex); if (!tegra->host_resumed) { if (buf) memset (buf, 0, wLength); //mutex_unlock(&tegra->tegra_ehci_hcd_mutex); return retval; } hsic = (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC); status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; spin_lock_irqsave(&ehci->lock, flags); /* * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits * that are write on clear, by writing back the register read value, so * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits */ if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) { temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS; ehci_writel(ehci, temp & ~PORT_PE, status_reg); goto done; } else if (typeReq == GetPortStatus) { temp = ehci_readl(ehci, status_reg); if (tegra->port_resuming && !(temp & PORT_SUSPEND) && time_after_eq(jiffies, ehci->reset_done[wIndex-1])) { clear_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); ehci->reset_done[wIndex-1] = 0; do_post_resume = true; } else if (tegra->port_resuming && (temp & PORT_RESUME) && time_after_eq(jiffies, ehci->reset_done[wIndex-1]) ) { do_post_resume = true; } if (do_post_resume) { tegra->port_resuming = 0; tegra_usb_phy_postresume(tegra->phy, false); if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) { ehci->command |= CMD_RUN; /* * ehci run bit is disabled to avoid SOF. * 2LS WAR is executed by now enable the run bit. */ ehci_writel(ehci, ehci->command, &ehci->regs->command); /* Now we can safely re-enable irqs */ ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); } } } else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { temp = ehci_readl(ehci, status_reg); if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { retval = -EPIPE; goto done; } temp &= ~PORT_WKCONN_E; temp |= PORT_WKDISC_E | PORT_WKOC_E; ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); /* Need a 4ms delay before the controller goes to suspend */ mdelay(4); /* * If a transaction is in progress, there may be a delay in * suspending the port. Poll until the port is suspended. */ if (handshake(ehci, status_reg, PORT_SUSPEND, PORT_SUSPEND, 5000)) pr_err("%s: timeout waiting for SUSPEND\n", __func__); set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) { /* Disable RUN bit. */ ehci->command &= ~CMD_RUN; ehci_writel(ehci, ehci->command, &ehci->regs->command); } tegra_usb_phy_postsuspend(tegra->phy, false); goto done; } /* * Tegra host controller will time the resume operation to clear the bit * when the port control state switches to HS or FS Idle. This behavior * is different from EHCI where the host controller driver is required * to set this bit to a zero after the resume duration is timed in the * driver. */ else if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { temp = ehci_readl(ehci, status_reg); if ((temp & PORT_RESET) || !(temp & PORT_PE)) { retval = -EPIPE; goto done; } if (!(temp & PORT_SUSPEND)) goto done; tegra->port_resuming = 1; if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) { /* disable interrupts */ ehci_writel(ehci, 0, &ehci->regs->intr_enable); /* Disable RUN bit. */ ehci->command &= ~CMD_RUN; ehci_writel(ehci, ehci->command, &ehci->regs->command); } /* Disable disconnect detection during port resume */ tegra_usb_phy_preresume(tegra->phy, false); #ifndef CONFIG_ARCH_TEGRA_2x_SOC if (tegra->phy->usb_phy_type != TEGRA_USB_PHY_TYPE_UTMIP) { #endif ehci_dbg(ehci, "%s:USBSTS = 0x%x", __func__, ehci_readl(ehci, &ehci->regs->status)); usbsts_reg = ehci_readl(ehci, &ehci->regs->status); ehci_writel(ehci, usbsts_reg, &ehci->regs->status); usbsts_reg = ehci_readl(ehci, &ehci->regs->status); udelay(20); if (handshake(ehci, &ehci->regs->status, STS_SRI, STS_SRI, 2000)) pr_err("%s: timeout set for STS_SRI\n", __func__); usbsts_reg = ehci_readl(ehci, &ehci->regs->status); ehci_writel(ehci, usbsts_reg, &ehci->regs->status); if (handshake(ehci, &ehci->regs->status, STS_SRI, 0, 2000)) pr_err("%s: timeout clear STS_SRI\n", __func__); if (handshake(ehci, &ehci->regs->status, STS_SRI, STS_SRI, 2000)) pr_err("%s: timeout set STS_SRI\n", __func__); udelay(20); #ifndef CONFIG_ARCH_TEGRA_2x_SOC } #endif temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); /* start resume signaling */ ehci_writel(ehci, temp | PORT_RESUME, status_reg); ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); /* whoever resumes must GetPortStatus to complete it!! */ goto done; } /* Handle port reset here */ if ((hsic) && (typeReq == SetPortFeature) && ((wValue == USB_PORT_FEAT_RESET) || (wValue == USB_PORT_FEAT_POWER))) { selector = wIndex >> 8; wIndex &= 0xff; if (!wIndex || wIndex > ports) { retval = -EPIPE; goto done; } wIndex--; status = 0; temp = ehci_readl(ehci, status_reg); if (temp & PORT_OWNER) goto done; temp &= ~PORT_RWC_BITS; switch (wValue) { case USB_PORT_FEAT_RESET: { if (temp & PORT_RESUME) { retval = -EPIPE; goto done; } /* line status bits may report this as low speed, * which can be fine if this root hub has a * transaction translator built in. */ if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT && !ehci_is_TDI(ehci) && PORT_USB11 (temp)) { ehci_dbg (ehci, "port %d low speed --> companion\n", wIndex + 1); temp |= PORT_OWNER; ehci_writel(ehci, temp, status_reg); } else { ehci_vdbg(ehci, "port %d reset\n", wIndex + 1); temp &= ~PORT_PE; /* * caller must wait, then call GetPortStatus * usb 2.0 spec says 50 ms resets on root */ ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(50); ehci_writel(ehci, temp, status_reg); if (hsic && (wIndex == 0)) tegra_usb_phy_bus_reset(tegra->phy); } break; } case USB_PORT_FEAT_POWER: { if (HCS_PPC(ehci->hcs_params)) ehci_writel(ehci, temp | PORT_POWER, status_reg); if (hsic && (wIndex == 0)) tegra_usb_phy_bus_connect(tegra->phy); break; } } goto done; }
void handshake(handshake_type type, const ConstBufferSequence& buffers) { asio::error_code ec; handshake(type, buffers, ec); asio::detail::throw_error(ec, "handshake"); }
static int ehci_hub_control ( struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength ) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); int ports = HCS_N_PORTS (ehci->hcs_params); u32 temp, status; unsigned long flags; int retval = 0; /* * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. * HCS_INDICATOR may say we can change LEDs to off/amber/green. * (track current state ourselves) ... blink for diagnostics, * power, "this is the one", etc. EHCI spec supports this. */ spin_lock_irqsave (&ehci->lock, flags); switch (typeReq) { case ClearHubFeature: switch (wValue) { case C_HUB_LOCAL_POWER: case C_HUB_OVER_CURRENT: /* no hub-wide feature/status flags */ break; default: goto error; } break; case ClearPortFeature: if (!wIndex || wIndex > ports) goto error; wIndex--; temp = readl (&ehci->regs->port_status [wIndex]); if (temp & PORT_OWNER) break; switch (wValue) { case USB_PORT_FEAT_ENABLE: writel (temp & ~PORT_PE, &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_C_ENABLE: writel((temp & ~PORT_RWC_BITS) | PORT_PEC, &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_SUSPEND: if (temp & PORT_RESET) goto error; if (temp & PORT_SUSPEND) { if ((temp & PORT_PE) == 0) goto error; /* resume signaling for 20 msec */ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); writel (temp | PORT_RESUME, &ehci->regs->port_status [wIndex]); ehci->reset_done [wIndex] = jiffies + msecs_to_jiffies (20); } break; case USB_PORT_FEAT_C_SUSPEND: /* we auto-clear this feature */ break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) writel (temp & ~(PORT_RWC_BITS | PORT_POWER), &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_C_CONNECTION: writel ((temp & ~PORT_RWC_BITS) | PORT_CSC, &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_C_OVER_CURRENT: writel ((temp & ~PORT_RWC_BITS) | PORT_OCC, &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_C_RESET: /* GetPortStatus clears reset */ break; default: goto error; } readl (&ehci->regs->command); /* unblock posted write */ break; case GetHubDescriptor: ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) buf); break; case GetHubStatus: /* no hub-wide feature/status flags */ memset (buf, 0, 4); //cpu_to_le32s ((u32 *) buf); break; case GetPortStatus: if (!wIndex || wIndex > ports) goto error; wIndex--; status = 0; temp = readl (&ehci->regs->port_status [wIndex]); // wPortChange bits if (temp & PORT_CSC) status |= 1 << USB_PORT_FEAT_C_CONNECTION; if (temp & PORT_PEC) status |= 1 << USB_PORT_FEAT_C_ENABLE; if (temp & PORT_OCC) status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; /* whoever resumes must GetPortStatus to complete it!! */ if ((temp & PORT_RESUME) && time_after (jiffies, ehci->reset_done [wIndex])) { status |= 1 << USB_PORT_FEAT_C_SUSPEND; ehci->reset_done [wIndex] = 0; /* stop resume signaling */ temp = readl (&ehci->regs->port_status [wIndex]); writel (temp & ~(PORT_RWC_BITS | PORT_RESUME), &ehci->regs->port_status [wIndex]); retval = handshake ( &ehci->regs->port_status [wIndex], PORT_RESUME, 0, 2000 /* 2msec */); if (retval != 0) { ehci_err (ehci, "port %d resume error %d\n", wIndex + 1, retval); goto error; } temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); } /* whoever resets must GetPortStatus to complete it!! */ if ((temp & PORT_RESET) && time_after (jiffies, ehci->reset_done [wIndex])) { status |= 1 << USB_PORT_FEAT_C_RESET; ehci->reset_done [wIndex] = 0; /* force reset to complete */ writel (temp & ~(PORT_RWC_BITS | PORT_RESET), &ehci->regs->port_status [wIndex]); retval = handshake ( &ehci->regs->port_status [wIndex], PORT_RESET, 0, 500); if (retval != 0) { ehci_err (ehci, "port %d reset error %d\n", wIndex + 1, retval); goto error; } /* see what we found out */ temp = check_reset_complete (ehci, wIndex, readl (&ehci->regs->port_status [wIndex])); } // don't show wPortStatus if it's owned by a companion hc if (!(temp & PORT_OWNER)) { if (temp & PORT_CONNECT) { status |= 1 << USB_PORT_FEAT_CONNECTION; // status may be from integrated TT status |= ehci_port_speed(ehci, temp); } if (temp & PORT_PE) status |= 1 << USB_PORT_FEAT_ENABLE; if (temp & (PORT_SUSPEND|PORT_RESUME)) status |= 1 << USB_PORT_FEAT_SUSPEND; if (temp & PORT_OC) status |= 1 << USB_PORT_FEAT_OVER_CURRENT; if (temp & PORT_RESET) status |= 1 << USB_PORT_FEAT_RESET; if (temp & PORT_POWER) status |= 1 << USB_PORT_FEAT_POWER; } #ifndef EHCI_VERBOSE_DEBUG if (status & ~0xffff) /* only if wPortChange is interesting */ #endif dbg_port (ehci, "GetStatus", wIndex + 1, temp); // we "know" this alignment is good, caller used kmalloc()... *((__le32 *) buf) = cpu_to_le32 (status); break; case SetHubFeature: switch (wValue) { case C_HUB_LOCAL_POWER: case C_HUB_OVER_CURRENT: /* no hub-wide feature/status flags */ break; default: goto error; } break; case SetPortFeature: if (!wIndex || wIndex > ports) goto error; wIndex--; temp = readl (&ehci->regs->port_status [wIndex]); if (temp & PORT_OWNER) break; temp &= ~PORT_RWC_BITS; switch (wValue) { case USB_PORT_FEAT_SUSPEND: if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) goto error; if (ehci->hcd.remote_wakeup) temp |= PORT_WAKE_BITS; writel (temp | PORT_SUSPEND, &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) writel (temp | PORT_POWER, &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_RESET: if (temp & PORT_RESUME) goto error; /* line status bits may report this as low speed, * which can be fine if this root hub has a * transaction translator built in. */ if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT && !ehci_is_ARC(ehci) && PORT_USB11 (temp)) { ehci_dbg (ehci, "port %d low speed --> companion\n", wIndex + 1); temp |= PORT_OWNER; } else { ehci_vdbg (ehci, "port %d reset\n", wIndex + 1); temp |= PORT_RESET; temp &= ~PORT_PE; /* * caller must wait, then call GetPortStatus * usb 2.0 spec says 50 ms resets on root */ ehci->reset_done [wIndex] = jiffies + msecs_to_jiffies (50); } writel (temp, &ehci->regs->port_status [wIndex]); break; default: goto error; } readl (&ehci->regs->command); /* unblock posted writes */ break; default: error: /* "stall" on error */ retval = -EPIPE; } spin_unlock_irqrestore (&ehci->lock, flags); return retval; }
static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) { ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN); struct qTD *qtd; int qtd_count = 0; int qtd_counter = 0; volatile struct qTD *vtd; unsigned long ts; uint32_t *tdp; uint32_t endpt, maxpacket, token, usbsts; uint32_t c, toggle; uint32_t cmd; int timeout; int ret = 0; struct ehci_ctrl *ctrl = dev->controller; debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, buffer, length, req); if (req != NULL) debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", req->request, req->request, req->requesttype, req->requesttype, le16_to_cpu(req->value), le16_to_cpu(req->value), le16_to_cpu(req->index)); #define PKT_ALIGN 512 /* * The USB transfer is split into qTD transfers. Eeach qTD transfer is * described by a transfer descriptor (the qTD). The qTDs form a linked * list with a queue head (QH). * * Each qTD transfer starts with a new USB packet, i.e. a packet cannot * have its beginning in a qTD transfer and its end in the following * one, so the qTD transfer lengths have to be chosen accordingly. * * Each qTD transfer uses up to QT_BUFFER_CNT data buffers, mapped to * single pages. The first data buffer can start at any offset within a * page (not considering the cache-line alignment issues), while the * following buffers must be page-aligned. There is no alignment * constraint on the size of a qTD transfer. */ if (req != NULL) /* 1 qTD will be needed for SETUP, and 1 for ACK. */ qtd_count += 1 + 1; if (length > 0 || req == NULL) { /* * Determine the qTD transfer size that will be used for the * data payload (not considering the first qTD transfer, which * may be longer or shorter, and the final one, which may be * shorter). * * In order to keep each packet within a qTD transfer, the qTD * transfer size is aligned to PKT_ALIGN, which is a multiple of * wMaxPacketSize (except in some cases for interrupt transfers, * see comment in submit_int_msg()). * * By default, i.e. if the input buffer is aligned to PKT_ALIGN, * QT_BUFFER_CNT full pages will be used. */ int xfr_sz = QT_BUFFER_CNT; /* * However, if the input buffer is not aligned to PKT_ALIGN, the * qTD transfer size will be one page shorter, and the first qTD * data buffer of each transfer will be page-unaligned. */ if ((uint32_t)buffer & (PKT_ALIGN - 1)) xfr_sz--; /* Convert the qTD transfer size to bytes. */ xfr_sz *= EHCI_PAGE_SIZE; /* * Approximate by excess the number of qTDs that will be * required for the data payload. The exact formula is way more * complicated and saves at most 2 qTDs, i.e. a total of 128 * bytes. */ qtd_count += 2 + length / xfr_sz; } /* * Threshold value based on the worst-case total size of the allocated qTDs for * a mass-storage transfer of 65535 blocks of 512 bytes. */ #if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024 #warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI #endif qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD)); if (qtd == NULL) { printf("unable to allocate TDs\n"); return -1; } memset(qh, 0, sizeof(struct QH)); memset(qtd, 0, qtd_count * sizeof(*qtd)); toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); /* * Setup QH (3.6 in ehci-r10.pdf) * * qh_link ................. 03-00 H * qh_endpt1 ............... 07-04 H * qh_endpt2 ............... 0B-08 H * - qh_curtd * qh_overlay.qt_next ...... 13-10 H * - qh_overlay.qt_altnext */ qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH); c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe); maxpacket = usb_maxpacket(dev, pipe); endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) | QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) | QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) | QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) | QH_ENDPT1_DEVADDR(usb_pipedevice(pipe)); qh->qh_endpt1 = cpu_to_hc32(endpt); endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0); qh->qh_endpt2 = cpu_to_hc32(endpt); ehci_update_endpt2_dev_n_port(dev, qh); qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); tdp = &qh->qh_overlay.qt_next; if (req != NULL) { /* * Setup request qTD (3.5 in ehci-r10.pdf) * * qt_next ................ 03-00 H * qt_altnext ............. 07-04 H * qt_token ............... 0B-08 H * * [ buffer, buffer_hi ] loaded with "req". */ qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = QT_TOKEN_DT(0) | QT_TOKEN_TOTALBYTES(sizeof(*req)) | QT_TOKEN_IOC(0) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | QT_TOKEN_PID(QT_TOKEN_PID_SETUP) | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); qtd[qtd_counter].qt_token = cpu_to_hc32(token); if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req))) { printf("unable to construct SETUP TD\n"); goto fail; } /* Update previous qTD! */ *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); tdp = &qtd[qtd_counter++].qt_next; toggle = 1; } if (length > 0 || req == NULL) { uint8_t *buf_ptr = buffer; int left_length = length; do { /* * Determine the size of this qTD transfer. By default, * QT_BUFFER_CNT full pages can be used. */ int xfr_bytes = QT_BUFFER_CNT * EHCI_PAGE_SIZE; /* * However, if the input buffer is not page-aligned, the * portion of the first page before the buffer start * offset within that page is unusable. */ xfr_bytes -= (uint32_t)buf_ptr & (EHCI_PAGE_SIZE - 1); /* * In order to keep each packet within a qTD transfer, * align the qTD transfer size to PKT_ALIGN. */ xfr_bytes &= ~(PKT_ALIGN - 1); /* * This transfer may be shorter than the available qTD * transfer size that has just been computed. */ xfr_bytes = min(xfr_bytes, left_length); /* * Setup request qTD (3.5 in ehci-r10.pdf) * * qt_next ................ 03-00 H * qt_altnext ............. 07-04 H * qt_token ............... 0B-08 H * * [ buffer, buffer_hi ] loaded with "buffer". */ qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = QT_TOKEN_DT(toggle) | QT_TOKEN_TOTALBYTES(xfr_bytes) | QT_TOKEN_IOC(req == NULL) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | QT_TOKEN_PID(usb_pipein(pipe) ? QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); qtd[qtd_counter].qt_token = cpu_to_hc32(token); if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr, xfr_bytes)) { printf("unable to construct DATA TD\n"); goto fail; } /* Update previous qTD! */ *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); tdp = &qtd[qtd_counter++].qt_next; /* * Data toggle has to be adjusted since the qTD transfer * size is not always an even multiple of * wMaxPacketSize. */ if ((xfr_bytes / maxpacket) & 1) toggle ^= 1; buf_ptr += xfr_bytes; left_length -= xfr_bytes; } while (left_length > 0); } if (req != NULL) { /* * Setup request qTD (3.5 in ehci-r10.pdf) * * qt_next ................ 03-00 H * qt_altnext ............. 07-04 H * qt_token ............... 0B-08 H */ qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = QT_TOKEN_DT(1) | QT_TOKEN_TOTALBYTES(0) | QT_TOKEN_IOC(1) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | QT_TOKEN_PID(usb_pipein(pipe) ? QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); qtd[qtd_counter].qt_token = cpu_to_hc32(token); /* Update previous qTD! */ *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); tdp = &qtd[qtd_counter++].qt_next; } ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH); /* Flush dcache */ flush_dcache_range((uint32_t)&ctrl->qh_list, ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1)); flush_dcache_range((uint32_t)qtd, ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); /* Set async. queue head pointer. */ ehci_writel(&ctrl->hcor->or_asynclistaddr, (uint32_t)&ctrl->qh_list); usbsts = ehci_readl(&ctrl->hcor->or_usbsts); ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f)); /* Enable async. schedule. */ cmd = ehci_readl(&ctrl->hcor->or_usbcmd); cmd |= CMD_ASE; ehci_writel(&ctrl->hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STS_ASS set\n"); goto fail; } /* Wait for TDs to be processed. */ ts = get_timer(0); vtd = &qtd[qtd_counter - 1]; timeout = USB_TIMEOUT_MS(pipe); do { /* Invalidate dcache */ invalidate_dcache_range((uint32_t)&ctrl->qh_list, ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); invalidate_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1)); invalidate_dcache_range((uint32_t)qtd, ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); token = hc32_to_cpu(vtd->qt_token); if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) break; WATCHDOG_RESET(); } while (get_timer(ts) < timeout); /* * Invalidate the memory area occupied by buffer * Don't try to fix the buffer alignment, if it isn't properly * aligned it's upper layer's fault so let invalidate_dcache_range() * vow about it. But we have to fix the length as it's actual * transfer length and can be unaligned. This is potentially * dangerous operation, it's responsibility of the calling * code to make sure enough space is reserved. */ invalidate_dcache_range((uint32_t)buffer, ALIGN((uint32_t)buffer + length, ARCH_DMA_MINALIGN)); /* Check that the TD processing happened */ if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE) printf("EHCI timed out on TD - token=%#x\n", token); /* Disable async schedule. */ cmd = ehci_readl(&ctrl->hcor->or_usbcmd); cmd &= ~CMD_ASE; ehci_writel(&ctrl->hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STS_ASS reset\n"); goto fail; } token = hc32_to_cpu(qh->qh_overlay.qt_token); if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) { debug("TOKEN=%#x\n", token); switch (QT_TOKEN_GET_STATUS(token) & ~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) { case 0: toggle = QT_TOKEN_GET_DT(token); usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle); dev->status = 0; break; case QT_TOKEN_STATUS_HALTED: dev->status = USB_ST_STALLED; break; case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR: case QT_TOKEN_STATUS_DATBUFERR: dev->status = USB_ST_BUF_ERR; break; case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET: case QT_TOKEN_STATUS_BABBLEDET: dev->status = USB_ST_BABBLE_DET; break; default: dev->status = USB_ST_CRC_ERR; if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED) dev->status |= USB_ST_STALLED; break; } dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token); } else { dev->act_len = 0; #ifndef CONFIG_USB_EHCI_FARADAY debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n", dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts), ehci_readl(&ctrl->hcor->or_portsc[0]), ehci_readl(&ctrl->hcor->or_portsc[1])); #endif } free(qtd); return (dev->status != USB_ST_NOT_PROC) ? 0 : -1; fail: free(qtd); return -1; }
static int omap_ehci_hub_control( struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength ) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); u32 __iomem *status_reg = &ehci->regs->port_status[ (wIndex & 0xff) - 1]; u32 __iomem *hostpc_reg = NULL; u32 temp, temp1, status; unsigned long flags; int retval = 0; u32 runstop, temp_reg; spin_lock_irqsave(&ehci->lock, flags); switch (typeReq) { case GetPortStatus: wIndex--; status = 0; temp = ehci_readl(ehci, status_reg); /* wPortChange bits */ if (temp & PORT_CSC) status |= USB_PORT_STAT_C_CONNECTION << 16; if (temp & PORT_PEC) status |= USB_PORT_STAT_C_ENABLE << 16; if ((temp & PORT_OCC) && !ignore_oc) { status |= USB_PORT_STAT_C_OVERCURRENT << 16; /* * Hubs should disable port power on over-current. * However, not all EHCI implementations do this * automatically, even if they _do_ support per-port * power switching; they're allowed to just limit the * current. khubd will turn the power back on. */ if (HCS_PPC(ehci->hcs_params)) { ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_POWER), status_reg); } } /* whoever resumes must GetPortStatus to complete it!! */ if (temp & PORT_RESUME) { /* Remote Wakeup received? */ if (!ehci->reset_done[wIndex]) { /* resume signaling for 20 msec */ ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(20); /* check the port again */ mod_timer(&ehci_to_hcd(ehci)->rh_timer, ehci->reset_done[wIndex]); } /* resume completed? */ else if (time_after_eq(jiffies, ehci->reset_done[wIndex])) { clear_bit(wIndex, &ehci->suspended_ports); set_bit(wIndex, &ehci->port_c_suspend); ehci->reset_done[wIndex] = 0; /* * Workaround for OMAP errata: * To Stop Resume Signalling, it is required * to Stop the Host Controller and disable the * TLL Functional Clock. */ /* Stop the Host Controller */ runstop = ehci_readl(ehci, &ehci->regs->command); ehci_writel(ehci, (runstop & ~CMD_RUN), &ehci->regs->command); (void) ehci_readl(ehci, &ehci->regs->command); handshake(ehci, &ehci->regs->status, STS_HALT, STS_HALT, 2000); temp_reg = omap_readl(L3INIT_HSUSBTLL_CLKCTRL); temp_reg &= ~(1 << 9); /* stop resume signaling */ temp = ehci_readl(ehci, status_reg); ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESUME), status_reg); /* Disable the Channel 1 Optional Fclk */ omap_writel(temp_reg, L3INIT_HSUSBTLL_CLKCTRL); retval = handshake(ehci, status_reg, PORT_RESUME, 0, 2000 /* 2msec */); /* * Enable the Host Controller and start the * Channel 1 Optional Fclk since resume has * finished. */ udelay(2); omap_writel((temp_reg | (1 << 9)), L3INIT_HSUSBTLL_CLKCTRL); ehci_writel(ehci, (runstop), &ehci->regs->command); (void) ehci_readl(ehci, &ehci->regs->command); if (retval != 0) { ehci_err(ehci, "port %d resume error %d\n", wIndex + 1, retval); spin_unlock_irqrestore(&ehci->lock, flags); return -EPIPE; } temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); } } /* whoever resets must GetPortStatus to complete it!! */ if ((temp & PORT_RESET) && time_after_eq(jiffies, ehci->reset_done[wIndex])) { status |= USB_PORT_STAT_C_RESET << 16; ehci->reset_done[wIndex] = 0; /* force reset to complete */ ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET), status_reg); /* REVISIT: some hardware needs 550+ usec to clear * this bit; seems too long to spin routinely... */ retval = handshake(ehci, status_reg, PORT_RESET, 0, 1000); if (retval != 0) { ehci_err(ehci, "port %d reset error %d\n", wIndex + 1, retval); spin_unlock_irqrestore(&ehci->lock, flags); return -EPIPE; } /* see what we found out */ temp = check_reset_complete(ehci, wIndex, status_reg, ehci_readl(ehci, status_reg)); } if (!(temp & (PORT_RESUME|PORT_RESET))) ehci->reset_done[wIndex] = 0; /* transfer dedicated ports to the companion hc */ if ((temp & PORT_CONNECT) && test_bit(wIndex, &ehci->companion_ports)) { temp &= ~PORT_RWC_BITS; temp |= PORT_OWNER; ehci_writel(ehci, temp, status_reg); ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1); temp = ehci_readl(ehci, status_reg); } /* * Even if OWNER is set, there's no harm letting khubd * see the wPortStatus values (they should all be 0 except * for PORT_POWER anyway). */ if (temp & PORT_CONNECT) { status |= USB_PORT_STAT_CONNECTION; /* status may be from integrated TT */ if (ehci->has_hostpc) { temp1 = ehci_readl(ehci, hostpc_reg); status |= ehci_port_speed(ehci, temp1); } else status |= ehci_port_speed(ehci, temp); } if (temp & PORT_PE) status |= USB_PORT_STAT_ENABLE; /* maybe the port was unsuspended without our knowledge */ if (temp & (PORT_SUSPEND|PORT_RESUME)) { status |= USB_PORT_STAT_SUSPEND; } else if (test_bit(wIndex, &ehci->suspended_ports)) { clear_bit(wIndex, &ehci->suspended_ports); ehci->reset_done[wIndex] = 0; if (temp & PORT_PE) set_bit(wIndex, &ehci->port_c_suspend); } if (temp & PORT_OC) status |= USB_PORT_STAT_OVERCURRENT; if (temp & PORT_RESET) status |= USB_PORT_STAT_RESET; if (temp & PORT_POWER) status |= USB_PORT_STAT_POWER; if (test_bit(wIndex, &ehci->port_c_suspend)) status |= USB_PORT_STAT_C_SUSPEND << 16; #ifndef VERBOSE_DEBUG if (status & ~0xffff) /* only if wPortChange is interesting */ #endif dbg_port(ehci, "GetStatus", wIndex + 1, temp); put_unaligned_le32(status, buf); break; default: spin_unlock_irqrestore(&ehci->lock, flags); retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); spin_lock_irqsave(&ehci->lock, flags); } spin_unlock_irqrestore(&ehci->lock, flags); return retval; }
int main(int argc, char **argv) { int sockfd; /* socket */ int portno; /* port to listen on */ struct sockaddr_in clientaddr; /* client addr */ socklen_t clientlen; /* byte size of client's address */ struct sockaddr_in serveraddr; /* server's addr */ int optval; /* flag value for setsockopt */ int fd; long file_size; long total_read = 0; unsigned char file_buf[MAX_SEQ_NUM_HALF]; unsigned long lastbyteSent, lastbyteAcked, maxbyte; unsigned char *lastbyteSentPtr, *lastbyteAckedPtr, *maxbytePtr; clock_t clock_start, clock_end; bool eof = false; int dupAck = 0; map<uint16_t, clock_t> time_map; /* check command line arguments */ if (argc != 3) error("Usage: ./server PORT-NUMBER FILE-NAME"); portno = atoi(argv[1]); /* socket: create the parent socket */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) error("ERROR opening socket"); optval = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) == -1){ perror("setsockopt"); return 1; }; /* build the server's Internet address */ bzero((char *) &serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons((unsigned short)portno); /* bind: associate the parent socket with a port */ if (::bind(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) == -1){ perror("bind"); return 2; } clientlen = sizeof(clientaddr); if (handshake(sockfd, clientaddr, clientlen) == USHRT_MAX) return 3; if ((fd = open(argv[2], O_RDONLY, 0644)) == -1){ perror("open"); return 4; } if ((file_size = lseek(fd, 0, SEEK_END)) == -1){ perror("lseek"); return 5; } if (lseek(fd, 0, SEEK_SET) == -1){ perror("lseek"); return 6; } maxbyte = lastbyteSent = lastbyteAcked = 0; maxbytePtr = lastbyteSentPtr = lastbyteAckedPtr = file_buf; clock_start = clock_end = clock(); bool firstRTT = true; while (!(eof && lastbyteAcked == maxbyte)) { for ( ; (lastbyteSent < maxbyte) && (unackedPackets < cwndPackets); (lastbyteSent += BUFSIZE) && (unackedPackets++)) { segment seg; seg.setSeqnum(server_seq); int send_size; if ((maxbyte-lastbyteSent)/BUFSIZE >= 1) send_size = BUFSIZE; else send_size = (int)(maxbyte - lastbyteSent); if (lastbyteSentPtr + send_size > file_buf + MAX_SEQ_NUM_HALF) { unsigned char temp[BUFSIZE]; long send_part2 = (lastbyteSentPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF); long send_part1 = send_size - send_part2; memcpy((char*)temp, (char*)lastbyteSentPtr, send_part1); memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2); unsigned char *send_buf = seg.encode(temp, send_size); sendto(sockfd, send_buf, send_size+HEADERSIZE, 0, (struct sockaddr *)&clientaddr, clientlen); lastbyteSentPtr = lastbyteSentPtr + send_size - MAX_SEQ_NUM_HALF; } else { unsigned char *send_buf = seg.encode(lastbyteSentPtr, send_size); sendto(sockfd, send_buf, send_size+HEADERSIZE, 0, (struct sockaddr *)&clientaddr, clientlen); lastbyteSentPtr = lastbyteSentPtr + send_size; } clock_t now = clock(); time_map[server_seq] = now; cout << "Sending packet " << server_seq << " " << cwnd << " " << ssthresh << endl; server_seq = (server_seq + send_size) % MAX_SEQ_NUM; } while (true) { unsigned char recv_buf[HEADERSIZE]; long recv_len; if ((recv_len = recvfrom(sockfd, recv_buf, HEADERSIZE, MSG_DONTWAIT, (struct sockaddr *) &clientaddr, &clientlen)) == -1) { if (errno != EWOULDBLOCK && errno != EAGAIN) perror("recvfrom"); break; } segment ack; ack.decode(recv_buf, HEADERSIZE); if (ack.getFlagack()) { cout << "Receiving packet " << ack.getAcknum() << endl; if (ack.getAcknum() != server_ack) { map<uint16_t, clock_t>::iterator it = time_map.find(server_ack); if (it != time_map.end()) { clock_t now, then; now = clock(); then = it->second; time_map.erase(server_ack); double sampleRTT = double(now - then) / CLOCKS_PER_SEC; if (firstRTT) { estimatedRTT = sampleRTT; devRTT = sampleRTT / 2; adaptiveRTO = estimatedRTT + 4 * devRTT; timeout = adaptiveRTO; firstRTT = false; } else { double difference = sampleRTT - estimatedRTT >= 0 ? sampleRTT - estimatedRTT : estimatedRTT - sampleRTT; estimatedRTT = 0.875 * estimatedRTT + 0.125 * sampleRTT; devRTT = 0.75 * devRTT + 0.25 * difference; adaptiveRTO = estimatedRTT + 4 * devRTT; timeout = adaptiveRTO; } } uint16_t diff; if (ack.getAcknum() > server_ack) diff = ack.getAcknum() - server_ack; else diff = MAX_SEQ_NUM - server_ack + ack.getAcknum(); lastbyteAcked += diff; if (lastbyteAckedPtr + diff > file_buf + MAX_SEQ_NUM_HALF) lastbyteAckedPtr = lastbyteAckedPtr + diff - MAX_SEQ_NUM_HALF; else lastbyteAckedPtr = lastbyteAckedPtr + diff; server_ack = ack.getAcknum(); int num_acked = diff/BUFSIZE; unackedPackets -= num_acked; for (int i = 0; i < num_acked; i++) updateCwnd(); clock_start = clock_end = clock(); dupAck = 0; } else { if (state != FASTRECOVERY) { dupAck++; if (dupAck == 3) { state = FASTRECOVERY; dupAck = 0; ssthresh = cwnd/2 < BUFSIZE ? BUFSIZE : cwnd/2; ssthreshPackets = ssthresh / BUFSIZE; cwnd = ssthresh + BUFSIZE*3; cwndPackets = cwnd / BUFSIZE; segment seg; seg.setSeqnum(server_ack); int send_size; if ((maxbyte-lastbyteAcked)/BUFSIZE >= 1) send_size = BUFSIZE; else send_size = (int)(maxbyte - lastbyteAcked); if (lastbyteAckedPtr + send_size > file_buf + MAX_SEQ_NUM_HALF) { unsigned char temp[BUFSIZE]; long send_part2 = (lastbyteAckedPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF); long send_part1 = send_size - send_part2; memcpy((char*)temp, (char*)lastbyteAckedPtr, send_part1); memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2); unsigned char *send_buf = seg.encode(temp, send_size); sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen); } else { unsigned char *send_buf = seg.encode(lastbyteAckedPtr, send_size); sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen); } cout << "Sending packet " << server_ack << " " << cwnd << " " << ssthresh << " Retransmission" << endl; clock_start = clock_end = clock(); time_map.erase(server_ack); } } else { cwnd += BUFSIZE; cwndPackets += 1; } } } } clock_end = clock(); double elapsed_secs = double(clock_end - clock_start) / CLOCKS_PER_SEC; if (elapsed_secs >= timeout) { state = SLOWSTART; dupAck = 0; ssthresh = cwnd/2 < BUFSIZE ? BUFSIZE : cwnd/2; ssthreshPackets = ssthresh / BUFSIZE; cwnd = BUFSIZE; cwndPackets = 1; segment seg; seg.setSeqnum(server_ack); int send_size; if ((maxbyte-lastbyteAcked)/BUFSIZE >= 1) send_size = BUFSIZE; else send_size = (int)(maxbyte - lastbyteAcked); if (lastbyteAckedPtr + send_size > file_buf + MAX_SEQ_NUM_HALF) { unsigned char temp[BUFSIZE]; long send_part2 = (lastbyteAckedPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF); long send_part1 = send_size - send_part2; memcpy((char*)temp, (char*)lastbyteAckedPtr, send_part1); memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2); unsigned char *send_buf = seg.encode(temp, send_size); sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen); } else { unsigned char *send_buf = seg.encode(lastbyteAckedPtr, send_size); sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen); } cout << "Sending packet " << server_ack << " " << cwnd << " " << ssthresh << " Retransmission" << endl; clock_start = clock_end = clock(); timeout *= 2; time_map.erase(server_ack); } if (maxbyte - lastbyteAcked <= MAX_SEQ_NUM_HALF) { long bytes_left = MAX_SEQ_NUM_HALF - (maxbyte - lastbyteAcked); long bytes_read = 0; long read_len; if (MAX_SEQ_NUM_HALF-(maxbytePtr-file_buf) < (bytes_left)) { unsigned long part1 = MAX_SEQ_NUM_HALF - (maxbytePtr - file_buf); unsigned long part2 = bytes_left - part1; read_len = read(fd, maxbytePtr, part1); bytes_read += read_len; read_len = read(fd, file_buf, part2); bytes_read += read_len; } else { read_len = read(fd, maxbytePtr, bytes_left); bytes_read += read_len; } maxbyte += bytes_read; if (maxbytePtr + bytes_read > file_buf + MAX_SEQ_NUM_HALF) maxbytePtr = maxbytePtr + bytes_read - MAX_SEQ_NUM_HALF; else maxbytePtr = maxbytePtr + bytes_read; total_read += bytes_read; if (total_read == file_size) eof = true; } } teardown(sockfd, clientaddr, clientlen, 0, server_seq); }
static int tegra_usb_resume(struct usb_hcd *hcd) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct ehci_regs __iomem *hw = ehci->regs; unsigned long val; set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); tegra_ehci_power_up(hcd); if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) { /* Wait for the phy to detect new devices * before we restart the controller */ msleep(10); goto restart; } /* Force the phy to keep data lines in suspend state */ tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed); /* Enable host mode */ tdi_reset(ehci); /* Enable Port Power */ val = readl(&hw->port_status[0]); val |= PORT_POWER; writel(val, &hw->port_status[0]); udelay(10); /* Check if the phy resume from LP0. When the phy resume from LP0 * USB register will be reset. */ if (!readl(&hw->async_next)) { /* Program the field PTC based on the saved speed mode */ val = readl(&hw->port_status[0]); val &= ~PORT_TEST(~0); if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH) val |= PORT_TEST_FORCE; else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) val |= PORT_TEST(6); else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) val |= PORT_TEST(7); writel(val, &hw->port_status[0]); udelay(10); /* Disable test mode by setting PTC field to NORMAL_OP */ val = readl(&hw->port_status[0]); val &= ~PORT_TEST(~0); writel(val, &hw->port_status[0]); udelay(10); } /* Poll until CCS is enabled */ if (handshake(ehci, &hw->port_status[0], PORT_CONNECT, PORT_CONNECT, 2000)) { pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__); goto restart; } /* Poll until PE is enabled */ if (handshake(ehci, &hw->port_status[0], PORT_PE, PORT_PE, 2000)) { pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__); goto restart; } /* Clear the PCI status, to avoid an interrupt taken upon resume */ val = readl(&hw->status); val |= STS_PCD; writel(val, &hw->status); /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */ val = readl(&hw->port_status[0]); if ((val & PORT_POWER) && (val & PORT_PE)) { val |= PORT_SUSPEND; writel(val, &hw->port_status[0]); /* Wait until port suspend completes */ if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND, PORT_SUSPEND, 1000)) { pr_err("%s: timeout waiting for PORT_SUSPEND\n", __func__); goto restart; } } tegra_ehci_phy_restore_end(tegra->phy); return 0; restart: if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) tegra_ehci_phy_restore_end(tegra->phy); tegra_ehci_restart(hcd); return 0; }
static int tegra_ehci_hub_control( struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength ) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); u32 __iomem *status_reg; u32 temp; unsigned long flags; int retval = 0; status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; spin_lock_irqsave(&ehci->lock, flags); /* * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits * that are write on clear, by writing back the register read value, so * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits */ if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) { temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS; ehci_writel(ehci, temp & ~PORT_PE, status_reg); goto done; } else if (typeReq == GetPortStatus) { temp = ehci_readl(ehci, status_reg); if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { /* Resume completed, re-enable disconnect detection */ tegra->port_resuming = 0; tegra_usb_phy_postresume(tegra->phy); } } else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { temp = ehci_readl(ehci, status_reg); if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { retval = -EPIPE; goto done; } temp &= ~PORT_WKCONN_E; temp |= PORT_WKDISC_E | PORT_WKOC_E; ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); /* * If a transaction is in progress, there may be a delay in * suspending the port. Poll until the port is suspended. */ if (handshake(ehci, status_reg, PORT_SUSPEND, PORT_SUSPEND, 5000)) pr_err("%s: timeout waiting for SUSPEND\n", __func__); set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); goto done; } /* For USB1 port we need to issue Port Reset twice internally */ if (tegra->phy->instance == 0 && (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { spin_unlock_irqrestore(&ehci->lock, flags); return tegra_ehci_internal_port_reset(ehci, status_reg); } /* * Tegra host controller will time the resume operation to clear the bit * when the port control state switches to HS or FS Idle. This behavior * is different from EHCI where the host controller driver is required * to set this bit to a zero after the resume duration is timed in the * driver. */ else if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { temp = ehci_readl(ehci, status_reg); if ((temp & PORT_RESET) || !(temp & PORT_PE)) { retval = -EPIPE; goto done; } if (!(temp & PORT_SUSPEND)) goto done; /* Disable disconnect detection during port resume */ tegra_usb_phy_preresume(tegra->phy); ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); /* start resume signalling */ ehci_writel(ehci, temp | PORT_RESUME, status_reg); spin_unlock_irqrestore(&ehci->lock, flags); msleep(20); spin_lock_irqsave(&ehci->lock, flags); /* Poll until the controller clears RESUME and SUSPEND */ if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000)) pr_err("%s: timeout waiting for RESUME\n", __func__); if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000)) pr_err("%s: timeout waiting for SUSPEND\n", __func__); ehci->reset_done[wIndex-1] = 0; tegra->port_resuming = 1; goto done; } spin_unlock_irqrestore(&ehci->lock, flags); /* Handle the hub control events here */ return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); done: spin_unlock_irqrestore(&ehci->lock, flags); return retval; }
network::connection ana_network_manager::create_client_and_connect(std::string host, int port) { ana::net_id new_client_id = ana::invalid_net_id; try { std::stringstream ss; ss << port; ana_component* new_component = new ana_component( host, ss.str() ); components_.insert( new_component ); ana::client* const client = new_component->client(); new_client_id = client->id(); ana_connect_handler handler; client->set_raw_data_mode(); client->set_connect_timeout( ana::time::seconds(10) ); if ( proxy_settings_.enabled ) client->connect_through_proxy( proxy_settings_.address, proxy_settings_.port, &handler, proxy_settings_.user, proxy_settings_.password); else client->connect( &handler ); client->set_listener_handler( this ); client->run(); handler.wait_completion(); // just wait for handler to finish if( handler.error() ) { network::disconnect( client->id() ); throw network::error(_("Could not connect to host"), client->id() ); } else { //Send handshake ana::serializer::bostream bos; ana::ana_uint32 handshake( 0 ); bos << handshake; ana_send_handler send_handler; client->send( ana::buffer( bos.str()), &send_handler); //, ana::ZERO_COPY ); send_handler.wait_completion(); if ( send_handler.error() ) throw network::error(_("Could not connect to host"), client->id() ); else { ana::ana_uint32 my_id; ana::serializer::bistream bis; client->wait_raw_object(bis, sizeof(ana::ana_uint32) ); bis >> my_id; ana::network_to_host_long( my_id ); new_component->set_wesnoth_id( my_id ); client->set_header_first_mode(); client->run_listener(); return network::connection( client->id() ); } } } catch( const std::exception& ) { throw network::error(_("Could not connect to host"), new_client_id ); return 0; } }
int deserializarYejecutar(char** package, int sock, int* tipoProceso, int* procesoActivo) { //int *operacion; int operacion; int offset = 0; int respuestaINT; char algo[1]; int i; /*algo[0] = *package[0]; operacion = algo[0];*/ char * bufferRespuesta; memcpy(&algo, (*package + offset), sizeof(uint32_t)); //log_debug(ptrLog, "Ejecutamos la operacion:%d", operacion); operacion = algo[0]; char* respuestaOperacion = malloc(sizeof(int)); /*memory leak * * VERIFICAR * * deberia hacer un free de respuesOperacion cada vez que entra en cada case * * * */ //Compruebo que me haya hecho el handshake //if (*tipoProceso != KERNEL || *tipoProceso != CPU) { //le asigno -1 para que cuando vaya al case, caiga en el default //return -1; //} switch (operacion) { case 1: log_info(ptrLog, "En el case (SERVIDOR)"); log_debug(ptrLog, "Solicitar Bytes"); log_debug(ptrLog, "Operacion : %u ", *(*package)); log_debug(ptrLog, "Base : %u ", *(*package + sizeof(uint32_t))); log_debug(ptrLog, "Offset : %u ", *(*package + sizeof(uint32_t) + sizeof(uint32_t))); log_debug(ptrLog, "Tamanio: %u ", *(*package + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t))); t_solicitarBytes *estructuraSolicitarBytes = deserializarSolicitarBytes( package); log_debug(ptrLog, "Antes de ejecutar la fn solicitarBytes - Imprimiendo la estructura"); log_debug(ptrLog, "Base : %u ", estructuraSolicitarBytes->base); log_debug(ptrLog, "Offset : %u ", estructuraSolicitarBytes->offset); log_debug(ptrLog, "Tamanio : %u ", estructuraSolicitarBytes->tamanio); if (*tipoProceso == KERNEL || *tipoProceso == CPU) { //bufferRespuesta=malloc(estructuraSolicitarBytes->tamanio); bufferRespuesta = solicitarBytes(estructuraSolicitarBytes, procesoActivo); if (bufferRespuesta[0] == -1) { log_error(ptrLog, "SEGFAULT"); enviarDatos(sock, &bufferRespuesta, estructuraSolicitarBytes->tamanio, 0); } else { enviarDatos(sock, &bufferRespuesta, estructuraSolicitarBytes->tamanio, 0); log_debug(ptrLog, "Lo que se obtuvo es: "); for (i = 0; i < estructuraSolicitarBytes->tamanio; ++i) log_debug(ptrLog, "%x ", bufferRespuesta[i]); log_info(ptrLog, "SolicitarBytes en server correcto"); } free(bufferRespuesta); free(estructuraSolicitarBytes); free(respuestaOperacion); return 1; } else { log_error(ptrLog, "Se quiere ejecutar una operacion donde no hay una CPU o un Kernel"); log_error(ptrLog, "Se envia la respuesta fallida"); bufferRespuesta = malloc(4); respuestaINT = -1; memcpy(bufferRespuesta, &respuestaINT, sizeof(int)); enviarDatos(sock, &bufferRespuesta, sizeof(int), 0); free(estructuraSolicitarBytes); free(bufferRespuesta); free(respuestaOperacion); return 1; //VERIFICAR } case 2: log_debug(ptrLog, "En el case (SERVIDOR)"); log_debug(ptrLog, "Enviar Bytes"); log_debug(ptrLog, "Operacion: %u", *(*package)); log_debug(ptrLog, "Base: %u", *(*package + sizeof(uint32_t))); log_debug(ptrLog, "Offset: %u", *(*package + sizeof(uint32_t) + sizeof(uint32_t))); log_debug(ptrLog, "Tamanio: %u", *(*package + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t))); log_debug(ptrLog, "%u", *(*package + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t))); t_enviarBytes *estructuraEnviarBytes = deserializarEnviarBytes(package); log_debug(ptrLog, "Antes de ejecutar la fn enviarBytes - Imprimiendo la estructura"); log_debug(ptrLog, "Base: %u ", estructuraEnviarBytes->base); log_debug(ptrLog, "Offset: %u ", estructuraEnviarBytes->offset); log_debug(ptrLog, "Tamanio: %u ", estructuraEnviarBytes->tamanio); log_debug(ptrLog, "Se recibio en el buffer lo siguiente:"); for (i = 0; i < estructuraEnviarBytes->tamanio; ++i) log_debug(ptrLog, "%x ", estructuraEnviarBytes->buffer[i]); bufferRespuesta = malloc(sizeof(int)); if (*tipoProceso == KERNEL || *tipoProceso == CPU) { log_info(ptrLog, "Se procede a enviar bytes"); bufferRespuesta = enviarBytes(estructuraEnviarBytes, *procesoActivo); if (bufferRespuesta[0] == -1) { log_error(ptrLog, "SEGFAULT"); enviarDatos(sock, &bufferRespuesta, sizeof(int), 0); } else { enviarDatos(sock, &bufferRespuesta, sizeof(int), 0); log_info(ptrLog, "Se envio bytes"); } free(bufferRespuesta); free(estructuraEnviarBytes->buffer); free(estructuraEnviarBytes); free(respuestaOperacion); return 1; } else { log_error(ptrLog, "Se quiere ejecutar una operacion donde no hay una CPU o un Kernel"); log_error(ptrLog, "Se envia la respuesta fallida"); bufferRespuesta = malloc(4); respuestaINT = -1; memcpy(bufferRespuesta, &respuestaINT, sizeof(int)); enviarDatos(sock, &bufferRespuesta, sizeof(int), 0); free(estructuraEnviarBytes); free(estructuraEnviarBytes->buffer); free(bufferRespuesta); free(respuestaOperacion); return 1; //VERIFICAR } case 3: log_debug(ptrLog, "En el case (SERVIDOR)"); log_debug(ptrLog, "Handshake"); log_debug(ptrLog, "Tipo de cliente: %u", *(*package + sizeof(uint32_t))); //log_debug(ptrLog, "%u", // *(*package + sizeof(uint32_t) + sizeof(uint32_t))); handshake(deserializarHandshake(package), tipoProceso); //Ejecutar funcion Handshake free(respuestaOperacion); return 1; case 4: log_debug(ptrLog, "En el case (SERVIDOR)"); log_debug(ptrLog, "Cambio de proceso activo"); log_debug(ptrLog, "PID: %u", **package + sizeof(uint32_t)); if (*tipoProceso == KERNEL || *tipoProceso == CPU) { log_info(ptrLog, "Se procede a cambiar el PID activo"); cambiarProcesoActivo(deserializarCambiarProcesoActivo(package), procesoActivo); free(respuestaOperacion); return 1; } else { log_error(ptrLog, "Se quiere ejecutar una operacion donde no hay una CPU o un Kernel"); free(respuestaOperacion); return 1; } case 5: log_debug(ptrLog, "En el case (SERVIDOR)"); log_debug(ptrLog, "Crear segmento"); log_debug(ptrLog, "PID %u", *(*package + sizeof(uint32_t))); //log_debug(ptrLog, "%u", // *(*package + sizeof(uint32_t) + sizeof(uint32_t))); if (*tipoProceso == KERNEL) { log_info(ptrLog, "Se procede a atender la solicitud de crear segmento del kernel"); respuestaINT = crearSegmento((deserializarCrearSegmento(package))); memcpy(respuestaOperacion, &respuestaINT, sizeof(int)); //Envio tamaño de la respuesta de la funcion enviarDatos(sock, &respuestaOperacion, sizeof(int), 0); free(respuestaOperacion); return 1; } else { respuestaINT = -1; memcpy(respuestaOperacion, &respuestaINT, sizeof(int)); enviarDatos(sock, &respuestaOperacion, sizeof(int), 0); log_error(ptrLog, "Se quiere ejecutar una operacion donde no hay una CPU o un Kernel"); free(respuestaOperacion); return 1; } case 6: log_debug(ptrLog, "En el case (SERVIDOR)"); log_debug(ptrLog, "Destruir segmento"); log_debug(ptrLog, "PID %u", *(*package + sizeof(uint32_t))); if (*tipoProceso == KERNEL) { respuestaINT = destruirSegmento( deserializarDestruirSegmento(package)); memcpy(respuestaOperacion, &respuestaINT, sizeof(int)); enviarDatos(sock, &respuestaOperacion, sizeof(int), 0); free(respuestaOperacion); log_info(ptrLog, "Se realizo la destruccion del segmento"); return 1; } else { respuestaINT = -1; memcpy(respuestaOperacion, &respuestaINT, sizeof(int)); enviarDatos(sock, &respuestaOperacion, sizeof(int), 0); free(respuestaOperacion); log_error(ptrLog, "Se quiere ejecutar una operacion donde no hay una CPU o un Kernel"); return 1; } default: log_debug(ptrLog, "En el case (SERVIDOR)"); log_error(ptrLog, "No llego la opción correcta. OPERACION INCORRECTA."); return -1; } }
int ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) { uint8_t tmpbuf[4]; u16 typeReq; void *srcptr = NULL; int len, srclen; uint32_t reg; uint32_t *status_reg; int port = le16_to_cpu(req->index) & 0xff; struct ehci_ctrl *ctrl = dev->controller; srclen = 0; debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", req->request, req->request, req->requesttype, req->requesttype, le16_to_cpu(req->value), le16_to_cpu(req->index)); typeReq = req->request | req->requesttype << 8; switch (typeReq) { case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): status_reg = ehci_get_portsc_register(ctrl->hcor, port - 1); if (!status_reg) return -1; break; default: status_reg = NULL; break; } switch (typeReq) { case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch (le16_to_cpu(req->value) >> 8) { case USB_DT_DEVICE: debug("USB_DT_DEVICE request\n"); srcptr = &descriptor.device; srclen = descriptor.device.bLength; break; case USB_DT_CONFIG: debug("USB_DT_CONFIG config\n"); srcptr = &descriptor.config; srclen = descriptor.config.bLength + descriptor.interface.bLength + descriptor.endpoint.bLength; break; case USB_DT_STRING: debug("USB_DT_STRING config\n"); switch (le16_to_cpu(req->value) & 0xff) { case 0: /* Language */ srcptr = "\4\3\1\0"; srclen = 4; break; case 1: /* Vendor */ srcptr = "\16\3u\0-\0b\0o\0o\0t\0"; srclen = 14; break; case 2: /* Product */ srcptr = "\52\3E\0H\0C\0I\0 " "\0H\0o\0s\0t\0 " "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0"; srclen = 42; break; default: debug("unknown value DT_STRING %x\n", le16_to_cpu(req->value)); goto unknown; } break; default: debug("unknown value %x\n", le16_to_cpu(req->value)); goto unknown; } break; case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): switch (le16_to_cpu(req->value) >> 8) { case USB_DT_HUB: debug("USB_DT_HUB config\n"); srcptr = &descriptor.hub; srclen = descriptor.hub.bLength; break; default: debug("unknown value %x\n", le16_to_cpu(req->value)); goto unknown; } break; case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8): debug("USB_REQ_SET_ADDRESS\n"); ctrl->rootdev = le16_to_cpu(req->value); break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: debug("USB_REQ_SET_CONFIGURATION\n"); /* Nothing to do */ break; case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8): tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */ tmpbuf[1] = 0; srcptr = tmpbuf; srclen = 2; break; case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): memset(tmpbuf, 0, 4); reg = ehci_readl(status_reg); if (reg & EHCI_PS_CS) tmpbuf[0] |= USB_PORT_STAT_CONNECTION; if (reg & EHCI_PS_PE) tmpbuf[0] |= USB_PORT_STAT_ENABLE; if (reg & EHCI_PS_SUSP) tmpbuf[0] |= USB_PORT_STAT_SUSPEND; if (reg & EHCI_PS_OCA) tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT; if (reg & EHCI_PS_PR) tmpbuf[0] |= USB_PORT_STAT_RESET; if (reg & EHCI_PS_PP) tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; if (ehci_is_TDI()) { switch (ehci_get_port_speed(ctrl->hcor, reg)) { case PORTSC_PSPD_FS: break; case PORTSC_PSPD_LS: tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; break; case PORTSC_PSPD_HS: default: tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; break; } } else { tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; } if (reg & EHCI_PS_CSC) tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; if (reg & EHCI_PS_PEC) tmpbuf[2] |= USB_PORT_STAT_C_ENABLE; if (reg & EHCI_PS_OCC) tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT; if (ctrl->portreset & (1 << port)) tmpbuf[2] |= USB_PORT_STAT_C_RESET; srcptr = tmpbuf; srclen = 4; break; case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): reg = ehci_readl(status_reg); reg &= ~EHCI_PS_CLEAR; switch (le16_to_cpu(req->value)) { case USB_PORT_FEAT_ENABLE: reg |= EHCI_PS_PE; ehci_writel(status_reg, reg); break; case USB_PORT_FEAT_POWER: if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) { reg |= EHCI_PS_PP; ehci_writel(status_reg, reg); } break; case USB_PORT_FEAT_RESET: if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && !ehci_is_TDI() && EHCI_PS_IS_LOWSPEED(reg)) { /* Low speed device, give up ownership. */ debug("port %d low speed --> companion\n", port - 1); reg |= EHCI_PS_PO; ehci_writel(status_reg, reg); break; } else { int ret; reg |= EHCI_PS_PR; reg &= ~EHCI_PS_PE; ehci_writel(status_reg, reg); /* * caller must wait, then call GetPortStatus * usb 2.0 specification say 50 ms resets on * root */ ehci_powerup_fixup(status_reg, ®); ehci_writel(status_reg, reg & ~EHCI_PS_PR); /* * A host controller must terminate the reset * and stabilize the state of the port within * 2 milliseconds */ ret = handshake(status_reg, EHCI_PS_PR, 0, 2 * 1000); if (!ret) ctrl->portreset |= 1 << port; else printf("port(%d) reset error\n", port - 1); } break; case USB_PORT_FEAT_TEST: ehci_shutdown(ctrl); reg &= ~(0xf << 16); reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16; ehci_writel(status_reg, reg); break; default: debug("unknown feature %x\n", le16_to_cpu(req->value)); goto unknown; } /* unblock posted writes */ (void) ehci_readl(&ctrl->hcor->or_usbcmd); break; case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): reg = ehci_readl(status_reg); reg &= ~EHCI_PS_CLEAR; switch (le16_to_cpu(req->value)) { case USB_PORT_FEAT_ENABLE: reg &= ~EHCI_PS_PE; break; case USB_PORT_FEAT_C_ENABLE: reg |= EHCI_PS_PE; break; case USB_PORT_FEAT_POWER: if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) reg &= ~EHCI_PS_PP; break; case USB_PORT_FEAT_C_CONNECTION: reg |= EHCI_PS_CSC; break; case USB_PORT_FEAT_OVER_CURRENT: reg |= EHCI_PS_OCC; break; case USB_PORT_FEAT_C_RESET: ctrl->portreset &= ~(1 << port); break; default: debug("unknown feature %x\n", le16_to_cpu(req->value)); goto unknown; } ehci_writel(status_reg, reg); /* unblock posted write */ (void) ehci_readl(&ctrl->hcor->or_usbcmd); break; default: debug("Unknown request\n"); goto unknown; }
/** * This function is used to perform SSL handshaking on the stream. The * function call will block until handshaking is complete or an error occurs. * * @param type The type of handshaking to be performed, i.e. as a client or as * a server. * * @throws boost::system::system_error Thrown on failure. */ void handshake(handshake_type type) { boost::system::error_code ec; handshake(type, ec); boost::asio::detail::throw_error(ec, "handshake"); }
void zmq::stream_engine_t::in_event () { // If still handshaking, receive and prcess the greeting message. if (unlikely (handshaking)) if (!handshake ()) return; zmq_assert (decoder); bool disconnection = false; // If there's no data to process in the buffer... if (!insize) { // Retrieve the buffer and read as much data as possible. // Note that buffer can be arbitrarily large. However, we assume // the underlying TCP layer has fixed buffer size and thus the // number of bytes read will be always limited. decoder->get_buffer (&inpos, &insize); insize = read (inpos, insize); // Check whether the peer has closed the connection. if (insize == (size_t) -1) { insize = 0; disconnection = true; } } // Push the data to the decoder. size_t processed = decoder->process_buffer (inpos, insize); if (unlikely (processed == (size_t) -1)) { disconnection = true; } else { // Stop polling for input if we got stuck. if (processed < insize) reset_pollin (handle); // Adjust the buffer. inpos += processed; insize -= processed; } // Flush all messages the decoder may have produced. session->flush (); // Input error has occurred. If the last decoded // message has already been accepted, we terminate // the engine immediately. Otherwise, we stop // waiting for input events and postpone the termination // until after the session has accepted the message. if (disconnection) { if (decoder->stalled ()) { rm_fd (handle); io_enabled = false; } else error (); } }
/** * This function is used to perform SSL handshaking on the stream. The * function call will block until handshaking is complete or an error occurs. * * @param type The type of handshaking to be performed, i.e. as a client or as * a server. * * @throws asio::system_error Thrown on failure. */ void handshake(handshake_type type) { asio::error_code ec; handshake(type, ec); asio::detail::throw_error(ec, "handshake"); }
static int msm_hsic_resume_thread(void *data) { struct msm_hsic_hcd *mehci = data; struct usb_hcd *hcd = hsic_to_hcd(mehci); struct ehci_hcd *ehci = hcd_to_ehci(hcd); u32 temp; unsigned long resume_needed = 0; int retry_cnt = 0; int tight_resume = 0; struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data; dbg_log_event(NULL, "Resume RH", 0); /* keep delay between bus states */ if (time_before(jiffies, ehci->next_statechange)) usleep_range(5000, 5000); spin_lock_irq(&ehci->lock); if (!HCD_HW_ACCESSIBLE(hcd)) { spin_unlock_irq(&ehci->lock); mehci->resume_status = -ESHUTDOWN; complete(&mehci->rt_completion); return 0; } if (unlikely(ehci->debug)) { if (!dbgp_reset_prep()) ehci->debug = NULL; else dbgp_external_startup(); } /* at least some APM implementations will try to deliver * IRQs right away, so delay them until we're ready. */ ehci_writel(ehci, 0, &ehci->regs->intr_enable); /* re-init operational registers */ ehci_writel(ehci, 0, &ehci->regs->segment); ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next); /*CMD_RUN will be set after, PORT_RESUME gets cleared*/ if (ehci->resume_sof_bug) ehci->command &= ~CMD_RUN; /* restore CMD_RUN, framelist size, and irq threshold */ ehci_writel(ehci, ehci->command, &ehci->regs->command); /* manually resume the ports we suspended during bus_suspend() */ resume_again: if (retry_cnt >= RESUME_RETRY_LIMIT) { pr_info("retry count(%d) reached max, resume in tight loop\n", retry_cnt); tight_resume = 1; } temp = ehci_readl(ehci, &ehci->regs->port_status[0]); temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) { temp |= PORT_RESUME; set_bit(0, &resume_needed); } dbg_log_event(NULL, "FPR: Set", temp); ehci_writel(ehci, temp, &ehci->regs->port_status[0]); /* HSIC controller has a h/w bug due to which it can try to send SOFs * (start of frames) during port resume resulting in phy lockup. HSIC hw * controller in MSM clears FPR bit after driving the resume signal for * 20ms. Workaround is to stop SOFs before driving resume and then start * sending SOFs immediately. Need to send SOFs within 3ms of resume * completion otherwise peripheral may enter undefined state. As * usleep_range does not gurantee exact sleep time, GPTimer is used to * to time the resume sequence. If driver exceeds allowable time SOFs, * repeat the resume process. */ if (ehci->resume_sof_bug && resume_needed) { if (!tight_resume) { mehci->resume_again = 0; ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_MS), &mehci->timer->gptimer0_ld); ehci_writel(ehci, GPT_RESET | GPT_RUN, &mehci->timer->gptimer0_ctrl); ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT, &ehci->regs->intr_enable); ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_SOF_MS), &mehci->timer->gptimer1_ld); ehci_writel(ehci, GPT_RESET | GPT_RUN, &mehci->timer->gptimer1_ctrl); spin_unlock_irq(&ehci->lock); if (pdata && pdata->swfi_latency) pm_qos_update_request(&mehci->pm_qos_req_dma, pdata->swfi_latency + 1); wait_for_completion(&mehci->gpt0_completion); if (pdata && pdata->swfi_latency) pm_qos_update_request(&mehci->pm_qos_req_dma, PM_QOS_DEFAULT_VALUE); spin_lock_irq(&ehci->lock); } else { dbg_log_event(NULL, "FPR: Tightloop", 0); /* do the resume in a tight loop */ handshake(ehci, &ehci->regs->port_status[0], PORT_RESUME, 0, 22 * 1000); ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) | CMD_RUN, &ehci->regs->command); } if (mehci->resume_again) { int temp; dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt); pr_info("FPR: retry count: %d\n", retry_cnt); spin_unlock_irq(&ehci->lock); temp = ehci_readl(ehci, &ehci->regs->port_status[0]); temp &= ~PORT_RWC_BITS; temp |= PORT_SUSPEND; ehci_writel(ehci, temp, &ehci->regs->port_status[0]); /* Keep the bus idle for 5ms so that peripheral * can detect and initiate suspend */ usleep_range(5000, 5000); dbg_log_event(NULL, "FPR: RResume", ehci_readl(ehci, &ehci->regs->port_status[0])); spin_lock_irq(&ehci->lock); mehci->resume_again = 0; retry_cnt++; goto resume_again; } } dbg_log_event(NULL, "FPR: RT-Done", 0); mehci->resume_status = 1; spin_unlock_irq(&ehci->lock); complete(&mehci->rt_completion); return 0; }
static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) { struct QH *qh; struct qTD *td; volatile struct qTD *vtd; unsigned long ts; uint32_t *tdp; uint32_t endpt, token, usbsts; uint32_t c, toggle; uint32_t cmd; int timeout; int ret = 0; debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, buffer, length, req); if (req != NULL) debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", req->request, req->request, req->requesttype, req->requesttype, le16_to_cpu(req->value), le16_to_cpu(req->value), le16_to_cpu(req->index)); qh = ehci_alloc(sizeof(struct QH), 32); if (qh == NULL) { debug("unable to allocate QH\n"); return -1; } qh->qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); c = (usb_pipespeed(pipe) != USB_SPEED_HIGH && usb_pipeendpoint(pipe) == 0) ? 1 : 0; endpt = (8 << 28) | (c << 27) | (usb_maxpacket(dev, pipe) << 16) | (0 << 15) | (1 << 14) | (usb_pipespeed(pipe) << 12) | (usb_pipeendpoint(pipe) << 8) | (0 << 7) | (usb_pipedevice(pipe) << 0); qh->qh_endpt1 = cpu_to_hc32(endpt); endpt = (1 << 30) | (dev->portnr << 23) | (dev->parent->devnum << 16) | (0 << 8) | (0 << 0); qh->qh_endpt2 = cpu_to_hc32(endpt); qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); td = NULL; tdp = &qh->qh_overlay.qt_next; toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); if (req != NULL) { td = ehci_alloc(sizeof(struct qTD), 32); if (td == NULL) { debug("unable to allocate SETUP td\n"); goto fail; } td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = (0 << 31) | (sizeof(*req) << 16) | (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0); td->qt_token = cpu_to_hc32(token); if (ehci_td_buffer(td, req, sizeof(*req)) != 0) { debug("unable construct SETUP td\n"); ehci_free(td, sizeof(*td)); goto fail; } *tdp = cpu_to_hc32((uint32_t) td); tdp = &td->qt_next; toggle = 1; } if (length > 0 || req == NULL) { td = ehci_alloc(sizeof(struct qTD), 32); if (td == NULL) { debug("unable to allocate DATA td\n"); goto fail; } td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = (toggle << 31) | (length << 16) | ((req == NULL ? 1 : 0) << 15) | (0 << 12) | (3 << 10) | ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0); td->qt_token = cpu_to_hc32(token); if (ehci_td_buffer(td, buffer, length) != 0) { debug("unable construct DATA td\n"); ehci_free(td, sizeof(*td)); goto fail; } *tdp = cpu_to_hc32((uint32_t) td); tdp = &td->qt_next; } if (req != NULL) { td = ehci_alloc(sizeof(struct qTD), 32); if (td == NULL) { debug("unable to allocate ACK td\n"); goto fail; } td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); token = (toggle << 31) | (0 << 16) | (1 << 15) | (0 << 12) | (3 << 10) | ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0); td->qt_token = cpu_to_hc32(token); *tdp = cpu_to_hc32((uint32_t) td); tdp = &td->qt_next; } qh_list.qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH); /* Flush dcache */ ehci_flush_dcache(&qh_list); usbsts = ehci_readl(&hcor->or_usbsts); ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f)); /* Enable async. schedule. */ cmd = ehci_readl(&hcor->or_usbcmd); cmd |= CMD_ASE; ehci_writel(&hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STD_ASS set\n"); goto fail; } /* Wait for TDs to be processed. */ ts = get_timer(0); vtd = td; timeout = USB_TIMEOUT_MS(pipe); do { /* Invalidate dcache */ ehci_invalidate_dcache(&qh_list); token = hc32_to_cpu(vtd->qt_token); if (!(token & 0x80)) break; WATCHDOG_RESET(); } while (get_timer(ts) < timeout); /* Check that the TD processing happened */ if (token & 0x80) { printf("EHCI timed out on TD - token=%#x\n", token); } /* Disable async schedule. */ cmd = ehci_readl(&hcor->or_usbcmd); cmd &= ~CMD_ASE; ehci_writel(&hcor->or_usbcmd, cmd); ret = handshake((uint32_t *)&hcor->or_usbsts, STD_ASS, 0, 100 * 1000); if (ret < 0) { printf("EHCI fail timeout STD_ASS reset\n"); goto fail; } qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); token = hc32_to_cpu(qh->qh_overlay.qt_token); if (!(token & 0x80)) { debug("TOKEN=%#x\n", token); switch (token & 0xfc) { case 0: toggle = token >> 31; usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle); dev->status = 0; break; case 0x40: dev->status = USB_ST_STALLED; break; case 0xa0: case 0x20: dev->status = USB_ST_BUF_ERR; break; case 0x50: case 0x10: dev->status = USB_ST_BABBLE_DET; break; default: dev->status = USB_ST_CRC_ERR; if ((token & 0x40) == 0x40) dev->status |= USB_ST_STALLED; break; } dev->act_len = length - ((token >> 16) & 0x7fff); } else {
static jdwpTransportError JNICALL socketTransport_accept(jdwpTransportEnv* env, jlong acceptTimeout, jlong handshakeTimeout) { int socketLen, err; struct sockaddr_in socket; jlong startTime = (jlong)0; /* * Use a default handshake timeout if not specified - this avoids an indefinite * hang in cases where something other than a debugger connects to our port. */ if (handshakeTimeout == 0) { handshakeTimeout = 2000; } do { /* * If there is an accept timeout then we put the socket in non-blocking * mode and poll for a connection. */ if (acceptTimeout > 0) { int rv; dbgsysConfigureBlocking(serverSocketFD, JNI_FALSE); startTime = dbgsysCurrentTimeMillis(); rv = dbgsysPoll(serverSocketFD, JNI_TRUE, JNI_FALSE, (long)acceptTimeout); if (rv <= 0) { /* set the last error here as could be overridden by configureBlocking */ if (rv == 0) { setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "poll failed"); } /* restore blocking state */ dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE); if (rv == 0) { RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "timed out waiting for connection"); } else { return JDWPTRANSPORT_ERROR_IO_ERROR; } } } /* * Accept the connection */ memset((void *)&socket,0,sizeof(struct sockaddr_in)); socketLen = sizeof(socket); socketFD = dbgsysAccept(serverSocketFD, (struct sockaddr *)&socket, &socketLen); /* set the last error here as could be overridden by configureBlocking */ if (socketFD < 0) { setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "accept failed"); } /* * Restore the blocking state - note that the accepted socket may be in * blocking or non-blocking mode (platform dependent). However as there * is a handshake timeout set then it will go into non-blocking mode * anyway for the handshake. */ if (acceptTimeout > 0) { dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE); } if (socketFD < 0) { return JDWPTRANSPORT_ERROR_IO_ERROR; } /* handshake with the debugger */ err = handshake(socketFD, handshakeTimeout); /* * If the handshake fails then close the connection. If there if an accept * timeout then we must adjust the timeout for the next poll. */ if (err) { fprintf(stderr, "Debugger failed to attach: %s\n", getLastError()); dbgsysSocketClose(socketFD); socketFD = -1; if (acceptTimeout > 0) { long endTime = dbgsysCurrentTimeMillis(); acceptTimeout -= (endTime - startTime); if (acceptTimeout <= 0) { setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "timeout waiting for debugger to connect"); return JDWPTRANSPORT_ERROR_IO_ERROR; } } } } while (socketFD < 0); return JDWPTRANSPORT_ERROR_NONE; }