Knight KE / Mbed OS Game_Master
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 #if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET
00023 
00024 #include "mbed.h"
00025 
00026 #include "EMAC.h"
00027 #include "EMACMemoryManager.h"
00028 #include "emac_TestMemoryManager.h"
00029 
00030 #include "emac_tests.h"
00031 #include "emac_ctp.h"
00032 
00033 #include "emac_initialize.h"
00034 #include "emac_util.h"
00035 #include "emac_membuf.h"
00036 
00037 using namespace utest::v1;
00038 
00039 // Unique identifier for message
00040 static int receipt_number = 0;
00041 
00042 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)
00043 {
00044     memcpy(&eth_frame[0], dest_addr, 6);
00045     memcpy(&eth_frame[6], origin_addr, 6);
00046 
00047     eth_frame[12] = 0x90; /* loop back */
00048     eth_frame[13] = 0x00;
00049 
00050     eth_frame[14] = 0x00; /* skip count */
00051     eth_frame[15] = 0x00;
00052 
00053     eth_frame[16] = 0x02; /* function, forward */
00054     eth_frame[17] = 0x00;
00055 
00056     memcpy(&eth_frame[18], forward_addr, 6);
00057 
00058     eth_frame[24] = 0x01; /* function, reply */
00059     eth_frame[25] = 0x00;
00060 
00061     receipt_number++;
00062 
00063     eth_frame[26] = receipt_number; /* receipt number */
00064     eth_frame[27] = receipt_number >> 8;
00065 
00066     return receipt_number;
00067 }
00068 
00069 ctp_function emac_if_ctp_header_handle(unsigned char *eth_input_frame, unsigned char *eth_output_frame, unsigned char *origin_addr, int *receipt_number)
00070 {
00071     if (eth_input_frame[12] != 0x90 || eth_input_frame[13] != 0x00) {
00072         return CTP_NONE;
00073     }
00074 
00075     int skip_count = eth_input_frame[15] << 8 | eth_input_frame[14];
00076     unsigned char *ethernet_ptr = &eth_input_frame[16] + skip_count;
00077 
00078     int function = ethernet_ptr[1] << 8 | ethernet_ptr[0];
00079     ethernet_ptr += 2;
00080 
00081     // Forward
00082     if (function == 0x0002) {
00083         memcpy(eth_output_frame, eth_input_frame, ETH_FRAME_HEADER_LEN);
00084         // Update skip count
00085         skip_count += 8;
00086         eth_output_frame[14] = skip_count;
00087         eth_output_frame[15] = skip_count >> 8;
00088         // Set forward address to destination address
00089         memcpy(&eth_output_frame[0], ethernet_ptr, 6);
00090         // Copy own address to origin
00091         memcpy(&eth_output_frame[6], origin_addr, 6);
00092         return CTP_FORWARD;
00093     // reply
00094     } else if (function == 0x0001) {
00095         *receipt_number = ethernet_ptr[1] << 8 | ethernet_ptr[0];
00096         return CTP_REPLY;
00097     }
00098 
00099     return CTP_NONE;
00100 }
00101 
00102 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)
00103 {
00104     if (eth_frame_len < ETH_FRAME_HEADER_LEN) {
00105         eth_frame_len = ETH_FRAME_HEADER_LEN;
00106     }
00107 
00108     if (emac_if_get_trace_level() & TRACE_SEND) {
00109         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]);
00110     }
00111 
00112     int outgoing_msg_index = emac_if_add_outgoing_msg(eth_frame_len);
00113 
00114     if (outgoing_msg_index < 0) {
00115         SET_ERROR_FLAGS(OUT_OF_MSG_DATA);
00116         return;
00117     }
00118 
00119     int alloc_opt = 0;
00120     int align = 0;
00121     if (options & CTP_OPT_NON_ALIGNED) {
00122         alloc_opt |= MEM_NO_ALIGN; // Force align to odd address
00123         align = 1;                 // Reserve memory overhead to align to odd address
00124     }
00125 
00126     emac_mem_buf_t *buf;
00127     if (options & CTP_OPT_HEAP) {
00128         buf = emac_m_mngr_get()->alloc_heap(eth_frame_len, align, alloc_opt);
00129     } else {
00130         // Default allocation is from pool
00131         buf = emac_m_mngr_get()->alloc_pool(eth_frame_len, align, alloc_opt);
00132     }
00133 
00134     if (!buf) {
00135         SET_ERROR_FLAGS(NO_FREE_MEM_BUF);
00136         emac_if_free_outgoing_msg(outgoing_msg_index);
00137         return;
00138     }
00139 
00140     if (memcmp(dest_addr, eth_mac_broadcast_addr, 6) == 0) {
00141         emac_if_set_outgoing_msg_flags(outgoing_msg_index, BROADCAST);
00142     }
00143 
00144     unsigned char eth_output_frame_data[ETH_FRAME_HEADER_LEN];
00145     int receipt_number = emac_if_ctp_header_build(eth_output_frame_data, dest_addr, origin_addr, forward_addr);
00146     emac_if_set_outgoing_msg_receipt_num(outgoing_msg_index, receipt_number);
00147 
00148     emac_if_memory_buffer_write(buf, eth_output_frame_data, true);
00149 
00150     emac_if_check_memory(true);
00151     emac_if_get()->link_out(buf);
00152     emac_if_check_memory(false);
00153 }
00154 
00155 #endif
00156