takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers emac_ctp.cpp Source File

emac_ctp.cpp

00001 /*
00002  * Copyright (c) 2017, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "greentea-client/test_env.h"
00019 #include "unity/unity.h"
00020 #include "utest.h"
00021 
00022 #include "mbed.h"
00023 
00024 #include "EMAC.h"
00025 #include "EMACMemoryManager.h"
00026 #include "emac_TestMemoryManager.h"
00027 
00028 #include "emac_tests.h"
00029 #include "emac_ctp.h"
00030 
00031 #include "emac_initialize.h"
00032 #include "emac_util.h"
00033 #include "emac_membuf.h"
00034 
00035 using namespace utest::v1;
00036 
00037 // Unique identifier for message
00038 static int receipt_number = 0;
00039 
00040 static int emac_if_ctp_header_build(unsigned char *eth_frame, const unsigned char *dest_addr, const unsigned char *origin_addr, const unsigned char *forward_addr)
00041 {
00042     memcpy(&eth_frame[0], dest_addr, 6);
00043     memcpy(&eth_frame[6], origin_addr, 6);
00044 
00045     eth_frame[12] = 0x90; /* loop back */
00046     eth_frame[13] = 0x00;
00047 
00048     eth_frame[14] = 0x00; /* skip count */
00049     eth_frame[15] = 0x00;
00050 
00051     eth_frame[16] = 0x02; /* function, forward */
00052     eth_frame[17] = 0x00;
00053 
00054     memcpy(&eth_frame[18], forward_addr, 6);
00055 
00056     eth_frame[24] = 0x01; /* function, reply */
00057     eth_frame[25] = 0x00;
00058 
00059     receipt_number++;
00060 
00061     eth_frame[26] = receipt_number; /* receipt number */
00062     eth_frame[27] = receipt_number >> 8;
00063 
00064     return receipt_number;
00065 }
00066 
00067 ctp_function emac_if_ctp_header_handle(unsigned char *eth_input_frame, unsigned char *eth_output_frame, unsigned char *origin_addr, int *receipt_number)
00068 {
00069     if (eth_input_frame[12] != 0x90 || eth_input_frame[13] != 0x00) {
00070         return CTP_NONE;
00071     }
00072 
00073     int skip_count = eth_input_frame[15] << 8 | eth_input_frame[14];
00074     unsigned char *ethernet_ptr = &eth_input_frame[16] + skip_count;
00075 
00076     int function = ethernet_ptr[1] << 8 | ethernet_ptr[0];
00077     ethernet_ptr += 2;
00078 
00079     // Forward
00080     if (function == 0x0002) {
00081         memcpy(eth_output_frame, eth_input_frame, ETH_FRAME_HEADER_LEN);
00082         // Update skip count
00083         skip_count += 8;
00084         eth_output_frame[14] = skip_count;
00085         eth_output_frame[15] = skip_count >> 8;
00086         // Set forward address to destination address
00087         memcpy(&eth_output_frame[0], ethernet_ptr, 6);
00088         // Copy own address to origin
00089         memcpy(&eth_output_frame[6], origin_addr, 6);
00090         return CTP_FORWARD;
00091         // reply
00092     } else if (function == 0x0001) {
00093         *receipt_number = ethernet_ptr[1] << 8 | ethernet_ptr[0];
00094         return CTP_REPLY;
00095     }
00096 
00097     return CTP_NONE;
00098 }
00099 
00100 void emac_if_ctp_msg_build(int eth_frame_len, const unsigned char *dest_addr, const unsigned char *origin_addr, const unsigned char *forward_addr, int options)
00101 {
00102     if (eth_frame_len < ETH_FRAME_HEADER_LEN) {
00103         eth_frame_len = ETH_FRAME_HEADER_LEN;
00104     }
00105 
00106     if (emac_if_get_trace_level() & TRACE_SEND) {
00107         printf("message sent %x:%x:%x:%x:%x:%x\r\n\r\n", dest_addr[0], dest_addr[1], dest_addr[2], dest_addr[3], dest_addr[4], dest_addr[5]);
00108     }
00109 
00110     int outgoing_msg_index = emac_if_add_outgoing_msg(eth_frame_len);
00111 
00112     if (outgoing_msg_index < 0) {
00113         SET_ERROR_FLAGS(OUT_OF_MSG_DATA);
00114         return;
00115     }
00116 
00117     int alloc_opt = 0;
00118     int align = 0;
00119     if (options & CTP_OPT_NON_ALIGNED) {
00120         alloc_opt |= MEM_NO_ALIGN; // Force align to odd address
00121         align = 1;                 // Reserve memory overhead to align to odd address
00122     }
00123 
00124     emac_mem_buf_t *buf;
00125     if (options & CTP_OPT_HEAP) {
00126         buf = emac_m_mngr_get()->alloc_heap(eth_frame_len, align, alloc_opt);
00127     } else {
00128         // Default allocation is from pool
00129         buf = emac_m_mngr_get()->alloc_pool(eth_frame_len, align, alloc_opt);
00130     }
00131 
00132     if (!buf) {
00133         SET_ERROR_FLAGS(NO_FREE_MEM_BUF);
00134         emac_if_free_outgoing_msg(outgoing_msg_index);
00135         return;
00136     }
00137 
00138     if (memcmp(dest_addr, eth_mac_broadcast_addr, 6) == 0) {
00139         emac_if_set_outgoing_msg_flags(outgoing_msg_index, BROADCAST);
00140     }
00141 
00142     unsigned char eth_output_frame_data[ETH_FRAME_HEADER_LEN];
00143     int receipt_number = emac_if_ctp_header_build(eth_output_frame_data, dest_addr, origin_addr, forward_addr);
00144     emac_if_set_outgoing_msg_receipt_num(outgoing_msg_index, receipt_number);
00145 
00146     emac_if_memory_buffer_write(buf, eth_output_frame_data, true);
00147 
00148     emac_if_check_memory(true);
00149     emac_if_get()->link_out(buf);
00150     emac_if_check_memory(false);
00151 }
00152 
00153