void uip_igmpsend(FAR struct uip_driver_s *dev, FAR struct igmp_group_s *group, FAR uip_ipaddr_t *destipaddr) { nllvdbg("msgid: %02x destipaddr: %08x\n", group->msgid, (int)*destipaddr); /* The total length to send is the size of the IP and IGMP headers and 4 * bytes for the ROUTER ALERT (and, eventually, the ethernet header) */ dev->d_len = UIP_IPIGMPH_LEN; /* The total size of the data is the size of the IGMP header */ dev->d_sndlen = UIP_IGMPH_LEN; /* Add the router alert option */ IGMPBUF->ra[0] = HTONS(IPOPT_RA >> 16); IGMPBUF->ra[1] = HTONS(IPOPT_RA & 0xffff); /* Initialize the IPv4 header */ IGMPBUF->vhl = 0x46; /* 4->IP; 6->24 bytes */ IGMPBUF->tos = 0; IGMPBUF->len[0] = (dev->d_len >> 8); IGMPBUF->len[1] = (dev->d_len & 0xff); ++g_ipid; IGMPBUF->ipid[0] = g_ipid >> 8; IGMPBUF->ipid[1] = g_ipid & 0xff; IGMPBUF->ipoffset[0] = UIP_TCPFLAG_DONTFRAG >> 8; IGMPBUF->ipoffset[1] = UIP_TCPFLAG_DONTFRAG & 0xff; IGMPBUF->ttl = IGMP_TTL; IGMPBUF->proto = UIP_PROTO_IGMP; uiphdr_ipaddr_copy(IGMPBUF->srcipaddr, &dev->d_ipaddr); uiphdr_ipaddr_copy(IGMPBUF->destipaddr, destipaddr); /* Calculate IP checksum. */ IGMPBUF->ipchksum = 0; IGMPBUF->ipchksum = ~uip_igmpchksum((FAR uint8_t *)IGMPBUF, UIP_IPH_LEN + RASIZE); /* Set up the IGMP message */ IGMPBUF->type = group->msgid; IGMPBUF->maxresp = 0; uiphdr_ipaddr_copy(IGMPBUF->grpaddr, &group->grpaddr); /* Calculate the IGMP checksum. */ IGMPBUF->chksum = 0; IGMPBUF->chksum = ~uip_igmpchksum(&IGMPBUF->type, UIP_IPIGMPH_LEN); IGMP_STATINCR(uip_stat.igmp.poll_send); IGMP_STATINCR(uip_stat.ip.sent); nllvdbg("Outgoing IGMP packet length: %d (%d)\n", dev->d_len, (IGMPBUF->len[0] << 8) | IGMPBUF->len[1]); igmp_dumppkt(RA, UIP_IPIGMPH_LEN + RASIZE); }
static uint16_t ack_interrupt(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { FAR struct sendfile_s *pstate = (FAR struct sendfile_s *)pvpriv; nllvdbg("flags: %04x\n", flags); if ((flags & TCP_ACKDATA) != 0) { #ifdef CONFIG_NET_SOCKOPTS /* Update the timeout */ pstate->snd_time = clock_systimer(); #endif /* The current acknowledgement number number is the (relative) offset * of the of the next byte needed by the receiver. The snd_isn is the * offset of the first byte to send to the receiver. The difference * is the number of bytes to be acknowledged. */ pstate->snd_acked = tcp_getsequence(TCPBUF->ackno) - pstate->snd_isn; nllvdbg("ACK: acked=%d sent=%d flen=%d\n", pstate->snd_acked, pstate->snd_sent, pstate->snd_flen); dev->d_sndlen = 0; flags &= ~TCP_ACKDATA; } else if ((flags & TCP_REXMIT) != 0) { nlldbg("REXMIT\n"); /* Yes.. in this case, reset the number of bytes that have been sent * to the number of bytes that have been ACKed. */ pstate->snd_sent = pstate->snd_acked; } /* Check for a loss of connection */ else if ((flags & (TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT)) != 0) { /* Report not connected */ nlldbg("Lost connection\n"); net_lostconnection(pstate->snd_sock, flags); pstate->snd_sent = -ENOTCONN; } /* Wake up the waiting thread */ sem_post(&pstate->snd_sem); return flags; }
static inline uint16_t tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn, uint16_t flags) { uint16_t ret; /* Assume that we will ACK the data. The data will be ACKed if it is * placed in the read-ahead buffer -OR- if it zero length */ ret = (flags & ~TCP_NEWDATA) | TCP_SNDACK; /* Is there new data? With non-zero length? (Certain connection events * can have zero-length with TCP_NEWDATA set just to cause an ACK). */ if (dev->d_len > 0) { #ifdef CONFIG_NET_TCP_READAHEAD uint8_t *buffer = dev->d_appdata; int buflen = dev->d_len; uint16_t recvlen; #endif nllvdbg("No listener on connection\n"); #ifdef CONFIG_NET_TCP_READAHEAD /* Save as the packet data as in the read-ahead buffer. NOTE that * partial packets will not be buffered. */ recvlen = tcp_datahandler(conn, buffer, buflen); if (recvlen < buflen) #endif { /* There is no handler to receive new data and there are no free * read-ahead buffers to retain the data -- drop the packet. */ nllvdbg("Dropped %d bytes\n", dev->d_len); #ifdef CONFIG_NET_STATISTICS g_netstats.tcp.syndrop++; g_netstats.tcp.drop++; #endif /* Clear the TCP_SNDACK bit so that no ACK will be sent */ ret &= ~TCP_SNDACK; } } /* In any event, the new data has now been handled */ dev->d_len = 0; return ret; }
static int lo_txpoll(FAR struct net_driver_s *dev) { FAR struct lo_driver_s *priv = (FAR struct lo_driver_s *)dev->d_private; /* Loop while there is data "sent", i.e., while d_len > 0. That should be * the case upon entry here and while the processing of the IPv4/6 packet * generates a new packet to be sent. Sending, of course, just means * relaying back through the network for this driver. */ while (priv->lo_dev.d_len > 0) { NETDEV_TXPACKETS(&priv->lo_dev); NETDEV_RXPACKETS(&priv->lo_dev); #ifdef CONFIG_NET_PKT /* When packet sockets are enabled, feed the frame into the packet tap */ pkt_input(&priv->lo_dev); #endif /* We only accept IP packets of the configured type and ARP packets */ #ifdef CONFIG_NET_IPv4 if ((IPv4BUF->vhl & IP_VERSION_MASK) == IPv4_VERSION) { nllvdbg("IPv4 frame\n"); NETDEV_RXIPV4(&priv->lo_dev); ipv4_input(&priv->lo_dev); } else #endif #ifdef CONFIG_NET_IPv6 if ((IPv6BUF->vtc & IP_VERSION_MASK) == IPv6_VERSION) { nllvdbg("Iv6 frame\n"); NETDEV_RXIPV6(&priv->lo_dev); ipv6_input(&priv->lo_dev); } else #endif { ndbg("WARNING: Unrecognized packet type dropped: %02x\n", IPv4BUF->vhl); NETDEV_RXDROPPED(&priv->lo_dev); priv->lo_dev.d_len = 0; } priv->lo_txdone = true; NETDEV_TXDONE(&priv->lo_dev); } return 0; }
static inline uint16_t net_dataevent(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn, uint16_t flags) { uint16_t ret; ret = (flags & ~UDP_NEWDATA); /* Is there new data? With non-zero length? (Certain connection events * can have zero-length with UDP_NEWDATA set just to cause an ACK). */ if (dev->d_len > 0) { #ifdef CONFIG_NET_UDP_READAHEAD uint8_t *buffer = dev->d_appdata; int buflen = dev->d_len; uint16_t recvlen; #endif nllvdbg("No receive on connection\n"); #ifdef CONFIG_NET_UDP_READAHEAD /* Save as the packet data as in the read-ahead buffer. NOTE that * partial packets will not be buffered. */ recvlen = udp_datahandler(dev, conn, buffer, buflen); if (recvlen < buflen) #endif { /* There is no handler to receive new data and there are no free * read-ahead buffers to retain the data -- drop the packet. */ nllvdbg("Dropped %d bytes\n", dev->d_len); #ifdef CONFIG_NET_STATISTICS g_netstats.udp.drop++; #endif } } /* In any event, the new data has now been handled */ dev->d_len = 0; return ret; }
static size_t recvfrom_newdata(FAR struct uip_driver_s *dev, FAR struct recvfrom_s *pstate) { size_t recvlen; /* Get the length of the data to return */ if (dev->d_len > pstate->rf_buflen) { recvlen = pstate->rf_buflen; } else { recvlen = dev->d_len; } /* Copy the new appdata into the user buffer */ memcpy(pstate->rf_buffer, dev->d_appdata, recvlen); nllvdbg("Received %d bytes (of %d)\n", (int)recvlen, (int)dev->d_len); /* Update the accumulated size of the data read */ pstate->rf_recvlen += recvlen; pstate->rf_buffer += recvlen; pstate->rf_buflen -= recvlen; return recvlen; }
static void tcp_sendcomplete(FAR struct net_driver_s *dev, FAR struct tcp_hdr_s *tcp) { #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 if (IFF_IS_IPv6(dev->d_flags)) #endif { tcp_ipv6_sendcomplete(dev, tcp, IPv6BUF); } #endif /* CONFIG_NET_IPv6 */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 else #endif { tcp_ipv4_sendcomplete(dev, tcp, IPv4BUF); } #endif /* CONFIG_NET_IPv4 */ nllvdbg("Outgoing TCP packet length: %d bytes\n", dev->d_len); #ifdef CONFIG_NET_STATISTICS g_netstats.tcp.sent++; #endif }
void igmp_poll(FAR struct net_driver_s *dev) { FAR struct igmp_group_s *group; nllvdbg("Entry\n"); /* Setup the poll operation */ dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev) + IPIGMP_HDRLEN]; dev->d_snddata = &dev->d_buf[NET_LL_HDRLEN(dev) + IPIGMP_HDRLEN]; dev->d_len = 0; dev->d_sndlen = 0; /* Check each member of the group */ for (group = (FAR struct igmp_group_s *)dev->grplist.head; group; group = group->next) { /* Does this member have a pending outgoing message? */ if (IS_SCHEDMSG(group->flags)) { /* Yes, create the IGMP message in the driver buffer */ igmp_sched_send(dev, group); /* Mark the message as sent and break out */ CLR_SCHEDMSG(group->flags); break; } } }
static void connection_event(struct uip_conn *conn, uint16_t flags) { FAR struct socket *psock = (FAR struct socket *)conn->connection_private; if (psock) { nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags); /* UIP_CLOSE: The remote host has closed the connection * UIP_ABORT: The remote host has aborted the connection * UIP_TIMEDOUT: Connection aborted due to too many retransmissions. */ if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) { /* Indicate that the socket is no longer connected */ psock->s_flags &= ~_SF_CONNECTED; } /* UIP_CONNECTED: The socket is successfully connected */ else if ((flags & UIP_CONNECTED) != 0) { /* Indicate that the socket is now connected */ psock->s_flags |= _SF_CONNECTED; } } }
static void uip_tcpsendcomplete(struct uip_driver_s *dev) { struct uip_tcpip_hdr *pbuf = BUF; pbuf->ttl = UIP_TTL; #ifdef CONFIG_NET_IPv6 /* For IPv6, the IP length field does not include the IPv6 IP header * length. */ pbuf->len[0] = ((dev->d_len - UIP_IPH_LEN) >> 8); pbuf->len[1] = ((dev->d_len - UIP_IPH_LEN) & 0xff); #else /* CONFIG_NET_IPv6 */ pbuf->len[0] = (dev->d_len >> 8); pbuf->len[1] = (dev->d_len & 0xff); #endif /* CONFIG_NET_IPv6 */ pbuf->urgp[0] = pbuf->urgp[1] = 0; /* Calculate TCP checksum. */ pbuf->tcpchksum = 0; pbuf->tcpchksum = ~(uip_tcpchksum(dev)); #ifdef CONFIG_NET_IPv6 pbuf->vtc = 0x60; pbuf->tcf = 0x00; pbuf->flow = 0x00; #else /* CONFIG_NET_IPv6 */ pbuf->vhl = 0x45; pbuf->tos = 0; pbuf->ipoffset[0] = 0; pbuf->ipoffset[1] = 0; ++g_ipid; pbuf->ipid[0] = g_ipid >> 8; pbuf->ipid[1] = g_ipid & 0xff; /* Calculate IP checksum. */ pbuf->ipchksum = 0; pbuf->ipchksum = ~(uip_ipchksum(dev)); #endif /* CONFIG_NET_IPv6 */ nllvdbg("Outgoing TCP packet length: %d (%d)\n", dev->d_len, (pbuf->len[0] << 8) | pbuf->len[1]); #ifdef CONFIG_NET_STATISTICS uip_stat.tcp.sent++; uip_stat.ip.sent++; #endif }
void uip_tcprexmit(struct uip_driver_s *dev, struct uip_conn *conn, uint16_t result) { nllvdbg("result: %04x d_sndlen: %d conn->unacked: %d\n", result, dev->d_sndlen, conn->unacked); dev->d_appdata = dev->d_snddata; /* If the application has data to be sent, or if the incoming packet had * new data in it, we must send out a packet. */ if (dev->d_sndlen > 0 && conn->unacked > 0) { /* We always set the ACK flag in response packets adding the length of * the IP and TCP headers. */ uip_tcpsend(dev, conn, TCP_ACK | TCP_PSH, dev->d_sndlen + UIP_TCPIP_HLEN); } /* If there is no data to send, just send out a pure ACK if one is requested`. */ else if ((result & UIP_SNDACK) != 0) { uip_tcpsend(dev, conn, TCP_ACK, UIP_TCPIP_HLEN); } /* There is nothing to do -- drop the packet */ else { dev->d_len = 0; } }
static void uip_igmptimeout(int argc, uint32_t arg, ...) { FAR struct igmp_group_s *group; /* If the state is DELAYING_MEMBER then we send a report for this group */ nllvdbg("Timeout!\n"); group = (FAR struct igmp_group_s *)arg; DEBUGASSERT(argc == 1 && group); /* If the group exists and is no an IDLE MEMBER, then it must be a DELAYING * member. Race conditions are avoided because (1) the timer is not started * until after the first IGMPv2_MEMBERSHIP_REPORT during the join, and (2) * the timer is canceled before sending the IGMP_LEAVE_GROUP during a leave. */ if (!IS_IDLEMEMBER(group->flags)) { /* Schedule (and forget) the Membership Report. NOTE: * Since we are executing from a timer interrupt, we cannot wait * for the message to be sent. */ IGMP_STATINCR(uip_stat.igmp.report_sched); uip_igmpschedmsg(group, IGMPv2_MEMBERSHIP_REPORT); /* Also note: The Membership Report is sent at most two times becasue * the timer is not reset here. Hmm.. does this mean that the group * is stranded if both reports were lost? This is consistent with the * RFC that states: "To cover the possibility of the initial Membership * Report being lost or damaged, it is recommended that it be repeated * once or twice after shortdelays [Unsolicited Report Interval]..." */ } }
static void connection_event(FAR struct uip_conn *conn, uint16_t flags) { FAR struct socket *psock = (FAR struct socket *)conn->connection_private; if (psock) { nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags); /* UIP_CLOSE, UIP_ABORT, or UIP_TIMEDOUT: Loss-of-connection events */ if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) { net_lostconnection(psock, flags); } /* UIP_CONNECTED: The socket is successfully connected */ else if ((flags & UIP_CONNECTED) != 0) { /* Indicate that the socket is now connected */ psock->s_flags |= _SF_CONNECTED; psock->s_flags &= ~_SF_CLOSED; } } }
static uint16_t connection_event(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { FAR struct socket *psock = (FAR struct socket *)pvpriv; if (psock) { nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags); /* TCP_DISCONN_EVENTS: TCP_CLOSE, TCP_ABORT, TCP_TIMEDOUT, or * NETDEV_DOWN. All loss-of-connection events. */ if ((flags & TCP_DISCONN_EVENTS) != 0) { connection_closed(psock, flags); } /* TCP_CONNECTED: The socket is successfully connected */ else if ((flags & TCP_CONNECTED) != 0) { /* Indicate that the socket is now connected */ psock->s_flags |= _SF_CONNECTED; psock->s_flags &= ~_SF_CLOSED; } } return flags; }
void icmp_send(FAR struct net_driver_s *dev, FAR in_addr_t *destaddr) { FAR struct icmp_iphdr_s *picmp = ICMPBUF; if (dev->d_sndlen > 0) { IFF_SET_IPv4(dev->d_flags); /* The total length to send is the size of the application data plus * the IP and ICMP headers (and, eventually, the Ethernet header) */ dev->d_len = dev->d_sndlen + IPICMP_HDRLEN; /* The total size of the data (for ICMP checksum calculation) includes * the size of the ICMP header */ dev->d_sndlen += ICMP_HDRLEN; /* Initialize the IP header. */ picmp->vhl = 0x45; picmp->tos = 0; picmp->len[0] = (dev->d_len >> 8); picmp->len[1] = (dev->d_len & 0xff); ++g_ipid; picmp->ipid[0] = g_ipid >> 8; picmp->ipid[1] = g_ipid & 0xff; picmp->ipoffset[0] = IP_FLAG_DONTFRAG >> 8; picmp->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff; picmp->ttl = IP_TTL; picmp->proto = IP_PROTO_ICMP; net_ipv4addr_hdrcopy(picmp->srcipaddr, &dev->d_ipaddr); net_ipv4addr_hdrcopy(picmp->destipaddr, destaddr); /* Calculate IP checksum. */ picmp->ipchksum = 0; picmp->ipchksum = ~(ipv4_chksum(dev)); /* Calculate the ICMP checksum. */ picmp->icmpchksum = 0; picmp->icmpchksum = ~(icmp_chksum(dev, dev->d_sndlen)); if (picmp->icmpchksum == 0) { picmp->icmpchksum = 0xffff; } nllvdbg("Outgoing ICMP packet length: %d (%d)\n", dev->d_len, (picmp->len[0] << 8) | picmp->len[1]); #ifdef CONFIG_NET_STATISTICS g_netstats.icmp.sent++; g_netstats.ipv4.sent++; #endif }
uint16_t uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn, uint16_t flags) { /* Preserve the UIP_ACKDATA, UIP_CLOSE, and UIP_ABORT in the response. * These is needed by uIP to handle responses and buffer state. The * UIP_NEWDATA indication will trigger the ACK response, but must be * explicitly set in the callback. */ nllvdbg("flags: %04x\n", flags); /* Perform the data callback. When a data callback is executed from 'list', * the input flags are normally returned, however, the implementation * may set one of the following: * * UIP_CLOSE - Gracefully close the current connection * UIP_ABORT - Abort (reset) the current connection on an error that * prevents UIP_CLOSE from working. * * And/Or set/clear the following: * * UIP_NEWDATA - May be cleared to indicate that the data was consumed * and that no further process of the new data should be * attempted. * UIP_SNDACK - If UIP_NEWDATA is cleared, then UIP_SNDACK may be set * to indicate that an ACK should be included in the response. * (In UIP_NEWDATA is cleared bu UIP_SNDACK is not set, then * dev->d_len should also be cleared). */ flags = uip_callbackexecute(dev, conn, flags, conn->list); /* There may be no new data handler in place at them moment that the new * incoming data is received. If the new incoming data was not handled, then * either (1) put the unhandled incoming data in the read-ahead buffer (if * enabled) or (2) suppress the ACK to the data in the hope that it will * be re-transmitted at a better time. */ if ((flags & UIP_NEWDATA) != 0) { /* Data was not handled.. dispose of it appropriately */ flags = uip_dataevent(dev, conn, flags); } /* Check if there is a connection-related event and a connection * callback. */ if (((flags & UIP_CONN_EVENTS) != 0) && conn->connection_event) { /* Perform the callback */ conn->connection_event(conn, flags); } return flags; }
int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn) { FAR struct uip_backlog_s *bls; FAR struct uip_blcontainer_s *blc; FAR struct uip_blcontainer_s *prev; nllvdbg("conn=%p blconn=%p\n", conn, blconn); #ifdef CONFIG_DEBUG if (!conn) { return -EINVAL; } #endif bls = conn->backlog; if (bls) { /* Find the container hold the connection */ for (blc = (FAR struct uip_blcontainer_s *)sq_peek(&bls->bl_pending), prev = NULL; blc; prev = blc, blc = (FAR struct uip_blcontainer_s *)sq_next(&blc->bc_node)) { if (blc->bc_conn == blconn) { if (prev) { /* Remove the a container from the middle of the list of * pending connections */ (void)sq_remafter(&prev->bc_node, &bls->bl_pending); } else { /* Remove the a container from the head of the list of * pending connections */ (void)sq_remfirst(&bls->bl_pending); } /* Put container in the free list */ blc->bc_conn = NULL; sq_addlast(&blc->bc_node, &bls->bl_free); return OK; } } nlldbg("Failed to find pending connection\n"); return -EINVAL; } return OK; }
static inline void igmp_sched_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group) { net_ipaddr_t *dest; /* Check what kind of message we need to send. There are only two * possibilities: */ if (group->msgid == IGMPv2_MEMBERSHIP_REPORT) { dest = &group->grpaddr; nllvdbg("Send IGMPv2_MEMBERSHIP_REPORT, dest=%08x flags=%02x\n", *dest, group->flags); IGMP_STATINCR(g_netstats.igmp.report_sched); SET_LASTREPORT(group->flags); /* Remember we were the last to report */ } else { DEBUGASSERT(group->msgid == IGMP_LEAVE_GROUP); dest = &g_allrouters; nllvdbg("Send IGMP_LEAVE_GROUP, dest=%08x flags=%02x\n", *dest, group->flags); IGMP_STATINCR(g_netstats.igmp.leave_sched); } /* Send the message */ igmp_send(dev, group, dest); /* Indicate that the message has been sent */ CLR_SCHEDMSG(group->flags); group->msgid = 0; /* If there is a thread waiting fore the message to be sent, wake it up */ if (IS_WAITMSG(group->flags)) { nllvdbg("Awakening waiter\n"); sem_post(&group->sem); } }
uint16_t hci_command_send(uint16_t usOpcode, uint8_t *pucBuff, uint8_t ucArgsLength) { uint8_t *stream; stream = (pucBuff + SPI_HEADER_SIZE); nllvdbg("Send 0x%x\n", usOpcode); UINT8_TO_STREAM(stream, HCI_TYPE_CMND); stream = UINT16_TO_STREAM(stream, usOpcode); UINT8_TO_STREAM(stream, ucArgsLength); /* Update the opcode of the event we will be waiting for */ cc3000_write(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE); nllvdbg("Send of 0x%x Completed\n", usOpcode); return 0; }
void SimpleLinkWaitData(uint8_t *pBuf, uint8_t *from, uint8_t *fromlen) { /* In the blocking implementation the control to caller will be returned only * after the end of current transaction, i.e. only after data will be received */ nllvdbg("Looking for Data\n"); uint16_t event_type; uint16_t opcode = tSLInformation.usRxEventOpcode; do { tSLInformation.pucReceivedData = cc3000_wait(); tSLInformation.usEventOrDataReceived = 1; if (*tSLInformation.pucReceivedData == HCI_TYPE_DATA) { tSLInformation.usRxDataPending = 1; hci_event_handler(pBuf, from, fromlen); break; } else { STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET, event_type); nllvdbg("Evtn:0x%x\n", event_type); if (hci_unsolicited_event_handler() == 1) { nllvdbg("Processed Event 0x%x want Data! Opcode 0x%x\n", event_type, opcode); } else { nllvdbg("!!!!!opcode 0x%x\n", opcode); } UNUSED(event_type); } } while (*tSLInformation.pucReceivedData == HCI_TYPE_EVNT); nllvdbg("Done for Data 0x%x\n", opcode); UNUSED(opcode); }
uint16_t uip_datahandler(FAR struct uip_conn *conn, FAR uint8_t *buffer, uint16_t buflen) { FAR struct uip_readahead_s *readahead1; FAR struct uip_readahead_s *readahead2 = NULL; uint16_t remaining; uint16_t recvlen = 0; /* First, we need to determine if we have space to buffer the data. This * needs to be verified before we actually begin buffering the data. We * will use any remaining space in the last allocated readahead buffer * plus as much one additional buffer. It is expected that the size of * readahead buffers are tuned so that one full packet will always fit * into one readahead buffer (for example if the buffer size is 420, then * a readahead buffer of 366 will hold a full packet of TCP data). */ readahead1 = (FAR struct uip_readahead_s*)conn->readahead.tail; if ((readahead1 && (CONFIG_NET_TCP_READAHEAD_BUFSIZE - readahead1->rh_nbytes) > buflen) || (readahead2 = uip_tcpreadahead_alloc()) != NULL) { /* We have buffer space. Now try to append add as much data as possible * to the last readahead buffer attached to this connection. */ remaining = buflen; if (readahead1) { recvlen = uip_readahead(readahead1, buffer, remaining); if (recvlen > 0) { buffer += recvlen; remaining -= recvlen; } } /* Do we need to buffer into the newly allocated buffer as well? */ if (readahead2) { readahead2->rh_nbytes = 0; recvlen += uip_readahead(readahead2, buffer, remaining); /* Save the readahead buffer in the connection structure where * it can be found with recv() is called. */ sq_addlast(&readahead2->rh_node, &conn->readahead); } } nllvdbg("Buffered %d bytes (of %d)\n", recvlen, buflen); return recvlen; }
static uint32_t arp_send_interrupt(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *priv, uint32_t flags) { FAR struct arp_send_s *state = (FAR struct arp_send_s *)priv; nllvdbg("flags: %04x sent: %d\n", flags, state->snd_sent); if (state) { /* Check if the network is still up */ if ((flags & NETDEV_DOWN) != 0) { nlldbg("ERROR: Interface is down\n"); arp_send_terminate(state, -ENETUNREACH); return flags; } /* Check if the outgoing packet is available. It may have been claimed * by a send interrupt serving a different thread -OR- if the output * buffer currently contains unprocessed incoming data. In these cases * we will just have to wait for the next polling cycle. */ if (dev->d_sndlen > 0 || (flags & PKT_NEWDATA) != 0) { /* Another thread has beat us sending data or the buffer is busy, * Check for a timeout. If not timed out, wait for the next * polling cycle and check again. */ /* REVISIT: No timeout. Just wait for the next polling cycle */ return flags; } /* It looks like we are good to send the data */ /* Copy the packet data into the device packet buffer and send it */ arp_format(dev, state->snd_ipaddr); /* Make sure no ARP request overwrites this ARP request. This * flag will be cleared in arp_out(). */ IFF_SET_NOARP(dev->d_flags); /* Don't allow any further call backs. */ arp_send_terminate(state, OK); } return flags; }
void SpiReceiveHandler(void *pvBuffer) { tSLInformation.pucReceivedData = (uint8_t *)pvBuffer; tSLInformation.usEventOrDataReceived = 1; uint16_t event_type; STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET,event_type); nllvdbg("Evtn:0x%x\n", event_type); hci_unsolicited_event_handler(); }
static void connection_event(struct uip_conn *conn, uint16_t flags) { FAR struct socket *psock = (FAR struct socket *)conn->connection_private; if (psock) { nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags); /* These loss-of-connection events may be reported: * * UIP_CLOSE: The remote host has closed the connection * UIP_ABORT: The remote host has aborted the connection * UIP_TIMEDOUT: Connection aborted due to too many retransmissions. * * And we need to set these two socket status bits appropriately: * * _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected * _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected * _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected */ if ((flags & UIP_CLOSE) != 0) { /* The peer gracefully closed the connection. Marking the * connection as disconnected will suppress some subsequent * ENOTCONN errors from receive. A graceful disconnection is * not handle as an error but as an "end-of-file" */ psock->s_flags &= ~_SF_CONNECTED; psock->s_flags |= _SF_CLOSED; } else if ((flags & (UIP_ABORT|UIP_TIMEDOUT)) != 0) { /* The loss of connection was less than graceful. This will (eventually) * be reported as an ENOTCONN error. */ psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED); } /* UIP_CONNECTED: The socket is successfully connected */ else if ((flags & UIP_CONNECTED) != 0) { /* Indicate that the socket is now connected */ psock->s_flags |= _SF_CONNECTED; psock->s_flags &= ~_SF_CLOSED; } } }
static int telnetd_open(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; FAR struct telnetd_dev_s *priv = inode->i_private; int tmp; int ret; nllvdbg("td_crefs: %d\n", priv->td_crefs); /* O_NONBLOCK is not supported */ if (filep->f_oflags & O_NONBLOCK) { ret = -ENOSYS; goto errout; } /* Get exclusive access to the device structures */ ret = sem_wait(&priv->td_exclsem); if (ret < 0) { ret = -errno; goto errout; } /* Increment the count of references to the device. If this the first * time that the driver has been opened for this device, then initialize * the device. */ tmp = priv->td_crefs + 1; if (tmp > 255) { /* More than 255 opens; uint8_t would overflow to zero */ ret = -EMFILE; goto errout_with_sem; } /* Save the new open count on success */ priv->td_crefs = tmp; ret = OK; errout_with_sem: sem_post(&priv->td_exclsem); errout: return ret; }
FAR struct igmp_group_s *igmp_grpalloc(FAR struct net_driver_s *dev, FAR const in_addr_t *addr) { FAR struct igmp_group_s *group; net_lock_t flags; nllvdbg("addr: %08x dev: %p\n", *addr, dev); if (up_interrupt_context()) { #if CONFIG_PREALLOC_IGMPGROUPS > 0 grplldbg("Use a pre-allocated group entry\n"); group = igmp_grpprealloc(); #else grplldbg("Cannot allocate from interrupt handler\n"); group = NULL; #endif } else { grplldbg("Allocate from the heap\n"); group = igmp_grpheapalloc(); } grplldbg("group: %p\n", group); /* Check if we successfully allocated a group structure */ if (group) { /* Initialize the non-zero elements of the group structure */ net_ipv4addr_copy(group->grpaddr, *addr); sem_init(&group->sem, 0, 0); /* Initialize the group timer (but don't start it yet) */ group->wdog = wd_create(); DEBUGASSERT(group->wdog); /* Interrupts must be disabled in order to modify the group list */ flags = net_lock(); /* Add the group structure to the list in the device structure */ sq_addfirst((FAR sq_entry_t *)group, &dev->grplist); net_unlock(flags); } return group; }
static uint32_t connection_event(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint32_t flags) { FAR struct socket *psock = (FAR struct socket *)pvpriv; if (psock) { nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags); /* TCP_DISCONN_EVENTS: TCP_CLOSE, TCP_ABORT, TCP_TIMEDOUT, or * NETDEV_DOWN. All loss-of-connection events. */ if ((flags & TCP_DISCONN_EVENTS) != 0) { connection_closed(psock, flags); } /* TCP_CONNECTED: The socket is successfully connected */ else if ((flags & TCP_CONNECTED) != 0) { #if 0 /* REVISIT: Assertion fires. Why? */ #ifdef CONFIG_NETDEV_MULTINIC FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)psock->s_conn; /* Make sure that this is the device bound to the connection */ DEBUGASSERT(conn->dev == NULL || conn->dev == dev); conn->dev = dev; #endif #endif /* If there is no local address assigned to the socket (perhaps * because it was INADDR_ANY), then assign it the address of the * connecting device. * * TODO: Implement this. */ /* Indicate that the socket is now connected */ psock->s_flags |= _SF_CONNECTED; psock->s_flags &= ~_SF_CLOSED; } } return flags; }
void uip_udpcallback(struct uip_driver_s *dev, struct uip_udp_conn *conn, uint16_t flags) { nllvdbg("flags: %04x\n", flags); /* Some sanity checking */ if (conn) { /* Perform the callback */ flags = uip_callbackexecute(dev, conn, flags, conn->list); } }
static uint16_t tcp_poll_interrupt(FAR struct net_driver_s *dev, FAR void *conn, FAR void *pvpriv, uint16_t flags) { FAR struct tcp_poll_s *info = (FAR struct tcp_poll_s *)pvpriv; nllvdbg("flags: %04x\n", flags); DEBUGASSERT(!info || (info->psock && info->fds)); /* 'priv' might be null in some race conditions (?) */ if (info) { pollevent_t eventset = 0; /* Check for data or connection availability events. */ if ((flags & (TCP_NEWDATA | TCP_BACKLOG)) != 0) { eventset |= POLLIN & info->fds->events; } /* A poll is a sign that we are free to send data. */ if ((flags & TCP_POLL) != 0) { eventset |= (POLLOUT & info->fds->events); } /* Check for a loss of connection events. */ if ((flags & (TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT)) != 0) { /* Marki that the connection has been lost */ net_lostconnection(info->psock, flags); eventset |= (POLLERR | POLLHUP); } /* Awaken the caller of poll() is requested event occurred. */ if (eventset) { info->fds->revents |= eventset; sem_post(info->fds->sem); } } return flags; }
static uint16_t netclose_interrupt(struct uip_driver_s *dev, void *pvconn, void *pvpriv, uint16_t flags) { struct tcp_close_s *pstate = (struct tcp_close_s *)pvpriv; nllvdbg("flags: %04x\n", flags); if (pstate) { /* UIP_CLOSE: The remote host has closed the connection * UIP_ABORT: The remote host has aborted the connection */ if ((flags & (UIP_CLOSE|UIP_ABORT)) != 0) { /* The disconnection is complete */ pstate->cl_cb->flags = 0; pstate->cl_cb->priv = NULL; pstate->cl_cb->event = NULL; sem_post(&pstate->cl_sem); nllvdbg("Resuming\n"); } else { /* Drop data received in this state and make sure that UIP_CLOSE * is set in the response */ dev->d_len = 0; return (flags & ~UIP_NEWDATA) | UIP_CLOSE; } } return flags; }