Esempio n. 1
0
END_TEST

/** Call tcp_new() and tcp_abort() and test memp stats */
START_TEST(test_tcp_listen_passive_open)
{
  struct tcp_pcb *pcb, *pcbl;
  struct tcp_pcb_listen *lpcb;
  struct netif netif;
  struct test_tcp_txcounters txcounters;
  struct test_tcp_counters counters;
  struct pbuf *p;
  ip_addr_t src_addr;
  err_t err;
  LWIP_UNUSED_ARG(_i);

  fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);

  test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
  /* initialize counter struct */
  memset(&counters, 0, sizeof(counters));

  pcb = tcp_new();
  EXPECT_RET(pcb != NULL);
  err = tcp_bind(pcb, &netif.ip_addr, 1234);
  EXPECT(err == ERR_OK);
  pcbl = tcp_listen(pcb);
  EXPECT_RET(pcbl != NULL);
  EXPECT_RET(pcbl != pcb);
  lpcb = (struct tcp_pcb_listen *)pcbl;

  ip_addr_set_ip4_u32_val(src_addr, lwip_htonl(lwip_ntohl(ip_addr_get_ip4_u32(&lpcb->local_ip)) + 1));

  /* check correct syn packet */
  p = tcp_create_segment(&src_addr, &lpcb->local_ip, 12345,
    lpcb->local_port, NULL, 0, 12345, 54321, TCP_SYN);
  EXPECT(p != NULL);
  if (p != NULL) {
    /* pass the segment to tcp_input */
    test_tcp_input(p, &netif);
    /* check if counters are as expected */
    EXPECT(txcounters.num_tx_calls == 1);
  }

  /* check syn packet with short length */
  p = tcp_create_segment(&src_addr, &lpcb->local_ip, 12345,
    lpcb->local_port, NULL, 0, 12345, 54321, TCP_SYN);
  EXPECT(p != NULL);
  EXPECT(p->next == NULL);
  if ((p != NULL) && (p->next == NULL)) {
    p->len -= 2;
    p->tot_len -= 2;
    /* pass the segment to tcp_input */
    test_tcp_input(p, &netif);
    /* check if counters are as expected */
    EXPECT(txcounters.num_tx_calls == 1);
  }

  tcp_close(pcbl);
}
Esempio n. 2
0
/**
 * Initialize request struct to be sent to server.
 */
static void
sntp_initialize_request(struct sntp_msg *req)
{
  memset(req, 0, SNTP_MSG_LEN);
  req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;

#if SNTP_CHECK_RESPONSE >= 2
  {
    u32_t sntp_time_sec, sntp_time_us;
    /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */
    SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us);
    sntp_last_timestamp_sent[0] = lwip_htonl(sntp_time_sec + DIFF_SEC_1900_1970);
    req->transmit_timestamp[0] = sntp_last_timestamp_sent[0];
    /* we send/save us instead of fraction to be faster... */
    sntp_last_timestamp_sent[1] = lwip_htonl(sntp_time_us);
    req->transmit_timestamp[1] = sntp_last_timestamp_sent[1];
  }
#endif /* SNTP_CHECK_RESPONSE >= 2 */
}
Esempio n. 3
0
/**
 * @ingroup netif_ip6
 * Create a link-local IPv6 address on a netif (stored in slot 0)
 *
 * @param netif the netif to create the address on
 * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion)
 *                       if == 0, use hwaddr directly as interface ID
 */
void
netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
{
  u8_t i, addr_index;

  /* Link-local prefix. */
  ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul);
  ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0;

  /* Generate interface ID. */
  if (from_mac_48bit) {
    /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
    ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
        ((u32_t)(netif->hwaddr[1]) << 16) |
        ((u32_t)(netif->hwaddr[2]) << 8) |
        (0xff));
    ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) |
        ((u32_t)(netif->hwaddr[3]) << 16) |
        ((u32_t)(netif->hwaddr[4]) << 8) |
        (netif->hwaddr[5]));
  } else {
    /* Use hwaddr directly as interface ID. */
    ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0;
    ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0;

    addr_index = 3;
    for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) {
      if (i == 4) {
        addr_index--;
      }
      ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03));
    }
  }

  /* Set address state. */
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
  /* Will perform duplicate address detection (DAD). */
  netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE;
#else
  /* Consider address valid. */
  netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED;
#endif /* LWIP_IPV6_AUTOCONFIG */
}
Esempio n. 4
0
static void frame_client_create_net_data(struct msfd_report_collection_data_sn_st *data)
{
	int i;
	
	for (i=0; i<sizeof(data->coll_data.pt_ct_app_p)/sizeof(data->coll_data.pt_ct_app_p[0]); i++) {
		data->coll_data.pt_ct_app_p[i] = lwip_htonl(data->coll_data.pt_ct_app_p[i]);
	}

	for (i=0; i<sizeof(data->coll_data.pt_ct_ap_p)/sizeof(data->coll_data.pt_ct_ap_p[0]); i++) {
		data->coll_data.pt_ct_ap_p[i] = lwip_htonl(data->coll_data.pt_ct_ap_p[i]);
	}

	for (i=0; i<sizeof(data->coll_data.pt_ct_v)/sizeof(data->coll_data.pt_ct_v[0]); i++) {
		data->coll_data.pt_ct_v[i] = lwip_htonl(data->coll_data.pt_ct_v[i]);
	}

	for (i=0; i<sizeof(data->coll_data.pt_ct_i)/sizeof(data->coll_data.pt_ct_i[0]); i++) {
		data->coll_data.pt_ct_i[i] = lwip_htonl(data->coll_data.pt_ct_i[i]);
	}

	data->last_update_time = lwip_htonl(data->last_update_time);
}
Esempio n. 5
0
/* Send 6LoWPAN TX packets as UDP broadcast */
static err_t
zepif_linkoutput(struct netif *netif, struct pbuf *p)
{
  err_t err;
  struct pbuf *q;
  struct zep_hdr *zep;
  struct zepif_state *state;

  LWIP_ASSERT("invalid netif", netif != NULL);
  LWIP_ASSERT("invalid pbuf", p != NULL);

  if (p->tot_len > ZEP_MAX_DATA_LEN) {
    return ERR_VAL;
  }
  LWIP_ASSERT("TODO: support chained pbufs", p->next == NULL);

  state = (struct zepif_state *)netif->state;
  LWIP_ASSERT("state->pcb != NULL", state->pcb != NULL);

  q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct zep_hdr) + p->tot_len, PBUF_RAM);
  if (q == NULL) {
    return ERR_MEM;
  }
  zep = (struct zep_hdr *)q->payload;
  memset(zep, 0, sizeof(struct zep_hdr));
  zep->prot_id[0] = 'E';
  zep->prot_id[1] = 'X';
  zep->prot_version = 2;
  zep->type = 1; /* Data */
  zep->channel_id = 0; /* whatever */
  zep->device_id = lwip_htons(1); /* whatever */
  zep->crc_mode = 1;
  zep->unknown_1 = 0xff;
  zep->seq_num = lwip_htonl(state->seqno);
  state->seqno++;
  zep->len = (u8_t)p->tot_len;

  err = pbuf_take_at(q, p->payload, p->tot_len, sizeof(struct zep_hdr));
  if (err == ERR_OK) {
#if ZEPIF_LOOPBACK
    zepif_udp_recv(netif, state->pcb, pbuf_clone(PBUF_RAW, PBUF_RAM, q), NULL, 0);
#endif
    err = udp_sendto(state->pcb, q, state->init.zep_dst_ip_addr, state->init.zep_dst_udp_port);
  }
  pbuf_free(q);

  return err;
}
Esempio n. 6
0
/** Start TCP connection back to the client (either parallel or after the
 * receive test has finished.
 */
static err_t
lwiperf_tx_start(lwiperf_state_tcp_t* conn)
{
  err_t err;
  lwiperf_state_tcp_t* client_conn;
  struct tcp_pcb* newpcb;
  ip_addr_t remote_addr;
  u16_t remote_port;

  client_conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t);
  if (client_conn == NULL) {
    return ERR_MEM;
  }
  newpcb = tcp_new();
  if (newpcb == NULL) {
    LWIPERF_FREE(lwiperf_state_tcp_t, client_conn);
    return ERR_MEM;
  }

  MEMCPY(client_conn, conn, sizeof(lwiperf_state_tcp_t));
  client_conn->base.server = 0;
  client_conn->server_pcb = NULL;
  client_conn->conn_pcb = newpcb;
  client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */
  client_conn->poll_count = 0;
  client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */
  client_conn->bytes_transferred = 0;
  client_conn->settings.flags = 0; /* prevent the remote side starting back as client again */

  tcp_arg(newpcb, client_conn);
  tcp_sent(newpcb, lwiperf_tcp_client_sent);
  tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
  tcp_err(newpcb, lwiperf_tcp_err);

  ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip);
  remote_port = (u16_t)lwip_htonl(client_conn->settings.remote_port);

  err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected);
  if (err != ERR_OK) {
    lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL);
    return err;
  }
  lwiperf_list_add(&client_conn->base);
  return ERR_OK;
}
Esempio n. 7
0
/** Checks if a netmask is valid (starting with ones, then only zeros)
 *
 * @param netmask the IPv4 netmask to check (in network byte order!)
 * @return 1 if the netmask is valid, 0 if it is not
 */
uint8_t ip4_addr_netmask_valid(uint32_t netmask)
{
	uint32_t mask;
	uint32_t nm_hostorder = lwip_htonl(netmask);

	/* first, check for the first zero */
	for (mask = 1UL << 31; mask != 0; mask >>= 1) {
		if ((nm_hostorder & mask) == 0) {
			break;
		}
	}
	/* then check that there is no one */
	for (; mask != 0; mask >>= 1) {
		if ((nm_hostorder & mask) != 0) {
			/* there is a one after the first zero -> invalid */
			return 0;
		}
	}
	/* no one after the first zero -> valid */
	return 1;
}
Esempio n. 8
0
/**
 * RTP send packets
 */
static void
rtp_send_packets( int sock, struct sockaddr_in* to)
{
  struct rtp_hdr* rtphdr;
  u8_t*           rtp_payload;
  int             rtp_payload_size;
  size_t          rtp_data_index;

  /* prepare RTP packet */
  rtphdr = (struct rtp_hdr*)rtp_send_packet;
  rtphdr->version     = RTP_VERSION;
  rtphdr->payloadtype = 0;
  rtphdr->ssrc        = PP_HTONL(RTP_SSRC);
  rtphdr->timestamp   = lwip_htonl(lwip_ntohl(rtphdr->timestamp) + RTP_TIMESTAMP_INCREMENT);

  /* send RTP stream packets */
  rtp_data_index = 0;
  do {
    rtp_payload      = rtp_send_packet+sizeof(struct rtp_hdr);
    rtp_payload_size = LWIP_MIN(RTP_PAYLOAD_SIZE, (sizeof(rtp_data) - rtp_data_index));

    MEMCPY(rtp_payload, rtp_data + rtp_data_index, rtp_payload_size);

    /* set MARKER bit in RTP header on the last packet of an image */
    rtphdr->payloadtype = RTP_PAYLOADTYPE | (((rtp_data_index + rtp_payload_size)
      >= sizeof(rtp_data)) ? RTP_MARKER_MASK : 0);

    /* send RTP stream packet */
    if (sendto(sock, rtp_send_packet, sizeof(struct rtp_hdr) + rtp_payload_size,
        0, (struct sockaddr *)to, sizeof(struct sockaddr)) >= 0) {
      rtphdr->seqNum  = lwip_htons(lwip_ntohs(rtphdr->seqNum) + 1);
      rtp_data_index += rtp_payload_size;
    } else {
      LWIP_DEBUGF(RTP_DEBUG, ("rtp_sender: not sendto==%i\n", errno));
    }
  }while (rtp_data_index < sizeof(rtp_data));
}
Esempio n. 9
0
/**
 * Check whether "cp" is a valid ascii representation
 * of an IPv6 address and convert to a binary address.
 * Returns 1 if the address is valid, 0 if not.
 *
 * @param cp IPv6 address in ascii representation (e.g. "FF01::1")
 * @param addr pointer to which to save the ip address in network order
 * @return 1 if cp could be converted to addr, 0 on failure
 */
int
ip6addr_aton(const char *cp, ip6_addr_t *addr)
{
  u32_t addr_index, zero_blocks, current_block_index, current_block_value;
  const char *s;
#if LWIP_IPV4
  int check_ipv4_mapped = 0;
#endif /* LWIP_IPV4 */

  /* Count the number of colons, to count the number of blocks in a "::" sequence
     zero_blocks may be 1 even if there are no :: sequences */
  zero_blocks = 8;
  for (s = cp; *s != 0; s++) {
    if (*s == ':') {
      zero_blocks--;
#if LWIP_IPV4
    } else if (*s == '.') {
      if ((zero_blocks == 5) ||(zero_blocks == 2)) {
        check_ipv4_mapped = 1;
        /* last block could be the start of an IPv4 address */
        zero_blocks--;
      } else {
        /* invalid format */
        return 0;
      }
      break;
#endif /* LWIP_IPV4 */
    } else if (!lwip_isxdigit(*s)) {
      break;
    }
  }

  /* parse each block */
  addr_index = 0;
  current_block_index = 0;
  current_block_value = 0;
  for (s = cp; *s != 0; s++) {
    if (*s == ':') {
      if (addr) {
        if (current_block_index & 0x1) {
          addr->addr[addr_index++] |= current_block_value;
        }
        else {
          addr->addr[addr_index] = current_block_value << 16;
        }
      }
      current_block_index++;
#if LWIP_IPV4
      if (check_ipv4_mapped) {
        if (current_block_index == 6) {
          ip4_addr_t ip4;
          int ret = ip4addr_aton(s + 1, &ip4);
          if (ret) {
            if (addr) {
              addr->addr[3] = lwip_htonl(ip4.addr);
              current_block_index++;
              goto fix_byte_order_and_return;
            }
            return 1;
          }
        }
      }
#endif /* LWIP_IPV4 */
      current_block_value = 0;
      if (current_block_index > 7) {
        /* address too long! */
        return 0;
      }
      if (s[1] == ':') {
        if (s[2] == ':') {
          /* invalid format: three successive colons */
          return 0;
        }
        s++;
        /* "::" found, set zeros */
        while (zero_blocks > 0) {
          zero_blocks--;
          if (current_block_index & 0x1) {
            addr_index++;
          } else {
            if (addr) {
              addr->addr[addr_index] = 0;
            }
          }
          current_block_index++;
          if (current_block_index > 7) {
            /* address too long! */
            return 0;
          }
        }
      }
    } else if (lwip_isxdigit(*s)) {
      /* add current digit */
      current_block_value = (current_block_value << 4) +
          (lwip_isdigit(*s) ? (u32_t)(*s - '0') :
          (u32_t)(10 + (lwip_islower(*s) ? *s - 'a' : *s - 'A')));
    } else {
      /* unexpected digit, space? CRLF? */
      break;
    }
  }

  if (addr) {
    if (current_block_index & 0x1) {
      addr->addr[addr_index++] |= current_block_value;
    }
    else {
      addr->addr[addr_index] = current_block_value << 16;
    }
#if LWIP_IPV4
fix_byte_order_and_return:
#endif
    /* convert to network byte order. */
    for (addr_index = 0; addr_index < 4; addr_index++) {
      addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]);
    }

    ip6_addr_clear_zone(addr);
  }

  if (current_block_index != 7) {
    return 0;
  }

  return 1;
}
Esempio n. 10
0
/**
 * Fragment an IPv6 datagram if too large for the netif or path MTU.
 *
 * Chop the datagram in MTU sized chunks and send them in order
 * by pointing PBUF_REFs into p
 *
 * @param p ipv6 packet to send
 * @param netif the netif on which to send
 * @param dest destination ipv6 address to which to send
 *
 * @return ERR_OK if sent successfully, err_t otherwise
 */
err_t
ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest)
{
  struct ip6_hdr *original_ip6hdr;
  struct ip6_hdr *ip6hdr;
  struct ip6_frag_hdr *frag_hdr;
  struct pbuf *rambuf;
#if !LWIP_NETIF_TX_SINGLE_PBUF
  struct pbuf *newpbuf;
  u16_t newpbuflen = 0;
  u16_t left_to_copy;
#endif
  static u32_t identification;
  u16_t nfb;
  u16_t left, cop;
  u16_t mtu;
  u16_t fragment_offset = 0;
  u16_t last;
  u16_t poff = IP6_HLEN;

  identification++;

  original_ip6hdr = (struct ip6_hdr *)p->payload;

  mtu = nd6_get_destination_mtu(dest, netif);

  /* @todo we assume there are no options in the unfragmentable part (IPv6 header). */
  left = p->tot_len - IP6_HLEN;

  nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK;

  while (left) {
    last = (left <= nfb);

    /* Fill this fragment */
    cop = last ? left : nfb;

#if LWIP_NETIF_TX_SINGLE_PBUF
    rambuf = pbuf_alloc(PBUF_IP, cop + IP6_FRAG_HLEN, PBUF_RAM);
    if (rambuf == NULL) {
      IP6_FRAG_STATS_INC(ip6_frag.memerr);
      return ERR_MEM;
    }
    LWIP_ASSERT("this needs a pbuf in one piece!",
      (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
    poff += pbuf_copy_partial(p, (u8_t*)rambuf->payload + IP6_FRAG_HLEN, cop, poff);
    /* make room for the IP header */
    if (pbuf_header(rambuf, IP6_HLEN)) {
      pbuf_free(rambuf);
      IP6_FRAG_STATS_INC(ip6_frag.memerr);
      return ERR_MEM;
    }
    /* fill in the IP header */
    SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN);
    ip6hdr = (struct ip6_hdr *)rambuf->payload;
    frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN);
#else
    /* When not using a static buffer, create a chain of pbufs.
     * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header.
     * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
     * but limited to the size of an mtu.
     */
    rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM);
    if (rambuf == NULL) {
      IP6_FRAG_STATS_INC(ip6_frag.memerr);
      return ERR_MEM;
    }
    LWIP_ASSERT("this needs a pbuf in one piece!",
                (p->len >= (IP6_HLEN)));
    SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN);
    ip6hdr = (struct ip6_hdr *)rambuf->payload;
    frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN);

    /* Can just adjust p directly for needed offset. */
    p->payload = (u8_t *)p->payload + poff;
    p->len -= poff;
    p->tot_len -= poff;

    left_to_copy = cop;
    while (left_to_copy) {
      struct pbuf_custom_ref *pcr;
      newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
      /* Is this pbuf already empty? */
      if (!newpbuflen) {
        p = p->next;
        continue;
      }
      pcr = ip6_frag_alloc_pbuf_custom_ref();
      if (pcr == NULL) {
        pbuf_free(rambuf);
        IP6_FRAG_STATS_INC(ip6_frag.memerr);
        return ERR_MEM;
      }
      /* Mirror this pbuf, although we might not need all of it. */
      newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen);
      if (newpbuf == NULL) {
        ip6_frag_free_pbuf_custom_ref(pcr);
        pbuf_free(rambuf);
        IP6_FRAG_STATS_INC(ip6_frag.memerr);
        return ERR_MEM;
      }
      pbuf_ref(p);
      pcr->original = p;
      pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom;

      /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
       * so that it is removed when pbuf_dechain is later called on rambuf.
       */
      pbuf_cat(rambuf, newpbuf);
      left_to_copy -= newpbuflen;
      if (left_to_copy) {
        p = p->next;
      }
    }
    poff = newpbuflen;
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */

    /* Set headers */
    frag_hdr->_nexth = original_ip6hdr->_nexth;
    frag_hdr->reserved = 0;
    frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG));
    frag_hdr->_identification = lwip_htonl(identification);

    IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
    IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN);

    /* No need for separate header pbuf - we allowed room for it in rambuf
     * when allocated.
     */
    IP6_FRAG_STATS_INC(ip6_frag.xmit);
    netif->output_ip6(netif, rambuf, dest);

    /* Unfortunately we can't reuse rambuf - the hardware may still be
     * using the buffer. Instead we free it (and the ensuing chain) and
     * recreate it next time round the loop. If we're lucky the hardware
     * will have already sent the packet, the free will really free, and
     * there will be zero memory penalty.
     */

    pbuf_free(rambuf);
    left -= cop;
    fragment_offset += cop;
  }
  return ERR_OK;
}
Esempio n. 11
0
/** Try to send more data on an iperf tcp session */
static err_t
lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn)
{
  int send_more;
  err_t err;
  u16_t txlen;
  u16_t txlen_max;
  void* txptr;
  u8_t apiflags;

  LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0));

  do {
    send_more = 0;
    if (conn->settings.amount & PP_HTONL(0x80000000)) {
      /* this session is time-limited */
      u32_t now = sys_now();
      u32_t diff_ms = now - conn->time_started;
      u32_t time = (u32_t)-(s32_t)lwip_htonl(conn->settings.amount);
      u32_t time_ms = time * 10;
      if (diff_ms >= time_ms) {
        /* time specified by the client is over -> close the connection */
        lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
        return ERR_OK;
      }
    } else {
      /* this session is byte-limited */
      u32_t amount_bytes = lwip_htonl(conn->settings.amount);
      /* @todo: this can send up to 1*MSS more than requested... */
      if (amount_bytes >= conn->bytes_transferred) {
        /* all requested bytes transferred -> close the connection */
        lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
        return ERR_OK;
      }
    }

    if (conn->bytes_transferred < 24) {
      /* transmit the settings a first time */
      txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred];
      txlen_max = (u16_t)(24 - conn->bytes_transferred);
      apiflags = TCP_WRITE_FLAG_COPY;
    } else if (conn->bytes_transferred < 48) {
      /* transmit the settings a second time */
      txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24];
      txlen_max = (u16_t)(48 - conn->bytes_transferred);
      apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE;
      send_more = 1;
    } else {
      /* transmit data */
      /* @todo: every x bytes, transmit the settings again */
      txptr = (void*)(size_t)&lwiperf_txbuf_const[conn->bytes_transferred % 10];
      txlen_max = TCP_MSS;
      if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
        txlen_max = TCP_MSS - 24;
      }
      apiflags = 0; /* no copying needed */
      send_more = 1;
    }
    txlen = txlen_max;
    do {
      err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags);
      if (err ==  ERR_MEM) {
        txlen /= 2;
      }
    } while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2)));

    if (err == ERR_OK) {
      conn->bytes_transferred += txlen;
    } else {
      send_more = 0;
    }
  } while(send_more);

  tcp_output(conn->conn_pcb);
  return ERR_OK;
}
Esempio n. 12
0
/**
 * Check whether "cp" is a valid ascii representation
 * of an Internet address and convert to a binary address.
 * Returns 1 if the address is valid, 0 if not.
 * This replaces inet_addr, the return value from which
 * cannot distinguish between failure and a local broadcast address.
 *
 * @param cp IP address in ascii representation (e.g. "127.0.0.1")
 * @param addr pointer to which to save the ip address in network order
 * @return 1 if cp could be converted to addr, 0 on failure
 */
int
ip4addr_aton(const char *cp, ip4_addr_t *addr)
{
  u32_t val;
  u8_t base;
  char c;
  u32_t parts[4];
  u32_t *pp = parts;

  c = *cp;
  for (;;) {
    /*
     * Collect number up to ``.''.
     * Values are specified as for C:
     * 0x=hex, 0=octal, 1-9=decimal.
     */
    if (!isdigit(c)) {
      return 0;
    }
    val = 0;
    base = 10;
    if (c == '0') {
      c = *++cp;
      if (c == 'x' || c == 'X') {
        base = 16;
        c = *++cp;
      } else {
        base = 8;
      }
    }
    for (;;) {
      if (isdigit(c)) {
        val = (val * base) + (u32_t)(c - '0');
        c = *++cp;
      } else if (base == 16 && isxdigit(c)) {
        val = (val << 4) | (u32_t)(c + 10 - (islower(c) ? 'a' : 'A'));
        c = *++cp;
      } else {
        break;
      }
    }
    if (c == '.') {
      /*
       * Internet format:
       *  a.b.c.d
       *  a.b.c   (with c treated as 16 bits)
       *  a.b (with b treated as 24 bits)
       */
      if (pp >= parts + 3) {
        return 0;
      }
      *pp++ = val;
      c = *++cp;
    } else {
      break;
    }
  }
  /*
   * Check for trailing characters.
   */
  if (c != '\0' && !isspace(c)) {
    return 0;
  }
  /*
   * Concoct the address according to
   * the number of parts specified.
   */
  switch (pp - parts + 1) {

  case 0:
    return 0;       /* initial nondigit */

  case 1:             /* a -- 32 bits */
    break;

  case 2:             /* a.b -- 8.24 bits */
    if (val > 0xffffffUL) {
      return 0;
    }
    if (parts[0] > 0xff) {
      return 0;
    }
    val |= parts[0] << 24;
    break;

  case 3:             /* a.b.c -- 8.8.16 bits */
    if (val > 0xffff) {
      return 0;
    }
    if ((parts[0] > 0xff) || (parts[1] > 0xff)) {
      return 0;
    }
    val |= (parts[0] << 24) | (parts[1] << 16);
    break;

  case 4:             /* a.b.c.d -- 8.8.8.8 bits */
    if (val > 0xff) {
      return 0;
    }
    if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) {
      return 0;
    }
    val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
    break;
  default:
    LWIP_ASSERT("unhandled", 0);
    break;
  }
  if (addr) {
    ip4_addr_set_u32(addr, lwip_htonl(val));
  }
  return 1;
}
Esempio n. 13
0
void
cliSetVar(const clivalue_t *var, const char *str) {
    uint32_t val = 0;
    uint8_t val2 = 0;
    switch (var->type) {
    case VAR_UINT32:
        *(uint32_t*)var->ptr = atoi_decimal(str);
        break;
    case VAR_UINT16:
        *(uint16_t*)var->ptr = atoi_decimal(str);
        break;
#if CLI_TYPE_IP4
    case VAR_IP4:
        while (*str) {
            if (*str == '.') {
                val = (val << 8) | val2;
                val2 = 0;
            } else if (*str >= '0' && *str <= '9') {
                val2 = val2 * 10 + (*str - '0');
            }
            str++;
        }
        val = (val << 8) | val2;
        *(uint32_t*)var->ptr = lwip_htonl(val);
        break;
#endif
#if CLI_TYPE_IP6
    case VAR_IP6:
        {
            uint32_t *packed = (uint32_t*)var->ptr;
            uint8_t i;
            uint16_t words[8];
            for (i = 0; i < 8; i++) {
                words[i] = 0;
            }
            i = 0;
            while (*str) {
                if (*str == ':') {
                    if (++i == 8) {
                        break;
                    }
                } else {
                    words[i] = (words[i] << 4) | parse_hex(*str);
                }
                str++;
            }
            packed[0] = htonl(words[1] | ((uint32_t)words[0] << 16));
            packed[1] = htonl(words[3] | ((uint32_t)words[2] << 16));
            packed[2] = htonl(words[5] | ((uint32_t)words[4] << 16));
            packed[3] = htonl(words[7] | ((uint32_t)words[6] << 16));
            break;
        }
#endif
#if CLI_TYPE_HEX
    case VAR_HEX:
        {
            uint8_t *ptr = (uint8_t*)var->ptr;
            int i;
            for (i = 0; i < var->len; i++) {
                val2 = *str++;
                if (val2 == 0) {
                    break;
                } else {
                    val = parse_hex(val2) << 4;
                }
                val2 = *str++;
                if (val2 == 0) {
                    break;
                } else {
                    val |= parse_hex(val2);
                }
                *ptr++ = val;
            }
            /* Pad the remainder with zeroes */
            for (; i < var->len; i++) {
                *ptr++ = 0;
            }
            break;
        }
#endif
#if CLI_TYPE_FLAG
    case VAR_FLAG:
        if (*str == 't' || *str == 'y'
                || (*str == 'o' && *(str+1) == 'n')) {
            *(uint32_t*)var->ptr |= var->len;
        } else if (*str == 'f' || *str == 'n'
                || (*str == 'o' && *(str+1) == 'f')) {
            *(uint32_t*)var->ptr &= ~(var->len);
        }
        break;
#endif
    case VAR_INVALID:
        break;
    }
}
Esempio n. 14
0
/**
 * Check whether "cp" is a valid ascii representation
 * of an IPv6 address and convert to a binary address.
 * Returns 1 if the address is valid, 0 if not.
 *
 * @param cp IPv6 address in ascii representation (e.g. "FF01::1")
 * @param addr pointer to which to save the ip address in network order
 * @return 1 if cp could be converted to addr, 0 on failure
 */
int
ip6addr_aton(const char *cp, ip6_addr_t *addr)
{
  u32_t addr_index, zero_blocks, current_block_index, current_block_value;
  const char *s;

  /* Count the number of colons, to count the number of blocks in a "::" sequence
     zero_blocks may be 1 even if there are no :: sequences */
  zero_blocks = 8;
  for (s = cp; *s != 0; s++) {
    if (*s == ':') {
      zero_blocks--;
    } else if (!isxdigit(*s)) {
      break;
    }
  }

  /* parse each block */
  addr_index = 0;
  current_block_index = 0;
  current_block_value = 0;
  for (s = cp; *s != 0; s++) {
    if (*s == ':') {
      if (addr) {
        if (current_block_index & 0x1) {
          addr->addr[addr_index++] |= current_block_value;
        }
        else {
          addr->addr[addr_index] = current_block_value << 16;
        }
      }
      current_block_index++;
      current_block_value = 0;
      if (current_block_index > 7) {
        /* address too long! */
        return 0;
      }
      if (s[1] == ':') {
        if (s[2] == ':') {
          /* invalid format: three successive colons */
          return 0;
        }
        s++;
        /* "::" found, set zeros */
        while (zero_blocks > 0) {
          zero_blocks--;
          if (current_block_index & 0x1) {
            addr_index++;
          } else {
            if (addr) {
              addr->addr[addr_index] = 0;
            }
          }
          current_block_index++;
          if (current_block_index > 7) {
            /* address too long! */
            return 0;
          }
        }
      }
    } else if (isxdigit(*s)) {
      /* add current digit */
      current_block_value = (current_block_value << 4) +
          (isdigit(*s) ? (u32_t)(*s - '0') :
          (u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A')));
    } else {
      /* unexpected digit, space? CRLF? */
      break;
    }
  }

  if (addr) {
    if (current_block_index & 0x1) {
      addr->addr[addr_index++] |= current_block_value;
    }
    else {
      addr->addr[addr_index] = current_block_value << 16;
    }
  }

  /* convert to network byte order. */
  if (addr) {
    for (addr_index = 0; addr_index < 4; addr_index++) {
      addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]);
    }
  }

  if (current_block_index != 7) {
    return 0;
  }

  return 1;
}
Esempio n. 15
0
/*
 * 获取除了"区分三相的数据"以及"波形采用数据"以外的其他数据
 *
 * 当返回值为SIE_OK时,非空指针指向的变量存储了返回值
 */
enum sinkinfo_error_e get_sinkinfo_other_param(int em_no, enum sinkinfo_cmd_e cmd, u32_t *pinfo)
{
	enum sinkinfo_error_e ret = SIE_OK;
	int temp;

	if (NULL==pinfo)
		return SIE_NULL_PTR;

	ret = rt_sem_take(&sinkinfo_sem, RT_WAITING_FOREVER);
	if (RT_EOK != ret) {
		printf_syn("take sinkinfo_sem fail(%d)\n", ret);
		return SIE_FAIL;
	}

	switch (cmd) {
	case SIC_GET_EM_ACT_ELECTRIC_ENERGY:
		if(sinkinfo_all_em[em_no].em_dev_info.em_act_total_energy == INVLIDE_DATAL){
			*pinfo = lwip_htonl(sinkinfo_all_em[em_no].em_dev_info.em_act_total_energy);
		}else{
			*pinfo = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].em_dev_info.em_act_total_energy));
		}
		break;

	case SIC_GET_DEV_ACT_ELECTRIC_ENERGY:
		*pinfo = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].em_dev_info.em_act_total_energy)); //sinkinfo.emc_dev_info.dev_act_electric_energy;
		break;

	case SIC_GET_EM_REACT_ELECTRIC_ENERGY:
		if(sinkinfo_all_em[em_no].em_dev_info.em_react_total_energy == INVLIDE_DATAL){
			*pinfo = lwip_htonl(sinkinfo_all_em[em_no].em_dev_info.em_react_total_energy);
		}else{
			*pinfo = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].em_dev_info.em_react_total_energy));
		}
		break;

	case SIC_GET_DEV_REACT_ELECTRIC_ENERGY:
		*pinfo = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].em_dev_info.em_react_total_energy)); //sinkinfo.emc_dev_info.dev_react_electric_energy;
		break;

	case SIC_GET_ACT_INACCURACY:
		if(sinkinfo_all_em[em_no].em_dev_info.em_act_ee_inaccuracy == INVLIDE_DATAL){
			temp = sinkinfo_all_em[em_no].em_dev_info.em_act_ee_inaccuracy;
		}else{
			temp = conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].em_dev_info.em_act_ee_inaccuracy);
		}
		*pinfo = lwip_htonl(temp);
		break;
		
	case SIC_GET_REACT_INACCURACY:
		if(sinkinfo_all_em[em_no].em_dev_info.em_react_ee_inaccuracy == INVLIDE_DATAL){
			temp = sinkinfo_all_em[em_no].em_dev_info.em_react_ee_inaccuracy;
		}else{
			temp = conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].em_dev_info.em_react_ee_inaccuracy);
		}
		*pinfo = lwip_htonl(temp);
		break;
		
	case SIC_GET_EM_METER_TEMPERATURE:
		if(sinkinfo_all_em[em_no].em_dev_info.em_temper == INVLIDE_DATAS){
			temp = sinkinfo_all_em[em_no].em_dev_info.em_temper;
		}else{
			temp = conv_4byte_bcd_to_long((unsigned long)sinkinfo_all_em[em_no].em_dev_info.em_temper);

		}
		*pinfo = lwip_htonl(temp);
		break;
		
	case SIC_GET_EM_CLOCK_BATTERY_VOL:
		if(sinkinfo_all_em[em_no].em_dev_info.em_v_clock == INVLIDE_DATAL){
			temp = sinkinfo_all_em[em_no].em_dev_info.em_v_clock;

		}else{
			temp = conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].em_dev_info.em_v_clock);
		}
		*pinfo = lwip_htonl(temp);
		break;
		
	case SIC_GET_EM_METER_COLLECT_BATTERY_VOL:
		if(sinkinfo_all_em[em_no].em_dev_info.em_v_read_em == INVLIDE_DATAL){
			temp = sinkinfo_all_em[em_no].em_dev_info.em_v_read_em;

		}else{
			temp = conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].em_dev_info.em_v_read_em);
		}
		*pinfo = lwip_htonl(temp);
		break;

	case SIC_GET_PT_TEMP:
		temp = sinkinfo_all_em[em_no].pttmp;
		*pinfo = lwip_htonl(temp);
		break;
	
	case SIC_GET_CT_TEMP:
		temp = sinkinfo_all_em[em_no].cttmp;
		*pinfo = lwip_htonl(temp);
		break;

#if 0
	case SIC_GET_EM_MONTH_ELECTRIC_ENERGY:
		break;

	case SIC_GET_DEV_MONTH_ELECTRIC_ENERGY:
		break;

	case SIC_GET_MONTH_INACCURACY:
		break;
#endif
	default:
		ret = SIE_INVALID_CMD;
		break;
	}

	rt_sem_release(&sinkinfo_sem);

	return ret;
}
Esempio n. 16
0
/*
 * 获取"区分三相的数据",但不包括"波形采用数据"(波形数据有专用接口函数)
 *
 * 当返回值为SIE_OK时,非空指针指向的变量存储了返回值,不需要获取的使用NULL
 * 例如,获取A相电压的调用形式为:get_sinkinfo_abc_param(SIC_GET_VOLTAGE, &a, NULL, NULL)
 */
enum sinkinfo_error_e get_sinkinfo_abc_param(int em_no, int ptct_no,enum sinkinfo_cmd_e cmd, u32_t *pa, u32_t *pb, u32_t *pc)
{
	enum sinkinfo_error_e ret = SIE_OK;

	if (NULL==pa && NULL==pb && NULL==pc)
		return SIE_NULL_PTR;

	ret = rt_sem_take(&sinkinfo_sem, RT_WAITING_FOREVER);
	if (RT_EOK != ret) {
		printf_syn("take sinkinfo_sem fail(%d)\n", ret);
		return SIE_FAIL;
	}

	switch (cmd) {
	case SIC_GET_VOLTAGE:
		if (NULL != pa)
			*pa = sinkinfo_all_em[em_no].si_emc_ind_pa.vx;
		
		if (NULL != pb)
			*pb = sinkinfo_all_em[em_no].si_emc_ind_pb.vx;

		if (NULL != pc)
			*pc = sinkinfo_all_em[em_no].si_emc_ind_pc.vx;
		break;

	case SIC_GET_CURRENT:
		if (NULL != pa)
			*pa = sinkinfo_all_em[em_no].si_emc_ind_pa.ix;

		if (NULL != pb)
			*pb = sinkinfo_all_em[em_no].si_emc_ind_pb.ix;

		if (NULL != pc)
			*pc = sinkinfo_all_em[em_no].si_emc_ind_pc.ix;
		break;

	case SIC_GET_FREQUENCY:
		if (NULL != pa)
			*pa = sinkinfo_all_em[em_no].si_emc_ind_pa.hzx;

		if (NULL != pb)
			*pb = sinkinfo_all_em[em_no].si_emc_ind_pb.hzx;

		if (NULL != pc)
			*pc = sinkinfo_all_em[em_no].si_emc_ind_pc.hzx;
		break;

	case SIC_GET_PHASE:
		if (NULL != pa)
			*pa = sinkinfo_all_em[em_no].si_emc_ind_pa.phx;

		if (NULL != pb)
			*pb = sinkinfo_all_em[em_no].si_emc_ind_pb.phx;

		if (NULL != pc)
			*pc = sinkinfo_all_em[em_no].si_emc_ind_pc.phx;
		break;

	case SIC_GET_ACTIVE_POWER:
		if (NULL != pa)
			*pa = sinkinfo_all_em[em_no].si_emc_ind_pa.apx;

		if (NULL != pb)
			*pb = sinkinfo_all_em[em_no].si_emc_ind_pb.apx;

		if (NULL != pc)
			*pc = sinkinfo_all_em[em_no].si_emc_ind_pc.apx;
		break;

	case SIC_GET_REACTIVE_POWER:
		if (NULL != pa)
//			*pa = sinkinfo.si_emc_ind_pa.rapx;
			*pa = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pa.rapx));

		if (NULL != pb)
//			*pb = sinkinfo.si_emc_ind_pb.rapx;
			*pb = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pb.rapx));

		if (NULL != pc)
//			*pc = sinkinfo.si_emc_ind_pc.rapx;
			*pc = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pc.rapx));
		break;

	case SIC_GET_APPARENT_POWER:
		if (NULL != pa)
			*pa = sinkinfo_all_em[em_no].si_emc_ind_pa.appx;

		if (NULL != pb)
			*pb =sinkinfo_all_em[em_no].si_emc_ind_pb.appx;

		if (NULL != pc)
			*pc = sinkinfo_all_em[em_no].si_emc_ind_pc.appx;
		break;

	case SIC_GET_POWER_FACTOR:
		if (NULL != pa)
			*pa = sinkinfo_all_em[em_no].si_emc_ind_pa.pfx;

		if (NULL != pb)
			*pb = sinkinfo_all_em[em_no].si_emc_ind_pb.pfx;

		if (NULL != pc)
			*pc = sinkinfo_all_em[em_no].si_emc_ind_pc.pfx;
		break;

	case SIC_GET_VOLTAGE_DISTORTION:
		if (NULL != pa)
			*pa = INVLIDE_DATAL; //sinkinfo.si_emc_ind_pa.vdx; /* 该版本不实现, 所有二进制bit置1 */

		if (NULL != pb)
			*pb = INVLIDE_DATAL; //sinkinfo.si_emc_ind_pb.vdx;

		if (NULL != pc)
			*pc = INVLIDE_DATAL; //sinkinfo.si_emc_ind_pc.vdx;
		break;

	case SIC_GET_CURRENT_DISTORTION:
		if (NULL != pa)
			*pa =  INVLIDE_DATAL; //sinkinfo.si_emc_ind_pa.cdx; /* 该版本不实现, 所有二进制bit置1 */

		if (NULL != pb)
			*pb =  INVLIDE_DATAL; //sinkinfo.si_emc_ind_pb.cdx;

		if (NULL != pc)
			*pc =  INVLIDE_DATAL; //sinkinfo.si_emc_ind_pc.cdx;
		break;

	case SIC_GET_EM_VOLTAGE:			/* 电表中读取的电压 */
		if (NULL != pa)
			*pa = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pa.vx));

		if (NULL != pb)
			*pb = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pb.vx));

		if (NULL != pc)
			*pc = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pc.vx));
		break;

	case SIC_GET_EM_CURRENT:			/* 电表中读取的电流 */
		if (NULL != pa)
			*pa = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pa.ix));

		if (NULL != pb)
			*pb = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pb.ix));

		if (NULL != pc)
			*pc = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pc.ix));
		break;

	case SIC_GET_EM_ACTIVE_POWER:		/* 电表中读取的有功功率 */
		if (NULL != pa)
			*pa = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pa.apx));

		if (NULL != pb)
			*pb = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pb.apx));

		if (NULL != pc)
			*pc = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pc.apx));
		break;

	case SIC_GET_EM_REACTIVE_POWER:		/* 电表中读取的无功功率 */
		if (NULL != pa)
			*pa = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pa.rapx));

		if (NULL != pb)
			*pb = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pb.rapx));

		if (NULL != pc)
			*pc = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pc.rapx));
		break;

	case SIC_GET_EM_POWER_FACTOR:		/* 电表中读取的功率因数 */
		if (NULL != pa)
			*pa = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pa.pfx));

		if (NULL != pb)
			*pb = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pb.pfx));

		if (NULL != pc)
			*pc = lwip_htonl(conv_4byte_bcd_to_long(sinkinfo_all_em[em_no].si_em_ind_pc.pfx));
		break;


	case SIC_GET_PT_LOAD:	/* pt负荷 */
		if (NULL != pa)
			*pa = sinkinfo_all_em[em_no].pt_info.pt_pa.appx;

		if (NULL != pb)
			*pb = sinkinfo_all_em[em_no].pt_info.pt_pb.appx;

		if (NULL != pc)
			*pc = sinkinfo_all_em[em_no].pt_info.pt_pc.appx;
		break;

	case SIC_GET_CT_LOAD:	/* ct负荷 */
		if (ptct_no == 1){
			if (NULL != pa)
				*pa = sinkinfo_all_em[em_no].ct_info.ct_pa.appx;

		if (NULL != pb)
			*pb = sinkinfo_all_em[em_no].ct_info.ct_pb.appx;

			if (NULL != pc)
				*pc = sinkinfo_all_em[em_no].ct_info.ct_pc.appx;
		}else if (ptct_no == 2){
			if (NULL != pa)
				*pa = sinkinfo_all_em[em_no].ct1_info.ct_pa.appx;

			if (NULL != pb)
				*pb = sinkinfo_all_em[em_no].ct1_info.ct_pb.appx;

			if (NULL != pc)
				*pc = sinkinfo_all_em[em_no].ct1_info.ct_pc.appx;
		}
		break;

	case SIC_GET_PT_VOLTAGE_DROP: /* 二次侧电压 */
		if (NULL != pa)
			*pa = sinkinfo_all_em[em_no].pt_info.pt_pa.vx;

		if (NULL != pb)
			*pb = sinkinfo_all_em[em_no].pt_info.pt_pb.vx;

		if (NULL != pc)
			*pc = sinkinfo_all_em[em_no].pt_info.pt_pc.vx;
		break;

	default:
		ret = SIE_INVALID_CMD;
		break;
	}

	rt_sem_release(&sinkinfo_sem);

	return ret;
}