1 /*
2  * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company)
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /** @file
19  *
20  * Implements functions called by WHD user APIs, but not directly exposed to user
21  *
22  * This file provides functions which are not directly exposed to user but, called by end-user functions which allow actions such as
23  * seting the MAC address, getting channel info, etc
24  */
25 
26 #include "whd_ap.h"
27 #include "whd_chip_constants.h"
28 #include "whd_debug.h"
29 #include "whd_events_int.h"
30 #include "whd_cdc_bdc.h"
31 #include "whd_thread_internal.h"
32 #include "whd_utils.h"
33 #include "whd_wifi_api.h"
34 #include "whd_wlioctl.h"
35 
36 /******************************************************
37 * @cond       Constants
38 ******************************************************/
39 #define MAC_ADDRESS_LOCALLY_ADMINISTERED_BIT 0x02
40 
41 /******************************************************
42 *             Local Structures
43 ******************************************************/
44 
45 
46 
47 /******************************************************
48 *                   Variables
49 ******************************************************/
50 void (*whd_wifi_link_update_callback)(void) = NULL;
51 
52 /******************************************************
53 *             Function definitions
54 ******************************************************/
55 
whd_wifi_set_mac_address(whd_interface_t ifp,whd_mac_t mac)56 uint32_t whd_wifi_set_mac_address(whd_interface_t ifp, whd_mac_t mac)
57 {
58     whd_buffer_t buffer;
59     uint32_t *data;
60     whd_driver_t whd_driver = ifp->whd_driver;
61 
62     /* AP interface needs to come up with MAC different from STA  */
63 #ifdef APOLLO_AUDIO
64 
65     /* Work around the issue of asking API to set one address and it sets a different address.
66      * This will cause any comparison of set and get mac address to fail.  TODO: move twiddling this
67      * bit to a higher level.
68      */
69     if (0)
70 #else
71     if (ifp->role == WHD_AP_ROLE)
72 #endif
73     {
74         whd_mac_t ap_mac_address;
75 
76         memcpy(&ap_mac_address, &mac, sizeof(whd_mac_t) );
77         if (ap_mac_address.octet[0] & MAC_ADDRESS_LOCALLY_ADMINISTERED_BIT)
78         {
79             ap_mac_address.octet[0] &= (uint8_t) ~(MAC_ADDRESS_LOCALLY_ADMINISTERED_BIT);
80         }
81         else
82         {
83             ap_mac_address.octet[0] |= MAC_ADDRESS_LOCALLY_ADMINISTERED_BIT;
84         }
85 
86         data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(whd_mac_t), IOVAR_STR_CUR_ETHERADDR);
87         CHECK_IOCTL_BUFFER(data);
88         memcpy(data, &ap_mac_address, sizeof(whd_mac_t) );
89         CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
90 
91         if (memcmp(&mac, &ap_mac_address, sizeof(whd_mac_t) ) != 0)
92         {
93             WPRINT_WHD_INFO( (" STA MAC address : %02x:%02x:%02x:%02x:%02x:%02x \n"
94                               " AP  MAC address : %02x:%02x:%02x:%02x:%02x:%02x \n",
95                               mac.octet[0], mac.octet[1], mac.octet[2],
96                               mac.octet[3], mac.octet[4], mac.octet[3],
97                               ap_mac_address.octet[0], ap_mac_address.octet[1], ap_mac_address.octet[2],
98                               ap_mac_address.octet[3], ap_mac_address.octet[4], ap_mac_address.octet[3]) );
99         }
100     }
101     else
102     {
103         data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(whd_mac_t), IOVAR_STR_CUR_ETHERADDR);
104         CHECK_IOCTL_BUFFER(data);
105         memcpy(data, &mac, sizeof(whd_mac_t) );
106         CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) );
107     }
108 
109     return WHD_SUCCESS;
110 }
111