Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ethernet_mac_api.c Source File

ethernet_mac_api.c

00001 /*
00002  * Copyright (c) 2016-2018, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may 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,
00013  * WITHOUT 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 "nsconfig.h"
00019 #include <string.h>
00020 #include "ethernet_mac_api.h"
00021 #include "eventOS_event.h"
00022 #include "nsdynmemLIB.h"
00023 #include "common_functions.h"
00024 #include "MAC/rf_driver_storage.h"
00025 
00026 typedef struct eth_mac_internal_s {
00027     eth_mac_api_t *mac_api;
00028     arm_device_driver_list_s *dev_driver;
00029     uint8_t *mtu_ptr;
00030     uint16_t mtu_size;
00031     uint8_t mac48_iid64[8];
00032     bool active_data_request;
00033     int8_t tasklet_id;
00034     //linked list link
00035 } eth_mac_internal_t;
00036 
00037 static eth_mac_internal_t mac_store = { //Hack only at this point, later put into linked list
00038     .tasklet_id = -1
00039 };
00040 
00041 #define ETH_INIT_EVENT 0
00042 #define ETH_DATA_IND_EVENT 1
00043 #define ETH_DATA_CNF_EVENT 2
00044 
00045 
00046 #define ETHERNET_HDROFF_DST_ADDR    0
00047 #define ETHERNET_HDROFF_SRC_ADDR    6
00048 #define ETHERNET_HDROFF_TYPE        12
00049 #define ETHERNET_HDRLEN             14
00050 
00051 static int8_t eth_mac_api_init(eth_mac_api_t *api, eth_mac_data_confirm *conf_cb, eth_mac_data_indication *ind_cb, uint8_t parent_id);
00052 static void data_req(const eth_mac_api_t *api, const eth_data_req_t *data);
00053 static int8_t mac48_address_set(const eth_mac_api_t *api, const uint8_t *mac48);
00054 static int8_t mac48_address_get(const eth_mac_api_t *api, uint8_t *mac48_buf);
00055 static int8_t iid64_address_set(const eth_mac_api_t *api, const uint8_t *iid64);
00056 static int8_t iid64_address_get(const eth_mac_api_t *api, uint8_t *iid64_buf);
00057 
00058 static int8_t eth_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len, uint8_t link_quality, int8_t dbm, int8_t driver_id);
00059 static int8_t eth_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
00060 static void ethernet_mac_tasklet(arm_event_s *event);
00061 
00062 int8_t ethernet_mac_destroy(eth_mac_api_t *mac_api)
00063 {
00064     if (!mac_api || mac_store.mac_api != mac_api) {
00065         return -1;
00066     }
00067 
00068     mac_store.active_data_request = false;
00069     ns_dyn_mem_free(mac_store.mac_api);
00070     mac_store.mac_api = NULL;
00071     mac_store.dev_driver = NULL;
00072     ns_dyn_mem_free(mac_store.mtu_ptr);
00073     mac_store.mtu_ptr = NULL;
00074     mac_store.mtu_size = 0;
00075     return 0;
00076 }
00077 
00078 
00079 
00080 eth_mac_api_t *ethernet_mac_create(int8_t driver_id)
00081 {
00082     //TODO: Refactor this away, Drivers should be stored in MAC layer in future
00083     arm_device_driver_list_s *driver = arm_net_phy_driver_pointer(driver_id);
00084     if (!driver || !driver->phy_driver) {
00085         return NULL;
00086     }
00087 
00088     //Accept to return same mac if mac is generated and driver is same
00089     if (mac_store.mac_api) {
00090         if (mac_store.dev_driver == driver) {
00091             return mac_store.mac_api;
00092         }
00093         return NULL;
00094     }
00095 
00096     uint8_t *buffer_ptr = NULL;
00097     uint16_t buffer_length = 0;
00098     bool address_resolution_needed = true;
00099 
00100     switch (driver->phy_driver->link_type) {
00101 
00102         case PHY_LINK_SLIP:
00103         case PHY_LINK_PPP:
00104             //Do not Allocate
00105             address_resolution_needed = false;
00106             buffer_length = 0;
00107             break;
00108 
00109         case PHY_LINK_TUN:
00110             address_resolution_needed = false;
00111             buffer_length = 1500 + 4;
00112             break;
00113         case PHY_LINK_ETHERNET_TYPE:
00114 
00115             buffer_length = 1500 + ETHERNET_HDRLEN;
00116 
00117 
00118 
00119             break;
00120 
00121         default:
00122             return NULL;
00123     }
00124     if (buffer_length) {
00125         buffer_ptr = ns_dyn_mem_alloc(buffer_length);
00126         if (!buffer_ptr) {
00127             return NULL;
00128         }
00129     }
00130 
00131     eth_mac_api_t *this = ns_dyn_mem_alloc(sizeof(eth_mac_api_t));
00132     if (!this) {
00133         ns_dyn_mem_free(buffer_ptr);
00134         return NULL;
00135     }
00136     memset(this, 0, sizeof(eth_mac_api_t));
00137     this->mac_initialize = &eth_mac_api_init;
00138     this->data_req = &data_req;
00139 
00140     if (driver->phy_driver->link_type == PHY_LINK_PPP) {
00141         this->iid64_get = &iid64_address_get;
00142         this->iid64_set = &iid64_address_set;
00143     } else {
00144         this->mac48_get = &mac48_address_get;
00145         this->mac48_set = &mac48_address_set;
00146     }
00147 
00148     this->address_resolution_needed = address_resolution_needed;
00149 
00150     memset(&mac_store.mac48_iid64, 0, 8);
00151     mac_store.active_data_request = false;
00152     mac_store.mac_api = this;
00153     mac_store.dev_driver = driver;
00154     mac_store.mtu_ptr = buffer_ptr;
00155     mac_store.mtu_size = buffer_length;
00156 
00157     if (driver->phy_driver->link_type == PHY_LINK_PPP) {
00158         memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 8);
00159     } else {
00160         memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
00161     }
00162     if (mac_store.tasklet_id == -1) {
00163         mac_store.tasklet_id = eventOS_event_handler_create(&ethernet_mac_tasklet, ETH_INIT_EVENT);
00164     }
00165     arm_net_phy_init(driver->phy_driver, &eth_mac_net_phy_rx, &eth_mac_net_phy_tx_done);
00166 
00167     return this;
00168 }
00169 
00170 static void ethernet_mac_tasklet(arm_event_s *event)
00171 {
00172     uint8_t event_type = event->event_type;
00173 
00174     switch (event_type) {
00175         case ETH_DATA_IND_EVENT: {
00176             eth_data_ind_t *data_ind = event->data_ptr;
00177             mac_store.mac_api->data_ind_cb(mac_store.mac_api, data_ind);
00178             ns_dyn_mem_free(((eth_data_ind_t *)event->data_ptr)->msdu);
00179             ns_dyn_mem_free(event->data_ptr);
00180             break;
00181         }
00182         case ETH_DATA_CNF_EVENT: {
00183             eth_data_conf_t *data_conf = event->data_ptr;
00184             mac_store.mac_api->data_conf_cb(mac_store.mac_api, data_conf);
00185             ns_dyn_mem_free(event->data_ptr);
00186             mac_store.active_data_request = false;
00187             break;
00188         }
00189         case ETH_INIT_EVENT:
00190         default: {
00191             break;
00192         }
00193     }
00194 }
00195 
00196 static int8_t eth_mac_api_init(eth_mac_api_t *api, eth_mac_data_confirm *conf_cb, eth_mac_data_indication *ind_cb, uint8_t parent_id)
00197 {
00198     if (mac_store.mac_api != api) {
00199         return -1;
00200     }
00201     eth_mac_api_t *cur = mac_store.mac_api;
00202     cur->data_conf_cb = conf_cb;
00203     cur->data_ind_cb = ind_cb;
00204     cur->parent_id = parent_id;
00205 
00206     return 0;
00207 }
00208 
00209 static void data_req(const eth_mac_api_t *api, const eth_data_req_t *data)
00210 {
00211     if (mac_store.mac_api != api || !mac_store.dev_driver->phy_driver || !data  || !data->msduLength) {
00212         return;
00213     }
00214 
00215 
00216     uint8_t *data_ptr;
00217     uint16_t data_length;
00218 
00219     //Build header
00220     switch (mac_store.dev_driver->phy_driver->link_type) {
00221         case PHY_LINK_ETHERNET_TYPE:
00222 
00223             if (data->msduLength + ETHERNET_HDRLEN > mac_store.mtu_size || !data->dstAddress || !data->srcAddress) {
00224                 return;
00225             }
00226 
00227             data_ptr = mac_store.mtu_ptr;
00228             data_length = data->msduLength + ETHERNET_HDRLEN;
00229             memcpy(data_ptr + ETHERNET_HDROFF_DST_ADDR, data->dstAddress, 6);
00230             memcpy(data_ptr + ETHERNET_HDROFF_SRC_ADDR, data->srcAddress, 6);
00231             common_write_16_bit(data->etehernet_type, data_ptr + ETHERNET_HDROFF_TYPE);
00232             memcpy(data_ptr + ETHERNET_HDRLEN, data->msdu, data->msduLength);
00233             break;
00234 
00235         case PHY_LINK_TUN:
00236             if (data->msduLength + 4 > mac_store.mtu_size) {
00237                 return;
00238             }
00239             data_ptr = mac_store.mtu_ptr;
00240             /* TUN header
00241              * [ TUN FLAGS 2B | PROTOCOL 2B | PAYLOAD ]
00242              * Tun flags may be 0, and protocol is same as in ether-type field, so
00243              * replace flags with e.g. IFF_TUN and packet is converted to TUN frame
00244              */
00245             common_write_16_bit(0, data_ptr);
00246             common_write_16_bit(data->etehernet_type, data_ptr + 2);
00247             memcpy(data_ptr + 4, data->msdu, data->msduLength);
00248             data_length = data->msduLength + 4;
00249             break;
00250 
00251         default: //SLIP
00252             data_ptr = data->msdu;
00253             data_length = data->msduLength;
00254             break;
00255     }
00256 
00257     mac_store.active_data_request = true;
00258     mac_store.dev_driver->phy_driver->tx(data_ptr, data_length, 0, PHY_LAYER_PAYLOAD);
00259 }
00260 
00261 static int8_t eth_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len, uint8_t link_quality, int8_t dbm, int8_t driver_id)
00262 {
00263     arm_device_driver_list_s *driver = arm_net_phy_driver_pointer(driver_id);
00264     if (!data_ptr || !driver || driver != mac_store.dev_driver) {
00265         return -1;
00266     }
00267 
00268     if (data_len == 0) {
00269         return -1;
00270     }
00271 
00272     eth_data_ind_t *data_ind = ns_dyn_mem_temporary_alloc(sizeof(eth_data_ind_t));
00273     if (!data_ind) {
00274         return -1;
00275     }
00276     memset(data_ind, 0, sizeof(eth_data_ind_t));
00277 
00278     if (driver->phy_driver->link_type == PHY_LINK_ETHERNET_TYPE) {
00279         if (data_len < ETHERNET_HDRLEN + 1) {
00280             ns_dyn_mem_free(data_ind);
00281             return -1;
00282         }
00283 
00284         memcpy(data_ind->dstAddress, data_ptr +  ETHERNET_HDROFF_DST_ADDR, 6);
00285         memcpy(data_ind->srcAddress, data_ptr +  ETHERNET_HDROFF_SRC_ADDR, 6);
00286 
00287         data_ind->etehernet_type = common_read_16_bit(data_ptr + ETHERNET_HDROFF_TYPE);
00288 
00289         data_ptr += ETHERNET_HDRLEN;
00290         data_len -= ETHERNET_HDRLEN;
00291 
00292     } else if (driver->phy_driver->link_type == PHY_LINK_TUN) {
00293         if (data_len < 5) {
00294             ns_dyn_mem_free(data_ind);
00295             return -1;
00296         }
00297         /* TUN header
00298          * [ TUN FLAGS 2B | PROTOCOL 2B | PAYLOAD ]
00299          * Protocol is ether-type id.
00300          */
00301         data_ind->etehernet_type = common_read_16_bit(data_ptr + 2);
00302 
00303         data_len -= 4;
00304         data_ptr += 4;
00305     } else if (driver->phy_driver->link_type == PHY_LINK_SLIP || driver->phy_driver->link_type == PHY_LINK_PPP) {
00306         data_ind->etehernet_type = ETHERTYPE_IPV6;
00307     }
00308 
00309     data_ind->msdu = ns_dyn_mem_temporary_alloc(data_len);
00310     if (!data_ind->msdu) {
00311         ns_dyn_mem_free(data_ind);
00312         return -1;
00313     }
00314     memcpy(data_ind->msdu, data_ptr, data_len);
00315     data_ind->msduLength = data_len;
00316     data_ind->dbm = dbm;
00317     data_ind->link_quality = link_quality;
00318 
00319     arm_event_s event = {
00320         .receiver = mac_store.tasklet_id,
00321         .sender = 0,
00322         .event_id = 0,
00323         .data_ptr = data_ind,
00324         .event_type = ETH_DATA_IND_EVENT,
00325         .priority = ARM_LIB_HIGH_PRIORITY_EVENT,
00326     };
00327 
00328     if (eventOS_event_send(&event)) {
00329         ns_dyn_mem_free(data_ind->msdu);
00330         ns_dyn_mem_free(data_ind);
00331         return -1;
00332     }
00333 
00334     return 0;
00335 }
00336 
00337 static int8_t eth_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry)
00338 {
00339     (void)tx_handle;
00340     (void)cca_retry;
00341     (void)tx_retry;
00342     arm_device_driver_list_s *driver = arm_net_phy_driver_pointer(driver_id);
00343     if (!driver) {
00344         return -1;
00345     }
00346 
00347     if (mac_store.active_data_request) {
00348         mac_store.active_data_request = false;
00349         eth_data_conf_t *data_conf = ns_dyn_mem_temporary_alloc(sizeof(eth_data_conf_t));
00350         if (!data_conf) {
00351             return -1;
00352         }
00353         data_conf->status = status;
00354         arm_event_s event = {
00355             .receiver = mac_store.tasklet_id,
00356             .sender = 0,
00357             .event_id = 0,
00358             .data_ptr = data_conf,
00359             .event_type = ETH_DATA_CNF_EVENT,
00360             .priority = ARM_LIB_HIGH_PRIORITY_EVENT,
00361         };
00362 
00363         return eventOS_event_send(&event);
00364     }
00365     return 0;
00366 }
00367 
00368 static int8_t mac48_address_set(const eth_mac_api_t *api, const uint8_t *mac48)
00369 {
00370     if (!mac48 || !api || mac_store.mac_api != api) {
00371         return -1;
00372     }
00373     memcpy(mac_store.mac48_iid64, mac48, 6);
00374     phy_device_driver_s *driver = mac_store.dev_driver->phy_driver;
00375     if (driver->address_write) {
00376         driver->address_write(PHY_MAC_48BIT, mac_store.mac48_iid64);
00377     }
00378     return 0;
00379 }
00380 
00381 static int8_t mac48_address_get(const eth_mac_api_t *api, uint8_t *mac48_buf)
00382 {
00383     if (!mac48_buf || !api || mac_store.mac_api != api) {
00384         return -1;
00385     }
00386     memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
00387     memcpy(mac48_buf, mac_store.mac48_iid64, 6);
00388     return 0;
00389 }
00390 
00391 static int8_t iid64_address_set(const eth_mac_api_t *api, const uint8_t *iid64)
00392 {
00393     if (!iid64 || !api || mac_store.mac_api != api) {
00394         return -1;
00395     }
00396     memcpy(mac_store.mac48_iid64, iid64, 8);
00397     phy_device_driver_s *driver = mac_store.dev_driver->phy_driver;
00398     if (driver->address_write) {
00399         driver->address_write(PHY_MAC_48BIT, mac_store.mac48_iid64);
00400     }
00401     return 0;
00402 }
00403 
00404 static int8_t iid64_address_get(const eth_mac_api_t *api, uint8_t *iid64_buf)
00405 {
00406     if (!iid64_buf || !api || mac_store.mac_api != api) {
00407         return -1;
00408     }
00409     memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 8);
00410     memcpy(iid64_buf, mac_store.mac48_iid64, 8);
00411     return 0;
00412 }