diff --git a/abstraction-rtos/.cyignore b/abstraction-rtos/.cyignore new file mode 100644 index 00000000..d8f8d469 --- /dev/null +++ b/abstraction-rtos/.cyignore @@ -0,0 +1 @@ +docs diff --git a/abstraction-rtos/LICENSE b/abstraction-rtos/LICENSE new file mode 100644 index 00000000..59cd3f8a --- /dev/null +++ b/abstraction-rtos/LICENSE @@ -0,0 +1,165 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. diff --git a/abstraction-rtos/README.md b/abstraction-rtos/README.md new file mode 100644 index 00000000..54d1813b --- /dev/null +++ b/abstraction-rtos/README.md @@ -0,0 +1,111 @@ +# RTOS Abstraction + +## Overview + +The RTOS abstraction layer provides simple RTOS services like threads, semaphores, mutexes, queues, and timers. It is not intended to be a full features RTOS interface, but the provide just enough support to allow for RTOS independent drivers and middleware. This allows middleware applications to be as portable as possible within ModusToolbox™. This library provides a unified API around the actual RTOS. This allows middleware libraries to be written once independent of the RTOS actually selected for the application. The abstraction layer provides access to all the standard RTOS resources listed in the feature section below. + +While the primary purpose of the library is for middleware, the abstraction layer can be used by the application code. However, since this API does not provide all RTOS features and the application generally knows what RTOS is being used, this is typically an unnecessary overhead. + +All the RTOS abstraction layer functions generally all work the same way. The basic process is: +1. Include the cyabs_rtos.h header file so that you have access to the RTOS functions. +2. Declare a variable of the right type (e.g. cy_mutex_t) +3. Call the appropriate create or initialize function (e.g. cy_rtos_init_mutex()). Provide it with a reference to the variable that was created in step 2. +4. Access the RTOS object using one of the access functions. e.g. cy_rtos_set_mutex(). +5. If you don't need it anymore, free up the pointer with the appropriate de-init function (e.g. cy_rtos_deinit_mutex()). + +NOTE: All these functions need a pointer, so it is generally best to declare these "shared" resources as static global variables within the file that they are used. + +## Getting Started + +To use the RTOS Abstraction, simply include a reference to `cyabs_rtos.h` and update the application's makefile to include the appropriate component. e.g. one of: +* COMPONENTS+=RTX +* COMPONENTS+=FREERTOS +* COMPONENTS+=THREADX + +## Features + +* APIs for interacting with common RTOS Features including: + * Threads + * Mutexes + * Semaphores + * Timers + * Queues + * Events +* Implementations are provided for + * FreeRTOS + * RTX (CMSIS RTOS) + * ThreadX + +## RTOS Configuration Requirements +### FreeRTOS +To enable all functionality when using with FreeRTOS, the following configuration options must be enabled in FreeRTOSConfig.h: +* configSUPPORT_DYNAMIC_ALLOCATION +* configSUPPORT_STATIC_ALLOCATION +* configUSE_COUNTING_SEMAPHORES +* configUSE_MUTEXES +* configUSE_NEWLIB_REENTRANT +* configUSE_RECURSIVE_MUTEXES +* configUSE_TASK_NOTIFICATIONS +* configUSE_TICKLESS_IDLE +* configUSE_TIMERS +* configUSE_TRACE_FACILITY + +* INCLUDE_vTaskDelay +* INCLUDE_vTaskDelete +* INCLUDE_vTaskPrioritySet +* INCLUDE_uxTaskPriorityGet +* INCLUDE_xTimerPendFunctionCall +* INCLUDE_vTaskSuspend + +Enabling configSUPPORT_STATIC_ALLOCATION requires the application to provide implementations for `vApplicationGetIdleTaskMemory` and +`vApplicationGetTimerTaskMemory`functions. Weak implementations for these functions are provided as a part of this library. These can +be overridden by the application if custom implementations of these functions are desired.
+ +This library provides an API `vApplicationSleep` which can be used to enable tickless support in FreeRTOS. In order to enable tickless mode with this API, the following changes need to be made in `FreeRTOSConfig.h`: +* Enables tickless mode with user specified `portSUPPRESS_TICKS_AND_SLEEP` implementation.
+\c \#define `configUSE_TICKLESS_IDLE 2` +* Hook `portSUPPRESS_TICKS_AND_SLEEP` macro to `vApplicationSleep` implementation.
+\c \#define `portSUPPRESS_TICKS_AND_SLEEP( xIdleTime ) vApplicationSleep( xIdleTime )` + +For further details on Low power support in FreeRTOS please refer to documentation [here](https://www.freertos.org/low-power-tickless-rtos.html) + +### RTX / ThreadX +No specific requirements exist + +## Porting Notes +In order to port to a new environment, the file cyabs_rtos_impl.h must be provided with definitions of some basic types for the abstraction layer. The types expected to be defined are: + +- `cy_thread_t` : typedef from underlying RTOS thread type +- `cy_thread_arg_t` : typedef from the RTOS type that is passed to the entry function of a thread. +- `cy_mutex_t` : typedef from the underlying RTOS mutex type +- `cy_semaphore_t`: typedef from the underlying RTOS semaphore type +- `cy_event_t` : typedef from the underlying RTOS event type +- `cy_queue_t` : typedef from the underlying RTOS queue type +- `cy_timer_callback_arg_t` : typedef from the RTOS type that is passed to the timer callback function +- `cy_timer_t` : typedef from the underlying RTOS timer type +- `cy_time_t` : count of time in milliseconds +- `cy_rtos_error_t` : typedef from the underlying RTOS error type + +The enum `cy_thread_priority_t` needs to have the following priority values defined and mapped to RTOS specific values: +- `CY_RTOS_PRIORITY_MIN` +- `CY_RTOS_PRIORITY_LOW` +- `CY_RTOS_PRIORITY_BELOWNORMAL` +- `CY_RTOS_PRIORITY_NORMAL` +- `CY_RTOS_PRIORITY_ABOVENORMAL` +- `CY_RTOS_PRIORITY_HIGH` +- `CY_RTOS_PRIORITY_REALTIME` +- `CY_RTOS_PRIORITY_MAX` + +Finally, the following macros need to be defined for memory allocations: +- `CY_RTOS_MIN_STACK_SIZE` +- `CY_RTOS_ALIGNMENT` +- `CY_RTOS_ALIGNMENT_MASK` + +## More information +* [API Reference Guide](https://infineon.github.io/abstraction-rtos/html/modules.html) +* [Cypress Semiconductor, an Infineon Technologies Company](http://www.cypress.com) +* [Infineon GitHub](https://github.com/infineon) +* [ModusToolbox™](https://www.cypress.com/products/modustoolbox-software-environment) + +--- +© Cypress Semiconductor Corporation (an Infineon company) or an affiliate of Cypress Semiconductor Corporation, 2019-2021. diff --git a/abstraction-rtos/RELEASE.md b/abstraction-rtos/RELEASE.md new file mode 100644 index 00000000..c3e4b010 --- /dev/null +++ b/abstraction-rtos/RELEASE.md @@ -0,0 +1,73 @@ +# RTOS Abstraction Library +The RTOS Abstraction APIs allow middleware to be written to be RTOS aware, but not need to care about what the actual RTOS is. + +### What's Included? +The this release of the RTOS Abstraction API includes support for the following: +* APIs for interacting with common RTOS Features including: + * Threads + * Mutexes + * Semaphores + * Timers + * Queues + * Events +* Implementations are provided for + * FreeRTOS + * RTX (CMSIS RTOS) + * ThreadX + +### What Changed? +#### v1.5.0 +* Added additional parameter validation for ThreadX +#### v1.4.0 +* Added new thread functions: cy_rtos_wait_thread_notification and cy_rtos_set_thread_notification +* Minor documentation updates for clarity +#### v1.3.1 +* Fixed a couple bugs in the FreeRTOS port +#### v1.3.0 +* Update to work with a wider range of MCUs +* Fixed a race condition in the worker thread +* Fixed possible issue with thread priorities +* Minor documentation updates +#### v1.2.2 +* Minor update for documentation & branding +#### v1.2.1 +* Fixed possible race condition in cy_rtos_join_thread for FreeRTOS +* Minor documentation updates +#### v1.2.0 +* Added utility library for for creating background worker threads: cy_worker_thread.h +* Added support for getting a semaphore's count: cy_rtos_get_count_semaphore() +* Added support for non-recursive mutexes: cy_rtos_init_mutex2() +* Added default implementations for FreeRTOS vApplicationGetIdleTaskMemory, vApplicationGetTimerTaskMemory, and vApplicationSleep +* Added support for ThreadX +NOTE: The vApplicationSleep implementation for FreeRTOS depends on the psoc6hal 1.2.0 or later. +#### v1.1.0 +* Fixed an issue with the FreeRTOS implementation where it would always allocate memory for the thread stack, even if a pre-allocated buffer was provided. +* Removed usage of assert() and replaced with CY_ASSERT() +#### v1.0.1 +* Added a new function to get the ID of the currently running thread. +* A few minor updates to avoid possible warnings depending on compiler. +* Minor documentation updates +#### v1.0.0 +* Initial release supporting FreeRTOS & RTX + +### Supported Software and Tools +This version of the RTOS Abstraction API was validated for compatibility with the following Software and Tools: + +| Software and Tools | Version | +| :--- | :----: | +| ModusToolbox™ Software Environment | 2.4.0 | +| GCC Compiler | 10.3.1 | +| IAR Compiler | 8.4 | +| ARM Compiler | 6.11 | + +Minimum required ModusToolbox™ Software Environment: v2.0 + +### More information +Use the following links for more information, as needed: +* [API Reference Guide](https://infineon.github.io/abstraction-rtos/html/modules.html) +* [Cypress Semiconductor, an Infineon Technologies Company](http://www.cypress.com) +* [Infineon GitHub](https://github.com/infineon) +* [ModusToolbox™](https://www.cypress.com/products/modustoolbox-software-environment) + +--- +© Cypress Semiconductor Corporation (an Infineon company) or an affiliate of Cypress Semiconductor Corporation, 2019-2021. \ No newline at end of file diff --git a/abstraction-rtos/include/COMPONENT_FREERTOS/cyabs_rtos_impl.h b/abstraction-rtos/include/COMPONENT_FREERTOS/cyabs_rtos_impl.h new file mode 100644 index 00000000..7d47ab32 --- /dev/null +++ b/abstraction-rtos/include/COMPONENT_FREERTOS/cyabs_rtos_impl.h @@ -0,0 +1,105 @@ +/***********************************************************************************************//** + * \file cyabs_rtos_impl.h + * + * \brief + * Internal definitions for RTOS abstraction layer + * + *************************************************************************************************** + * \copyright + * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include "stdbool.h" +#if defined(CY_USING_HAL) +#include "cyhal.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************** +* Constants +******************************************************/ +#define CY_RTOS_MIN_STACK_SIZE 300 /**< Minimum stack size in bytes */ +#define CY_RTOS_ALIGNMENT 0x00000008UL /**< Minimum alignment for RTOS objects */ +#define CY_RTOS_ALIGNMENT_MASK 0x00000007UL /**< Mask for checking the alignment of + created RTOS objects */ + +/****************************************************** +* Enumerations +******************************************************/ + +typedef enum cy_thread_priority +{ + CY_RTOS_PRIORITY_MIN = 0, + CY_RTOS_PRIORITY_LOW = (configMAX_PRIORITIES * 1 / 7), + CY_RTOS_PRIORITY_BELOWNORMAL = (configMAX_PRIORITIES * 2 / 7), + CY_RTOS_PRIORITY_NORMAL = (configMAX_PRIORITIES * 3 / 7), + CY_RTOS_PRIORITY_ABOVENORMAL = (configMAX_PRIORITIES * 4 / 7), + CY_RTOS_PRIORITY_HIGH = (configMAX_PRIORITIES * 5 / 7), + CY_RTOS_PRIORITY_REALTIME = (configMAX_PRIORITIES * 6 / 7), + CY_RTOS_PRIORITY_MAX = configMAX_PRIORITIES - 1 +} cy_thread_priority_t; + +/****************************************************** +* Type Definitions +******************************************************/ + +typedef struct +{ + SemaphoreHandle_t mutex_handle; + bool is_recursive; +} cy_mutex_t; + +typedef QueueHandle_t cy_queue_t; +typedef SemaphoreHandle_t cy_semaphore_t; +typedef TaskHandle_t cy_thread_t; +typedef EventGroupHandle_t cy_event_t; +typedef TimerHandle_t cy_timer_t; +typedef uint32_t cy_timer_callback_arg_t; +typedef void* cy_thread_arg_t; +typedef uint32_t cy_time_t; +typedef BaseType_t cy_rtos_error_t; + +#if defined(CY_USING_HAL) +/** Stores a reference to an lptimer instance for use with vApplicationSleep(). + * + * @param[in] timer Pointer to the lptimer handle + */ +void cyabs_rtos_set_lptimer(cyhal_lptimer_t* timer); + +/** Gets a reference to the lptimer instance object used by vApplicationSleep(). This instance is + * what was explicitly set by @ref cyabs_rtos_set_lptimer or, if none was set, what was + * automatically allocated by the first call to vApplicationSleep(). + * + * @return Pointer to the lptimer handle + */ +cyhal_lptimer_t* cyabs_rtos_get_lptimer(void); +#endif //defined(CY_USING_HAL) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/abstraction-rtos/include/COMPONENT_RTX/cyabs_rtos_impl.h b/abstraction-rtos/include/COMPONENT_RTX/cyabs_rtos_impl.h new file mode 100644 index 00000000..4511eedf --- /dev/null +++ b/abstraction-rtos/include/COMPONENT_RTX/cyabs_rtos_impl.h @@ -0,0 +1,78 @@ +/***********************************************************************************************//** + * \file cyabs_rtos_impl.h + * + * \brief + * Internal definitions for RTOS abstraction layer + * + *************************************************************************************************** + * \copyright + * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#pragma once + +#include "cmsis_os2.h" +#include "rtx_os.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Constants +******************************************************/ +#define CY_RTOS_MIN_STACK_SIZE 300 /** Minimum stack size in bytes */ +#define CY_RTOS_ALIGNMENT 0x00000008UL /** Minimum alignment for RTOS objects */ +#define CY_RTOS_ALIGNMENT_MASK 0x00000007UL /** Mask for checking the alignment of + created RTOS objects */ + + +/****************************************************** +* Type Definitions +******************************************************/ + +// RTOS thread priority +typedef enum +{ + CY_RTOS_PRIORITY_MIN = osPriorityNone, + CY_RTOS_PRIORITY_LOW = osPriorityLow, + CY_RTOS_PRIORITY_BELOWNORMAL = osPriorityBelowNormal, + CY_RTOS_PRIORITY_NORMAL = osPriorityNormal, + CY_RTOS_PRIORITY_ABOVENORMAL = osPriorityAboveNormal, + CY_RTOS_PRIORITY_HIGH = osPriorityHigh, + CY_RTOS_PRIORITY_REALTIME = osPriorityRealtime, + CY_RTOS_PRIORITY_MAX = osPriorityRealtime7 +} cy_thread_priority_t; + +typedef osThreadId_t cy_thread_t; /** CMSIS definition of a thread handle */ +typedef void* cy_thread_arg_t; /** Argument passed to the entry function of + a thread */ +typedef osMutexId_t cy_mutex_t; /** CMSIS definition of a mutex */ +typedef osSemaphoreId_t cy_semaphore_t; /** CMSIS definition of a semaphore */ +typedef osEventFlagsId_t cy_event_t; /** CMSIS definition of an event */ +typedef osMessageQueueId_t cy_queue_t; /** CMSIS definition of a message queue */ +typedef osTimerId_t cy_timer_t; /** CMSIS definition of a timer */ +typedef void* cy_timer_callback_arg_t; /** Argument passed to the timer callback + function */ +typedef uint32_t cy_time_t; /** Time in milliseconds */ +typedef osStatus_t cy_rtos_error_t; /** CMSIS definition of a error status */ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/abstraction-rtos/include/COMPONENT_THREADX/cyabs_rtos_impl.h b/abstraction-rtos/include/COMPONENT_THREADX/cyabs_rtos_impl.h new file mode 100644 index 00000000..a8381adb --- /dev/null +++ b/abstraction-rtos/include/COMPONENT_THREADX/cyabs_rtos_impl.h @@ -0,0 +1,96 @@ +/***********************************************************************************************//** + * \file cyabs_rtos_impl.h + * + * \brief + * Internal definitions for RTOS abstraction layer. + * + *************************************************************************************************** + * \copyright + * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#pragma once + +#include +#include + +#include "tx_api.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Constants +******************************************************/ +#define CY_RTOS_MIN_STACK_SIZE TX_MINIMUM_STACK /** Minimum stack size in bytes */ +#define CY_RTOS_ALIGNMENT 0x00000008UL /** Minimum alignment for RTOS objects */ +#define CY_RTOS_ALIGNMENT_MASK 0x00000007UL /** Checks for 8-byte alignment */ + + +/****************************************************** +* Type Definitions +******************************************************/ + +// RTOS thread priority +typedef enum +{ + CY_RTOS_PRIORITY_MIN = TX_MAX_PRIORITIES - 1, + CY_RTOS_PRIORITY_LOW = (TX_MAX_PRIORITIES * 6 / 7), + CY_RTOS_PRIORITY_BELOWNORMAL = (TX_MAX_PRIORITIES * 5 / 7), + CY_RTOS_PRIORITY_NORMAL = (TX_MAX_PRIORITIES * 4 / 7), + CY_RTOS_PRIORITY_ABOVENORMAL = (TX_MAX_PRIORITIES * 3 / 7), + CY_RTOS_PRIORITY_HIGH = (TX_MAX_PRIORITIES * 2 / 7), + CY_RTOS_PRIORITY_REALTIME = (TX_MAX_PRIORITIES * 1 / 7), + CY_RTOS_PRIORITY_MAX = 0 +} cy_thread_priority_t; + +typedef struct +{ + uint32_t maxcount; + TX_SEMAPHORE tx_semaphore; +} cy_semaphore_t; + +typedef struct +{ + ULONG* mem; + // ThreadX buffer size is a power of 2 times word size, + // this is used to prevent memory corruption when get message from queue. + size_t itemsize; + TX_QUEUE tx_queue; +} cy_queue_t; + +typedef struct +{ + bool oneshot; + TX_TIMER tx_timer; +} cy_timer_t; + +typedef TX_THREAD* cy_thread_t; +typedef ULONG cy_thread_arg_t; +typedef TX_MUTEX cy_mutex_t; +typedef TX_EVENT_FLAGS_GROUP cy_event_t; +typedef ULONG cy_timer_callback_arg_t; +typedef uint32_t cy_time_t; +typedef UINT cy_rtos_error_t; + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/abstraction-rtos/include/Template/cyabs_rtos_impl.h b/abstraction-rtos/include/Template/cyabs_rtos_impl.h new file mode 100644 index 00000000..2e5c4752 --- /dev/null +++ b/abstraction-rtos/include/Template/cyabs_rtos_impl.h @@ -0,0 +1,112 @@ +/***********************************************************************************************//** + * \file cyabs_rtos_impl.h + * + * \brief + * Template file for internal definitions for RTOS abstraction layer. + * Replace all TODO items with the proper values for the RTOS that is + * being wrapped. + * + *************************************************************************************************** + * \copyright + * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#pragma once + +/* + * Exclude template files except for documentation purposes. + * This should be removed when using the template to support a new RTOS. + */ +#if defined(DOXYGEN) + +// #include "TODO: RTOS HEADER" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \addtogroup group_abstraction_rtos_port RTOS Specific Types and Defines + * \ingroup group_abstraction_rtos_common + * \{ + * The following defines and types have values that are specific to each RTOS port. + * The define values are specific to each RTOS. The types are simple aliases that + * wrap RTOS specifc types. Code cannot assume anything about the values or internals + * of any types. + */ + +/****************************************************** +* Constants +******************************************************/ +// TODO: Replace these with proper values for the target RTOS +#define CY_RTOS_MIN_STACK_SIZE 300 /**< Minimum stack size */ +#define CY_RTOS_ALIGNMENT_MASK 0x00000007UL /**< Checks for 8-bit alignment */ + + +/****************************************************** +* Type Definitions +******************************************************/ + +// TODO: Replace all priority values with values specific to the RTOS +/** RTOS thread priority. + * Note: Depending on the RTOS and interrupt options for the device, some of these priorities may + * end up being the same priority level in practice. Even if this happens, the relative ordering + * of priorities is still maintained. eg: + * MAX >= REALTIME >= HIGH >= ABOVENORMAL >= NORMAL >= BELOWNORMAL >= LOW >= MIN + */ +typedef enum +{ + CY_RTOS_PRIORITY_MIN = 0, /**< Minumum allowable Thread priority */ + CY_RTOS_PRIORITY_LOW = 1, /**< A low priority Thread */ + CY_RTOS_PRIORITY_BELOWNORMAL = 2, /**< A slightly below normal Thread priority */ + CY_RTOS_PRIORITY_NORMAL = 3, /**< The normal Thread priority */ + CY_RTOS_PRIORITY_ABOVENORMAL = 4, /**< A slightly elevated Thread priority */ + CY_RTOS_PRIORITY_HIGH = 5, /**< A high priority Thread */ + CY_RTOS_PRIORITY_REALTIME = 6, /**< Realtime Thread priority */ + CY_RTOS_PRIORITY_MAX = 7 /**< Maximum allowable Thread priority */ +} cy_thread_priority_t; + +/** Alias for the RTOS specific definition of a thread handle */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_thread_t; +/** Alias for the RTOS specific argument passed to the entry function of a thread */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_thread_arg_t; +/** Alias for the RTOS specific definition of a mutex */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_mutex_t; +/** Alias for the RTOS specific definition of a semaphore */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_semaphore_t; +/** Alias for the RTOS specific definition of an event */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_event_t; +/** Alias for the RTOS specific definition of a message queue */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_queue_t; +/** Alias for the RTOS specific definition of a timer */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_timer_t; +/** Alias for the RTOS specific argument passed to the timer callback function */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_timer_callback_arg_t; +/** Alias for the RTOS specific time unit (in milliseconds) */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_time_t; +/** Alias for the RTOS specific definition of a error status */ +typedef void* /* TODO: Replace with RTOS specific type*/ cy_rtos_error_t; + +/** \} group_abstraction_rtos_port */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // defined(DOXYGEN) diff --git a/abstraction-rtos/include/cy_worker_thread.h b/abstraction-rtos/include/cy_worker_thread.h new file mode 100644 index 00000000..7a911d87 --- /dev/null +++ b/abstraction-rtos/include/cy_worker_thread.h @@ -0,0 +1,145 @@ +/***********************************************************************************************//** + * \file cy_worker_thread.h + * + * \brief + * Defines the interface for the worker thread utility. Provides prototypes for + * functions that allow creating/deleting worker threads and queueing work to + * a worker thread. + *************************************************************************************************** + * \copyright + * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "cy_result.h" +#include "cyabs_rtos.h" + +/** + * \addtogroup group_worker_thread_util Worker Thread Utility + * \{ + * Worker thread utility that allows functions to be run a different thread context. + * This utility can be used to delegate work that is not timing critical. For example, + * scheduling work in interrupt handlers to keep handler execution times low or if some + * work needs to be done at a different priority. + */ + +/**< Default worker thread name */ +#define CY_WORKER_THREAD_DEFAULT_NAME "CYWorker" +/** Default number of work items in the queue */ +#define CY_WORKER_DEFAULT_ENTRIES (16) + +/** Additional work cannot be enqueued because the worker thread has been terminated. + * This can occur if \ref cy_worker_thread_create was not called or \ref cy_worker_thread_delete was + * called before calling \ref cy_worker_thread_enqueue + */ +#define CY_WORKER_THREAD_ERR_THREAD_INVALID \ + CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 32) + +/** Worker thread function call prototype */ +typedef void (cy_worker_thread_func_t)(void* arg); + +/** Thread state enumeration */ +typedef enum +{ + CY_WORKER_THREAD_INVALID, /**< Worker Thread is in invalid state */ + CY_WORKER_THREAD_VALID, /**< Worker Thread is in valid state */ + CY_WORKER_THREAD_ENQUEUING, /**< Worker Thread is adding to the queue */ + CY_WORKER_THREAD_TERMINATING, /**< Worker Thread is starting to terminate */ + CY_WORKER_THREAD_JOIN_COMPLETE /**< Worker Thread join is complete */ +} cy_worker_thread_state_t; + +/** Worker Thread Parameters. */ +typedef struct +{ + cy_thread_priority_t priority; /**< Requested thread priority. */ + uint32_t stack_size; /**< Size of stack for new thread. + Note that this must be atleast CY_RTOS_MIN_STACK_SIZE */ + uint8_t* stack; /**< Pointer to stack. If this is NULL a stack of + size \ref stack_size will be allocated. */ + const char* name; /**< Thread name. If set to NULL, + \ref CY_WORKER_THREAD_DEFAULT_NAME will be used. */ + uint32_t num_entries; /**< Maximum number of enteries the worker thread can queue. + If set to 0, \ref CY_WORKER_DEFAULT_ENTRIES + will be used. */ +} cy_worker_thread_params_t; + +/** Worker Thread Information. */ +typedef struct +{ + cy_queue_t event_queue; /**< Event Queue for this thread */ + uint32_t enqueue_count; /**< Number of conccurent enqueue requests */ + cy_thread_t thread; /**< Thread object */ + cy_worker_thread_state_t state; /**< State of the worker thread */ +} cy_worker_thread_info_t; + +/** Create worker thread to handle running callbacks in a separate thread. + * + * @note Calling this function twice on the same thread object ( \ref cy_worker_thread_info_t) + * without + * calling \ref cy_worker_thread_delete will cause memory leakage. + * + * @param[out] new_worker pointer to cy_worker_thread_info_t structure to be filled when created. + * @param[in] params pointer to requested parameters for starting worker thread. + * + * @return The status of the worker thread creation request. + */ +cy_rslt_t cy_worker_thread_create(cy_worker_thread_info_t* new_worker, + const cy_worker_thread_params_t* params); + +/** Delete worker thread. + * + * @note This function will wait for the thread to complete all pending work in the + * queue and exit before returning. + * + * @param[in] old_worker pointer to cy_worker_thread_info_t structure to be deleted. + * + * @return The status of the deletion of the worker thread. + */ +cy_rslt_t cy_worker_thread_delete(cy_worker_thread_info_t* old_worker); + +/** Queue work on a worker thread. + * + * Call the given function in the worker thread context. + * + * @note If the thread priority is below that of the current thread, you must yield to allow + * the worker thread to run. This can be done by calling \ref cy_rtos_delay_milliseconds or + * by waiting on an RTOS object in all higher priority threads. + * + * @param[in] worker_info pointer to worker_thread used to run function + * @param[in] work_func function to run + * @param[in] arg opaque arg to be used in function call + * + * @return The status of the queueing of work. + */ +cy_rslt_t cy_worker_thread_enqueue(cy_worker_thread_info_t* worker_info, + cy_worker_thread_func_t* work_func, void* arg); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +/** \} group_abstraction_resource */ diff --git a/abstraction-rtos/include/cyabs_rtos.h b/abstraction-rtos/include/cyabs_rtos.h new file mode 100644 index 00000000..72a3eab4 --- /dev/null +++ b/abstraction-rtos/include/cyabs_rtos.h @@ -0,0 +1,779 @@ +/***********************************************************************************************//** + * \file cyabs_rtos.h + * + * \brief + * Defines the Cypress RTOS Interface. Provides prototypes for functions that + * allow Cypress libraries to use RTOS resources such as threads, mutexes & + * timing functions in an abstract way. The APIs are implemented in the Port + * Layer RTOS interface which is specific to the RTOS in use. + * + *************************************************************************************************** + * \copyright + * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#pragma once + +#include "cyabs_rtos_impl.h" +#include "cy_result.h" +#include +#include +#include + +/** + * \defgroup group_abstraction_rtos_common Common + * General types and defines for working with the RTOS abstraction layer. + * \defgroup group_abstraction_rtos_event Events + * APIs for acquiring and working with Events. + * \defgroup group_abstraction_rtos_mutex Mutex + * APIs for acquiring and working with Mutexes. + * \defgroup group_abstraction_rtos_queue Queue + * APIs for creating and working with Queues. + * \defgroup group_abstraction_rtos_semaphore Semaphore + * APIs for acquiring and working with Semaphores. + * \defgroup group_abstraction_rtos_threads Threads + * APIs for creating and working with Threads. + * \defgroup group_abstraction_rtos_time Time + * APIs for getting the current time and waiting. + * \defgroup group_abstraction_rtos_timer Timer + * APIs for creating and working with Timers. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/******************************************** CONSTANTS *******************************************/ + +/** + * \ingroup group_abstraction_rtos_common + * \{ + */ + +#if defined(DOXYGEN) +/** Return value indicating success */ +#define CY_RSLT_SUCCESS ((cy_rslt_t)0x00000000U) +#endif + +/** Used with RTOS calls that require a timeout. This implies the call will never timeout. */ +#define CY_RTOS_NEVER_TIMEOUT ( (uint32_t)0xffffffffUL ) + +// +// Note on error strategy. If the error is a normal part of operation (timeouts, full queues, empty +// queues), the these errors are listed here and the abstraction layer implementation must map from +// the underlying errors to these. If the errors are special cases, the the error \ref +// CY_RTOS_GENERAL_ERROR will be returned and \ref cy_rtos_last_error() can be used to retrieve the +// RTOS specific error message. +// +/** Requested operation did not complete in the specified time */ +#define CY_RTOS_TIMEOUT \ + CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 0) +/** The RTOS could not allocate memory for the specified operation */ +#define CY_RTOS_NO_MEMORY \ + CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 1) +/** An error occured in the RTOS */ +#define CY_RTOS_GENERAL_ERROR \ + CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 2) +/** A bad argument was passed into the APIs */ +#define CY_RTOS_BAD_PARAM \ + CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 5) +/** A memory alignment issue was detected. Ensure memory provided is aligned per \ref + CY_RTOS_ALIGNMENT_MASK */ +#define CY_RTOS_ALIGNMENT_ERROR \ + CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 6) + +/** \} group_abstraction_rtos_common */ + +/** + * \ingroup group_abstraction_rtos_queue + * \{ + */ + +/** The Queue is already full and can't accept any more items at this time */ +#define CY_RTOS_QUEUE_FULL \ + CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 3) +/** The Queue is empty and has nothing to remove */ +#define CY_RTOS_QUEUE_EMPTY \ + CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 4) + +/** \} group_abstraction_rtos_queue */ + +/********************************************* TYPES **********************************************/ + +/** + * The state a thread can be in + * + * \ingroup group_abstraction_rtos_threads + */ +typedef enum cy_thread_state +{ + CY_THREAD_STATE_INACTIVE, /**< thread has not started or was terminated but not yet joined */ + CY_THREAD_STATE_READY, /**< thread can run, but is not currently */ + CY_THREAD_STATE_RUNNING, /**< thread is currently running */ + CY_THREAD_STATE_BLOCKED, /**< thread is blocked waiting for something */ + CY_THREAD_STATE_TERMINATED, /**< thread has terminated but not freed */ + CY_THREAD_STATE_UNKNOWN /**< thread is in an unknown state */ +} cy_thread_state_t; + +/** + * The type of timer + * + * \ingroup group_abstraction_rtos_timer + */ +typedef enum cy_timer_trigger_type +{ + CY_TIMER_TYPE_PERIODIC, /**< called periodically until stopped */ + CY_TIMER_TYPE_ONCE, /**< called once only */ + cy_timer_type_periodic = CY_TIMER_TYPE_PERIODIC, /**< \deprecated replaced by \ref + CY_TIMER_TYPE_PERIODIC */ + cy_timer_type_once = CY_TIMER_TYPE_ONCE /**< \deprecated replaced by \ref + CY_TIMER_TYPE_ONCE */ +} cy_timer_trigger_type_t; + +/** + * The type of a function that is the entry point for a thread + * + * @param[in] arg the argument passed from the thread create call to the entry function + * + * \ingroup group_abstraction_rtos_threads + */ +typedef void (* cy_thread_entry_fn_t)(cy_thread_arg_t arg); + +/** + * The callback function to be called by a timer + * + * \ingroup group_abstraction_rtos_timer + */ +typedef void (* cy_timer_callback_t)(cy_timer_callback_arg_t arg); + +/** + * Return the last error from the RTOS. + * + * The functions in the RTOS abstraction layer adhere to the Infineon return + * results calling convention. The underlying RTOS implementations will not but rather + * will have their own error code conventions. This function is provided as a service + * to the developer, mostly for debugging, and returns the underlying RTOS error code + * from the last RTOS abstraction layer that returned \ref CY_RTOS_GENERAL_ERROR. + * + * @return RTOS specific error code. + * + * \ingroup group_abstraction_rtos_common + */ +cy_rtos_error_t cy_rtos_last_error(void); + + +/********************************************* Threads ********************************************/ + +/** + * \ingroup group_abstraction_rtos_threads + * \{ + */ + +/** Create a thread with specific thread argument. + * + * This function is called to startup a new thread. If the thread can exit, it must call + * \ref cy_rtos_exit_thread() just before doing so. All created threads that can terminate, either + * by themselves or forcefully by another thread MUST have \ref cy_rtos_join_thread() called on them + * by another thread in order to cleanup any resources that might have been allocated for them. + * + * @param[out] thread Pointer to a variable which will receive the new thread handle + * @param[in] entry_function Function pointer which points to the main function for the new thread + * @param[in] name String thread name used for a debugger + * @param[in] stack The buffer to use for the thread stack. This must be aligned to + * \ref CY_RTOS_ALIGNMENT_MASK with a size of at least \ref + * CY_RTOS_MIN_STACK_SIZE. + * If stack is null, cy_rtos_create_thread will allocate a stack from + * the heap. + * @param[in] stack_size The size of the thread stack in bytes + * @param[in] priority The priority of the thread. Values are operating system specific, + * but some common priority levels are defined: + * CY_THREAD_PRIORITY_LOW + * CY_THREAD_PRIORITY_NORMAL + * CY_THREAD_PRIORITY_HIGH + * @param[in] arg The argument to pass to the new thread + * + * @return The status of thread create request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_create_thread(cy_thread_t* thread, cy_thread_entry_fn_t entry_function, + const char* name, void* stack, uint32_t stack_size, + cy_thread_priority_t priority, cy_thread_arg_t arg); + +/** Exit the current thread. + * + * This function is called just before a thread exits. In some cases it is sufficient + * for a thread to just return to exit, but in other cases, the RTOS must be explicitly + * signaled. In cases where a return is sufficient, this should be a null funcition. + * where the RTOS must be signaled, this function should perform that In cases operation. + * In code using RTOS services, this function should be placed at any at any location + * where the main thread function will return, exiting the thread. Threads that can + * exit must still be joined (\ref cy_rtos_join_thread) to ensure their resources are + * fully cleaned up. + * + * @return The status of thread exit request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_exit_thread(void); + +/** Terminates another thread. + * + * This function is called to terminate another thread and reap the resources claimed + * by the thread. This should be called both when forcibly terminating another thread + * as well as any time a thread can exit on its own. For some RTOS implementations + * this is not required as the thread resources are claimed as soon as it exits. In + * other cases, this must be called to reclaim resources. Threads that are terminated + * must still be joined (\ref cy_rtos_join_thread) to ensure their resources are fully + * cleaned up. + * + * @param[in] thread Handle of the thread to terminate + * + * @returns The status of the thread terminate. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread); + +/** Waits for a thread to complete. + * + * This must be called on any thread that can complete to ensure that any resources that + * were allocated for it are cleaned up. + * + * @param[in] thread Handle of the thread to wait for + * + * @returns The status of thread join request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread); + +/** Checks if the thread is running + * + * This function is called to determine if a thread is actively running or not. For information on + * the thread state, use the \ref cy_rtos_get_thread_state() function. + * + * @param[in] thread Handle of the terminated thread to delete + * @param[out] running Returns true if the thread is running, otherwise false + * + * @returns The status of the thread running check. [\ref CY_RSLT_SUCCESS, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running); + +/** Gets the state the thread is currently in + * + * This function is called to determine if a thread is running/blocked/inactive/ready etc. + * + * @param[in] thread Handle of the terminated thread to delete + * @param[out] state Returns the state the thread is currently in + * + * @returns The status of the thread state check. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state); + +/** Get current thread handle + * + * Returns the unique thread handle of the current running thread. + * + * @param[out] thread Handle of the current running thread + * + * @returns The status of thread join request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread); + + +/** Suspend current thread until notification is received + * + * This function suspends the execution of current thread until it is notified + * by \ref cy_rtos_set_thread_notification from another thread or ISR, or timed out with + * specify timeout value + * + * @param[in] timeout_ms Maximum number of milliseconds to wait + * Use the \ref CY_RTOS_NEVER_TIMEOUT constant to wait forever. + * + * @returns The status of thread wait. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_TIMEOUT, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t timeout_ms); + + +/** Set the thread notification for a thread + * + * This function sets the thread notification for the target thread. + * The target thread waiting for the notification to be set will resume from suspended state. + * + * @param[in] thread Handle of the target thread + * @param[in] in_isr If true this is being called from within an ISR + * + * @returns The status of thread wait. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR, + * \ref CY_RTOS_BAD_PARAM] + */ +cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr); + + +/** \} group_abstraction_rtos_threads */ + + +/********************************************* Mutexes ********************************************/ + +/** + * \ingroup group_abstraction_rtos_mutex + * \{ + */ + +/** Create a recursive mutex. + * + * Creates a binary mutex which can be used for mutual exclusion to prevent simulatenous + * access of shared resources. Created mutexes can support priority inheritance if recursive. + * + * This function has been replaced by \ref cy_rtos_init_mutex2 which allow for specifying + * whether or not the mutex supports recursion or not. + * + * @param[out] mutex Pointer to the mutex handle to be initialized + * + * @return The status of mutex creation request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR] + */ +#define cy_rtos_init_mutex(mutex) cy_rtos_init_mutex2(mutex, true) + +/** Create a mutex which can support recursion or not. + * + * Creates a binary mutex which can be used for mutual exclusion to prevent simulatenous + * access of shared resources. Created mutexes can support priority inheritance if recursive. + * + * \note Not all RTOS implementations support non-recursive mutexes. In this case a recursive + * mutex will be created. + * + * @param[out] mutex Pointer to the mutex handle to be initialized + * @param[in] recursive Should the created mutex support recursion or not + * + * @return The status of mutex creation request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive); + +/** Get a mutex. + * + * If the mutex is available, it is acquired and this function returned. + * If the mutex is not available, the thread waits until the mutex is available + * or until the timeout occurs. + * + * @note This function must not be called from an interrupt context as it may block. + * + * @param[in] mutex Pointer to the mutex handle + * @param[in] timeout_ms Maximum number of milliseconds to wait while attempting to get + * the mutex. Use the \ref CY_RTOS_NEVER_TIMEOUT constant to wait forever. + * + * @return The status of the get mutex. Returns timeout if mutex was not acquired + * before timeout_ms period. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_TIMEOUT, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms); + +/** Set a mutex. + * + * The mutex is released allowing any other threads waiting on the mutex to + * obtain the semaphore. + * + * @param[in] mutex Pointer to the mutex handle + * + * @return The status of the set mutex request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + * + */ +cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex); + +/** Deletes a mutex. + * + * This function frees the resources associated with a sempahore. + * + * @param[in] mutex Pointer to the mutex handle + * + * @return The status to the delete request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex); + +/** \} group_abstraction_rtos_mutex */ + +/******************************************** Semaphores ******************************************/ + +/** + * \ingroup group_abstraction_rtos_semaphore + * \{ + */ + +/** + * Create a semaphore + * + * This is basically a counting semaphore. It can be used for synchronization between tasks and + * tasks and interrupts. + * + * @param[in,out] semaphore Pointer to the semaphore handle to be initialized + * @param[in] maxcount The maximum count for this semaphore + * @param[in] initcount The initial count for this semaphore + * + * @return The status of the semaphore creation. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount); + +/** + * Get/Acquire a semaphore + * + * If the semaphore count is zero, waits until the semaphore count is greater than zero. + * Once the semaphore count is greater than zero, this function decrements + * the count and return. It may also return if the timeout is exceeded. + * + * @param[in] semaphore Pointer to the semaphore handle + * @param[in] timeout_ms Maximum number of milliseconds to wait while attempting to get + * the semaphore. Use the \ref CY_RTOS_NEVER_TIMEOUT constant to wait + * forever. Must be zero if in_isr is true. + * @param[in] in_isr true if we are trying to get the semaphore from with an ISR + * @return The status of get semaphore operation [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_TIMEOUT, \ref + * CY_RTOS_NO_MEMORY, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, cy_time_t timeout_ms, bool in_isr); + +/** + * Set/Release a semaphore + * + * Increments the semaphore count, up to the maximum count for this semaphore. + * + * @param[in] semaphore Pointer to the semaphore handle + * @param[in] in_isr Value of true indicates calling from interrupt context + * Value of false indicates calling from normal thread context + * @return The status of set semaphore operation [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr); + +/** + * Get the count of a semaphore. + * + * Gets the number of available tokens on the semaphore. + * + * @param[in] semaphore Pointer to the semaphore handle + * @param[out] count Pointer to the return count + * @return The status of get semaphore count operation [\ref CY_RSLT_SUCCESS, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count); + +/** + * Deletes a semaphore + * + * This function frees the resources associated with a semaphore. + * + * @param[in] semaphore Pointer to the semaphore handle + * + * @return The status of semaphore deletion [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore); + +/** \} group_abstraction_rtos_semaphore */ + +/********************************************* Events ********************************************/ + +/** + * \ingroup group_abstraction_rtos_event + * \{ + */ + +/** Create an event. + * + * This is an event which can be used to signal a set of threads + * with a 32 bit data element. + * + * @param[in,out] event Pointer to the event handle to be initialized + * + * @return The status of the event initialization request. + * [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_init_event(cy_event_t* event); + +/** Set the event flag bits. + * + * This is an event which can be used to signal a set of threads + * with a 32 bit data element. Any threads waiting on this event are released + * + * @param[in] event Pointer to the event handle + * @param[in] bits The value of the 32 bit flags + * @param[in] in_isr If true, this is called from an ISR, otherwise from a thread + * + * @return The status of the set request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr); + +/** + * Clear the event flag bits + * + * This function clears bits in the event. + * + * @param[in] event Pointer to the event handle + * @param[in] bits Any bits set in this value, will be cleared in the event. + * @param[in] in_isr if true, this is called from an ISR, otherwise from a thread + * + * @return The status of the clear flags request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, + * \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr); + +/** Get the event bits. + * + * Returns the current bits for the event. + * + * @param[in] event Pointer to the event handle + * @param[out] bits pointer to receive the value of the event flags + * + * @return The status of the get request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits); + +/** Wait for the event and return bits. + * + * Waits for the event to be set and then returns the bits associated + * with the event, or waits for the given timeout period. + * @note This function returns if any bit in the set is set. + * + * @param[in] event Pointer to the event handle + * @param[in,out] bits pointer to receive the value of the event flags + * @param[in] clear if true, clear any bits set that cause the wait to return + * if false, do not clear bits + * @param[in] all if true, all bits in the initial bits value must be set to return + * if false, any one bit in the initial bits value must be set to return + * @param[in] timeout_ms The amount of time to wait in milliseconds + * + * @return The status of the wait for event request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, + * \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* bits, bool clear, bool all, + cy_time_t timeout_ms); + +/** Deinitialize a event. + * + * This function frees the resources associated with an event. + * + * @param[in] event Pointer to the event handle + * + * @return The status of the deletion request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_deinit_event(cy_event_t* event); + +/** \} group_abstraction_rtos_event */ + +/********************************************* Queues *********************************************/ + +/** + * \ingroup group_abstraction_rtos_queue + * \{ + */ + +/** Create a queue. + * + * This is a queue of data where entries are placed on the back of the queue + * and removed from the front of the queue. + * + * @param[out] queue Pointer to the queue handle + * @param[in] length The maximum length of the queue in items + * @param[in] itemsize The size of each item in the queue. + * + * @return The status of the init request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize); + +/** Put an item in a queue. + * + * This function puts an item in the queue. The item is copied + * into the queue using a memory copy and the data pointed to by item_ptr + * is no longer referenced once the call returns. + * + * @note If in_isr is true, timeout_ms must be zero. + * + * @param[in] queue Pointer to the queue handle + * @param[in] item_ptr Pointer to the item to place in the queue + * @param[in] timeout_ms The time to wait to place the item in the queue + * @param[in] in_isr If true this is being called from within and ISR + * + * @return The status of the put request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR, \ref CY_RTOS_QUEUE_FULL] + */ +cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeout_ms, + bool in_isr); + +/** Gets an item in a queue. + * + * This function gets an item from the queue. The item is copied + * out of the queue into the memory provide by item_ptr. This space must be + * large enough to hold a queue entry as defined when the queue was initialized. + * + * @note If in_isr is true, timeout_ms must be zero. + * + * @param[in] queue Pointer to the queue handle + * @param[in] item_ptr Pointer to the memory for the item from the queue + * @param[in] timeout_ms The time to wait to get an item from the queue + * @param[in] in_isr If true this is being called from within an ISR + * + * @return The status of the get request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref + * CY_RTOS_GENERAL_ERROR, \ref CY_RTOS_QUEUE_EMPTY] + */ +cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeout_ms, bool in_isr); + +/** Return the number of items in the queue. + * + * This function returns the number of items currently in the queue. + * + * @param[in] queue Pointer to the queue handle + * @param[out] num_waiting Pointer to the return count + * + * @return The status of the count request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting); + +/** Return the amount of empty space in the queue. + * + * This function returns the amount of empty space in the + * queue. For instance, if the queue was created with 10 entries max and there + * are currently 2 entries in the queue, this will return 8. + * + * @param[in] queue Pointer to the queue handle + * @param[out] num_spaces Pointer to the return count. + * + * @return The status of the space request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces); + +/** Reset the queue. + * + * This function sets the queue to empty. + * + * @param[in] queue pointer to the queue handle + * + * @return The status of the reset request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue); + +/** Deinitialize the queue handle. + * + * This function de-initializes the queue and returns all + * resources used by the queue. + * + * @param[in] queue Pointer to the queue handle + * + * @return The status of the deinit request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue); + +/** \} group_abstraction_rtos_queue */ + +/********************************************* Timers *********************************************/ + +/** + * \ingroup group_abstraction_rtos_timer + * \{ + */ + +/** Create a new timer. + * + * This function initializes a timer object. + * @note The timer is not active until start is called. + * @note The callback may be (likely will be) called from a different thread. + * + * @param[out] timer Pointer to the timer handle to initialize + * @param[in] type Type of timer (periodic or once) + * @param[in] fun The function + * @param[in] arg Argument to pass along to the callback function + * + * @return The status of the init request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_init_timer(cy_timer_t* timer, cy_timer_trigger_type_t type, + cy_timer_callback_t fun, cy_timer_callback_arg_t arg); + +/** Sends a request to start the timer. Depending on the priorities of threads in the system, + * it may be necessary for high priority items to wait before the timer actually starts running. + * + * @param[in] timer Pointer to the timer handle + * @param[in] num_ms The number of milliseconds to wait before the timer fires + * + * @return The status of the start request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms); + +/** Sends a request to stop the timer. Depending on the priorities of threads in the system, + * it may be necessary for high priority items to wait before the timer is actually stopped. + * + * @param[in] timer Pointer to the timer handle + * + * @return The status of the stop request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer); + +/** Returns state of a timer. + * + * @param[in] timer Pointer to the timer handle + * @param[out] state Return value for state, true if running, false otherwise + * + * @return The status of the is_running request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state); + +/** Deinit the timer. + * + * This function deinitializes the timer and frees all consumed resources. + * + * @param[in] timer Pointer to the timer handle + * + * @return The status of the deinit request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer); + +/** \} group_abstraction_rtos_timer */ + +/********************************************** Time **********************************************/ + +/** + * \ingroup group_abstraction_rtos_time + * \{ + */ + +/** Gets time in milliseconds since RTOS start. + * + * @note Since this is only 32 bits, it will roll over every 49 days, 17 hours, 2 mins, 47.296 + * seconds + * + * @param[out] tval Pointer to the struct to populate with the RTOS time + * + * @returns Time in milliseconds since the RTOS started. + */ +cy_rslt_t cy_rtos_get_time(cy_time_t* tval); + +/** Delay for a number of milliseconds. + * + * Processing of this function depends on the minimum sleep + * time resolution of the RTOS. The current thread should sleep for + * the longest period possible which is less than the delay required, + * then makes up the difference with a tight loop. + * + * @param[in] num_ms The number of milliseconds to delay for + * + * @return The status of the delay request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR] + */ +cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms); + +/** \} group_abstraction_rtos_time */ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/abstraction-rtos/include/cyabs_rtos_internal.h b/abstraction-rtos/include/cyabs_rtos_internal.h new file mode 100644 index 00000000..e1655cf1 --- /dev/null +++ b/abstraction-rtos/include/cyabs_rtos_internal.h @@ -0,0 +1,53 @@ +/***********************************************************************************************//** + * \file cyabs_rtos_internal.h + * + * \brief + * Internal interface used for RTOS abstraction utilities. + *************************************************************************************************** + * \copyright + * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** Checks to see if code is currently executing within an interrupt context. + * + * @return Boolean indicating whether this was executed from an interrupt context. + */ +static inline bool is_in_isr(void) +{ + #if defined(COMPONENT_CR4) // Can work for any Cortex-A & Cortex-R + uint32_t mode = __get_mode(); + return (mode == 0x11U /*FIQ*/) || (mode == 0x12U /*IRQ*/) || (mode == 0x13U /*SVC*/) || + (mode == 0x17U /*ABT*/) || (mode == 0x1BU /*UND*/); + #else // Cortex-M + return (__get_IPSR() != 0); + #endif +} + + +#if defined(__cplusplus) +} +#endif diff --git a/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_freertos_helpers.c b/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_freertos_helpers.c new file mode 100644 index 00000000..a1af9d17 --- /dev/null +++ b/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_freertos_helpers.c @@ -0,0 +1,225 @@ +/***********************************************************************************************//** + * \file cyabs_freertos_helpers.c + * + * \brief + * Provides implementations for functions required to enable static allocation and + * tickless mode in FreeRTOS. + * + *************************************************************************************************** + * \copyright + * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ +#include "FreeRTOS.h" +#include "task.h" +#include "cyabs_rtos.h" +#if defined(CY_USING_HAL) +#include "cyhal.h" +#endif + +// This is included to allow the user to control the idle task behavior via the configurator +// System->Power->RTOS->System Idle Power Mode setting. +#if defined(COMPONENT_BSP_DESIGN_MODUS) || defined(COMPONENT_CUSTOM_DESIGN_MODUS) +#include "cycfg.h" +#endif + +#define pdTICKS_TO_MS(xTicks) ( ( ( TickType_t ) ( xTicks ) * 1000u ) / configTICK_RATE_HZ ) + +#if defined(CY_USING_HAL) +static cyhal_lptimer_t* _timer = NULL; + +//-------------------------------------------------------------------------------------------------- +// cyabs_rtos_set_lptimer +//-------------------------------------------------------------------------------------------------- +void cyabs_rtos_set_lptimer(cyhal_lptimer_t* timer) +{ + _timer = timer; +} + + +//-------------------------------------------------------------------------------------------------- +// cyabs_rtos_get_lptimer +//-------------------------------------------------------------------------------------------------- +cyhal_lptimer_t* cyabs_rtos_get_lptimer(void) +{ + return _timer; +} + + +#endif //defined(CY_USING_HAL) + +// The following implementations were sourced from https://www.freertos.org/a00110.html + +//-------------------------------------------------------------------------------------------------- +// vApplicationGetIdleTaskMemory +// +// configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an implementation of +// vApplicationGetIdleTaskMemory() to provide the memory that is used by the Idle task. +//-------------------------------------------------------------------------------------------------- +__WEAK void vApplicationGetIdleTaskMemory(StaticTask_t** ppxIdleTaskTCBBuffer, + StackType_t** ppxIdleTaskStackBuffer, + uint32_t* pulIdleTaskStackSize) +{ + // If the buffers to be provided to the Idle task are declared inside this function then they + // must be declared static – otherwise they will be allocated on the stack and so not exists + // after this function exits. + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE]; + + // Pass out a pointer to the StaticTask_t structure in which the Idle task’s state will be + // stored. + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + // Pass out the array that will be used as the Idle task’s stack. + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + // Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. Note that, as the + // array is necessarily of type StackType_t, configMINIMAL_STACK_SIZE is specified in words, not + // bytes. + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + + +/*———————————————————–*/ + +//-------------------------------------------------------------------------------------------------- +// vApplicationGetTimerTaskMemory +// +// configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the application must +// provide an implementation of vApplicationGetTimerTaskMemory() to provide the memory that is used +// by the Timer service task. +//-------------------------------------------------------------------------------------------------- +__WEAK void vApplicationGetTimerTaskMemory(StaticTask_t** ppxTimerTaskTCBBuffer, + StackType_t** ppxTimerTaskStackBuffer, + uint32_t* pulTimerTaskStackSize) +{ + // If the buffers to be provided to the Timer task are declared inside this function then they + // must be declared static – otherwise they will be allocated on the stack and so not exists + // after this function exits. + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH]; + + // Pass out a pointer to the StaticTask_t structure in which the Timer task’s state will be + // stored. + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + // Pass out the array that will be used as the Timer task’s stack. + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + // Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. Note that, as the + // array is necessarily of type StackType_t, configTIMER_TASK_STACK_DEPTH is specified in words, + // not bytes. + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} + + +#if defined(CY_USING_HAL) && (configUSE_TICKLESS_IDLE != 0) +//-------------------------------------------------------------------------------------------------- +// vApplicationSleep +// +/** User defined tickless idle sleep function. + * + * Provides a implementation for portSUPPRESS_TICKS_AND_SLEEP macro that allows + * the device to attempt to deep-sleep for the idle time the kernel expects before + * the next task is ready. This function disables the system timer and enables low power + * timer that can operate in deep-sleep mode to wake the device from deep-sleep after + * expected idle time has elapsed. + * + * @param[in] xExpectedIdleTime Total number of tick periods before + * a task is due to be moved into the Ready state. + */ +//-------------------------------------------------------------------------------------------------- +__WEAK void vApplicationSleep(TickType_t xExpectedIdleTime) +{ + static cyhal_lptimer_t timer; + uint32_t actual_sleep_ms = 0; + + if (NULL == _timer) + { + cy_rslt_t result = cyhal_lptimer_init(&timer); + if (result == CY_RSLT_SUCCESS) + { + _timer = &timer; + } + else + { + CY_ASSERT(false); + } + } + + if (NULL != _timer) + { + /* Disable interrupts so that nothing can change the status of the RTOS while + * we try to go to sleep or deep-sleep. + */ + uint32_t status = cyhal_system_critical_section_enter(); + eSleepModeStatus sleep_status = eTaskConfirmSleepModeStatus(); + + if (sleep_status != eAbortSleep) + { + // By default, the device will deep-sleep in the idle task unless if the device + // configurator overrides the behaviour to sleep in the System->Power->RTOS->System + // Idle Power Mode setting. + bool deep_sleep = true; + #if defined (CY_CFG_PWR_SYS_IDLE_MODE) + // If the system needs to operate in active mode the tickless mode should not be used in + // FreeRTOS + CY_ASSERT(CY_CFG_PWR_SYS_IDLE_MODE != CY_CFG_PWR_MODE_ACTIVE); + deep_sleep = + ((CY_CFG_PWR_SYS_IDLE_MODE & CY_CFG_PWR_MODE_DEEPSLEEP) == + CY_CFG_PWR_MODE_DEEPSLEEP); + #endif + uint32_t sleep_ms = pdTICKS_TO_MS(xExpectedIdleTime); + cy_rslt_t result; + if (deep_sleep) + { + // Adjust the deep-sleep time by the sleep/wake latency if set. + #if defined(CY_CFG_PWR_DEEPSLEEP_LATENCY) + if (sleep_ms > CY_CFG_PWR_DEEPSLEEP_LATENCY) + { + sleep_ms -= CY_CFG_PWR_DEEPSLEEP_LATENCY; + result = cyhal_syspm_tickless_deepsleep(_timer, sleep_ms, &actual_sleep_ms); + } + else + { + result = CY_RTOS_TIMEOUT; + } + #else // defined(CY_CFG_PWR_DEEPSLEEP_LATENCY) + result = cyhal_syspm_tickless_deepsleep(_timer, sleep_ms, &actual_sleep_ms); + #endif // defined(CY_CFG_PWR_DEEPSLEEP_LATENCY) + } + else + { + result = cyhal_syspm_tickless_sleep(_timer, sleep_ms, &actual_sleep_ms); + } + + if (result == CY_RSLT_SUCCESS) + { + // If you hit this assert, the latency time (CY_CFG_PWR_DEEPSLEEP_LATENCY) should + // be increased. This can be set though the Device Configurator, or by manually + // defining the variable. + CY_ASSERT(actual_sleep_ms <= pdTICKS_TO_MS(xExpectedIdleTime)); + vTaskStepTick(pdMS_TO_TICKS(actual_sleep_ms)); + } + } + + cyhal_system_critical_section_exit(status); + } +} + + +#endif // defined(CY_USING_HAL) && (configUSE_TICKLESS_IDLE != 0) diff --git a/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_rtos_freertos.c b/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_rtos_freertos.c new file mode 100644 index 00000000..871bd1d5 --- /dev/null +++ b/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_rtos_freertos.c @@ -0,0 +1,1173 @@ +/***********************************************************************************************//** + * \file cyabs_rtos_freertos.c + * + * \brief + * Implementation for FreeRTOS abstraction + * + *************************************************************************************************** + * \copyright + * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "cyabs_rtos_internal.h" + +static const uint32_t TASK_IDENT = 0xABCDEF01U; +static cy_rtos_error_t last_error; + +typedef struct +{ + cy_timer_callback_t cb; + cy_timer_callback_arg_t arg; +} callback_data_t; + +// Wrapper function to convert FreeRTOS callback signature to match expectation +// for our cyabs_rtos abstraction API. +static void timer_callback(TimerHandle_t arg) +{ + callback_data_t* cb_arg = (callback_data_t*)pvTimerGetTimerID(arg); + if (NULL != cb_arg->cb) + { + cb_arg->cb(cb_arg->arg); + } +} + + +//================================================================================================== +// Error Converter +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_last_error +//-------------------------------------------------------------------------------------------------- +cy_rtos_error_t cy_rtos_last_error(void) +{ + return last_error; +} + + +//================================================================================================== +// Threads +//================================================================================================== + +typedef struct +{ + StaticTask_t task; + SemaphoreHandle_t sema; + uint32_t magic; + void* memptr; +} cy_task_wrapper_t; + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_create_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_create_thread(cy_thread_t* thread, cy_thread_entry_fn_t entry_function, + const char* name, void* stack, uint32_t stack_size, + cy_thread_priority_t priority, cy_thread_arg_t arg) +{ + cy_rslt_t status; + if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE)) + { + status = CY_RTOS_BAD_PARAM; + } + else if ((stack != NULL) && (0 != (((uint32_t)stack) & CY_RTOS_ALIGNMENT_MASK))) + { + status = CY_RTOS_ALIGNMENT_ERROR; + } + else + { + // If the user provides a stack, we need to allocate memory for the StaticTask_t. If we + // allocate memory we also need to clean it up. This is true when the task exits itself or + // when it is killed. In the case it is killed is fairly straight forward. In the case + // where it exits, we can't clean up any allocated memory since we can't free it before + // calling vTaskDelete() and vTaskDelete() never returns. Thus we need to do it in join. + // However, if the task exited itself it has also released any memory it allocated. Thus + // in order to be able to reliably free memory as part of join, we need to know that the + // data we are accessing (the StaticTask_t) has not been freed. We therefore need to always + // allocate that object ourselves. This means we also need to allocate the stack if the + // user did not provide one. + uint32_t offset = (stack == NULL) + ? (stack_size & ~CY_RTOS_ALIGNMENT_MASK) + : 0; + uint32_t size = offset + sizeof(cy_task_wrapper_t); + uint8_t* ident = (uint8_t*)pvPortMalloc(size); + + if (ident == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + StackType_t stack_size_rtos = + ((stack_size & ~CY_RTOS_ALIGNMENT_MASK) / sizeof(StackType_t)); + StackType_t* stack_rtos = (stack == NULL) + ? (StackType_t*)ident + : (StackType_t*)stack; + + cy_task_wrapper_t* wrapper = (cy_task_wrapper_t*)(ident + offset); + wrapper->sema = xSemaphoreCreateBinary(); + CY_ASSERT(wrapper->sema != NULL); + wrapper->magic = TASK_IDENT; + wrapper->memptr = ident; + CY_ASSERT(((uint32_t)wrapper & CY_RTOS_ALIGNMENT_MASK) == 0UL); + *thread = xTaskCreateStatic((TaskFunction_t)entry_function, name, stack_size_rtos, arg, + priority, stack_rtos, &(wrapper->task)); + CY_ASSERT(((void*)*thread == (void*)&(wrapper->task)) || (*thread == NULL)); + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_exit_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_exit_thread(void) +{ + TaskHandle_t handle = xTaskGetCurrentTaskHandle(); + // Ideally this would just call vTaskDelete(NULL); however FreeRTOS + // does not provide any way to know when the task is actually cleaned + // up. It will tell you that it has been deleted, but when delete is + // called from the thread itself it doesn't actually get deleted at + // that time. It just gets added to the list of items that will be + // deleted when the idle task runs, but there is no way of knowing + // that the idle task ran unless you add an application hook which is + // not something that can be done here. This means that + // cy_rtos_join_thread() has no way of knowing that it is actually + // save to cleanup memory. So, instad of deleting here, we use a + // semaphore to indicate that we can delete and then join waits on + // the semaphore. + + // This cast is ok because the handle internally represents the TCB that we created in the + // thread create function. + cy_task_wrapper_t* wrapper = ((cy_task_wrapper_t*)handle); + if (wrapper->magic == TASK_IDENT) + { + // This signals to the thread deleting the current thread that it it is safe to delete the + // current thread. + xSemaphoreGive(wrapper->sema); + } + else + { + CY_ASSERT(false); + } + + // This function is not expected to return and calling cy_rtos_join_thread will call vTaskDelete + // on this thread and clean up. + while (1) + { + #if defined(INCLUDE_vTaskSuspend) + vTaskSuspend(handle); + #else + vTaskDelay(10000); + #endif + } +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_terminate_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread) +{ + cy_rslt_t status; + if (thread == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + vTaskDelete(*thread); + // Check to see if we allocated the task and if so free it up. + cy_task_wrapper_t* wrapper = ((cy_task_wrapper_t*)*thread); + vTaskSuspendAll(); + if (wrapper->magic == TASK_IDENT) + { + wrapper->magic = 0; + vSemaphoreDelete(wrapper->sema); + vPortFree(wrapper->memptr); + } + xTaskResumeAll(); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_is_thread_running +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running) +{ + cy_rslt_t status; + if ((thread == NULL) || (running == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + eTaskState st = eTaskGetState(*thread); + *running = (st == eRunning); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_thread_state +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state) +{ + cy_rslt_t status; + if ((thread == NULL) || (state == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + eTaskState st = eTaskGetState(*thread); + switch (st) + { + case eSuspended: + *state = CY_THREAD_STATE_INACTIVE; + break; + + case eReady: + *state = CY_THREAD_STATE_READY; + break; + + case eRunning: + *state = CY_THREAD_STATE_RUNNING; + break; + + case eBlocked: + *state = CY_THREAD_STATE_BLOCKED; + break; + + case eDeleted: + *state = CY_THREAD_STATE_TERMINATED; + break; + + case eInvalid: + default: + *state = CY_THREAD_STATE_UNKNOWN; + break; + } + + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_join_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + if (thread == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + cy_task_wrapper_t* wrapper = ((cy_task_wrapper_t*)(*thread)); + // This makes sure that the thread to be deleted has completed. See cy_rtos_exit_thread() + // for description of why this is done. + if (wrapper->magic == TASK_IDENT) + { + xSemaphoreTake(wrapper->sema, portMAX_DELAY); + status = cy_rtos_terminate_thread(thread); + } + *thread = NULL; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_thread_handle +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + + if (thread == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *thread = xTaskGetCurrentTaskHandle(); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_wait_thread_notification +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t num_ms) +{ + uint32_t ret; + + ret = ulTaskNotifyTake(pdTRUE, (num_ms == CY_RTOS_NEVER_TIMEOUT) ? + portMAX_DELAY : pdMS_TO_TICKS(num_ms)); + if (0 != ret) + { + /* Received notify from another thread or ISR */ + return CY_RSLT_SUCCESS; + } + else + { + return CY_RTOS_TIMEOUT; + } +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_set_thread_notification +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr) +{ + cy_rslt_t status; + if (thread == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + if (in_isr) + { + BaseType_t taskWoken = pdFALSE; + /* No error checking as this function always returns pdPASS. */ + vTaskNotifyGiveFromISR(*thread, &taskWoken); + portEND_SWITCHING_ISR(taskWoken); + } + else + { + /* No error checking as this function always returns pdPASS. */ + xTaskNotifyGive(*thread); + } + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//================================================================================================== +// Mutexes +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_mutex2 +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive) +{ + cy_rslt_t status; + if (mutex == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + mutex->is_recursive = recursive; + mutex->mutex_handle = recursive + ? xSemaphoreCreateRecursiveMutex() + : xSemaphoreCreateMutex(); + if (mutex->mutex_handle == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_mutex +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms) +{ + cy_rslt_t status; + if (mutex == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + TickType_t ticks = pdMS_TO_TICKS(timeout_ms); + BaseType_t result = (mutex->is_recursive) + ? xSemaphoreTakeRecursive(mutex->mutex_handle, ticks) + : xSemaphoreTake(mutex->mutex_handle, ticks); + + status = (result == pdFALSE) + ? CY_RTOS_TIMEOUT + : CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_set_mutex +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex) +{ + cy_rslt_t status; + if (mutex == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t result = (mutex->is_recursive) + ? xSemaphoreGiveRecursive(mutex->mutex_handle) + : xSemaphoreGive(mutex->mutex_handle); + + status = (result == pdFALSE) + ? CY_RTOS_GENERAL_ERROR + : CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_mutex +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex) +{ + cy_rslt_t status; + if (mutex == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + vSemaphoreDelete(mutex->mutex_handle); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//================================================================================================== +// Semaphores +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount) +{ + cy_rslt_t status; + if (semaphore == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *semaphore = xSemaphoreCreateCounting(maxcount, initcount); + if (*semaphore == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, uint32_t timeout_ms, bool in_isr) +{ + cy_rslt_t status; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + // xSemaphoreTakeFromISR does not take timeout as a parameter + // since it cannot block. Hence we return an error if the user + // tries to set a timeout. + if ((semaphore == NULL) || (in_isr && (timeout_ms != 0))) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + TickType_t ticks = pdMS_TO_TICKS(timeout_ms); + status = CY_RSLT_SUCCESS; + + if (in_isr) + { + if (pdFALSE == xSemaphoreTakeFromISR(*semaphore, &xHigherPriorityTaskWoken)) + { + status = CY_RTOS_TIMEOUT; + } + } + else + { + if (pdFALSE == xSemaphoreTake(*semaphore, ticks)) + { + status = CY_RTOS_TIMEOUT; + } + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_set_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr) +{ + cy_rslt_t status; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + if (semaphore == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t ret; + + if (in_isr) + { + ret = xSemaphoreGiveFromISR(*semaphore, &xHigherPriorityTaskWoken); + #if configUSE_PREEMPTION == 1 + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + #endif + } + else + { + ret = xSemaphoreGive(*semaphore); + } + + if (ret == pdFALSE) + { + status = CY_RTOS_GENERAL_ERROR; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_count_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count) +{ + cy_rslt_t status; + if (semaphore == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *count = uxSemaphoreGetCount(*semaphore); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore) +{ + cy_rslt_t status; + if (semaphore == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + vSemaphoreDelete(*semaphore); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//================================================================================================== +// Events +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_event(cy_event_t* event) +{ + cy_rslt_t status; + if (event == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *event = xEventGroupCreate(); + if (*event == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_setbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr) +{ + cy_rslt_t status; + if (event == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t ret; + if (in_isr) + { + BaseType_t bt = pdFALSE; + ret = xEventGroupSetBitsFromISR(*event, bits, &bt); + } + else + { + ret = xEventGroupSetBits(*event, bits); + } + + if (ret == pdFALSE) + { + status = CY_RTOS_GENERAL_ERROR; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_clearbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr) +{ + cy_rslt_t status; + if (event == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t ret; + if (in_isr) + { + ret = xEventGroupClearBitsFromISR(*event, bits); + } + else + { + ret = xEventGroupClearBits(*event, bits); + } + + if (ret == pdFALSE) + { + status = CY_RTOS_GENERAL_ERROR; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_getbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits) +{ + cy_rslt_t status; + if ((event == NULL) || (bits == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *bits = xEventGroupGetBits(*event); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_waitbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* waitfor, bool clear, bool allset, + cy_time_t timeout) +{ + cy_rslt_t status; + if ((event == NULL) || (waitfor == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + TickType_t ticks = pdMS_TO_TICKS(timeout); + uint32_t bits = *waitfor; + + *waitfor = xEventGroupWaitBits(*event, bits, clear, allset, ticks); + status = (((bits & *waitfor) == bits) || (((bits & *waitfor) > 0) & !allset)) + ? CY_RSLT_SUCCESS + : CY_RTOS_TIMEOUT; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_event(cy_event_t* event) +{ + cy_rslt_t status; + if (event == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + vEventGroupDelete(*event); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//================================================================================================== +// Queues +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize) +{ + cy_rslt_t status; + if (queue == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *queue = xQueueCreate(length, itemsize); + if (*queue == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_put_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeoutms, + bool in_isr) +{ + cy_rslt_t status; + if ((queue == NULL) || (item_ptr == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t ret; + if (in_isr) + { + ret = xQueueSendToBackFromISR(*queue, item_ptr, NULL); + } + else + { + TickType_t ticks = pdMS_TO_TICKS(timeoutms); + ret = xQueueSendToBack(*queue, item_ptr, ticks); + } + + if (ret == pdFALSE) + { + status = CY_RTOS_GENERAL_ERROR; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeoutms, bool in_isr) +{ + cy_rslt_t status; + if ((queue == NULL) || (item_ptr == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t ret; + if (in_isr) + { + ret = xQueueReceiveFromISR(*queue, item_ptr, NULL); + } + else + { + TickType_t ticks = pdMS_TO_TICKS(timeoutms); + ret = xQueueReceive(*queue, item_ptr, ticks); + } + + if (ret == pdFALSE) + { + status = CY_RTOS_GENERAL_ERROR; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_count_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting) +{ + cy_rslt_t status; + if ((queue == NULL) || (num_waiting == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *num_waiting = is_in_isr() + ? uxQueueMessagesWaitingFromISR(*queue) + : uxQueueMessagesWaiting(*queue); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_space_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces) +{ + cy_rslt_t status; + if ((queue == NULL) || (num_spaces == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *num_spaces = uxQueueSpacesAvailable(*queue); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_reset_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue) +{ + cy_rslt_t status; + if (queue == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t ret = xQueueReset(*queue); + + if (ret == pdFALSE) + { + status = CY_RTOS_GENERAL_ERROR; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue) +{ + cy_rslt_t status; + if (queue == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + vQueueDelete(*queue); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//================================================================================================== +// Timers +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_timer(cy_timer_t* timer, cy_timer_trigger_type_t type, + cy_timer_callback_t fun, cy_timer_callback_arg_t arg) +{ + cy_rslt_t status; + if ((timer == NULL) || (fun == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t reload = (type == CY_TIMER_TYPE_PERIODIC) ? pdTRUE : pdFALSE; + + // Create a wrapper callback to make sure to call fun() with arg as opposed + // to providing the timer reference as FreeRTOS does by default. + callback_data_t* cb_arg = (callback_data_t*)malloc(sizeof(callback_data_t)); + if (NULL == cb_arg) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + cb_arg->cb = fun; + cb_arg->arg = arg; + + *timer = xTimerCreate("", 1, reload, cb_arg, &timer_callback); + + if (*timer == NULL) + { + free(cb_arg); + status = CY_RTOS_NO_MEMORY; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_start_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms) +{ + cy_rslt_t status; + if (timer == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + TickType_t ticks = pdMS_TO_TICKS(num_ms); + BaseType_t ret = xTimerChangePeriod(*timer, ticks, 0); + + if (ret == pdPASS) + { + ret = xTimerStart(*timer, 0); + } + + if (ret == pdFALSE) + { + status = CY_RTOS_GENERAL_ERROR; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_stop_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer) +{ + cy_rslt_t status; + if (timer == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t ret = xTimerStop(*timer, 0); + + if (ret == pdFALSE) + { + status = CY_RTOS_GENERAL_ERROR; + } + else + { + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_is_running_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state) +{ + cy_rslt_t status; + if ((timer == NULL) || (state == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + BaseType_t active = xTimerIsTimerActive(*timer); + *state = (active != pdFALSE); + + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer) +{ + cy_rslt_t status; + if (timer == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + void* cb = pvTimerGetTimerID(*timer); + BaseType_t ret = xTimerDelete(*timer, 0); + + if (ret == pdFALSE) + { + status = CY_RTOS_GENERAL_ERROR; + } + else + { + free(cb); + status = CY_RSLT_SUCCESS; + } + } + return status; +} + + +//================================================================================================== +// Time +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_time +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_time(cy_time_t* tval) +{ + cy_rslt_t status; + if (tval == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *tval = (cy_time_t)((xTaskGetTickCount() * 1000LL) / configTICK_RATE_HZ); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_delay_milliseconds +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_delay_milliseconds(uint32_t num_ms) +{ + vTaskDelay(pdMS_TO_TICKS(num_ms)); + return CY_RSLT_SUCCESS; +} diff --git a/abstraction-rtos/source/COMPONENT_RTX/cyabs_rtos_rtxv5.c b/abstraction-rtos/source/COMPONENT_RTX/cyabs_rtos_rtxv5.c new file mode 100644 index 00000000..86edbda3 --- /dev/null +++ b/abstraction-rtos/source/COMPONENT_RTX/cyabs_rtos_rtxv5.c @@ -0,0 +1,1196 @@ +/***********************************************************************************************//** + * \file cyabs_rtos_rtxv5.c + * + * \brief + * Implementation for CMSIS RTOS v2 abstraction + * + *************************************************************************************************** + * \copyright + * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#define CY_RTOS_THREAD_FLAG 0x01 + +/****************************************************** +* Error Converter +******************************************************/ + +// Last received error status +static cy_rtos_error_t dbgErr; + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_last_error +//-------------------------------------------------------------------------------------------------- +cy_rtos_error_t cy_rtos_last_error(void) +{ + return dbgErr; +} + + +//-------------------------------------------------------------------------------------------------- +// error_converter +// +// Converts internal error type to external error type +//-------------------------------------------------------------------------------------------------- +static cy_rslt_t error_converter(cy_rtos_error_t internalError) +{ + cy_rslt_t value; + + switch (internalError) + { + case osOK: + value = CY_RSLT_SUCCESS; + break; + + case osErrorTimeout: + value = CY_RTOS_TIMEOUT; + break; + + case osErrorParameter: + value = CY_RTOS_BAD_PARAM; + break; + + case osErrorNoMemory: + value = CY_RTOS_NO_MEMORY; + break; + + case osError: + case osErrorResource: + case osErrorISR: + default: + value = CY_RTOS_GENERAL_ERROR; + break; + } + + // Update the last known error status + dbgErr = internalError; + return value; +} + + +//-------------------------------------------------------------------------------------------------- +// convert_ms_to_ticks +//-------------------------------------------------------------------------------------------------- +static uint32_t convert_ms_to_ticks(cy_time_t timeout_ms) +{ + if (timeout_ms == CY_RTOS_NEVER_TIMEOUT) + { + return osWaitForever; + } + else if (timeout_ms == 0) + { + return 0; + } + else + { + // Get number of ticks per second + uint32_t tick_freq = osKernelGetTickFreq(); + uint32_t ticks = (uint32_t)(((uint64_t)timeout_ms * tick_freq) / 1000); + + if (ticks == 0) + { + ticks = 1; + } + else if (ticks >= UINT32_MAX) + { + // if ticks if more than 32 bits, change ticks to max possible value that isn't + // osWaitForever. + ticks = UINT32_MAX - 1; + } + return ticks; + } +} + + +/****************************************************** +* Threads +******************************************************/ + +cy_rslt_t cy_rtos_create_thread(cy_thread_t* thread, cy_thread_entry_fn_t entry_function, + const char* name, void* stack, uint32_t stack_size, + cy_thread_priority_t priority, cy_thread_arg_t arg) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + osThreadAttr_t attr; + + if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE)) + { + status = CY_RTOS_BAD_PARAM; + } + else if ((stack != NULL) && (0 != (((uint32_t)stack) & CY_RTOS_ALIGNMENT_MASK))) + { + status = CY_RTOS_ALIGNMENT_ERROR; + } + else + { + attr.name = name; + attr.attr_bits = osThreadJoinable; + attr.cb_size = osRtxThreadCbSize; + attr.stack_size = stack_size; + attr.priority = (osPriority_t)priority; + attr.tz_module = 0; + attr.reserved = 0; + + // Allocate stack if NULL was passed + if ((uint32_t*)stack == NULL) + { + // Note: 1 malloc so that it can be freed with 1 call when terminating + uint32_t cb_mem_pad = (~osRtxThreadCbSize + 1) & CY_RTOS_ALIGNMENT_MASK; + attr.cb_mem = malloc(osRtxThreadCbSize + cb_mem_pad + stack_size); + if (attr.cb_mem != NULL) + { + attr.stack_mem = + (uint32_t*)((uint32_t)attr.cb_mem + osRtxThreadCbSize + cb_mem_pad); + } + } + else + { + attr.cb_mem = malloc(osRtxThreadCbSize); + attr.stack_mem = stack; + } + + if (attr.cb_mem == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); + CY_ASSERT(((uint32_t)attr.stack_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); + *thread = osThreadNew((osThreadFunc_t)entry_function, arg, &attr); + CY_ASSERT((*thread == attr.cb_mem) || (*thread == NULL)); + status = (*thread == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_exit_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_exit_thread(void) +{ + // This does not have a return statement because the osThreadExit() function * does not return + // so the return statement would be unreachable and causes a * warning for IAR compiler. + osThreadExit(); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_terminate_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (thread == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osThreadTerminate(*thread); + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_is_thread_running +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + + if ((thread == NULL) || (running == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *running = (osThreadGetState(*thread) == osThreadRunning) ? true : false; + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_thread_state +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + + if ((thread == NULL) || (state == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + switch (osThreadGetState(*thread)) + { + case osThreadInactive: + *state = CY_THREAD_STATE_INACTIVE; + break; + + case osThreadReady: + *state = CY_THREAD_STATE_READY; + break; + + case osThreadRunning: + *state = CY_THREAD_STATE_RUNNING; + break; + + case osThreadBlocked: + *state = CY_THREAD_STATE_BLOCKED; + break; + + case osThreadTerminated: + *state = CY_THREAD_STATE_TERMINATED; + break; + + case osThreadError: + case osThreadReserved: + default: + *state = CY_THREAD_STATE_UNKNOWN; + break; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_join_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (thread == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osThreadJoin(*thread); + status = error_converter(statusInternal); + + if (status == CY_RSLT_SUCCESS) + { + free(*thread); + *thread = NULL; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_thread_handle +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + + if (thread == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *thread = osThreadGetId(); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_wait_thread_notification +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t timeout_ms) +{ + uint32_t ret; + cy_rslt_t status = CY_RSLT_SUCCESS; + ret = osThreadFlagsWait(CY_RTOS_THREAD_FLAG, osFlagsWaitAll, convert_ms_to_ticks(timeout_ms)); + if (ret & osFlagsError) + { + status = (ret == osFlagsErrorTimeout) ? CY_RTOS_TIMEOUT : CY_RTOS_GENERAL_ERROR; + // Update the last known error status + dbgErr = (cy_rtos_error_t)ret; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_set_thread_notification +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + uint32_t ret; + + (void)in_isr; + if (thread == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + /* According to the description of CMSIS-RTOS v2 + * osThreadFlagsSet() can be called inside ISR + */ + ret = osThreadFlagsSet(*thread, CY_RTOS_THREAD_FLAG); + if (ret & osFlagsError) + { + status = CY_RTOS_GENERAL_ERROR; + // Update the last known error status + dbgErr = (cy_rtos_error_t)ret; + } + } + return status; +} + + +/****************************************************** +* Mutexes +******************************************************/ + +cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive) +{ + cy_rslt_t status; + osMutexAttr_t attr; + + if (mutex == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + attr.name = NULL; + attr.attr_bits = osMutexPrioInherit; + if (recursive) + { + attr.attr_bits |= osMutexRecursive; + } + attr.cb_mem = malloc(osRtxMutexCbSize); + attr.cb_size = osRtxMutexCbSize; + + if (attr.cb_mem == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); + *mutex = osMutexNew(&attr); + CY_ASSERT((*mutex == attr.cb_mem) || (*mutex == NULL)); + status = (*mutex == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_mutex +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (mutex == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osMutexAcquire(*mutex, timeout_ms); + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_set_mutex +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (mutex == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osMutexRelease(*mutex); + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_mutex +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (mutex == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osMutexDelete(*mutex); + status = error_converter(statusInternal); + + if (status == CY_RSLT_SUCCESS) + { + free(*mutex); + *mutex = NULL; + } + } + + return status; +} + + +/****************************************************** +* Semaphores +******************************************************/ + +cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount) +{ + cy_rslt_t status; + osSemaphoreAttr_t attr; + + if (semaphore == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + attr.name = NULL; + attr.attr_bits = 0U; + attr.cb_mem = malloc(osRtxSemaphoreCbSize); + attr.cb_size = osRtxSemaphoreCbSize; + + if (attr.cb_mem == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); + *semaphore = osSemaphoreNew(maxcount, initcount, &attr); + CY_ASSERT((*semaphore == attr.cb_mem) || (*semaphore == NULL)); + status = (*semaphore == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, cy_time_t timeout_ms, bool in_isr) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + cy_rtos_error_t statusInternal; + + // Based on documentation when osSemaphoreAcquire is called from ISR timeout must be zero. + // https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b + if ((semaphore == NULL) || (in_isr && (timeout_ms != 0))) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osSemaphoreAcquire(*semaphore, timeout_ms); + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_set_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + cy_rtos_error_t statusInternal; + (void)in_isr; // Unused parameter in this implementation + + if (semaphore == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osSemaphoreRelease(*semaphore); + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_count_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count) +{ + cy_rslt_t status; + if ((semaphore == NULL) || (count == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *count = osSemaphoreGetCount(*semaphore); + status = CY_RSLT_SUCCESS; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (semaphore == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osSemaphoreDelete(*semaphore); + status = error_converter(statusInternal); + if (status == CY_RSLT_SUCCESS) + { + free(*semaphore); + *semaphore = NULL; + } + } + + return status; +} + + +/****************************************************** +* Events +******************************************************/ + +#define CY_RTOS_EVENT_ERRORFLAG 0x80000000UL +#define CY_RTOS_EVENT_FLAGS 0x7FFFFFFFUL + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_event(cy_event_t* event) +{ + cy_rslt_t status; + osEventFlagsAttr_t attr; + + if (event == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + attr.name = NULL; + attr.attr_bits = 0U; + attr.cb_mem = malloc(osRtxEventFlagsCbSize); + attr.cb_size = osRtxEventFlagsCbSize; + + if (attr.cb_mem == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); + *event = osEventFlagsNew(&attr); + CY_ASSERT((*event == attr.cb_mem) || (*event == NULL)); + status = (*event == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_setbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + cy_rtos_error_t statusInternal; + (void)in_isr; // Unused parameter in this implementation + + if (event == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = (osStatus_t)osEventFlagsSet(*event, bits); + if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) != 0UL) + { + status = error_converter(statusInternal); + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_clearbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + cy_rtos_error_t statusInternal; + (void)in_isr; // Unused parameter in this implementation + + if (event == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = (osStatus_t)osEventFlagsClear(*event, bits); + if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) != 0UL) + { + status = error_converter(statusInternal); + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_getbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + + if ((event == NULL) || (bits == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *bits = osEventFlagsGet(*event); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_waitbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* bits, bool clear, bool all, + cy_time_t timeout) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + cy_rtos_error_t statusInternal; + uint32_t flagOption; + + if ((event == NULL) || (bits == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + flagOption = (all) ? osFlagsWaitAll : osFlagsWaitAny; + if (!clear) + { + flagOption |= osFlagsNoClear; + } + + statusInternal = (osStatus_t)osEventFlagsWait(*event, *bits, flagOption, timeout); + if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) == 0UL) + { + *bits = statusInternal; + } + else + { + status = error_converter(statusInternal); + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_event(cy_event_t* event) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (event == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osEventFlagsDelete(*event); + status = error_converter(statusInternal); + if (status == CY_RSLT_SUCCESS) + { + free(*event); + *event = NULL; + } + } + + return status; +} + + +/****************************************************** +* Queues +******************************************************/ + +cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize) +{ + cy_rslt_t status; + osMessageQueueAttr_t attr; + + if (queue == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + attr.name = NULL; + attr.attr_bits = 0U; + attr.cb_size = osRtxMessageQueueCbSize; + uint32_t blockSize = ((itemsize + 3U) & ~3UL) + sizeof(osRtxMessage_t); + attr.mq_size = blockSize * length; + + // Note: 1 malloc for both so that they can be freed with 1 call + uint32_t cb_mem_pad = (8 - (osRtxMessageQueueCbSize & 0x07)) & 0x07; + attr.cb_mem = malloc(osRtxMessageQueueCbSize + cb_mem_pad + attr.mq_size); + if (attr.cb_mem != NULL) + { + attr.mq_mem = (uint32_t*)((uint32_t)attr.cb_mem + osRtxMessageQueueCbSize + cb_mem_pad); + } + + if (attr.cb_mem == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); + CY_ASSERT(((uint32_t)attr.mq_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); + *queue = osMessageQueueNew(length, itemsize, &attr); + CY_ASSERT((*queue == attr.cb_mem) || (*queue == NULL)); + status = (*queue == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_put_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeout_ms, + bool in_isr) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if ((queue == NULL) || (item_ptr == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + // Not allowed to be called in ISR if timeout != 0 + if ((!in_isr) || (in_isr && (timeout_ms == 0U))) + { + statusInternal = osMessageQueuePut(*queue, (uint8_t*)item_ptr, 0u, timeout_ms); + } + else + { + statusInternal = osErrorISR; + } + + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeout_ms, bool in_isr) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if ((queue == NULL) || (item_ptr == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + // Not allowed to be called in ISR if timeout != 0 + if ((!in_isr) || (in_isr && (timeout_ms == 0U))) + { + statusInternal = osMessageQueueGet(*queue, (uint8_t*)item_ptr, 0u, timeout_ms); + } + else + { + statusInternal = osErrorISR; + } + + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_count_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + + if ((queue == NULL) || (num_waiting == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *num_waiting = osMessageQueueGetCount(*queue); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_space_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + + if ((queue == NULL) || (num_spaces == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *num_spaces = osMessageQueueGetSpace(*queue); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_reset_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (queue == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osMessageQueueReset(*queue); + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (queue == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osMessageQueueDelete(*queue); + status = error_converter(statusInternal); + + if (status == CY_RSLT_SUCCESS) + { + free(*queue); + *queue = NULL; + } + } + + return status; +} + + +/****************************************************** +* Timers +******************************************************/ + +cy_rslt_t cy_rtos_init_timer(cy_timer_t* timer, cy_timer_trigger_type_t type, + cy_timer_callback_t fun, cy_timer_callback_arg_t arg) +{ + cy_rslt_t status; + osTimerAttr_t attr; + + if (timer == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + attr.name = NULL; + attr.attr_bits = 0U; + attr.cb_mem = malloc(osRtxTimerCbSize); + attr.cb_size = osRtxTimerCbSize; + + if (attr.cb_mem == NULL) + { + status = CY_RTOS_NO_MEMORY; + } + else + { + osTimerType_t osTriggerType = (CY_TIMER_TYPE_PERIODIC == type) + ? osTimerPeriodic + : osTimerOnce; + + CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL); + *timer = osTimerNew((osTimerFunc_t)fun, osTriggerType, (void*)arg, &attr); + CY_ASSERT((*timer == attr.cb_mem) || (*timer == NULL)); + status = (*timer == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_start_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (timer == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osTimerStart(*timer, convert_ms_to_ticks(num_ms)); + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_stop_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (timer == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osTimerStop(*timer); + status = error_converter(statusInternal); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_is_running_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + + if ((timer == NULL) || (state == NULL)) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + *state = osTimerIsRunning(*timer); + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + if (timer == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + statusInternal = osTimerDelete(*timer); + status = error_converter(statusInternal); + + if (status == CY_RSLT_SUCCESS) + { + free(*timer); + *timer = NULL; + } + } + + return status; +} + + +/****************************************************** +* Time +******************************************************/ + +cy_rslt_t cy_rtos_get_time(cy_time_t* tval) +{ + cy_rslt_t status = CY_RSLT_SUCCESS; + uint32_t tick_freq; + + if (tval == NULL) + { + status = CY_RTOS_BAD_PARAM; + } + else + { + // Get Number of ticks per second + tick_freq = osKernelGetTickFreq(); + + // Convert ticks count to time in milliseconds + if (tick_freq != 0) + { + *tval = (cy_time_t)((osKernelGetTickCount() * 1000LL) / tick_freq); + } + else + { + status = CY_RTOS_GENERAL_ERROR; + } + } + + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_delay_milliseconds +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms) +{ + cy_rslt_t status; + cy_rtos_error_t statusInternal; + + statusInternal = osDelay(num_ms); + status = error_converter(statusInternal); + + return status; +} + + +#if defined(__cplusplus) +} +#endif diff --git a/abstraction-rtos/source/COMPONENT_THREADX/cyabs_rtos_threadx.c b/abstraction-rtos/source/COMPONENT_THREADX/cyabs_rtos_threadx.c new file mode 100644 index 00000000..001e9b67 --- /dev/null +++ b/abstraction-rtos/source/COMPONENT_THREADX/cyabs_rtos_threadx.c @@ -0,0 +1,967 @@ +/***********************************************************************************************//** + * \file cyabs_rtos_threadx.c + * + * \brief + * Implementation for ThreadX abstraction + * + *************************************************************************************************** + * \copyright + * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#include +#include +#include +#include +#include + +static const uint32_t WRAPPER_IDENT = 0xABCDEF01U; +static const uint32_t MAX_QUEUE_MESSAGE_SIZE = 16; +#define ALL_EVENT_FLAGS (0xFFFFFFFFU) +#define MILLISECONDS_PER_SECOND (1000) + +static cy_rtos_error_t last_error; + + +//-------------------------------------------------------------------------------------------------- +// convert_ms_to_ticks +//-------------------------------------------------------------------------------------------------- +static cy_time_t convert_ms_to_ticks(cy_time_t timeout_ms) +{ + if (timeout_ms == CY_RTOS_NEVER_TIMEOUT) + { + return TX_WAIT_FOREVER; + } + else if (timeout_ms == 0) + { + return 0; + } + else + { + uint64_t ticks = (uint64_t)timeout_ms * (uint64_t)TX_TIMER_TICKS_PER_SECOND / + (uint64_t)MILLISECONDS_PER_SECOND; + if (ticks == 0) + { + ticks = 1; + } + else if (ticks >= UINT32_MAX) + { + // if ticks if more than 32 bits, change ticks to max possible value that isn't + // TX_WAIT_FOREVER. + ticks = UINT32_MAX - 1; + } + return (cy_time_t)ticks; + } +} + + +//-------------------------------------------------------------------------------------------------- +// convert_ticks_to_ms +//-------------------------------------------------------------------------------------------------- +static inline cy_time_t convert_ticks_to_ms(cy_time_t timeout_ticks) +{ + return (cy_time_t)((uint64_t)timeout_ticks * (uint64_t)MILLISECONDS_PER_SECOND / + (uint64_t)TX_TIMER_TICKS_PER_SECOND); +} + + +//-------------------------------------------------------------------------------------------------- +// convert_error +//-------------------------------------------------------------------------------------------------- +static inline cy_rslt_t convert_error(cy_rtos_error_t error) +{ + if (error != TX_SUCCESS) + { + last_error = error; + return CY_RTOS_GENERAL_ERROR; + } + return CY_RSLT_SUCCESS; +} + + +/****************************************************** +* Last Error +******************************************************/ + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_last_error +//-------------------------------------------------------------------------------------------------- +cy_rtos_error_t cy_rtos_last_error(void) +{ + return last_error; +} + + +/****************************************************** +* Threads +******************************************************/ + +typedef struct +{ + TX_THREAD thread; + uint32_t magic; + void* memptr; +} cy_thread_wrapper_t; + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_create_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_create_thread(cy_thread_t* thread, cy_thread_entry_fn_t entry_function, + const char* name, void* stack, uint32_t stack_size, + cy_thread_priority_t priority, cy_thread_arg_t arg) +{ + stack_size &= ~CY_RTOS_ALIGNMENT_MASK; // make stack pointer 8-byte aligned + if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE)) + { + return CY_RTOS_BAD_PARAM; + } + + if ((stack != NULL) && (0 != (((uint32_t)stack) & CY_RTOS_ALIGNMENT_MASK))) + { + return CY_RTOS_ALIGNMENT_ERROR; + } + + size_t malloc_size = sizeof(cy_thread_wrapper_t); + if (stack == NULL) + { + malloc_size += stack_size; + } + void* buffer = malloc(malloc_size); + if (buffer == NULL) + { + return CY_RTOS_NO_MEMORY; + } + + cy_thread_wrapper_t* wrapper_ptr; + if (stack == NULL) + { + stack = buffer; + // Have stack be in front of wrapper since stack size is 8-byte aligned. + wrapper_ptr = (cy_thread_wrapper_t*)(buffer + stack_size); + wrapper_ptr->memptr = stack; + } + else + { + wrapper_ptr = buffer; + wrapper_ptr->memptr = NULL; + } + wrapper_ptr->magic = WRAPPER_IDENT; + + *thread = (cy_thread_t)wrapper_ptr; + + // Disable preemption-thresholding and time slicing + cy_rtos_error_t tx_rslt = tx_thread_create(*thread, (CHAR*)name, entry_function, arg, stack, + stack_size, priority, priority, TX_NO_TIME_SLICE, + TX_AUTO_START); + + if (TX_SUCCESS != tx_rslt) + { + last_error = tx_rslt; + free(buffer); + return CY_RTOS_GENERAL_ERROR; + } + + return CY_RSLT_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_exit_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_exit_thread(void) +{ + // No need to do anything before thread exit + return CY_RSLT_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_terminate_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread) +{ + if (thread == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + return convert_error(tx_thread_terminate(*thread)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_is_thread_running +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running) +{ + if ((thread == NULL) || (running == NULL)) + { + return CY_RTOS_BAD_PARAM; + } + + // Only true when the given thread is the current one + *running = (*thread == tx_thread_identify()); + return CY_RSLT_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_thread_state +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state) +{ + if ((thread == NULL) || (state == NULL)) + { + return CY_RTOS_BAD_PARAM; + } + + bool running; + cy_rslt_t rslt = cy_rtos_is_thread_running(thread, &running); + if (CY_RSLT_SUCCESS != rslt) + { + return rslt; + } + else if (running) + { + *state = CY_THREAD_STATE_RUNNING; + return CY_RSLT_SUCCESS; + } + + UINT thread_state; + cy_rtos_error_t tx_rslt = tx_thread_info_get(*thread, TX_NULL, &thread_state, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, TX_NULL, TX_NULL); + if (TX_SUCCESS != tx_rslt) + { + last_error = tx_rslt; + return CY_RTOS_GENERAL_ERROR; + } + + // Descriptions of these states are not given in the ThreadX user guide - these are best guesses + // as to their meanings + switch (thread_state) + { + case TX_READY: + *state = CY_THREAD_STATE_READY; + break; + + case TX_COMPLETED: + case TX_TERMINATED: + *state = CY_THREAD_STATE_TERMINATED; + break; + + case TX_SUSPENDED: + case TX_SLEEP: + case TX_QUEUE_SUSP: + case TX_SEMAPHORE_SUSP: + case TX_MUTEX_SUSP: + case TX_EVENT_FLAG: // Likely waiting for event flags to be set (tx_event_flags_get) + case TX_BLOCK_MEMORY: // Likely waiting to allocate a memory block (tx_block_allocate) + case TX_BYTE_MEMORY: // Likely waiting to allocate a byte pool (tx_byte_allocate) + *state = CY_THREAD_STATE_BLOCKED; + break; + + default: + *state = CY_THREAD_STATE_UNKNOWN; + break; + } + + return CY_RSLT_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_join_thread +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread) +{ + if (thread == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + // ThreadX doesn't have a join method itself, so just repeatedly check the thread's state until + // it completes or is terminated. + // Check if the thread we are joining has a higher priority, if it does, we need to lower our + // priority to that of the other thread. + UINT thread_state; + + cy_rtos_error_t tx_rslt = tx_thread_info_get(*thread, TX_NULL, &thread_state, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, TX_NULL, TX_NULL); + if (TX_SUCCESS != tx_rslt) + { + last_error = tx_rslt; + return CY_RTOS_GENERAL_ERROR; + } + + while (TX_TERMINATED != thread_state && TX_COMPLETED != thread_state) + { + tx_rslt = tx_thread_sleep(1); + if (TX_SUCCESS != tx_rslt) + { + last_error = tx_rslt; + return CY_RTOS_GENERAL_ERROR; + } + + tx_rslt = tx_thread_info_get(*thread, TX_NULL, &thread_state, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, TX_NULL, TX_NULL); + if (TX_SUCCESS != tx_rslt) + { + last_error = tx_rslt; + return CY_RTOS_GENERAL_ERROR; + } + } + + tx_rslt = tx_thread_delete(*thread); + if (TX_SUCCESS != tx_rslt) + { + last_error = tx_rslt; + return CY_RTOS_GENERAL_ERROR; + } + + cy_thread_wrapper_t* wrapper_ptr = (cy_thread_wrapper_t*)(*thread); + if (wrapper_ptr->magic == WRAPPER_IDENT) + { + if (wrapper_ptr->memptr != NULL) + { + free(wrapper_ptr->memptr); + } + else + { + free(wrapper_ptr); + } + } + return CY_RSLT_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_thread_handle +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread) +{ + if (thread == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + *thread = tx_thread_identify(); + return CY_RSLT_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_wait_thread_notification +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t timeout_ms) +{ + UINT ret; + cy_rslt_t status = CY_RSLT_SUCCESS; + + ret = tx_thread_sleep(convert_ms_to_ticks(timeout_ms)); + /* Update the last known error status */ + last_error = (cy_rtos_error_t)ret; + + if (ret == TX_SUCCESS) + { + status = CY_RTOS_TIMEOUT; + } + else if (ret != TX_WAIT_ABORTED) + { + status = CY_RTOS_GENERAL_ERROR; + } + return status; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_set_thread_notification +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr) +{ + (void)in_isr; + + if (thread == NULL) + { + return CY_RTOS_BAD_PARAM; + } + /* According to ThreadX user guide, this function allowed to + * be called from ISR + */ + return convert_error(tx_thread_wait_abort(*thread)); +} + + +/****************************************************** +* Mutexes +******************************************************/ + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_mutex2 +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive) +{ + if (mutex == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + // Non recursive mutex is not supported by ThreadX. A recursive mutex is returned + // even if a non-recursive mutex was requested. This is ok because in all the cases + // where the behavior of the two types differs would have ended in a deadlock. So + // the difference in behavior should not have a functional impact on application. + CY_UNUSED_PARAMETER(recursive); + return convert_error(tx_mutex_create(mutex, TX_NULL, TX_INHERIT)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_mutex +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms) +{ + if (mutex == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + cy_rtos_error_t tx_rslt = tx_mutex_get(mutex, convert_ms_to_ticks(timeout_ms)); + if (TX_NOT_AVAILABLE == tx_rslt) + { + return CY_RTOS_TIMEOUT; + } + else + { + return convert_error(tx_rslt); + } +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_set_mutex +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex) +{ + if (mutex == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + return convert_error(tx_mutex_put(mutex)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_mutex +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex) +{ + if (mutex == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + return convert_error(tx_mutex_delete(mutex)); +} + + +/****************************************************** +* Semaphores +******************************************************/ + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount) +{ + if (semaphore == NULL) + { + return CY_RTOS_BAD_PARAM; + } + semaphore->maxcount = maxcount; + return convert_error(tx_semaphore_create(&(semaphore->tx_semaphore), TX_NULL, initcount)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, cy_time_t timeout_ms, bool in_isr) +{ + // Based on documentation + // http://www.ece.ualberta.ca/~cmpe490/documents/ghs/405/threadxug_g40c.pdf + // pg 168 it specifies that the timeout must be zero when called from ISR. + if ((semaphore == NULL) || (in_isr && (timeout_ms != 0))) + { + return CY_RTOS_BAD_PARAM; + } + cy_rtos_error_t tx_rslt = + tx_semaphore_get(&(semaphore->tx_semaphore), convert_ms_to_ticks(timeout_ms)); + if (TX_NO_INSTANCE == tx_rslt) + { + return CY_RTOS_TIMEOUT; + } + else + { + return convert_error(tx_rslt); + } +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_set_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr) +{ + (void)in_isr; // Unused parameter in this implementation + if (semaphore == NULL) + { + return CY_RTOS_BAD_PARAM; + } + return convert_error(tx_semaphore_ceiling_put(&(semaphore->tx_semaphore), semaphore->maxcount)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_count_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count) +{ + if ((semaphore == NULL) || (count == NULL)) + { + return CY_RTOS_BAD_PARAM; + } + return convert_error(tx_semaphore_info_get(&(semaphore->tx_semaphore), TX_NULL, (ULONG*)count, + TX_NULL, TX_NULL, TX_NULL)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_semaphore +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore) +{ + if (semaphore == NULL) + { + return CY_RTOS_BAD_PARAM; + } + return convert_error(tx_semaphore_delete(&(semaphore->tx_semaphore))); +} + + +/****************************************************** +* Events +******************************************************/ + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_event(cy_event_t* event) +{ + if (event == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + return convert_error(tx_event_flags_create(event, TX_NULL)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_setbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr) +{ + (void)in_isr; // Unused parameter in this implementation + + if (event == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + return convert_error(tx_event_flags_set(event, bits, TX_OR)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_clearbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr) +{ + (void)in_isr; // Unused parameter in this implementation + + if (event == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + return convert_error(tx_event_flags_set(event, ~bits, TX_AND)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_getbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits) +{ + if ((event == NULL) || (bits == NULL)) + { + return CY_RTOS_BAD_PARAM; + } + + cy_rtos_error_t tx_rslt = tx_event_flags_get(event, ALL_EVENT_FLAGS, TX_OR, bits, TX_NO_WAIT); + if (TX_NO_EVENTS == tx_rslt) // If timeout error occur with ALL_EVENT_FLAGS and TX_OR, then no + // flag is set + { + *bits = 0; + return CY_RSLT_SUCCESS; + } + else + { + return convert_error(tx_rslt); + } +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_waitbits_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* bits, bool clear, bool all, + cy_time_t timeout_ms) +{ + UINT get_option; + + if ((event == NULL) || (bits == NULL)) + { + return CY_RTOS_BAD_PARAM; + } + + if (all) + { + get_option = clear ? TX_AND_CLEAR : TX_AND; + } + else + { + get_option = clear ? TX_OR_CLEAR : TX_OR; + } + + cy_rtos_error_t tx_rslt = + tx_event_flags_get(event, *bits, get_option, bits, convert_ms_to_ticks(timeout_ms)); + if (TX_NO_EVENTS == tx_rslt) + { + return CY_RTOS_TIMEOUT; + } + else + { + return convert_error(tx_rslt); + } +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_event +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_event(cy_event_t* event) +{ + if (event == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + return convert_error(tx_event_flags_delete(event)); +} + + +/****************************************************** +* Queues +******************************************************/ + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize) +{ + // Valid message lengths are {1-ULONG, 2-ULONG, 4-ULONG, 8-ULONG, 16-ULONG} + static const uint32_t BYTES_PER_QUEUE_WORD = sizeof(ULONG); + + if ((queue == NULL) || (itemsize == 0) || + (itemsize > BYTES_PER_QUEUE_WORD * MAX_QUEUE_MESSAGE_SIZE)) + { + return CY_RTOS_BAD_PARAM; + } + + // round message words to next power of 2 times word size. + UINT message_words = 1; + while (message_words * BYTES_PER_QUEUE_WORD < itemsize) + { + message_words <<= 1; + } + + queue->itemsize = itemsize; + ULONG queue_size = length * message_words * BYTES_PER_QUEUE_WORD; + queue->mem = malloc(queue_size); + if (queue->mem == NULL) + { + return CY_RTOS_NO_MEMORY; + } + + cy_rtos_error_t tx_rslt = tx_queue_create(&(queue->tx_queue), TX_NULL, message_words, + queue->mem, queue_size); + if (TX_SUCCESS != tx_rslt) + { + last_error = tx_rslt; + free(queue->mem); + return CY_RTOS_GENERAL_ERROR; + } + + return CY_RSLT_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_put_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeout_ms, + bool in_isr) +{ + if ((queue == NULL) || (item_ptr == NULL) || (in_isr && (timeout_ms != 0))) + { + return CY_RTOS_BAD_PARAM; + } + + cy_rtos_error_t tx_rslt = tx_queue_send(&(queue->tx_queue), (void*)item_ptr, convert_ms_to_ticks( + timeout_ms)); + if (TX_QUEUE_FULL == tx_rslt) + { + return CY_RTOS_NO_MEMORY; + } + else + { + return convert_error(tx_rslt); + } +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeout_ms, bool in_isr) +{ + ULONG buffer[MAX_QUEUE_MESSAGE_SIZE]; + if ((queue == NULL) || (item_ptr == NULL) || (in_isr && (timeout_ms != 0))) + { + return CY_RTOS_BAD_PARAM; + } + + cy_rtos_error_t tx_rslt = + tx_queue_receive(&(queue->tx_queue), buffer, convert_ms_to_ticks(timeout_ms)); + if (TX_QUEUE_EMPTY == tx_rslt) + { + return CY_RTOS_TIMEOUT; + } + else if (tx_rslt == TX_SUCCESS) + { + memcpy(item_ptr, buffer, queue->itemsize); + return CY_RSLT_SUCCESS; + } + else + { + last_error = tx_rslt; + return CY_RTOS_GENERAL_ERROR; + } +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_count_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting) +{ + if ((queue == NULL) || (num_waiting == NULL)) + { + return CY_RTOS_BAD_PARAM; + } + return convert_error(tx_queue_info_get(&(queue->tx_queue), TX_NULL, (ULONG*)num_waiting, + TX_NULL, TX_NULL, TX_NULL, TX_NULL)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_space_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces) +{ + if ((queue == NULL) || (num_spaces == NULL)) + { + return CY_RTOS_BAD_PARAM; + } + return convert_error(tx_queue_info_get(&(queue->tx_queue), TX_NULL, TX_NULL, (ULONG*)num_spaces, + TX_NULL, TX_NULL, TX_NULL)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_reset_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue) +{ + if (queue == NULL) + { + return CY_RTOS_BAD_PARAM; + } + return convert_error(tx_queue_flush(&(queue->tx_queue))); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_queue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue) +{ + if (queue == NULL) + { + return CY_RTOS_BAD_PARAM; + } + cy_rslt_t result = convert_error(tx_queue_delete(&(queue->tx_queue))); + if (result == CY_RSLT_SUCCESS) + { + free(queue->mem); + } + return result; +} + + +/****************************************************** +* Timers +******************************************************/ + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_init_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_init_timer(cy_timer_t* timer, cy_timer_trigger_type_t type, + cy_timer_callback_t fun, cy_timer_callback_arg_t arg) +{ + if ((timer == NULL) || (fun == NULL)) + { + return CY_RTOS_BAD_PARAM; + } + timer->oneshot = (type == CY_TIMER_TYPE_ONCE); + // Use 1s here as default timeouts since these are going to get changed anyway + return convert_error(tx_timer_create(&(timer->tx_timer), TX_NULL, fun, arg, 1, 1, + TX_NO_ACTIVATE)); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_start_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms) +{ + if (timer == NULL) + { + return CY_RTOS_BAD_PARAM; + } + ULONG timer_ticks = convert_ms_to_ticks(num_ms); + cy_rslt_t rslt = + convert_error(tx_timer_change(&(timer->tx_timer), timer_ticks, + timer->oneshot ? 0 : timer_ticks)); + if (CY_RSLT_SUCCESS != rslt) + { + return rslt; + } + return convert_error(tx_timer_activate(&(timer->tx_timer))); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_stop_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer) +{ + if (timer == NULL) + { + return CY_RTOS_BAD_PARAM; + } + return convert_error(tx_timer_deactivate(&(timer->tx_timer))); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_is_running_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state) +{ + if ((timer == NULL) || (state == NULL)) + { + return CY_RTOS_BAD_PARAM; + } + + UINT active; + cy_rslt_t rslt = + convert_error(tx_timer_info_get(&(timer->tx_timer), TX_NULL, &active, TX_NULL, TX_NULL, + TX_NULL)); + if (CY_RSLT_SUCCESS == rslt) + { + *state = (active == TX_TRUE); + } + return rslt; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_deinit_timer +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer) +{ + if (timer == NULL) + { + return CY_RTOS_BAD_PARAM; + } + return convert_error(tx_timer_delete(&(timer->tx_timer))); +} + + +/****************************************************** +* Time +******************************************************/ + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_get_time +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_get_time(cy_time_t* tval) +{ + if (tval == NULL) + { + return CY_RTOS_BAD_PARAM; + } + + *tval = convert_ticks_to_ms(tx_time_get()); + + return CY_RSLT_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_rtos_delay_milliseconds +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms) +{ + cy_time_t ticks = convert_ms_to_ticks(num_ms); + + return convert_error(tx_thread_sleep(ticks)); +} diff --git a/abstraction-rtos/source/cy_worker_thread.c b/abstraction-rtos/source/cy_worker_thread.c new file mode 100644 index 00000000..07bf345a --- /dev/null +++ b/abstraction-rtos/source/cy_worker_thread.c @@ -0,0 +1,229 @@ +/***********************************************************************************************//** + * \file cy_worker_thread.c + * + * \brief + * Provides implementation for functions that allow creating/deleting worker + * threads and deferring work to a worker thread. + *************************************************************************************************** + * \copyright + * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#include +#include + +#include "cy_worker_thread.h" +#include "cy_utils.h" +#include "cyabs_rtos_internal.h" +#if defined(CY_USING_HAL) +#include "cyhal_system.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// Info for dispatching a function call +typedef struct +{ + cy_worker_thread_func_t* work_func; + void* arg; +} cy_worker_dispatch_info_t; + + +//-------------------------------------------------------------------------------------------------- +// cy_worker_thread_func +// +/* Worker Thread to dispatch the events that added to the event queue. + * It will wait indefinitely for a item to be queued and will terminate + * when the NULL work function is queued by delete. It will process all + * events before the terminating event. + * @param arg : pointer to @ref cy_worker_thread_info_t + */ +//-------------------------------------------------------------------------------------------------- +static void cy_worker_thread_func(cy_thread_arg_t arg) +{ + cy_rslt_t result; + cy_worker_dispatch_info_t dispatch_info; + cy_worker_thread_info_t* worker = (cy_worker_thread_info_t*)arg; + + while (1) + { + result = cy_rtos_get_queue(&worker->event_queue, &dispatch_info, CY_RTOS_NEVER_TIMEOUT, + false); + if (result == CY_RSLT_SUCCESS) + { + if (dispatch_info.work_func != NULL) + { + dispatch_info.work_func(dispatch_info.arg); + } + else + { + break; + } + } + } + cy_rtos_exit_thread(); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_worker_thread_create +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_worker_thread_create(cy_worker_thread_info_t* new_worker, + const cy_worker_thread_params_t* params) +{ + // Param check + CY_ASSERT((params != NULL) && (new_worker != NULL)); + CY_ASSERT((params->stack == NULL) || ((params->stack != NULL) && (params->stack_size != 0))); + + // Start with a clean structure + memset(new_worker, 0, sizeof(cy_worker_thread_info_t)); + + cy_rslt_t result = cy_rtos_init_queue(&new_worker->event_queue, + (params->num_entries != 0) + ? params->num_entries + : CY_WORKER_DEFAULT_ENTRIES, + sizeof(cy_worker_dispatch_info_t)); + if (result == CY_RSLT_SUCCESS) + { + new_worker->state = CY_WORKER_THREAD_VALID; + result = cy_rtos_create_thread(&new_worker->thread, + cy_worker_thread_func, + (params->name != NULL) + ? params->name + : CY_WORKER_THREAD_DEFAULT_NAME, + params->stack, + params->stack_size, + params->priority, + (cy_thread_arg_t)new_worker); + + if (result != CY_RSLT_SUCCESS) + { + new_worker->state = CY_WORKER_THREAD_INVALID; + cy_rtos_deinit_queue(&new_worker->event_queue); + } + } + return result; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_worker_thread_delete +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_worker_thread_delete(cy_worker_thread_info_t* old_worker) +{ + cy_rslt_t result = CY_RSLT_SUCCESS; + + uint32_t state = cyhal_system_critical_section_enter(); + if (old_worker->state != CY_WORKER_THREAD_INVALID) + { + // Don't allow terminating while cy_rtos_put_queue is running + if (old_worker->state == CY_WORKER_THREAD_VALID) + { + // A terminating event is queued that will break the while loop + // Note that this is ok because thread enqueue function will not + // allow NULL as a valid value for the work function. + old_worker->state = CY_WORKER_THREAD_TERMINATING; + cyhal_system_critical_section_exit(state); + cy_worker_dispatch_info_t dispatch_info = { NULL, NULL }; + bool in_isr = is_in_isr(); + result = cy_rtos_put_queue(&old_worker->event_queue, &dispatch_info, 0, in_isr); + if (result != CY_RSLT_SUCCESS) + { + // Could not enqueue termination task, return to valid state + state = cyhal_system_critical_section_enter(); + old_worker->state = CY_WORKER_THREAD_VALID; + cyhal_system_critical_section_exit(state); + + return result; + } + } + + if (old_worker->state != CY_WORKER_THREAD_JOIN_COMPLETE) + { + cyhal_system_critical_section_exit(state); + result = cy_rtos_join_thread(&old_worker->thread); + if (result != CY_RSLT_SUCCESS) + { + return result; + } + state = cyhal_system_critical_section_enter(); + old_worker->state = CY_WORKER_THREAD_JOIN_COMPLETE; + } + + if (old_worker->state != CY_WORKER_THREAD_INVALID) + { + cyhal_system_critical_section_exit(state); + result = cy_rtos_deinit_queue(&old_worker->event_queue); + if (result != CY_RSLT_SUCCESS) + { + return result; + } + state = cyhal_system_critical_section_enter(); + old_worker->state = CY_WORKER_THREAD_INVALID; + } + } + + cyhal_system_critical_section_exit(state); + return result; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_worker_thread_enqueue +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cy_worker_thread_enqueue(cy_worker_thread_info_t* worker_info, + cy_worker_thread_func_t* work_func, void* arg) +{ + CY_ASSERT(worker_info != NULL); + CY_ASSERT(work_func != NULL); + + uint32_t state = cyhal_system_critical_section_enter(); + if ((worker_info->state != CY_WORKER_THREAD_VALID) && + (worker_info->state != CY_WORKER_THREAD_ENQUEUING)) + { + cyhal_system_critical_section_exit(state); + return CY_WORKER_THREAD_ERR_THREAD_INVALID; + } + worker_info->enqueue_count++; + worker_info->state = CY_WORKER_THREAD_ENQUEUING; + cyhal_system_critical_section_exit(state); + + cy_worker_dispatch_info_t dispatch_info = { work_func, arg }; + // Queue an event to be run by the worker thread + bool in_isr = is_in_isr(); + cy_rslt_t result = cy_rtos_put_queue(&worker_info->event_queue, &dispatch_info, 0, in_isr); + + state = cyhal_system_critical_section_enter(); + worker_info->enqueue_count--; + if (worker_info->enqueue_count == 0) + { + worker_info->state = CY_WORKER_THREAD_VALID; + } + cyhal_system_critical_section_exit(state); + + return result; +} + + +#if defined(__cplusplus) +} +#endif + +#endif // defined(CY_USING_HAL) diff --git a/abstraction-rtos/version.xml b/abstraction-rtos/version.xml new file mode 100644 index 00000000..a2159543 --- /dev/null +++ b/abstraction-rtos/version.xml @@ -0,0 +1 @@ +1.5.0.25183 diff --git a/whd-bsp-integration/COMPONENT_CAT4/cy_map_hostbuffer.c b/whd-bsp-integration/COMPONENT_CAT4/cy_map_hostbuffer.c new file mode 100644 index 00000000..9531d117 --- /dev/null +++ b/whd-bsp-integration/COMPONENT_CAT4/cy_map_hostbuffer.c @@ -0,0 +1,97 @@ +/***************************************************************************//** +* \file cy_map_hostbuffer.c +* +* \brief +* Implements a set of mapping functions for M2M DMA host buffer routines. +* +******************************************************************************** +* \copyright +* Copyright 2021-2022 Cypress Semiconductor Corporation (an Infineon company) or +* an affiliate of Cypress Semiconductor Corporation +* +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#include "wiced_osl.h" +#include "cy_network_buffer.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + +#define HOST_BUFFER_WAIT_MS (1000UL) + +/******************************************************************************* +* Host buffer functions +*******************************************************************************/ + +cy_rslt_t host_buffer_get(wiced_buffer_t* buffer, wwd_buffer_dir_t direction, + uint16_t size, bool wait) +{ + uint32_t timeout_ms = wait ? HOST_BUFFER_WAIT_MS : 0UL; + + return (cy_rslt_t)cy_host_buffer_get((whd_buffer_t*)buffer, (whd_buffer_dir_t)direction, + size, timeout_ms); +} + + +//-------------------------------------------------------------------------------------------------- +// host_buffer_release +//-------------------------------------------------------------------------------------------------- +void host_buffer_release(wiced_buffer_t buffer, wwd_buffer_dir_t direction) +{ + cy_buffer_release((whd_buffer_t)buffer, (whd_buffer_dir_t)direction); +} + + +//-------------------------------------------------------------------------------------------------- +// host_buffer_get_current_piece_data_pointer +//-------------------------------------------------------------------------------------------------- +uint8_t* host_buffer_get_current_piece_data_pointer(wiced_buffer_t buffer) +{ + return cy_buffer_get_current_piece_data_pointer((whd_buffer_t)buffer); +} + + +//-------------------------------------------------------------------------------------------------- +// host_buffer_get_current_piece_size +//-------------------------------------------------------------------------------------------------- +uint16_t host_buffer_get_current_piece_size(wiced_buffer_t buffer) +{ + return cy_buffer_get_current_piece_size((whd_buffer_t)buffer); +} + + +//-------------------------------------------------------------------------------------------------- +// host_buffer_set_size +//-------------------------------------------------------------------------------------------------- +cy_rslt_t host_buffer_set_size(wiced_buffer_t buffer, uint16_t size) +{ + return (cy_rslt_t)cy_buffer_set_size((whd_buffer_t)buffer, size); +} + + +//-------------------------------------------------------------------------------------------------- +// host_buffer_add_remove_at_front +//-------------------------------------------------------------------------------------------------- +cy_rslt_t host_buffer_add_remove_at_front(wiced_buffer_t* buffer, int32_t add_remove_amount) +{ + return (cy_rslt_t)cy_buffer_add_remove_at_front((whd_buffer_t*)buffer, add_remove_amount); +} + + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ diff --git a/whd-bsp-integration/COMPONENT_LWIP/cy_network_buffer_lwip.c b/whd-bsp-integration/COMPONENT_LWIP/cy_network_buffer_lwip.c new file mode 100644 index 00000000..4d5a5487 --- /dev/null +++ b/whd-bsp-integration/COMPONENT_LWIP/cy_network_buffer_lwip.c @@ -0,0 +1,168 @@ +/***********************************************************************************************//** + * \file cy_network_buffer_lwip.c + * + * \brief + * Basic set of APIs for dealing with network packet buffers. This is used by WHD + * for relaying data between the network stack and the connectivity chip. + * + *************************************************************************************************** + * \copyright + * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#include +#include "cy_network_buffer.h" +#include "cy_utils.h" +#include "cyhal_system.h" +#include "lwip/pbuf.h" + +#define SDIO_BLOCK_SIZE (64U) + +//-------------------------------------------------------------------------------------------------- +// cy_buffer_pool_init +//-------------------------------------------------------------------------------------------------- +whd_result_t cy_buffer_pool_init(void* tx_packet_pool, void* rx_packet_pool) +{ + CY_UNUSED_PARAMETER(tx_packet_pool); + CY_UNUSED_PARAMETER(rx_packet_pool); + + /* + * Not used for LwIP. + */ + + return WHD_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_host_buffer_get +//-------------------------------------------------------------------------------------------------- +whd_result_t cy_host_buffer_get(whd_buffer_t* buffer, whd_buffer_dir_t direction, + uint16_t size, uint32_t timeout_ms) +{ + struct pbuf* p = NULL; + uint32_t counter = 0; + + do + { + counter++; + if (direction == WHD_NETWORK_TX) + { + // Allocate from the POOL if possible to avoid dynamic memory allocation + pbuf_type type = (size <= PBUF_POOL_BUFSIZE) ? PBUF_POOL : PBUF_RAM; + p = pbuf_alloc(PBUF_RAW, size, type); + } + else + { + // Increase allocation size to ensure the SDIO can write fully aligned blocks for + // best throughput performance + p = pbuf_alloc(PBUF_RAW, size + SDIO_BLOCK_SIZE, PBUF_RAM); + if (p != NULL) + { + p->len = size; + p->tot_len -= SDIO_BLOCK_SIZE; + } + } + + if (NULL == p) + { + cyhal_system_delay_ms(1); + } + } while ((NULL == p) && (counter <= timeout_ms)); + + if (p != NULL) + { + *buffer = p; + return WHD_SUCCESS; + } + else + { + return WHD_BUFFER_ALLOC_FAIL; + } +} + + +//-------------------------------------------------------------------------------------------------- +// cy_buffer_release +//-------------------------------------------------------------------------------------------------- +void cy_buffer_release(whd_buffer_t buffer, whd_buffer_dir_t direction) +{ + CY_UNUSED_PARAMETER(direction); + (void)pbuf_free((struct pbuf*)buffer); +} + + +//-------------------------------------------------------------------------------------------------- +// cy_buffer_get_current_piece_data_pointer +//-------------------------------------------------------------------------------------------------- +uint8_t* cy_buffer_get_current_piece_data_pointer(whd_buffer_t buffer) +{ + CY_ASSERT(buffer != NULL); + struct pbuf* pbuffer= (struct pbuf*)buffer; + return (uint8_t*)pbuffer->payload; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_buffer_get_current_piece_size +//-------------------------------------------------------------------------------------------------- +uint16_t cy_buffer_get_current_piece_size(whd_buffer_t buffer) +{ + CY_ASSERT(buffer != NULL); + struct pbuf* pbuffer = (struct pbuf*)buffer; + return (uint16_t)pbuffer->len; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_buffer_set_size +//-------------------------------------------------------------------------------------------------- +whd_result_t cy_buffer_set_size(whd_buffer_t buffer, uint16_t size) +{ + CY_ASSERT(buffer != NULL); + struct pbuf* pbuffer = (struct pbuf*)buffer; + + if (size > ((uint16_t)WHD_LINK_MTU + + LWIP_MEM_ALIGN_SIZE(LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))) + + LWIP_MEM_ALIGN_SIZE(size))) + { + return WHD_BUFFER_SIZE_SET_ERROR; + } + + pbuffer->tot_len = size; + pbuffer->len = size; + + return CY_RSLT_SUCCESS; +} + + +//-------------------------------------------------------------------------------------------------- +// cy_buffer_add_remove_at_front +//-------------------------------------------------------------------------------------------------- +whd_result_t cy_buffer_add_remove_at_front(whd_buffer_t* buffer, int32_t add_remove_amount) +{ + CY_ASSERT(buffer != NULL); + struct pbuf** pbuffer = (struct pbuf**)buffer; + + if ((u8_t)0 != pbuf_header(*pbuffer, (s16_t)(-add_remove_amount))) + { + return WHD_BUFFER_POINTER_MOVE_ERROR; + } + + return WHD_SUCCESS; +} diff --git a/whd-bsp-integration/README.md b/whd-bsp-integration/README.md new file mode 100644 index 00000000..65ade86e --- /dev/null +++ b/whd-bsp-integration/README.md @@ -0,0 +1,60 @@ +# WiFi Host Driver Board Support Package Integration + +## Overview + +This library provides some convenience functions for connecting the WiFi Host Driver (WHD) library to a Board Support Package (BSP) that includes a WLAN chip. This library initializes the hardware and passes a reference to the communication interface on the board into WHD. It also sets up the LwIP or NetXDuo based network buffers to be used for sending packets back and forth. + +The BSP is expected to set a component indicating what communication interface to use to relay information between the MCU and the WIFI chip. The legal options are restricted based on what MCU and WIFI chips are being used. The selected interface must be supported by both sides. The legal component values are one of: +* WIFI_INTERFACE_SDIO +* WIFI_INTERFACE_SPI +* WIFI_INTERFACE_M2M + +Some additional customization of the library is possible by setting defines when building the library. If no custom value is provided, the library will pick a reasonable default value. The following options are available for customization: +* CY_WIFI_COUNTRY: Defines the country this will operate in for wifi initialization parameters. See the wifi-host-driver's whd_country_code_t for legal options. +* CY_WIFI_THREAD_STACK_SIZE: Defines the amount of stack memory available for the wifi thread. +* CY_WIFI_THREAD_PRIORITY: Defines the priority of the thread that services wifi packets. Legal values are defined by the RTOS being used. +* CY_WIFI_HOST_WAKE_SW_FORCE: Defines whether to use the out-of-band pin to allow the WIFI chip to wake up the MCU. +* CY_WIFI_OOB_INTR_PRIORITY: Defines the priority of the interrupt that handles out-of-band notifications from the WIFI chip. Legal values are defined by the MCU running this code. + + +## Getting Started + +To use this library: +1. Implement the cy_network_process_ethernet_data() function. This should be something similar to the example below. +```cpp +/* This needs to be the same item as passed to netifapi_netif_add() */ +static struct netif *default_interface = NULL; + +void cy_network_process_ethernet_data(whd_interface_t iface, whd_buffer_t buf) +{ + if (default_interface != NULL) + { + if (default_interface->input(buf, default_interface) != ERR_OK) + cy_buffer_release(buf, WHD_NETWORK_RX); + } + else + { + cy_buffer_release(buf, WHD_NETWORK_RX); + } +} +``` +2. Include a reference to `cybsp_wifi.h`. +3. Call cybsp_wifi_init_primary() to initialize the interface. This needs to be done after having called cybsp_init(). + +## Features + +* APIs for setting up the WHD interface with the BSP's SDIO/SPI/M2M interface. + * Initialize a primary WiFi interface + * Optionally initialize a secondary WiFi interface + * Cleanup interfaces +* APIs for connecting WHD to LwIP/NetXDuo memory buffers (whd_buffer_funcs_t) +* Framework for connecting WHD to LwIP/NetXDuo network interface (whd_netif_funcs_t) + +## More information +* [API Reference Guide](https://infineon.github.io/whd-bsp-integration/html/modules.html) +* [Cypress Semiconductor, an Infineon Technologies Company](http://www.cypress.com) +* [Infineon GitHub](https://github.com/infineon) +* [ModusToolbox™](https://www.cypress.com/products/modustoolbox-software-environment) + +--- +© Cypress Semiconductor Corporation (an Infineon company) or an affiliate of Cypress Semiconductor Corporation, 2019-2022. diff --git a/whd-bsp-integration/RELEASE.md b/whd-bsp-integration/RELEASE.md new file mode 100644 index 00000000..3631c28d --- /dev/null +++ b/whd-bsp-integration/RELEASE.md @@ -0,0 +1,58 @@ +# WiFi Host Driver Board Support Package Integration Release Notes +This library helps streamline the process of getting the WiFi Host Driver (WHD) setup and running with a Board Support Package (BSP) that includes a WLAN chip. + +### What's Included? +* APIs for setting up the WHD interface with the BSP's SDIO interface. +* APIs for connecting WHD to LwIP/NetXDuo memory buffers (whd_buffer_funcs_t) +* Framework for connecting WHD to LwIP/NetXDuo network interface (whd_netif_funcs_t) + +### What Changed? +#### v2.1.0 +* Added support for dyanmically allocated NetX Duo packets to support WHD IOVARs with payloads larger than MTU. +* Added support for NetX Duo +* Made SDIO initialization more robust +#### v2.0.0 +* Added support for different communication protocols (SDIO, SPI, DMA) between MCU and Radio +* Card initialization process improvements. Code now checks whether SDIO device supports 1.8V signaling, and, if it does, performs the actions needed in order to switch to 1.8V. +* Added support for overriding the default country code by defining CY_WIFI_COUNTRY to a value from whd_country_code_t. +* Added argument to cybsp_wifi_init_primary_extended() to set WHD initialization parameters +* SDIO frequency is increased to 50 MHz if High Speed Mode is supported +* Added support for HAL API v1 or v2 +* Minimum required `wifi-host-driver` library version for this release - `2.0.0` +#### v1.2.0 +* Fixed possible memory corruption issue introduced with changes from v1.1.0 +#### v1.1.2 +* Robustness update for WLAN initialization +#### v1.1.1 +* Update network buffer allocation for improved performance +#### v1.1.0 +* Fixed a memory leak when shutting down the WHD interface +* Minor code style cleanups +#### v1.0.2 +* Minor update for documentation & branding +#### v1.0.1 +* Fixed issue with a missing ; +#### v1.0.0 +* Initial release + +### Supported Software and Tools +This version of the RTOS Abstraction API was validated for compatibility with the following Software and Tools: + +| Software and Tools | Version | +| :--- | :----: | +| ModusToolbox™ Software Environment | 2.4.0 | +| GCC Compiler | 10.3.1 | +| IAR Compiler | 9.30.1 | +| ARM Compiler | 6.16 | + +Minimum required ModusToolbox™ Software Environment: v2.0 + +### More information +Use the following links for more information, as needed: +* [API Reference Guide](https://infineon.github.io/whd-bsp-integration/html/modules.html) +* [Cypress Semiconductor, an Infineon Technologies Company](http://www.cypress.com) +* [Infineon GitHub](https://github.com/infineon) +* [ModusToolbox™](https://www.cypress.com/products/modustoolbox-software-environment) + +--- +© Cypress Semiconductor Corporation (an Infineon company) or an affiliate of Cypress Semiconductor Corporation, 2019-2022. diff --git a/whd-bsp-integration/cy_network_buffer.h b/whd-bsp-integration/cy_network_buffer.h new file mode 100644 index 00000000..60be632e --- /dev/null +++ b/whd-bsp-integration/cy_network_buffer.h @@ -0,0 +1,187 @@ +/***********************************************************************************************//** + * \file cy_network_buffer.h + * + * \brief + * Basic set of APIs for dealing with network packet buffers. This is used by WHD + * for relaying data between the network stack and the connectivity chip. + * + *************************************************************************************************** + * \copyright + * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +/** + * \addtogroup group_bsp_network_buffer Buffer management + * \{ + * Basic set of APIs for dealing with network packet buffers + */ + +#pragma once + +#include +#include +#include "cy_result.h" +#include "whd.h" +#include "whd_network_types.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** Initialize the buffer pools + * + * Initialize the buffer pools used by the buffer management routines. + * A pair of pools, one for RX buffers and one for TX buffers in passed + * in for use by the management routines. + * + * Not all implementations use preallocated buffer pools. + * + * @param tx_packet_pool : Pointer to the initialized NetXDuo TX packet buffer pool + * @param rx_packet_pool : Pointer to the initialized NetXDuo RX packet buffer pool + * + * @return : CY_RSLT_SUCCESS or WHD_BADARG + */ +whd_result_t cy_buffer_pool_init(void* tx_packet_pool, void* rx_packet_pool); + +/** Allocates a packet buffer + * + * Attempts to allocate a packet buffer of the size requested. It can do this + * by allocating a pre-existing packet from a pool, using a static buffer, + * or by dynamically allocating memory. The method of allocation does not + * concern WHD, however it must match the way the network stack expects packet + * buffers to be allocated. Usually WHD requires packet of size of WHD_LINK_MTU + * which includes the MTU. Refer to whd_types.h to find the size of WHD_LINK_MTU. + * + * @param buffer : A pointer which receives the allocated packet buffer handle + * @param direction : Indicates transmit/receive direction that the packet buffer is + * used for. This may be needed if tx/rx pools are separate. + * @param size : The number of bytes to allocate. + * @param timeout_ms: Time to wait for a packet buffer to be available + * + * @return : CY_RSLT_SUCCESS or WHD_BUFFER_ALLOC_FAIL if the buffer could not be allocated + */ +whd_result_t cy_host_buffer_get(whd_buffer_t* buffer, whd_buffer_dir_t direction, + uint16_t size, uint32_t timeout_ms); + +/** Releases a packet buffer + * + * This function is used by WHD to indicate that it no longer requires + * a packet buffer. The buffer can then be released back into a pool for + * reuse, or the dynamically allocated memory can be freed, according to + * how the packet was allocated. + * Returns void since WHD cannot do anything about failures + * + * @param buffer : The handle of the packet buffer to be released + * @param direction : Indicates transmit/receive direction that the packet buffer has + * been used for. This might be needed if tx/rx pools are separate. + */ +void cy_buffer_release(whd_buffer_t buffer, whd_buffer_dir_t direction); + +/** Retrieves the current pointer of a packet buffer + * + * Since packet buffers usually need to be created with space at the + * front for additional headers, this function allows WHD to get + * the current 'front' location pointer. + * + * @param buffer : The handle of the packet buffer whose pointer is to be retrieved + * + * @return : The packet buffer's current pointer. + */ +uint8_t* cy_buffer_get_current_piece_data_pointer(whd_buffer_t buffer); + +/** Retrieves the size of a packet buffer + * + * Since packet buffers usually need to be created with space at the + * front for additional headers, the memory block used to contain a packet buffer + * will often be larger than the current size of the packet buffer data. + * This function allows WHD to retrieve the current size of a packet buffer's data. + * + * @param buffer : The handle of the packet buffer whose size is to be retrieved + * + * @return : The size of the packet buffer. + */ +uint16_t cy_buffer_get_current_piece_size(whd_buffer_t buffer); + +/** Sets the current size of a WHD packet + * + * This function sets the current length of a WHD packet buffer + * + * @param buffer : The packet to be modified + * @param size : The new size of the packet buffer + * + * @return : CY_RSLT_SUCCESS or WHD_BUFFER_SIZE_SET_ERROR if the requested size is not valid + */ +whd_result_t cy_buffer_set_size(whd_buffer_t buffer, uint16_t size); + +/** Moves the current pointer of a packet buffer + * + * Since packet buffers usually need to be created with space at the front for additional headers, + * this function allows WHD to move the current 'front' location pointer so that it has space to + * add headers to transmit packets, and so that the network stack does not see the internal WHD + * headers on received packets. + * + * @param buffer : A pointer to the handle of the current packet buffer for which the + * current pointer will be moved. On return this may contain a pointer + * to a newly allocated packet buffer which has been daisy chained to + * the front of the given one. This would be the case if the given + * packet buffer didn't have enough space at the front. + * @param add_remove_amount : This is the number of bytes to move the current pointer of the packet + * buffer - a negative value increases the space for headers at the + * front of the packet, a positive value decreases the space. + * + * @return : CY_RSLT_SUCCESS or WHD_BUFFER_POINTER_MOVE_ERROR if the added amount + * is outside the size of the buffer + */ +whd_result_t cy_buffer_add_remove_at_front(whd_buffer_t* buffer, int32_t add_remove_amount); + + +/** Called by WHD to pass received data to the network stack + * + * Packets received from the Wi-Fi network by WHD are forwarded to by calling function ptr which + * must be implemented in the network interface. Ethernet headers + * are present at the start of these packet buffers. + * + * This function is called asynchronously in the context of the + * WHD thread whenever new data has arrived. + * Packet buffers are allocated within WHD, and ownership is transferred + * to the network stack. The network stack or application is thus + * responsible for releasing the packet buffers. + * Most packet buffering systems have a pointer to the 'current point' within + * the packet buffer. When this function is called, the pointer points + * to the start of the Ethernet header. There is other inconsequential data + * before the Ethernet header. + * + * It is preferable that the (whd_network_process_ethernet_data)() function simply puts + * the received packet on a queue for processing by another thread. This avoids the + * WHD thread being unnecessarily tied up which would delay other packets + * being transmitted or received. + * + * @param interface : The interface on which the packet was received. + * @param buffer : Handle of the packet which has just been received. Responsibility for + * releasing this buffer is transferred from WHD at this point. + * + */ +void cy_network_process_ethernet_data(whd_interface_t interface, whd_buffer_t buffer); + + +#ifdef __cplusplus +} +#endif // __cplusplus + +/** \} group_bsp_network_buffer */ diff --git a/whd-bsp-integration/cy_wifi_fw_section.h b/whd-bsp-integration/cy_wifi_fw_section.h new file mode 100644 index 00000000..ae3d5b25 --- /dev/null +++ b/whd-bsp-integration/cy_wifi_fw_section.h @@ -0,0 +1,77 @@ +/***********************************************************************************************//** + * \file cy_wifi_fw_section.h + * + * \brief + * Determines the start and end of the region the WiFi firmware is stored in. + * + *************************************************************************************************** + * \copyright + * Copyright 2020-2022 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#pragma once + +#if defined(CY_STORAGE_WIFI_DATA_OUTPUT) + +#include "cy_utils.h" + +#if defined(__ARMCC_VERSION) + +#define CY_SECTION_BASE_SYMBOL_BASE(SECTION) Image$$ ## SECTION ## $$Base +#define CY_SECTION_BASE_SYMBOL(SECTION) CY_SECTION_BASE_SYMBOL_BASE(SECTION) +extern char CY_SECTION_BASE_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT); +#define CY_WIFI_FW_SECTION_START (&CY_SECTION_BASE_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT)) + +#define CY_SECTION_LIMIT_SYMBOL_BASE(SECTION) Image$$ ## SECTION ## $$Limit +#define CY_SECTION_LIMIT_SYMBOL(SECTION) CY_SECTION_LIMIT_SYMBOL_BASE(SECTION) +extern char CY_SECTION_LIMIT_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT); +#define CY_WIFI_FW_SECTION_END (&CY_SECTION_LIMIT_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT)) + +#elif defined(__GNUC__) + +// Must define ___start and ___end in the linker script + +#define CY_SECTION_START_SYMBOL_BASE(SECTION) __ ## SECTION ## _start +#define CY_SECTION_START_SYMBOL(SECTION) CY_SECTION_START_SYMBOL_BASE(SECTION) +extern char CY_SECTION_START_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT); +#define CY_WIFI_FW_SECTION_START (&CY_SECTION_START_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT)) + +#define CY_SECTION_END_SYMBOL_BASE(SECTION) __ ## SECTION ## _end +#define CY_SECTION_END_SYMBOL(SECTION) CY_SECTION_END_SYMBOL_BASE(SECTION) +extern char CY_SECTION_END_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT); +#define CY_WIFI_FW_SECTION_END (&CY_SECTION_END_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT)) + +#elif defined(__ICCARM__) + +#define CY_DECLARE_SECTION_BASE(SECTION) CY_PRAGMA(section = #SECTION) +#define CY_DECLARE_SECTION(SECTION) CY_DECLARE_SECTION_BASE(SECTION) +CY_DECLARE_SECTION(CY_STORAGE_WIFI_DATA_OUTPUT) + +#define CY_SECTION_BEGIN_SYMBOL_BASE(SECTION) __section_begin(#SECTION) +#define CY_SECTION_BEGIN_SYMBOL(SECTION) CY_SECTION_BEGIN_SYMBOL_BASE(SECTION) +#define CY_WIFI_FW_SECTION_START (CY_SECTION_BEGIN_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT)) + +#define CY_SECTION_END_SYMBOL_BASE(SECTION) __section_end(#SECTION) +#define CY_SECTION_END_SYMBOL(SECTION) CY_SECTION_END_SYMBOL_BASE(SECTION) +#define CY_WIFI_FW_SECTION_END (CY_SECTION_END_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT)) + +#else // if defined(__ARMCC_VERSION) +#error "An unsupported toolchain" +#endif // defined(__ARMCC_VERSION) + +#endif // defined(CY_STORAGE_WIFI_DATA_OUTPUT) diff --git a/whd-bsp-integration/cybsp_wifi.c b/whd-bsp-integration/cybsp_wifi.c new file mode 100644 index 00000000..1658bb74 --- /dev/null +++ b/whd-bsp-integration/cybsp_wifi.c @@ -0,0 +1,746 @@ +/***********************************************************************************************//** + * \file cybsp_wifi.c + * + * \brief + * Provides utility functions that are used by board support packages. + * + *************************************************************************************************** + * \copyright + * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +#include "cybsp.h" +#include "cybsp_wifi.h" +#include "cy_network_buffer.h" +#include "cyabs_rtos.h" +#include "whd_types.h" +#include "cyhal.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * \addtogroup group_bsp_wifi + * \{ + * Macros to abstract out whether the LEDs & Buttons are wired high or active low. + */ + +/** Defines the amount of stack memory available for the wifi thread. */ +#if !defined(CY_WIFI_THREAD_STACK_SIZE) +#define CY_WIFI_THREAD_STACK_SIZE (5120) +#endif + +/** Defines the priority of the thread that services wifi packets. Legal values are defined by the + * RTOS being used. + */ +#if !defined(CY_WIFI_THREAD_PRIORITY) +#define CY_WIFI_THREAD_PRIORITY (CY_RTOS_PRIORITY_HIGH) +#endif + +/** Defines the country this will operate in for wifi initialization parameters. See the + * wifi-host-driver's whd_country_code_t for legal options. + */ +#if !defined(CY_WIFI_COUNTRY) +#define CY_WIFI_COUNTRY (WHD_COUNTRY_AUSTRALIA) +#endif + +/** Defines the priority of the interrupt that handles out-of-band notifications from the wifi + * chip. Legal values are defined by the MCU running this code. + */ +#if !defined(CY_WIFI_OOB_INTR_PRIORITY) + #define CY_WIFI_OOB_INTR_PRIORITY (2) +#endif + +/** Defines whether to use the out-of-band pin to allow the WIFI chip to wake up the MCU. */ +#if defined(CY_WIFI_HOST_WAKE_SW_FORCE) + #define CY_USE_OOB_INTR (CY_WIFI_HOST_WAKE_SW_FORCE) +#else + #define CY_USE_OOB_INTR (1u) +#endif // defined(CY_WIFI_HOST_WAKE_SW_FORCE) + +/** \} group_bsp_wifi */ + +#define DEFAULT_OOB_PIN (0) +#define WLAN_POWER_UP_DELAY_MS (250) +#define WLAN_CBUCK_DISCHARGE_MS (10) + +#if defined(COMPONENT_WIFI_INTERFACE_SDIO) || \ + defined(COMPONENT_WIFI_INTERFACE_SPI) || \ + defined(COMPONENT_WIFI_INTERFACE_M2M) + +// Old versions of the BSP performed WIFI SDIO init as part of cybsp_init() this has been replaced +// with just minimal resource reservation when needed in the latest versions of BSPs. +#define CYBSP_WIFI_SDIO_NEEDS_INIT (1) + +#else + +#if (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SDIO_INTERFACE) +#define COMPONENT_WIFI_INTERFACE_SDIO +#elif (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SPI_INTERFACE) +#define COMPONENT_WIFI_INTERFACE_SPI +#elif (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_M2M_INTERFACE) +#define COMPONENT_WIFI_INTERFACE_M2M +#else +// For old versions of HAL/BSP fallback to the default interface +#define COMPONENT_WIFI_INTERFACE_SDIO +#endif + +#endif // if defined(COMPONENT_WIFI_INTERFACE_SDIO) || defined(COMPONENT_WIFI_INTERFACE_SPI) || +// defined(COMPONENT_WIFI_INTERFACE_M2M) + +#if !defined(COMPONENT_WIFI_INTERFACE_M2M) + +#define SDIO_ENUMERATION_TRIES (500) +#define SDIO_RETRY_DELAY_MS (1) +#define SDIO_BUS_LEVEL_MAX_RETRIES (5) + +#define SDIO_FREQ_25MHZ (25000000) +#define SDIO_FREQ_50MHZ (50000000) + +// Switching to 1.8 Request / Switching to 1.8V Accepted +#define SDIO_CMD5_S18R_BIT (1UL << 24) +// Number of I/O functions position in CMD5 response (R4) +#define SDIO_CMD5_RESP_IO_FUNC_POS (28) +// Mask of I/O Number in CMD5 response (R4). This field is 3-bit wide +#define SDIO_CMD5_RESP_IO_FUNC_MSK (0x7) +// The IO OCR register mask in CMD5 request / response (R4) +#define SDIO_CMD5_IO_OCR_MSK (0x00FFFFFFUL) +// C bit in CMD5 response. Set to 1 if Card is ready to operate after initialization +#define SDIO_CMD5_RESP_IORDY (1UL << 31) + +// Per SDIO Specification - IO_RW_DIRECT Command (CMD52) + +// This bit determines the direction of the I/O operation. If this bit is 0, this command shall read +// data from the SDIO +#define SDIO_CMD52_ARG_RW_READ (0) +#define SDIO_CMD52_ARG_RW_WRITE (1) +// The Read after Write flag. If this bit is set to 1 and the R/W flag is set to 1, then the command +// shall read the value of the register after the write +#define SDIO_CMD52_ARG_RAW_NOT_SET (0) +#define SDIO_CMD52_ARG_RAW_SET (1) +// The number of the function within the I/O card you wish to read or write. Function 0 selects the +// common I/O area (CIA) +#define SDIO_FUNC_NUM_0 (0) + +// Per SDIO Specification -Card Common Control Registers (CCCR) + +// Bus Speed Select register +#define SDIO_CMD52_CCCR_SPEED_SLCT_ADDR (0x00013) +// Select High Speed by setting BSS0 bit +#define SDIO_CMD52_CCCR_SPEED_SLCT_HS (0x2) + +// Per SDIO specification - IO_RW_DIRECT Response (R5) + +// | Start | Dir | CMD Index | Stuff | Response Flags Bit | Read or Write Data | CRC7 | End | +// ------------------------------------------------------------------------------------------ +// | 1 | 1 | 6 | 16 | 8 | 8 | 7 | 1 | + +// Expected response for High Speed support check command +// | CMD=DAT lines free | High-Speed support | +// | 00010000b | 00000001b | +#define SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SUPPORTED (0x00001001) +// Expected response for High Speed support check command +// | CMD=DAT lines free | HS/SDR25 activated | +// | 00010000b | 00000010b | +#define SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SELECTED (0x00001002) + +// *SUSPEND-FORMATTING* +#if (CY_USE_OOB_INTR != 0) + // Setup configuration based on configurator or BSP, where configurator has precedence. + #if defined(CYCFG_WIFI_HOST_WAKE_ENABLED) + #define CY_WIFI_HOST_WAKE_GPIO CYCFG_WIFI_HOST_WAKE_GPIO + #define CY_WIFI_HOST_WAKE_IRQ_EVENT CYCFG_WIFI_HOST_WAKE_IRQ_EVENT + #else + // Setup host-wake pin + #if defined(CYBSP_WIFI_HOST_WAKE) + #define CY_WIFI_HOST_WAKE_GPIO CYBSP_WIFI_HOST_WAKE + #else + #error "CYBSP_WIFI_HOST_WAKE must be defined" + #endif + // Setup host-wake irq + #if defined(CYBSP_WIFI_HOST_WAKE_IRQ_EVENT) + #define CY_WIFI_HOST_WAKE_IRQ_EVENT CYBSP_WIFI_HOST_WAKE_IRQ_EVENT + #else + #error "CYBSP_WIFI_HOST_WAKE_IRQ_EVENT must be defined" + #endif + #endif // if defined(CYCFG_WIFI_HOST_WAKE_ENABLED) +#else // if (CY_USE_OOB_INTR != 0) + #define CY_WIFI_HOST_WAKE_GPIO CYHAL_NC_PIN_VALUE + #define CY_WIFI_HOST_WAKE_IRQ_EVENT 0 +#endif // (CY_USE_OOB_INTR != 0) +// *RESUME-FORMATTING* + +// Add compatability for HAL 1.x +#if !defined(CYHAL_API_VERSION) +typedef cyhal_transfer_t cyhal_sdio_transfer_type_t; +#define CYHAL_SDIO_XFER_TYPE_READ CYHAL_READ +#define CYHAL_SDIO_XFER_TYPE_WRITE CYHAL_WRITE +#endif + +#endif // if !defined(COMPONENT_WIFI_INTERFACE_M2M) + +static whd_driver_t whd_drv; + +extern whd_resource_source_t resource_ops; + +static whd_init_config_t init_config_default = +{ + .thread_stack_size = CY_WIFI_THREAD_STACK_SIZE, + .thread_stack_start = NULL, + .thread_priority = (uint32_t)CY_WIFI_THREAD_PRIORITY, + .country = CY_WIFI_COUNTRY +}; + +static whd_buffer_funcs_t buffer_if_default = +{ + .whd_host_buffer_get = cy_host_buffer_get, + .whd_buffer_release = cy_buffer_release, + .whd_buffer_get_current_piece_data_pointer = cy_buffer_get_current_piece_data_pointer, + .whd_buffer_get_current_piece_size = cy_buffer_get_current_piece_size, + .whd_buffer_set_size = cy_buffer_set_size, + .whd_buffer_add_remove_at_front = cy_buffer_add_remove_at_front, +}; + +static whd_netif_funcs_t netif_if_default = +{ + .whd_network_process_ethernet_data = cy_network_process_ethernet_data, +}; + +#if !defined(COMPONENT_WIFI_INTERFACE_M2M) +static const whd_oob_config_t OOB_CONFIG = +{ + .host_oob_pin = CY_WIFI_HOST_WAKE_GPIO, + .dev_gpio_sel = DEFAULT_OOB_PIN, + .is_falling_edge = (CY_WIFI_HOST_WAKE_IRQ_EVENT == CYHAL_GPIO_IRQ_FALL) + ? WHD_TRUE + : WHD_FALSE, + .intr_priority = CY_WIFI_OOB_INTR_PRIORITY +}; + + +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_reset_wifi_chip +//-------------------------------------------------------------------------------------------------- +static void _cybsp_wifi_reset_wifi_chip(void) +{ + // WiFi into reset + // Allow CBUCK regulator to discharge + (void)cyhal_system_delay_ms(WLAN_CBUCK_DISCHARGE_MS); + // WiFi out of reset + cyhal_gpio_write(CYBSP_WIFI_WL_REG_ON, true); + (void)cyhal_system_delay_ms(WLAN_POWER_UP_DELAY_MS); +} + + +#endif // if !defined(COMPONENT_WIFI_INTERFACE_M2M) + + +#if defined(COMPONENT_WIFI_INTERFACE_SDIO) +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_sdio_try_send_cmd +//-------------------------------------------------------------------------------------------------- +static cy_rslt_t _cybsp_wifi_sdio_try_send_cmd(cyhal_sdio_t* sdio_object, + cyhal_sdio_transfer_type_t direction, + cyhal_sdio_command_t command, uint32_t argument, + uint32_t* response) +{ + uint8_t loop_count = 0; + cy_rslt_t result = CYBSP_RSLT_WIFI_SDIO_ENUM_TIMEOUT; + do + { + result = cyhal_sdio_send_cmd(sdio_object, direction, command, argument, response); + if (result != CY_RSLT_SUCCESS) + { + cyhal_system_delay_ms(SDIO_RETRY_DELAY_MS); + } + loop_count++; + } while((result != CY_RSLT_SUCCESS) && (loop_count <= SDIO_BUS_LEVEL_MAX_RETRIES)); + return result; +} + + +#if !defined(CYHAL_UDB_SDIO) +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_create_cmd_52_arg +//-------------------------------------------------------------------------------------------------- +static uint32_t _cybsp_wifi_create_cmd_52_arg(uint8_t rw, uint8_t func, uint8_t raw, uint32_t addr, + uint8_t data) +{ + return (((rw & 0x01) << 31) /* set R/W flag */ + | ((func & 0x07) << 28) /* set the function number */ + | ((raw & 0x01) << 27) /* set the RAW flag */ + | ((addr & 0x1FFFF) << 9) /* set the address */ + | data); /* set the data */ +} + + +#endif /* !defined(CYHAL_UDB_SDIO) */ + +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_sdio_card_init +//-------------------------------------------------------------------------------------------------- +static cy_rslt_t _cybsp_wifi_sdio_card_init(cyhal_sdio_t* sdio_object) +{ + cy_rslt_t result; + uint32_t loop_count = 0; + uint32_t rel_addr; + + uint32_t response = 0; + uint32_t no_argument = 0; + + #if !defined(CYHAL_UDB_SDIO) + uint32_t argument = 0; + uint32_t io_num = 0; + bool abort_sdio = false; + #else + const bool abort_sdio = false; + #endif /* !defined(CYHAL_UDB_SDIO) */ + + do + { + // Send CMD0 to set it to idle state + result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE, + CYHAL_SDIO_CMD_GO_IDLE_STATE, + no_argument, &response /*ignored*/); + + // CMD5. + if (result == CY_RSLT_SUCCESS) + { + result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_READ, + CYHAL_SDIO_CMD_IO_SEND_OP_COND, + no_argument, + &response /*ignored on UDB-based SDIO*/); + } + + // UDB-based SDIO does not support io volt switch sequence + #if !defined(CYHAL_UDB_SDIO) + if (result == CY_RSLT_SUCCESS) + { + // Check number of IO functions, that are supported by device + io_num = (response >> SDIO_CMD5_RESP_IO_FUNC_POS) & SDIO_CMD5_RESP_IO_FUNC_MSK; + if (io_num > 0) + { + // Sending 1.8V switch request + argument = (response & SDIO_CMD5_IO_OCR_MSK) | SDIO_CMD5_S18R_BIT; + + // CMD5. + result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE, + CYHAL_SDIO_CMD_IO_SEND_OP_COND, + argument, &response); + + if (CY_RSLT_SUCCESS == result) + { + // IORDY = 1 (Card is ready to operate) + if (response & SDIO_CMD5_RESP_IORDY) + { + // Switching to 1.8V accepted + if (response & SDIO_CMD5_S18R_BIT) + { + // CMD11. + result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, + CYHAL_SDIO_XFER_TYPE_WRITE, + CYHAL_SDIO_CMD_VOLTAGE_SWITCH, + no_argument, + &response); + + if (CY_RSLT_SUCCESS == result) + { + #if defined(CYBSP_WIFI_SDIO_VOLT_SEL) + cyhal_gpio_t io_volt_sel_pin = CYBSP_WIFI_SDIO_VOLT_SEL; + #else + // No actual voltage switch will be done as no pin provided. + cyhal_gpio_t io_volt_sel_pin = NC; + #endif /* defined(CYBSP_WIFI_SDIO_VOLT_SEL) */ + + // Perform voltage switch sequence + // And, if pin provided, switch the voltage + result = cyhal_sdio_set_io_voltage(sdio_object, io_volt_sel_pin, + CYHAL_SDIO_IO_VOLTAGE_1_8V, + CYHAL_SDIO_IO_VOLT_ACTION_SWITCH_SEQ_ONLY); + + if (CYHAL_SDIO_RSLT_ERR_UNSUPPORTED == result) + { + // Changing IO voltage is not supported by current + // implementation. No reason to try again. + abort_sdio = true; + } + } + } + // Nothing to do for 'else'. 1.8V is not supported. + } + else + { + result = CYBSP_RSLT_WIFI_SDIO_ENUM_NOT_READY; + } + } + } + else + { + result = CYBSP_RSLT_WIFI_SDIO_ENUM_IO_NOT_SUPPORTED; + // IO is not supported by this SD device, no reason to try enumeration again + abort_sdio = true; + } + } + #endif /* !defined(CYHAL_UDB_SDIO) */ + + if (CY_RSLT_SUCCESS == result) + { + // Send CMD3 to get RCA. + result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_READ, + CYHAL_SDIO_CMD_SEND_RELATIVE_ADDR, + no_argument, &rel_addr); + } + + if ((!abort_sdio) && (result != CY_RSLT_SUCCESS)) + { + cyhal_system_delay_ms(SDIO_RETRY_DELAY_MS); + } + loop_count++; + } while ((!abort_sdio) && (result != CY_RSLT_SUCCESS) && + (loop_count <= SDIO_ENUMERATION_TRIES)); + + if (result == CY_RSLT_SUCCESS) + { + // Send CMD7 with the returned RCA to select the card + result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE, + CYHAL_SDIO_CMD_SELECT_CARD, + rel_addr, + &response /*ignored*/); + } + + uint32_t sdio_frequency = SDIO_FREQ_25MHZ; + + // use constant 25 MHz frequency for UDB-based SDIO + // and perform supported speed check and switch for SDHC-based SDIO + #if !defined(CYHAL_UDB_SDIO) + if (result == CY_RSLT_SUCCESS) + { + uint32_t tmp_arg = _cybsp_wifi_create_cmd_52_arg(SDIO_CMD52_ARG_RW_READ, SDIO_FUNC_NUM_0, + SDIO_CMD52_ARG_RAW_NOT_SET, + SDIO_CMD52_CCCR_SPEED_SLCT_ADDR, 0x00); + result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE, + CYHAL_SDIO_CMD_IO_RW_DIRECT, + tmp_arg, &response); + + if (result == CY_RSLT_SUCCESS) + { + if (SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SUPPORTED == response) + { + tmp_arg = _cybsp_wifi_create_cmd_52_arg(SDIO_CMD52_ARG_RW_WRITE, SDIO_FUNC_NUM_0, + SDIO_CMD52_ARG_RAW_NOT_SET, + SDIO_CMD52_CCCR_SPEED_SLCT_ADDR, + SDIO_CMD52_CCCR_SPEED_SLCT_HS); + result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE, + CYHAL_SDIO_CMD_IO_RW_DIRECT, + tmp_arg, &response); + + if (result == CY_RSLT_SUCCESS) + { + if (SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SELECTED == response) + { + // High Speed mode switch allowed, configure clock frequency for 50 MHz + sdio_frequency = SDIO_FREQ_50MHZ; + } + } + else + { + result = CYBSP_RSLT_WIFI_SDIO_HS_SWITCH_FAILED; + } + } + } + } + #endif /* !defined(CYHAL_UDB_SDIO) */ + + if (result == CY_RSLT_SUCCESS) + { + cyhal_sdio_cfg_t config = { .frequencyhal_hz = sdio_frequency, .block_size = 0 }; + result = cyhal_sdio_configure(sdio_object, &config); + } + return result; +} + + +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_sdio_init_bus2 +//-------------------------------------------------------------------------------------------------- +static cy_rslt_t _cybsp_wifi_sdio_init_bus2(cyhal_sdio_t* obj) +{ + cy_rslt_t result = _cybsp_wifi_sdio_card_init(obj); + if (result == CY_RSLT_SUCCESS) + { + // If the configurator reserved the pin, we need to release it here since + // WHD will try to reserve it again. WHD has no idea about configurators + // and expects it can reserve the pin that it is going to manage. + #if defined(CYCFG_WIFI_HOST_WAKE_ENABLED) + cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(CY_WIFI_HOST_WAKE_GPIO); + cyhal_hwmgr_free(&pinRsc); + #endif + + whd_sdio_config_t whd_sdio_config = + { + .sdio_1bit_mode = WHD_FALSE, + .high_speed_sdio_clock = WHD_FALSE, + .oob_config = OOB_CONFIG + }; + whd_bus_sdio_attach(whd_drv, &whd_sdio_config, obj); + } + return result; +} + + +#if defined(CYBSP_WIFI_SDIO_NEEDS_INIT) +static cyhal_sdio_t sdio_obj; +#endif + +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_sdio_init_bus +//-------------------------------------------------------------------------------------------------- +static cy_rslt_t _cybsp_wifi_sdio_init_bus(void) +{ + #if defined(CYBSP_WIFI_SDIO_NEEDS_INIT) + cy_rslt_t result = cyhal_sdio_init(&sdio_obj, CYBSP_WIFI_SDIO_CMD, CYBSP_WIFI_SDIO_CLK, + CYBSP_WIFI_SDIO_D0, CYBSP_WIFI_SDIO_D1, CYBSP_WIFI_SDIO_D2, + CYBSP_WIFI_SDIO_D3); + + if (result == CY_RSLT_SUCCESS) + { + result = _cybsp_wifi_sdio_init_bus2(&sdio_obj); + if (result != CY_RSLT_SUCCESS) + { + cyhal_sdio_free(&sdio_obj); + } + } + #else // if defined(CYBSP_WIFI_SDIO_NEEDS_INIT) + cyhal_sdio_t* sdio_p = cybsp_get_wifi_sdio_obj(); + cy_rslt_t result = _cybsp_wifi_sdio_init_bus2(sdio_p); + #endif // if defined(CYBSP_WIFI_SDIO_NEEDS_INIT) + + return result; +} + + +#elif defined(COMPONENT_WIFI_INTERFACE_SPI) + +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_spi_init_bus +//-------------------------------------------------------------------------------------------------- +static cy_rslt_t _cybsp_wifi_spi_init_bus(void) +{ + static cyhal_spi_t spi_obj; + cy_rslt_t rslt = cyhal_spi_init(&spi_obj, + CYBSP_WIFI_SPI_MOSI, CYBSP_WIFI_SPI_MISO, CYBSP_WIFI_SPI_SCLK, + CYBSP_WIFI_SPI_SSEL, + NULL, 32, CYHAL_SPI_MODE_00_MSB, false); + if (CY_RSLT_SUCCESS == rslt) + { + rslt = cyhal_spi_set_frequency(&spi_obj, 50000000); // 50 MHz operation + if (CY_RSLT_SUCCESS == rslt) + { + whd_spi_config_t whd_spi_config = + { + .is_normal_mode = false, + .oob_config = OOB_CONFIG + }; + rslt = whd_bus_spi_attach(whd_drv, &whd_spi_config, &spi_obj); + } + else + { + cyhal_spi_free(&spi_obj); + } + } + + return rslt; +} + + +#elif defined(COMPONENT_WIFI_INTERFACE_M2M) + +static cyhal_m2m_t m2m_obj; + +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_m2m_init_bus +//-------------------------------------------------------------------------------------------------- +static cy_rslt_t _cybsp_wifi_m2m_init_bus(void) +{ + cy_rslt_t rslt; + + whd_m2m_config_t whd_m2m_config = + { + .is_normal_mode = false, + }; + // Note: The m2m itself is initialized in the WHD + rslt = whd_bus_m2m_attach(whd_drv, &whd_m2m_config, &m2m_obj); + + return rslt; +} + + +#endif // defined(COMPONENT_WIFI_INTERFACE_M2M) + + +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_bus_init +//-------------------------------------------------------------------------------------------------- +static inline cy_rslt_t _cybsp_wifi_bus_init(void) +{ + #if !defined(COMPONENT_WIFI_INTERFACE_M2M) + _cybsp_wifi_reset_wifi_chip(); + #endif + #if defined(COMPONENT_WIFI_INTERFACE_SDIO) + return _cybsp_wifi_sdio_init_bus(); + #elif defined(COMPONENT_WIFI_INTERFACE_SPI) + return _cybsp_wifi_spi_init_bus(); + #elif defined(COMPONENT_WIFI_INTERFACE_M2M) + return _cybsp_wifi_m2m_init_bus(); + #endif +} + + +//-------------------------------------------------------------------------------------------------- +// _cybsp_wifi_bus_detach +//-------------------------------------------------------------------------------------------------- +static inline void _cybsp_wifi_bus_detach(void) +{ + #if defined(COMPONENT_WIFI_INTERFACE_SDIO) + whd_bus_sdio_detach(whd_drv); + #elif defined(COMPONENT_WIFI_INTERFACE_SPI) + whd_bus_spi_detach(whd_drv); + #elif defined(COMPONENT_WIFI_INTERFACE_M2M) + whd_bus_m2m_detach(whd_drv); + #endif +} + + +//-------------------------------------------------------------------------------------------------- +// cybsp_wifi_init_primary_extended +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cybsp_wifi_init_primary_extended(whd_interface_t* interface, + whd_init_config_t* init_config, + whd_resource_source_t* resource_if, + whd_buffer_funcs_t* buffer_if, + whd_netif_funcs_t* netif_if) +{ + #if defined(COMPONENT_WIFI_INTERFACE_M2M) + cy_rslt_t result = CY_RSLT_SUCCESS; + #else + cy_rslt_t result = cyhal_gpio_init(CYBSP_WIFI_WL_REG_ON, CYHAL_GPIO_DIR_OUTPUT, + CYHAL_GPIO_DRIVE_PULLUP, false); + #endif + + if (result == CY_RSLT_SUCCESS) + { + if (init_config == NULL) + { + init_config = &init_config_default; + } + if (resource_if == NULL) + { + resource_if = &resource_ops; + } + if (buffer_if == NULL) + { + buffer_if = &buffer_if_default; + } + if (netif_if == NULL) + { + netif_if = &netif_if_default; + } + + result = whd_init(&whd_drv, init_config, resource_if, buffer_if, netif_if); + if (result == CY_RSLT_SUCCESS) + { + result = _cybsp_wifi_bus_init(); + + if (result == CY_RSLT_SUCCESS) + { + result = whd_wifi_on(whd_drv, interface); + + if (result != CY_RSLT_SUCCESS) + { + _cybsp_wifi_bus_detach(); + } + } + + if (result != CY_RSLT_SUCCESS) + { + whd_deinit(*interface); + } + } + + #if !defined(COMPONENT_WIFI_INTERFACE_M2M) + if (result != CY_RSLT_SUCCESS) + { + cyhal_gpio_free(CYBSP_WIFI_WL_REG_ON); + } + #endif + } + + return result; +} + + +//-------------------------------------------------------------------------------------------------- +// cybsp_wifi_init_secondary +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cybsp_wifi_init_secondary(whd_interface_t* interface, whd_mac_t* mac_address) +{ + return whd_add_secondary_interface(whd_drv, mac_address, interface); +} + + +//-------------------------------------------------------------------------------------------------- +// cybsp_wifi_deinit +//-------------------------------------------------------------------------------------------------- +cy_rslt_t cybsp_wifi_deinit(whd_interface_t interface) +{ + cy_rslt_t result = whd_wifi_off(interface); + + if (result == CY_RSLT_SUCCESS) + { + _cybsp_wifi_bus_detach(); + #if !defined(COMPONENT_WIFI_INTERFACE_M2M) + cyhal_gpio_free(CYBSP_WIFI_WL_REG_ON); + #endif + // While deinit() takes an interface, it only uses it to get the underlying whd driver to + // cleanup. As a result, we only need to call this on one of the interfaces. + result = whd_deinit(interface); + + #if defined(CYBSP_WIFI_SDIO_NEEDS_INIT) + if (result == CY_RSLT_SUCCESS) + { + cyhal_sdio_free(&sdio_obj); + } + #endif + } + return result; +} + + +//-------------------------------------------------------------------------------------------------- +// cybsp_get_wifi_driver +//-------------------------------------------------------------------------------------------------- +whd_driver_t cybsp_get_wifi_driver(void) +{ + return whd_drv; +} + + +#if defined(__cplusplus) +} +#endif diff --git a/whd-bsp-integration/cybsp_wifi.h b/whd-bsp-integration/cybsp_wifi.h new file mode 100644 index 00000000..65e705a2 --- /dev/null +++ b/whd-bsp-integration/cybsp_wifi.h @@ -0,0 +1,143 @@ +/***********************************************************************************************//** + * \file cybsp_wifi.h + * + * \brief + * Basic abstraction layer for dealing with boards containing a Cypress MCU. This + * API provides convenience methods for initializing and manipulating different + * hardware found on the board. + * + *************************************************************************************************** + * \copyright + * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **************************************************************************************************/ + +/** + * \addtogroup group_bsp_wifi WiFi Initialization + * \{ + * Basic integration code for interfacing the WiFi Host Driver (WHD) with the Board + * Support Packages (BSPs). + */ +#pragma once + +#include "cy_result.h" +#include "whd_wifi_api.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** Initialization of the WiFi driver failed. */ +#define CYBSP_RSLT_WIFI_INIT_FAILED \ + (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_WHD_INTEGRATION, 0)) + +/** SDIO enumeration failed. */ +#define CYBSP_RSLT_WIFI_SDIO_ENUM_TIMEOUT \ + (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_WHD_INTEGRATION, 1)) + +/** SD device does not support IO functionality */ +#define CYBSP_RSLT_WIFI_SDIO_ENUM_IO_NOT_SUPPORTED \ + (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_WHD_INTEGRATION, 2)) + +/** SDIO device is not ready */ +#define CYBSP_RSLT_WIFI_SDIO_ENUM_NOT_READY \ + (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_WHD_INTEGRATION, 3)) + +/** SDIO switch to High Speed mode failed. */ +#define CYBSP_RSLT_WIFI_SDIO_HS_SWITCH_FAILED \ + (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_WHD_INTEGRATION, 4)) + +/** Initializes the primary interface for the WiFi driver on the board. This sets up + * the WHD interface to use the \ref group_bsp_network_buffer APIs and to communicate + * over the SDIO interface on the board. This function does the following:
+ * 1) Initializes the WiFi driver.
+ * 2) Turns on the WiFi chip. + * + * @note This function cannot be called multiple times. If the interface needs to be + * reinitialized, \ref cybsp_wifi_deinit must be called before calling this function + * again. + * + * @param[out] interface Interface to be initialized + * @param[in] init_config Pointer to the configuration parameters to initialize the driver. + * Passing NULL will use default values. + * @param[in] resource_if Pointer to resource interface to provide resources to the driver + * initialization process. Passing NULL will use the default. + * @param[in] buffer_if Pointer to a buffer interface to provide buffer related services to the + * driver instance. Passing NULL will use the default. + * @param[in] netif_if Pointer to a whd_netif_funcs_t to provide network stack services to the + * driver instance. Passing NULL will use the default. + * + * @return CY_RSLT_SUCCESS for successful initialization or error if initialization failed. + */ +cy_rslt_t cybsp_wifi_init_primary_extended(whd_interface_t* interface, + whd_init_config_t* init_config, + whd_resource_source_t* resource_if, + whd_buffer_funcs_t* buffer_if, + whd_netif_funcs_t* netif_if); + +/** + * Initializes the primary interface for the WiFi driver on the board using the default + * configuration, resource, buffer, and network interfaces. + * See cybsp_wifi_init_primary_extended() for more details. + * + * @param[out] interface Interface to be initialized + * + * @return CY_RSLT_SUCCESS for successful initialization or error if initialization failed. + */ +static inline cy_rslt_t cybsp_wifi_init_primary(whd_interface_t* interface) +{ + return cybsp_wifi_init_primary_extended(interface, NULL, NULL, NULL, NULL); +} + + +/** This function initializes and adds a secondary interface to the WiFi driver. + * @note This function does not initialize the WiFi driver or turn on the WiFi chip. + * That is required to be done by first calling \ref cybsp_wifi_init_primary. + * + * @param[out] interface Interface to be initialized + * @param[in] mac_address Mac address for secondary interface + * + * @return CY_RSLT_SUCCESS for successful initialization or error if initialization failed. + */ +cy_rslt_t cybsp_wifi_init_secondary(whd_interface_t* interface, whd_mac_t* mac_address); + +/** De-initializes all WiFi interfaces and the WiFi driver. This function does the + * following:
+ * 1) Deinitializes all WiFi interfaces.
+ * 2) Deinitializes the WiFi driver.
+ * 3) Turns off the WiFi chip. + * + * @param[in] interface Either the Primary or Secondary interface. + * + * @return CY_RSLT_SUCCESS for successful de-initialization or error if de-initialization failed. + */ +cy_rslt_t cybsp_wifi_deinit(whd_interface_t interface); + +/** Gets the wifi driver instance initialized by the driver. This should only be called + * after being initialized by \ref cybsp_wifi_init_primary() and before being + * deinitialized by \ref cybsp_wifi_deinit(). This is also the only time where the + * driver reference is valid. + * + * @return Wifi driver instance pointer. + */ +whd_driver_t cybsp_get_wifi_driver(void); + +#ifdef __cplusplus +} +#endif // __cplusplus + +/** \} group_bsp_wifi */ diff --git a/whd-bsp-integration/props.json b/whd-bsp-integration/props.json new file mode 100644 index 00000000..4a4af83d --- /dev/null +++ b/whd-bsp-integration/props.json @@ -0,0 +1,7 @@ +{ + "core": { + "id": "8d3bf5ea-9158-5310-aa34-a1ad1ee0c2ee", + "name": "whd-bsp-integration", + "version": "2.1.0.29660" + } +} \ No newline at end of file diff --git a/wifi-host-driver/LICENSE.txt b/wifi-host-driver/LICENSE.txt new file mode 100644 index 00000000..01d5e585 --- /dev/null +++ b/wifi-host-driver/LICENSE.txt @@ -0,0 +1,211 @@ +CYPRESS (AN INFINEON COMPANY) END USER LICENSE AGREEMENT + +PLEASE READ THIS END USER LICENSE AGREEMENT ("Agreement") CAREFULLY BEFORE +DOWNLOADING, INSTALLING, COPYING, OR USING THIS SOFTWARE AND ACCOMPANYING +DOCUMENTATION. BY DOWNLOADING, INSTALLING, COPYING OR USING THE SOFTWARE, +YOU ARE AGREEING TO BE BOUND BY THIS AGREEMENT. IF YOU DO NOT AGREE TO ALL +OF THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN AND DO NOT USE THE SOFTWARE. +IF YOU HAVE PURCHASED THIS LICENSE TO THE SOFTWARE, YOUR RIGHT TO RETURN THE +SOFTWARE EXPIRES 30 DAYS AFTER YOUR PURCHASE AND APPLIES ONLY TO THE ORIGINAL +PURCHASER. + +1. Definitions. + + "Software" means this software and any accompanying documentation, + including any upgrades, updates, bug fixes or modified versions provided + to you by Cypress. + + "Source Code" means software in human-readable form. + + "Binary Code" means the software in binary code form such as object code or + an executable. + + "Development Tools" means software that is intended to be installed on a + personal computer and used to create programming code for Firmware, + Drivers, or Host Applications. Examples of Development Tools are + Cypress's PSoC Creator software, Cypress's AIROC SDKs, and Cypress's + ModusToolbox software. + + "Firmware" means software that executes on a Cypress hardware product. + + "Driver" means software that enables the use of a Cypress hardware product + on a particular host operating system such as GNU/Linux, Windows, MacOS, + Android, and iOS. + + "Host Application" means software that executes on a device other than a + Cypress hardware product in order to program, control, or communicate + with a Cypress hardware product. + + "inf File" means a hardware setup information file (.inf file) created by + the Software to allow a Microsoft Windows operating system to install + the driver for a Cypress hardware product. + +2. License. Subject to the terms and conditions of this Agreement, Cypress +Semiconductor Corporation ("Cypress") and its suppliers grant to you a +non-exclusive, non-transferable license under their copyright rights: + + a. to use the Development Tools in object code form solely for the purpose + of creating Firmware, Drivers, Host Applications, and inf Files for + Cypress hardware products; and + + b. (i) if provided in Source Code form, to copy, modify, and compile the + Firmware Source Code to create Firmware for execution on a Cypress + hardware product, and + (ii) to distribute Firmware in binary code form only, only when + installed onto a Cypress hardware product; and + + c. (i) if provided in Source Code form, to copy, modify, and compile the + Driver Source Code to create one or more Drivers to enable the use + of a Cypress hardware product on a particular host operating + system, and + (ii) to distribute the Driver, in binary code form only, only when + installed on a device that includes the Cypress hardware product + that the Driver is intended to enable; and + + d. (i) if provided in Source Code form, to copy, modify, and compile the + Host Application Source Code to create one or more Host + Applications to program, control, or communicate with a Cypress + hardware product, and + (ii) to distribute Host Applications, in binary code form only, only + when installed on a device that includes a Cypress hardware product + that the Host Application is intended to program, control, or + communicate with; and + + e. to freely distribute any inf File. + +Any distribution of Software permitted under this Agreement must be made +pursuant to your standard end user license agreement used for your proprietary +(closed source) software products, such end user license agreement to include, +at a minimum, provisions limiting your licensors' liability and prohibiting +reverse engineering of the Software, consistent with such provisions in this +Agreement. + +3. Free and Open Source Software. Portions of the Software may be licensed +under free and/or open source licenses such as the GNU General Public License +or other licenses from third parties ("Third Party Software"). Third Party +Software is subject to the applicable license agreement and not this +Agreement. If you are entitled to receive the source code from Cypress for +any Third Party Software included with the Software, either the source code +will be included with the Software or you may obtain the source code at no +charge from +. +The applicable license terms will accompany each source code package. To +review the license terms applicable to any Third Party Software for which +Cypress is not required to provide you with source code, please see the +Software's installation directory on your computer. + +4. Proprietary Rights; Ownership. The Software, including all intellectual +property rights therein, is and will remain the sole and exclusive property of +Cypress or its suppliers. Cypress retains ownership of the Source Code and +any compiled version thereof. Subject to Cypress' ownership of the underlying +Software (including Source Code), you retain ownership of any modifications +you make to the Source Code. You agree not to remove any Cypress copyright or +other notices from the Source Code and any modifications thereof. You agree +to keep the Source Code confidential. Any reproduction, modification, +translation, compilation, or representation of the Source Code except as +permitted in Section 2 ("License") is prohibited without the express written +permission of Cypress. Except as otherwise expressly provided in this +Agreement, you may not: + (i) modify, adapt, or create derivative works based upon the Software; + (ii) copy the Software; + (iii) except and only to the extent explicitly permitted by applicable + law despite this limitation, decompile, translate, reverse engineer, + disassemble or otherwise reduce the Software to human-readable form; + or + (iv) use the Software or any sample code other than for the Purpose. +You hereby covenant that you will not assert any claim that the Software, or +derivative works thereof created by or for Cypress, infringe any intellectual +property right owned or controlled by you + +5. No Support. Cypress may, but is not required to, provide technical support +for the Software. + +6. Term and Termination. This Agreement is effective until terminated, and +either party may terminate this Agreement at any time with or without cause. +This Agreement and your license rights under this Agreement will terminate +immediately without notice from Cypress if you fail to comply with any +provision of this Agreement. Upon termination, you must destroy all copies of +Software in your possession or control. The following paragraphs shall +survive any termination of this Agreement: "Free and Open Source Software," +"Proprietary Rights; Ownership," "Compliance With Law," "Disclaimer," +"Limitation of Liability," and "General." + +7. Compliance With Law. Each party agrees to comply with all applicable laws, +rules and regulations in connection with its activities under this Agreement. +Without limiting the foregoing, the Software may be subject to export control +laws and regulations of the United States and other countries. You agree to +comply strictly with all such laws and regulations and acknowledge that you +have the responsibility to obtain licenses to export, re-export, or import the +Software. + +8. Disclaimer. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, CYPRESS +MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THE +SOFTWARE, INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress +reserves the right to make changes to the Software without notice. Cypress +does not assume any liability arising out of the application or use of +Software or any product or circuit described in the Software. It is the +responsibility of the user of the Software to properly design, program, and +test the functionality and safety of any application made of the Software and +any resulting product. Cypress does not authorize its Software or products +for use in any products where a malfunction or failure of the Software or +Cypress product may reasonably be expected to result in significant property +damage, injury or death ("High Risk Product"). If you include any Software or +Cypress product in a High Risk Product, you assume all risk of such use and +agree to indemnify Cypress and its suppliers against all liability. No +computing device can be absolutely secure. Therefore, despite security +measures implemented in Cypress hardware or software products, Cypress does +not assume any liability arising out of any security breach, such as +unauthorized access to or use of a Cypress product. + +9. Limitation of Liability. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE +LAW, IN NO EVENT WILL CYPRESS OR ITS SUPPLIERS, RESELLERS, OR DISTRIBUTORS BE +LIABLE FOR ANY LOST REVENUE, PROFIT, OR DATA, OR FOR SPECIAL, INDIRECT, +CONSEQUENTIAL, INCIDENTAL, OR PUNITIVE DAMAGES HOWEVER CAUSED AND REGARDLESS +OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO THE USE OF OR +INABILITY TO USE THE SOFTWARE EVEN IF CYPRESS OR ITS SUPPLIERS, RESELLERS, OR +DISTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN NO +EVENT SHALL CYPRESS' OR ITS SUPPLIERS', RESELLERS', OR DISTRIBUTORS' TOTAL +LIABILITY TO YOU, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), OR +OTHERWISE, EXCEED THE GREATER OF US$500 OR THE PRICE PAID BY YOU FOR THE +SOFTWARE. THE FOREGOING LIMITATIONS SHALL APPLY EVEN IF THE ABOVE-STATED +WARRANTY FAILS OF ITS ESSENTIAL PURPOSE. BECAUSE SOME STATES OR JURISDICTIONS +DO NOT ALLOW LIMITATION OR EXCLUSION OF CONSEQUENTIAL OR INCIDENTAL DAMAGES, +ALL OR PORTIONS OF THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + +10. Restricted Rights. The Software is commercial computer software as that +term is described in 48 C.F.R. 252.227-7014(a)(1). If the Software is being +acquired by or on behalf of the U.S. Government or by a U.S. Government prime +contractor or subcontractor (at any tier), then the Government's rights in +Software shall be only those set forth in this Agreement. + +11. Personal Information. You agree that information you provide through your +registration on Cypress IoT Community Forum or other Cypress websites, +including contact information or other personal information, may be collected +and used by Cypress consistent with its Data Privacy Policy +(https://www.infineon.com/cms/en/about-infineon/privacy-policy/), as updated +or revised from time to time, and may be provided to its third party sales +representatives, distributors and other entities conducting sales activities +for Cypress for sales-related and other business purposes. + +12. General. This Agreement will bind and inure to the benefit of each +party's successors and assigns, provided that you may not assign or transfer +this Agreement, in whole or in part, without Cypress' written consent. This +Agreement shall be governed by and construed in accordance with the laws of +the State of California, United States of America, as if performed wholly +within the state and without giving effect to the principles of conflict of +law. The parties consent to personal and exclusive jurisdiction of and venue +in, the state and federal courts within Santa Clara County, California; +provided however, that nothing in this Agreement will limit Cypress' right to +bring legal action in any venue in order to protect or enforce its +intellectual property rights. No failure of either party to exercise or +enforce any of its rights under this Agreement will act as a waiver of such +rights. If any portion of this Agreement is found to be void or +unenforceable, the remaining provisions of this Agreement shall remain in full +force and effect. This Agreement is the complete and exclusive agreement +between the parties with respect to the subject matter hereof, superseding and +replacing any and all prior agreements, communications, and understandings +(both written and oral) regarding such subject matter. Any notice to Cypress +will be deemed effective when actually received and must be sent to Cypress +Semiconductor Corporation, ATTN: Chief Legal Officer, 198 Champion Court, San +Jose, CA 95134 USA. diff --git a/wifi-host-driver/README.md b/wifi-host-driver/README.md new file mode 100644 index 00000000..de91c640 --- /dev/null +++ b/wifi-host-driver/README.md @@ -0,0 +1,28 @@ +# Wi-Fi Host Driver (WHD) + +### Overview +The WHD is an independent, embedded Wi-Fi Host Driver that provides a set of APIs to interact with Infineon WLAN chips. The WHD is an independent firmware product that is easily portable to any embedded software environment, including popular IoT frameworks such as Mbed OS and Amazon FreeRTOS. Therefore, the WHD includes hooks for RTOS and TCP/IP network abstraction layers. + +The [release notes](./RELEASE.md) detail the current release. You can also find information about previous versions. + +### Supported bus interface +--------------------------------------------------- +| Interface |4343W|43438|4373 |43012|43439|43907| +|:-----------:|:---:|:---:|:---:|:---:|:---:|:---:| +| SDIO | O | O | O | O | O | | +| SPI | O | O | | | O | | +| M2M | | | | | | O | + +### WPA3 AP mode support +--------------------------------------------------- +| Security |4343W|43438|4373 |43012|43439|43907| +|:-----------:|:---:|:---:|:---:|:---:|:---:|:---:| +| WPA3 | | | O | | O | | + +### More information +* [Wi-Fi Host Driver API Reference Manual and Porting Guide](https://cypresssemiconductorco.github.io/wifi-host-driver/html/index.html) +* [Wi-Fi Host Driver Release Notes](./RELEASE.md) +* [Infineon Technologies](http://www.infineon.com) + +--- +© Infineon Technologies, 2019. diff --git a/wifi-host-driver/RELEASE.md b/wifi-host-driver/RELEASE.md new file mode 100644 index 00000000..979b7e11 --- /dev/null +++ b/wifi-host-driver/RELEASE.md @@ -0,0 +1,66 @@ +# Wi-Fi Host Driver (WHD) v2.5.0 +Please refer to the [README File](./README.md) and the [WHD API Reference Manual](https://cypresssemiconductorco.github.io/wifi-host-driver/html/index.html) for a complete description of the Wi-Fi Host Driver. + +## Features +* Supports Out-of-Band (OOB) +* Provides API functions for ARP, packet filters +* Supports Wi-Fi Station (STA) and AP mode of operation +* Supports concurrent operation of STA and AP interface +* Supports multiple security methods such as WPA2, WPA3, and open +* Provides functions for Advanced Power Management +* Supports low-power offloads, including ARP, packet filters, TCP Keepalive offload, DHCP lease time renewal offload, and Beacon trim +* Includes WFA pre-certification support for 802.11n and WPA3 + +## Changes since v2.4.0 +### New Features + + +### Defect Fixes +* Fix build errors on IAR toolchain + +### Known Issues + + +#### CYW4343W +* --- 7.45.98.120 --- + +#### CYW43012 +* --- 13.10.271.289 --- +* Apply SUTD Security Patches +* --- 13.10.271.287 --- + +#### CYW4373 +* --- 13.10.246.286 --- +* Apply SUTD Security Patches +* --- 13.10.246.279 --- + +#### CYW43439 +* --- 7.95.55 --- +* Apply SUTD Security Patches +* --- 7.95.54 --- + +#### CYW43909 +* --- 7.15.168.156 --- + +Note: [r] is regulatory-related + +## Supported Software and Tools +This version of the WHD was validated for compatibility with the following software and tools: + +| Software and Tools | Version | +| :--- | :---- | +| GCC Compiler | 10.3 | +| IAR Compiler | 9.3 | +| Arm Compiler 6 | 6.16 | +| Mbed OS | 6.2.0 | +| ThreadX/NetX-Duo | 5.8 | +| FreeRTOS/LWIP | 2.1.2 | + + +## More Information +* [Wi-Fi Host Driver README File](./README.md) +* [Wi-Fi Host Driver API Reference Manual and Porting Guide](https://cypresssemiconductorco.github.io/wifi-host-driver/html/index.html) +* [Infineon Technologies](http://www.infineon.com) + +--- +© Infineon Technologies, 2019. diff --git a/wifi-host-driver/WiFi_Host_Driver/inc/whd.h b/wifi-host-driver/WiFi_Host_Driver/inc/whd.h new file mode 100644 index 00000000..34b18bbf --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/inc/whd.h @@ -0,0 +1,88 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file whd.h + * Provides abstract pointer type to act as instance for: driver, interface, buffer funcs, network funcs, resource funcs and bus funcs. + */ + +#include "whd_types.h" + +#ifndef INCLUDED_WHD_H +#define INCLUDED_WHD_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Abstract pointer type that acts as a handle to an instance of the driver + */ +typedef struct whd_driver *whd_driver_t; +/** + * Abstract pointer type that acts as a handle to an instance of the bt base address + */ +typedef struct whd_bt_info *whd_bt_info_t; +/** + * Abstract pointer type that acts as a handle to an instance of the bt device + */ +typedef struct whd_bt_dev *whd_bt_dev_t; +/** + * Abstract pointer type to handle instance of whd interface + */ +typedef struct whd_interface *whd_interface_t; + +/** + * Abstract type that acts as a handle to an instance of a buffer function + */ +typedef struct whd_buffer_funcs whd_buffer_funcs_t; + +/** + * Abstract type that acts as a handle to an instance of a network interface function + */ +typedef struct whd_netif_funcs whd_netif_funcs_t; + +/** + * Abstract type that acts as a handle to an instance of a resource function + */ +typedef struct whd_resource_source whd_resource_source_t; + +/** + * Abstract type that acts as a handle to an instance of a bus function used for SDIO specific functionality + */ +typedef struct whd_bus_funcs whd_sdio_funcs_t; + +/** + * Abstract type that acts as a handle to an instance of a bus function used for SPI specific functionality + */ +typedef struct whd_bus_funcs whd_spi_funcs_t; + +/** + * Structure for storing WHD init configurations + */ +typedef struct whd_init_config +{ + void *thread_stack_start; /**< Pointer to the WHD thread stack */ + uint32_t thread_stack_size; /**< Size of the WHD thread stack */ + uint32_t thread_priority; /**< Priority to be set to WHD Thread */ + whd_country_code_t country; /**< Variable to strore country code information */ +} whd_init_config_t; + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* INCLUDED_WHD_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/inc/whd_events.h b/wifi-host-driver/WiFi_Host_Driver/inc/whd_events.h new file mode 100644 index 00000000..46df219e --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/inc/whd_events.h @@ -0,0 +1,274 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file whd_events.h + * Header for Event detection + * + * Provides constants and prototypes for functions that allow + * user applications to receive event callbacks and set event handlers + */ +#ifndef INCLUDED_WHD_EVENTS_API_H +#define INCLUDED_WHD_EVENTS_API_H + +#include "whd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* List of events */ +#define WLC_E_NONE (0x7FFFFFFE) /**< Indicates the end of the event array list */ + +#define WLC_E_SET_SSID 0 /**< Indicates status of set SSID. This event occurs when STA tries to join the AP*/ +#define WLC_E_AUTH 3 /**< 802.11 AUTH request event occurs when STA tries to get authenticated with the AP */ +#define WLC_E_DEAUTH 5 /**< 802.11 DEAUTH request event occurs when the the SOFTAP is stopped to deuthenticate the connected stations*/ +#define WLC_E_DEAUTH_IND 6 /**< 802.11 DEAUTH indication event occurs when the STA gets deauthenticated by the AP */ +#define WLC_E_ASSOC 7 /**< 802.11 ASSOC request event occurs when STA joins the AP */ +#define WLC_E_ASSOC_IND 8 /**< 802.11 ASSOC indication occurs when a station joins the SOFTAP that is started */ +#define WLC_E_REASSOC 9 /**< 802.11 REASSOC request event when the STA again gets associated with the AP */ +#define WLC_E_REASSOC_IND 10 /**< 802.11 REASSOC indication occurs when a station again reassociates with the SOFTAP*/ +#define WLC_E_DISASSOC 11 /**< 802.11 DISASSOC request occurs when the STA the tries to leave the AP*/ +#define WLC_E_DISASSOC_IND 12 /**< 802.11 DISASSOC indication occurs when the connected station gets disassociates from SOFTAP, + also when STA gets diassociated by the AP*/ +#define WLC_E_LINK 16 /**< generic link indication */ +#define WLC_E_PROBREQ_MSG 44 /**< Indicates probe request received for the SOFTAP started*/ +#define WLC_E_PSK_SUP 46 /**< WPA Handshake fail during association*/ +#define WLC_E_ACTION_FRAME 59 /**< Indicates Action frame Rx */ +#define WLC_E_ACTION_FRAME_COMPLETE 60 /**< Indicates Action frame Tx complete */ +#define WLC_E_ESCAN_RESULT 69 /**< escan result event occurs when we scan for the networks */ +#define WLC_E_EXT_AUTH_REQ 187 /**< authentication request received */ +#define WLC_E_EXT_AUTH_FRAME_RX 188 /**< authentication request received */ +#define WLC_E_MGMT_FRAME_TXSTATUS 189 /**< mgmt frame Tx complete */ + +/* List of status codes - Applicable for any event type */ +#define WLC_E_STATUS_SUCCESS 0 /**< operation was successful */ +#define WLC_E_STATUS_FAIL 1 /**< operation failed */ +#define WLC_E_STATUS_TIMEOUT 2 /**< operation timed out */ +#define WLC_E_STATUS_NO_NETWORKS 3 /**< failed due to no matching network found */ +#define WLC_E_STATUS_ABORT 4 /**< operation was aborted */ +#define WLC_E_STATUS_NO_ACK 5 /**< protocol failure: packet not ack'd */ +#define WLC_E_STATUS_UNSOLICITED 6 /**< AUTH or ASSOC packet was unsolicited */ +#define WLC_E_STATUS_ATTEMPT 7 /**< attempt to assoc to an auto auth configuration */ +#define WLC_E_STATUS_PARTIAL 8 /**< scan results are incomplete */ +#define WLC_E_STATUS_NEWSCAN 9 /**< scan aborted by another scan */ +#define WLC_E_STATUS_NEWASSOC 10 /**< scan aborted due to assoc in progress */ +#define WLC_E_STATUS_11HQUIET 11 /**< 802.11h quiet period started */ +#define WLC_E_STATUS_SUPPRESS 12 /**< user disabled scanning (WLC_SET_SCANSUPPRESS) */ +#define WLC_E_STATUS_NOCHANS 13 /**< no allowable channels to scan */ +#define WLC_E_STATUS_CCXFASTRM 14 /**< scan aborted due to CCX fast roam */ +#define WLC_E_STATUS_CS_ABORT 15 /**< abort channel select */ +#define WLC_E_STATUS_ERROR 16 /**< request failed due to error */ +#define WLC_E_STATUS_INVALID 0xff /**< Invalid status code to init variables. */ + +#define WLC_SUP_STATUS_OFFSET (256) /**< Status offset added to the status codes to match the values from firmware. */ + +/** + * @brief Status code for event WLC_E_PSK_SUP + * + * -Basic supplicant authentication states + * + * + WLC_SUP_DISCONNECTED + * + WLC_SUP_CONNECTING + * + WLC_SUP_IDREQUIRED + * + WLC_SUP_AUTHENTICATING + * + WLC_SUP_AUTHENTICATED + * + WLC_SUP_KEYXCHANGE + * + WLC_SUP_KEYED + * + WLC_SUP_TIMEOUT + * + WLC_SUP_LAST_BASIC_STATE + * + * -Extended supplicant authentication states + * + * + WLC_SUP_KEYXCHANGE_WAIT_M1 + * + WLC_SUP_KEYXCHANGE_PREP_M2 + * + WLC_SUP_KEYXCHANGE_WAIT_M3 + * + WLC_SUP_KEYXCHANGE_PREP_M4 + * + WLC_SUP_KEYXCHANGE_WAIT_G1 + * + WLC_SUP_KEYXCHANGE_PREP_G2 + */ +typedef enum sup_auth_status +{ + WLC_SUP_DISCONNECTED = 0 + WLC_SUP_STATUS_OFFSET, /**< Disconnected */ + WLC_SUP_CONNECTING = 1 + WLC_SUP_STATUS_OFFSET, /**< Connecting */ + WLC_SUP_IDREQUIRED = 2 + WLC_SUP_STATUS_OFFSET, /**< ID Required */ + WLC_SUP_AUTHENTICATING = 3 + WLC_SUP_STATUS_OFFSET, /**< Authenticating */ + WLC_SUP_AUTHENTICATED = 4 + WLC_SUP_STATUS_OFFSET, /**< Authenticated */ + WLC_SUP_KEYXCHANGE = 5 + WLC_SUP_STATUS_OFFSET, /**< Key Exchange */ + WLC_SUP_KEYED = 6 + WLC_SUP_STATUS_OFFSET, /**< Key Exchanged */ + WLC_SUP_TIMEOUT = 7 + WLC_SUP_STATUS_OFFSET, /**< Timeout */ + WLC_SUP_LAST_BASIC_STATE = 8 + WLC_SUP_STATUS_OFFSET, /**< Last Basic State */ + WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED, /**< Waiting to receive handshake msg M1 */ + WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE, /**< Preparing to send handshake msg M2 */ + WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE, /**< Waiting to receive handshake msg M3 */ + WLC_SUP_KEYXCHANGE_PREP_M4 = 9 + WLC_SUP_STATUS_OFFSET, /**< Preparing to send handshake msg M4 */ + WLC_SUP_KEYXCHANGE_WAIT_G1 = 10 + WLC_SUP_STATUS_OFFSET, /**< Waiting to receive handshake msg G1 */ + WLC_SUP_KEYXCHANGE_PREP_G2 = 11 + WLC_SUP_STATUS_OFFSET /**< Preparing to send handshake msg G2 */ +} sup_auth_status_t; + +#define WHD_MSG_IFNAME_MAX 16 /**< Max length of Interface name */ + +/* Reason codes for LINK */ +#define WLC_E_LINK_BCN_LOSS 1 /**< Link down because of beacon loss */ +#define WLC_E_LINK_DISASSOC 2 /**< Link down because of disassoc */ +#define WLC_E_LINK_ASSOC_REC 3 /**< Link down because assoc recreate failed */ +#define WLC_E_LINK_BSSCFG_DIS 4 /**< Link down due to bsscfg down */ + +#pragma pack(1) + +/** + * Structure to store ethernet header fields in event packets + */ +typedef struct whd_event_eth_hdr +{ + uint16_t subtype; /**< Vendor specific..32769 */ + uint16_t length; /**< Length of ethernet header*/ + uint8_t version; /**< Version is 0 */ + uint8_t oui[3]; /**< Organizationally Unique Identifier */ + uint16_t usr_subtype; /**< User specific data */ +} whd_event_eth_hdr_t; + +/** + * Structure to store ethernet destination, source and ethertype in event packets + */ +typedef struct whd_event_ether_header +{ + whd_mac_t destination_address; /**< Ethernet destination address */ + whd_mac_t source_address; /**< Ethernet source address */ + uint16_t ethertype; /**< Ethertype for identifying event packets */ +} whd_event_ether_header_t; + +/** + * Structure to store fields after ethernet header in event message + */ +struct whd_event_msg +{ + uint16_t version; /**< Version */ + uint16_t flags; /**< see flags below */ + uint32_t event_type; /**< Event type indicating a response from firmware for IOCTLs/IOVARs sent */ + uint32_t status; /**< Status code corresponding to any event type */ + uint32_t reason; /**< Reason code associated with the event occurred */ + uint32_t auth_type; /**< WLC_E_AUTH: 802.11 AUTH request */ + uint32_t datalen; /**< Length of data in event message */ + whd_mac_t addr; /**< Station address (if applicable) */ + char ifname[WHD_MSG_IFNAME_MAX]; /**< name of the incoming packet interface */ + uint8_t ifidx; /**< destination OS i/f index */ + uint8_t bsscfgidx; /**< source bsscfg index */ +}; + +/** + * Event structure used by driver msgs + */ +typedef struct whd_event +{ + whd_event_ether_header_t eth; /**< Variable to store ethernet destination, source and ethertype in event packets */ + whd_event_eth_hdr_t eth_evt_hdr; /**< Variable to store ethernet header fields in event message */ + whd_event_header_t whd_event; /**< Variable to store rest of the event packet fields after ethernet header */ + /* data portion follows */ +} whd_event_t; + +#pragma pack() + +/** @addtogroup event WHD Event handling API + * Functions that allow user applications to receive event callbacks and set event handlers + * @{ + */ +/** Event handler prototype definition + * + * @param ifp Pointer to handle instance of whd interface + * @param event_header whd event header + * @param event_data event data + * @param handler_user_data semaphore data + */ +typedef void *(*whd_event_handler_t)(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data); +/** Error handler prototype definition + * + * @param whd_driver Pointer to handle instance of whd driver + * @param error_type whd error type + * @param event_data event data + * @param handler_user_data semaphore data + */ +typedef void *(*whd_error_handler_t)(whd_driver_t whd_driver, const uint8_t *error_type, + const uint8_t *event_data, void *handler_user_data); +/* @} */ +/** Registers a handler to receive event callbacks. + * + * This function registers a callback handler to be notified when + * a particular event is received. + * + * + * @note Currently each event may only be registered to one handler and there is a limit to the number of simultaneously + * registered events. Maximum of 5 event handlers can registered simultaneously, this also includes the internal + * event handler registration which happens during scan, join and starting an AP. + * + * @param ifp Pointer to handle instance of whd interface + * @param event_type Pointer to the event list array + * @param handler_func A function pointer to the handler callback + * @param handler_user_data A pointer value which will be passed to the event handler function + * at the time an event is triggered (NULL is allowed) + * @param event_index Entry where the event handler is registered in the list + * + * @return WHD_SUCCESS or Error code + */ +uint32_t whd_wifi_set_event_handler(whd_interface_t ifp, const uint32_t *event_type, whd_event_handler_t handler_func, + void *handler_user_data, uint16_t *event_index); +/** Registers a handler to receive error callbacks. + * + * This function registers a callback handler to be notified when + * a particular event is received. + * + * + * @note Currently each event may only be registered to one handler and there is a limit to the number of simultaneously + * registered events. Maximum of 5 event handlers can registered simultaneously, this also includes the internal + * event handler registration which happens during scan, join and starting an AP. + * + * @param ifp Pointer to handle instance of whd interface + * @param error_nums Pointer to the event list as WLC_ERR_BUS and WLC_ERR_FW + * @param handler_func A function pointer to the handler callback + * @param handler_user_data A pointer value which will be passed to the event handler function + * at the time an event is triggered (NULL is allowed) + * @param error_index Entry where the error handler is registered in the list + * + * @return WHD_SUCCESS or Error code + */ +uint32_t whd_wifi_set_error_handler(whd_interface_t ifp, const uint8_t *error_nums, whd_error_handler_t handler_func, + void *handler_user_data, uint16_t *error_index); + +/** Delete/Deregister the event entry where callback is registered + * + * @param ifp Pointer to handle instance of whd interface + * @param event_index Event index obtained during registration by whd_wifi_set_event_handler + * + * @return WHD_SUCCESS or Error code + */ + +uint32_t whd_wifi_deregister_event_handler(whd_interface_t ifp, uint16_t event_index); +/** Delete/Deregister the error entry where callback is registered + * + * @param ifp Pointer to handle instance of whd interface + * @param error_index Error index obtained during registration by whd_wifi_set_error_handler + * + * @return WHD_SUCCESS or Error code + */ + +uint32_t whd_wifi_deregister_error_handler(whd_interface_t ifp, uint16_t error_index); + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef */ diff --git a/wifi-host-driver/WiFi_Host_Driver/inc/whd_network_types.h b/wifi-host-driver/WiFi_Host_Driver/inc/whd_network_types.h new file mode 100644 index 00000000..9b884bba --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/inc/whd_network_types.h @@ -0,0 +1,229 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file whd_network_types.h + * Prototypes of functions corresponding to Buffer and Network Interface + * + * This file provides prototypes for functions which allows different functionalities related to: + * - Buffer Interface: Allocate and release a packet buffer, Retrieve the current pointer and size of a packet buffer, etc. + * - Network Interface: Called by WHD to pass received data to the network stack, to send an ethernet frame to WHD, etc. + */ +#include "whd.h" + +#ifndef INC_WHD_NETWORK_TYPES_H_ +#define INC_WHD_NETWORK_TYPES_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Constants +******************************************************/ +/** @addtogroup buffif WHD Buffer Interface API + * Allows WHD to perform buffer related operations like, allocating, releasing, retrieving the current pointer of and size of a packet buffer. + * @{ + */ + +/** + * Indicates transmit/receive direction that the packet buffer has + * been used for. This is needed if tx/rx pools are separate. + */ +typedef enum +{ + WHD_NETWORK_TX, /**< Transmit direction */ + WHD_NETWORK_RX /**< Recieve direction */ +} whd_buffer_dir_t; + +/** + * Allows WHD to perform buffer related operations like, allocating, releasing, retrieving the current pointer of and size of a packet buffer. + */ +struct whd_buffer_funcs +{ + /** Allocates a packet buffer + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * Attempts to allocate a packet buffer of the size requested. It can do this + * by allocating a pre-existing packet from a pool, using a static buffer, + * or by dynamically allocating memory. The method of allocation does not + * concern WHD, however it must match the way the network stack expects packet + * buffers to be allocated. Usually WHD requires packet of size of WHD_LINK_MTU + * which includes the MTU, other other various header. Refer to whd_types.h + * to find the size of WHD_LINK_MTU + * + * @param buffer A pointer which receives the allocated packet buffer handle + * @param direction Indicates transmit/receive direction that the packet buffer is + * used for. This may be needed if tx/rx pools are separate. + * @param size The number of bytes to allocate. + * @param timeout_ms Maximum period to block for available buffer + * + * @return WHD_SUCCESS or error code + * + */ + whd_result_t (*whd_host_buffer_get)(whd_buffer_t *buffer, whd_buffer_dir_t direction, uint16_t size, + uint32_t timeout_ms); + + /** Releases a packet buffer + * + * Implemented in the port layer interface, which will be specific to the + * buffering scheme in use. + * This function is used by WHD to indicate that it no longer requires + * a packet buffer. The buffer can then be released back into a pool for + * reuse, or the dynamically allocated memory can be freed, according to + * how the packet was allocated. + * Returns void since WHD cannot do anything about failures + * + * @param buffer The handle of the packet buffer to be released + * @param direction Indicates transmit/receive direction that the packet buffer has + * been used for. This might be needed if tx/rx pools are separate. + * + */ + void (*whd_buffer_release)(whd_buffer_t buffer, whd_buffer_dir_t direction); + + /** Retrieves the current pointer of a packet buffer + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * Since packet buffers usually need to be created with space at the + * front for additional headers, this function allows WHD to get + * the current 'front' location pointer. + * + * @param buffer The handle of the packet buffer whose pointer is to be retrieved + * + * @return The packet buffer's current pointer. + */ + uint8_t *(*whd_buffer_get_current_piece_data_pointer)(whd_buffer_t buffer); + + /** Retrieves the size of a packet buffer + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * Since packet buffers usually need to be created with space at the + * front for additional headers, the memory block use to contain a packet buffer + * will often be larger than the current size of the packet buffer data. + * This function allows WHD to retrieve the current size of a packet buffer's data. + * + * @param buffer The handle of the packet buffer whose size is to be retrieved + * + * @return The size of the packet buffer. + */ + uint16_t (*whd_buffer_get_current_piece_size)(whd_buffer_t buffer); + + /** Sets the current size of a WHD packet + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * This function sets the current length of a WHD packet buffer + * + * @param buffer The packet to be modified + * @param size The new size of the packet buffer + * + * @return WHD_SUCCESS or error code + */ + whd_result_t (*whd_buffer_set_size)(whd_buffer_t buffer, uint16_t size); + + /** Moves the current pointer of a packet buffer + * + * Implemented in the port layer interface which is specific to the buffering scheme in use. + * + * Since packet buffers usually need to be created with space at the front for additional headers, + * this function allows WHD to move the current 'front' location pointer so that it has space to + * add headers to transmit packets, and so that the network stack does not see the internal WHD + * headers on received packets. + * + * @param buffer A pointer to the handle of the current packet buffer for which the + * current pointer will be moved. On return this may contain a pointer + * to a newly allocated packet buffer which has been daisy chained to + * the front of the given packet buffer. This would be the case if the given packet + * buffer didn't have enough space at the front. + * @param add_remove_amount This is the number of bytes to move the current pointer of the packet + * buffer - a negative value increases the space for headers at the front + * of the packet, a positive value decreases the space. + * + * @return WHD_SUCCESS or error code + */ + whd_result_t (*whd_buffer_add_remove_at_front)(whd_buffer_t *buffer, int32_t add_remove_amount); +}; +/* @} */ + +/** @addtogroup netif WHD Network Interface API + * Allows WHD to pass received data to the network stack, to send an ethernet frame to WHD, etc. + * @{ + */ + +/** + * Contains functions which allows WHD to pass received data to the network stack, to send an ethernet frame to WHD, etc + */ +struct whd_netif_funcs +{ + /** Called by WHD to pass received data to the network stack + * + * + * Packets received from the Wi-Fi network by WHD are forwarded to by calling function ptr which + * must be implemented in the network interface. Ethernet headers + * are present at the start of these packet buffers. + * + * This function is called asynchronously in the context of the + * WHD thread whenever new data has arrived. + * Packet buffers are allocated within WHD, and ownership is transferred + * to the network stack. The network stack or application is thus + * responsible for releasing the packet buffers. + * Most packet buffering systems have a pointer to the 'current point' within + * the packet buffer. When this function is called, the pointer points + * to the start of the Ethernet header. There is other inconsequential data + * before the Ethernet header. + * + * It is preferable that the (whd_network_process_ethernet_data)() function simply puts + * the received packet on a queue for processing by another thread. This avoids the + * WHD thread being unnecessarily tied up which would delay other packets + * being transmitted or received. + * + * @param interface The interface on which the packet was received. + * @param buffer Handle of the packet which has just been received. Responsibility for + * releasing this buffer is transferred from WHD at this point. + * + */ + void (*whd_network_process_ethernet_data)(whd_interface_t ifp, whd_buffer_t buffer); +}; + +/** To send an ethernet frame to WHD (called by the Network Stack) + * + * This function takes ethernet data from the network stack and queues it for transmission over the wireless network. + * The function can be called from any thread context as it is thread safe, however + * it must not be called from interrupt context since it might get blocked while waiting + * for a lock on the transmit queue. + * + * This function returns immediately after the packet has been queued for transmit, + * NOT after it has been transmitted. Packet buffers passed to the WHD + * are released inside the WHD once they have been transmitted. + * + * @param ifp Pointer to handle instance of whd interface + * @param buffer Handle of the packet buffer to be sent. + * + * @return WHD_SUCCESS or Error code + * + */ +extern whd_result_t whd_network_send_ethernet_data(whd_interface_t ifp, whd_buffer_t buffer); +/* @} */ + + +#ifdef __cplusplus +} /*extern "C" */ +#endif +#endif /* INC_WHD_NETWORK_TYPES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/inc/whd_resource_api.h b/wifi-host-driver/WiFi_Host_Driver/inc/whd_resource_api.h new file mode 100644 index 00000000..6e9d8d60 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/inc/whd_resource_api.h @@ -0,0 +1,142 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file whd_resource_api.h + * Prototypes of functions for providing external resources to the radio driver + * + * This file provides prototypes for functions which allow + * WHD to download firmware, NVRAM and CLM BLOB on a particular hardware platform. + * + */ +#include "whd.h" + +#ifndef INCLUDED_WHD_RESOURCE_API_H_ +#define INCLUDED_WHD_RESOURCE_API_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define BLOCK_SIZE 1024 /**< Size of the block */ +/** + * Type of resources + */ +typedef enum +{ + WHD_RESOURCE_WLAN_FIRMWARE, /**< Resource type: WLAN Firmware */ + WHD_RESOURCE_WLAN_NVRAM, /**< Resource type: NVRAM file */ + WHD_RESOURCE_WLAN_CLM, /**< Resource type: CLM_BLOB file */ +} whd_resource_type_t; + +/****************************************************** +* Global Variables +******************************************************/ + +/** @addtogroup res WHD Resource API + * @brief Functions that enable WHD to download WLAN firmware, NVRAM and CLM BLOB on a particular hardware platform. + * @{ + */ + +/** + * Interface to a data source that provides external resources to the radio driver + */ + +/** This data structure defines a source for data generally intended to be downloaded to the radio device. + * + * The data is assumed to be available as a set of blocks that are all the same size with the exception + * of the last block. The whd_get_resource_block_size function returns this block size. The whd_get_resource_block call + * returns a pointer to a block of data. The actual storage for the data block is owned by the data source, so only a pointer + * to the block is returned. There are two predominate use cases. If the data is stored in the internal + * flash memory, then whd_get_resource_no_of_blocks will return 1 and a call to whd_get_resource_block will return a pointer to + * the data image with the size being the size of the data image. If the data is stored in an external flash of some + * type, each block of data can be read from the external flash one at a time. whd_get_resource_no_of_blocks will return + * the physical number of blocks in the data and each call to whd_get_resource_block will read data from the external memory + * and make it available via an internal buffer. + */ +struct whd_resource_source +{ + /** Gets the size of the resource for respective resource type + * + * + * @param whd_drv Pointer to handle instance of the driver + * @param resource Type of resource - WHD_RESOURCE_WLAN_FIRMWARE, WHD_RESOURCE_WLAN_NVRAM, WHD_RESOURCE_WLAN_CLM + * @param size_out Size of the resource + * + * @return WHD_SUCCESS or error code + * + */ + uint32_t (*whd_resource_size)(whd_driver_t whd_drv, whd_resource_type_t resource, uint32_t *size_out); + + /** Gets the resource block for specified resource type + * + * @param whd_drv Pointer to handle instance of the driver + * @param type Type of resource - WHD_RESOURCE_WLAN_FIRMWARE, WHD_RESOURCE_WLAN_NVRAM, WHD_RESOURCE_WLAN_CLM + * @param blockno The number of block + * @param data Pointer to a block of data + * @param size_out Size of the resource + * + * @return WHD_SUCCESS or error code + * + */ + uint32_t (*whd_get_resource_block)(whd_driver_t whd_drv, whd_resource_type_t type, + uint32_t blockno, const uint8_t **data, uint32_t *size_out); + + /** Gets block count for the specified resource_type + * + * @param whd_drv Pointer to handle instance of the driver + * @param type Type of resource - WHD_RESOURCE_WLAN_FIRMWARE, WHD_RESOURCE_WLAN_NVRAM, WHD_RESOURCE_WLAN_CLM + * @param block_count Pointer to store block count for the resource + * + * @return WHD_SUCCESS or error code + * + */ + uint32_t (*whd_get_resource_no_of_blocks)(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *block_count); + + /** Gets block size for the specified resource_type + * + * @param whd_drv Pointer to handle instance of the driver + * @param type Type of resources - WHD_RESOURCE_WLAN_FIRMWARE, WHD_RESOURCE_WLAN_NVRAM, WHD_RESOURCE_WLAN_CLM + * @param size_out Pointer to store size of the block + * + * @return WHD_SUCCESS or error code + * + */ + uint32_t (*whd_get_resource_block_size)(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *size_out); + + /** Gets the resource for specified resource type + * + * @param whd_drv Pointer to handle instance of the driver + * @param type Type of resource - WHD_RESOURCE_WLAN_FIRMWARE, WHD_RESOURCE_WLAN_NVRAM, WHD_RESOURCE_WLAN_CLM + * @param offset offset address to store buffer + * @param size Pointer to a size of buffer + * @param size_out Pointer to store size of buffer + * @param buffer Pointer to a buffer + * + * @return WHD_SUCCESS or error code + * + */ + uint32_t (*whd_resource_read)(whd_driver_t whd_drv, whd_resource_type_t type, + uint32_t offset, uint32_t size, uint32_t *size_out, void *buffer); +}; + +/** @} */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef INCLUDED_WHD_RESOURCE_API_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/inc/whd_types.h b/wifi-host-driver/WiFi_Host_Driver/inc/whd_types.h new file mode 100644 index 00000000..5cc4f8c5 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/inc/whd_types.h @@ -0,0 +1,1174 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file whd_types.h + * Defines common data types used with WHD + * + */ + +#include + +#include "cybsp.h" +#include "cy_result.h" +#include "cyhal_hw_types.h" + +#ifndef INCLUDED_WHD_TYPES_H_ +#define INCLUDED_WHD_TYPES_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Macros +******************************************************/ +#define SSID_NAME_SIZE (32) /**< SSID Length */ + +#define WEP_ENABLED 0x0001 /**< Flag to enable WEP Security */ +#define TKIP_ENABLED 0x0002 /**< Flag to enable TKIP Encryption */ +#define AES_ENABLED 0x0004 /**< Flag to enable AES Encryption */ +#define SHARED_ENABLED 0x00008000 /**< Flag to enable Shared key Security */ +#define WPA_SECURITY 0x00200000 /**< Flag to enable WPA Security */ +#define WPA2_SECURITY 0x00400000 /**< Flag to enable WPA2 Security */ +#define WPA3_SECURITY 0x01000000 /**< Flag to enable WPA3 PSK Security */ +#define SECURITY_MASK (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED) /**< Flag to Security mask */ + +#define ENTERPRISE_ENABLED 0x02000000 /**< Flag to enable Enterprise Security */ +#define WPS_ENABLED 0x10000000 /**< Flag to enable WPS Security */ +#define IBSS_ENABLED 0x20000000 /**< Flag to enable IBSS mode */ +#define FBT_ENABLED 0x40000000 /**< Flag to enable FBT */ + +#define PM1_POWERSAVE_MODE (1) /**< Powersave mode on specified interface without regard for throughput reduction */ +#define PM2_POWERSAVE_MODE (2) /**< Powersave mode on specified interface with High throughput */ +#define NO_POWERSAVE_MODE (0) /**< No Powersave mode */ + +#define PMKID_LEN (16) /**< PMKID LENGTH */ + +/** + * Suppress unused parameter warning + */ +#ifndef UNUSED_PARAMETER +#define UNUSED_PARAMETER(x) ( (void)(x) ) +#endif + +/** + * Suppress unused variable warning + */ +#ifndef UNUSED_VARIABLE +#define UNUSED_VARIABLE(x) ( (void)(x) ) +#endif + +/** + * Suppress unused variable warning occurring due to an assert which is disabled in release mode + */ +#ifndef REFERENCE_DEBUG_ONLY_VARIABLE +#define REFERENCE_DEBUG_ONLY_VARIABLE(x) ( (void)(x) ) +#endif + +/****************************************************** +*@cond Type Definitions +******************************************************/ +typedef void *whd_buffer_t; +typedef struct wl_bss_info_struct whd_bss_info_t; +typedef struct edcf_acparam whd_edcf_ac_param_t; +typedef struct wl_af_params whd_af_params_t; +typedef struct whd_arp_stats_s whd_arp_stats_t; +typedef struct wl_pkt_filter_stats whd_pkt_filter_stats_t; +typedef struct whd_tko_retry whd_tko_retry_t; +typedef struct whd_tko_connect whd_tko_connect_t; +typedef struct whd_tko_status whd_tko_status_t; +/** @endcond */ +/****************************************************** +* Constants +******************************************************/ + +#define WIFI_IE_OUI_LENGTH (3) /**< OUI length for Information Element */ +#define VNDR_IE_MAX_LEN 255 /**< vendor IE max length, without ID and len */ + +/* Below constants are used to allocate the buffer pool by the application */ + +#define BDC_HEADER_WITH_PAD 6 /**< BDC Header with padding 4 + 2 */ + +/** From bdc header, Ethernet data starts after an offset of (bdc_header->data_offset<<2). + * It is variable, but usually 4. + */ +#define BDC_HEADER_OFFSET_TO_DATA 4 + +#define SDPCM_HEADER (8 + 4) /**< SDPCM SW header + Frame tag */ + +#if (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SDIO_INTERFACE) +#define MAX_BUS_HEADER_SIZE 4 /**< Max bus header size for all bus types (sdio) */ +#elif (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SPI_INTERFACE) +#define MAX_BUS_HEADER_SIZE 4 /**< Max bus header size for all bus types (spi) */ +#elif (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_M2M_INTERFACE) +#define MAX_BUS_HEADER_SIZE 8 /**< Max bus header size for all bus types (m2m) */ +#else +#error "CYBSP_WIFI_INTERFACE_TYPE is not defined" +#endif + +#define BUFFER_OVERHEAD 4 /**< Buffer overhead, sizeof(void *) */ + +/** + * The maximum space in bytes required for headers in front of the Ethernet header. + * 6 + (8 + 4) + 4 + 4 + 4 = 30 bytes + */ +#define WHD_LINK_HEADER (BDC_HEADER_WITH_PAD + BDC_HEADER_OFFSET_TO_DATA + \ + SDPCM_HEADER + MAX_BUS_HEADER_SIZE + BUFFER_OVERHEAD) + +/** + * The size of an Ethernet header + */ +#define WHD_ETHERNET_SIZE (14) + +/** + * The size in bytes of the Link layer header i.e. the whd specific headers and the Ethernet header + */ +#define WHD_PHYSICAL_HEADER (WHD_LINK_HEADER + WHD_ETHERNET_SIZE) + +/** + * The maximum size in bytes of the data part of an Ethernet frame + */ +#ifndef WHD_PAYLOAD_MTU +#define WHD_PAYLOAD_MTU (1500) +#endif + +/** + * The maximum size in bytes of a packet used within whd. + * Pool should be atleast of this size. + * Usually buffer pools needs implementation specific headers like pbuf header etc, that should be + * taken into account along with this during buffer pool creation. Also buffer pools needs alignment with + * cache size of the platform for better performance + */ +#define WHD_LINK_MTU (WHD_PAYLOAD_MTU + WHD_PHYSICAL_HEADER) + +/** @cond */ +#ifdef __x86_64__ +typedef uint64_t whd_thread_arg_t; +#else +typedef uint32_t whd_thread_arg_t; +#endif +/** @endcond */ +/****************************************************** +* Structures and Enumerations +******************************************************/ +/** + * Enumeration of Dot11 Reason Codes + */ +typedef enum +{ + WHD_DOT11_RC_RESERVED = 0, /**< Reserved */ + WHD_DOT11_RC_UNSPECIFIED = 1 /**< Unspecified */ +} whd_dot11_reason_code_t; + +/** + * Boolean values + */ +typedef enum +{ + WHD_FALSE = 0, /**< Boolean True */ + WHD_TRUE = 1 /**< Boolean False */ +} whd_bool_t; + + +/** + * Transfer direction for the WHD platform bus interface + */ +typedef enum +{ + /* If updating this enum, the bus_direction_mapping variable will also need to be updated */ + BUS_READ, /**< Specifies bus type and read direction */ + BUS_WRITE /**< Specifies bus type and write direction */ +} whd_bus_transfer_direction_t; + +/** + * Enumeration of Wi-Fi security modes + */ +typedef enum +{ + WHD_SECURITY_OPEN = 0, /**< Open security */ + WHD_SECURITY_WEP_PSK = WEP_ENABLED, /**< WEP PSK Security with open authentication */ + WHD_SECURITY_WEP_SHARED = (WEP_ENABLED | SHARED_ENABLED), /**< WEP PSK Security with shared authentication */ + WHD_SECURITY_WPA_TKIP_PSK = (WPA_SECURITY | TKIP_ENABLED), /**< WPA PSK Security with TKIP */ + WHD_SECURITY_WPA_AES_PSK = (WPA_SECURITY | AES_ENABLED), /**< WPA PSK Security with AES */ + WHD_SECURITY_WPA_MIXED_PSK = (WPA_SECURITY | AES_ENABLED | TKIP_ENABLED), /**< WPA PSK Security with AES & TKIP */ + WHD_SECURITY_WPA2_AES_PSK = (WPA2_SECURITY | AES_ENABLED), /**< WPA2 PSK Security with AES */ + WHD_SECURITY_WPA2_TKIP_PSK = (WPA2_SECURITY | TKIP_ENABLED), /**< WPA2 PSK Security with TKIP */ + WHD_SECURITY_WPA2_MIXED_PSK = (WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED), /**< WPA2 PSK Security with AES & TKIP */ + WHD_SECURITY_WPA2_FBT_PSK = (WPA2_SECURITY | AES_ENABLED | FBT_ENABLED), /**< WPA2 FBT PSK Security with AES & TKIP */ + WHD_SECURITY_WPA3_SAE = (WPA3_SECURITY | AES_ENABLED), /**< WPA3 Security with AES */ + WHD_SECURITY_WPA2_WPA_AES_PSK = (WPA2_SECURITY | WPA_SECURITY | AES_ENABLED), /**< WPA2 WPA PSK Security with AES */ + WHD_SECURITY_WPA2_WPA_MIXED_PSK = (WPA2_SECURITY | WPA_SECURITY | AES_ENABLED | TKIP_ENABLED), /**< WPA2 WPA PSK Security with AES & TKIP */ + + WHD_SECURITY_WPA3_WPA2_PSK = (WPA3_SECURITY | WPA2_SECURITY | AES_ENABLED), /**< WPA3 WPA2 PSK Security with AES */ + + WHD_SECURITY_WPA_TKIP_ENT = (ENTERPRISE_ENABLED | WPA_SECURITY | TKIP_ENABLED), /**< WPA Enterprise Security with TKIP */ + WHD_SECURITY_WPA_AES_ENT = (ENTERPRISE_ENABLED | WPA_SECURITY | AES_ENABLED), /**< WPA Enterprise Security with AES */ + WHD_SECURITY_WPA_MIXED_ENT = (ENTERPRISE_ENABLED | WPA_SECURITY | AES_ENABLED | TKIP_ENABLED), /**< WPA Enterprise Security with AES & TKIP */ + WHD_SECURITY_WPA2_TKIP_ENT = (ENTERPRISE_ENABLED | WPA2_SECURITY | TKIP_ENABLED), /**< WPA2 Enterprise Security with TKIP */ + WHD_SECURITY_WPA2_AES_ENT = (ENTERPRISE_ENABLED | WPA2_SECURITY | AES_ENABLED), /**< WPA2 Enterprise Security with AES */ + WHD_SECURITY_WPA2_MIXED_ENT = (ENTERPRISE_ENABLED | WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED), /**< WPA2 Enterprise Security with AES & TKIP */ + WHD_SECURITY_WPA2_FBT_ENT = (ENTERPRISE_ENABLED | WPA2_SECURITY | AES_ENABLED | FBT_ENABLED), /**< WPA2 Enterprise Security with AES & FBT */ + + WHD_SECURITY_IBSS_OPEN = (IBSS_ENABLED), /**< Open security on IBSS ad-hoc network */ + WHD_SECURITY_WPS_SECURE = AES_ENABLED, /**< WPS with AES security */ + + WHD_SECURITY_UNKNOWN = -1, /**< May be returned by scan function if security is unknown. Do not pass this to the join function! */ + + WHD_SECURITY_FORCE_32_BIT = 0x7fffffff /**< Exists only to force whd_security_t type to 32 bits */ +} whd_security_t; + +/** + * Enumeration of methods of scanning + */ +typedef enum +{ + WHD_SCAN_TYPE_ACTIVE = 0x00, /**< Actively scan a network by sending 802.11 probe(s) */ + WHD_SCAN_TYPE_PASSIVE = 0x01, /**< Passively scan a network by listening for beacons from APs */ + WHD_SCAN_TYPE_PNO = 0x02, /**< Use preferred network offload to detect an AP */ + WHD_SCAN_TYPE_PROHIBITED_CHANNELS = 0x04, /**< Permit (passively) scanning a channel that isn't valid for the current country */ + WHD_SCAN_TYPE_NO_BSSID_FILTER = 0x08 /**< Return a scan record for each beacon or probe response RX'ed */ +} whd_scan_type_t; + +/** + * Enumeration of network types + */ +typedef enum +{ + WHD_BSS_TYPE_INFRASTRUCTURE = 0, /**< Denotes infrastructure network */ + WHD_BSS_TYPE_ADHOC = 1, /**< Denotes an 802.11 ad-hoc IBSS network */ + WHD_BSS_TYPE_ANY = 2, /**< Denotes either infrastructure or ad-hoc network */ + WHD_BSS_TYPE_MESH = 3, /**< Denotes 802.11 mesh network */ + + WHD_BSS_TYPE_UNKNOWN = -1 /**< May be returned by scan function if BSS type is unknown. Do not pass this to the Join function */ +} whd_bss_type_t; + +/** + * Enumeration of 802.11 radio bands + */ +typedef enum +{ + WHD_802_11_BAND_5GHZ = 0, /**< Denotes 5GHz radio band */ + WHD_802_11_BAND_2_4GHZ = 1 /**< Denotes 2.4GHz radio band */ +} whd_802_11_band_t; + +/** + * Enumeration of custom IE(Information Element) management actions + */ +typedef enum +{ + WHD_ADD_CUSTOM_IE, /**< Add a custom IE(Information Element) */ + WHD_REMOVE_CUSTOM_IE /**< Remove a custom IE(Information Element) */ +} whd_custom_ie_action_t; + + +/** + * Enumeration of listen interval time unit types + */ +typedef enum +{ + WHD_LISTEN_INTERVAL_TIME_UNIT_BEACON, /**< Time units specified in beacon periods */ + WHD_LISTEN_INTERVAL_TIME_UNIT_DTIM /**< Time units specified in DTIM periods */ +} whd_listen_interval_time_unit_t; + +/** + * Structure for storing scan status + */ +typedef enum +{ + WHD_SCAN_INCOMPLETE, /**< Denotes that scan is not finished */ + WHD_SCAN_COMPLETED_SUCCESSFULLY, /**< Successful completion of scan */ + WHD_SCAN_ABORTED, /**< Scan is aborted */ +} whd_scan_status_t; + +/** + * Structure for storing status of auth event + */ +typedef enum +{ + WHD_AUTH_EXT_REQ, /**< Request authentication received */ + WHD_AUTH_EXT_FRAME_RX, /**< Authentication frame received */ +} whd_auth_status_t; + +/** + * Structure for storing radio band list information + */ +typedef struct +{ + int32_t number_of_bands; /**< Number of bands supported, currently 1 or 2 */ + int32_t current_band; /**< Current band type: WLC_BAND_2G or WLC_BAND_5G */ + int32_t other_band; /**< If value of number_of_bands parameter is 2, then this member specifies the 2nd band */ +} whd_band_list_t; + +/** + * Enumeration of scan result flags + */ +typedef enum +{ + WHD_SCAN_RESULT_FLAG_RSSI_OFF_CHANNEL = 0x01, /**< RSSI came from an off channel DSSS (1 or 1 Mb) Rx */ + WHD_SCAN_RESULT_FLAG_BEACON = 0x02, /**< Beacon (vs probe response) */ + WHD_SCAN_RESULT_FLAG_SAE_H2E = 0x04, /**< BSS is H2E(Hash-to-Element) */ +} whd_scan_result_flag_t; + +/** + * Protected Management Frame Capability + */ +enum +{ + WL_MFP_NONE = 0, /**< Disables the client support for MFP. */ + WL_MFP_CAPABLE, /**< Allows both MFP-capable and clients that do not support MFP to join the network. */ + WL_MFP_REQUIRED /**< Clients are allowed to associate only if MFP is negotiated. */ +}; + + +/** + * Enumeration of ioctl get + */ +typedef enum +{ + WHD_IOCTL_GET_RATE = 12, + WHD_IOCTL_GET_COUNTRY = 83, + WHD_IOCTL_GET_CLK = 160, + WHD_IOCTL_GET_WSEC = 133, + WHD_IOCTL_GET_AUTH = 21, + WHD_IOCTL_GET_WPA_AUTH = 164, + WHD_IOCTL_GET_PM = 85, + WHD_IOCTL_GET_BSSID = 23, + WHD_IOCTL_GET_ASSOCLIST = 159, + WHD_IOCTL_GET_BSS_INFO = 136, + WHD_IOCTL_GET_CHANNEL = 29 + +} whd_usr_ioctl_get_list_t; + +/** + * Enumeration of ioctl set + */ +typedef enum +{ + WHD_IOCTL_SET_CHANNEL = 30, + WHD_IOCTL_SET_WSEC_PMK = 268, + WHD_IOCTL_SET_KEY = 45, + WHD_IOCTL_SET_WPA_AUTH = 165, + WHD_IOCTL_SCB_DEAUTHENTICATE_FOR_REASON = 201, + WHD_IOCTL_SET_PM = 86, + WHD_IOCTL_SET_SSID = 26, + WHD_IOCTL_SET_BCNPRD = 76, + WHD_IOCTL_SET_DTIMPRD = 78, + WHD_IOCTL_SET_WSEC = 134, + WHD_IOCTL_SET_INFRA = 20, + WHD_IOCTL_SET_AUTH = 22 + +} whd_usr_ioctl_set_list_t; + +/** + * IOVAR set list + */ +typedef enum +{ + WHD_IOVAR_SET_MFP = 0, + WHD_IOVAR_SET_MPC, + WHD_IOVAR_SET_AMPDU_BA_WINDOW_SIZE, + WHD_IOVAR_SET_AMPDU_MPDU, + WHD_IOVAR_SET_LISTEN_INTERVAL_BEACON, + WHD_IOVAR_SET_LISTEN_INTERVAL_DTIM, + WHD_IOVAR_SET_LISTEN_INTERVAL_ASSOC, +} whd_usr_iovar_set_list_t; + +/** + * IOVAR get list + */ +typedef enum +{ + WHD_IOVAR_GET_MFP = 0, + WHD_IOVAR_GET_MPC, + WHD_IOVAR_GET_AMPDU_BA_WINDOW_SIZE, + WHD_IOVAR_GET_AMPDU_MPDU, + WHD_IOVAR_GET_LISTEN_INTERVAL, /**< Get Listen Interval value */ + WHD_IOVAR_GET_MAC_ADDRESS, /**< Get mac address */ +} whd_usr_iovar_get_list_t; + +/** + * Enumeration of bus type + */ +typedef enum +{ + WHD_BUS_SDIO = 0, + WHD_BUS_SPI, + WHD_BUS_M2M, + WHD_BUS_NO_DEFINE = 0xff, +} whd_bus_type_t; + +/** + * Expand fw capabilities list to enumeration + */ +typedef enum +{ + WHD_FWCAP_SAE = 0, /**< Internal SAE */ + WHD_FWCAP_SAE_EXT = 1, /**< External SAE */ +} whd_fwcap_id_t; + +/****************************************************** +* Type Definitions +******************************************************/ +/** @cond */ +typedef struct whd_event_msg whd_event_header_t; +/** @endcond */ + +/** + * Structure for storing a MAC address (Wi-Fi Media Access Control address). + */ +typedef struct +{ + uint8_t octet[6]; /**< Unique 6-byte MAC address */ +} whd_mac_t; + +/** + * Structure for storing the supported channels. + */ +typedef struct +{ + uint32_t count; + uint32_t element[1]; +} whd_list_t; + +/** + * Structure for storing a Service Set Identifier (i.e. Name of Access Point) + */ +typedef struct +{ + uint8_t length; /**< SSID length */ + uint8_t value[SSID_NAME_SIZE]; /**< SSID name (AP name) */ +} whd_ssid_t; + +/**< + The received packet formats are different when EXT_STA is enabled. In case + of EXT_STA the received packets are in 802.11 format, where as in other + case the received packets have Ethernet II format + + 1. 802.11 frames + ---------------------------------------------------------------------------- + | FC (2) | DID (2) |A1 (6) |A2 (6)|A3 (6) |SID (2) |SNAP (6) |type (2) |data (46 - 1500) | + ---------------------------------------------------------------------------- + + 2. Ethernet II frames + ------------------------------------------------- + | DA (6) | SA (6) | type (2) | data (46 - 1500) | + ------------------------------------------------- + */ + + +/** + * Macro for creating country codes according to endianness + * @cond !ADDTHIS + */ +#ifdef IL_BIGENDIAN +#define MK_CNTRY(a, b, \ + rev) ( ( (unsigned char)(b) ) + ( ( (unsigned char)(a) ) << 8 ) + \ + ( ( (unsigned short)(rev) ) << 16 ) ) +#else /* ifdef IL_BIGENDIAN */ +#define MK_CNTRY(a, b, \ + rev) ( ( (unsigned char)(a) ) + ( ( (unsigned char)(b) ) << 8 ) + \ + ( ( (unsigned short)(rev) ) << 16 ) ) +#endif /* ifdef IL_BIGENDIAN */ +/** @endcond */ + +/** + * Enumerated list of country codes + */ +typedef enum +{ + WHD_COUNTRY_AFGHANISTAN = MK_CNTRY('A', 'F', 0), /**< AF Afghanistan */ + WHD_COUNTRY_ALBANIA = MK_CNTRY('A', 'L', 0), /**< AL Albania */ + WHD_COUNTRY_ALGERIA = MK_CNTRY('D', 'Z', 0), /**< DZ Algeria */ + WHD_COUNTRY_AMERICAN_SAMOA = MK_CNTRY('A', 'S', 0), /**< AS American_Samoa */ + WHD_COUNTRY_ANGOLA = MK_CNTRY('A', 'O', 0), /**< AO Angola */ + WHD_COUNTRY_ANGUILLA = MK_CNTRY('A', 'I', 0), /**< AI Anguilla */ + WHD_COUNTRY_ANTIGUA_AND_BARBUDA = MK_CNTRY('A', 'G', 0), /**< AG Antigua_and_Barbuda */ + WHD_COUNTRY_ARGENTINA = MK_CNTRY('A', 'R', 0), /**< AR Argentina */ + WHD_COUNTRY_ARMENIA = MK_CNTRY('A', 'M', 0), /**< AM Armenia */ + WHD_COUNTRY_ARUBA = MK_CNTRY('A', 'W', 0), /**< AW Aruba */ + WHD_COUNTRY_AUSTRALIA = MK_CNTRY('A', 'U', 0), /**< AU Australia */ + WHD_COUNTRY_AUSTRIA = MK_CNTRY('A', 'T', 0), /**< AT Austria */ + WHD_COUNTRY_AZERBAIJAN = MK_CNTRY('A', 'Z', 0), /**< AZ Azerbaijan */ + WHD_COUNTRY_BAHAMAS = MK_CNTRY('B', 'S', 0), /**< BS Bahamas */ + WHD_COUNTRY_BAHRAIN = MK_CNTRY('B', 'H', 0), /**< BH Bahrain */ + WHD_COUNTRY_BAKER_ISLAND = MK_CNTRY('0', 'B', 0), /**< 0B Baker_Island */ + WHD_COUNTRY_BANGLADESH = MK_CNTRY('B', 'D', 0), /**< BD Bangladesh */ + WHD_COUNTRY_BARBADOS = MK_CNTRY('B', 'B', 0), /**< BB Barbados */ + WHD_COUNTRY_BELARUS = MK_CNTRY('B', 'Y', 0), /**< BY Belarus */ + WHD_COUNTRY_BELGIUM = MK_CNTRY('B', 'E', 0), /**< BE Belgium */ + WHD_COUNTRY_BELIZE = MK_CNTRY('B', 'Z', 0), /**< BZ Belize */ + WHD_COUNTRY_BENIN = MK_CNTRY('B', 'J', 0), /**< BJ Benin */ + WHD_COUNTRY_BERMUDA = MK_CNTRY('B', 'M', 0), /**< BM Bermuda */ + WHD_COUNTRY_BHUTAN = MK_CNTRY('B', 'T', 0), /**< BT Bhutan */ + WHD_COUNTRY_BOLIVIA = MK_CNTRY('B', 'O', 0), /**< BO Bolivia */ + WHD_COUNTRY_BOSNIA_AND_HERZEGOVINA = MK_CNTRY('B', 'A', 0), /**< BA Bosnia_and_Herzegovina */ + WHD_COUNTRY_BOTSWANA = MK_CNTRY('B', 'W', 0), /**< BW Botswana */ + WHD_COUNTRY_BRAZIL = MK_CNTRY('B', 'R', 0), /**< BR Brazil */ + WHD_COUNTRY_BRITISH_INDIAN_OCEAN_TERRITORY = MK_CNTRY('I', 'O', 0), /**< IO British_Indian_Ocean_Territory */ + WHD_COUNTRY_BRUNEI_DARUSSALAM = MK_CNTRY('B', 'N', 0), /**< BN Brunei_Darussalam */ + WHD_COUNTRY_BULGARIA = MK_CNTRY('B', 'G', 0), /**< BG Bulgaria */ + WHD_COUNTRY_BURKINA_FASO = MK_CNTRY('B', 'F', 0), /**< BF Burkina_Faso */ + WHD_COUNTRY_BURUNDI = MK_CNTRY('B', 'I', 0), /**< BI Burundi */ + WHD_COUNTRY_CAMBODIA = MK_CNTRY('K', 'H', 0), /**< KH Cambodia */ + WHD_COUNTRY_CAMEROON = MK_CNTRY('C', 'M', 0), /**< CM Cameroon */ + WHD_COUNTRY_CANADA = MK_CNTRY('C', 'A', 0), /**< CA Canada */ + WHD_COUNTRY_CANADA_REV950 = MK_CNTRY('C', 'A', 950), /**< CA Canada Revision 950 */ + WHD_COUNTRY_CAPE_VERDE = MK_CNTRY('C', 'V', 0), /**< CV Cape_Verde */ + WHD_COUNTRY_CAYMAN_ISLANDS = MK_CNTRY('K', 'Y', 0), /**< KY Cayman_Islands */ + WHD_COUNTRY_CENTRAL_AFRICAN_REPUBLIC = MK_CNTRY('C', 'F', 0), /**< CF Central_African_Republic */ + WHD_COUNTRY_CHAD = MK_CNTRY('T', 'D', 0), /**< TD Chad */ + WHD_COUNTRY_CHILE = MK_CNTRY('C', 'L', 0), /**< CL Chile */ + WHD_COUNTRY_CHINA = MK_CNTRY('C', 'N', 0), /**< CN China */ + WHD_COUNTRY_CHRISTMAS_ISLAND = MK_CNTRY('C', 'X', 0), /**< CX Christmas_Island */ + WHD_COUNTRY_COLOMBIA = MK_CNTRY('C', 'O', 0), /**< CO Colombia */ + WHD_COUNTRY_COMOROS = MK_CNTRY('K', 'M', 0), /**< KM Comoros */ + WHD_COUNTRY_CONGO = MK_CNTRY('C', 'G', 0), /**< CG Congo */ + WHD_COUNTRY_CONGO_THE_DEMOCRATIC_REPUBLIC_OF_THE = MK_CNTRY('C', 'D', 0), /**< CD Congo,_The_Democratic_Republic_Of_The */ + WHD_COUNTRY_COSTA_RICA = MK_CNTRY('C', 'R', 0), /**< CR Costa_Rica */ + WHD_COUNTRY_COTE_DIVOIRE = MK_CNTRY('C', 'I', 0), /**< CI Cote_D'ivoire */ + WHD_COUNTRY_CROATIA = MK_CNTRY('H', 'R', 0), /**< HR Croatia */ + WHD_COUNTRY_CUBA = MK_CNTRY('C', 'U', 0), /**< CU Cuba */ + WHD_COUNTRY_CYPRUS = MK_CNTRY('C', 'Y', 0), /**< CY Cyprus */ + WHD_COUNTRY_CZECH_REPUBLIC = MK_CNTRY('C', 'Z', 0), /**< CZ Czech_Republic */ + WHD_COUNTRY_DENMARK = MK_CNTRY('D', 'K', 0), /**< DK Denmark */ + WHD_COUNTRY_DJIBOUTI = MK_CNTRY('D', 'J', 0), /**< DJ Djibouti */ + WHD_COUNTRY_DOMINICA = MK_CNTRY('D', 'M', 0), /**< DM Dominica */ + WHD_COUNTRY_DOMINICAN_REPUBLIC = MK_CNTRY('D', 'O', 0), /**< DO Dominican_Republic */ + WHD_COUNTRY_DOWN_UNDER = MK_CNTRY('A', 'U', 0), /**< AU G'Day mate! */ + WHD_COUNTRY_ECUADOR = MK_CNTRY('E', 'C', 0), /**< EC Ecuador */ + WHD_COUNTRY_EGYPT = MK_CNTRY('E', 'G', 0), /**< EG Egypt */ + WHD_COUNTRY_EL_SALVADOR = MK_CNTRY('S', 'V', 0), /**< SV El_Salvador */ + WHD_COUNTRY_EQUATORIAL_GUINEA = MK_CNTRY('G', 'Q', 0), /**< GQ Equatorial_Guinea */ + WHD_COUNTRY_ERITREA = MK_CNTRY('E', 'R', 0), /**< ER Eritrea */ + WHD_COUNTRY_ESTONIA = MK_CNTRY('E', 'E', 0), /**< EE Estonia */ + WHD_COUNTRY_ETHIOPIA = MK_CNTRY('E', 'T', 0), /**< ET Ethiopia */ + WHD_COUNTRY_FALKLAND_ISLANDS_MALVINAS = MK_CNTRY('F', 'K', 0), /**< FK Falkland_Islands_(Malvinas) */ + WHD_COUNTRY_FAROE_ISLANDS = MK_CNTRY('F', 'O', 0), /**< FO Faroe_Islands */ + WHD_COUNTRY_FIJI = MK_CNTRY('F', 'J', 0), /**< FJ Fiji */ + WHD_COUNTRY_FINLAND = MK_CNTRY('F', 'I', 0), /**< FI Finland */ + WHD_COUNTRY_FRANCE = MK_CNTRY('F', 'R', 0), /**< FR France */ + WHD_COUNTRY_FRENCH_GUINA = MK_CNTRY('G', 'F', 0), /**< GF French_Guina */ + WHD_COUNTRY_FRENCH_POLYNESIA = MK_CNTRY('P', 'F', 0), /**< PF French_Polynesia */ + WHD_COUNTRY_FRENCH_SOUTHERN_TERRITORIES = MK_CNTRY('T', 'F', 0), /**< TF French_Southern_Territories */ + WHD_COUNTRY_GABON = MK_CNTRY('G', 'A', 0), /**< GA Gabon */ + WHD_COUNTRY_GAMBIA = MK_CNTRY('G', 'M', 0), /**< GM Gambia */ + WHD_COUNTRY_GEORGIA = MK_CNTRY('G', 'E', 0), /**< GE Georgia */ + WHD_COUNTRY_GERMANY = MK_CNTRY('D', 'E', 0), /**< DE Germany */ + WHD_COUNTRY_EUROPEAN_WIDE_REV895 = MK_CNTRY('E', '0', 895), /**< E0 European_Wide Revision 895 */ + WHD_COUNTRY_GHANA = MK_CNTRY('G', 'H', 0), /**< GH Ghana */ + WHD_COUNTRY_GIBRALTAR = MK_CNTRY('G', 'I', 0), /**< GI Gibraltar */ + WHD_COUNTRY_GREECE = MK_CNTRY('G', 'R', 0), /**< GR Greece */ + WHD_COUNTRY_GRENADA = MK_CNTRY('G', 'D', 0), /**< GD Grenada */ + WHD_COUNTRY_GUADELOUPE = MK_CNTRY('G', 'P', 0), /**< GP Guadeloupe */ + WHD_COUNTRY_GUAM = MK_CNTRY('G', 'U', 0), /**< GU Guam */ + WHD_COUNTRY_GUATEMALA = MK_CNTRY('G', 'T', 0), /**< GT Guatemala */ + WHD_COUNTRY_GUERNSEY = MK_CNTRY('G', 'G', 0), /**< GG Guernsey */ + WHD_COUNTRY_GUINEA = MK_CNTRY('G', 'N', 0), /**< GN Guinea */ + WHD_COUNTRY_GUINEA_BISSAU = MK_CNTRY('G', 'W', 0), /**< GW Guinea-bissau */ + WHD_COUNTRY_GUYANA = MK_CNTRY('G', 'Y', 0), /**< GY Guyana */ + WHD_COUNTRY_HAITI = MK_CNTRY('H', 'T', 0), /**< HT Haiti */ + WHD_COUNTRY_HOLY_SEE_VATICAN_CITY_STATE = MK_CNTRY('V', 'A', 0), /**< VA Holy_See_(Vatican_City_State) */ + WHD_COUNTRY_HONDURAS = MK_CNTRY('H', 'N', 0), /**< HN Honduras */ + WHD_COUNTRY_HONG_KONG = MK_CNTRY('H', 'K', 0), /**< HK Hong_Kong */ + WHD_COUNTRY_HUNGARY = MK_CNTRY('H', 'U', 0), /**< HU Hungary */ + WHD_COUNTRY_ICELAND = MK_CNTRY('I', 'S', 0), /**< IS Iceland */ + WHD_COUNTRY_INDIA = MK_CNTRY('I', 'N', 0), /**< IN India */ + WHD_COUNTRY_INDONESIA = MK_CNTRY('I', 'D', 0), /**< ID Indonesia */ + WHD_COUNTRY_IRAN_ISLAMIC_REPUBLIC_OF = MK_CNTRY('I', 'R', 0), /**< IR Iran,_Islamic_Republic_Of */ + WHD_COUNTRY_IRAQ = MK_CNTRY('I', 'Q', 0), /**< IQ Iraq */ + WHD_COUNTRY_IRELAND = MK_CNTRY('I', 'E', 0), /**< IE Ireland */ + WHD_COUNTRY_ISRAEL = MK_CNTRY('I', 'L', 0), /**< IL Israel */ + WHD_COUNTRY_ITALY = MK_CNTRY('I', 'T', 0), /**< IT Italy */ + WHD_COUNTRY_JAMAICA = MK_CNTRY('J', 'M', 0), /**< JM Jamaica */ + WHD_COUNTRY_JAPAN = MK_CNTRY('J', 'P', 0), /**< JP Japan */ + WHD_COUNTRY_JERSEY = MK_CNTRY('J', 'E', 0), /**< JE Jersey */ + WHD_COUNTRY_JORDAN = MK_CNTRY('J', 'O', 0), /**< JO Jordan */ + WHD_COUNTRY_KAZAKHSTAN = MK_CNTRY('K', 'Z', 0), /**< KZ Kazakhstan */ + WHD_COUNTRY_KENYA = MK_CNTRY('K', 'E', 0), /**< KE Kenya */ + WHD_COUNTRY_KIRIBATI = MK_CNTRY('K', 'I', 0), /**< KI Kiribati */ + WHD_COUNTRY_KOREA_REPUBLIC_OF = MK_CNTRY('K', 'R', 1), /**< KR Korea,_Republic_Of */ + WHD_COUNTRY_KOSOVO = MK_CNTRY('0', 'A', 0), /**< 0A Kosovo */ + WHD_COUNTRY_KUWAIT = MK_CNTRY('K', 'W', 0), /**< KW Kuwait */ + WHD_COUNTRY_KYRGYZSTAN = MK_CNTRY('K', 'G', 0), /**< KG Kyrgyzstan */ + WHD_COUNTRY_LAO_PEOPLES_DEMOCRATIC_REPUBIC = MK_CNTRY('L', 'A', 0), /**< LA Lao_People's_Democratic_Repubic */ + WHD_COUNTRY_LATVIA = MK_CNTRY('L', 'V', 0), /**< LV Latvia */ + WHD_COUNTRY_LEBANON = MK_CNTRY('L', 'B', 0), /**< LB Lebanon */ + WHD_COUNTRY_LESOTHO = MK_CNTRY('L', 'S', 0), /**< LS Lesotho */ + WHD_COUNTRY_LIBERIA = MK_CNTRY('L', 'R', 0), /**< LR Liberia */ + WHD_COUNTRY_LIBYAN_ARAB_JAMAHIRIYA = MK_CNTRY('L', 'Y', 0), /**< LY Libyan_Arab_Jamahiriya */ + WHD_COUNTRY_LIECHTENSTEIN = MK_CNTRY('L', 'I', 0), /**< LI Liechtenstein */ + WHD_COUNTRY_LITHUANIA = MK_CNTRY('L', 'T', 0), /**< LT Lithuania */ + WHD_COUNTRY_LUXEMBOURG = MK_CNTRY('L', 'U', 0), /**< LU Luxembourg */ + WHD_COUNTRY_MACAO = MK_CNTRY('M', 'O', 0), /**< MO Macao */ + WHD_COUNTRY_MACEDONIA_FORMER_YUGOSLAV_REPUBLIC_OF = MK_CNTRY('M', 'K', 0), /**< MK Macedonia,_Former_Yugoslav_Republic_Of */ + WHD_COUNTRY_MADAGASCAR = MK_CNTRY('M', 'G', 0), /**< MG Madagascar */ + WHD_COUNTRY_MALAWI = MK_CNTRY('M', 'W', 0), /**< MW Malawi */ + WHD_COUNTRY_MALAYSIA = MK_CNTRY('M', 'Y', 0), /**< MY Malaysia */ + WHD_COUNTRY_MALDIVES = MK_CNTRY('M', 'V', 0), /**< MV Maldives */ + WHD_COUNTRY_MALI = MK_CNTRY('M', 'L', 0), /**< ML Mali */ + WHD_COUNTRY_MALTA = MK_CNTRY('M', 'T', 0), /**< MT Malta */ + WHD_COUNTRY_MAN_ISLE_OF = MK_CNTRY('I', 'M', 0), /**< IM Man,_Isle_Of */ + WHD_COUNTRY_MARTINIQUE = MK_CNTRY('M', 'Q', 0), /**< MQ Martinique */ + WHD_COUNTRY_MAURITANIA = MK_CNTRY('M', 'R', 0), /**< MR Mauritania */ + WHD_COUNTRY_MAURITIUS = MK_CNTRY('M', 'U', 0), /**< MU Mauritius */ + WHD_COUNTRY_MAYOTTE = MK_CNTRY('Y', 'T', 0), /**< YT Mayotte */ + WHD_COUNTRY_MEXICO = MK_CNTRY('M', 'X', 0), /**< MX Mexico */ + WHD_COUNTRY_MICRONESIA_FEDERATED_STATES_OF = MK_CNTRY('F', 'M', 0), /**< FM Micronesia,_Federated_States_Of */ + WHD_COUNTRY_MOLDOVA_REPUBLIC_OF = MK_CNTRY('M', 'D', 0), /**< MD Moldova,_Republic_Of */ + WHD_COUNTRY_MONACO = MK_CNTRY('M', 'C', 0), /**< MC Monaco */ + WHD_COUNTRY_MONGOLIA = MK_CNTRY('M', 'N', 0), /**< MN Mongolia */ + WHD_COUNTRY_MONTENEGRO = MK_CNTRY('M', 'E', 0), /**< ME Montenegro */ + WHD_COUNTRY_MONTSERRAT = MK_CNTRY('M', 'S', 0), /**< MS Montserrat */ + WHD_COUNTRY_MOROCCO = MK_CNTRY('M', 'A', 0), /**< MA Morocco */ + WHD_COUNTRY_MOZAMBIQUE = MK_CNTRY('M', 'Z', 0), /**< MZ Mozambique */ + WHD_COUNTRY_MYANMAR = MK_CNTRY('M', 'M', 0), /**< MM Myanmar */ + WHD_COUNTRY_NAMIBIA = MK_CNTRY('N', 'A', 0), /**< NA Namibia */ + WHD_COUNTRY_NAURU = MK_CNTRY('N', 'R', 0), /**< NR Nauru */ + WHD_COUNTRY_NEPAL = MK_CNTRY('N', 'P', 0), /**< NP Nepal */ + WHD_COUNTRY_NETHERLANDS = MK_CNTRY('N', 'L', 0), /**< NL Netherlands */ + WHD_COUNTRY_NETHERLANDS_ANTILLES = MK_CNTRY('A', 'N', 0), /**< AN Netherlands_Antilles */ + WHD_COUNTRY_NEW_CALEDONIA = MK_CNTRY('N', 'C', 0), /**< NC New_Caledonia */ + WHD_COUNTRY_NEW_ZEALAND = MK_CNTRY('N', 'Z', 0), /**< NZ New_Zealand */ + WHD_COUNTRY_NICARAGUA = MK_CNTRY('N', 'I', 0), /**< NI Nicaragua */ + WHD_COUNTRY_NIGER = MK_CNTRY('N', 'E', 0), /**< NE Niger */ + WHD_COUNTRY_NIGERIA = MK_CNTRY('N', 'G', 0), /**< NG Nigeria */ + WHD_COUNTRY_NORFOLK_ISLAND = MK_CNTRY('N', 'F', 0), /**< NF Norfolk_Island */ + WHD_COUNTRY_NORTHERN_MARIANA_ISLANDS = MK_CNTRY('M', 'P', 0), /**< MP Northern_Mariana_Islands */ + WHD_COUNTRY_NORWAY = MK_CNTRY('N', 'O', 0), /**< NO Norway */ + WHD_COUNTRY_OMAN = MK_CNTRY('O', 'M', 0), /**< OM Oman */ + WHD_COUNTRY_PAKISTAN = MK_CNTRY('P', 'K', 0), /**< PK Pakistan */ + WHD_COUNTRY_PALAU = MK_CNTRY('P', 'W', 0), /**< PW Palau */ + WHD_COUNTRY_PANAMA = MK_CNTRY('P', 'A', 0), /**< PA Panama */ + WHD_COUNTRY_PAPUA_NEW_GUINEA = MK_CNTRY('P', 'G', 0), /**< PG Papua_New_Guinea */ + WHD_COUNTRY_PARAGUAY = MK_CNTRY('P', 'Y', 0), /**< PY Paraguay */ + WHD_COUNTRY_PERU = MK_CNTRY('P', 'E', 0), /**< PE Peru */ + WHD_COUNTRY_PHILIPPINES = MK_CNTRY('P', 'H', 0), /**< PH Philippines */ + WHD_COUNTRY_POLAND = MK_CNTRY('P', 'L', 0), /**< PL Poland */ + WHD_COUNTRY_PORTUGAL = MK_CNTRY('P', 'T', 0), /**< PT Portugal */ + WHD_COUNTRY_PUETO_RICO = MK_CNTRY('P', 'R', 0), /**< PR Pueto_Rico */ + WHD_COUNTRY_QATAR = MK_CNTRY('Q', 'A', 0), /**< QA Qatar */ + WHD_COUNTRY_REUNION = MK_CNTRY('R', 'E', 0), /**< RE Reunion */ + WHD_COUNTRY_ROMANIA = MK_CNTRY('R', 'O', 0), /**< RO Romania */ + WHD_COUNTRY_RUSSIAN_FEDERATION = MK_CNTRY('R', 'U', 0), /**< RU Russian_Federation */ + WHD_COUNTRY_RWANDA = MK_CNTRY('R', 'W', 0), /**< RW Rwanda */ + WHD_COUNTRY_SAINT_KITTS_AND_NEVIS = MK_CNTRY('K', 'N', 0), /**< KN Saint_Kitts_and_Nevis */ + WHD_COUNTRY_SAINT_LUCIA = MK_CNTRY('L', 'C', 0), /**< LC Saint_Lucia */ + WHD_COUNTRY_SAINT_PIERRE_AND_MIQUELON = MK_CNTRY('P', 'M', 0), /**< PM Saint_Pierre_and_Miquelon */ + WHD_COUNTRY_SAINT_VINCENT_AND_THE_GRENADINES = MK_CNTRY('V', 'C', 0), /**< VC Saint_Vincent_and_The_Grenadines */ + WHD_COUNTRY_SAMOA = MK_CNTRY('W', 'S', 0), /**< WS Samoa */ + WHD_COUNTRY_SANIT_MARTIN_SINT_MARTEEN = MK_CNTRY('M', 'F', 0), /**< MF Sanit_Martin_/_Sint_Marteen */ + WHD_COUNTRY_SAO_TOME_AND_PRINCIPE = MK_CNTRY('S', 'T', 0), /**< ST Sao_Tome_and_Principe */ + WHD_COUNTRY_SAUDI_ARABIA = MK_CNTRY('S', 'A', 0), /**< SA Saudi_Arabia */ + WHD_COUNTRY_SENEGAL = MK_CNTRY('S', 'N', 0), /**< SN Senegal */ + WHD_COUNTRY_SERBIA = MK_CNTRY('R', 'S', 0), /**< RS Serbia */ + WHD_COUNTRY_SEYCHELLES = MK_CNTRY('S', 'C', 0), /**< SC Seychelles */ + WHD_COUNTRY_SIERRA_LEONE = MK_CNTRY('S', 'L', 0), /**< SL Sierra_Leone */ + WHD_COUNTRY_SINGAPORE = MK_CNTRY('S', 'G', 0), /**< SG Singapore */ + WHD_COUNTRY_SLOVAKIA = MK_CNTRY('S', 'K', 0), /**< SK Slovakia */ + WHD_COUNTRY_SLOVENIA = MK_CNTRY('S', 'I', 0), /**< SI Slovenia */ + WHD_COUNTRY_SOLOMON_ISLANDS = MK_CNTRY('S', 'B', 0), /**< SB Solomon_Islands */ + WHD_COUNTRY_SOMALIA = MK_CNTRY('S', 'O', 0), /**< SO Somalia */ + WHD_COUNTRY_SOUTH_AFRICA = MK_CNTRY('Z', 'A', 0), /**< ZA South_Africa */ + WHD_COUNTRY_SPAIN = MK_CNTRY('E', 'S', 0), /**< ES Spain */ + WHD_COUNTRY_SRI_LANKA = MK_CNTRY('L', 'K', 0), /**< LK Sri_Lanka */ + WHD_COUNTRY_SURINAME = MK_CNTRY('S', 'R', 0), /**< SR Suriname */ + WHD_COUNTRY_SWAZILAND = MK_CNTRY('S', 'Z', 0), /**< SZ Swaziland */ + WHD_COUNTRY_SWEDEN = MK_CNTRY('S', 'E', 0), /**< SE Sweden */ + WHD_COUNTRY_SWITZERLAND = MK_CNTRY('C', 'H', 0), /**< CH Switzerland */ + WHD_COUNTRY_SYRIAN_ARAB_REPUBLIC = MK_CNTRY('S', 'Y', 0), /**< SY Syrian_Arab_Republic */ + WHD_COUNTRY_TAIWAN_PROVINCE_OF_CHINA = MK_CNTRY('T', 'W', 0), /**< TW Taiwan,_Province_Of_China */ + WHD_COUNTRY_TAJIKISTAN = MK_CNTRY('T', 'J', 0), /**< TJ Tajikistan */ + WHD_COUNTRY_TANZANIA_UNITED_REPUBLIC_OF = MK_CNTRY('T', 'Z', 0), /**< TZ Tanzania,_United_Republic_Of */ + WHD_COUNTRY_THAILAND = MK_CNTRY('T', 'H', 0), /**< TH Thailand */ + WHD_COUNTRY_TOGO = MK_CNTRY('T', 'G', 0), /**< TG Togo */ + WHD_COUNTRY_TONGA = MK_CNTRY('T', 'O', 0), /**< TO Tonga */ + WHD_COUNTRY_TRINIDAD_AND_TOBAGO = MK_CNTRY('T', 'T', 0), /**< TT Trinidad_and_Tobago */ + WHD_COUNTRY_TUNISIA = MK_CNTRY('T', 'N', 0), /**< TN Tunisia */ + WHD_COUNTRY_TURKEY = MK_CNTRY('T', 'R', 0), /**< TR Turkey */ + WHD_COUNTRY_TURKMENISTAN = MK_CNTRY('T', 'M', 0), /**< TM Turkmenistan */ + WHD_COUNTRY_TURKS_AND_CAICOS_ISLANDS = MK_CNTRY('T', 'C', 0), /**< TC Turks_and_Caicos_Islands */ + WHD_COUNTRY_TUVALU = MK_CNTRY('T', 'V', 0), /**< TV Tuvalu */ + WHD_COUNTRY_UGANDA = MK_CNTRY('U', 'G', 0), /**< UG Uganda */ + WHD_COUNTRY_UKRAINE = MK_CNTRY('U', 'A', 0), /**< UA Ukraine */ + WHD_COUNTRY_UNITED_ARAB_EMIRATES = MK_CNTRY('A', 'E', 0), /**< AE United_Arab_Emirates */ + WHD_COUNTRY_UNITED_KINGDOM = MK_CNTRY('G', 'B', 0), /**< GB United_Kingdom */ + WHD_COUNTRY_UNITED_STATES = MK_CNTRY('U', 'S', 0), /**< US United_States */ + WHD_COUNTRY_UNITED_STATES_REV4 = MK_CNTRY('U', 'S', 4), /**< US United_States Revision 4 */ + WHD_COUNTRY_UNITED_STATES_REV931 = MK_CNTRY('Q', '1', 931), /**< Q1 United_States Revision 931 */ + WHD_COUNTRY_UNITED_STATES_NO_DFS = MK_CNTRY('Q', '2', 0), /**< Q2 United_States_(No_DFS) */ + WHD_COUNTRY_UNITED_STATES_MINOR_OUTLYING_ISLANDS = MK_CNTRY('U', 'M', 0), /**< UM United_States_Minor_Outlying_Islands */ + WHD_COUNTRY_URUGUAY = MK_CNTRY('U', 'Y', 0), /**< UY Uruguay */ + WHD_COUNTRY_UZBEKISTAN = MK_CNTRY('U', 'Z', 0), /**< UZ Uzbekistan */ + WHD_COUNTRY_VANUATU = MK_CNTRY('V', 'U', 0), /**< VU Vanuatu */ + WHD_COUNTRY_VENEZUELA = MK_CNTRY('V', 'E', 0), /**< VE Venezuela */ + WHD_COUNTRY_VIET_NAM = MK_CNTRY('V', 'N', 0), /**< VN Viet_Nam */ + WHD_COUNTRY_VIRGIN_ISLANDS_BRITISH = MK_CNTRY('V', 'G', 0), /**< VG Virgin_Islands,_British */ + WHD_COUNTRY_VIRGIN_ISLANDS_US = MK_CNTRY('V', 'I', 0), /**< VI Virgin_Islands,_U.S. */ + WHD_COUNTRY_WALLIS_AND_FUTUNA = MK_CNTRY('W', 'F', 0), /**< WF Wallis_and_Futuna */ + WHD_COUNTRY_WEST_BANK = MK_CNTRY('0', 'C', 0), /**< 0C West_Bank */ + WHD_COUNTRY_WESTERN_SAHARA = MK_CNTRY('E', 'H', 0), /**< EH Western_Sahara */ + WHD_COUNTRY_WORLD_WIDE_XV_REV983 = MK_CNTRY('X', 'V', 983), /**< Worldwide Locale Revision 983 */ + WHD_COUNTRY_WORLD_WIDE_XX = MK_CNTRY('X', 'X', 0), /**< Worldwide Locale (passive Ch12-14) */ + WHD_COUNTRY_WORLD_WIDE_XX_REV17 = MK_CNTRY('X', 'X', 17), /**< Worldwide Locale (passive Ch12-14) Revision 17 */ + WHD_COUNTRY_YEMEN = MK_CNTRY('Y', 'E', 0), /**< YE Yemen */ + WHD_COUNTRY_ZAMBIA = MK_CNTRY('Z', 'M', 0), /**< ZM Zambia */ + WHD_COUNTRY_ZIMBABWE = MK_CNTRY('Z', 'W', 0), /**< ZW Zimbabwe */ +} whd_country_code_t; + +/** + * Structure for storing extended scan parameters + */ +typedef struct +{ + int32_t number_of_probes_per_channel; /**< Number of probes to send on each channel */ + int32_t scan_active_dwell_time_per_channel_ms; /**< Period of time to wait on each channel when active scanning */ + int32_t scan_passive_dwell_time_per_channel_ms; /**< Period of time to wait on each channel when passive scanning */ + int32_t scan_home_channel_dwell_time_between_channels_ms; /**< Period of time to wait on the home channel when scanning. Only relevant if associated. */ +} whd_scan_extended_params_t; + +/** + * Structure for storing scan results + */ +#pragma pack(1) +typedef struct whd_scan_result +{ + whd_ssid_t SSID; /**< Service Set Identification (i.e. Name of Access Point) */ + whd_mac_t BSSID; /**< Basic Service Set Identification (i.e. MAC address of Access Point) */ + int16_t signal_strength; /**< Receive Signal Strength Indication in dBm. <-90=Very poor, >-30=Excellent */ + uint32_t max_data_rate; /**< Maximum data rate in kilobits/s */ + whd_bss_type_t bss_type; /**< Network type */ + whd_security_t security; /**< Security type */ + uint8_t channel; /**< Radio channel that the AP beacon was received on */ + whd_802_11_band_t band; /**< Radio band */ + uint8_t ccode[2]; /**< Two letter ISO country code from AP */ + uint8_t flags; /**< flags */ + struct whd_scan_result *next; /**< Pointer to the next scan result */ + uint8_t *ie_ptr; /**< Pointer to received Beacon/Probe Response IE(Information Element) */ + uint32_t ie_len; /**< Length of IE(Information Element) */ +} whd_scan_result_t; +#pragma pack() + +/** + * Structure to store scan result parameters for each AP + */ +typedef struct whd_simple_scan_result +{ + whd_ssid_t SSID; /**< Service Set Identification (i.e. Name of Access Point) */ + whd_mac_t BSSID; /**< Basic Service Set Identification (i.e. MAC address of Access Point) */ + int16_t signal_strength; /**< Receive Signal Strength Indication in dBm. <-90=Very poor, >-30=Excellent */ + whd_security_t security; /**< Security type */ + uint8_t channel; /**< Radio channel that the AP beacon was received on */ +} whd_sync_scan_result_t; + +typedef uint16_t wl_chanspec_t; /**< Channel specified in uint16_t */ +#define MCSSET_LEN 16 /**< Maximum allowed mcs rate */ + +/** BSS(Basic Service Set) information structure + * + * Applications MUST CHECK ie_offset field and length field to access IEs(Information Elements) and + * next bss_info structure in a vector (in whd_sync_scan_result_t) + */ +typedef struct wl_bss_info_struct +{ + uint32_t version; /**< version field */ + uint32_t length; /**< byte length of data in this record, starting at version and including IEs */ + whd_mac_t BSSID; /**< Unique 6-byte MAC address */ + uint16_t beacon_period; /**< Interval between two consecutive beacon frames. Units are Kusec */ + uint16_t capability; /**< Capability information */ + uint8_t SSID_len; /**< SSID length */ + uint8_t SSID[32]; /**< Array to store SSID */ + uint8_t reserved1[1]; /**< Reserved(padding) */ + struct + { + uint32_t count; /**< Count of rates in this set */ + uint8_t rates[16]; /**< rates in 500kbps units, higher bit set if basic */ + } rateset; /**< supported rates */ + wl_chanspec_t chanspec; /**< Channel specification for basic service set */ + uint16_t atim_window; /**< Announcement traffic indication message window size. Units are Kusec */ + uint8_t dtim_period; /**< Delivery traffic indication message period */ + uint8_t reserved2[1]; /**< Reserved(padding) */ + int16_t RSSI; /**< receive signal strength (in dBm) */ + int8_t phy_noise; /**< noise (in dBm) */ + + uint8_t n_cap; /**< BSS is 802.11N Capable */ + uint8_t reserved3[2]; /**< Reserved(padding) */ + uint32_t nbss_cap; /**< 802.11N BSS Capabilities (based on HT_CAP_*) */ + uint8_t ctl_ch; /**< 802.11N BSS control channel number */ + uint8_t reserved4[3]; /**< Reserved(padding) */ + uint32_t reserved32[1]; /**< Reserved for expansion of BSS properties */ + uint8_t flags; /**< flags */ + uint8_t vht_cap; /**< BSS is vht capable */ + uint8_t reserved5[2]; /**< Reserved(padding) */ + uint8_t basic_mcs[MCSSET_LEN]; /**< 802.11N BSS required MCS set */ + + uint16_t ie_offset; /**< offset at which IEs start, from beginning */ + uint32_t ie_length; /**< byte length of Information Elements */ + int16_t SNR; /**< Average SNR(signal to noise ratio) during frame reception */ + /* Add new fields here */ + /* variable length Information Elements */ +} wl_bss_info_t; + +/** Structure for storing 802.11 powersave listen interval values \n + * See @ref whd_wifi_get_listen_interval for more information + */ +typedef struct +{ + uint8_t beacon; /**< Listen interval in beacon periods */ + uint8_t dtim; /**< Listen interval in DTIM periods */ + uint16_t assoc; /**< Listen interval as sent to APs */ +} whd_listen_interval_t; + +/** + * WHD result is specified as uint32_t value + */ +typedef uint32_t whd_result_t; + +/* whd_result_t error code format + * |31-18 (14 bit) for module id|17-16 (2 bit) for result type|15-0 for whd error code| + */ +#define WHD_RESULT_TYPE 0 /**< WHD Result type */ +#define WHD_RESULT_CREATE(x) CY_RSLT_CREATE(WHD_RESULT_TYPE, CY_RSLT_MODULE_DRIVERS_WHD_BASE, (x) ) /**< Create a result value from the specified type, module, and result code */ + +#define WHD_SUCCESS CY_RSLT_SUCCESS /**< Success */ +#define WHD_PENDING WHD_RESULT_CREATE(1) /**< Pending */ +#define WHD_TIMEOUT WHD_RESULT_CREATE(2) /**< Timeout */ +#define WHD_BADARG WHD_RESULT_CREATE(5) /**< Bad Arguments */ +#define WHD_UNFINISHED WHD_RESULT_CREATE(10) /**< Operation not finished yet WHD_RESULT_CREATE(maybe aborted) */ + +#define WHD_PARTIAL_RESULTS WHD_RESULT_CREATE(1003) /**< Partial results */ +#define WHD_INVALID_KEY WHD_RESULT_CREATE(1004) /**< Invalid key */ +#define WHD_DOES_NOT_EXIST WHD_RESULT_CREATE(1005) /**< Does not exist */ +#define WHD_NOT_AUTHENTICATED WHD_RESULT_CREATE(1006) /**< Not authenticated */ +#define WHD_NOT_KEYED WHD_RESULT_CREATE(1007) /**< Not keyed */ +#define WHD_IOCTL_FAIL WHD_RESULT_CREATE(1008) /**< IOCTL fail */ +#define WHD_BUFFER_UNAVAILABLE_TEMPORARY WHD_RESULT_CREATE(1009) /**< Buffer unavailable temporarily */ +#define WHD_BUFFER_UNAVAILABLE_PERMANENT WHD_RESULT_CREATE(1010) /**< Buffer unavailable permanently */ +#define WHD_CONNECTION_LOST WHD_RESULT_CREATE(1012) /**< Connection lost */ +#define WHD_OUT_OF_EVENT_HANDLER_SPACE WHD_RESULT_CREATE(1013) /**< Cannot add extra event handler */ +#define WHD_SEMAPHORE_ERROR WHD_RESULT_CREATE(1014) /**< Error manipulating a semaphore */ +#define WHD_FLOW_CONTROLLED WHD_RESULT_CREATE(1015) /**< Packet retrieval cancelled due to flow control */ +#define WHD_NO_CREDITS WHD_RESULT_CREATE(1016) /**< Packet retrieval cancelled due to lack of bus credits */ +#define WHD_NO_PACKET_TO_SEND WHD_RESULT_CREATE(1017) /**< Packet retrieval cancelled due to no pending packets */ +#define WHD_CORE_CLOCK_NOT_ENABLED WHD_RESULT_CREATE(1018) /**< Core disabled due to no clock */ +#define WHD_CORE_IN_RESET WHD_RESULT_CREATE(1019) /**< Core disabled - in reset */ +#define WHD_UNSUPPORTED WHD_RESULT_CREATE(1020) /**< Unsupported function */ +#define WHD_BUS_WRITE_REGISTER_ERROR WHD_RESULT_CREATE(1021) /**< Error writing to WLAN register */ +#define WHD_SDIO_BUS_UP_FAIL WHD_RESULT_CREATE(1022) /**< SDIO bus failed to come up */ +#define WHD_JOIN_IN_PROGRESS WHD_RESULT_CREATE(1023) /**< Join not finished yet */ +#define WHD_NETWORK_NOT_FOUND WHD_RESULT_CREATE(1024) /**< Specified network was not found */ +#define WHD_INVALID_JOIN_STATUS WHD_RESULT_CREATE(1025) /**< Join status error */ +#define WHD_UNKNOWN_INTERFACE WHD_RESULT_CREATE(1026) /**< Unknown interface specified */ +#define WHD_SDIO_RX_FAIL WHD_RESULT_CREATE(1027) /**< Error during SDIO receive */ +#define WHD_HWTAG_MISMATCH WHD_RESULT_CREATE(1028) /**< Hardware tag header corrupt */ +#define WHD_RX_BUFFER_ALLOC_FAIL WHD_RESULT_CREATE(1029) /**< Failed to allocate a buffer to receive into */ +#define WHD_BUS_READ_REGISTER_ERROR WHD_RESULT_CREATE(1030) /**< Error reading a bus hardware register */ +#define WHD_THREAD_CREATE_FAILED WHD_RESULT_CREATE(1031) /**< Failed to create a new thread */ +#define WHD_QUEUE_ERROR WHD_RESULT_CREATE(1032) /**< Error manipulating a queue */ +#define WHD_BUFFER_POINTER_MOVE_ERROR WHD_RESULT_CREATE(1033) /**< Error moving the current pointer of a packet buffer */ +#define WHD_BUFFER_SIZE_SET_ERROR WHD_RESULT_CREATE(1034) /**< Error setting size of packet buffer */ +#define WHD_THREAD_STACK_NULL WHD_RESULT_CREATE(1035) /**< Null stack pointer passed when non null was reqired */ +#define WHD_THREAD_DELETE_FAIL WHD_RESULT_CREATE(1036) /**< Error deleting a thread */ +#define WHD_SLEEP_ERROR WHD_RESULT_CREATE(1037) /**< Error sleeping a thread */ +#define WHD_BUFFER_ALLOC_FAIL WHD_RESULT_CREATE(1038) /**< Failed to allocate a packet buffer */ +#define WHD_NO_PACKET_TO_RECEIVE WHD_RESULT_CREATE(1039) /**< No Packets waiting to be received */ +#define WHD_INTERFACE_NOT_UP WHD_RESULT_CREATE(1040) /**< Requested interface is not active */ +#define WHD_DELAY_TOO_LONG WHD_RESULT_CREATE(1041) /**< Requested delay is too long */ +#define WHD_INVALID_DUTY_CYCLE WHD_RESULT_CREATE(1042) /**< Duty cycle is outside limit 0 to 100 */ +#define WHD_PMK_WRONG_LENGTH WHD_RESULT_CREATE(1043) /**< Returned pmk was the wrong length */ +#define WHD_UNKNOWN_SECURITY_TYPE WHD_RESULT_CREATE(1044) /**< AP security type was unknown */ +#define WHD_WEP_NOT_ALLOWED WHD_RESULT_CREATE(1045) /**< AP not allowed to use WEP - it is not secure - use Open instead */ +#define WHD_WPA_KEYLEN_BAD WHD_RESULT_CREATE(1046) /**< WPA / WPA2 key length must be between 8 & 64 bytes */ +#define WHD_FILTER_NOT_FOUND WHD_RESULT_CREATE(1047) /**< Specified filter id not found */ +#define WHD_SPI_ID_READ_FAIL WHD_RESULT_CREATE(1048) /**< Failed to read 0xfeedbead SPI id from chip */ +#define WHD_SPI_SIZE_MISMATCH WHD_RESULT_CREATE(1049) /**< Mismatch in sizes between SPI header and SDPCM header */ +#define WHD_ADDRESS_ALREADY_REGISTERED WHD_RESULT_CREATE(1050) /**< Attempt to register a multicast address twice */ +#define WHD_SDIO_RETRIES_EXCEEDED WHD_RESULT_CREATE(1051) /**< SDIO transfer failed too many times. */ +#define WHD_NULL_PTR_ARG WHD_RESULT_CREATE(1052) /**< Null Pointer argument passed to function. */ +#define WHD_THREAD_FINISH_FAIL WHD_RESULT_CREATE(1053) /**< Error deleting a thread */ +#define WHD_WAIT_ABORTED WHD_RESULT_CREATE(1054) /**< Semaphore/mutex wait has been aborted */ +#define WHD_SET_BLOCK_ACK_WINDOW_FAIL WHD_RESULT_CREATE(1055) /**< Failed to set block ack window */ +#define WHD_DELAY_TOO_SHORT WHD_RESULT_CREATE(1056) /**< Requested delay is too short */ +#define WHD_INVALID_INTERFACE WHD_RESULT_CREATE(1057) /**< Invalid interface provided */ +#define WHD_WEP_KEYLEN_BAD WHD_RESULT_CREATE(1058) /**< WEP / WEP_SHARED key length must be 5 or 13 bytes */ +#define WHD_HANDLER_ALREADY_REGISTERED WHD_RESULT_CREATE(1059) /**< EAPOL handler already registered */ +#define WHD_AP_ALREADY_UP WHD_RESULT_CREATE(1060) /**< Soft AP or P2P group owner already up */ +#define WHD_EAPOL_KEY_PACKET_M1_TIMEOUT WHD_RESULT_CREATE(1061) /**< Timeout occurred while waiting for EAPOL packet M1 from AP */ +#define WHD_EAPOL_KEY_PACKET_M3_TIMEOUT WHD_RESULT_CREATE(1062) /**< Timeout occurred while waiting for EAPOL packet M3 from APwhich may indicate incorrect WPA2/WPA passphrase */ +#define WHD_EAPOL_KEY_PACKET_G1_TIMEOUT WHD_RESULT_CREATE(1063) /**< Timeout occurred while waiting for EAPOL packet G1 from AP */ +#define WHD_EAPOL_KEY_FAILURE WHD_RESULT_CREATE(1064) /**< Unknown failure occurred during the EAPOL key handshake */ +#define WHD_MALLOC_FAILURE WHD_RESULT_CREATE(1065) /**< Memory allocation failure */ +#define WHD_ACCESS_POINT_NOT_FOUND WHD_RESULT_CREATE(1066) /**< Access point not found */ +#define WHD_RTOS_ERROR WHD_RESULT_CREATE(1067) /**< RTOS operation failed */ +#define WHD_CLM_BLOB_DLOAD_ERROR WHD_RESULT_CREATE(1068) /**< CLM blob download failed */ +#define WHD_HAL_ERROR WHD_RESULT_CREATE(1069) /**< WHD HAL Error */ +#define WHD_RTOS_STATIC_MEM_LIMIT WHD_RESULT_CREATE(1070) /**< Exceeding the RTOS static objects memory */ +#define WHD_NO_REGISTER_FUNCTION_POINTER WHD_RESULT_CREATE(1071) /**< No register function pointer */ + +#define WLAN_ENUM_OFFSET 2000 /**< WLAN enum offset for WHD_WLAN error processing */ + +#define WHD_WLAN_ERROR WHD_RESULT_CREATE(2001) /**< Generic Error */ +#define WHD_WLAN_BADARG WHD_RESULT_CREATE(2002) /**< Bad Argument */ +#define WHD_WLAN_BADOPTION WHD_RESULT_CREATE(2003) /**< Bad option */ +#define WHD_WLAN_NOTUP WHD_RESULT_CREATE(2004) /**< Not up */ +#define WHD_WLAN_NOTDOWN WHD_RESULT_CREATE(2005) /**< Not down */ +#define WHD_WLAN_NOTAP WHD_RESULT_CREATE(2006) /**< Not AP */ +#define WHD_WLAN_NOTSTA WHD_RESULT_CREATE(2007) /**< Not STA */ +#define WHD_WLAN_BADKEYIDX WHD_RESULT_CREATE(2008) /**< BAD Key Index */ +#define WHD_WLAN_RADIOOFF WHD_RESULT_CREATE(2009) /**< Radio Off */ +#define WHD_WLAN_NOTBANDLOCKED WHD_RESULT_CREATE(2010) /**< Not band locked */ +#define WHD_WLAN_NOCLK WHD_RESULT_CREATE(2011) /**< No Clock */ +#define WHD_WLAN_BADRATESET WHD_RESULT_CREATE(2012) /**< BAD Rate valueset */ +#define WHD_WLAN_BADBAND WHD_RESULT_CREATE(2013) /**< BAD Band */ +#define WHD_WLAN_BUFTOOSHORT WHD_RESULT_CREATE(2014) /**< Buffer too short */ +#define WHD_WLAN_BUFTOOLONG WHD_RESULT_CREATE(2015) /**< Buffer too long */ +#define WHD_WLAN_BUSY WHD_RESULT_CREATE(2016) /**< Busy */ +#define WHD_WLAN_NOTASSOCIATED WHD_RESULT_CREATE(2017) /**< Not Associated */ +#define WHD_WLAN_BADSSIDLEN WHD_RESULT_CREATE(2018) /**< Bad SSID len */ +#define WHD_WLAN_OUTOFRANGECHAN WHD_RESULT_CREATE(2019) /**< Out of Range Channel */ +#define WHD_WLAN_BADCHAN WHD_RESULT_CREATE(2020) /**< Bad Channel */ +#define WHD_WLAN_BADADDR WHD_RESULT_CREATE(2021) /**< Bad Address */ +#define WHD_WLAN_NORESOURCE WHD_RESULT_CREATE(2022) /**< Not Enough Resources */ +#define WHD_WLAN_UNSUPPORTED WHD_RESULT_CREATE(2023) /**< Unsupported */ +#define WHD_WLAN_BADLEN WHD_RESULT_CREATE(2024) /**< Bad length */ +#define WHD_WLAN_NOTREADY WHD_RESULT_CREATE(2025) /**< Not Ready */ +#define WHD_WLAN_EPERM WHD_RESULT_CREATE(2026) /**< Not Permitted */ +#define WHD_WLAN_NOMEM WHD_RESULT_CREATE(2027) /**< No Memory */ +#define WHD_WLAN_ASSOCIATED WHD_RESULT_CREATE(2028) /**< Associated */ +#define WHD_WLAN_RANGE WHD_RESULT_CREATE(2029) /**< Not In Range */ +#define WHD_WLAN_NOTFOUND WHD_RESULT_CREATE(2030) /**< Not Found */ +#define WHD_WLAN_WME_NOT_ENABLED WHD_RESULT_CREATE(2031) /**< WME Not Enabled */ +#define WHD_WLAN_TSPEC_NOTFOUND WHD_RESULT_CREATE(2032) /**< TSPEC Not Found */ +#define WHD_WLAN_ACM_NOTSUPPORTED WHD_RESULT_CREATE(2033) /**< ACM Not Supported */ +#define WHD_WLAN_NOT_WME_ASSOCIATION WHD_RESULT_CREATE(2034) /**< Not WME Association */ +#define WHD_WLAN_SDIO_ERROR WHD_RESULT_CREATE(2035) /**< SDIO Bus Error */ +#define WHD_WLAN_WLAN_DOWN WHD_RESULT_CREATE(2036) /**< WLAN Not Accessible */ +#define WHD_WLAN_BAD_VERSION WHD_RESULT_CREATE(2037) /**< Incorrect version */ +#define WHD_WLAN_TXFAIL WHD_RESULT_CREATE(2038) /**< TX failure */ +#define WHD_WLAN_RXFAIL WHD_RESULT_CREATE(2039) /**< RX failure */ +#define WHD_WLAN_NODEVICE WHD_RESULT_CREATE(2040) /**< Device not present */ +#define WHD_WLAN_UNFINISHED WHD_RESULT_CREATE(2041) /**< To be finished */ +#define WHD_WLAN_NONRESIDENT WHD_RESULT_CREATE(2042) /**< access to nonresident overlay */ +#define WHD_WLAN_DISABLED WHD_RESULT_CREATE(2043) /**< Disabled in this build */ +#define WHD_WLAN_NOFUNCTION WHD_RESULT_CREATE(2044) /**< Function pointer not provided */ +#define WHD_WLAN_INVALID WHD_RESULT_CREATE(2045) /**< Not valid */ +#define WHD_WLAN_NOBAND WHD_RESULT_CREATE(2046) /**< No Band */ + +/** + * type definition for whd_buffer_t + */ +typedef whd_buffer_t whd_buffer_queue_ptr_t; + +#pragma pack(1) + +/** + * Structure for storing AP information + */ +typedef struct whd_ap_info +{ + whd_ssid_t SSID; /**< Service Set Identification (i.e. Name of Access Point) */ + whd_mac_t BSSID; /**< Basic Service Set Identification (i.e. MAC address of Access Point) */ + int16_t signal_strength; /**< Receive Signal Strength Indication in dBm. <-90=Very poor, >-30=Excellent */ + uint32_t max_data_rate; /**< Maximum data rate in kilobits/s */ + whd_bss_type_t bss_type; /**< Network type */ + whd_security_t security; /**< Security type */ + uint8_t channel; /**< Radio channel that the AP beacon was received on */ + whd_802_11_band_t band; /**< Radio band */ + struct whd_ap_info *next; /**< Pointer to the next scan result */ +} whd_ap_info_t; + +/** + * Structure describing a list of associated softAP clients + */ +typedef struct +{ + uint32_t count; /**< Number of MAC addresses in the list */ + whd_mac_t mac_list[1]; /**< Variable length array of MAC addresses */ +} whd_maclist_t; + +#pragma pack() + +/** + * Structure describing a list of PMKID + */ +typedef struct _pmkid +{ + whd_mac_t BSSID; + uint8_t PMKID[PMKID_LEN]; +} pmkid_t; + +typedef struct _pmkid_list +{ + uint32_t npmkid; + pmkid_t pmkid[1]; +} pmkid_list_t; + +/** + * Structure used by both dongle and host + * dongle asks host to start auth(SAE), host updates auth status to dongle. + */ +typedef struct whd_auth_req_status +{ + uint16_t flags; + whd_mac_t peer_mac; /* peer mac address */ + uint32_t ssid_len; + uint8_t ssid[SSID_NAME_SIZE]; + uint8_t pmkid[PMKID_LEN]; +} whd_auth_req_status_t; + +/** + * Time value in milliseconds + */ +typedef uint32_t whd_time_t; + +/** + * Structure for storing a WEP key + */ +typedef struct +{ + uint8_t index; /**< WEP key index [0/1/2/3] */ + uint8_t length; /**< WEP key length. Either 5 bytes (40-bits) or 13-bytes (104-bits) */ + uint8_t data[32]; /**< WEP key as values NOT characters */ +} whd_wep_key_t; + +/** + * Structure for management frame(auth) params + */ +typedef struct whd_auth_params +{ + uint32_t version; + uint32_t dwell_time; + uint16_t len; /* Len includes Len(MAC Headers) + Len(Contents) */ + uint16_t fc; + uint16_t channel; + whd_mac_t da; + whd_mac_t bssid; + uint32_t packetId; + uint8_t data[1]; /* It contains MAC Headers + Contexts*/ +} whd_auth_params_t; + +/** + * Structure for Out-of-band interrupt config parameters which can be set by application during whd power up + */ +typedef struct whd_oob_config +{ + cyhal_gpio_t host_oob_pin; /**< Host-side GPIO pin selection */ + uint8_t dev_gpio_sel; /**< WiFi device-side GPIO pin selection (must be zero) */ + whd_bool_t is_falling_edge; /**< Interrupt trigger (polarity) */ + uint8_t intr_priority; /**< OOB interrupt priority */ +} whd_oob_config_t; + +/** + * Structure for SDIO config parameters which can be set by application during whd power up + */ +typedef struct whd_sdio_config +{ + /* Bus config */ + whd_bool_t sdio_1bit_mode; /**< Default is false, means SDIO operates under 4 bit mode */ + whd_bool_t high_speed_sdio_clock; /**< Default is false, means SDIO operates in normal clock rate */ + whd_oob_config_t oob_config; /**< Out-of-band interrupt configuration (required when bus can sleep) */ +} whd_sdio_config_t; + +/** + * Structure for SPI config parameters which can be set by application during whd power up + */ +typedef struct whd_spi_config +{ + /* Bus config */ + whd_bool_t is_spi_normal_mode; /**< Default is false */ + whd_oob_config_t oob_config; /**< Out-of-band interrupt configuration */ +} whd_spi_config_t; + +/** + * Structure for M2M config parameters which can be set by application during whd power up + */ +typedef struct whd_m2m_config +{ + /* Bus config */ + whd_bool_t is_normal_mode; /**< Default is false */ +} whd_m2m_config_t; + + +/** + * Enumeration of applicable packet mask bits for custom Information Elements (IEs) + */ +typedef enum +{ + VENDOR_IE_BEACON = 0x1, /**< Denotes beacon packet */ + VENDOR_IE_PROBE_RESPONSE = 0x2, /**< Denotes probe response packet */ + VENDOR_IE_ASSOC_RESPONSE = 0x4, /**< Denotes association response packet */ + VENDOR_IE_AUTH_RESPONSE = 0x8, /**< Denotes authentication response packet */ + VENDOR_IE_PROBE_REQUEST = 0x10, /**< Denotes probe request packet */ + VENDOR_IE_ASSOC_REQUEST = 0x20, /**< Denotes association request packet */ + VENDOR_IE_CUSTOM = 0x100, /**< Denotes a custom IE(Information Element) identifier */ + VENDOR_IE_UNKNOWN = ~(VENDOR_IE_BEACON | VENDOR_IE_PROBE_RESPONSE | VENDOR_IE_ASSOC_RESPONSE | \ + VENDOR_IE_AUTH_RESPONSE | VENDOR_IE_PROBE_REQUEST | VENDOR_IE_ASSOC_REQUEST | \ + VENDOR_IE_CUSTOM) +} whd_ie_packet_flag_t; + +/** + * Structure for LE Scan parameters + */ +typedef struct whd_btc_lescan_params +{ + uint16_t priority; /**< LE scan priority */ + uint16_t duty_cycle; /**< LE scan duty cycle */ + uint16_t max_win; /**< LE Max Scan window */ + uint16_t int_grant; /**< LE Small Interval Grant */ + uint16_t scan_int; /**< LE scan interval */ + uint16_t scan_win; /**< LE scan Window */ +} whd_btc_lescan_params_t; + +/** + * Structure for coex config parameters which can be set by application + */ +typedef struct whd_coex_config +{ + whd_btc_lescan_params_t le_scan_params; /**< LE Scan Parameters */ +} whd_coex_config_t; + +#define PORT_FILTER_LEN 26 /**< Port filter len */ +#define PACKET_FILTER_LIST_BUFFER_MAX_LEN 1000 /**< Packet filter buffer max len */ +/** + * Enumeration of packet filter rules + */ +typedef enum +{ + WHD_PACKET_FILTER_RULE_POSITIVE_MATCHING = 0, /**< Specifies that a filter should match a given pattern */ + WHD_PACKET_FILTER_RULE_NEGATIVE_MATCHING = 1 /**< Specifies that a filter should NOT match a given pattern */ +} whd_packet_filter_rule_t; + +/** + * Structure describing a packet filter list item + */ +typedef struct +{ + uint32_t id; /**< Unique identifier for a packet filter item */ + whd_packet_filter_rule_t rule; /**< Filter matches are either POSITIVE or NEGATIVE matching */ + uint16_t offset; /**< Offset in bytes to start filtering (referenced to the start of the ethernet packet) */ + uint16_t mask_size; /**< Size of the mask in bytes */ + uint8_t *mask; /**< Pattern mask bytes to be ANDed with the pattern eg. "\xff00" (must be in network byte order) */ + uint8_t *pattern; /**< Pattern bytes used to filter eg. "\x0800" (must be in network byte order) */ + whd_bool_t enabled_status; /**< When returned from wwd_wifi_get_packet_filters, indicates if the filter is enabled */ +} whd_packet_filter_t; + +#define TKO_DATA_OFFSET offsetof(wl_tko_t, data) /**< TKO data offset */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef INCLUDED_WHD_TYPES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/inc/whd_version.h b/wifi-host-driver/WiFi_Host_Driver/inc/whd_version.h new file mode 100644 index 00000000..a94bc25d --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/inc/whd_version.h @@ -0,0 +1,3 @@ +#define WHD_VERSION "v2.5.0" +#define WHD_BRANCH "v2.5.0" +#define WHD_DATE "2022-09-23 13:14:02 +0800" diff --git a/wifi-host-driver/WiFi_Host_Driver/inc/whd_wifi_api.h b/wifi-host-driver/WiFi_Host_Driver/inc/whd_wifi_api.h new file mode 100644 index 00000000..76a3f10e --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/inc/whd_wifi_api.h @@ -0,0 +1,1321 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Prototypes of functions for controlling the Wi-Fi system + * + * This file provides prototypes for end-user functions which allow + * actions such as scanning for Wi-Fi networks, joining Wi-Fi + * networks, getting the MAC address, etc + * + */ + +#include "cybsp.h" +#include "whd.h" +#include "whd_types.h" + +#ifndef INCLUDED_WHD_WIFI_API_H +#define INCLUDED_WHD_WIFI_API_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Function declarations +******************************************************/ + +/** @addtogroup wifi WHD Wi-Fi API + * APIs for controlling the Wi-Fi system + * @{ + */ + +/** @addtogroup wifimanagement WHD Wi-Fi Management API + * @ingroup wifi + * Initialisation and other management functions for WHD system + * @{ + */ + +/** Initialize an instance of the WHD driver + * + * @param whd_driver_ptr Pointer to Pointer to handle instance of the driver + * @param whd_init_config Pointer to configuration data that controls how the driver is initialized + * @param resource_ops Pointer to resource interface to provide resources to the driver initialization process + * @param buffer_ops Pointer to a buffer interface to provide buffer related services to the driver instance + * @param network_ops Pointer to a whd_netif_funcs_t to provide network stack services to the driver instance + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_init(whd_driver_t *whd_driver_ptr, whd_init_config_t *whd_init_config, + whd_resource_source_t *resource_ops, whd_buffer_funcs_t *buffer_ops, + whd_netif_funcs_t *network_ops); +/* @} */ +/* @} */ + +/** @addtogroup busapi WHD Bus API + * Allows WHD to operate with specific SDIO/SPI bus + * @{ + */ + +#if (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SDIO_INTERFACE) +/** Attach the WLAN Device to a specific SDIO bus + * + * @param whd_driver Pointer to handle instance of the driver + * @param whd_config Configuration for SDIO bus + * @param sdio_obj The SDHC hardware interface, from the Level 3 CY HW APIs + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_bus_sdio_attach(whd_driver_t whd_driver, whd_sdio_config_t *whd_config, cyhal_sdio_t *sdio_obj); + +/** Detach the WLAN Device to a specific SDIO bus + * + * @param whd_driver Pointer to handle instance of the driver + */ +extern void whd_bus_sdio_detach(whd_driver_t whd_driver); + +#elif (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SPI_INTERFACE) +/** Attach the WLAN Device to a specific SPI bus + * + * @param whd_driver Pointer to handle instance of the driver + * @param whd_config Configuration for SPI bus + * @param spi_obj The SPI hardware interface, from the Level 3 CY HW APIs + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_bus_spi_attach(whd_driver_t whd_driver, whd_spi_config_t *whd_config, cyhal_spi_t *spi_obj); + +/** Detach the WLAN Device to a specific SPI bus + * + * @param whd_driver Pointer to handle instance of the driver + */ +extern void whd_bus_spi_detach(whd_driver_t whd_driver); + +#elif (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_M2M_INTERFACE) +/** Attach the WLAN Device to M2M bus + * + * @param whd_driver Pointer to handle instance of the driver + * @param whd_config Configuration for M2M bus + * @param m2m_obj The M2M hardware interface, from the Level 3 CY HW APIs + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_bus_m2m_attach(whd_driver_t whd_driver, whd_m2m_config_t *whd_config, cyhal_m2m_t *m2m_obj); + +/** Detach the WLAN Device to a specific M2M bus + * + * @param whd_driver Pointer to handle instance of the driver + */ +extern void whd_bus_m2m_detach(whd_driver_t whd_driver); + +#else +error "CYBSP_WIFI_INTERFACE_TYPE is not defined" +#endif + +/* @} */ + +/** @addtogroup wifi WHD Wi-Fi API + * APIs for controlling the Wi-Fi system + * @{ + */ + +/** @addtogroup wifimanagement WHD Wi-Fi Management API + * @ingroup wifi + * Initialisation and other management functions for WHD system + * @{ + */ + +/** + * Turn on the Wi-Fi device + * + * Initialise Wi-Fi platform + * Program various WiFi parameters and modes + * + * @param whd_driver Pointer to handle instance of the driver + * @param ifpp Pointer to Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS if initialization is successful, error code otherwise + */ +extern uint32_t whd_wifi_on(whd_driver_t whd_driver, whd_interface_t *ifpp); + +/** + * Turn off the Wi-Fi device + * + * - De-Initialises the required parts of the hardware platform + * i.e. pins for SDIO/SPI, interrupt, reset, power etc. + * + * - De-Initialises the whd thread which arbitrates access + * to the SDIO/SPI bus + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS if deinitialization is successful, Error code otherwise + */ +extern uint32_t whd_wifi_off(whd_interface_t ifp); + +/** Shutdown this instance of the wifi driver, freeing all used resources + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_deinit(whd_interface_t ifp); + +/** Brings up the Wi-Fi core + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_up(whd_interface_t ifp); + +/** Bring down the Wi-Fi core + * + * WARNING / NOTE: + * This brings down the Wi-Fi core and existing network connections will be lost. + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_down(whd_interface_t ifp); + +/** Creates a secondary interface + * + * @param whd_drv Pointer to handle instance of the driver + * @param mac_addr MAC address for the interface + * @param ifpp Pointer to the whd interface pointer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_add_secondary_interface(whd_driver_t whd_drv, whd_mac_t *mac_addr, whd_interface_t *ifpp); +/* @} */ + +/** @addtogroup wifijoin WHD Wi-Fi Join, Scan and Halt API + * @ingroup wifi + * Wi-Fi APIs for join, scan & leave + * @{ + */ + +/** Scan result callback function pointer type + * + * @param result_ptr A pointer to the pointer that indicates where to put the next scan result + * @param user_data User provided data + * @param status Status of scan process + */ +typedef void (*whd_scan_result_callback_t)(whd_scan_result_t **result_ptr, void *user_data, whd_scan_status_t status); + +/** Initiates a scan to search for 802.11 networks. + * + * This functions returns the scan results with limited sets of parameter in a buffer provided by the caller. + * It is also a blocking call. It is an simplified version of the whd_wifi_scan(). + * + * @param ifp Pointer to handle instance of whd interface + * @param scan_result Pointer to user requested records buffer. + * @param count Pointer to the no of records user is interested in, and also to the no of record received. + * + * @note When scanning specific channels, devices with a strong signal strength on nearby channels may be detected + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_scan_synch(whd_interface_t ifp, + whd_sync_scan_result_t *scan_result, + uint32_t *count + ); + +/** Initiates a scan to search for 802.11 networks. + * + * The scan progressively accumulates results over time, and may take between 1 and 10 seconds to complete. + * The results of the scan will be individually provided to the callback function. + * Note: The callback function will be executed in the context of the WHD thread and so must not perform any + * actions that may cause a bus transaction. + * + * @param ifp Pointer to handle instance of whd interface + * @param scan_type Specifies whether the scan should be Active, Passive or scan Prohibited channels + * @param bss_type Specifies whether the scan should search for Infrastructure networks (those using + * an Access Point), Ad-hoc networks, or both types. + * @param optional_ssid If this is non-Null, then the scan will only search for networks using the specified SSID. + * @param optional_mac If this is non-Null, then the scan will only search for networks where + * the BSSID (MAC address of the Access Point) matches the specified MAC address. + * @param optional_channel_list If this is non-Null, then the scan will only search for networks on the + * specified channels - array of channel numbers to search, terminated with a zero + * @param optional_extended_params If this is non-Null, then the scan will obey the specifications about + * dwell times and number of probes. + * @param callback The callback function which will receive and process the result data. + * @param result_ptr Pointer to a pointer to a result storage structure. + * @param user_data user specific data that will be passed directly to the callback function + * + * @note - When scanning specific channels, devices with a strong signal strength on nearby channels may be detected + * - Callback must not use blocking functions, nor use WHD functions, since it is called from the context of the + * WHD thread. + * - The callback, result_ptr and user_data variables will be referenced after the function returns. + * Those variables must remain valid until the scan is complete. + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_scan(whd_interface_t ifp, + whd_scan_type_t scan_type, + whd_bss_type_t bss_type, + const whd_ssid_t *optional_ssid, + const whd_mac_t *optional_mac, + const uint16_t *optional_channel_list, + const whd_scan_extended_params_t *optional_extended_params, + whd_scan_result_callback_t callback, + whd_scan_result_t *result_ptr, + void *user_data); + +/** Abort a previously issued scan + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_stop_scan(whd_interface_t ifp); + +/** Auth result callback function pointer type + * + * @param result_prt A pointer to the pointer that indicates where to put the auth result + * @param len the size of result + * @param status Status of auth process + * @param flag flag of h2e will be indicated in auth request event, otherwise is NULL. + * @param user_data user specific data that will be passed directly to the callback function + * + */ +typedef void (*whd_auth_result_callback_t)(void *result_ptr, uint32_t len, whd_auth_status_t status, uint8_t *flag, + void *user_data); + +/** Initiates SAE auth + * + * The results of the auth will be individually provided to the callback function. + * Note: The callback function will be executed in the context of the WHD thread and so must not perform any + * actions that may cause a bus transaction. + * + * @param ifp Pointer to handle instance of whd interface + * @param callback The callback function which will receive and process the result data. + * @param data Pointer to a pointer to a result storage structure. + * @param user_data user specific data that will be passed directly to the callback function + * + * @note - Callback must not use blocking functions, nor use WHD functions, since it is called from the context of the + * WHD thread. + * - The callback, result_ptr and user_data variables will be referenced after the function returns. + * Those variables must remain valid until the scan is complete. + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_external_auth_request(whd_interface_t ifp, + whd_auth_result_callback_t callback, + void *result_ptr, + void *user_data); +/** Abort authentication request + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_stop_external_auth_request(whd_interface_t ifp); + +/** Joins a Wi-Fi network + * + * Scans for, associates and authenticates with a Wi-Fi network. + * On successful return, the system is ready to send data packets. + * + * @param ifp Pointer to handle instance of whd interface + * @param ssid A null terminated string containing the SSID name of the network to join + * @param auth_type Authentication type + * @param security_key A byte array containing either the cleartext security key for WPA/WPA2/WPA3 secured networks + * @param key_length The length of the security_key in bytes. + * + * @note In case of WPA3/WPA2 transition mode, the security_key value is WPA3 password. + * + * @return WHD_SUCCESS when the system is joined and ready to send data packets + * Error code if an error occurred + */ +extern uint32_t whd_wifi_join(whd_interface_t ifp, const whd_ssid_t *ssid, whd_security_t auth_type, + const uint8_t *security_key, uint8_t key_length); + +/** Joins a specific Wi-Fi network + * + * Associates and authenticates with a specific Wi-Fi access point. + * On successful return, the system is ready to send data packets. + * + * @param ifp Pointer to handle instance of whd interface + * @param ap A pointer to a whd_scan_result_t structure containing AP details and + * set ap.channel to 0 for unspecificed channel + * @param security_key A byte array containing either the cleartext security key for WPA/WPA2 + * secured networks + * @param key_length The length of the security_key in bytes. + * + * @return WHD_SUCCESS when the system is joined and ready to send data packets + * Error code if an error occurred + */ +extern uint32_t whd_wifi_join_specific(whd_interface_t ifp, const whd_scan_result_t *ap, const uint8_t *security_key, + uint8_t key_length); + +/* @} */ + +/** @addtogroup wifiutilities WHD Wi-Fi Utility API + * @ingroup wifi + * Allows WHD to perform utility operations + * @{ + */ + +/** Set the current channel on the WLAN radio + * + * @note On most WLAN devices this will set the channel for both AP *AND* STA + * (since there is only one radio - it cannot be on two channels simulaneously) + * + * @param ifp Pointer to handle instance of whd interface + * @param channel The desired channel + * + * @return WHD_SUCCESS if the channel was successfully set + * Error code if the channel was not successfully set + */ +extern uint32_t whd_wifi_set_channel(whd_interface_t ifp, uint32_t channel); + +/** Get the current channel on the WLAN radio + * + * @note On most WLAN devices this will get the channel for both AP *AND* STA + * (since there is only one radio - it cannot be on two channels simulaneously) + * + * @param ifp Pointer to handle instance of whd interface + * @param channel Pointer to receive the current channel + * + * @return WHD_SUCCESS if the channel was successfully retrieved + * Error code if the channel was not successfully retrieved + */ +extern uint32_t whd_wifi_get_channel(whd_interface_t ifp, uint32_t *channel); + +/** Gets the supported channels + * + * @param ifp Pointer to handle instance of whd interface + * @param channel_list Buffer to store list of the supported channels + * and max channel is WL_NUMCHANNELS + * + * @return WHD_SUCCESS if the active connections was successfully read + * WHD_ERROR if the active connections was not successfully read + */ +extern uint32_t whd_wifi_get_channels(whd_interface_t ifp, whd_list_t *channel_list); + + +/** Set the passphrase + * + * @param ifp Pointer to handle instance of whd interface + * @param security_key The security key (passphrase) which is to be set + * @param key_length length of the key + * + * @return WHD_SUCCESS when the key is set + * Error code if an error occurred + */ +extern uint32_t whd_wifi_set_passphrase(whd_interface_t ifp, const uint8_t *security_key, uint8_t key_length); + +/** Set the SAE password + * + * @param ifp Pointer to handle instance of whd interface + * @param security_key The security key (password) which is to be set + * @param key_length length of the key + * + * @return WHD_SUCCESS when the key is set + * Error code if an error occurred + */ +extern uint32_t whd_wifi_sae_password(whd_interface_t ifp, const uint8_t *security_key, uint8_t key_length); + +/** Enable WHD internal supplicant and set WPA2 passphrase in case of WPA3/WPA2 transition mode + * + * @param ifp Pointer to handle instance of whd interface + * @param security_key_psk The security key (passphrase) which is to be set + * @param psk_length length of the key + * @param auth_type Authentication type: @ref WHD_SECURITY_WPA3_WPA2_PSK + * + * @return WHD_SUCCESS when the supplicant variable and wpa2 passphrase is set + * Error code if an error occurred + */ +extern uint32_t whd_wifi_enable_sup_set_passphrase(whd_interface_t ifp, const uint8_t *security_key_psk, + uint8_t psk_length, whd_security_t auth_type); + +/** Set the PMK Key + * + * @param ifp Pointer to handle instance of whd interface + * @param security_key The security key (PMK) which is to be set + * @param key_length length of the PMK(It must be 32 bytes) + * + * @return WHD_SUCCESS when the key is set + * Error code if an error occurred + */ +extern whd_result_t whd_wifi_set_pmk(whd_interface_t ifp, const uint8_t *security_key, uint8_t key_length); + +/** Set the Roam time threshold + * + * @param ifp Pointer to handle instance of whd interface + * @param roam_time_threshold The maximum roam time threshold which is to be set + * + * @return WHD_SUCCESS when the roam_time_threshold is set + * Error code if an error occurred + */ +extern whd_result_t whd_wifi_set_roam_time_threshold(whd_interface_t ifp, uint32_t roam_time_threshold); + +/** Enable WHD internal supplicant + * + * @param ifp Pointer to handle instance of whd interface + * @param auth_type Authentication type + * + * @return WHD_SUCCESS when the supplicant variable is set + * Error code if an error occurred + */ +extern uint32_t whd_wifi_enable_supplicant(whd_interface_t ifp, whd_security_t auth_type); + +/** Set PMKID in Device (WLAN) + * + * @param ifp Pointer to handle instance of whd interface + * @param pmkid Pointer to BSSID and PMKID(16 bytes) + * + * @return whd_result_t + */ +extern whd_result_t whd_wifi_set_pmksa(whd_interface_t ifp, const pmkid_t *pmkid); + +/** Retrieve the latest RSSI value + * + * @param ifp Pointer to handle instance of whd interface + * @param rssi The location where the RSSI value will be stored + * + * @return WHD_SUCCESS if the RSSI was successfully retrieved + * Error code if the RSSI was not retrieved + */ +extern uint32_t whd_wifi_get_rssi(whd_interface_t ifp, int32_t *rssi); + +/** Retrieve the latest Roam time threshold value + * + * @param ifp Pointer to handle instance of whd interface + * @param roam_time_threshold The location where the roam time threshold value will be stored + * + * @return WHD_SUCCESS if the roam time threshold was successfully retrieved + * Error code if the roam time threshold was not retrieved + */ +extern uint32_t whd_wifi_get_roam_time_threshold(whd_interface_t ifp, uint32_t *roam_time_threshold); + +/** Retrieve the associated STA's RSSI value + * + * @param ifp : Pointer to handle instance of whd interface + * @param rssi : The location where the RSSI value will be stored + * @param client_mac : Pointer to associated client's MAC address + * + * @return WHD_SUCCESS : if the RSSI was successfully retrieved + * Error code : if the RSSI was not retrieved + */ +extern uint32_t whd_wifi_get_ap_client_rssi(whd_interface_t ifp, int32_t *rssi, const whd_mac_t *client_mac); + + +/* @} */ + +/** @addtogroup wifijoin WHD Wi-Fi Join, Scan and Halt API + * @ingroup wifi + * Wi-Fi APIs for join, scan & leave + * @{ + */ +/** Disassociates from a Wi-Fi network. + * Applicable only for STA role + * + * @param ifp Pointer to handle instance of whd interface. + * + * @return WHD_SUCCESS On successful disassociation from the AP + * Error code If an error occurred + */ +extern uint32_t whd_wifi_leave(whd_interface_t ifp); +/* @} */ + +/** @addtogroup wifiutilities WHD Wi-Fi Utility API + * @ingroup wifi + * Allows WHD to perform utility operations + * @{ + */ + +/** Retrieves the current Media Access Control (MAC) address + * (or Ethernet hardware address) of the 802.11 device + * + * @param ifp Pointer to handle instance of whd interface + * @param mac Pointer to a variable that the current MAC address will be written to + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_mac_address(whd_interface_t ifp, whd_mac_t *mac); + +/** Get the BSSID of the interface + * + * @param ifp Pointer to the whd_interface_t + * @param bssid Returns the BSSID address (mac address) if associated + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_bssid(whd_interface_t ifp, whd_mac_t *bssid); +/* @} */ + +/** @addtogroup wifisoftap WHD Wi-Fi SoftAP API + * @ingroup wifi + * Wi-Fi APIs to perform SoftAP related functionalities + * @{ + */ + +/** Initialises an infrastructure WiFi network (SoftAP) + * + * @param ifp Pointer to handle instance of whd interface + * @param ssid A null terminated string containing the SSID name of the network to join + * @param auth_type Authentication type + * @param security_key A byte array containing the cleartext security key for the network + * @param key_length The length of the security_key in bytes. + * @param channel 802.11 channel number + * + * @return WHD_SUCCESS if successfully initialises an AP + * Error code if an error occurred + */ +extern uint32_t whd_wifi_init_ap(whd_interface_t ifp, whd_ssid_t *ssid, whd_security_t auth_type, + const uint8_t *security_key, uint8_t key_length, uint8_t channel); + +/** Start the infrastructure WiFi network (SoftAP) + * using the parameter set by whd_wifi_init_ap() and optionaly by whd_wifi_manage_custom_ie() + * + * @return WHD_SUCCESS if successfully creates an AP + * Error code if an error occurred + */ +extern uint32_t whd_wifi_start_ap(whd_interface_t ifp); + +/** Stops an existing infrastructure WiFi network + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS if the AP is successfully stopped or if the AP has not yet been brought up + * Error code if an error occurred + */ +extern uint32_t whd_wifi_stop_ap(whd_interface_t ifp); + + +/** Get the maximum number of associations supported by AP interfaces + * + * @param ifp Pointer to handle instance of whd interface + * @param max_assoc The maximum number of associations supported by Soft AP interfaces. + * + * @return WHD_SUCCESS if the maximum number of associated clients was successfully read + * WHD_ERROR if the maximum number of associated clients was not successfully read + */ +extern uint32_t whd_wifi_ap_get_max_assoc(whd_interface_t ifp, uint32_t *max_assoc); + +/** Gets the current number of active connections + * + * @param ifp Pointer to handle instance of whd interface + * @param client_list_buffer Buffer to store list of associated clients + * @param buffer_length Length of client list buffer + * + * @return WHD_SUCCESS if the active connections was successfully read + * WHD_ERROR if the active connections was not successfully read + */ +extern uint32_t whd_wifi_get_associated_client_list(whd_interface_t ifp, void *client_list_buffer, + uint16_t buffer_length); + +/** Deauthenticates a STA which may or may not be associated to SoftAP + * + * @param ifp Pointer to handle instance of whd interface + * @param mac Pointer to a variable containing the MAC address to which the deauthentication will be sent + * NULL mac address will deauthenticate all the associated STAs + * + * @param reason Deauthentication reason code + * + * @return WHD_SUCCESS On successful deauthentication of the other STA + * WHD_ERROR If an error occurred + */ +extern uint32_t whd_wifi_deauth_sta(whd_interface_t ifp, whd_mac_t *mac, whd_dot11_reason_code_t reason); + +/** Retrieves AP information + * + * @param ifp Pointer to handle instance of whd interface + * @param ap_info Returns a whd_bss_info_t structure containing AP details + * @param security Authentication type + * + * @return WHD_SUCCESS if the AP info was successfully retrieved + * Error code if the AP info was not successfully retrieved + */ +extern uint32_t whd_wifi_get_ap_info(whd_interface_t ifp, whd_bss_info_t *ap_info, whd_security_t *security); + +/** Set the beacon interval. + * + * Note that the value needs to be set before ap_start in order to beacon interval to take effect. + * + * @param ifp Pointer to handle instance of whd interface + * @param interval Beacon interval in time units (Default: 100 time units = 102.4 ms) + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_ap_set_beacon_interval(whd_interface_t ifp, uint16_t interval); + +/** Set the DTIM interval. + * + * Note that the value needs to be set before ap_start in order to DTIM interval to take effect. + * + * @param ifp Pointer to handle instance of whd interface + * @param interval DTIM interval, in unit of beacon interval + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_ap_set_dtim_interval(whd_interface_t ifp, uint16_t interval); +/* @} */ + + +/** @addtogroup wifipowersave WHD Wi-Fi Power Save API + * @ingroup wifi + * Wi-Fi functions for WLAN low power modes + * @{ + */ + +/** Enables powersave mode on specified interface without regard for throughput reduction + * + * This function enables (legacy) 802.11 PS-Poll mode and should be used + * to achieve the lowest power consumption possible when the Wi-Fi device + * is primarily passively listening to the network + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_enable_powersave(whd_interface_t ifp); + +/** Enables powersave mode on specified interface while attempting to maximise throughput + * + * + * Network traffic is typically bursty. Reception of a packet often means that another + * packet will be received shortly afterwards (and vice versa for transmit). + * + * In high throughput powersave mode, rather then entering powersave mode immediately + * after receiving or sending a packet, the WLAN chip waits for a timeout period before + * returning to sleep. + * + * @param ifp Pointer to handle instance of whd interface + * @param return_to_sleep_delay The variable to set return to sleep delay. + * return to sleep delay must be set to a multiple of 10 and not equal to zero. + * + * @return WHD_SUCCESS if power save mode was successfully enabled + * Error code if power save mode was not successfully enabled + * + */ +extern uint32_t whd_wifi_enable_powersave_with_throughput(whd_interface_t ifp, uint16_t return_to_sleep_delay); + +/** Get powersave mode on specified interface + * + * @param ifp Pointer to handle instance of whd interface + * @param value Value of the current powersave state + * PM1_POWERSAVE_MODE, PM2_POWERSAVE_MODE, NO_POWERSAVE_MODE + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_powersave_mode(whd_interface_t ifp, uint32_t *value); + +/** Disables 802.11 power save mode on specified interface + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS if power save mode was successfully disabled + * Error code if power save mode was not successfully disabled + * + */ +extern uint32_t whd_wifi_disable_powersave(whd_interface_t ifp); +/* @} */ + +/** @addtogroup wifiutilities WHD Wi-Fi Utility API + * @ingroup wifi + * Allows WHD to perform utility operations + * @{ + */ +/** Registers interest in a multicast address + * + * Once a multicast address has been registered, all packets detected on the + * medium destined for that address are forwarded to the host. + * Otherwise they are ignored. + * + * @param ifp Pointer to handle instance of whd interface + * @param mac Ethernet MAC address + * + * @return WHD_SUCCESS if the address was registered successfully + * Error code if the address was not registered + */ +extern uint32_t whd_wifi_register_multicast_address(whd_interface_t ifp, const whd_mac_t *mac); + +/** Unregisters interest in a multicast address + * + * Once a multicast address has been unregistered, all packets detected on the + * medium destined for that address are ignored. + * + * @param ifp Pointer to handle instance of whd interface + * @param mac Ethernet MAC address + * + * @return WHD_SUCCESS if the address was unregistered successfully + * Error code if the address was not unregistered + */ +extern uint32_t whd_wifi_unregister_multicast_address(whd_interface_t ifp, const whd_mac_t *mac); + +/** Sets the 802.11 powersave listen interval for a Wi-Fi client, and communicates + * the listen interval to the Access Point. The listen interval will be set to + * (listen_interval x time_unit) seconds. + * + * The default value for the listen interval is 0. With the default value of 0 set, + * the Wi-Fi device wakes to listen for AP beacons every DTIM period. + * + * If the DTIM listen interval is non-zero, the DTIM listen interval will over ride + * the beacon listen interval value. + * + * @param ifp Pointer to handle instance of whd interface + * @param listen_interval The desired beacon listen interval + * @param time_unit The listen interval time unit; options are beacon period or DTIM period. + * + * @return WHD_SUCCESS If the listen interval was successfully set. + * Error code If the listen interval was not successfully set. + */ +extern uint32_t whd_wifi_set_listen_interval(whd_interface_t ifp, uint8_t listen_interval, + whd_listen_interval_time_unit_t time_unit); + +/** Gets the current value of all beacon listen interval variables + * + * @param ifp Pointer to handle instance of whd interface + * @param li Powersave listen interval values + * - listen_interval_beacon : The current value of the listen interval set as a multiple of the beacon period + * - listen_interval_dtim : The current value of the listen interval set as a multiple of the DTIM period + * - listen_interval_assoc : The current value of the listen interval sent to access points in an association request frame + * + * @return WHD_SUCCESS If all listen interval values are read successfully + * Error code If at least one of the listen interval values are NOT read successfully + */ +extern uint32_t whd_wifi_get_listen_interval(whd_interface_t ifp, whd_listen_interval_t *li); + +/** Determines if a particular interface is ready to transceive ethernet packets + * + * @param ifp Pointer to handle instance of whd interface + * + * @return WHD_SUCCESS if the interface is ready to transceive ethernet packets + * WHD_NOTFOUND no AP with a matching SSID was found + * WHD_NOT_AUTHENTICATED Matching AP was found but it won't let you authenticate. + * This can occur if this device is in the block list on the AP. + * WHD_NOT_KEYED Device has authenticated and associated but has not completed the key exchange. + * This can occur if the passphrase is incorrect. + * Error code if the interface is not ready to transceive ethernet packets + */ +extern uint32_t whd_wifi_is_ready_to_transceive(whd_interface_t ifp); + +/* Certification APIs */ + +/** Retrieve the latest STA EDCF AC parameters + * + * Retrieve the latest Station (STA) interface EDCF (Enhanced Distributed + * Coordination Function) Access Category parameters + * + * @param ifp Pointer to handle instance of whd interface + * @param acp The location where the array of AC parameters will be stored + * + * @return WHD_SUCCESS if the AC Parameters were successfully retrieved + * Error code if the AC Parameters were not retrieved + */ +extern uint32_t whd_wifi_get_acparams(whd_interface_t ifp, whd_edcf_ac_param_t *acp); + +/* Action Frames */ + +/** Manage the addition and removal of custom IEs + * + * @param ifp Pointer to handle instance of whd interface + * @param action the action to take (add or remove IE) + * @param oui the oui of the custom IE + * @param subtype the IE sub-type + * @param data a pointer to the buffer that hold the custom IE + * @param length the length of the buffer pointed to by 'data' + * @param which_packets A mask to indicate in which all packets this IE should be included. See whd_ie_packet_flag_t. + * + * @return WHD_SUCCESS if the custom IE action was successful + * Error code if the custom IE action failed + */ +extern uint32_t whd_wifi_manage_custom_ie(whd_interface_t ifp, whd_custom_ie_action_t action, + const uint8_t *oui, uint8_t subtype, const void *data, + uint16_t length, uint16_t which_packets); + +/** Send a pre-prepared action frame + * + * @param ifp Pointer to handle instance of whd interface + * @param af_params A pointer to a pre-prepared action frame structure + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_send_action_frame(whd_interface_t ifp, whd_af_params_t *af_params); + +/** Send a pre-prepared authentication frame + * + * @param ifp Pointer to handle instance of whd interface + * @param auth_params pointer to a pre-prepared authentication frame structure + * + * @return WHD_SUCCESS or Error code + */ +extern whd_result_t whd_wifi_send_auth_frame(whd_interface_t ifp, whd_auth_params_t *auth_params); + +/** Set coex configuration + * + * @param ifp Pointer to handle instance of whd interface + * @param coex_config Pointer to the structure whd_coex_config_t + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_coex_config(whd_interface_t ifp, whd_coex_config_t *coex_config); + +/** Set auth status used for External AUTH(SAE) + * + * @param ifp Pointer to handle instance of whd interface + * @param whd_auth_req_status Pointer to Auth_Status structure + * + * @return WHD_SUCCESS or Error code + */ +extern whd_result_t whd_wifi_set_auth_status(whd_interface_t ifp, whd_auth_req_status_t *params); + +/** Get FW(chip) Capability + * + * @param ifp Pointer to handle instance of whd interface + * @param value Enum value of the current FW capability, ex: sae or sae_ext or ...etc, + * (enum value map to whd_fwcap_id_t) + * @return WHD_SUCCESS or Error code + */ +extern whd_result_t whd_wifi_get_fwcap(whd_interface_t ifp, uint32_t *value); + +/** Get version of Device (WLAN) Firmware + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[out] version : pointer to store version # + * + * @return whd_result_t + */ +whd_result_t whd_arp_version(whd_interface_t ifp, uint32_t *version); + +/** Get ARP Offload Peer Age from Device (WLAN) + * Length of time in seconds before aging out an entry in the WLAN processor ARP table. + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[out] seconds : pointer to store value + * + * @return whd_result_t + */ +whd_result_t whd_arp_peerage_get(whd_interface_t ifp, uint32_t *seconds); + +/** Set ARP Offload Peer Age in Device (WLAN) + * Length of time in seconds before aging out an entry in the WLAN processor ARP table. + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] seconds : Seconds to age out IP + * + * @return whd_result_t + */ +whd_result_t whd_arp_peerage_set(whd_interface_t ifp, uint32_t seconds); + +/** Get ARP Offload Agent Enable from Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[out] agent_enable : pointer to store value + * + * @return whd_result_t + */ +whd_result_t whd_arp_arpoe_get(whd_interface_t ifp, uint32_t *agent_enable); + +/** Set ARP Offload Agent Enable in Device (WLAN) + * Set Enable/Disable of ARP Offload Agent + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] agent_enable : Enable=1 / Disable=0 + * + * @return whd_result_t + */ +whd_result_t whd_arp_arpoe_set(whd_interface_t ifp, uint32_t agent_enable); + +/** Clear ARP Offload cache in Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * + * @return whd_result_t + */ +whd_result_t whd_arp_cache_clear(whd_interface_t ifp); + +/** Get ARP Offload Feature Flags from Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[out] features : ptr to store currently set features - bit flags CY_ARP_OL_AGENT_ENABLE, etc. + * ARL_OL_AGENT | ARL_OL_SNOOP | ARP_OL_HOST_AUTO_REPLY | ARP_OL_PEER_AUTO_REPLY + * + * @return whd_result_t + */ +whd_result_t whd_arp_features_get(whd_interface_t ifp, uint32_t *features); + +/** Set ARP Offload Feature Flags in Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] features : features to set value (you can OR ('|') multiple flags) CY_ARP_OL_AGENT_ENABLE, etc. + * ARL_OL_AGENT | ARL_OL_SNOOP | ARP_OL_HOST_AUTO_REPLY | ARP_OL_PEER_AUTO_REPLY + * + * @return whd_result_t + */ +whd_result_t whd_arp_features_set(whd_interface_t ifp, uint32_t features); + +/** Print ARP Offload Feature Flags in Human readable form to console + * + * @param[in] features : feature flags to set (you can OR '|' multiple flags) CY_ARP_OL_AGENT_ENABLE, etc. + * ARL_OL_AGENT | ARL_OL_SNOOP | ARP_OL_HOST_AUTO_REPLY | ARP_OL_PEER_AUTO_REPLY + * @param[in] title : Optional: Title for output (NULL == no title) + * + * @return whd_result_t + */ +whd_result_t whd_arp_features_print(uint32_t features, const char *title); + +/** Add ARP Offload Host IP Identifier(s) to HostIP List to Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] host_ipv4_list : pointer to host_ip data (IPv4, 1 uint32_t per ip addr) + * @param[in] count : Number of array elements in host_ip + * + * @return whd_result_t + */ +whd_result_t whd_arp_hostip_list_add(whd_interface_t ifp, uint32_t *host_ipv4_list, uint32_t count); + +/** Add One ARP Offload Host IP Identifier to HostIP List (mbed-style IP string) to Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] ip_addr : pointer to ip string (as returned from mbedos calls) + * + * @return whd_result_t + */ +whd_result_t whd_arp_hostip_list_add_string(whd_interface_t ifp, const char *ip_addr); + +/** Clear One ARP Offload Host IP Identifier from Host IP List in Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] ipv4_addr : ip addr expressed as a uint32_t + * + * @return whd_result_t + */ +whd_result_t whd_arp_hostip_list_clear_id(whd_interface_t ifp, uint32_t ipv4_addr); + +/** Clear One ARP Offload Host IP Identifier from Host IP List (mbed-style IP string) in Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] ip_addr : pointer to ip string (as returned from mbedos calls) + * + * @return whd_result_t + */ +whd_result_t whd_arp_hostip_list_clear_id_string(whd_interface_t ifp, const char *ip_addr); + +/** Clear all ARP Offload Host IP Identifier List + * + * @param[in] ifp : pointer to handle instance of whd interface + * + * @return whd_result_t + */ +whd_result_t whd_arp_hostip_list_clear(whd_interface_t ifp); + +/** Get ARP Offload Host IP Identifiers from Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] count : Number of array elements in host_ip + * @param[out] host_ipv4_list : Pointer to structure array to store host_ip data + * @param[out] filled : Number of array elements filled by this routine + * + * @return whd_result_t + */ +whd_result_t whd_arp_hostip_list_get(whd_interface_t ifp, uint32_t count, uint32_t *host_ipv4_list, uint32_t *filled); + +/** Clear ARP Offload statistics in Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * + * @return whd_result_t + */ +whd_result_t whd_arp_stats_clear(whd_interface_t ifp); + +/** Get ARP Offload statistics from Device (WLAN) + * + * @param[in] ifp : pointer to handle instance of whd interface + * @param[out] stats : Ptr to store statistics whd_arp_stats_t + * + * @return whd_result_t + */ +whd_result_t whd_arp_stats_get(whd_interface_t ifp, whd_arp_stats_t *stats); + +/** Print ARP Offload statistics + * NOTE: call whd_arp_stats_get(), then print them using this function. + * + * @param[in] arp_stats : Ptr to ARP statistics structure + * @param[in] title : Optional: Title for output (NULL == no title) + * + * @return whd_result_t + */ +whd_result_t whd_arp_stats_print(whd_arp_stats_t *arp_stats, const char *title); + +/** A filter must be added (e.g. created) before it can be enabled. + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] settings : Ptr to filter settings @ref whd_packet_filter_t + * @return whd_result_t + */ +whd_result_t whd_pf_add_packet_filter(whd_interface_t ifp, const whd_packet_filter_t *settings); + +/** Remove a previously added filter. + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] filter_id : filter to remove + * @return whd_result_t + */ +whd_result_t whd_pf_remove_packet_filter(whd_interface_t ifp, uint8_t filter_id); + +/** After a filter has been added it can be enabled or disabled as needed. + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] filter_id : filter to enable + * @return whd_result_t + */ +whd_result_t whd_pf_enable_packet_filter(whd_interface_t ifp, uint8_t filter_id); + +/** After a filter has been added it can be enabled or disabled as needed. + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] filter_id : filter to disable + * @return whd_result_t + */ +whd_result_t whd_pf_disable_packet_filter(whd_interface_t ifp, uint8_t filter_id); + +/** After a filter has been added it can be enabled or disabled as needed. + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] filter_id : filter to disable/enable + * @param[in] enable : Enable/Disable Flag + * @return whd_result_t + */ +whd_result_t whd_wifi_toggle_packet_filter(whd_interface_t ifp, uint8_t filter_id, whd_bool_t enable); + +/** Filters are implemented in WLAN subsystem as a bit pattern and matching bit mask that + * are applied to incoming packets. This API retrieves the pattern and mask. + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] filter_id : which filter to retrieve + * @param[in] max_size : size of both mask and pattern buffers + * @param[out] mask : mask for this filter + * @param[out] pattern : pattern for this filter + * @param[out] size_out : length of both mask and pattern + * @return whd_result_t + */ +whd_result_t whd_pf_get_packet_filter_mask_and_pattern(whd_interface_t ifp, uint8_t filter_id, uint32_t max_size, + uint8_t *mask, + uint8_t *pattern, uint32_t *size_out); + +/** Clear the packet filter stats associated with a filter id + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] filter_id : which filter + * @return whd_result_t + */ +whd_result_t whd_wifi_clear_packet_filter_stats(whd_interface_t ifp, uint32_t filter_id); + +/** Return the stats associated with a filter + * @param[in] ifp : pointer to handle instance of whd interface + * @param[in] filter_id : which filter + * @param[out] stats : Ptr to store statistics wl_pkt_filter_stats_t + * @return whd_result_t + */ +whd_result_t whd_pf_get_packet_filter_stats(whd_interface_t ifp, uint8_t filter_id, whd_pkt_filter_stats_t *stats); + +/** Set/Get TKO retry & interval parameters + * @param[in] ifp : Pointer to handle instance of whd interface + * @param[in] whd_tko_retry : whd retry & interval parameters structure + * @param[in] set : Set(1)/Get(0) Flag + * @return whd_result_t + */ +whd_result_t whd_tko_param(whd_interface_t ifp, whd_tko_retry_t *whd_tko_retry, uint8_t set); + +/** Return the tko status for all indexes + * @param[in] ifp : Pointer to handle instance of whd interface + * @param[out] tko_status : Ptr to store tko_status + * @return whd_result_t + */ +whd_result_t whd_tko_get_status(whd_interface_t ifp, whd_tko_status_t *tko_status); + +/** Return the stats associated with a filter + * @param[in] ifp : Pointer to handle instance of whd interface + * @param[out] max : returns Max TCP connections supported by WLAN Firmware + * @return whd_result_t + */ +whd_result_t whd_tko_max_assoc(whd_interface_t ifp, uint8_t *max); + +/** Return the stats associated with a filter + * @param[in] ifp : Pointer to handle instance of whd interface + * @param[in] index : index for TCP offload connection + * @param[out] whd_connect : tko_connect structure buffer from Firmware + * @param[in] buflen : Buffer given for tko_connect + * @return whd_result_t + */ +whd_result_t whd_tko_get_FW_connect(whd_interface_t ifp, uint8_t index, whd_tko_connect_t *whd_connect, + uint16_t buflen); + +/** Return the stats associated with a filter + * @param[in] ifp : Pointer to handle instance of whd interface + * @param[in] enable : Enable/Disable TCP Keepalive offload + * @return whd_result_t + */ +whd_result_t whd_tko_toggle(whd_interface_t ifp, whd_bool_t enable); + + +/* @} */ + +/** @addtogroup wifiioctl WHD Wi-Fi IOCTL Set/Get API + * @ingroup wifi + * Set and get IOCTL values + * @{ + */ +/** Sends an IOCTL command - CDC_SET IOCTL value + * + * @param ifp Pointer to handle instance of whd interface + * @param ioctl CDC_SET - To set the I/O control + * @param value Data value to be sent + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_ioctl_value(whd_interface_t ifp, uint32_t ioctl, uint32_t value); + +/** Sends an IOCTL command - CDC_GET IOCTL value + * + * @param ifp Pointer to handle instance of whd interface + * @param ioctl CDC_GET - To get the I/O control + * @param value Pointer to receive the data value + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_ioctl_value(whd_interface_t ifp, uint32_t ioctl, uint32_t *value); + +/** Sends an IOCTL command - CDC_SET IOCTL buffer + * + * @param ifp Pointer to handle instance of whd interface + * @param ioctl CDC_SET - To set the I/O control + * @param buffer Handle for a packet buffer containing the data value to be sent. + * @param buffer_length Length of buffer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_ioctl_buffer(whd_interface_t ifp, uint32_t ioctl, void *buffer, uint16_t buffer_length); + +/** Sends an IOCTL command - CDC_GET IOCTL buffer + * + * @param ifp Pointer to handle instance of whd interface + * @param ioctl CDC_GET - To get the I/O control + * @param out_buffer Pointer to receive the handle for the packet buffer containing the response data value received + * @param out_length Length of out_buffer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_ioctl_buffer(whd_interface_t ifp, uint32_t ioctl, uint8_t *out_buffer, + uint16_t out_length); + +/** Sends an IOVAR command + * + * @param ifp Pointer to handle instance of whd interface + * @param iovar_name SDPCM_GET - To get the I/O Variable + * @param param Paramater to be passed for the IOVAR + * @param paramlen Paramter length + * @param out_buffer Pointer to receive the handle for the packet buffer containing the response data value received + * @param out_length Length of out_buffer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_iovar_buffer_with_param(whd_interface_t ifp, const char *iovar_name, void *param, + uint32_t paramlen, uint8_t *out_buffer, uint32_t out_length); + +/* @} */ + +/** @addtogroup dbg WHD Wi-Fi Debug API + * @ingroup wifi + * WHD APIs which allows debugging like, printing whd log information, getting whd stats, etc. + * @{ + */ +/** Retrieves the WLAN firmware version + * + * @param ifp Pointer to handle instance of whd interface + * @param version Pointer to a buffer that version information will be written to + * @param length Length of the buffer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_wifi_version(whd_interface_t ifp, char *version, uint8_t length); + +/** Retrieves the WLAN CLM version + * + * @param ifp Pointer to handle instance of whd interface + * @param version Pointer to a buffer that version information will be written to + * @param length Length of the buffer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_clm_version(whd_interface_t ifp, char *version, uint8_t length); + +/** To print whd log information + * + * @param whd_drv Pointer to handle instance of the driver + * @param buffer Buffer to store read log results + * @param buffer_size Variable to store size of the buffer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_read_wlan_log(whd_driver_t whd_drv, char *buffer, uint32_t buffer_size); + +/** To print whd log information + * + * @param whd_drv Pointer to handle instance of the driver + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_print_whd_log(whd_driver_t whd_drv); + +/** Retrieves the ifidx from interface pointer. + * ifidx is a unique value and be used to identify a instance of tcp/ip stack + * + * @param ifp Pointer to the whd_interface_t + * @param ifidx Pointer to ifidx + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_network_get_ifidx_from_ifp(whd_interface_t ifp, uint8_t *ifidx); + +/** Retrieves the bsscfgidx from interface pointer. + * + * Can be used to send IOCTL with requires bsscfgidx + * + * @param ifp Pointer to handle instance of whd interface + * @param bsscfgidx Pointer to bsscfgidx + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_network_get_bsscfgidx_from_ifp(whd_interface_t ifp, uint8_t *bsscfgidx); + + +/** Retrives the bss info + * + * @param ifp Pointer to handle instance of whd interface + * @param bi A pointer to the structure wl_bss_info_t + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_bss_info(whd_interface_t ifp, wl_bss_info_t *bi); + +/** Prints WHD stats + * + * @param whd_drv Pointer to handle instance of the driver + * @param reset_after_print Bool variable to decide if whd_stats to be reset + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_print_stats(whd_driver_t whd_drv, whd_bool_t reset_after_print); + +/* @} */ +/* @} */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef INCLUDED_WHD_WIFI_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/43012C0-mfgtest_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/43012C0-mfgtest_clm_blob.c new file mode 100644 index 00000000..06cfa3b6 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/43012C0-mfgtest_clm_blob.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__( (used) ) +#endif +const unsigned char wifi_mfg_firmware_clm_blob_data[7697] = +{ + #include +}; +const resource_hnd_t wifi_mfg_firmware_clm_blob = +{ RESOURCE_IN_MEMORY, 7697, {.mem = { (const char *)wifi_mfg_firmware_clm_blob_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/43012C0_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/43012C0_clm_blob.c new file mode 100644 index 00000000..794b958a --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/43012C0_clm_blob.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__( (used) ) +#endif +const unsigned char wifi_firmware_clm_blob_data[7697] = +{ + #include +}; +const resource_hnd_t wifi_firmware_clm_blob = +{ RESOURCE_IN_MEMORY, 7697, {.mem = { (const char *)wifi_firmware_clm_blob_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/clm_resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/clm_resources.h new file mode 100644 index 00000000..41577aa2 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/clm_resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_CLM_RESOURCES_H_ +#define INCLUDED_CLM_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_clm_blob; +extern const unsigned char wifi_firmware_clm_blob_data[7697]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_clm_blob; +extern const unsigned char wifi_mfg_firmware_clm_blob_data[7697]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_CLM_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/43438A1-mfgtest_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/43438A1-mfgtest_clm_blob.c new file mode 100644 index 00000000..003f6673 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/43438A1-mfgtest_clm_blob.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__( (used) ) +#endif +const unsigned char wifi_mfg_firmware_clm_blob_data[7222] = +{ + #include +}; +const resource_hnd_t wifi_mfg_firmware_clm_blob = +{ RESOURCE_IN_MEMORY, 7222, {.mem = { (const char *)wifi_mfg_firmware_clm_blob_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/43438A1_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/43438A1_clm_blob.c new file mode 100644 index 00000000..1c92980b --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/43438A1_clm_blob.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__( (used) ) +#endif +const unsigned char wifi_firmware_clm_blob_data[7222] = +{ + #include +}; +const resource_hnd_t wifi_firmware_clm_blob = +{ RESOURCE_IN_MEMORY, 7222, {.mem = { (const char *)wifi_firmware_clm_blob_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/clm_resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/clm_resources.h new file mode 100644 index 00000000..4d4ee119 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/clm_resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_CLM_RESOURCES_H_ +#define INCLUDED_CLM_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_clm_blob; +extern const unsigned char wifi_firmware_clm_blob_data[7222]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_clm_blob; +extern const unsigned char wifi_mfg_firmware_clm_blob_data[7222]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_CLM_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/43439A0-mfgtest_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/43439A0-mfgtest_clm_blob.c new file mode 100644 index 00000000..72886d83 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/43439A0-mfgtest_clm_blob.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_mfg_firmware_clm_blob_data[4752] = { + #include +}; +const resource_hnd_t wifi_mfg_firmware_clm_blob = { RESOURCE_IN_MEMORY, 4752, {.mem = { (const char *) wifi_mfg_firmware_clm_blob_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/43439A0_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/43439A0_clm_blob.c new file mode 100644 index 00000000..23e43739 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/43439A0_clm_blob.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_firmware_clm_blob_data[4752] = { + #include +}; +const resource_hnd_t wifi_firmware_clm_blob = { RESOURCE_IN_MEMORY, 4752, {.mem = { (const char *) wifi_firmware_clm_blob_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/clm_resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/clm_resources.h new file mode 100644 index 00000000..11778158 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/clm_resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_CLM_RESOURCES_H_ +#define INCLUDED_CLM_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_clm_blob; +extern const unsigned char wifi_firmware_clm_blob_data[4752]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_clm_blob; +extern const unsigned char wifi_mfg_firmware_clm_blob_data[4752]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_CLM_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/4343WA1-mfgtest_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/4343WA1-mfgtest_clm_blob.c new file mode 100644 index 00000000..003f6673 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/4343WA1-mfgtest_clm_blob.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__( (used) ) +#endif +const unsigned char wifi_mfg_firmware_clm_blob_data[7222] = +{ + #include +}; +const resource_hnd_t wifi_mfg_firmware_clm_blob = +{ RESOURCE_IN_MEMORY, 7222, {.mem = { (const char *)wifi_mfg_firmware_clm_blob_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/4343WA1_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/4343WA1_clm_blob.c new file mode 100644 index 00000000..1c92980b --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/4343WA1_clm_blob.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__( (used) ) +#endif +const unsigned char wifi_firmware_clm_blob_data[7222] = +{ + #include +}; +const resource_hnd_t wifi_firmware_clm_blob = +{ RESOURCE_IN_MEMORY, 7222, {.mem = { (const char *)wifi_firmware_clm_blob_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/clm_resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/clm_resources.h new file mode 100644 index 00000000..4d4ee119 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/clm_resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_CLM_RESOURCES_H_ +#define INCLUDED_CLM_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_clm_blob; +extern const unsigned char wifi_firmware_clm_blob_data[7222]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_clm_blob; +extern const unsigned char wifi_mfg_firmware_clm_blob_data[7222]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_CLM_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/4373A0-mfgtest_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/4373A0-mfgtest_clm_blob.c new file mode 100644 index 00000000..7c59243b --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/4373A0-mfgtest_clm_blob.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__( (used) ) +#endif +const unsigned char wifi_mfg_firmware_clm_blob_data[7341] = +{ + #include +}; +const resource_hnd_t wifi_mfg_firmware_clm_blob = +{ RESOURCE_IN_MEMORY, 7341, {.mem = { (const char *)wifi_mfg_firmware_clm_blob_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/4373A0_clm_blob.c b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/4373A0_clm_blob.c new file mode 100644 index 00000000..d9df0a7a --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/4373A0_clm_blob.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__( (used) ) +#endif +const unsigned char wifi_firmware_clm_blob_data[7341] = +{ + #include +}; +const resource_hnd_t wifi_firmware_clm_blob = +{ RESOURCE_IN_MEMORY, 7341, {.mem = { (const char *)wifi_firmware_clm_blob_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/clm_resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/clm_resources.h new file mode 100644 index 00000000..4bc9217b --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/clm_resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_CLM_RESOURCES_H_ +#define INCLUDED_CLM_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_clm_blob; +extern const unsigned char wifi_firmware_clm_blob_data[7341]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_clm_blob; +extern const unsigned char wifi_mfg_firmware_clm_blob_data[7341]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_CLM_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/43012C0-mfgtest_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/43012C0-mfgtest_bin.c new file mode 100644 index 00000000..6142596f --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/43012C0-mfgtest_bin.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_mfg_firmware_image_data[498728] = { + #include +}; +const resource_hnd_t wifi_mfg_firmware_image = { RESOURCE_IN_MEMORY, 498728, {.mem = { (const char *) wifi_mfg_firmware_image_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/43012C0_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/43012C0_bin.c new file mode 100644 index 00000000..e3be96c3 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/43012C0_bin.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_firmware_image_data[436005] = { + #include +}; +const resource_hnd_t wifi_firmware_image = { RESOURCE_IN_MEMORY, 463571, {.mem = { (const char *) wifi_firmware_image_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/resources.h new file mode 100644 index 00000000..bd284a39 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_RESOURCES_H_ +#define INCLUDED_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_image; +extern const unsigned char wifi_firmware_image_data[436005]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_image; +extern const unsigned char wifi_mfg_firmware_image_data[498728]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/43438A1-mfgtest_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/43438A1-mfgtest_bin.c new file mode 100644 index 00000000..2cacd2f7 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/43438A1-mfgtest_bin.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_mfg_firmware_image_data[396322] = { + #include +}; +const resource_hnd_t wifi_mfg_firmware_image = { RESOURCE_IN_MEMORY, 396322, {.mem = { (const char *) wifi_mfg_firmware_image_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/43438A1_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/43438A1_bin.c new file mode 100644 index 00000000..d100f150 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/43438A1_bin.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_firmware_image_data[419799] = { + #include +}; +const resource_hnd_t wifi_firmware_image = { RESOURCE_IN_MEMORY, 419799, {.mem = { (const char *) wifi_firmware_image_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/resources.h new file mode 100644 index 00000000..66342b26 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_RESOURCES_H_ +#define INCLUDED_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_image; +extern const unsigned char wifi_firmware_image_data[419799]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_image; +extern const unsigned char wifi_mfg_firmware_image_data[396322]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/43439a0-mfgtest_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/43439a0-mfgtest_bin.c new file mode 100644 index 00000000..a7dbf410 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/43439a0-mfgtest_bin.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_mfg_firmware_image_data[223628] = { + #include +}; +const resource_hnd_t wifi_mfg_firmware_image = { RESOURCE_IN_MEMORY, 223628, {.mem = { (const char *) wifi_mfg_firmware_image_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/43439a0_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/43439a0_bin.c new file mode 100644 index 00000000..f225d806 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/43439a0_bin.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_firmware_image_data[229074] = { + #include +}; +const resource_hnd_t wifi_firmware_image = { RESOURCE_IN_MEMORY, 229074, {.mem = { (const char *) wifi_firmware_image_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/resources.h new file mode 100644 index 00000000..8921bffc --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_RESOURCES_H_ +#define INCLUDED_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_image; +extern const unsigned char wifi_firmware_image_data[229074]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_image; +extern const unsigned char wifi_mfg_firmware_image_data[223628]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/4343WA1-mfgtest_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/4343WA1-mfgtest_bin.c new file mode 100644 index 00000000..8f83d51f --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/4343WA1-mfgtest_bin.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_mfg_firmware_image_data[397936] = { + #include +}; +const resource_hnd_t wifi_mfg_firmware_image = { RESOURCE_IN_MEMORY, 397936, {.mem = { (const char *) wifi_mfg_firmware_image_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ + diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/4343WA1_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/4343WA1_bin.c new file mode 100644 index 00000000..a035025a --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/4343WA1_bin.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_firmware_image_data[421421] = { + #include +}; +const resource_hnd_t wifi_firmware_image = { RESOURCE_IN_MEMORY, 421421, {.mem = { (const char *) wifi_firmware_image_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/resources.h new file mode 100644 index 00000000..6ecb6158 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_RESOURCES_H_ +#define INCLUDED_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_image; +extern const unsigned char wifi_firmware_image_data[421421]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_image; +extern const unsigned char wifi_mfg_firmware_image_data[397936]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/4373A0-mfgtest_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/4373A0-mfgtest_bin.c new file mode 100644 index 00000000..0b2d2877 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/4373A0-mfgtest_bin.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifdef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_mfg_firmware_image_data[580722] = { + #include +}; +const resource_hnd_t wifi_mfg_firmware_image = { RESOURCE_IN_MEMORY, 580722, {.mem = { (const char *) wifi_mfg_firmware_image_data }}}; +#endif /* WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/4373A0_bin.c b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/4373A0_bin.c new file mode 100644 index 00000000..a4c0f9f2 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/4373A0_bin.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +#if defined(CY_STORAGE_WIFI_DATA) +CY_SECTION_WHD(CY_STORAGE_WIFI_DATA) __attribute__((used)) +#endif +const unsigned char wifi_firmware_image_data[589547] = { + #include +}; +const resource_hnd_t wifi_firmware_image = { RESOURCE_IN_MEMORY, 589547, {.mem = { (const char *) wifi_firmware_image_data }}}; +#endif /* !WLAN_MFG_FIRMWARE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/resources.h b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/resources.h new file mode 100644 index 00000000..e1c49795 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/resources.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Automatically generated file - this comment ensures resources.h file creation */ +/* Auto-generated header file. Do not edit */ +#ifndef INCLUDED_RESOURCES_H_ +#define INCLUDED_RESOURCES_H_ +#include "wiced_resource.h" + +#ifndef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_firmware_image; +extern const unsigned char wifi_firmware_image_data[589547]; +#endif /* !WLAN_MFG_FIRMWARE */ +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_image; +extern const unsigned char wifi_mfg_firmware_image_data[580722]; +#endif /* WLAN_MFG_FIRMWARE */ + +#endif /* ifndef INCLUDED_RESOURCES_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43012/COMPONENT_MURATA-1LV/wifi_nvram_image.h b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43012/COMPONENT_MURATA-1LV/wifi_nvram_image.h new file mode 100644 index 00000000..36e46cdb --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43012/COMPONENT_MURATA-1LV/wifi_nvram_image.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_NVRAM_IMAGE_H_ +#define INCLUDED_NVRAM_IMAGE_H_ + +#include +#include +#include "generated_mac_address.txt" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Character array of NVRAM image + * Generated from cyw9cy8ckit_062S2_43012_P100_723349.txt + */ + +static const char wifi_nvram_image[] = + "NVRAMRev=$Rev:723349$" "\x00" + "sromrev=11" "\x00" + "cckdigfilttype=4" "\x00" + "cckpwroffset0=2" "\x00" + "bphyscale=0x20" "\x00" + "boardflags3=0x40000100" "\x00" + "vendid=0x14e4" "\x00" + "devid=0xA804" "\x00" + "manfid=0x2d0" "\x00" + "prodid=0x052e" "\x00" + NVRAM_GENERATED_MAC_ADDRESS "\x00" + "mac_clkgating=1" "\x00" + "nocrc=1" "\x00" + "boardtype=0x0869" "\x00" + "boardrev=0x1102" "\x00" + "xtalfreq=37400" "\x00" + "boardflags2=0xc0000000" "\x00" + "boardflags=0x00000001" "\x00" + "etmode=0x11" "\x00" + "extpagain2g=2" "\x00" + "extpagain5g=2" "\x00" + "ccode=0" "\x00" + "regrev=0" "\x00" + "antswitch=0" "\x00" + "rxgains2gelnagaina0=0" "\x00" + "rxgains2gtrisoa0=15" "\x00" + "rxgains2gtrelnabypa0=0" "\x00" + "rxgains5gelnagaina0=0" "\x00" + "rxgains5gtrisoa0=9" "\x00" + "rxgains5gtrelnabypa0=0" "\x00" + "pdgain5g=0" "\x00" + "pdgain2g=0" "\x00" + "tworangetssi2g=0" "\x00" + "tworangetssi5g=0" "\x00" + "rxchain=1" "\x00" + "txchain=1" "\x00" + "aa2g=1" "\x00" + "aa5g=1" "\x00" + "tssipos5g=0" "\x00" + "tssipos2g=0" "\x00" + "femctrl=17" "\x00" + "subband5gver=4" "\x00" + "pa2ga0=-108,6062,-661" "\x00" + "pa5ga0=-82,6252,-698,-14,6722,-697,-92,6084,-710,-88,6465,-755" "\x00" + "pdoffset40ma0=0" "\x00" + "pdoffset80ma0=0" "\x00" + "lowpowerrange2g=0" "\x00" + "lowpowerrange5g=0" "\x00" + "ed_thresh2g=-63" "\x00" + "ed_thresh5g=-63" "\x00" + "swctrlmap_2g=0x10101010,0x20202020,0x10101010,0x442020,0x3ff" "\x00" + "swctrlmapext_2g=0x01000100,0x01000100,0x01000100,0x000000,0x301" "\x00" + "swctrlmap_5g=0x80808080,0x00000000,0x80808080,0x442020,0x381" "\x00" + "swctrlmapext_5g=0x01000100,0x01000100,0x00000000,0x000000,0x303" "\x00" + "ulpnap=0" "\x00" + "ulpadc=1" "\x00" + "ssagc_en=0" "\x00" + "ds1_nap=0" "\x00" + "spurcan_ch_list_MHz=2422,2427,2432,2437,2462,2467,2472" "\x00" + "spurcan_sp_freq_KHz=9000,4000,-1000,-6000,6400,1400,-3600" "\x00" + "spurcan_NumSpur=7" "\x00" + "epacal2g=0" "\x00" + "epacal5g=0" "\x00" + "papdcck=0" "\x00" + "epacal2g_mask=0x3fff" "\x00" + "maxp2ga0=74" "\x00" + "ofdmlrbw202gpo=0x0020" "\x00" + "dot11agofdmhrbw202gpo=0x6442" "\x00" + "mcsbw202gpo=0xCC864420" "\x00" + "maxp5ga0=70,70,70,70" "\x00" + "mcsbw205glpo=0xCC864220" "\x00" + "mcsbw205gmpo=0xCC864220" "\x00" + "mcsbw205ghpo=0xCC864220" "\x00" + "femctrlwar=0" "\x00" + "use5gpllfor2g=1" "\x00" + "pt5db_gaintbl=0" "\x00" + "muxenab=0x01" "\x00" + "txwbpapden=1" "\x00" + "wb_rxattn=0x0303" "\x00" + "wb_txattn=0x0203" "\x00" + "wb_papdcalidx=0x0808" "\x00" + "wb_papdcalidx_5g=0x00101010" "\x00" + "wb_eps_offset=0x01ba01a8" "\x00" + "wb_eps_offset_5g=0x01ba01bc" "\x00" + "wb_bbmult=0x2040" "\x00" + "wb_bbmult_5g=0x00303030" "\x00" + "wb_calref_db=0x1c2e" "\x00" + "wb_tia_gain_mode=0x0606" "\x00" + "wb_txbuf_offset=0x1e1e" "\x00" + "wb_frac_del=0x6991" "\x00" + "wb_g_frac_bits=0xab" "\x00" + "nb_rxattn=0x0404" "\x00" + "nb_txattn=0x0404" "\x00" + "nb_papdcalidx=0x1414" "\x00" + "nb_eps_offset=0x01d701d7" "\x00" + "nb_bbmult=0x5A5A" "\x00" + "nb_tia_gain_mode=0x0000" "\x00" + "AvVmid_c0=6,100,7,70,7,70,7,70,7,70" "\x00" + "tssisleep_en=0x5" "\x00" + "lpflags=0x0" "\x00" + "lpo_select=4" "\x00" + "paprrmcsgamma2g=450,500,550,600,675,950,950,950,950,950,950,950" "\x00" + "paprrmcsgamma5g20=450,500,550,600,800,950,1100,1100,1100,1100,1100,1100""\x00" + "swdiv_en=0" "\x00" + "swdiv_gpio=0" "\x00" + "swdiv_swctrl_en=2" "\x00" + "swdiv_swctrl_ant0=0" "\x00" + "swdiv_swctrl_ant1=1" "\x00" + "swdiv_antmap2g_main=1" "\x00" + "swdiv_antmap5g_main=1" "\x00" + "swdiv_snrlim=10000" "\x00" + "swdiv_thresh=3000" "\x00" + "swdiv_snrthresh=24" "\x00" + "lhlgpio_cfg=0x00000020,0x00000000" "\x00" + "\x00\x00"; +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#else /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ + +#error Wi-Fi NVRAM image included twice + +#endif /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43439/COMPONENT_MURATA-1YN/wifi_nvram_image.h b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43439/COMPONENT_MURATA-1YN/wifi_nvram_image.h new file mode 100644 index 00000000..9fed4438 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43439/COMPONENT_MURATA-1YN/wifi_nvram_image.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_NVRAM_IMAGE_H_ +#define INCLUDED_NVRAM_IMAGE_H_ + +#include +#include +#include "generated_mac_address.txt" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Character array of NVRAM image + * Generated from brcmfmac43439-sdio.txt + */ + +static const char wifi_nvram_image[] = + "NVRAMRev=$Rev: 726808 $" "\x00" + "manfid=0x2d0" "\x00" + "prodid=0x0727" "\x00" + "vendid=0x14e4" "\x00" + "devid=0x43e2" "\x00" + "boardtype=0x0887" "\x00" + "boardrev=0x1101" "\x00" + "boardnum=22" "\x00" + NVRAM_GENERATED_MAC_ADDRESS "\x00" + "sromrev=11" "\x00" + "boardflags=0x00404001" "\x00" + "boardflags3=0x08000000" "\x00" + "xtalfreq=37400" "\x00" + "nocrc=1" "\x00" + "ag0=255" "\x00" + "aa2g=1" "\x00" + "ccode=ALL" "\x00" + "pa0itssit=0x20" "\x00" + "extpagain2g=0" "\x00" + "pa2ga0=-168,6777,-789" "\x00" + "AvVmid_c0=0x0,0xc8" "\x00" + "cckpwroffset0=5" "\x00" + "maxp2ga0=84" "\x00" + "txpwrbckof=6" "\x00" + "cckbw202gpo=0" "\x00" + "legofdmbw202gpo=0x66111111" "\x00" + "mcsbw202gpo=0x77711111" "\x00" + "propbw202gpo=0xdd" "\x00" + "ofdmdigfilttype=18" "\x00" + "ofdmdigfilttypebe=18" "\x00" + "papdmode=1" "\x00" + "papdvalidtest=1" "\x00" + "pacalidx2g=45" "\x00" + "papdepsoffset=-30" "\x00" + "papdendidx=58" "\x00" + "ltecxmux=0" "\x00" + "ltecxpadnum=0x0102" "\x00" + "ltecxfnsel=0x44" "\x00" + "ltecxgcigpio=0x01" "\x00" + "il0macaddr=00:90:4c:c5:12:38" "\x00" + "wl0id=0x431b" "\x00" + "deadman_to=0xffffffff" "\x00" + "muxenab=0x11" "\x00" + "spurconfig=0x3" "\x00" + "glitch_based_crsmin=1" "\x00" + "btc_mode=1" "\x00" + "bt_default_ant=0" "\x00" + "\x00\x00"; +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#else /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ + +#error Wi-Fi NVRAM image included twice + +#endif /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43439/COMPONENT_STERLING-LWBplus/wifi_nvram_image.h b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43439/COMPONENT_STERLING-LWBplus/wifi_nvram_image.h new file mode 100644 index 00000000..4fbb2413 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43439/COMPONENT_STERLING-LWBplus/wifi_nvram_image.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_NVRAM_IMAGE_H_ +#define INCLUDED_NVRAM_IMAGE_H_ + +#include +#include +#include "generated_mac_address.txt" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Character array of NVRAM image + * Generated from brcmfmac43439-sdio.txt + */ + +static const char wifi_nvram_image[] = + "NVRAMRev=$Rev$" "\x00" + "manfid=0x2d0" "\x00" + "prodid=0x0727" "\x00" + "vendid=0x14e4" "\x00" + "devid=0x43e2" "\x00" + "boardtype=0x0887" "\x00" + "boardrev=0x1102" "\x00" + "boardnum=22" "\x00" + NVRAM_GENERATED_MAC_ADDRESS "\x00" + "sromrev=11" "\x00" + "boardflags=0x00404001" "\x00" + "boardflags3=0x08000000" "\x00" + "xtalfreq=26000" "\x00" + "nocrc=1" "\x00" + "ag0=255" "\x00" + "aa2g=1" "\x00" + "rssicorrnorm=0" "\x00" + "pa0itssit=0x20" "\x00" + "extpagain2g=0" "\x00" + "pa2ga0=-155,6912,-779" "\x00" + "AvVmid_c0=0x0,0xc8" "\x00" + "cckpwroffset0=5" "\x00" + "maxp2ga0=78" "\x00" + "txpwrbckof=6" "\x00" + "cckbw202gpo=0" "\x00" + "legofdmbw202gpo=0x40000000" "\x00" + "mcsbw202gpo=0x60000000" "\x00" + "propbw202gpo=0xdd" "\x00" + "ofdmdigfilttype=18" "\x00" + "ofdmdigfilttypebe=18" "\x00" + "papdmode=1" "\x00" + "papdvalidtest=1" "\x00" + "pacalidx2g=45" "\x00" + "papdepsoffset=-30" "\x00" + "papdendidx=58" "\x00" + "il0macaddr=00:90:4c:c5:12:38" "\x00" + "wl0id=0x431b" "\x00" + "deadman_to=0xffffffff" "\x00" + "muxenab=0x1" "\x00" + "spurconfig=0x3" "\x00" + "glitch_based_crsmin=1" "\x00" + "btc_mode=0" "\x00" + "bt_default_ant=0" "\x00" + "edonthd20l=-72" "\x00" + "edoffthd20ul=-78" "\x00" + "\x00\x00"; +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#else /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ + +#error Wi-Fi NVRAM image included twice + +#endif /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_4343W/COMPONENT_MURATA-1DX/wifi_nvram_image.h b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_4343W/COMPONENT_MURATA-1DX/wifi_nvram_image.h new file mode 100644 index 00000000..27fb6daa --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_4343W/COMPONENT_MURATA-1DX/wifi_nvram_image.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_NVRAM_IMAGE_H_ +#define INCLUDED_NVRAM_IMAGE_H_ + +#include +#include +#include "generated_mac_address.txt" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Character array of NVRAM image + * Generated from cyw94343cy8cmod-062-4343w.txt + */ + +static const char wifi_nvram_image[] = + "NVRAMRev=$Rev: 723141 $" "\x00" + "manfid=0x2d0" "\x00" + "prodid=0x086d" "\x00" + "vendid=0x14e4" "\x00" + "devid=0x43e2" "\x00" + "boardtype=0x086d" "\x00" + "boardrev=0x1101" "\x00" + "boardnum=22" "\x00" + NVRAM_GENERATED_MAC_ADDRESS "\x00" + "sromrev=11" "\x00" + "boardflags=0x00404201" "\x00" + "boardflags3=0x08000000" "\x00" + "xtalfreq=37400" "\x00" + "nocrc=1" "\x00" + "ag0=255" "\x00" + "aa2g=1" "\x00" + "ccode=ALL" "\x00" + "pa0itssit=0x20" "\x00" + "extpagain2g=0" "\x00" + "pa2ga0=-168,6905,-799" "\x00" + "AvVmid_c0=0x0,0xc8" "\x00" + "AvVmidIQcal=0x2,0xa8" "\x00" + "cckpwroffset0=5" "\x00" + "maxp2ga0=84" "\x00" + "txpwrbckof=6" "\x00" + "cckbw202gpo=0" "\x00" + "legofdmbw202gpo=0x66111111" "\x00" + "mcsbw202gpo=0x77711111" "\x00" + "propbw202gpo=0xdd" "\x00" + "ofdmdigfilttype=18" "\x00" + "ofdmdigfilttypebe=18" "\x00" + "papdmode=1" "\x00" + "papdvalidtest=1" "\x00" + "pacalidx2g=32" "\x00" + "papdepsoffset=-36" "\x00" + "papdendidx=61" "\x00" + "wl0id=0x431b" "\x00" + "deadman_to=0xffffffff" "\x00" + "muxenab=0x11" "\x00" + "spurconfig=0x3 " "\x00" + "\x00\x00"; +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#else /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ + +#error Wi-Fi NVRAM image included twice + +#endif /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/wifi_nvram_image.h b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/wifi_nvram_image.h new file mode 100644 index 00000000..d68c3bbe --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/wifi_nvram_image.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2019, Cypress Semiconductor Corporation, All Rights Reserved + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_NVRAM_IMAGE_H_ +#define INCLUDED_NVRAM_IMAGE_H_ + +#include +#include +#include "generated_mac_address.txt" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Character array of NVRAM image + * Generated from brcmfmac4373-sa-switch_210528.txt + */ + +static const char wifi_nvram_image[] = + "NVRAMRev=$Rev$" "\x00" + "sromrev=11" "\x00" + "vendid=0x14e4" "\x00" + "devid=0x4418" "\x00" + "manfid=0x2d0" "\x00" + "prodid=0x070f" "\x00" + NVRAM_GENERATED_MAC_ADDRESS "\x00" + "nocrc=1" "\x00" + "boardtype=0x83d" "\x00" + "boardrev=0x1200" "\x00" + "xtalfreq=37400" "\x00" + "boardflags=0x00000001" "\x00" + "boardflags2=0x00800000" "\x00" + "boardflags3=0x48202100" "\x00" + "ext_lpo_margin_frac=0" "\x00" + "tempthresh=105" "\x00" + "temps_hysteresis=20" "\x00" + "temps_txduty_lowlimit=0" "\x00" + "temps_period=1" "\x00" + "phycal_tempdelta=15" "\x00" + "rxgains2gelnagaina0=0" "\x00" + "rxgains2gtrisoa0=0" "\x00" + "rxgains2gtrelnabypa0=0" "\x00" + "rxgains5gelnagaina0=0" "\x00" + "rxgains5gtrisoa0=0" "\x00" + "rxgains5gtrelnabypa0=0" "\x00" + "pdgain5g=3" "\x00" + "pdgain2g=3" "\x00" + "antswitch=0x6" "\x00" + "rxchain=1" "\x00" + "txchain=1" "\x00" + "aa2g=1" "\x00" + "aa5g=1" "\x00" + "tssipos5g=1" "\x00" + "tssipos2g=1" "\x00" + "femctrl=0" "\x00" + "pa2ga0=-214,4762,-584" "\x00" + "pa5ga0=-153,5528,-664,-153,5528,-664,-155,5563,-666,-167,5492,-668" "\x00" + "pdoffsetcckma0=0xf" "\x00" + "pdoffset2g40ma0=0xc" "\x00" + "pdoffset40ma0=0xffff" "\x00" + "pdoffset80ma0=0xeeee" "\x00" + "extpagain5g=2" "\x00" + "extpagain2g=2" "\x00" + "AvVmid_c0=1,130,0,160,0,160,0,160,0,160" "\x00" + "maxp2ga0=72" "\x00" + "maxp5ga0=70,70,70,70" "\x00" + "cckbw202gpo=0x1111" "\x00" + "dot11agofdmhrbw202gpo=0x4422" "\x00" + "ofdmlrbw202gpo=0x0022" "\x00" + "mcsbw202gpo=0xAA666666" "\x00" + "mcsbw402gpo=0xFFEEEEEE" "\x00" + "mcsbw205glpo=0xDD662222" "\x00" + "mcsbw205gmpo=0xDD662222" "\x00" + "mcsbw205ghpo=0xDD662222" "\x00" + "mcsbw405glpo=0xDDAAAAAA" "\x00" + "mcsbw405gmpo=0xDDAAAAAA" "\x00" + "mcsbw405ghpo=0xDDAAAAAA" "\x00" + "mcsbw805glpo=0xEECCCCCC" "\x00" + "mcsbw805gmpo=0xEECCCCCC" "\x00" + "mcsbw805ghpo=0xEECCCCCC" "\x00" + "ppr_hitemp_offset=70,10" "\x00" + "cckbw202gpo_ht=0x0000" "\x00" + "ofdmbw202gpo_ht=0x00000000" "\x00" + "mcsbw202gpo_ht=0x22222222" "\x00" + "ofdmbw205gpo_ht=0x22222222" "\x00" + "mcsbw205gpo_ht=0x22222222" "\x00" + "mcsbw405gpo_ht=0x22222222" "\x00" + "mcsbw805gpo_ht=0x22222222" "\x00" + "swctrlmap_2g=0x00001131,0x00001131,0x00001131,0x313131,0x1ff" "\x00" + "swctrlmap_5g=0x00201131,0x40405171,0x00001131,0x313131,0x1ff" "\x00" + "swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x000" "\x00" + "swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x000" "\x00" + "fem_table_init_val=0x1131,0x1131" "\x00" + "nb_papdcalidx=0x280f" "\x00" + "nb_txattn=0x0303" "\x00" + "nb_rxattn=0x0303" "\x00" + "nb_bbmult=0x3948" "\x00" + "nb_eps_offset=0x01e601ea" "\x00" + "papdmode=1" "\x00" + "rssi_delta_2g_c0=-2,-2,-2,-2" "\x00" + "rssi_delta_5gl_c0=-2,-2,-3,-3,-1,-1" "\x00" + "rssi_delta_5gml_c0=-2,-2,-3,-3,-1,-1" "\x00" + "rssi_delta_5gmu_c0=0,0,-1,-1,0,0" "\x00" + "rssi_delta_5gh_c0=-1,-1,-2,-2,0,0" "\x00" + "ATErcalmode=0" "\x00" + "swdiv_gpio=0" "\x00" + "swdiv_swctrl_en=2" "\x00" + "swdiv_swctrl_ant0=0" "\x00" + "swdiv_swctrl_ant1=1" "\x00" + "swdiv_antmap2g_main=1" "\x00" + "swdiv_antmap5g_main=1" "\x00" + "swdiv_snrlim=290 " "\x00" + "swdiv_thresh=2000 " "\x00" + "swdiv_snrthresh=24 " "\x00" + "swdiv_timeon=10" "\x00" + "swdiv_timeoff=1" "\x00" + "swdiv_snr2g20=232" "\x00" + "swdiv_snr2g40=257" "\x00" + "swdiv_snr5g20=296" "\x00" + "swdiv_snr5g40=312" "\x00" + "swdiv_snr5g80=296" "\x00" + "swdiv_ap_dead_check=1 " "\x00" + "swdiv_ap_div=1 " "\x00" + "idac_main_mode=1" "\x00" + "paldo3p3_voltage=4" "\x00" + "xtal_ldo_ctl=1" "\x00" + "e_grade=1" "\x00" + "fdss_level_2g=4" "\x00" + "fdss_level_5g=4" "\x00" + "fdss_interp_en=1" "\x00" + "muxenab=0x10" "\x00" + "\x00\x00"; +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#else /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ + +#error Wi-Fi NVRAM image included twice + +#endif /* ifndef INCLUDED_NVRAM_IMAGE_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/nvram/README b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/README new file mode 100644 index 00000000..ab8a5442 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/nvram/README @@ -0,0 +1,8 @@ +The following list is for specific board from customer + +COMPONENT_LAIRD_LWB5PM2 folder is for Laird's 4373 board and includes nvram,clm and resources.h. +When using LAIRD_LWB5PM2 component, you need to rename the duplicate files in resources/firmware/COMPONENT_4373, +or adding them into cyignore or adding CY_IGNORE variable as part of the BSP's makefile. +1.4373A0_clm_blob.c +2.resources.h +3.wifi_nvram_image.h diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/resource_imp/whd_resources.c b/wifi-host-driver/WiFi_Host_Driver/resources/resource_imp/whd_resources.c new file mode 100644 index 00000000..554f391d --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/resource_imp/whd_resources.c @@ -0,0 +1,353 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Defines WHD resource functions for BCM943340WCD1 platform + */ +#include "resources.h" +#include "clm_resources.h" +#include "wifi_nvram_image.h" +#include "whd_resource_api.h" +#include "whd_debug.h" +#include "whd.h" + +/****************************************************** +* Macros +******************************************************/ +#define BLOCK_BUFFER_SIZE (1024) + +/****************************************************** +* Constants +******************************************************/ + +#if defined(WHD_DYNAMIC_NVRAM) +#define NVRAM_SIZE dynamic_nvram_size +#define NVRAM_IMAGE_VARIABLE dynamic_nvram_image +#else +#define NVRAM_SIZE sizeof(wifi_nvram_image) +#define NVRAM_IMAGE_VARIABLE wifi_nvram_image +#endif + +/****************************************************** +* Enumerations +******************************************************/ + +/****************************************************** +* Type Definitions +******************************************************/ + +/****************************************************** +* Structures +******************************************************/ + +/****************************************************** +* Static Function Declarations +******************************************************/ +uint32_t host_platform_resource_size(whd_driver_t whd_drv, whd_resource_type_t resource, uint32_t *size_out); +uint32_t host_get_resource_block(whd_driver_t whd_drv, whd_resource_type_t type, + uint32_t blockno, const uint8_t **data, uint32_t *size_out); +uint32_t host_get_resource_no_of_blocks(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *block_count); +uint32_t host_get_resource_block_size(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *size_out); +resource_result_t resource_read(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, uint32_t *size, + void *buffer); +uint32_t host_resource_read(whd_driver_t whd_drv, whd_resource_type_t type, + uint32_t offset, uint32_t size, uint32_t *size_out, void *buffer); +/****************************************************** +* Variable Definitions +******************************************************/ + +#ifdef WLAN_MFG_FIRMWARE +extern const resource_hnd_t wifi_mfg_firmware_image; +extern const resource_hnd_t wifi_mfg_firmware_clm_blob; +#else +extern const resource_hnd_t wifi_firmware_image; +extern const resource_hnd_t wifi_firmware_clm_blob; +#endif + +unsigned char r_buffer[BLOCK_BUFFER_SIZE]; + +#if defined(WHD_DYNAMIC_NVRAM) +uint32_t dynamic_nvram_size = sizeof(wifi_nvram_image); +void *dynamic_nvram_image = &wifi_nvram_image; +#endif + +/****************************************************** +* Function Definitions +******************************************************/ + +resource_result_t resource_read(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, uint32_t *size, + void *buffer) +{ + if (offset > resource->size) + { + return RESOURCE_OFFSET_TOO_BIG; + } + + *size = MIN(maxsize, resource->size - offset); + + if (resource->location == RESOURCE_IN_MEMORY) + { + memcpy(buffer, &resource->val.mem.data[offset], *size); + } +#ifdef USES_RESOURCES_IN_EXTERNAL_STORAGE + else if (resource->location == RESOURCE_IN_EXTERNAL_STORAGE) + { + return platform_read_external_resource(resource, offset, maxsize, size, buffer); + } +#endif +#ifdef USES_RESOURCE_GENERIC_FILESYSTEM + else + { + wiced_file_t file_handle; + uint64_t size64; + uint64_t maxsize64 = maxsize; + if (WICED_SUCCESS != + wiced_filesystem_file_open (&resource_fs_handle, &file_handle, resource->val.fs.filename, + WICED_FILESYSTEM_OPEN_FOR_READ) ) + { + return RESOURCE_FILE_OPEN_FAIL; + } + if (WICED_SUCCESS != wiced_filesystem_file_seek (&file_handle, (offset + resource->val.fs.offset), SEEK_SET) ) + { + return RESOURCE_FILE_SEEK_FAIL; + } + if (WICED_SUCCESS != wiced_filesystem_file_read (&file_handle, buffer, maxsize64, &size64) ) + { + wiced_filesystem_file_close (&file_handle); + return RESOURCE_FILE_READ_FAIL; + } + *size = (uint32_t)size64; + wiced_filesystem_file_close (&file_handle); + } +#else +#ifdef USES_RESOURCE_FILESYSTEM + else + { + wicedfs_file_t file_hnd; + + if (0 != wicedfs_fopen(&resource_fs_handle, &file_hnd, resource->val.fs.filename) ) + { + return RESOURCE_FILE_OPEN_FAIL; + } + + if (0 != wicedfs_fseek(&file_hnd, (long)(offset + resource->val.fs.offset), SEEK_SET) ) + { + wicedfs_fclose(&file_hnd); + return RESOURCE_FILE_SEEK_FAIL; + } + + if (*size != wicedfs_fread(buffer, 1, *size, &file_hnd) ) + { + wicedfs_fclose(&file_hnd); + return RESOURCE_FILE_READ_FAIL; + } + + wicedfs_fclose(&file_hnd); + } +#endif /* ifdef USES_RESOURCE_FILESYSTEM */ +#endif /* USES_RESOURCE_GENERIC_FILESYSTEM */ + return RESOURCE_SUCCESS; +} + +uint32_t host_platform_resource_size(whd_driver_t whd_drv, whd_resource_type_t resource, uint32_t *size_out) +{ + if (resource == WHD_RESOURCE_WLAN_FIRMWARE) + { +#ifdef NO_WIFI_FIRMWARE + whd_assert("Request firmware in a no wifi firmware application", 0 == 1); + *size_out = 0; +#else +#ifdef WIFI_FIRMWARE_IN_MULTI_APP + wiced_app_t wifi_app; + + *size_out = 0; + if (wiced_waf_app_open(DCT_WIFI_FIRMWARE_INDEX, &wifi_app) != WICED_SUCCESS) + { + return ( whd_result_t )RESOURCE_UNSUPPORTED; + } + wiced_waf_app_get_size(&wifi_app, size_out); +#else +#ifdef WLAN_MFG_FIRMWARE + *size_out = (uint32_t)resource_get_size(&wifi_mfg_firmware_image); +#else + *size_out = (uint32_t)resource_get_size(&wifi_firmware_image); +#endif /* WLAN_MFG_FIRMWARE */ +#endif /* WIFI_FIRMWARE_IN_MULTI_APP */ +#endif /* NO_WIFI_FIRMWARE */ + + } + else if (resource == WHD_RESOURCE_WLAN_NVRAM) + { + *size_out = NVRAM_SIZE; + } + else + { +#ifdef WLAN_MFG_FIRMWARE + *size_out = (uint32_t)resource_get_size(&wifi_mfg_firmware_clm_blob); +#else + *size_out = (uint32_t)resource_get_size(&wifi_firmware_clm_blob); +#endif /* WLAN_MFG_FIRMWARE */ + } + return WHD_SUCCESS; +} + +uint32_t host_get_resource_block(whd_driver_t whd_drv, whd_resource_type_t type, + uint32_t blockno, const uint8_t **data, uint32_t *size_out) +{ + uint32_t resource_size; + uint32_t block_size; + uint32_t block_count; + uint32_t read_pos; + uint32_t result; + + host_platform_resource_size(whd_drv, type, &resource_size); + host_get_resource_block_size(whd_drv, type, &block_size); + host_get_resource_no_of_blocks(whd_drv, type, &block_count); + memset(r_buffer, 0, block_size); + read_pos = blockno * block_size; + + if (blockno >= block_count) + { + return WHD_BADARG; + } + + if (type == WHD_RESOURCE_WLAN_FIRMWARE) + { +#ifdef WLAN_MFG_FIRMWARE + result = resource_read( (const resource_hnd_t *)&wifi_mfg_firmware_image, read_pos, block_size, size_out, + r_buffer ); +#else + result = resource_read( (const resource_hnd_t *)&wifi_firmware_image, read_pos, block_size, size_out, + r_buffer ); +#endif /* WLAN_MFG_FIRMWARE */ + if (result != WHD_SUCCESS) + { + return result; + } + *data = (uint8_t *)&r_buffer; + /* + * In case of local buffer read use the following code + * + * *size_out = MIN(BLOCK_BUFFER_SIZE, resource_size - transfer_progress); + * *data = (uint8_t *)wifi_firmware_image_data; + * + * For sending the entire buffer in single block set size out as following + * *size_out = (uint32_t)resource_get_size(&wifi_firmware_image); + */ + } + else if (type == WHD_RESOURCE_WLAN_NVRAM) + { + if (NVRAM_SIZE - read_pos > block_size) + { + *size_out = block_size; + } + else + { + *size_out = NVRAM_SIZE - read_pos; + } + *data = ( (uint8_t *)NVRAM_IMAGE_VARIABLE ) + read_pos; + } + else + { +#ifdef WLAN_MFG_FIRMWARE + result = resource_read( (const resource_hnd_t *)&wifi_mfg_firmware_clm_blob, read_pos, block_size, + size_out, + r_buffer ); +#else + result = resource_read( (const resource_hnd_t *)&wifi_firmware_clm_blob, read_pos, block_size, + size_out, + r_buffer ); +#endif /* WLAN_MFG_FIRMWARE */ + if (result != WHD_SUCCESS) + { + return result; + } + *data = (uint8_t *)&r_buffer; + /* + * In case of local buffer read use the following code + * + * *size_out = MIN(BLOCK_BUFFER_SIZE, resource_size - transfer_progress); + * *data = (uint8_t *)wifi_firmware_clm_blob_image_data; + * + * For sending the entire buffer in single block set size out as following + * *size_out = sizeof(wifi_firmware_clm_blob_image_data); + */ + + } + + return WHD_SUCCESS; +} + +uint32_t host_get_resource_block_size(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *size_out) +{ + *size_out = BLOCK_BUFFER_SIZE; + return WHD_SUCCESS; +} + +uint32_t host_get_resource_no_of_blocks(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *block_count) +{ + uint32_t resource_size; + uint32_t block_size; + + host_platform_resource_size(whd_drv, type, &resource_size); + host_get_resource_block_size(whd_drv, type, &block_size); + *block_count = resource_size / block_size; + if (resource_size % block_size) + *block_count += 1; + + return WHD_SUCCESS; +} + +uint32_t host_resource_read(whd_driver_t whd_drv, whd_resource_type_t type, + uint32_t offset, uint32_t size, uint32_t *size_out, void *buffer) +{ + uint32_t result; + + if (type == WHD_RESOURCE_WLAN_FIRMWARE) + { +#ifdef WLAN_MFG_FIRMWARE + result = resource_read( (const resource_hnd_t *)&wifi_mfg_firmware_image, offset, size, + size_out, buffer ); +#else + result = resource_read( (const resource_hnd_t *)&wifi_firmware_image, offset, size, + size_out, buffer ); +#endif /* WLAN_MFG_FIRMWARE */ + + if (result != WHD_SUCCESS) + return result; + + } + else if (type == WHD_RESOURCE_WLAN_NVRAM) + { + if (size != sizeof(wifi_nvram_image) ) + { + return WHD_BUFFER_SIZE_SET_ERROR; + } + memcpy( (uint8_t *)buffer, wifi_nvram_image, sizeof(wifi_nvram_image) ); + *size_out = sizeof(wifi_nvram_image); + } + return WHD_SUCCESS; +} + +whd_resource_source_t resource_ops = +{ + .whd_resource_size = host_platform_resource_size, + .whd_get_resource_block_size = host_get_resource_block_size, + .whd_get_resource_no_of_blocks = host_get_resource_no_of_blocks, + .whd_get_resource_block = host_get_resource_block, + .whd_resource_read = host_resource_read +}; diff --git a/wifi-host-driver/WiFi_Host_Driver/resources/resource_imp/wiced_resource.h b/wifi-host-driver/WiFi_Host_Driver/resources/resource_imp/wiced_resource.h new file mode 100644 index 00000000..79ae6a4e --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/resources/resource_imp/wiced_resource.h @@ -0,0 +1,228 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * WICED Resource API's + * The Resource Management functions reads resource from a resource location + * and returns the number of bytes from an offset in an caller filled buffer. + * + * Functions to get the resource size and resource data + * + * The Resource could be one of the three locations + * + * - Wiced Filesystem (File System) + * - Internal Memory (Embedded Flash memory) + * - External Storage ( External Flash connected via SPI interface) + * + */ + +#ifndef INCLUDED_RESOURCE_H_ +#define INCLUDED_RESOURCE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/****************************************************** +* Macros +******************************************************/ +#ifndef MIN +#define MIN(x, y) ( (x) < (y) ? (x) : (y) ) +#endif /* ifndef MIN */ + +/* Suppress unused parameter warning */ +#ifndef UNUSED_PARAMETER +#define UNUSED_PARAMETER(x) ( (void)(x) ) +#endif + +#ifndef RESULT_ENUM +#define RESULT_ENUM(prefix, name, value) prefix ## name = (value) +#endif /* ifndef RESULT_ENUM */ + +#if defined(CY_SECTION) +#define CY_SECTION_WHD CY_SECTION +#else +#if !defined(CY_SECTION_WHD) +#if defined(__ARMCC_VERSION) +#define CY_SECTION_WHD(name) __attribute__ ( (section(name) ) ) +#elif defined (__GNUC__) +#if defined (__clang__) +#define CY_SECTION_WHD(name) __attribute__ ( (section("__DATA, "name) ) ) +#else +#define CY_SECTION_WHD(name) __attribute__ ( (section(name) ) ) +#endif +#elif defined (__ICCARM__) +#define CY_PRAGMA_WHD(x) _Pragma(#x) +#define CY_SECTION_WHD(name) CY_PRAGMA_WHD(location = name) +#else +#error "An unsupported toolchain" +#endif /* (__ARMCC_VERSION) */ +#endif /* !defined(CY_SECTION_WHD) */ +#endif /* defined(CY_SECTION) */ + +/* These Enum result values are for Resource errors + * Values: 4000 - 4999 + */ +#define RESOURCE_RESULT_LIST(prefix) \ + RESULT_ENUM(prefix, SUCCESS, 0), /**< Success */ \ + RESULT_ENUM(prefix, UNSUPPORTED, 7), /**< Unsupported function */ \ + RESULT_ENUM(prefix, OFFSET_TOO_BIG, 4001), /**< Offset past end of resource */ \ + RESULT_ENUM(prefix, FILE_OPEN_FAIL, 4002), /**< Failed to open resource file */ \ + RESULT_ENUM(prefix, FILE_SEEK_FAIL, 4003), /**< Failed to seek to requested offset in resource file */ \ + RESULT_ENUM(prefix, FILE_READ_FAIL, 4004), /**< Failed to read resource file */ + +#define resource_get_size(resource) ( (resource)->size ) + +/****************************************************** +* Constants +******************************************************/ + +#define RESOURCE_ENUM_OFFSET (1300) + +/****************************************************** +* Enumerations +******************************************************/ + +/** + * Result type for WICED Resource function + */ +typedef enum +{ + RESOURCE_RESULT_LIST(RESOURCE_) +} resource_result_t; + +/****************************************************** +* Type Definitions +******************************************************/ + +typedef const void *resource_data_t; +typedef unsigned long resource_size_t; + +/****************************************************** +* Structures +******************************************************/ + +/** + * Memory handle + */ +typedef struct +{ + const char *data; /**< resource data */ +} memory_resource_handle_t; + +/** + * Filesystem handle + */ +typedef struct +{ + unsigned long offset; /**< Offset to the start of the resource */ + const char *filename; /**< name of the resource */ +} filesystem_resource_handle_t; + + +typedef enum +{ + RESOURCE_IN_MEMORY, /**< resource location in memory */ + RESOURCE_IN_FILESYSTEM, /**< resource location in filesystem */ + RESOURCE_IN_EXTERNAL_STORAGE /**< resource location in external storage */ +} resource_location_t; + +/** + * Resource handle structure + */ +typedef struct +{ + resource_location_t location; /**< resource location */ + unsigned long size; /**< resource size */ + union + { + filesystem_resource_handle_t fs; /** < filesystem resource handle */ + memory_resource_handle_t mem; /** < memory resource handle */ + void *external_storage_context; /** < external storage context */ + } val; +} resource_hnd_t; + +/****************************************************** +* Global Variables +******************************************************/ + +/****************************************************** +* Function Declarations +******************************************************/ + +/*****************************************************************************/ +/** @addtogroup resourceapi Wiced Resource Management API's + * @ingroup framework + * + * WCIED Resource Management API's has functions to get the + * resource size and reads resource data from a resource + * location and returns the number of bytes in an caller + * filled buffer + * + * The Resource could be one of the three locations + * + * - Wiced Filesystem ( File System) + * - Internal Memory (Embedded Flash memory) + * - External Storage ( External Flash connected via SPI interface ) + * + * @{ + */ +/*****************************************************************************/ + +/** Read resource using the handle specified + * + * @param[in] resource : handle of the resource to read + * @param[in] offset : offset from the beginning of the resource block + * @param[in] maxsize : size of the buffer + * @param[out] size : size of the data successfully read + * @param[in] buffer : pointer to a buffer to contain the read data + * + * @return @ref resource_result_t + */ +extern resource_result_t resource_read(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, + uint32_t *size, void *buffer); + +/** Retrieve a read only resource buffer using the handle specified + * + * @param[in] resource : handle of the resource to read + * @param[in] offset : offset from the beginning of the resource block + * @param[in] maxsize : size of the buffer + * @param[out] size : size of the data successfully read + * @param[out] buffer : pointer to a buffer pointer to point to the resource data + * + * @return @ref resource_result_t + */ +extern resource_result_t resource_get_readonly_buffer(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, + uint32_t *size_out, const void **buffer); + +/** Free a read only resource buffer using the handle specified + * + * @param[in] resource : handle of the resource to read + * @param[in] buffer : pointer to a buffer set using resource_get_readonly_buffer + * + * @return @ref resource_result_t + */ +extern resource_result_t resource_free_readonly_buffer(const resource_hnd_t *handle, const void *buffer); +/* @} */ +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif /* ifndef INCLUDED_RESOURCE_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus.c b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus.c new file mode 100644 index 00000000..d4e8db26 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus.c @@ -0,0 +1,230 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * + */ + +#include +#include "whd_bus.h" +#include "whd_int.h" + + +whd_driver_t g_bt_whd_driver; + +whd_result_t whd_bus_write_reg_value(whd_driver_t whd_driver, uint32_t address, + uint8_t value_length, uint32_t value) +{ + CHECK_RETURN(whd_ensure_wlan_bus_is_up(whd_driver) ); + return whd_bus_write_backplane_value(whd_driver, address, value_length, value); + +} + +whd_result_t whd_bus_read_reg_value(whd_driver_t whd_driver, uint32_t address, + uint8_t value_length, uint8_t *value) +{ + CHECK_RETURN(whd_ensure_wlan_bus_is_up(whd_driver) ); + return whd_bus_read_backplane_value(whd_driver, address, value_length, value); + +} + +whd_result_t whd_bus_share_bt_init(whd_driver_t whd_driver) +{ + if (!whd_driver) + return WHD_WLAN_ERROR; + g_bt_whd_driver = whd_driver; + return WHD_SUCCESS; +} + +whd_driver_t whd_bt_get_whd_driver(void) +{ + if (g_bt_whd_driver) + return g_bt_whd_driver; + else + return NULL; +} + +whd_result_t whd_bus_bt_attach(whd_driver_t whd_driver, void *btdata, + void (*bt_int_fun)(void *data) ) +{ + whd_bt_dev_t btdev; + if (whd_driver->bt_dev) + { + return WHD_SUCCESS; + } + /* Allocate bt dev */ + btdev = (whd_bt_dev_t)malloc(sizeof(struct whd_bt_dev) ); + if (btdev == NULL) + { + WPRINT_WHD_ERROR( ("Memory allocation failed for whd_bt_dev_t in %s\n", __FUNCTION__) ); + return WHD_BUFFER_UNAVAILABLE_PERMANENT; + } + btdev->bt_data = btdata; + btdev->intr = WHD_TRUE; + whd_driver->bt_dev = btdev; + whd_bus_init_stats(whd_driver); + btdev->bt_int_cb = bt_int_fun; + if (!btdev->bt_int_cb) + { + btdev->intr = WHD_FALSE; + } + return WHD_SUCCESS; +} + +void whd_bus_bt_detach(whd_driver_t whd_driver) +{ + whd_bt_dev_t btdev = whd_driver->bt_dev; + if (btdev) + { + if (btdev->bt_data) + btdev->bt_data = NULL; + if (btdev->bt_int_cb) + btdev->bt_int_cb = NULL; + if (whd_driver->bt_dev) + { + whd_driver->bt_dev = NULL; + free(btdev); + } + } +} + +whd_result_t whd_bus_init(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_init_fptr(whd_driver); +} + +whd_result_t whd_bus_deinit(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_deinit_fptr(whd_driver); +} + +whd_bool_t whd_bus_wake_interrupt_present(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_wake_interrupt_present_fptr(whd_driver); +} + +whd_result_t whd_bus_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + return whd_driver->bus_if->whd_bus_send_buffer_fptr(whd_driver, buffer); +} + +uint32_t whd_bus_packet_available_to_read(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_packet_available_to_read_fptr(whd_driver); +} + +whd_result_t whd_bus_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer) +{ + return whd_driver->bus_if->whd_bus_read_frame_fptr(whd_driver, buffer); +} + +whd_result_t whd_bus_write_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint32_t value) +{ + return whd_driver->bus_if->whd_bus_write_backplane_value_fptr(whd_driver, address, register_length, value); +} + +whd_result_t whd_bus_read_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint8_t *value) +{ + return whd_driver->bus_if->whd_bus_read_backplane_value_fptr(whd_driver, address, register_length, value); +} + +whd_result_t whd_bus_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function, uint32_t address, + uint8_t value_length, uint8_t *value) +{ + return whd_driver->bus_if->whd_bus_read_register_value_fptr(whd_driver, function, address, value_length, value); +} + +whd_result_t whd_bus_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function, uint32_t address, + uint8_t value_length, uint32_t value) +{ + return whd_driver->bus_if->whd_bus_write_register_value_fptr(whd_driver, function, address, value_length, value); +} + +whd_result_t whd_bus_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t size, + whd_transfer_bytes_packet_t *data) +{ + return whd_driver->bus_if->whd_bus_transfer_bytes_fptr(whd_driver, direction, function, address, size, data); +} + +whd_result_t whd_bus_poke_wlan(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_poke_wlan_fptr(whd_driver); +} + +whd_result_t whd_bus_wakeup(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_wakeup_fptr(whd_driver); +} + +whd_result_t whd_bus_sleep(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_sleep_fptr(whd_driver); +} + +whd_result_t whd_bus_wait_for_wlan_event(whd_driver_t whd_driver, cy_semaphore_t *transceive_semaphore) +{ + return whd_driver->bus_if->whd_bus_wait_for_wlan_event_fptr(whd_driver, transceive_semaphore); +} + +whd_bool_t whd_bus_use_status_report_scheme(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_use_status_report_scheme_fptr(whd_driver); +} + +uint8_t whd_bus_backplane_read_padd_size(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_backplane_read_padd_size_fptr(whd_driver); +} + +uint32_t whd_bus_get_max_transfer_size(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_get_max_transfer_size_fptr(whd_driver); +} + +void whd_bus_init_stats(whd_driver_t whd_driver) +{ + whd_driver->bus_if->whd_bus_init_stats_fptr(whd_driver); +} + +whd_result_t whd_bus_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print) +{ + return whd_driver->bus_if->whd_bus_print_stats_fptr(whd_driver, reset_after_print); +} + +whd_result_t whd_bus_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware) +{ + return whd_driver->bus_if->whd_bus_reinit_stats_fptr(whd_driver, wake_from_firmware); +} + +whd_result_t whd_bus_irq_register(whd_driver_t whd_driver) +{ + return whd_driver->bus_if->whd_bus_irq_register_fptr(whd_driver); +} + +whd_result_t whd_bus_irq_enable(whd_driver_t whd_driver, whd_bool_t enable) +{ + return whd_driver->bus_if->whd_bus_irq_enable_fptr(whd_driver, enable); +} + +whd_result_t whd_bus_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, uint32_t image_size) +{ + return whd_driver->bus_if->whd_bus_download_resource_fptr(whd_driver, resource, direct_resource, address, image_size); +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus.h b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus.h new file mode 100644 index 00000000..f5662537 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus.h @@ -0,0 +1,129 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * + */ + +#include "whd_bus_protocol_interface.h" +#include "whd_resource_api.h" + +#ifndef INCLUDED_WHD_BUS_H_ +#define INCLUDED_WHD_BUS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if 0 +typedef struct whd_bus_if *whd_bus_if_t; + +typedef whd_result_t (*whd_bus_transfer_t)(whd_bus_if_t *bus_if, whd_bus_transfer_direction_t dir, + uint8_t *data, uint16_t data_size, void *arg1, void *arg2, void *arg3, + void *arg4); +#endif + +typedef whd_result_t (*whd_bus_init_t)(whd_driver_t whd_driver); +typedef whd_result_t (*whd_bus_deinit_t)(whd_driver_t whd_driver); + +typedef whd_result_t (*whd_bus_ack_interrupt_t)(whd_driver_t whd_driver, uint32_t intstatus); +typedef whd_bool_t (*whd_bus_wake_interrupt_present_t)(whd_driver_t whd_driver); +typedef uint32_t (*whd_bus_packet_available_to_read_t)(whd_driver_t whd_driver); +typedef whd_result_t (*whd_bus_read_frame_t)(whd_driver_t whd_driver, whd_buffer_t *buffer); + +typedef whd_result_t (*whd_bus_set_backplane_window_t)(whd_driver_t whd_driver, uint32_t addr, uint32_t *cur_base_addr); +typedef whd_result_t (*whd_bus_write_backplane_value_t)(whd_driver_t whd_driver, uint32_t address, + uint8_t register_length, uint32_t value); +typedef whd_result_t (*whd_bus_read_backplane_value_t)(whd_driver_t whd_driver, uint32_t address, + uint8_t register_length, uint8_t *value); + +typedef whd_result_t (*whd_bus_write_register_value_t)(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint32_t value); +typedef whd_result_t (*whd_bus_read_register_value_t)(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint8_t *value); + +typedef whd_result_t (*whd_bus_transfer_bytes_t)(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t size, + whd_transfer_bytes_packet_t *data); + +typedef whd_result_t (*whd_bus_poke_wlan_t)(whd_driver_t whd_driver); + +typedef whd_result_t (*whd_bus_wakeup_t)(whd_driver_t whd_driver); +typedef whd_result_t (*whd_bus_sleep_t)(whd_driver_t whd_driver); +typedef uint8_t (*whd_bus_backplane_read_padd_size_t)(whd_driver_t whd_driver); +typedef whd_result_t (*whd_bus_send_buffer_t)(whd_driver_t whd_driver, whd_buffer_t buffer); +typedef whd_result_t (*whd_bus_wait_for_wlan_event_t)(whd_driver_t whd_driver, + cy_semaphore_t *transceive_semaphore); +typedef whd_bool_t (*whd_bus_use_status_report_scheme_t)(whd_driver_t whd_driver); +typedef uint32_t (*whd_bus_get_max_transfer_size_t)(whd_driver_t whd_driver); + +typedef void (*whd_bus_init_stats_t)(whd_driver_t whd_driver); +typedef whd_result_t (*whd_bus_print_stats_t)(whd_driver_t whd_driver, whd_bool_t reset_after_print); +typedef whd_result_t (*whd_bus_reinit_stats_t)(whd_driver_t whd_driver, whd_bool_t wake_from_firmware); +typedef whd_result_t (*whd_bus_irq_register_t)(whd_driver_t whd_driver); +typedef whd_result_t (*whd_bus_irq_enable_t)(whd_driver_t whd_driver, whd_bool_t enable); +typedef whd_result_t (*whd_bus_download_resource_t)(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, + uint32_t image_size); + +typedef struct whd_bus_info +{ + whd_bus_init_t whd_bus_init_fptr; + whd_bus_deinit_t whd_bus_deinit_fptr; + + whd_bus_ack_interrupt_t whd_bus_ack_interrupt_fptr; + whd_bus_send_buffer_t whd_bus_send_buffer_fptr; + + whd_bus_wake_interrupt_present_t whd_bus_wake_interrupt_present_fptr; + whd_bus_packet_available_to_read_t whd_bus_packet_available_to_read_fptr; + whd_bus_read_frame_t whd_bus_read_frame_fptr; + + whd_bus_set_backplane_window_t whd_bus_set_backplane_window_fptr; + whd_bus_write_backplane_value_t whd_bus_write_backplane_value_fptr; + whd_bus_read_backplane_value_t whd_bus_read_backplane_value_fptr; + + whd_bus_write_register_value_t whd_bus_write_register_value_fptr; + whd_bus_read_register_value_t whd_bus_read_register_value_fptr; + + whd_bus_transfer_bytes_t whd_bus_transfer_bytes_fptr; + + whd_bus_poke_wlan_t whd_bus_poke_wlan_fptr; + + whd_bus_wakeup_t whd_bus_wakeup_fptr; + whd_bus_sleep_t whd_bus_sleep_fptr; + + whd_bus_backplane_read_padd_size_t whd_bus_backplane_read_padd_size_fptr; + + whd_bus_wait_for_wlan_event_t whd_bus_wait_for_wlan_event_fptr; + whd_bus_use_status_report_scheme_t whd_bus_use_status_report_scheme_fptr; + + whd_bus_get_max_transfer_size_t whd_bus_get_max_transfer_size_fptr; + + whd_bus_init_stats_t whd_bus_init_stats_fptr; + whd_bus_print_stats_t whd_bus_print_stats_fptr; + whd_bus_reinit_stats_t whd_bus_reinit_stats_fptr; + whd_bus_irq_register_t whd_bus_irq_register_fptr; + whd_bus_irq_enable_t whd_bus_irq_enable_fptr; + whd_bus_download_resource_t whd_bus_download_resource_fptr; +} whd_bus_info_t; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef INCLUDED_WHD_BUS_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_common.c b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_common.c new file mode 100644 index 00000000..ec3312e1 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_common.c @@ -0,0 +1,382 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * + */ +#include +#include "cyabs_rtos.h" + +#include "whd_bus.h" +#include "whd_bus_common.h" +#include "whd_chip_reg.h" +#include "whd_sdio.h" +#include "whd_chip_constants.h" +#include "whd_int.h" +#include "whd_chip.h" +#include "whd_bus_protocol_interface.h" +#include "whd_debug.h" +#include "whd_buffer_api.h" +#include "whd_resource_if.h" +#include "whd_resource_api.h" +#include "whd_types_int.h" + + +/****************************************************** +* Macros +******************************************************/ +#define WHD_SAVE_INTERRUPTS(flags) do { UNUSED_PARAMETER(flags); } while (0); +#define WHD_RESTORE_INTERRUPTS(flags) do { } while (0); + +/****************************************************** +* Constants +******************************************************/ +#define INDIRECT_BUFFER_SIZE (1024) +#define WHD_BUS_ROUND_UP_ALIGNMENT (64) +#define WHD_BUS_MAX_TRANSFER_SIZE (WHD_BUS_MAX_BACKPLANE_TRANSFER_SIZE) + +#define WHD_BUS_WLAN_ALLOW_SLEEP_INVALID_MS ( (uint32_t)-1 ) + +/****************************************************** +* Structures +******************************************************/ + +struct whd_bus_common_info +{ + whd_bool_t bus_is_up; + + whd_time_t delayed_bus_release_deadline; + whd_bool_t delayed_bus_release_scheduled; + uint32_t delayed_bus_release_timeout_ms; + volatile uint32_t delayed_bus_release_timeout_ms_request; + + uint32_t backplane_window_current_base_address; + whd_bool_t bus_flow_control; + volatile whd_bool_t resource_download_abort; +}; + +/****************************************************** +* Variables +******************************************************/ + +/****************************************************** +* Function declarations +******************************************************/ +whd_result_t whd_bus_common_write_wifi_nvram_image(whd_driver_t whd_driver); + +/****************************************************** +* Function definitions +******************************************************/ + +whd_bool_t whd_bus_is_up(whd_driver_t whd_driver) +{ + return whd_driver->bus_common_info->bus_is_up; +} + +void whd_bus_set_state(whd_driver_t whd_driver, whd_bool_t state) +{ + whd_driver->bus_common_info->bus_is_up = state; +} + +whd_result_t whd_bus_set_flow_control(whd_driver_t whd_driver, uint8_t value) +{ + if (value != 0) + { + whd_driver->bus_common_info->bus_flow_control = WHD_TRUE; + } + else + { + whd_driver->bus_common_info->bus_flow_control = WHD_FALSE; + } + return WHD_SUCCESS; +} + +whd_bool_t whd_bus_is_flow_controlled(whd_driver_t whd_driver) +{ + return whd_driver->bus_common_info->bus_flow_control; +} + +whd_result_t whd_bus_set_backplane_window(whd_driver_t whd_driver, uint32_t addr) +{ + uint32_t *curbase = &whd_driver->bus_common_info->backplane_window_current_base_address; + return whd_driver->bus_if->whd_bus_set_backplane_window_fptr(whd_driver, addr, curbase); +} + + +void whd_bus_common_info_init(whd_driver_t whd_driver) +{ + struct whd_bus_common_info *bus_common = (struct whd_bus_common_info *)malloc(sizeof(struct whd_bus_common_info) ); + + if (bus_common != NULL) + { + whd_driver->bus_common_info = bus_common; + + bus_common->delayed_bus_release_deadline = 0; + bus_common->delayed_bus_release_scheduled = WHD_FALSE; + bus_common->delayed_bus_release_timeout_ms = PLATFORM_WLAN_ALLOW_BUS_TO_SLEEP_DELAY_MS; + bus_common->delayed_bus_release_timeout_ms_request = WHD_BUS_WLAN_ALLOW_SLEEP_INVALID_MS; + bus_common->backplane_window_current_base_address = 0; + + bus_common->bus_is_up = WHD_FALSE; + bus_common->bus_flow_control = WHD_FALSE; + + bus_common->resource_download_abort = WHD_FALSE; + } + else + { + WPRINT_WHD_ERROR( ("Memory allocation failed for whd_bus_common_info in %s\n", __FUNCTION__) ); + } +} + +void whd_bus_common_info_deinit(whd_driver_t whd_driver) +{ + if (whd_driver->bus_common_info != NULL) + { + free(whd_driver->bus_common_info); + whd_driver->bus_common_info = NULL; + } +} + +void whd_delayed_bus_release_schedule_update(whd_driver_t whd_driver, whd_bool_t is_scheduled) +{ + whd_driver->bus_common_info->delayed_bus_release_scheduled = is_scheduled; + whd_driver->bus_common_info->delayed_bus_release_deadline = 0; +} + +uint32_t whd_bus_handle_delayed_release(whd_driver_t whd_driver) +{ + uint32_t time_until_release = 0; + uint32_t current_time = 0; + struct whd_bus_common_info *bus_common = whd_driver->bus_common_info; + + if (bus_common->delayed_bus_release_timeout_ms_request != WHD_BUS_WLAN_ALLOW_SLEEP_INVALID_MS) + { + whd_bool_t schedule = + ( (bus_common->delayed_bus_release_scheduled != 0) || + (bus_common->delayed_bus_release_deadline != 0) ) ? WHD_TRUE : WHD_FALSE; + uint32_t flags; + + WHD_SAVE_INTERRUPTS(flags); + bus_common->delayed_bus_release_timeout_ms = bus_common->delayed_bus_release_timeout_ms_request; + bus_common->delayed_bus_release_timeout_ms_request = WHD_BUS_WLAN_ALLOW_SLEEP_INVALID_MS; + WHD_RESTORE_INTERRUPTS(flags); + + DELAYED_BUS_RELEASE_SCHEDULE(whd_driver, schedule); + } + + if (bus_common->delayed_bus_release_scheduled == WHD_TRUE) + { + bus_common->delayed_bus_release_scheduled = WHD_FALSE; + + if (bus_common->delayed_bus_release_timeout_ms != 0) + { + cy_rtos_get_time(¤t_time); + bus_common->delayed_bus_release_deadline = current_time + + bus_common->delayed_bus_release_timeout_ms; + time_until_release = bus_common->delayed_bus_release_timeout_ms; + } + } + else if (bus_common->delayed_bus_release_deadline != 0) + { + whd_time_t now; + + cy_rtos_get_time(&now); + + if (bus_common->delayed_bus_release_deadline - now <= bus_common->delayed_bus_release_timeout_ms) + { + time_until_release = bus_common->delayed_bus_release_deadline - now; + } + + if (time_until_release == 0) + { + bus_common->delayed_bus_release_deadline = 0; + } + } + + if (time_until_release != 0) + { + if (whd_bus_is_up(whd_driver) == WHD_FALSE) + { + time_until_release = 0; + } + else if (whd_bus_platform_mcu_power_save_deep_sleep_enabled(whd_driver) ) + { + time_until_release = 0; + } + } + + return time_until_release; +} + +whd_bool_t whd_bus_platform_mcu_power_save_deep_sleep_enabled(whd_driver_t whd_driver) +{ + return WHD_FALSE; +} + +void whd_bus_init_backplane_window(whd_driver_t whd_driver) +{ + whd_driver->bus_common_info->backplane_window_current_base_address = 0; +} + +whd_result_t whd_bus_write_wifi_firmware_image(whd_driver_t whd_driver) +{ + whd_result_t result = WHD_SUCCESS; + uint32_t ram_start_address; + uint32_t image_size; + + /* Pass the ram_start_address to the firmware Download + * CR4 chips have offset and CM3 starts from 0 */ + + ram_start_address = GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS); + + result = whd_resource_size(whd_driver, WHD_RESOURCE_WLAN_FIRMWARE, &image_size); + + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Fatal error: download_resource doesn't exist, %s failed at line %d \n", __func__, + __LINE__) ); + return result; + } + + if (image_size <= 0) + { + WPRINT_WHD_ERROR( ("Fatal error: download_resource cannot load with invalid size, %s failed at line %d \n", + __func__, __LINE__) ); + return WHD_BADARG; + } + + result = whd_bus_download_resource(whd_driver, WHD_RESOURCE_WLAN_FIRMWARE, WHD_FALSE, ram_start_address, image_size); + + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("Bus common resource download failed, %s failed at %d \n", __func__, __LINE__) ); + + return result; +} + +void whd_bus_set_resource_download_halt(whd_driver_t whd_driver, whd_bool_t halt) +{ + whd_driver->bus_common_info->resource_download_abort = halt; +} + +/* Default implementation of WHD bus resume function, which does nothing */ +whd_result_t whd_bus_resume_after_deep_sleep(whd_driver_t whd_driver) +{ + whd_assert("In order to support deep-sleep platform need to implement this function", 0); + return WHD_UNSUPPORTED; +} + +whd_result_t whd_bus_mem_bytes(whd_driver_t whd_driver, uint8_t direct, + uint32_t address, uint32_t size, uint8_t *data) +{ + whd_bus_transfer_direction_t direction = direct ? BUS_WRITE : BUS_READ; + CHECK_RETURN(whd_ensure_wlan_bus_is_up(whd_driver) ); + return whd_bus_transfer_backplane_bytes(whd_driver, direction, address, size, data); +} + +whd_result_t whd_bus_transfer_backplane_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + uint32_t address, uint32_t size, uint8_t *data) +{ + whd_buffer_t pkt_buffer = NULL; + uint8_t *packet; + uint32_t transfer_size; + uint32_t remaining_buf_size; + uint32_t window_offset_address; + uint32_t trans_addr; + whd_result_t result; + + result = whd_host_buffer_get(whd_driver, &pkt_buffer, (direction == BUS_READ) ? WHD_NETWORK_RX : WHD_NETWORK_TX, + ( uint16_t )(whd_bus_get_max_transfer_size(whd_driver) + + whd_bus_backplane_read_padd_size( + whd_driver) + MAX_BUS_HEADER_SIZE), WHD_BACKPLAIN_BUF_TIMEOUT); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Packet buffer allocation failed in %s at %d \n", __func__, __LINE__) ); + goto done; + } + packet = (uint8_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, pkt_buffer); + CHECK_PACKET_NULL(packet, WHD_NO_REGISTER_FUNCTION_POINTER); + for (remaining_buf_size = size; remaining_buf_size != 0; + remaining_buf_size -= transfer_size, address += transfer_size) + { + transfer_size = (remaining_buf_size > + whd_bus_get_max_transfer_size(whd_driver) ) ? whd_bus_get_max_transfer_size(whd_driver) : + remaining_buf_size; + + /* Check if the transfer crosses the backplane window boundary */ + window_offset_address = address & BACKPLANE_ADDRESS_MASK; + if ( (window_offset_address + transfer_size) > BACKPLANE_ADDRESS_MASK ) + { + /* Adjust the transfer size to within current window */ + transfer_size = BACKPLANE_WINDOW_SIZE - window_offset_address; + } + result = whd_bus_set_backplane_window(whd_driver, address); + if (result == WHD_UNSUPPORTED) + { + /* No backplane support, write data to address directly */ + trans_addr = address; + } + else if (result == WHD_SUCCESS) + { + trans_addr = address & BACKPLANE_ADDRESS_MASK; + } + else + { + goto done; + } + + if (direction == BUS_WRITE) + { + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + memcpy( ( (whd_transfer_bytes_packet_t *)packet )->data, data + size - remaining_buf_size, transfer_size ); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + result = whd_bus_transfer_bytes(whd_driver, direction, BACKPLANE_FUNCTION, + trans_addr, (uint16_t)transfer_size, + (whd_transfer_bytes_packet_t *)packet); + if (result != WHD_SUCCESS) + { + goto done; + } + } + else + { + result = whd_bus_transfer_bytes(whd_driver, direction, BACKPLANE_FUNCTION, + trans_addr, + ( uint16_t )(transfer_size + whd_bus_backplane_read_padd_size(whd_driver) ), + (whd_transfer_bytes_packet_t *)packet); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("whd_bus_transfer_bytes failed\n") ); + goto done; + } + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + memcpy(data + size - remaining_buf_size, (uint8_t *)( (whd_transfer_bytes_packet_t *)packet )->data + + whd_bus_backplane_read_padd_size(whd_driver), transfer_size); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + } + } + +done: + whd_bus_set_backplane_window(whd_driver, CHIPCOMMON_BASE_ADDRESS); + if (pkt_buffer != NULL) + { + CHECK_RETURN(whd_buffer_release(whd_driver, pkt_buffer, + (direction == BUS_READ) ? WHD_NETWORK_RX : WHD_NETWORK_TX) ); + } + CHECK_RETURN(result); + + return WHD_SUCCESS; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_common.h b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_common.h new file mode 100644 index 00000000..c811ca1e --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_common.h @@ -0,0 +1,67 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "whd.h" +#include + +#ifndef INCLUDED_WHD_BUS_COMMON_H +#define INCLUDED_WHD_BUS_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define WHD_BACKPLAIN_BUF_TIMEOUT (0xFFFFFFFF) +#define WHD_RX_BUF_TIMEOUT (10) + + +struct whd_bus_common_info; + +void whd_bus_common_info_init(whd_driver_t whd_driver); +void whd_bus_common_info_deinit(whd_driver_t whd_driver); + +/* Configure delayed sleep of bus. + * A high number will mean a longer delay before sleep after the last operation (higher performance) + * A shorter delay will mean quicker sleep after last operation (lower power use) + */ +extern void whd_bus_sdio_wlan_set_delayed_bus_powersave_milliseconds(whd_driver_t whd_driver, uint32_t time_ms); +extern whd_result_t whd_bus_resume_after_deep_sleep(whd_driver_t whd_driver); + +extern whd_result_t whd_bus_write_wifi_firmware_image(whd_driver_t whd_driver); +extern whd_result_t whd_bus_write_wifi_nvram_image(whd_driver_t whd_driver); +extern void whd_bus_set_resource_download_halt(whd_driver_t whd_driver, whd_bool_t halt); + +extern whd_result_t whd_bus_transfer_backplane_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + uint32_t address, uint32_t size, uint8_t *data); +extern void whd_bus_init_backplane_window(whd_driver_t whd_driver); +whd_result_t whd_bus_set_backplane_window(whd_driver_t whd_driver, uint32_t addr); + +whd_bool_t whd_bus_is_up(whd_driver_t whd_driver); +extern whd_result_t whd_bus_set_flow_control(whd_driver_t whd_driver, uint8_t value); +extern whd_bool_t whd_bus_is_flow_controlled(whd_driver_t whd_driver); + +void whd_bus_set_state(whd_driver_t whd_driver, whd_bool_t state); + +extern void whd_delayed_bus_release_schedule_update(whd_driver_t whd_driver, whd_bool_t is_scheduled); + +/* handle delayed sleep of bus */ +extern uint32_t whd_bus_handle_delayed_release(whd_driver_t whd_driver); +whd_bool_t whd_bus_platform_mcu_power_save_deep_sleep_enabled(whd_driver_t whd_driver); +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_m2m_protocol.c b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_m2m_protocol.c new file mode 100644 index 00000000..e3bf9c74 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_m2m_protocol.c @@ -0,0 +1,622 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Broadcom WLAN M2M Protocol interface + * + * Implements the WHD Bus Protocol Interface for M2M + * Provides functions for initialising, de-intitialising 802.11 device, + * sending/receiving raw packets etc + */ + +#include "cybsp.h" +#if (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_M2M_INTERFACE) + +#include "cyhal_dma.h" +#include "cyhal_hw_types.h" +#include "whd_bus_m2m_protocol.h" + +#include "whd_bus.h" +#include "whd_bus_common.h" +#include "whd_chip_reg.h" +#include "whd_chip_constants.h" +#include "whd_buffer_api.h" +#include "whd_types_int.h" +#include "whd_types.h" +#include "whd_thread_internal.h" +#include "whd_resource_if.h" +#include "whd_wlioctl.h" + +/****************************************************** +* Constants +******************************************************/ + +#define WHD_BUS_M2M_BACKPLANE_READ_PADD_SIZE (0) +#define WHD_BUS_M2M_MAX_BACKPLANE_TRANSFER_SIZE (WHD_PAYLOAD_MTU) +#define BOOT_WLAN_WAIT_TIME (5) /* 5ms wait time */ +#define M2M_DMA_RX_BUFFER_SIZE (WHD_PHYSICAL_HEADER + WLC_IOCTL_MEDLEN) + +#define ARMCR4_SW_INT0 (0x1 << 0) + +#if !defined (__IAR_SYSTEMS_ICC__) +/* assume registers are Device memory, so have implicit CPU memory barriers */ +#define MEMORY_BARRIER_AGAINST_COMPILER_REORDERING() __asm__ __volatile__ ("" : : : "memory") +#define REGISTER_WRITE_WITH_BARRIER(type, address, value) \ + do {*(volatile type *)(address) = (type)(value); \ + MEMORY_BARRIER_AGAINST_COMPILER_REORDERING();} while (0) +#define REGISTER_READ(type, address) \ + (*(volatile type *)(address) ) +#endif + +/****************************************************** +* Structures +******************************************************/ +struct whd_bus_priv +{ + whd_m2m_config_t m2m_config; + cyhal_m2m_t *m2m_obj; +}; + +/****************************************************** +* Variables +******************************************************/ +static whd_bus_info_t whd_bus_m2m_info; +static struct whd_bus_priv whd_bus_priv; + +/****************************************************** +* Function declarations +******************************************************/ +static whd_result_t whd_bus_m2m_init(whd_driver_t whd_driver); +static whd_result_t whd_bus_m2m_deinit(whd_driver_t whd_driver); +static whd_result_t whd_bus_m2m_ack_interrupt(whd_driver_t whd_driver, uint32_t intstatus); +static whd_result_t whd_bus_m2m_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer); + +static whd_bool_t whd_bus_m2m_wake_interrupt_present(whd_driver_t whd_driver); +static uint32_t whd_bus_m2m_packet_available_to_read(whd_driver_t whd_driver); +static whd_result_t whd_bus_m2m_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer); + +static whd_result_t whd_bus_m2m_write_backplane_value(whd_driver_t whd_driver, uint32_t address, + uint8_t register_length, uint32_t value); +static whd_result_t whd_bus_m2m_read_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint8_t *value); +static whd_result_t whd_bus_m2m_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint32_t value); +static whd_result_t whd_bus_m2m_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint8_t *value); +static whd_result_t whd_bus_m2m_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t size, + whd_transfer_bytes_packet_t *data); + +static whd_result_t whd_bus_m2m_poke_wlan(whd_driver_t whd_driver); +static whd_result_t whd_bus_m2m_wakeup(whd_driver_t whd_driver); +static whd_result_t whd_bus_m2m_sleep(whd_driver_t whd_driver); +static uint8_t whd_bus_m2m_backplane_read_padd_size(whd_driver_t whd_driver); +static whd_result_t whd_bus_m2m_wait_for_wlan_event(whd_driver_t whd_driver, cy_semaphore_t *transceive_semaphore); +static whd_bool_t whd_bus_m2m_use_status_report_scheme(whd_driver_t whd_driver); +static uint32_t whd_bus_m2m_get_max_transfer_size(whd_driver_t whd_driver); +static void whd_bus_m2m_init_stats(whd_driver_t whd_driver); +static whd_result_t whd_bus_m2m_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print); +static whd_result_t whd_bus_m2m_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware); +static whd_result_t whd_bus_m2m_irq_register(whd_driver_t whd_driver); +static whd_result_t whd_bus_m2m_irq_enable(whd_driver_t whd_driver, whd_bool_t enable); +static whd_result_t whd_bus_m2m_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, uint32_t image_size); +static whd_result_t whd_bus_m2m_write_wifi_nvram_image(whd_driver_t whd_driver); +static whd_result_t whd_bus_m2m_set_backplane_window(whd_driver_t whd_driver, uint32_t addr, uint32_t *curaddr); + +static whd_result_t boot_wlan(whd_driver_t whd_driver); +whd_bool_t whd_ensure_wlan_is_up(whd_driver_t whd_driver); +whd_result_t m2m_bus_write_wifi_firmware_image(whd_driver_t whd_driver); +void whd_bus_m2m_irq_handler(void *callback_arg, cyhal_m2m_event_t events); + + +/****************************************************** +* Function definitions +******************************************************/ + +// Functions for whd_driver->bus_if function list +uint32_t whd_bus_m2m_attach(whd_driver_t whd_driver, whd_m2m_config_t *whd_m2m_config, cyhal_m2m_t *m2m_obj) +{ + WPRINT_WHD_INFO( ("m2m_attach\n") ); + + whd_driver->bus_if = &whd_bus_m2m_info; + whd_driver->bus_priv = &whd_bus_priv; + + memset(whd_driver->bus_if, 0, sizeof(whd_bus_info_t) ); + memset(whd_driver->bus_priv, 0, sizeof(struct whd_bus_priv) ); + + whd_driver->bus_priv->m2m_obj = m2m_obj; + whd_driver->bus_priv->m2m_config = *whd_m2m_config; + + whd_driver->bus_if->whd_bus_init_fptr = whd_bus_m2m_init; + whd_driver->bus_if->whd_bus_deinit_fptr = whd_bus_m2m_deinit; + + whd_driver->bus_if->whd_bus_ack_interrupt_fptr = whd_bus_m2m_ack_interrupt; + whd_driver->bus_if->whd_bus_send_buffer_fptr = whd_bus_m2m_send_buffer; + + whd_driver->bus_if->whd_bus_wake_interrupt_present_fptr = whd_bus_m2m_wake_interrupt_present; + whd_driver->bus_if->whd_bus_packet_available_to_read_fptr = whd_bus_m2m_packet_available_to_read; + whd_driver->bus_if->whd_bus_read_frame_fptr = whd_bus_m2m_read_frame; + + + whd_driver->bus_if->whd_bus_write_backplane_value_fptr = whd_bus_m2m_write_backplane_value; + whd_driver->bus_if->whd_bus_read_backplane_value_fptr = whd_bus_m2m_read_backplane_value; + + whd_driver->bus_if->whd_bus_write_register_value_fptr = whd_bus_m2m_write_register_value; + whd_driver->bus_if->whd_bus_read_register_value_fptr = whd_bus_m2m_read_register_value; + + whd_driver->bus_if->whd_bus_transfer_bytes_fptr = whd_bus_m2m_transfer_bytes; + + whd_driver->bus_if->whd_bus_poke_wlan_fptr = whd_bus_m2m_poke_wlan; + + whd_driver->bus_if->whd_bus_wakeup_fptr = whd_bus_m2m_wakeup; + whd_driver->bus_if->whd_bus_sleep_fptr = whd_bus_m2m_sleep; + + whd_driver->bus_if->whd_bus_backplane_read_padd_size_fptr = whd_bus_m2m_backplane_read_padd_size; + + whd_driver->bus_if->whd_bus_wait_for_wlan_event_fptr = whd_bus_m2m_wait_for_wlan_event; + whd_driver->bus_if->whd_bus_use_status_report_scheme_fptr = whd_bus_m2m_use_status_report_scheme; + + whd_driver->bus_if->whd_bus_get_max_transfer_size_fptr = whd_bus_m2m_get_max_transfer_size; + + whd_driver->bus_if->whd_bus_init_stats_fptr = whd_bus_m2m_init_stats; + whd_driver->bus_if->whd_bus_print_stats_fptr = whd_bus_m2m_print_stats; + whd_driver->bus_if->whd_bus_reinit_stats_fptr = whd_bus_m2m_reinit_stats; + whd_driver->bus_if->whd_bus_irq_register_fptr = whd_bus_m2m_irq_register; + whd_driver->bus_if->whd_bus_irq_enable_fptr = whd_bus_m2m_irq_enable; + whd_driver->bus_if->whd_bus_download_resource_fptr = whd_bus_m2m_download_resource; + whd_driver->bus_if->whd_bus_set_backplane_window_fptr = whd_bus_m2m_set_backplane_window; + + return WHD_SUCCESS; +} + +void whd_bus_m2m_detach(whd_driver_t whd_driver) +{ + whd_driver->bus_if = NULL; + whd_driver->bus_priv = NULL; +} + +void whd_bus_m2m_irq_handler(void *callback_arg, cyhal_m2m_event_t events) +{ + whd_driver_t whd_driver = (whd_driver_t)callback_arg; + + whd_bus_m2m_irq_enable(whd_driver, WHD_FALSE); + whd_thread_notify_irq(whd_driver); +} + +static whd_result_t whd_bus_m2m_init(whd_driver_t whd_driver) +{ + whd_result_t result = WHD_SUCCESS; + +#if !defined (__IAR_SYSTEMS_ICC__) + /* Get chip id */ + whd_chip_set_chip_id(whd_driver, (uint16_t)REGISTER_READ(uint32_t, CHIPCOMMON_BASE_ADDRESS) ); +#endif + + result = boot_wlan(whd_driver); + + if (result == WHD_SUCCESS) + { + cyhal_m2m_init(whd_driver->bus_priv->m2m_obj, M2M_DMA_RX_BUFFER_SIZE); + cyhal_m2m_register_callback(whd_driver->bus_priv->m2m_obj, whd_bus_m2m_irq_handler, whd_driver); + } + return result; +} + +static whd_result_t whd_bus_m2m_deinit(whd_driver_t whd_driver) +{ + //PLATFORM_WLAN_POWERSAVE_RES_UP(); + + /* Down M2M and WLAN */ + CHECK_RETURN(whd_disable_device_core(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_CPU_HALT) ); + cyhal_m2m_free(whd_driver->bus_priv->m2m_obj); + + /* Put WLAN to reset. */ + //host_platform_reset_wifi( WICED_TRUE ); + + //PLATFORM_WLAN_POWERSAVE_RES_DOWN( NULL, WICED_FALSE ); + + /* Force resource down even if resource up/down is unbalanced */ + //PLATFORM_WLAN_POWERSAVE_RES_DOWN( NULL, WICED_TRUE ); + + CHECK_RETURN(whd_allow_wlan_bus_to_sleep(whd_driver) ); + + whd_bus_set_resource_download_halt(whd_driver, WHD_FALSE); + + DELAYED_BUS_RELEASE_SCHEDULE(whd_driver, WHD_FALSE); + + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_ack_interrupt(whd_driver_t whd_driver, uint32_t intstatus) +{ + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + whd_result_t result = WHD_SUCCESS; + + if (cyhal_m2m_tx_send(whd_driver->bus_priv->m2m_obj, buffer) != CY_RSLT_SUCCESS) + { + result = WHD_WLAN_ERROR; + } + + return result; +} + +static whd_bool_t whd_bus_m2m_wake_interrupt_present(whd_driver_t whd_driver) +{ + /* functionality is only currently needed and present on SDIO */ + return WHD_FALSE; +} + +static uint32_t whd_bus_m2m_packet_available_to_read(whd_driver_t whd_driver) +{ + return 1; +} + +static whd_result_t whd_bus_m2m_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer) +{ + whd_result_t result = WHD_SUCCESS; + cyhal_m2m_event_t m2m_event; + uint16_t *hwtag; + void *packet = NULL; + bool signal_txdone; + + cyhal_m2m_rx_prepare(whd_driver->bus_priv->m2m_obj); + + m2m_event = cyhal_m2m_intr_status(whd_driver->bus_priv->m2m_obj, &signal_txdone); + if (signal_txdone) + { + /* Signal WLAN core there is a TX done by setting wlancr4 SW interrupt 0 */ + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x1c, + (uint8_t)4, ARMCR4_SW_INT0) ); + } + + /* Handle DMA interrupts */ + if ( (m2m_event & CYHAL_M2M_TX_CHANNEL_INTERRUPT) != 0 ) + { + cyhal_m2m_tx_release(whd_driver->bus_priv->m2m_obj); + } + + /* Handle DMA receive interrupt */ + cyhal_m2m_rx_receive(whd_driver->bus_priv->m2m_obj, &packet, &hwtag); + if (packet == NULL) + { + result = WHD_NO_PACKET_TO_RECEIVE; + } + else + { + *buffer = packet; + + /* move the data pointer 12 bytes(sizeof(wwd_buffer_header_t)) + * back to the start of the pakcet + */ + whd_buffer_add_remove_at_front(whd_driver, buffer, -(int)sizeof(whd_buffer_header_t) ); + whd_sdpcm_update_credit(whd_driver, (uint8_t *)hwtag); + } + + cyhal_m2m_rx_prepare(whd_driver->bus_priv->m2m_obj); + + return result; +} + +static whd_result_t whd_bus_m2m_write_backplane_value(whd_driver_t whd_driver, uint32_t address, + uint8_t register_length, uint32_t value) +{ +#if !defined (__IAR_SYSTEMS_ICC__) + MEMORY_BARRIER_AGAINST_COMPILER_REORDERING(); + + if (register_length == 4) + { + REGISTER_WRITE_WITH_BARRIER(uint32_t, address, value); + } + else if (register_length == 2) + { + REGISTER_WRITE_WITH_BARRIER(uint16_t, address, value); + } + else if (register_length == 1) + { + REGISTER_WRITE_WITH_BARRIER(uint8_t, address, value); + } + else + { + return WHD_WLAN_ERROR; + } +#endif + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_read_backplane_value(whd_driver_t whd_driver, uint32_t address, + uint8_t register_length, /*@out@*/ uint8_t *value) +{ +#if !defined (__IAR_SYSTEMS_ICC__) + MEMORY_BARRIER_AGAINST_COMPILER_REORDERING(); + + if (register_length == 4) + { + *( (uint32_t *)value ) = REGISTER_READ(uint32_t, address); + } + else if (register_length == 2) + { + *( (uint16_t *)value ) = REGISTER_READ(uint16_t, address); + } + else if (register_length == 1) + { + *value = REGISTER_READ(uint8_t, address); + } + else + { + return WHD_WLAN_ERROR; + } +#endif + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint32_t value) +{ + // Not used by M2M bus + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint8_t *value) +{ + // Not used by M2M bus + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t size, + whd_transfer_bytes_packet_t *data) +{ + if (function != BACKPLANE_FUNCTION) + { + return WHD_DOES_NOT_EXIST; + } + + if (direction == BUS_WRITE) + { + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + memcpy( (uint8_t *)address, data->data, size ); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + if (address == 0) + { + uint32_t resetinst = *( (uint32_t *)data->data ); + + /* CR4_FF_ROM_SHADOW_INDEX_REGISTER */ + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x080, + (uint8_t)1, 0) ); + + /* CR4_FF_ROM_SHADOW_DATA_REGISTER */ + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x084, + (uint8_t)4, resetinst) ); + } + } + else + { + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + memcpy(data->data, (uint8_t *)address, size); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + } + + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_poke_wlan(whd_driver_t whd_driver) +{ + // Not used by M2M bus + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_wakeup(whd_driver_t whd_driver) +{ + WPRINT_WHD_INFO( ("bus_m2m_wakeup\n") ); + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_sleep(whd_driver_t whd_driver) +{ + WPRINT_WHD_INFO( ("bus_m2m_sleep\n") ); + return WHD_SUCCESS; +} + +static uint8_t whd_bus_m2m_backplane_read_padd_size(whd_driver_t whd_driver) +{ + return WHD_BUS_M2M_BACKPLANE_READ_PADD_SIZE; +} + +static whd_result_t whd_bus_m2m_wait_for_wlan_event(whd_driver_t whd_driver, cy_semaphore_t *transceive_semaphore) +{ + whd_result_t result = WHD_SUCCESS; + uint32_t timeout_ms; + + timeout_ms = CY_RTOS_NEVER_TIMEOUT; + + whd_bus_m2m_irq_enable(whd_driver, WHD_TRUE); + result = cy_rtos_get_semaphore(transceive_semaphore, timeout_ms, WHD_FALSE); + + return result; +} + +static whd_bool_t whd_bus_m2m_use_status_report_scheme(whd_driver_t whd_driver) +{ + /* !M2M_RX_POLL_MODE */ + return WHD_FALSE; +} + +static uint32_t whd_bus_m2m_get_max_transfer_size(whd_driver_t whd_driver) +{ + return WHD_BUS_M2M_MAX_BACKPLANE_TRANSFER_SIZE; +} + +static void whd_bus_m2m_init_stats(whd_driver_t whd_driver) +{ + /* To be implemented */ +} + +static whd_result_t whd_bus_m2m_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print) +{ + /* To be implemented */ + UNUSED_VARIABLE(reset_after_print); + WPRINT_MACRO( ("Bus stats not available\n") ); + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_m2m_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware) +{ + UNUSED_PARAMETER(wake_from_firmware); + /* functionality is only currently needed and present on SDIO */ + return WHD_UNSUPPORTED; +} + +static whd_result_t whd_bus_m2m_irq_register(whd_driver_t whd_driver) +{ + return WHD_TRUE; +} + +static whd_result_t whd_bus_m2m_irq_enable(whd_driver_t whd_driver, whd_bool_t enable) +{ + if (enable) + { + WPRINT_WHD_INFO( ("M2M interrupt enable\n") ); + _cyhal_system_m2m_enable_irq(); + _cyhal_system_sw0_enable_irq(); + } + else + { + WPRINT_WHD_INFO( ("M2M interrupt disable\n") ); + _cyhal_system_m2m_disable_irq(); + _cyhal_system_sw0_disable_irq(); + } + return WHD_TRUE; +} + +whd_result_t m2m_bus_write_wifi_firmware_image(whd_driver_t whd_driver) +{ + /* Halt ARM and remove from reset */ + WPRINT_WHD_INFO( ("Reset wlan core..\n") ); + VERIFY_RESULT(whd_reset_device_core(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_CPU_HALT) ); + + return whd_bus_write_wifi_firmware_image(whd_driver); +} + +static whd_result_t boot_wlan(whd_driver_t whd_driver) +{ + whd_result_t result = WHD_SUCCESS; + + /* Load wlan firmware from sflash */ + result = m2m_bus_write_wifi_firmware_image(whd_driver); + if ( (result == WHD_UNFINISHED) || (result != WHD_SUCCESS) ) + { + /* for user abort, then put wifi module into known good state */ + return result; + } + + VERIFY_RESULT(whd_bus_m2m_write_wifi_nvram_image(whd_driver) ); + + /* Release ARM core */ + WPRINT_WHD_INFO( ("Release WLAN core..\n") ); + VERIFY_RESULT(whd_wlan_armcore_run(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_NONE) ); + +#if (PLATFORM_BACKPLANE_ON_CPU_CLOCK_ENABLE == 0) + /* + * Wifi firmware initialization will change some BBPLL settings. When backplane clock + * source is not on CPU clock, accessing backplane during that period might wedge the + * ACPU. Running a delay loop in cache can avoid the wedge. At least 3ms is required + * to avoid the problem. + */ + cy_rtos_delay_milliseconds(10); +#endif /* PLATFORM_BACKPLANE_ON_CPU_CLOCK_ENABLE == 0 */ + + return result; +} + +static whd_result_t whd_bus_m2m_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, + uint32_t image_size) +{ + whd_result_t result = WHD_SUCCESS; + uint32_t size_out; + uint32_t reset_instr = 0; + + CHECK_RETURN(whd_resource_read(whd_driver, resource, 0, + GET_C_VAR(whd_driver, CHIP_RAM_SIZE), &size_out, + (uint8_t *)(address) ) ); + + CHECK_RETURN(whd_resource_read(whd_driver, resource, 0, 4, &size_out, &reset_instr) ); + + /* CR4_FF_ROM_SHADOW_INDEX_REGISTER */ + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x080, + (uint8_t)1, 0) ); + + /* CR4_FF_ROM_SHADOW_DATA_REGISTER */ + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x084, + (uint8_t)4, reset_instr) ); + + return result; +} + +static whd_result_t whd_bus_m2m_write_wifi_nvram_image(whd_driver_t whd_driver) +{ + uint32_t nvram_size; + uint32_t nvram_destination_address; + uint32_t nvram_size_in_words; + uint32_t size_out; + uint32_t image_size; + + /* Get the size of the variable image */ + CHECK_RETURN(whd_resource_size(whd_driver, WHD_RESOURCE_WLAN_NVRAM, &image_size) ); + + /* Round up the size of the image */ + nvram_size = ROUND_UP(image_size, 4); + + /* Put the NVRAM image at the end of RAM leaving the last 4 bytes for the size */ + nvram_destination_address = (GET_C_VAR(whd_driver, CHIP_RAM_SIZE) - 4) - nvram_size; + nvram_destination_address += GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS); + + /* Write NVRAM image into WLAN RAM */ + CHECK_RETURN(whd_resource_read(whd_driver, WHD_RESOURCE_WLAN_NVRAM, 0, + image_size, &size_out, (uint8_t *)nvram_destination_address) ); + + + /* Calculate the NVRAM image size in words (multiples of 4 bytes) and its bitwise inverse */ + nvram_size_in_words = nvram_size / 4; + nvram_size_in_words = (~nvram_size_in_words << 16) | (nvram_size_in_words & 0x0000FFFF); + + memcpy( (uint8_t *)(GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS) + GET_C_VAR(whd_driver, CHIP_RAM_SIZE) - 4), + (uint8_t *)&nvram_size_in_words, 4 ); + + return WHD_SUCCESS; +} + +whd_result_t whd_bus_m2m_set_backplane_window(whd_driver_t whd_driver, uint32_t addr, uint32_t *cur_addr) +{ + return WHD_UNSUPPORTED; +} + +whd_bool_t whd_ensure_wlan_is_up(whd_driver_t whd_driver) +{ + if ( (whd_driver != NULL) && (whd_driver->internal_info.whd_wlan_status.state == WLAN_UP) ) + return WHD_TRUE; + else + return WHD_FALSE; +} + +#endif /* (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_M2M_INTERFACE) */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_m2m_protocol.h b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_m2m_protocol.h new file mode 100644 index 00000000..21b47476 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_m2m_protocol.h @@ -0,0 +1,45 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "whd.h" +#include "bus_protocols/whd_bus_protocol_interface.h" + +#ifndef INCLUDED_M2M_WHD_BUS_PROTOCOL_H +#define INCLUDED_M2M_WHD_BUS_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************** +* Function declarations +******************************************************/ +extern void whd_delayed_bus_release_schedule_update(whd_driver_t whd_driver, whd_bool_t is_scheduled); +#define DELAYED_BUS_RELEASE_SCHEDULE(whd_driver, schedule) \ + do { whd_delayed_bus_release_schedule_update(whd_driver, schedule); } while (0) + + +/****************************************************** +* Global variables +******************************************************/ + + +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif /* ifndef INCLUDED_M2M_WHD_BUS_PROTOCOL_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_protocol_interface.h b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_protocol_interface.h new file mode 100644 index 00000000..742aa66b --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_protocol_interface.h @@ -0,0 +1,145 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cyabs_rtos.h" + +#include "whd.h" +#include "whd_network_types.h" +#include "whd_types_int.h" +#include "whd_resource_api.h" + +#ifndef INCLUDED_WHD_BUS_PROTOCOL_INTERFACE_H_ +#define INCLUDED_WHD_BUS_PROTOCOL_INTERFACE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Constants +******************************************************/ + +typedef enum +{ + BUS_FUNCTION = 0, + BACKPLANE_FUNCTION = 1, + WLAN_FUNCTION = 2 +} whd_bus_function_t; + +#define BUS_FUNCTION_MASK (0x3) /* Update this if adding functions */ +#define WHD_BUS_FAIL (0xFFFFFFFF) + +/****************************************************** +* Macros +******************************************************/ +#define PLATFORM_WLAN_ALLOW_BUS_TO_SLEEP_DELAY_MS 10 + +#define DELAYED_BUS_RELEASE_SCHEDULE(whd_driver, schedule) do { whd_delayed_bus_release_schedule_update(whd_driver, \ + schedule); \ +} while (0) + +/****************************************************** +* Structures +******************************************************/ + +#pragma pack(1) + +typedef struct +{ + uint8_t bus_header[MAX_BUS_HEADER_SIZE]; + uint32_t data[1]; +} whd_transfer_bytes_packet_t; + +#pragma pack() + +typedef void (*whd_bus_irq_callback_t)(void *handler_arg, uint32_t event); + +/****************************************************** +* Function declarations +******************************************************/ + +/* Share bus to BT */ +extern whd_result_t whd_bus_write_reg_value(whd_driver_t whd_driver, uint32_t address, + uint8_t value_length, uint32_t value); +extern whd_result_t whd_bus_read_reg_value(whd_driver_t whd_driver, uint32_t address, + uint8_t value_length, uint8_t *value); +extern whd_result_t whd_bus_mem_bytes(whd_driver_t whd_driver, uint8_t direct, + uint32_t address, uint32_t size, uint8_t *data); +extern whd_driver_t whd_bt_get_whd_driver(void); +extern whd_result_t whd_bus_share_bt_init(whd_driver_t whd_driver); +extern whd_result_t whd_bus_bt_attach(whd_driver_t whd_driver, void *btdata, + void (*bt_int_fun)(void *data) ); +extern void whd_bus_bt_detach(whd_driver_t whd_driver); +extern uint32_t whd_get_bt_info(whd_driver_t whd_drv, whd_bt_info_t bt_info); +/* Initialisation functions */ +extern whd_result_t whd_bus_init(whd_driver_t whd_driver); +extern whd_result_t whd_bus_deinit(whd_driver_t whd_driver); + +/* Device register access functions */ +extern whd_result_t whd_bus_set_backplane_window(whd_driver_t whd_driver, uint32_t addr); +extern whd_result_t whd_bus_write_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint32_t value); +extern whd_result_t whd_bus_read_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint8_t *value); +extern whd_result_t whd_bus_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function, uint32_t address, + uint8_t value_length, uint32_t value); +extern whd_result_t whd_bus_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function, uint32_t address, + uint8_t value_length, uint8_t *value); + +/* Device data transfer functions */ +extern whd_result_t whd_bus_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer); +extern whd_result_t whd_bus_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t size, + whd_transfer_bytes_packet_t *data); + +/* Frame transfer function */ +extern whd_result_t whd_bus_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer); + +extern uint32_t whd_bus_packet_available_to_read(whd_driver_t whd_driver); +extern whd_result_t whd_bus_poke_wlan(whd_driver_t whd_driver); +extern whd_result_t whd_bus_wait_for_wlan_event(whd_driver_t whd_driver, cy_semaphore_t *transceive_semaphore); + +extern whd_result_t whd_bus_ack_interrupt(whd_driver_t whd_driver, uint32_t intstatus); +extern whd_bool_t whd_bus_wake_interrupt_present(whd_driver_t whd_driver); + +extern whd_result_t whd_bus_set_flow_control(whd_driver_t whd_driver, uint8_t value); +extern whd_bool_t whd_bus_is_flow_controlled(whd_driver_t whd_driver); + +extern whd_result_t whd_bus_wakeup(whd_driver_t whd_driver); +extern whd_result_t whd_bus_sleep(whd_driver_t whd_driver); + +extern uint8_t whd_bus_backplane_read_padd_size(whd_driver_t whd_driver); +extern whd_bool_t whd_bus_use_status_report_scheme(whd_driver_t whd_driver); +extern uint32_t whd_bus_get_max_transfer_size(whd_driver_t whd_driver); + +extern void whd_bus_init_stats(whd_driver_t whd_driver); +extern whd_result_t whd_bus_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print); +extern whd_result_t whd_bus_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware); +extern whd_result_t whd_bus_irq_enable(whd_driver_t whd_driver, whd_bool_t enable); +extern whd_result_t whd_bus_irq_register(whd_driver_t whd_driver); +extern whd_result_t whd_bus_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, uint32_t image_size); +/****************************************************** +* Global variables +******************************************************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_BUS_PROTOCOL_INTERFACE_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.c b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.c new file mode 100644 index 00000000..522d6989 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.c @@ -0,0 +1,1797 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Broadcom WLAN SDIO Protocol interface + * + * Implements the WHD Bus Protocol Interface for SDIO + * Provides functions for initialising, de-intitialising 802.11 device, + * sending/receiving raw packets etc + */ + +#include +#include "cybsp.h" +#if (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SDIO_INTERFACE) + +#include "cyabs_rtos.h" +#include "cyhal_sdio.h" +#include "cyhal_gpio.h" + +#include "whd_bus_sdio_protocol.h" +#include "whd_bus.h" +#include "whd_bus_common.h" +#include "whd_chip_reg.h" +#include "whd_chip_constants.h" +#include "whd_int.h" +#include "whd_chip.h" +#include "whd_sdpcm.h" +#include "whd_debug.h" +#include "whd_sdio.h" +#include "whd_buffer_api.h" +#include "whd_resource_if.h" +#include "whd_types_int.h" +#include "whd_types.h" + + +/****************************************************** +* Constants +******************************************************/ +/* function 1 OCP space */ +#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */ +#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 +#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */ + +#define F0_WORKING_TIMEOUT_MS (500) +#define F1_AVAIL_TIMEOUT_MS (500) +#define F2_AVAIL_TIMEOUT_MS (500) +#define F2_READY_TIMEOUT_MS (1000) +#define ALP_AVAIL_TIMEOUT_MS (100) +#define HT_AVAIL_TIMEOUT_MS (500) +#define ABORT_TIMEOUT_MS (100) +/* Taken from FALCON_5_90_195_26 dhd/sys/dhd_sdio.c. */ +#define SDIO_F2_WATERMARK (8) + +#define INITIAL_READ 4 + +#define WHD_THREAD_POLL_TIMEOUT (CY_RTOS_NEVER_TIMEOUT) + +#define WHD_THREAD_POKE_TIMEOUT (100) + +#define HOSTINTMASK (I_HMB_SW_MASK) + + +/****************************************************** +* Structures +******************************************************/ +struct whd_bus_priv +{ + whd_sdio_config_t sdio_config; + whd_bus_stats_t whd_bus_stats; + cyhal_sdio_t *sdio_obj; + +}; + +/* For BSP backward compatible, should be removed the macro once 1.0 is not supported */ +#if (CYHAL_API_VERSION >= 2) +typedef cyhal_sdio_transfer_type_t cyhal_sdio_transfer_t; +#else +typedef cyhal_transfer_t cyhal_sdio_transfer_t; +#endif +/****************************************************** +* Variables +******************************************************/ + +/****************************************************** +* Static Function Declarations +******************************************************/ + +static whd_result_t whd_bus_sdio_transfer(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t data_size, + uint8_t *data, sdio_response_needed_t response_expected); +static whd_result_t whd_bus_sdio_cmd52(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint8_t value, + sdio_response_needed_t response_expected, uint8_t *response); +static whd_result_t whd_bus_sdio_cmd53(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, sdio_transfer_mode_t mode, uint32_t address, + uint16_t data_size, uint8_t *data, + sdio_response_needed_t response_expected, + uint32_t *response); +static whd_result_t whd_bus_sdio_abort_read(whd_driver_t whd_driver, whd_bool_t retry); +static whd_result_t whd_bus_sdio_download_firmware(whd_driver_t whd_driver); + +static whd_result_t whd_bus_sdio_set_oob_interrupt(whd_driver_t whd_driver, uint8_t gpio_pin_number); +#if (CYHAL_API_VERSION >= 2) +static void whd_bus_sdio_irq_handler(void *handler_arg, cyhal_sdio_event_t event); +static void whd_bus_sdio_oob_irq_handler(void *arg, cyhal_gpio_event_t event); +#else +static void whd_bus_sdio_irq_handler(void *handler_arg, cyhal_sdio_irq_event_t event); +static void whd_bus_sdio_oob_irq_handler(void *arg, cyhal_gpio_irq_event_t event); +#endif +static whd_result_t whd_bus_sdio_irq_register(whd_driver_t whd_driver); +static whd_result_t whd_bus_sdio_irq_enable(whd_driver_t whd_driver, whd_bool_t enable); +static whd_result_t whd_bus_sdio_init_oob_intr(whd_driver_t whd_driver); +static whd_result_t whd_bus_sdio_deinit_oob_intr(whd_driver_t whd_driver); +static whd_result_t whd_bus_sdio_register_oob_intr(whd_driver_t whd_driver); +static whd_result_t whd_bus_sdio_unregister_oob_intr(whd_driver_t whd_driver); +static whd_result_t whd_bus_sdio_enable_oob_intr(whd_driver_t whd_driver, whd_bool_t enable); +static whd_result_t whd_bus_sdio_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, uint32_t image_size); +static whd_result_t whd_bus_sdio_write_wifi_nvram_image(whd_driver_t whd_driver); +/****************************************************** +* Global Function definitions +******************************************************/ + +uint32_t whd_bus_sdio_attach(whd_driver_t whd_driver, whd_sdio_config_t *whd_sdio_config, cyhal_sdio_t *sdio_obj) +{ + struct whd_bus_info *whd_bus_info; + + if (!whd_driver || !whd_sdio_config) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + whd_bus_info = (whd_bus_info_t *)malloc(sizeof(whd_bus_info_t) ); + + if (whd_bus_info == NULL) + { + WPRINT_WHD_ERROR( ("Memory allocation failed for whd_bus_info in %s\n", __FUNCTION__) ); + return WHD_BUFFER_UNAVAILABLE_PERMANENT; + } + memset(whd_bus_info, 0, sizeof(whd_bus_info_t) ); + + whd_driver->bus_if = whd_bus_info; + + whd_driver->bus_priv = (struct whd_bus_priv *)malloc(sizeof(struct whd_bus_priv) ); + + if (whd_driver->bus_priv == NULL) + { + WPRINT_WHD_ERROR( ("Memory allocation failed for whd_bus_priv in %s\n", __FUNCTION__) ); + return WHD_BUFFER_UNAVAILABLE_PERMANENT; + } + memset(whd_driver->bus_priv, 0, sizeof(struct whd_bus_priv) ); + + whd_driver->bus_priv->sdio_obj = sdio_obj; + whd_driver->bus_priv->sdio_config = *whd_sdio_config; + + whd_bus_info->whd_bus_init_fptr = whd_bus_sdio_init; + whd_bus_info->whd_bus_deinit_fptr = whd_bus_sdio_deinit; + + whd_bus_info->whd_bus_write_backplane_value_fptr = whd_bus_sdio_write_backplane_value; + whd_bus_info->whd_bus_read_backplane_value_fptr = whd_bus_sdio_read_backplane_value; + whd_bus_info->whd_bus_write_register_value_fptr = whd_bus_sdio_write_register_value; + whd_bus_info->whd_bus_read_register_value_fptr = whd_bus_sdio_read_register_value; + + whd_bus_info->whd_bus_send_buffer_fptr = whd_bus_sdio_send_buffer; + whd_bus_info->whd_bus_transfer_bytes_fptr = whd_bus_sdio_transfer_bytes; + + whd_bus_info->whd_bus_read_frame_fptr = whd_bus_sdio_read_frame; + + whd_bus_info->whd_bus_packet_available_to_read_fptr = whd_bus_sdio_packet_available_to_read; + whd_bus_info->whd_bus_poke_wlan_fptr = whd_bus_sdio_poke_wlan; + whd_bus_info->whd_bus_wait_for_wlan_event_fptr = whd_bus_sdio_wait_for_wlan_event; + + whd_bus_info->whd_bus_ack_interrupt_fptr = whd_bus_sdio_ack_interrupt; + whd_bus_info->whd_bus_wake_interrupt_present_fptr = whd_bus_sdio_wake_interrupt_present; + + whd_bus_info->whd_bus_wakeup_fptr = whd_bus_sdio_wakeup; + whd_bus_info->whd_bus_sleep_fptr = whd_bus_sdio_sleep; + + whd_bus_info->whd_bus_backplane_read_padd_size_fptr = whd_bus_sdio_backplane_read_padd_size; + whd_bus_info->whd_bus_use_status_report_scheme_fptr = whd_bus_sdio_use_status_report_scheme; + + whd_bus_info->whd_bus_get_max_transfer_size_fptr = whd_bus_sdio_get_max_transfer_size; + + whd_bus_info->whd_bus_init_stats_fptr = whd_bus_sdio_init_stats; + whd_bus_info->whd_bus_print_stats_fptr = whd_bus_sdio_print_stats; + whd_bus_info->whd_bus_reinit_stats_fptr = whd_bus_sdio_reinit_stats; + whd_bus_info->whd_bus_irq_register_fptr = whd_bus_sdio_irq_register; + whd_bus_info->whd_bus_irq_enable_fptr = whd_bus_sdio_irq_enable; + whd_bus_info->whd_bus_download_resource_fptr = whd_bus_sdio_download_resource; + whd_bus_info->whd_bus_set_backplane_window_fptr = whd_bus_sdio_set_backplane_window; + return WHD_SUCCESS; +} + +void whd_bus_sdio_detach(whd_driver_t whd_driver) +{ + if (whd_driver->bus_if != NULL) + { + free(whd_driver->bus_if); + whd_driver->bus_if = NULL; + } + if (whd_driver->bus_priv != NULL) + { + free(whd_driver->bus_priv); + whd_driver->bus_priv = NULL; + } +} + +whd_result_t whd_bus_sdio_ack_interrupt(whd_driver_t whd_driver, uint32_t intstatus) +{ + return whd_bus_write_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, intstatus); +} + +whd_result_t whd_bus_sdio_wait_for_wlan_event(whd_driver_t whd_driver, cy_semaphore_t *transceive_semaphore) +{ + whd_result_t result = WHD_SUCCESS; + uint32_t timeout_ms = 1; + uint32_t delayed_release_timeout_ms; + + REFERENCE_DEBUG_ONLY_VARIABLE(result); + + delayed_release_timeout_ms = whd_bus_handle_delayed_release(whd_driver); + if (delayed_release_timeout_ms != 0) + { + timeout_ms = delayed_release_timeout_ms; + } + else + { + result = whd_allow_wlan_bus_to_sleep(whd_driver); + whd_assert("Error setting wlan sleep", (result == WHD_SUCCESS) || (result == WHD_PENDING) ); + + if (result == WHD_SUCCESS) + { + timeout_ms = CY_RTOS_NEVER_TIMEOUT; + } + } + + /* Check if we have run out of bus credits */ + if ( (whd_sdpcm_has_tx_packet(whd_driver) == WHD_TRUE) && (whd_sdpcm_get_available_credits(whd_driver) == 0) ) + { + /* Keep poking the WLAN until it gives us more credits */ + result = whd_bus_poke_wlan(whd_driver); + whd_assert("Poking failed!", result == WHD_SUCCESS); + + result = cy_rtos_get_semaphore(transceive_semaphore, (uint32_t)MIN_OF(timeout_ms, + WHD_THREAD_POKE_TIMEOUT), WHD_FALSE); + } + else + { + result = cy_rtos_get_semaphore(transceive_semaphore, (uint32_t)MIN_OF(timeout_ms, + WHD_THREAD_POLL_TIMEOUT), WHD_FALSE); + } + whd_assert("Could not get whd sleep semaphore\n", (result == CY_RSLT_SUCCESS) || (result == CY_RTOS_TIMEOUT) ); + + return result; +} + +/* Device data transfer functions */ +whd_result_t whd_bus_sdio_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + whd_result_t retval; + retval = + whd_bus_transfer_bytes(whd_driver, BUS_WRITE, WLAN_FUNCTION, 0, + (uint16_t)(whd_buffer_get_current_piece_size(whd_driver, + buffer) - sizeof(whd_buffer_t) ), + (whd_transfer_bytes_packet_t *)(whd_buffer_get_current_piece_data_pointer(whd_driver, + buffer) + + sizeof(whd_buffer_t) ) ); + CHECK_RETURN(whd_buffer_release(whd_driver, buffer, WHD_NETWORK_TX) ); + if (retval == WHD_SUCCESS) + { + DELAYED_BUS_RELEASE_SCHEDULE(whd_driver, WHD_TRUE); + } + CHECK_RETURN (retval); + + return WHD_SUCCESS; +} + +whd_result_t whd_bus_sdio_init(whd_driver_t whd_driver) +{ + uint8_t byte_data; + whd_result_t result; + uint32_t loop_count; + whd_time_t elapsed_time, current_time; + uint32_t wifi_firmware_image_size = 0; + uint16_t chip_id; + uint8_t *aligned_addr = NULL; + + whd_bus_set_flow_control(whd_driver, WHD_FALSE); + + whd_bus_init_backplane_window(whd_driver); + + /* Setup the backplane*/ + loop_count = 0; + do + { + /* Enable function 1 (backplane) */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1, + SDIO_FUNC_ENABLE_1) ); + if (loop_count != 0) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + } + CHECK_RETURN(whd_bus_read_register_value (whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1, &byte_data) ); + loop_count++; + if (loop_count >= (uint32_t)F0_WORKING_TIMEOUT_MS) + { + WPRINT_WHD_ERROR( ("Timeout while setting up the backplane, %s failed at %d \n", __func__, __LINE__) ); + return WHD_TIMEOUT; + } + } while (byte_data != (uint8_t)SDIO_FUNC_ENABLE_1); + + if (whd_driver->bus_priv->sdio_config.sdio_1bit_mode == WHD_FALSE) + { + /* Read the bus width and set to 4 bits */ + CHECK_RETURN(whd_bus_read_register_value (whd_driver, BUS_FUNCTION, SDIOD_CCCR_BICTRL, (uint8_t)1, + &byte_data) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_BICTRL, (uint8_t)1, + (byte_data & (~BUS_SD_DATA_WIDTH_MASK) ) | + BUS_SD_DATA_WIDTH_4BIT) ); + /* NOTE: We don't need to change our local bus settings since we're not sending any data (only using CMD52) + * until after we change the bus speed further down */ + } + + /* Set the block size */ + + /* Wait till the backplane is ready */ + loop_count = 0; + while ( ( (result = whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_BLKSIZE_0, (uint8_t)1, + (uint32_t)SDIO_64B_BLOCK) ) == WHD_SUCCESS ) && + ( (result = whd_bus_read_register_value (whd_driver, BUS_FUNCTION, SDIOD_CCCR_BLKSIZE_0, (uint8_t)1, + &byte_data) ) == WHD_SUCCESS ) && + (byte_data != (uint8_t)SDIO_64B_BLOCK) && + (loop_count < (uint32_t)F0_WORKING_TIMEOUT_MS) ) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + loop_count++; + if (loop_count >= (uint32_t)F0_WORKING_TIMEOUT_MS) + { + /* If the system fails here, check the high frequency crystal is working */ + WPRINT_WHD_ERROR( ("Timeout while setting block size, %s failed at %d \n", __func__, __LINE__) ); + return WHD_TIMEOUT; + } + } + + CHECK_RETURN(result); + + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_BLKSIZE_0, (uint8_t)1, + (uint32_t)SDIO_64B_BLOCK) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_F1BLKSIZE_0, (uint8_t)1, + (uint32_t)SDIO_64B_BLOCK) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_F2BLKSIZE_0, (uint8_t)1, + (uint32_t)SDIO_64B_BLOCK) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_F2BLKSIZE_1, (uint8_t)1, + (uint32_t)0) ); /* Function 2 = 64 */ + + /* Register interrupt handler*/ + whd_bus_sdio_irq_register(whd_driver); + /* Enable SDIO IRQ */ + whd_bus_sdio_irq_enable(whd_driver, WHD_TRUE); + + /* Enable/Disable Client interrupts */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_INTEN, (uint8_t)1, + INTR_CTL_MASTER_EN | INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN) ); + + if (whd_driver->bus_priv->sdio_config.high_speed_sdio_clock) + { + /* This code is required if we want more than 25 MHz clock */ + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_SPEED_CONTROL, 1, &byte_data) ); + if ( (byte_data & 0x1) != 0 ) + { + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_SPEED_CONTROL, 1, + byte_data | SDIO_SPEED_EHS) ); + } + else + { + WPRINT_WHD_ERROR( ("Error reading bus register, %s failed at %d \n", __func__, __LINE__) ); + return WHD_BUS_READ_REGISTER_ERROR; + } + }/* HIGH_SPEED_SDIO_CLOCK */ + + + + /* Wait till the backplane is ready */ + loop_count = 0; + while ( ( (result = whd_bus_read_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IORDY, (uint8_t)1, + &byte_data) ) == WHD_SUCCESS ) && + ( (byte_data & SDIO_FUNC_READY_1) == 0 ) && + (loop_count < (uint32_t)F1_AVAIL_TIMEOUT_MS) ) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + loop_count++; + } + if (loop_count >= (uint32_t)F1_AVAIL_TIMEOUT_MS) + { + WPRINT_WHD_ERROR( ("Timeout while waiting for backplane to be ready\n") ); + return WHD_TIMEOUT; + } + CHECK_RETURN(result); + + /* Set the ALP */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, + (uint32_t)(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ | + SBSDIO_FORCE_ALP) ) ); + + loop_count = 0; + while ( ( (result = whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, + &byte_data) ) == WHD_SUCCESS ) && + ( (byte_data & SBSDIO_ALP_AVAIL) == 0 ) && + (loop_count < (uint32_t)ALP_AVAIL_TIMEOUT_MS) ) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + loop_count++; + } + if (loop_count >= (uint32_t)ALP_AVAIL_TIMEOUT_MS) + { + WPRINT_WHD_ERROR( ("Timeout while waiting for alp clock\n") ); + return WHD_TIMEOUT; + } + CHECK_RETURN(result); + + /* Clear request for ALP */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, 0) ); + + /* Disable the extra SDIO pull-ups */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_PULL_UP, (uint8_t)1, 0) ); + /* Enable F1 and F2 */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1, + SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2) ); + + /* Setup host-wake signals */ + CHECK_RETURN(whd_bus_sdio_init_oob_intr(whd_driver) ); + + /* Enable F2 interrupt only */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_INTEN, (uint8_t)1, + INTR_CTL_MASTER_EN | INTR_CTL_FUNC2_EN) ); + + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IORDY, (uint8_t)1, &byte_data) ); + + /* Read the chip id */ + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, CHIPCOMMON_BASE_ADDRESS, 2, (uint8_t *)&chip_id) ); + whd_chip_set_chip_id(whd_driver, chip_id); + + cy_rtos_get_time(&elapsed_time); + result = whd_bus_sdio_download_firmware(whd_driver); + cy_rtos_get_time(¤t_time); + elapsed_time = current_time - elapsed_time; + CHECK_RETURN(whd_resource_size(whd_driver, WHD_RESOURCE_WLAN_FIRMWARE, &wifi_firmware_image_size) ); + WPRINT_WHD_INFO( ("WLAN FW download size: %" PRIu32 " bytes\n", wifi_firmware_image_size) ); + WPRINT_WHD_INFO( ("WLAN FW download time: %" PRIu32 " ms\n", elapsed_time) ); + + if (result != WHD_SUCCESS) + { + /* either an error or user abort */ + WPRINT_WHD_ERROR( ("SDIO firmware download error, %s failed at %d \n", __func__, __LINE__) ); + return result; + } + + /* Wait for F2 to be ready */ + loop_count = 0; + while ( ( (result = whd_bus_read_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IORDY, (uint8_t)1, + &byte_data) ) == WHD_SUCCESS ) && + ( (byte_data & SDIO_FUNC_READY_2) == 0 ) && + (loop_count < (uint32_t)F2_READY_TIMEOUT_MS) ) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + loop_count++; + } + if (loop_count >= (uint32_t)F2_READY_TIMEOUT_MS) + { + /* If your system fails here, it could be due to incorrect NVRAM variables. + * Check which 'wifi_nvram_image.h' file your platform is using, and + * check that it matches the WLAN device on your platform, including the + * crystal frequency. + */ + WPRINT_WHD_ERROR( ("Timeout while waiting for function 2 to be ready\n") ); + /* Reachable after hitting assert */ + return WHD_TIMEOUT; + } + if (whd_driver->aligned_addr == NULL) + { + if ( (aligned_addr = malloc(WHD_LINK_MTU) ) == NULL ) + { + WPRINT_WHD_ERROR( ("Memory allocation failed for aligned_addr in %s \n", __FUNCTION__) ); + return WHD_MALLOC_FAILURE; + } + whd_driver->aligned_addr = aligned_addr; + } + result = whd_chip_specific_init(whd_driver); + if (result != WHD_SUCCESS) + { + free(whd_driver->aligned_addr); + whd_driver->aligned_addr = NULL; + } + CHECK_RETURN(result); + result = whd_ensure_wlan_bus_is_up(whd_driver); + if (result != WHD_SUCCESS) + { + free(whd_driver->aligned_addr); + whd_driver->aligned_addr = NULL; + } + CHECK_RETURN(result); +#if (CYHAL_API_VERSION >= 2) + cyhal_sdio_enable_event(whd_driver->bus_priv->sdio_obj, CYHAL_SDIO_CARD_INTERRUPT, CYHAL_ISR_PRIORITY_DEFAULT, + WHD_TRUE); +#else + cyhal_sdio_irq_enable(whd_driver->bus_priv->sdio_obj, CYHAL_SDIO_CARD_INTERRUPT, WHD_TRUE); +#endif + UNUSED_PARAMETER(elapsed_time); + return result; +} + +whd_result_t whd_bus_sdio_deinit(whd_driver_t whd_driver) +{ + if (whd_driver->aligned_addr) + { + free(whd_driver->aligned_addr); + whd_driver->aligned_addr = NULL; + } + + CHECK_RETURN(whd_bus_sdio_deinit_oob_intr(whd_driver) ); +#if (CYHAL_API_VERSION >= 2) + cyhal_sdio_enable_event(whd_driver->bus_priv->sdio_obj, CYHAL_SDIO_CARD_INTERRUPT, CYHAL_ISR_PRIORITY_DEFAULT, + WHD_FALSE); +#else + cyhal_sdio_irq_enable(whd_driver->bus_priv->sdio_obj, CYHAL_SDIO_CARD_INTERRUPT, WHD_FALSE); +#endif + + CHECK_RETURN(whd_allow_wlan_bus_to_sleep(whd_driver) ); + whd_bus_set_resource_download_halt(whd_driver, WHD_FALSE); + + DELAYED_BUS_RELEASE_SCHEDULE(whd_driver, WHD_FALSE); + + return WHD_SUCCESS; +} + +whd_bool_t whd_bus_sdio_wake_interrupt_present(whd_driver_t whd_driver) +{ + uint32_t int_status = 0; + + /* Ensure the wlan backplane bus is up */ + if (WHD_SUCCESS != whd_ensure_wlan_bus_is_up(whd_driver) ) + return WHD_FALSE; + + if (whd_bus_read_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, + (uint8_t *)&int_status) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error reading interrupt status\n", __FUNCTION__) ); + goto exit; + } + if ( (I_HMB_HOST_INT & int_status) != 0 ) + { + /* Clear any interrupts */ + if (whd_bus_write_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, + I_HMB_HOST_INT) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error clearing interrupts\n", __FUNCTION__) ); + goto exit; + } + if (whd_bus_read_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, + (uint8_t *)&int_status) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error reading interrupt status\n", __FUNCTION__) ); + goto exit; + } + WPRINT_WHD_DEBUG( ("whd_bus_sdio_wake_interrupt_present after clearing int_status = [%x]\n", + (uint8_t)int_status) ); + return WHD_TRUE; + } +exit: + return WHD_FALSE; +} + +uint32_t whd_bus_sdio_packet_available_to_read(whd_driver_t whd_driver) +{ + uint32_t int_status = 0; + uint32_t hmb_data = 0; + uint8_t error_type = 0; + whd_bt_dev_t btdev = whd_driver->bt_dev; + + /* Ensure the wlan backplane bus is up */ + CHECK_RETURN(whd_ensure_wlan_bus_is_up(whd_driver) ); + + /* Read the IntStatus */ + if (whd_bus_read_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, + (uint8_t *)&int_status) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error reading interrupt status\n", __FUNCTION__) ); + int_status = 0; + return WHD_BUS_FAIL; + } + + if ( (I_HMB_HOST_INT & int_status) != 0 ) + { + /* Read mailbox data and ack that we did so */ + if (whd_bus_read_backplane_value(whd_driver, SDIO_TO_HOST_MAILBOX_DATA(whd_driver), 4, + (uint8_t *)&hmb_data) == WHD_SUCCESS) + if (whd_bus_write_backplane_value(whd_driver, SDIO_TO_SB_MAILBOX(whd_driver), (uint8_t)4, + SMB_INT_ACK) != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("%s: Failed writing SMB_INT_ACK\n", __FUNCTION__) ); + + /* dongle indicates the firmware has halted/crashed */ + if ( (I_HMB_DATA_FWHALT & hmb_data) != 0 ) + { + WPRINT_WHD_ERROR( ("%s: mailbox indicates firmware halted\n", __FUNCTION__) ); + whd_wifi_print_whd_log(whd_driver); + error_type = WLC_ERR_FW; + whd_set_error_handler_locally(whd_driver, &error_type, NULL, NULL, NULL); + } + } + if (btdev && btdev->bt_int_cb) + { + if ( (I_HMB_FC_CHANGE & int_status) != 0 ) + { + btdev->bt_int_cb(btdev->bt_data); + int_status = 0; + } + } + + if ( (HOSTINTMASK & int_status) != 0 ) + { + /* Clear any interrupts */ + if (whd_bus_write_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, + int_status & HOSTINTMASK) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error clearing interrupts\n", __FUNCTION__) ); + int_status = 0; + goto exit; + } + } +exit: + return ( (int_status) & (FRAME_AVAILABLE_MASK) ); +} + +/* + * From internal documentation: hwnbu-twiki/SdioMessageEncapsulation + * When data is available on the device, the device will issue an interrupt: + * - the device should signal the interrupt as a hint that one or more data frames may be available on the device for reading + * - the host may issue reads of the 4 byte length tag at any time -- that is, whether an interupt has been issued or not + * - if a frame is available, the tag read should return a nonzero length (>= 4) and the host can then read the remainder of the frame by issuing one or more CMD53 reads + * - if a frame is not available, the 4byte tag read should return zero + */ +whd_result_t whd_bus_sdio_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer) +{ + uint16_t hwtag[8]; + uint16_t extra_space_required; + whd_result_t result; + uint8_t *data = NULL; + + *buffer = NULL; + + /* Ensure the wlan backplane bus is up */ + CHECK_RETURN(whd_ensure_wlan_bus_is_up(whd_driver) ); + + /* Read the frame header and verify validity */ + memset(hwtag, 0, sizeof(hwtag) ); + + result = whd_bus_sdio_transfer(whd_driver, BUS_READ, WLAN_FUNCTION, 0, (uint16_t)INITIAL_READ, (uint8_t *)hwtag, + RESPONSE_NEEDED); + if (result != WHD_SUCCESS) + { + (void)whd_bus_sdio_abort_read(whd_driver, WHD_FALSE); /* ignore return - not much can be done if this fails */ + WPRINT_WHD_ERROR( ("Error during SDIO receive, %s failed at %d \n", __func__, __LINE__) ); + return WHD_SDIO_RX_FAIL; + } + + if ( ( (hwtag[0] | hwtag[1]) == 0 ) || + ( (hwtag[0] ^ hwtag[1]) != (uint16_t)0xFFFF ) ) + { + return WHD_HWTAG_MISMATCH; + } + + if ( (hwtag[0] == (uint16_t)12) && + (whd_driver->internal_info.whd_wlan_status.state == WLAN_UP) ) + { + result = whd_bus_sdio_transfer(whd_driver, BUS_READ, WLAN_FUNCTION, 0, (uint16_t)8, (uint8_t *)&hwtag[2], + RESPONSE_NEEDED); + if (result != WHD_SUCCESS) + { + /* ignore return - not much can be done if this fails */ + (void)whd_bus_sdio_abort_read(whd_driver, WHD_FALSE); + WPRINT_WHD_ERROR( ("Error during SDIO receive, %s failed at %d \n", __func__, __LINE__) ); + return WHD_SDIO_RX_FAIL; + } + whd_sdpcm_update_credit(whd_driver, (uint8_t *)hwtag); + return WHD_SUCCESS; + } + + /* Calculate the space we need to store entire packet */ + if ( (hwtag[0] > (uint16_t)INITIAL_READ) ) + { + extra_space_required = (uint16_t)(hwtag[0] - (uint16_t)INITIAL_READ); + } + else + { + extra_space_required = 0; + } + + /* Allocate a suitable buffer */ + result = whd_host_buffer_get(whd_driver, buffer, WHD_NETWORK_RX, + (uint16_t)(INITIAL_READ + extra_space_required + sizeof(whd_buffer_header_t) ), + (whd_sdpcm_has_tx_packet(whd_driver) ? 0 : WHD_RX_BUF_TIMEOUT) ); + if (result != WHD_SUCCESS) + { + /* Read out the first 12 bytes to get the bus credit information, 4 bytes are already read in hwtag */ + whd_assert("Get buffer error", + ( (result == WHD_BUFFER_UNAVAILABLE_TEMPORARY) || (result == WHD_BUFFER_UNAVAILABLE_PERMANENT) ) ); + result = whd_bus_sdio_transfer(whd_driver, BUS_READ, WLAN_FUNCTION, 0, (uint16_t)8, (uint8_t *)&hwtag[2], + RESPONSE_NEEDED); + if (result != WHD_SUCCESS) + { + /* ignore return - not much can be done if this fails */ + (void)whd_bus_sdio_abort_read(whd_driver, WHD_FALSE); + WPRINT_WHD_ERROR( ("Error during SDIO receive, %s failed at %d \n", __func__, __LINE__) ); + return WHD_SDIO_RX_FAIL; + } + result = whd_bus_sdio_abort_read(whd_driver, WHD_FALSE); + whd_assert("Read-abort failed", result == WHD_SUCCESS); + REFERENCE_DEBUG_ONLY_VARIABLE(result); + + whd_sdpcm_update_credit(whd_driver, (uint8_t *)hwtag); + WPRINT_WHD_ERROR( ("Failed to allocate a buffer to receive into, %s failed at %d \n", __func__, __LINE__) ); + return WHD_RX_BUFFER_ALLOC_FAIL; + } + data = whd_buffer_get_current_piece_data_pointer(whd_driver, *buffer); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + /* Copy the data already read */ + memcpy(data + sizeof(whd_buffer_header_t), hwtag, (size_t)INITIAL_READ); + + /* Read the rest of the data */ + if (extra_space_required > 0) + { + data = whd_buffer_get_current_piece_data_pointer(whd_driver, *buffer); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + result = whd_bus_sdio_transfer(whd_driver, BUS_READ, WLAN_FUNCTION, 0, extra_space_required, + data + sizeof(whd_buffer_header_t) + + INITIAL_READ, RESPONSE_NEEDED); + + if (result != WHD_SUCCESS) + { + (void)whd_bus_sdio_abort_read(whd_driver, WHD_FALSE); /* ignore return - not much can be done if this fails */ + CHECK_RETURN(whd_buffer_release(whd_driver, *buffer, WHD_NETWORK_RX) ); + WPRINT_WHD_ERROR( ("Error during SDIO receive, %s failed at %d \n", __func__, __LINE__) ); + return WHD_SDIO_RX_FAIL; + } + } + DELAYED_BUS_RELEASE_SCHEDULE(whd_driver, WHD_TRUE); + return WHD_SUCCESS; +} + +/****************************************************** +* Function definitions for Protocol Common +******************************************************/ + +/* Device register access functions */ +whd_result_t whd_bus_sdio_write_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint32_t value) +{ + CHECK_RETURN(whd_bus_set_backplane_window(whd_driver, address) ); + + address &= SBSDIO_SB_OFT_ADDR_MASK; + + if (register_length == 4) + address |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + CHECK_RETURN(whd_bus_sdio_transfer(whd_driver, BUS_WRITE, BACKPLANE_FUNCTION, address, register_length, + (uint8_t *)&value, RESPONSE_NEEDED) ); + + return whd_bus_set_backplane_window(whd_driver, CHIPCOMMON_BASE_ADDRESS); +} + +whd_result_t whd_bus_sdio_read_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint8_t *value) +{ + *value = 0; + CHECK_RETURN(whd_bus_set_backplane_window(whd_driver, address) ); + + address &= SBSDIO_SB_OFT_ADDR_MASK; + + if (register_length == 4) + address |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + CHECK_RETURN(whd_bus_sdio_transfer(whd_driver, BUS_READ, BACKPLANE_FUNCTION, address, register_length, value, + RESPONSE_NEEDED) ); + + return whd_bus_set_backplane_window(whd_driver, CHIPCOMMON_BASE_ADDRESS); +} + +whd_result_t whd_bus_sdio_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function, uint32_t address, + uint8_t value_length, uint32_t value) +{ + return whd_bus_sdio_transfer(whd_driver, BUS_WRITE, function, address, value_length, (uint8_t *)&value, + RESPONSE_NEEDED); +} + +whd_result_t whd_bus_sdio_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t size, + whd_transfer_bytes_packet_t *data) +{ + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + return whd_bus_sdio_transfer(whd_driver, direction, function, address, size, (uint8_t *)data->data, + RESPONSE_NEEDED); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) +} + +/****************************************************** +* Static Function definitions +******************************************************/ + +static whd_result_t whd_bus_sdio_transfer(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t data_size, + uint8_t *data, sdio_response_needed_t response_expected) +{ + /* Note: this function had broken retry logic (never retried), which has been removed. + * Failing fast helps problems on the bus get brought to light more quickly + * and preserves the original behavior. + */ + whd_result_t result = WHD_SUCCESS; + uint16_t data_byte_size; + uint16_t data_blk_size; + + if (data_size == 0) + { + return WHD_BADARG; + } + else if (data_size == (uint16_t)1) + { + return whd_bus_sdio_cmd52(whd_driver, direction, function, address, *data, response_expected, data); + } + else if (whd_driver->internal_info.whd_wlan_status.state == WLAN_UP) + { + return whd_bus_sdio_cmd53(whd_driver, direction, function, + (data_size >= (uint16_t)64) ? SDIO_BLOCK_MODE : SDIO_BYTE_MODE, address, data_size, + data, response_expected, NULL); + } + else + { + /* We need to handle remaining size for source image download */ + data_byte_size = data_size % SDIO_64B_BLOCK; + data_blk_size = data_size - data_byte_size; + if (data_blk_size != 0) + { + result = whd_bus_sdio_cmd53(whd_driver, direction, function, SDIO_BLOCK_MODE, address, + data_blk_size, data, response_expected, NULL); + if (result != WHD_SUCCESS) + { + return result; + } + data += data_blk_size; + address += data_blk_size; + } + if (data_byte_size) + { + result = whd_bus_sdio_cmd53(whd_driver, direction, function, SDIO_BYTE_MODE, address, + data_byte_size, data, response_expected, NULL); + } + return result; + } +} + +static whd_result_t whd_bus_sdio_cmd52(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint8_t value, + sdio_response_needed_t response_expected, uint8_t *response) +{ + uint32_t sdio_response; + whd_result_t result; + sdio_cmd_argument_t arg; + arg.value = 0; + arg.cmd52.function_number = (uint32_t)(function & BUS_FUNCTION_MASK); + arg.cmd52.register_address = (uint32_t)(address & 0x00001ffff); + arg.cmd52.rw_flag = (uint32_t)( (direction == BUS_WRITE) ? 1 : 0 ); + arg.cmd52.write_data = value; + + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, cmd52); + result = cyhal_sdio_send_cmd(whd_driver->bus_priv->sdio_obj, (cyhal_sdio_transfer_t)direction, + CYHAL_SDIO_CMD_IO_RW_DIRECT, arg.value, + &sdio_response); + WHD_BUS_STATS_CONDITIONAL_INCREMENT_VARIABLE(whd_driver->bus_priv, (result != WHD_SUCCESS), cmd52_fail); + + if (response != NULL) + { + *response = (uint8_t)(sdio_response & 0x00000000ff); + } + + /* Possibly device might not respond to this cmd. So, don't check return value here */ + if ( (result != WHD_SUCCESS) && (address == SDIO_SLEEP_CSR) ) + { + return result; + } + + CHECK_RETURN(result); + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_sdio_cmd53(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, sdio_transfer_mode_t mode, uint32_t address, + uint16_t data_size, uint8_t *data, + sdio_response_needed_t response_expected, uint32_t *response) +{ + sdio_cmd_argument_t arg; + whd_result_t result; + + if (direction == BUS_WRITE) + { + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, cmd53_write); + } + + arg.value = 0; + arg.cmd53.function_number = (uint32_t)(function & BUS_FUNCTION_MASK); + arg.cmd53.register_address = (uint32_t)(address & WHD_BIT_MASK(17) ); + arg.cmd53.op_code = (uint32_t)1; + arg.cmd53.rw_flag = (uint32_t)( (direction == BUS_WRITE) ? 1 : 0 ); + + if (mode == SDIO_BYTE_MODE) + { + whd_assert("whd_bus_sdio_cmd53: data_size > 512 for byte mode", (data_size <= (uint16_t )512) ); + arg.cmd53.count = (uint32_t)(data_size & 0x1FF); + + result = + cyhal_sdio_bulk_transfer(whd_driver->bus_priv->sdio_obj, (cyhal_sdio_transfer_t)direction, arg.value, + (uint32_t *)data, data_size, response); + + if (result != CY_RSLT_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d cyhal_sdio_bulk_transfer SDIO_BYTE_MODE failed\n", __func__, __LINE__) ); + goto done; + } + } + else + { + arg.cmd53.count = (uint32_t)( (data_size / (uint16_t)SDIO_64B_BLOCK) & WHD_BIT_MASK(9) ); + if ( (uint32_t)(arg.cmd53.count * (uint16_t)SDIO_64B_BLOCK) < data_size ) + { + ++arg.cmd53.count; + } + arg.cmd53.block_mode = (uint32_t)1; + + result = + cyhal_sdio_bulk_transfer(whd_driver->bus_priv->sdio_obj, (cyhal_sdio_transfer_t)direction, arg.value, + (uint32_t *)data, data_size, response); + + if (result != CY_RSLT_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d cyhal_sdio_bulk_transfer failed\n", __func__, __LINE__) ); + goto done; + } + } + + if (direction == BUS_READ) + { + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, cmd53_read); + } + +done: + WHD_BUS_STATS_CONDITIONAL_INCREMENT_VARIABLE(whd_driver->bus_priv, + ( (result != WHD_SUCCESS) && (direction == BUS_READ) ), + cmd53_read_fail); + WHD_BUS_STATS_CONDITIONAL_INCREMENT_VARIABLE(whd_driver->bus_priv, + ( (result != WHD_SUCCESS) && (direction == BUS_WRITE) ), + cmd53_write_fail); + CHECK_RETURN(result); + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_sdio_download_firmware(whd_driver_t whd_driver) +{ + uint8_t csr_val = 0; + whd_result_t result; + uint32_t loop_count; + uint32_t ram_start_address; + + ram_start_address = GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS); + if (ram_start_address != 0) + { + CHECK_RETURN(whd_reset_core(whd_driver, WLAN_ARM_CORE, SICF_CPUHALT, SICF_CPUHALT) ); + } + else + { + CHECK_RETURN(whd_disable_device_core(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_NONE) ); + CHECK_RETURN(whd_disable_device_core(whd_driver, SOCRAM_CORE, WLAN_CORE_FLAG_NONE) ); + CHECK_RETURN(whd_reset_device_core(whd_driver, SOCRAM_CORE, WLAN_CORE_FLAG_NONE) ); + + CHECK_RETURN(whd_chip_specific_socsram_init(whd_driver) ); + } + +#if 0 + /* 43362 specific: Remap JTAG pins to UART output */ + uint32_t data = 0; + CHECK_RETURN(whd_bus_write_backplane_value(0x18000650, 1, 1) ); + CHECK_RETURN(whd_bus_read_backplane_value(0x18000654, 4, (uint8_t *)&data) ); + data |= (1 << 24); + CHECK_RETURN(whd_bus_write_backplane_value(0x18000654, 4, data) ); +#endif + + result = whd_bus_write_wifi_firmware_image(whd_driver); + + if (result == WHD_UNFINISHED) + { + WPRINT_WHD_INFO( ("User aborted fw download\n") ); + /* user aborted */ + return result; + } + else if (result != WHD_SUCCESS) + { + whd_assert("Failed to load wifi firmware\n", result == WHD_SUCCESS); + return result; + } + + CHECK_RETURN(whd_bus_sdio_write_wifi_nvram_image(whd_driver) ); + + /* Take the ARM core out of reset */ + if (ram_start_address != 0) + { + CHECK_RETURN(whd_reset_core(whd_driver, WLAN_ARM_CORE, 0, 0) ); + } + else + { + CHECK_RETURN(whd_reset_device_core(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_NONE) ); + + result = whd_device_core_is_up(whd_driver, WLAN_ARM_CORE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Could not bring ARM core up\n") ); + /* Reachable after hitting assert */ + return result; + } + } + + /* Wait until the High Throughput clock is available */ + loop_count = 0; + while ( ( (result = whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, + &csr_val) ) == WHD_SUCCESS ) && + ( (csr_val & SBSDIO_HT_AVAIL) == 0 ) && + (loop_count < (uint32_t)HT_AVAIL_TIMEOUT_MS) ) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + loop_count++; + } + if (loop_count >= (uint32_t)HT_AVAIL_TIMEOUT_MS) + { + /* If your system times out here, it means that the WLAN firmware is not booting. + * Check that your WLAN chip matches the 'wifi_image.c' being built - in GNU toolchain, $(CHIP) + * makefile variable must be correct. + */ + WPRINT_WHD_ERROR( ("Timeout while waiting for high throughput clock\n") ); + /* Reachable after hitting assert */ + return WHD_TIMEOUT; + } + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error while waiting for high throughput clock\n") ); + /* Reachable after hitting assert */ + return result; + } + + /* Set up the interrupt mask and enable interrupts */ + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, SDIO_INT_HOST_MASK(whd_driver), (uint8_t)4, HOSTINTMASK) ); + + /* Enable F2 interrupts. This wasn't required for 4319 but is for the 43362 */ + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, SDIO_FUNCTION_INT_MASK(whd_driver), (uint8_t)1, + SDIO_FUNC_MASK_F1 | SDIO_FUNC_MASK_F2) ); + + /* Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped. */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_FUNCTION2_WATERMARK, (uint8_t)1, + (uint32_t)SDIO_F2_WATERMARK) ); + + return WHD_SUCCESS; +} + +/** Aborts a SDIO read of a packet from the 802.11 device + * + * This function is necessary because the only way to obtain the size of the next + * available received packet is to read the first four bytes of the packet. + * If the system reads these four bytes, and then fails to allocate the required + * memory, then this function allows the system to abort the packet read cleanly, + * and to optionally tell the 802.11 device to keep it allowing reception once + * memory is available. + * + * In order to do this abort, the following actions are performed: + * - Sets abort bit for Function 2 (WLAN Data) to request stopping transfer + * - Sets Read Frame Termination bit to flush and reset fifos + * - If packet is to be kept and resent by 802.11 device, a NAK is sent + * - Wait whilst the Fifo is emptied of the packet ( reading during this period would cause all zeros to be read ) + * + * @param retry : WHD_TRUE if 802.11 device is to keep and resend packet + * WHD_FALSE if 802.11 device is to drop packet + * + * @return WHD_SUCCESS if successful, otherwise error code + */ +static whd_result_t whd_bus_sdio_abort_read(whd_driver_t whd_driver, whd_bool_t retry) +{ + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, read_aborts); + + /* Abort transfer on WLAN_FUNCTION */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOABORT, (uint8_t)1, + (uint32_t)WLAN_FUNCTION) ); + + /* Send frame terminate */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_FRAME_CONTROL, (uint8_t)1, + SFC_RF_TERM) ); + + /* If we want to retry message, send NAK */ + if (retry == WHD_TRUE) + { + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, (uint32_t)SDIO_TO_SB_MAILBOX(whd_driver), (uint8_t)1, + SMB_NAK) ); + } + + return WHD_SUCCESS; +} + +whd_result_t whd_bus_sdio_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function, uint32_t address, + uint8_t value_length, uint8_t *value) +{ + memset(value, 0, (size_t)value_length); + return whd_bus_sdio_transfer(whd_driver, BUS_READ, function, address, value_length, value, RESPONSE_NEEDED); +} + +whd_result_t whd_bus_sdio_poke_wlan(whd_driver_t whd_driver) +{ + return whd_bus_write_backplane_value(whd_driver, SDIO_TO_SB_MAILBOX(whd_driver), (uint8_t)4, SMB_DEV_INT); +} + +whd_result_t whd_bus_sdio_wakeup(whd_driver_t whd_driver) +{ + return WHD_SUCCESS; +} + +whd_result_t whd_bus_sdio_sleep(whd_driver_t whd_driver) +{ + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_sdio_set_oob_interrupt(whd_driver_t whd_driver, uint8_t gpio_pin_number) +{ + if (gpio_pin_number != 0) + { + /* Redirect to OOB interrupt to GPIO1 */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_GPIO_SELECT, (uint8_t)1, + (uint32_t)0xF) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_GPIO_OUTPUT, (uint8_t)1, + (uint32_t)0x0) ); + + /* Enable GPIOx (bit x) */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_GPIO_ENABLE, (uint8_t)1, + (uint32_t)0x2) ); + + /* Set GPIOx (bit x) on Chipcommon GPIO Control register */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, CHIPCOMMON_GPIO_CONTROL, (uint8_t)4, + (uint32_t)0x2) ); + } + + return WHD_SUCCESS; +} + +void whd_bus_sdio_init_stats(whd_driver_t whd_driver) +{ + memset(&whd_driver->bus_priv->whd_bus_stats, 0, sizeof(whd_bus_stats_t) ); +} + +whd_result_t whd_bus_sdio_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print) +{ + WPRINT_MACRO( ("Bus Stats.. \n" + "cmd52:%" PRIu32 ", cmd53_read:%" PRIu32 ", cmd53_write:%" PRIu32 "\n" + "cmd52_fail:%" PRIu32 ", cmd53_read_fail:%" PRIu32 ", cmd53_write_fail:%" PRIu32 "\n" + "oob_intrs:%" PRIu32 ", sdio_intrs:%" PRIu32 ", error_intrs:%" PRIu32 ", read_aborts:%" PRIu32 + "\n", + whd_driver->bus_priv->whd_bus_stats.cmd52, whd_driver->bus_priv->whd_bus_stats.cmd53_read, + whd_driver->bus_priv->whd_bus_stats.cmd53_write, + whd_driver->bus_priv->whd_bus_stats.cmd52_fail, + whd_driver->bus_priv->whd_bus_stats.cmd53_read_fail, + whd_driver->bus_priv->whd_bus_stats.cmd53_write_fail, + whd_driver->bus_priv->whd_bus_stats.oob_intrs, + whd_driver->bus_priv->whd_bus_stats.sdio_intrs, + whd_driver->bus_priv->whd_bus_stats.error_intrs, + whd_driver->bus_priv->whd_bus_stats.read_aborts) ); + + if (reset_after_print == WHD_TRUE) + { + memset(&whd_driver->bus_priv->whd_bus_stats, 0, sizeof(whd_bus_stats_t) ); + } + + return WHD_SUCCESS; +} + +/* Waking the firmware up from Deep Sleep */ +whd_result_t whd_bus_sdio_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware) +{ + whd_result_t result = WHD_SUCCESS; + uint8_t byte_data; + uint32_t loop_count; + loop_count = 0; + + /* Setup the backplane*/ + loop_count = 0; + + do + { + /* Enable function 1 (backplane) */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1, + SDIO_FUNC_ENABLE_1) ); + if (loop_count != 0) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + } + + CHECK_RETURN(whd_bus_read_register_value (whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1, &byte_data) ); + loop_count++; + if (loop_count >= (uint32_t)F0_WORKING_TIMEOUT_MS) + { + WPRINT_WHD_ERROR( ("Timeout on CCCR update\n") ); + return WHD_TIMEOUT; + } + } while (byte_data != (uint8_t)SDIO_FUNC_ENABLE_1); + + if (whd_driver->bus_priv->sdio_config.sdio_1bit_mode == WHD_FALSE) + { + /* Read the bus width and set to 4 bits */ + CHECK_RETURN(whd_bus_read_register_value (whd_driver, BUS_FUNCTION, SDIOD_CCCR_BICTRL, (uint8_t)1, + &byte_data) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_BICTRL, (uint8_t)1, + (byte_data & (~BUS_SD_DATA_WIDTH_MASK) ) | BUS_SD_DATA_WIDTH_4BIT) ); + /* NOTE: We don't need to change our local bus settings since we're not sending any data (only using CMD52) + * until after we change the bus speed further down */ + } + + /* Set the block size */ + /* Wait till the backplane is ready */ + loop_count = 0; + while ( ( (result = whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_BLKSIZE_0, (uint8_t)1, + (uint32_t)SDIO_64B_BLOCK) ) == WHD_SUCCESS ) && + ( (result = whd_bus_read_register_value (whd_driver, BUS_FUNCTION, SDIOD_CCCR_BLKSIZE_0, (uint8_t)1, + &byte_data) ) == WHD_SUCCESS ) && + (byte_data != (uint8_t)SDIO_64B_BLOCK) && + (loop_count < (uint32_t)F0_WORKING_TIMEOUT_MS) ) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + loop_count++; + if (loop_count >= (uint32_t)F0_WORKING_TIMEOUT_MS) + { + /* If the system fails here, check the high frequency crystal is working */ + WPRINT_WHD_ERROR( ("Timeout while setting block size\n") ); + return WHD_TIMEOUT; + } + } + + CHECK_RETURN(result); + + WPRINT_WHD_DEBUG( ("Modding registers for blocks\n") ); + + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_BLKSIZE_0, (uint8_t)1, + (uint32_t)SDIO_64B_BLOCK) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_F1BLKSIZE_0, (uint8_t)1, + (uint32_t)SDIO_64B_BLOCK) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_F2BLKSIZE_0, (uint8_t)1, + (uint32_t)SDIO_64B_BLOCK) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_F2BLKSIZE_1, (uint8_t)1, + (uint32_t)0) ); /* Function 2 = 64 */ + + /* Enable/Disable Client interrupts */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_INTEN, (uint8_t)1, + INTR_CTL_MASTER_EN | INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN) ); + + + if (whd_driver->bus_priv->sdio_config.high_speed_sdio_clock) + { + WPRINT_WHD_DEBUG( ("SDIO HS clock enable\n") ); + + /* This code is required if we want more than 25 MHz clock */ + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_SPEED_CONTROL, 1, &byte_data) ); + if ( (byte_data & 0x1) != 0 ) + { + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_SPEED_CONTROL, 1, + byte_data | SDIO_SPEED_EHS) ); + } + else + { + WPRINT_WHD_ERROR( ("Error writing to WLAN register, %s failed at %d \n", __func__, __LINE__) ); + return WHD_BUS_READ_REGISTER_ERROR; + } + } /* HIGH_SPEED_SDIO_CLOCK */ + + /* Wait till the backplane is ready */ + loop_count = 0; + while ( ( (result = whd_bus_read_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IORDY, (uint8_t)1, + &byte_data) ) == WHD_SUCCESS ) && + ( (byte_data & SDIO_FUNC_READY_1) == 0 ) && + (loop_count < (uint32_t)F1_AVAIL_TIMEOUT_MS) ) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + loop_count++; + } + + if (loop_count >= (uint32_t)F1_AVAIL_TIMEOUT_MS) + { + WPRINT_WHD_ERROR( ("Timeout while waiting for backplane to be ready\n") ); + return WHD_TIMEOUT; + } + CHECK_RETURN(result); + + /* Set the ALP */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, + (uint32_t)(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ | + SBSDIO_FORCE_ALP) ) ); + loop_count = 0; + while ( ( (result = whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, + &byte_data) ) != WHD_SUCCESS ) || + ( ( (byte_data & SBSDIO_ALP_AVAIL) == 0 ) && + (loop_count < (uint32_t)ALP_AVAIL_TIMEOUT_MS) ) ) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + loop_count++; + } + if (loop_count >= (uint32_t)ALP_AVAIL_TIMEOUT_MS) + { + WPRINT_WHD_ERROR( ("Timeout while waiting for alp clock\n") ); + return WHD_TIMEOUT; + } + CHECK_RETURN(result); + + /* Clear request for ALP */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, 0) ); + + /* Disable the extra SDIO pull-ups */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_PULL_UP, (uint8_t)1, 0) ); + + /* Enable F1 and F2 */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1, + SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2) ); + + /* Setup host-wake signals */ + CHECK_RETURN(whd_bus_sdio_init_oob_intr(whd_driver) ); + + /* Enable F2 interrupt only */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_INTEN, (uint8_t)1, + INTR_CTL_MASTER_EN | INTR_CTL_FUNC2_EN) ); + + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IORDY, (uint8_t)1, &byte_data) ); + + result = whd_bus_sdio_download_firmware(whd_driver); + + if (result != WHD_SUCCESS) + { + /* either an error or user abort */ + WPRINT_WHD_DEBUG( ("FW download failed\n") ); + return result; + } + + /* Wait for F2 to be ready */ + loop_count = 0; + while ( ( (result = whd_bus_read_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IORDY, (uint8_t)1, + &byte_data) ) != WHD_SUCCESS ) || + ( ( (byte_data & SDIO_FUNC_READY_2) == 0 ) && + (loop_count < (uint32_t)F2_READY_TIMEOUT_MS) ) ) + { + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + loop_count++; + } + + if (loop_count >= (uint32_t)F2_READY_TIMEOUT_MS) + { + WPRINT_WHD_DEBUG( ("Timeout while waiting for function 2 to be ready\n") ); + + if (WHD_TRUE == wake_from_firmware) + { + /* If your system fails here, it could be due to incorrect NVRAM variables. + * Check which 'wifi_nvram_image.h' file your platform is using, and + * check that it matches the WLAN device on your platform, including the + * crystal frequency. + */ + WPRINT_WHD_ERROR( ("F2 failed on wake fr FW\n") ); + /* Reachable after hitting assert */ + return WHD_TIMEOUT; + } + /* Else: Ignore this failure if we're doing a reinit due to host wake: Linux DHD also ignores */ + + } + + /* Do chip specific init */ + CHECK_RETURN(whd_chip_specific_init(whd_driver) ); + + /* Ensure Bus is up */ + CHECK_RETURN(whd_ensure_wlan_bus_is_up(whd_driver) ); + + /* Allow bus to go to sleep */ + CHECK_RETURN(whd_allow_wlan_bus_to_sleep(whd_driver) ); + + WPRINT_WHD_INFO( ("whd_bus_reinit Completed \n") ); + return WHD_SUCCESS; +} + +uint8_t whd_bus_sdio_backplane_read_padd_size(whd_driver_t whd_driver) +{ + return WHD_BUS_SDIO_BACKPLANE_READ_PADD_SIZE; +} + +whd_bool_t whd_bus_sdio_use_status_report_scheme(whd_driver_t whd_driver) +{ + return WHD_FALSE; +} + +uint32_t whd_bus_sdio_get_max_transfer_size(whd_driver_t whd_driver) +{ + return WHD_BUS_SDIO_MAX_BACKPLANE_TRANSFER_SIZE; +} + +#if (CYHAL_API_VERSION >= 2) +static void whd_bus_sdio_irq_handler(void *handler_arg, cyhal_sdio_event_t event) +#else +static void whd_bus_sdio_irq_handler(void *handler_arg, cyhal_sdio_irq_event_t event) +#endif +{ + whd_driver_t whd_driver = (whd_driver_t)handler_arg; + + /* WHD registered only for CY_CYHAL_SDIO_CARD_INTERRUPT */ + if (event != CYHAL_SDIO_CARD_INTERRUPT) + { + WPRINT_WHD_ERROR( ("Unexpected interrupt event %d\n", event) ); + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, error_intrs); + return; + } + + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, sdio_intrs); + + /* call thread notify to wake up WHD thread */ + whd_thread_notify_irq(whd_driver); +} + +whd_result_t whd_bus_sdio_irq_register(whd_driver_t whd_driver) +{ +#if (CYHAL_API_VERSION >= 2) + cyhal_sdio_register_callback(whd_driver->bus_priv->sdio_obj, whd_bus_sdio_irq_handler, whd_driver); +#else + cyhal_sdio_register_irq(whd_driver->bus_priv->sdio_obj, whd_bus_sdio_irq_handler, whd_driver); +#endif + return WHD_SUCCESS; +} + +whd_result_t whd_bus_sdio_irq_enable(whd_driver_t whd_driver, whd_bool_t enable) +{ +#if (CYHAL_API_VERSION >= 2) + cyhal_sdio_enable_event(whd_driver->bus_priv->sdio_obj, CYHAL_SDIO_CARD_INTERRUPT, CYHAL_ISR_PRIORITY_DEFAULT, + enable); +#else + cyhal_sdio_irq_enable(whd_driver->bus_priv->sdio_obj, CYHAL_SDIO_CARD_INTERRUPT, enable); +#endif + return WHD_SUCCESS; +} + +#if (CYHAL_API_VERSION >= 2) +static void whd_bus_sdio_oob_irq_handler(void *arg, cyhal_gpio_event_t event) +#else +static void whd_bus_sdio_oob_irq_handler(void *arg, cyhal_gpio_irq_event_t event) +#endif +{ + whd_driver_t whd_driver = (whd_driver_t)arg; + const whd_oob_config_t *config = &whd_driver->bus_priv->sdio_config.oob_config; +#if (CYHAL_API_VERSION >= 2) + const cyhal_gpio_event_t expected_event = (config->is_falling_edge == WHD_TRUE) + ? CYHAL_GPIO_IRQ_FALL : CYHAL_GPIO_IRQ_RISE; +#else + const cyhal_gpio_irq_event_t expected_event = (config->is_falling_edge == WHD_TRUE) + ? CYHAL_GPIO_IRQ_FALL : CYHAL_GPIO_IRQ_RISE; +#endif + if (event != expected_event) + { + WPRINT_WHD_ERROR( ("Unexpected interrupt event %d\n", event) ); + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, error_intrs); + return; + } + + WHD_BUS_STATS_INCREMENT_VARIABLE(whd_driver->bus_priv, oob_intrs); + + /* Call thread notify to wake up WHD thread */ + whd_thread_notify_irq(whd_driver); +} + +static whd_result_t whd_bus_sdio_register_oob_intr(whd_driver_t whd_driver) +{ + const whd_oob_config_t *config = &whd_driver->bus_priv->sdio_config.oob_config; + + cyhal_gpio_init(config->host_oob_pin, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_NONE, 0); +#if (CYHAL_API_VERSION >= 2) + static cyhal_gpio_callback_data_t cbdata; + cbdata.callback = whd_bus_sdio_oob_irq_handler; + cbdata.callback_arg = whd_driver; + cyhal_gpio_register_callback(config->host_oob_pin, &cbdata); +#else + cyhal_gpio_register_irq(config->host_oob_pin, config->intr_priority, whd_bus_sdio_oob_irq_handler, + whd_driver); +#endif + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_sdio_unregister_oob_intr(whd_driver_t whd_driver) +{ + const whd_oob_config_t *config = &whd_driver->bus_priv->sdio_config.oob_config; +#if (CYHAL_API_VERSION >= 2) + cyhal_gpio_register_callback(config->host_oob_pin, NULL); +#else + cyhal_gpio_register_irq(config->host_oob_pin, config->intr_priority, NULL, NULL); +#endif + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_sdio_enable_oob_intr(whd_driver_t whd_driver, whd_bool_t enable) +{ + const whd_oob_config_t *config = &whd_driver->bus_priv->sdio_config.oob_config; +#if (CYHAL_API_VERSION >= 2) + const cyhal_gpio_event_t event = + (config->is_falling_edge == WHD_TRUE) ? CYHAL_GPIO_IRQ_FALL : CYHAL_GPIO_IRQ_RISE; + + cyhal_gpio_enable_event(config->host_oob_pin, event, config->intr_priority, (enable == WHD_TRUE) ? true : false); +#else + const cyhal_gpio_irq_event_t event = + (config->is_falling_edge == WHD_TRUE) ? CYHAL_GPIO_IRQ_FALL : CYHAL_GPIO_IRQ_RISE; + + cyhal_gpio_irq_enable(config->host_oob_pin, event, (enable == WHD_TRUE) ? true : false); +#endif + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_sdio_init_oob_intr(whd_driver_t whd_driver) +{ + const whd_oob_config_t *config = &whd_driver->bus_priv->sdio_config.oob_config; + uint8_t sepintpol; + + /* OOB isn't configured so bail */ + if (config->host_oob_pin == CYHAL_NC_PIN_VALUE) + return WHD_SUCCESS; + + /* Choose out-of-band interrupt polarity */ + if (config->is_falling_edge == WHD_FALSE) + { + sepintpol = SEP_INTR_CTL_POL; + } + else + { + sepintpol = 0; + } + + /* Set OOB interrupt to the correct WLAN GPIO pin (default to GPIO0) */ + if (config->dev_gpio_sel) + CHECK_RETURN(whd_bus_sdio_set_oob_interrupt(whd_driver, config->dev_gpio_sel) ); + + /* Enable out-of-band interrupt on the device */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_SEP_INT_CTL, (uint8_t)1, + SEP_INTR_CTL_MASK | SEP_INTR_CTL_EN | sepintpol) ); + + /* Register and enable OOB */ + /* XXX Remove this when BSP377 is implemented */ + CHECK_RETURN(whd_bus_sdio_register_oob_intr(whd_driver) ); + CHECK_RETURN(whd_bus_sdio_enable_oob_intr(whd_driver, WHD_TRUE) ); + + return WHD_SUCCESS; +} + +static whd_result_t whd_bus_sdio_deinit_oob_intr(whd_driver_t whd_driver) +{ + const whd_oob_config_t *config = &whd_driver->bus_priv->sdio_config.oob_config; + + if (config->host_oob_pin != CYHAL_NC_PIN_VALUE) + { + CHECK_RETURN(whd_bus_sdio_enable_oob_intr(whd_driver, WHD_FALSE) ); + CHECK_RETURN(whd_bus_sdio_unregister_oob_intr(whd_driver) ); + } + + return WHD_SUCCESS; +} + +#ifdef WPRINT_ENABLE_WHD_DEBUG +#define WHD_BLOCK_SIZE (1024) +static whd_result_t whd_bus_sdio_verify_resource(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, uint32_t image_size) +{ + whd_result_t result = WHD_SUCCESS; + uint8_t *image; + uint8_t *cmd_img = NULL; + uint32_t blocks_count = 0; + uint32_t i; + uint32_t size_out; + + result = whd_get_resource_no_of_blocks(whd_driver, resource, &blocks_count); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Fatal error: download_resource blocks count not known, %s failed at line %d \n", __func__, + __LINE__) ); + goto exit; + } + cmd_img = malloc(WHD_BLOCK_SIZE); + if (cmd_img != NULL) + { + for (i = 0; i < blocks_count; i++) + { + CHECK_RETURN(whd_get_resource_block(whd_driver, resource, i, (const uint8_t **)&image, &size_out) ); + result = whd_bus_transfer_backplane_bytes(whd_driver, BUS_READ, address, size_out, cmd_img); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Failed to read firmware image\n", __FUNCTION__) ); + goto exit; + } + if (memcmp(cmd_img, &image[0], size_out) ) + { + WPRINT_WHD_ERROR( ("%s: Downloaded image is corrupted, address is %d, len is %d, resource is %d \n", + __FUNCTION__, (int)address, (int)size_out, (int)resource) ); + } + address += size_out; + } + } +exit: + if (cmd_img) + free(cmd_img); + return WHD_SUCCESS; +} + +#endif +static whd_result_t whd_bus_sdio_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, uint32_t image_size) +{ + whd_result_t result = WHD_SUCCESS; + uint8_t *image; + uint32_t blocks_count = 0; + uint32_t i; + uint32_t size_out; + uint32_t reset_instr = 0; +#ifdef WPRINT_ENABLE_WHD_DEBUG + uint32_t pre_addr = address; +#endif + + result = whd_get_resource_no_of_blocks(whd_driver, resource, &blocks_count); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Fatal error: download_resource blocks count not known, %s failed at line %d \n", __func__, + __LINE__) ); + goto exit; + } + + for (i = 0; i < blocks_count; i++) + { + CHECK_RETURN(whd_get_resource_block(whd_driver, resource, i, (const uint8_t **)&image, &size_out) ); + if ( (resource == WHD_RESOURCE_WLAN_FIRMWARE) && (reset_instr == 0) ) + { + /* Copy the starting address of the firmware into a global variable */ + reset_instr = *( (uint32_t *)(&image[0]) ); + } + result = whd_bus_transfer_backplane_bytes(whd_driver, BUS_WRITE, address, size_out, &image[0]); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Failed to write firmware image\n", __FUNCTION__) ); + goto exit; + } + address += size_out; + } +#ifdef WPRINT_ENABLE_WHD_DEBUG + whd_bus_sdio_verify_resource(whd_driver, resource, direct_resource, pre_addr, image_size); +#endif + /* Below part of the code is applicable to arm_CR4 type chips only + * The CR4 chips by default firmware is not loaded at 0. So we need + * load the first 32 bytes with the offset of the firmware load address + * which is been copied before during the firmware download + */ + if ( (address != 0) && (reset_instr != 0) ) + { + /* write address 0 with reset instruction */ + result = whd_bus_write_backplane_value(whd_driver, 0, sizeof(reset_instr), reset_instr); + + if (result == WHD_SUCCESS) + { + uint32_t tmp; + + /* verify reset instruction value */ + result = whd_bus_read_backplane_value(whd_driver, 0, sizeof(tmp), (uint8_t *)&tmp); + + if ( (result == WHD_SUCCESS) && (tmp != reset_instr) ) + { + WPRINT_WHD_ERROR( ("%s: Failed to write 0x%08" PRIx32 " to addr 0\n", __FUNCTION__, reset_instr) ); + WPRINT_WHD_ERROR( ("%s: contents of addr 0 is 0x%08" PRIx32 "\n", __FUNCTION__, tmp) ); + return WHD_WLAN_SDIO_ERROR; + } + } + } +exit: return result; +} + +static whd_result_t whd_bus_sdio_write_wifi_nvram_image(whd_driver_t whd_driver) +{ + uint32_t img_base; + uint32_t img_end; + uint32_t image_size; + + /* Get the size of the variable image */ + CHECK_RETURN(whd_resource_size(whd_driver, WHD_RESOURCE_WLAN_NVRAM, &image_size) ); + + /* Round up the size of the image */ + image_size = ROUND_UP(image_size, 4); + + /* Write image */ + img_end = GET_C_VAR(whd_driver, CHIP_RAM_SIZE) - 4; + img_base = (img_end - image_size); + img_base += GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS); + + CHECK_RETURN(whd_bus_sdio_download_resource(whd_driver, WHD_RESOURCE_WLAN_NVRAM, WHD_FALSE, img_base, image_size) ); + + /* Write the variable image size at the end */ + image_size = (~(image_size / 4) << 16) | (image_size / 4); + + img_end += GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS); + + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, (uint32_t)img_end, 4, image_size) ); + return WHD_SUCCESS; +} + +/* + * Update the backplane window registers + */ +whd_result_t whd_bus_sdio_set_backplane_window(whd_driver_t whd_driver, uint32_t addr, uint32_t *curbase) +{ + whd_result_t result = WHD_BUS_WRITE_REGISTER_ERROR; + uint32_t base = addr & ( (uint32_t) ~BACKPLANE_ADDRESS_MASK ); + const uint32_t upper_32bit_mask = 0xFF000000; + const uint32_t upper_middle_32bit_mask = 0x00FF0000; + const uint32_t lower_middle_32bit_mask = 0x0000FF00; + + if (base == *curbase) + { + return WHD_SUCCESS; + } + if ( (base & upper_32bit_mask) != (*curbase & upper_32bit_mask) ) + { + if (WHD_SUCCESS != + (result = whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_BACKPLANE_ADDRESS_HIGH, + (uint8_t)1, (base >> 24) ) ) ) + { + WPRINT_WHD_ERROR( ("Failed to write register value to the bus, %s failed at %d \n", __func__, + __LINE__) ); + return result; + } + /* clear old */ + *curbase &= ~upper_32bit_mask; + /* set new */ + *curbase |= (base & upper_32bit_mask); + } + + if ( (base & upper_middle_32bit_mask) != + (*curbase & upper_middle_32bit_mask) ) + { + if (WHD_SUCCESS != + (result = whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_BACKPLANE_ADDRESS_MID, + (uint8_t)1, (base >> 16) ) ) ) + { + WPRINT_WHD_ERROR( ("Failed to write register value to the bus, %s failed at %d \n", __func__, + __LINE__) ); + return result; + } + /* clear old */ + *curbase &= ~upper_middle_32bit_mask; + /* set new */ + *curbase |= (base & upper_middle_32bit_mask); + } + + if ( (base & lower_middle_32bit_mask) != + (*curbase & lower_middle_32bit_mask) ) + { + if (WHD_SUCCESS != + (result = whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_BACKPLANE_ADDRESS_LOW, + (uint8_t)1, (base >> 8) ) ) ) + { + WPRINT_WHD_ERROR( ("Failed to write register value to the bus, %s failed at %d \n", __func__, + __LINE__) ); + return result; + } + + /* clear old */ + *curbase &= ~lower_middle_32bit_mask; + /* set new */ + *curbase |= (base & lower_middle_32bit_mask); + } + + return WHD_SUCCESS; +} + +#endif /* (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SDIO_INTERFACE) */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.h b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.h new file mode 100644 index 00000000..6daeb9b2 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.h @@ -0,0 +1,219 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "whd.h" +#include "bus_protocols/whd_bus_protocol_interface.h" + +#ifndef INCLUDED_SDIO_WHD_BUS_PROTOCOL_H +#define INCLUDED_SDIO_WHD_BUS_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************** +* Macros +******************************************************/ +#define WHD_BIT_MASK(x) ( (1 << x) - 1 ) + +#define WHD_BUS_HEADER_SIZE (0) + +#define WHD_BUS_SDIO_MAX_BACKPLANE_TRANSFER_SIZE (1536) +#define WHD_BUS_SDIO_BACKPLANE_READ_PADD_SIZE (0) + +#define WHD_BUS_STATS_INCREMENT_VARIABLE(bus_priv, var) \ + do { bus_priv->whd_bus_stats.var++; } while (0) + +#define WHD_BUS_STATS_CONDITIONAL_INCREMENT_VARIABLE(bus_priv, condition, var) \ + do { if (condition){ bus_priv->whd_bus_stats.var++; }} while (0) + +/****************************************************** +* Structures +******************************************************/ +#pragma pack(1) +typedef struct +{ + unsigned char stuff_bits; + unsigned int ocr : 24; +} sdio_cmd5_argument_t; + +typedef struct +{ + unsigned int _unique2 : 9; /* 0-8 */ + unsigned int register_address : 17; /* 9-25 */ + unsigned int _unique : 2; /* 26-27 */ + unsigned int function_number : 3; /* 28-30 */ + unsigned int rw_flag : 1; /* 31 */ +} sdio_cmd5x_argument_t; + +typedef struct +{ + uint8_t write_data; /* 0 - 7 */ + unsigned int _stuff2 : 1; /* 8 */ + unsigned int register_address : 17; /* 9-25 */ + unsigned int _stuff : 1; /* 26 */ + unsigned int raw_flag : 1; /* 27 */ + unsigned int function_number : 3; /* 28-30 */ + unsigned int rw_flag : 1; /* 31 */ +} whd_bus_sdio_cmd52_argument_t; + +typedef struct +{ + unsigned int count : 9; /* 0-8 */ + unsigned int register_address : 17; /* 9-25 */ + unsigned int op_code : 1; /* 26 */ + unsigned int block_mode : 1; /* 27 */ + unsigned int function_number : 3; /* 28-30 */ + unsigned int rw_flag : 1; /* 31 */ +} whd_bus_sdio_cmd53_argument_t; + +typedef union +{ + uint32_t value; + sdio_cmd5_argument_t cmd5; + sdio_cmd5x_argument_t cmd5x; + whd_bus_sdio_cmd52_argument_t cmd52; + whd_bus_sdio_cmd53_argument_t cmd53; +} sdio_cmd_argument_t; + +typedef struct +{ + unsigned int ocr : 24; /* 0-23 */ + unsigned int stuff_bits : 3; /* 24-26 */ + unsigned int memory_present : 1; /* 27 */ + unsigned int function_count : 3; /* 28-30 */ + unsigned int c : 1; /* 31 */ +} sdio_response4_t; + +typedef struct +{ + uint8_t data; /* 0-7 */ + uint8_t response_flags; /* 8-15 */ + uint16_t stuff; /* 16-31 */ +} sdio_response5_t; + +typedef struct +{ + uint16_t card_status; /* 0-15 */ + uint16_t rca; /* 16-31 */ +} sdio_response6_t; + +typedef union +{ + uint32_t value; + sdio_response4_t r4; + sdio_response5_t r5; + sdio_response6_t r6; +} sdio_response_t; + +typedef enum +{ + SDIO_BLOCK_MODE = (0 << 2), /* These are STM32 implementation specific */ + SDIO_BYTE_MODE = (1 << 2) /* These are STM32 implementation specific */ +} sdio_transfer_mode_t; + +typedef enum +{ + SDIO_1B_BLOCK = 1, SDIO_2B_BLOCK = 2, SDIO_4B_BLOCK = 4, SDIO_8B_BLOCK = 8, SDIO_16B_BLOCK = 16, + SDIO_32B_BLOCK = 32, SDIO_64B_BLOCK = 64, SDIO_128B_BLOCK = 128, SDIO_256B_BLOCK = 256, SDIO_512B_BLOCK = 512, + SDIO_1024B_BLOCK = 1024, SDIO_2048B_BLOCK = 2048 +} sdio_block_size_t; + +typedef enum +{ + RESPONSE_NEEDED, NO_RESPONSE +} sdio_response_needed_t; + +typedef struct +{ + uint32_t cmd52; /* Number of cmd52 reads/writes issued */ + uint32_t cmd53_read; /* Number of cmd53 reads */ + uint32_t cmd53_write; /* Number of cmd53 writes */ + uint32_t cmd52_fail; /* Number of cmd52 read/write fails */ + uint32_t cmd53_read_fail; /* Number of cmd53 read fails */ + uint32_t cmd53_write_fail; /* Number of cmd53 write fails */ + uint32_t oob_intrs; /* Number of OOB interrupts generated by wlan chip */ + uint32_t sdio_intrs; /* Number of SDIO interrupts generated by wlan chip */ + uint32_t error_intrs; /* Number of SDIO error interrupts generated by wlan chip */ + uint32_t read_aborts; /* Number of times read aborts are called */ +} whd_bus_stats_t; +#pragma pack() + +/****************************************************** +* Function declarations +******************************************************/ +/* Initialisation functions */ +extern whd_result_t whd_bus_sdio_init(whd_driver_t whd_driver); +extern whd_result_t whd_bus_sdio_resume_after_deep_sleep(whd_driver_t whd_driver); +extern whd_result_t whd_bus_sdio_deinit(whd_driver_t whd_driver); + +/* Device register access functions */ +extern whd_result_t whd_bus_sdio_write_backplane_value(whd_driver_t whd_driver, uint32_t address, + uint8_t register_length, uint32_t value); +extern whd_result_t whd_bus_sdio_read_backplane_value(whd_driver_t whd_driver, uint32_t address, + uint8_t register_length, uint8_t *value); +extern whd_result_t whd_bus_sdio_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint32_t value); +extern whd_result_t whd_bus_sdio_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint8_t *value); + +/* Device data transfer functions */ +extern whd_result_t whd_bus_sdio_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer); +extern whd_result_t whd_bus_sdio_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t size, + whd_transfer_bytes_packet_t *data); +extern whd_result_t whd_bus_sdio_transfer_backplane_bytes(whd_driver_t whd_driver, + whd_bus_transfer_direction_t direction, uint32_t address, + uint32_t size, uint8_t *data); + +/* Frame transfer function */ +extern whd_result_t whd_bus_sdio_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer); + +extern whd_result_t whd_bus_sdio_poke_wlan(whd_driver_t whd_driver); +extern uint32_t whd_bus_sdio_packet_available_to_read(whd_driver_t whd_driver); +extern whd_result_t whd_bus_sdio_ack_interrupt(whd_driver_t whd_driver, uint32_t intstatus); + +extern whd_result_t whd_bus_sdio_set_backplane_window(whd_driver_t whd_driver, uint32_t addr, uint32_t *curbase); + +extern void whd_delayed_bus_release_schedule_update(whd_driver_t whd_driver, whd_bool_t is_scheduled); +#define DELAYED_BUS_RELEASE_SCHEDULE(whd_driver, schedule) \ + do { whd_delayed_bus_release_schedule_update(whd_driver, schedule); } while (0) + +extern whd_bool_t whd_bus_sdio_wake_interrupt_present(whd_driver_t whd_driver); + +extern whd_result_t whd_bus_sdio_wakeup(whd_driver_t whd_driver); +extern whd_result_t whd_bus_sdio_sleep(whd_driver_t whd_driver); + +extern void whd_bus_sdio_init_stats(whd_driver_t whd_driver); +extern whd_result_t whd_bus_sdio_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print); +extern whd_result_t whd_bus_sdio_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware); + +uint8_t whd_bus_sdio_backplane_read_padd_size(whd_driver_t whd_driver); + +extern whd_result_t whd_bus_sdio_wait_for_wlan_event(whd_driver_t whd_driver, + cy_semaphore_t *transceive_semaphore); +extern whd_bool_t whd_bus_sdio_use_status_report_scheme(whd_driver_t whd_driver); +extern uint32_t whd_bus_sdio_get_max_transfer_size(whd_driver_t whd_driver); +/****************************************************** +* Global variables +******************************************************/ + +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif /* ifndef INCLUDED_SDIO_WHD_BUS_PROTOCOL_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_spi_protocol.c b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_spi_protocol.c new file mode 100644 index 00000000..b8cd4f51 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_spi_protocol.c @@ -0,0 +1,1369 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Broadcom WLAN SPI Protocol interface + * + * Implements the WHD Bus Protocol Interface for SPI + * Provides functions for initialising, de-intitialising 802.11 device, + * sending/receiving raw packets etc + */ + +#include +#include /* For memcpy */ + +#include "cybsp.h" +#if (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SPI_INTERFACE) + + +#include "cy_result.h" +#include "cyabs_rtos.h" +#include "cyhal_gpio.h" + +#include "whd_thread.h" +#include "whd_chip.h" +#include "whd_sdpcm.h" +#include "whd_chip_constants.h" +#include "whd_int.h" +#include "whd_bus_spi_protocol.h" +#include "whd_bus_common.h" +#include "whd_chip_reg.h" +#include "whd_debug.h" +#include "whd_bus.h" +#include "whd_spi.h" +#include "whd_sdio.h" +#include "whd_buffer_api.h" +#include "whd_debug.h" +#include "whd_types_int.h" +#include "whd_resource_if.h" + + +/****************************************************** +* Constants +******************************************************/ + +#define F2_READY_TIMEOUT_MS (1000) +#define F2_READY_TIMEOUT_LOOPS (1000) +#define F1_READY_TIMEOUT_LOOPS (1000) +#define FEADBEAD_TIMEOUT_MS (500) +#define ALP_AVAIL_TIMEOUT_MS (100) + +/* function 1 OCP space */ +#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */ +#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 +#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */ + +#define HT_AVAIL_TIMEOUT_MS (1000) + +/* Taken from FALCON_5_90_195_26 dhd/sys/dhd_sdio.c. For 43362, MUST be >= 8 and word-aligned otherwise dongle fw crashes */ +#define SPI_F2_WATERMARK (32) + +#define GSPI_PACKET_AVAILABLE (1 << 8) +#define GSPI_UNDERFLOW (1 << 1) + +#define SWAP32_16BIT_PARTS(val) ( (uint32_t)( ( ( (uint32_t)(val) ) >> 16 ) + \ + ( ( ( (uint32_t)(val) ) & 0xffff ) << 16 ) ) ) + +#define WHD_BUS_GSPI_PACKET_OVERHEAD (sizeof(whd_buffer_header_t) ) + +#define MAX_GSPI_TRANSFER_LEN 2048 + +#define H32TO16LE(x) ( ( uint32_t )( ( ( ( uint32_t )(x) & ( uint32_t )0x000000ffU ) << 8 ) | \ + ( ( ( uint32_t )(x) & ( uint32_t )0x0000ff00U ) >> 8 ) | \ + ( ( ( uint32_t )(x) & ( uint32_t )0x00ff0000U ) << 8 ) | \ + ( ( ( uint32_t )(x) & ( uint32_t )0xff000000U ) >> 8 ) ) ) + +#define WHD_THREAD_POLL_TIMEOUT (CY_RTOS_NEVER_TIMEOUT) + +#define WHD_THREAD_POKE_TIMEOUT (100) + +#define HOSTINTMASK (I_HMB_SW_MASK) + +#define BT_POLLING_TIME (100) +#define ALIGNED_ADDRESS ( (uint32_t)0x3 ) +typedef enum +{ + GSPI_INCREMENT_ADDRESS = 1, GSPI_FIXED_ADDRESS = 0 +} gspi_transfer_access_t; + +/****************************************************** +* Structures +******************************************************/ + +#pragma pack(1) + +typedef struct +{ + whd_bus_gspi_header_t header; + uint8_t response_delay[4]; +} gspi_backplane_f1_read_header_t; + +#pragma pack() + +typedef struct +{ + gspi_backplane_f1_read_header_t gspi_header; + uint32_t data[1]; +} gspi_backplane_f1_read_packet_t; + +/****************************************************** +* Static variables +******************************************************/ + +static const uint8_t whd_bus_gspi_command_mapping[] = { 0, 1 }; + +/****************************************************** +* Structures +******************************************************/ +struct whd_bus_priv +{ + whd_spi_config_t spi_config; + cyhal_spi_t *spi_obj; + +}; + +/****************************************************** +* Variables +******************************************************/ + +/****************************************************** +* Static Function Declarations +******************************************************/ + +static whd_result_t whd_spi_download_firmware(whd_driver_t whd_driver); +static whd_result_t whd_bus_spi_transfer_buffer(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, whd_buffer_t buffer); +static whd_result_t whd_bus_spi_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, uint32_t image_size); +static whd_result_t whd_bus_spi_write_wifi_nvram_image(whd_driver_t whd_driver); +static whd_result_t whd_bus_spi_set_backplane_window(whd_driver_t whd_driver, uint32_t addr, uint32_t *curbase); +/****************************************************** +* Global Function definitions +******************************************************/ +uint32_t whd_bus_spi_bt_packet_available_to_read(whd_driver_t whd_driver); + +uint32_t whd_bus_spi_attach(whd_driver_t whd_driver, whd_spi_config_t *whd_spi_config, cyhal_spi_t *spi_obj) +{ + struct whd_bus_info *whd_bus_info; + + if (!whd_driver || !whd_spi_config) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + if (whd_spi_config->oob_config.host_oob_pin == CYHAL_NC_PIN_VALUE) + { + WPRINT_WHD_ERROR( ("OOB interrupt pin argument must be provided in %s\n", __FUNCTION__) ); + return WHD_BADARG; + } + + whd_bus_info = (whd_bus_info_t *)malloc(sizeof(whd_bus_info_t) ); + + if (whd_bus_info == NULL) + { + WPRINT_WHD_ERROR( ("Memory allocation failed for whd_bus_info in %s\n", __FUNCTION__) ); + return WHD_BUFFER_UNAVAILABLE_PERMANENT; + } + memset(whd_bus_info, 0, sizeof(whd_bus_info_t) ); + + whd_driver->bus_if = whd_bus_info; + + whd_driver->bus_priv = (struct whd_bus_priv *)malloc(sizeof(struct whd_bus_priv) ); + + if (whd_driver->bus_priv == NULL) + { + WPRINT_WHD_ERROR( ("Memory allocation failed for whd_bus_priv in %s\n", __FUNCTION__) ); + return WHD_BUFFER_UNAVAILABLE_PERMANENT; + } + memset(whd_driver->bus_priv, 0, sizeof(struct whd_bus_priv) ); + + /* Pass the SPI object to bus private spi_obj pointer */ + whd_driver->bus_priv->spi_obj = spi_obj; + whd_driver->bus_priv->spi_config = *whd_spi_config; + + whd_bus_info->whd_bus_init_fptr = whd_bus_spi_init; + whd_bus_info->whd_bus_deinit_fptr = whd_bus_spi_deinit; + + whd_bus_info->whd_bus_write_backplane_value_fptr = whd_bus_spi_write_backplane_value; + whd_bus_info->whd_bus_read_backplane_value_fptr = whd_bus_spi_read_backplane_value; + whd_bus_info->whd_bus_write_register_value_fptr = whd_bus_spi_write_register_value; + whd_bus_info->whd_bus_read_register_value_fptr = whd_bus_spi_read_register_value; + + whd_bus_info->whd_bus_send_buffer_fptr = whd_bus_spi_send_buffer; + whd_bus_info->whd_bus_transfer_bytes_fptr = whd_bus_spi_transfer_bytes; + + whd_bus_info->whd_bus_read_frame_fptr = whd_bus_spi_read_frame; + + whd_bus_info->whd_bus_packet_available_to_read_fptr = whd_bus_spi_packet_available_to_read; + whd_bus_info->whd_bus_poke_wlan_fptr = whd_bus_spi_poke_wlan; + whd_bus_info->whd_bus_wait_for_wlan_event_fptr = whd_bus_spi_wait_for_wlan_event; + + whd_bus_info->whd_bus_ack_interrupt_fptr = whd_bus_spi_ack_interrupt; + whd_bus_info->whd_bus_wake_interrupt_present_fptr = whd_bus_spi_wake_interrupt_present; + + whd_bus_info->whd_bus_wakeup_fptr = whd_bus_spi_wakeup; + whd_bus_info->whd_bus_sleep_fptr = whd_bus_spi_sleep; + + whd_bus_info->whd_bus_backplane_read_padd_size_fptr = whd_bus_spi_backplane_read_padd_size; + whd_bus_info->whd_bus_use_status_report_scheme_fptr = whd_bus_spi_use_status_report_scheme; + + whd_bus_info->whd_bus_get_max_transfer_size_fptr = whd_bus_spi_get_max_transfer_size; + + whd_bus_info->whd_bus_init_stats_fptr = whd_bus_spi_init_stats; + whd_bus_info->whd_bus_print_stats_fptr = whd_bus_spi_print_stats; + whd_bus_info->whd_bus_reinit_stats_fptr = whd_bus_spi_reinit_stats; + whd_bus_info->whd_bus_irq_register_fptr = whd_bus_spi_irq_register; + whd_bus_info->whd_bus_irq_enable_fptr = whd_bus_spi_irq_enable; + whd_bus_info->whd_bus_download_resource_fptr = whd_bus_spi_download_resource; + whd_bus_info->whd_bus_set_backplane_window_fptr = whd_bus_spi_set_backplane_window; + + return WHD_SUCCESS; +} + +void whd_bus_spi_detach(whd_driver_t whd_driver) +{ + if (whd_driver->bus_if != NULL) + { + free(whd_driver->bus_if); + whd_driver->bus_if = NULL; + } + if (whd_driver->bus_priv != NULL) + { + free(whd_driver->bus_priv); + whd_driver->bus_priv = NULL; + } +} + +whd_result_t whd_bus_spi_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + whd_result_t result = whd_bus_spi_transfer_buffer(whd_driver, BUS_WRITE, WLAN_FUNCTION, 0, buffer); + CHECK_RETURN(whd_buffer_release(whd_driver, buffer, WHD_NETWORK_TX) ); + if (result == WHD_SUCCESS) + { + DELAYED_BUS_RELEASE_SCHEDULE (whd_driver, WHD_TRUE); + } + CHECK_RETURN(result); + + return WHD_SUCCESS; +} + +/* + * Perform a transfer on the gSPI bus + * Prerequisites: length < MAX_GSPI_TRANSFER_LEN + */ +static whd_result_t whd_bus_spi_transfer_buffer(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, whd_buffer_t buffer) +{ + uint32_t *temp, addr; + whd_result_t result; + uint16_t newsize; + whd_buffer_header_t *header = (whd_buffer_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + whd_buffer_header_t *aligned_header = (whd_buffer_header_t *)whd_driver->aligned_addr; + whd_bus_gspi_header_t *gspi_header; + size_t transfer_size; + + uint16_t size = ( uint16_t )(whd_buffer_get_current_piece_size(whd_driver, buffer) - sizeof(whd_buffer_header_t) ); + CHECK_PACKET_NULL(header, WHD_NO_REGISTER_FUNCTION_POINTER); + /* Round size up to 32-bit alignment */ + newsize = (uint16_t)ROUND_UP(size, 4); + + /* Send the data */ + if (direction == BUS_WRITE) + { + /* Wait for FIFO to be ready to accept data */ + if (function == WLAN_FUNCTION) + { + uint32_t whd_bus_gspi_status; + uint32_t loop_count = 0; + while ( ( (result = + whd_bus_spi_read_register_value(whd_driver, BUS_FUNCTION, SPI_STATUS_REGISTER, (uint8_t)4, + (uint8_t *)&whd_bus_gspi_status) ) == WHD_SUCCESS ) && + ( (whd_bus_gspi_status & (1 << 5) ) == 0 ) && + (loop_count < ( uint32_t )F2_READY_TIMEOUT_LOOPS) ) + { + loop_count++; + } + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error reading register value, %s failed at %d \n", __func__, __LINE__) ); + return result; + } + if (loop_count >= ( uint32_t )F2_READY_TIMEOUT_LOOPS) + { + WPRINT_WHD_ERROR( ("Timeout waiting for data FIFO to be ready\n") ); + return WHD_TIMEOUT; + } + } + + } + + transfer_size = (size_t)(newsize + sizeof(whd_bus_gspi_header_t) ); + gspi_header = + (whd_bus_gspi_header_t *)( (char *)header->bus_header + MAX_BUS_HEADER_SIZE - + sizeof(whd_bus_gspi_header_t) ); + /* Form the gSPI header */ + addr = (uint32_t )header; + /* check 4byte alignment */ + if ( (addr & ALIGNED_ADDRESS) ) + { + if (aligned_header) + { + /* use memcpy to get aligned event message */ + memcpy(aligned_header, header, sizeof(*aligned_header) + size); + gspi_header = + (whd_bus_gspi_header_t *)( (char *)aligned_header->bus_header + MAX_BUS_HEADER_SIZE - + sizeof(whd_bus_gspi_header_t) ); + } + } + /* Form the gSPI header */ + *gspi_header = + ( whd_bus_gspi_header_t )( ( uint32_t )( (whd_bus_gspi_command_mapping[(int)direction] & 0x1) << 31 ) | + ( uint32_t )( (GSPI_INCREMENT_ADDRESS & 0x1) << 30 ) | + ( uint32_t )( (function & 0x3) << 28 ) | + ( uint32_t )( (address & 0x1FFFF) << 11 ) | ( uint32_t )( (size & 0x7FF) << 0 ) ); + + /* Reshuffle the bits if we're not in 32 bit mode */ + if (whd_driver->bus_gspi_32bit == WHD_FALSE) + { + /* Note: This typecast should always be valid if the buffer containing the GSpi packet has been correctly declared as 32-bit aligned */ + temp = (uint32_t *)gspi_header; + *temp = H32TO16LE(*temp); + } + + /* Send the data */ + if (direction == BUS_READ) + { + result = cyhal_spi_transfer(whd_driver->bus_priv->spi_obj, NULL, + sizeof(whd_bus_gspi_header_t), + (uint8_t *)gspi_header, + transfer_size, 0); + + } + else + { + result = cyhal_spi_transfer(whd_driver->bus_priv->spi_obj, (uint8_t *)gspi_header, transfer_size, NULL, + 0, 0); + } + + return result; +} + +whd_result_t whd_bus_spi_poke_wlan(whd_driver_t whd_driver) +{ + return WHD_SUCCESS; +} + +whd_result_t whd_bus_spi_ack_interrupt(whd_driver_t whd_driver, uint32_t intstatus) +{ + return whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SPI_INTERRUPT_REGISTER, (uint8_t)2, intstatus); +} + +uint32_t whd_bus_spi_bt_packet_available_to_read(whd_driver_t whd_driver) +{ + whd_bt_dev_t btdev = whd_driver->bt_dev; + uint32_t int_status = 0; + + if (btdev && btdev->bt_int_cb) + { + if (whd_bus_spi_read_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, + (uint8_t *)&int_status) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error reading interrupt status\n", __FUNCTION__) ); + int_status = 0; + } + + if ( (I_HMB_FC_CHANGE & int_status) != 0 ) + { + + if (whd_bus_spi_write_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, + int_status & I_HMB_FC_CHANGE) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error write interrupt status\n", __FUNCTION__) ); + int_status = 0; + } + btdev->bt_int_cb(btdev->bt_data); + } + } + + return 0; +} + +uint32_t whd_bus_spi_packet_available_to_read(whd_driver_t whd_driver) +{ + uint16_t interrupt_register; + uint32_t int_status = 0; + + CHECK_RETURN(whd_ensure_wlan_bus_is_up(whd_driver) ); + + whd_bus_spi_bt_packet_available_to_read(whd_driver); + /* Read the interrupt register */ + if (whd_bus_spi_read_register_value(whd_driver, BUS_FUNCTION, SPI_INTERRUPT_REGISTER, (uint8_t)2, + (uint8_t *)&interrupt_register) != WHD_SUCCESS) + { + goto return_with_error; + } + + if ( (interrupt_register & 0x0086) != 0 ) /* This should be 0x87, but occasional "data not available" errors are flagged seemingly for no reason */ + { + /* Error condition detected */ + WPRINT_WHD_DEBUG( ("Bus error condition detected\n") ); + } + /* Read the IntStatus */ + if (whd_bus_spi_read_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, + (uint8_t *)&int_status) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error reading interrupt status\n", __FUNCTION__) ); + int_status = 0; + goto return_with_error; + } + + if ( (HOSTINTMASK & int_status) != 0 ) + { + if (whd_bus_spi_write_backplane_value(whd_driver, (uint32_t)SDIO_INT_STATUS(whd_driver), (uint8_t)4, + int_status & HOSTINTMASK) != WHD_SUCCESS) + { + int_status = 0; + goto return_with_error; + } + + } + /* Clear interrupt register */ + if (interrupt_register != 0) + { + if (whd_bus_spi_write_register_value(whd_driver, BUS_FUNCTION, SPI_INTERRUPT_REGISTER, (uint8_t)2, + interrupt_register) != WHD_SUCCESS) + { + goto return_with_error; + } + } + + return ( uint32_t )( (interrupt_register) & (F2_PACKET_AVAILABLE) ); + +return_with_error: whd_assert("Error accessing backplane", 0 != 0); + return 0; +} + +whd_result_t whd_bus_spi_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer) +{ + uint32_t whd_bus_gspi_status; + whd_result_t result; + uint32_t whd_gspi_bytes_pending; + + /* Ensure the wlan backplane bus is up */ + CHECK_RETURN(whd_ensure_wlan_bus_is_up(whd_driver) ); + + do + { + result = whd_bus_spi_read_register_value(whd_driver, BUS_FUNCTION, SPI_STATUS_REGISTER, (uint8_t)4, + (uint8_t *)&whd_bus_gspi_status); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error reading register value, %s failed at %d \n", __func__, __LINE__) ); + return result; + } + } while (whd_bus_gspi_status == 0xFFFFFFFF); + + if ( (whd_bus_gspi_status & GSPI_PACKET_AVAILABLE) != 0 ) + { + if ( ( ( (whd_bus_gspi_status >> 9) & 0x7FF ) == 0 ) || + ( ( (whd_bus_gspi_status >> 9) & 0x7FF ) > (WHD_LINK_MTU - WHD_BUS_GSPI_PACKET_OVERHEAD) ) || + (whd_bus_gspi_status & GSPI_UNDERFLOW) ) + { + CHECK_RETURN(whd_bus_spi_write_register_value(whd_driver, BACKPLANE_FUNCTION, SPI_FRAME_CONTROL, 1, + (1 << 0) ) ); + return WHD_NO_PACKET_TO_RECEIVE; + } + } + + whd_gspi_bytes_pending = 0; + + if ( (whd_bus_gspi_status & GSPI_PACKET_AVAILABLE) != 0 ) + { + whd_gspi_bytes_pending = ( (whd_bus_gspi_status >> 9) & 0x7FF ); + } + + if (whd_gspi_bytes_pending == 0) + { + return WHD_NO_PACKET_TO_RECEIVE; + } + + /* Allocate a suitable buffer */ + result = whd_host_buffer_get(whd_driver, buffer, WHD_NETWORK_RX, + (uint16_t)(whd_gspi_bytes_pending + WHD_BUS_GSPI_PACKET_OVERHEAD), + (whd_sdpcm_has_tx_packet(whd_driver) ? 0 : WHD_RX_BUF_TIMEOUT) ); + + if (result != WHD_SUCCESS) + { + /* Read out the first 12 bytes to get the bus credit information */ + uint8_t temp_buffer[12 + MAX_BUS_HEADER_SIZE]; + CHECK_RETURN(whd_bus_spi_transfer_bytes(whd_driver, BUS_READ, WLAN_FUNCTION, 0, 12, + (whd_transfer_bytes_packet_t *)temp_buffer) ); + + /* Abort the transfer to force the packet to be dropped */ + if (whd_gspi_bytes_pending > 12) + { + CHECK_RETURN(whd_bus_spi_write_register_value(whd_driver, BACKPLANE_FUNCTION, SPI_FRAME_CONTROL, 1, + (1 << 0) ) ); + } + + /* Process bus data credit information */ + whd_sdpcm_update_credit(whd_driver, (uint8_t *)(temp_buffer + sizeof(whd_bus_header_t) ) ); + WPRINT_WHD_ERROR( ("Packet buffer allocation failed in %s at %d \n", __func__, __LINE__) ); + return result; + } + + result = whd_bus_spi_transfer_buffer(whd_driver, BUS_READ, WLAN_FUNCTION, 0, *buffer); + if (result != WHD_SUCCESS) + { + CHECK_RETURN(whd_buffer_release(whd_driver, *buffer, WHD_NETWORK_RX) ); + WPRINT_WHD_ERROR( ("SPI buffer transfer failed in %s at %d \n", __func__, __LINE__) ); + return result; + } + + DELAYED_BUS_RELEASE_SCHEDULE (whd_driver, WHD_TRUE); + return WHD_SUCCESS; +} + +whd_result_t whd_bus_spi_init(whd_driver_t whd_driver) +{ + uint32_t data = 0; + uint32_t whd_bus_gspi_status; + uint16_t data16 = 0; + uint32_t loop_count; + whd_result_t result; + uint8_t init_data[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint32_t interrupt_polarity = 0; + uint16_t chip_id; + size_t transfer_size = 12; + uint8_t *aligned_addr = NULL; + whd_oob_config_t *config = &whd_driver->bus_priv->spi_config.oob_config; + + whd_driver->bus_gspi_32bit = WHD_FALSE; + + if (config->is_falling_edge == WHD_FALSE) + interrupt_polarity = INTERRUPT_POLARITY_HIGH; + + whd_bus_init_backplane_window(whd_driver); + + whd_bus_gspi_header_t *gspi_header = (whd_bus_gspi_header_t *)init_data; + + /* Due to an chip issue, the first transfer will be corrupted. + * This means a repeated safe read of a known value register is required until + * the correct value is returned - signalling the bus is running. + * This known value register must be accessed using fixed (non-incrementing) address + * mode, hence a custom packet header must be constructed + * Due to the chip issue, the data received could be left shifted by one bit. + */ + loop_count = 0; + do + { + /* Header needs to calculated every time as init_data gets modified in cyhal_spi_transfer() */ + *gspi_header = + ( whd_bus_gspi_header_t )SWAP32_16BIT_PARTS(SWAP32( (uint32_t)( (whd_bus_gspi_command_mapping[(int)BUS_READ] + & 0x1) << 31 ) | + (uint32_t)( (GSPI_FIXED_ADDRESS & 0x1) << 30 ) | + (uint32_t)( (BUS_FUNCTION & 0x3) << 28 ) | + (uint32_t)( (SPI_READ_TEST_REGISTER & 0x1FFFFu) << + 11 ) | + (uint32_t)( (4u /*size*/ & 0x7FFu) << 0 ) ) ); + CHECK_RETURN(cyhal_spi_transfer(whd_driver->bus_priv->spi_obj, NULL, sizeof(whd_bus_gspi_header_t), + init_data, transfer_size, 0) ); + loop_count++; + } while ( (NULL == memchr(&init_data[4], SPI_READ_TEST_REG_LSB, (size_t)8) ) && + (NULL == memchr(&init_data[4], SPI_READ_TEST_REG_LSB_SFT1, (size_t)8) ) && + (NULL == memchr(&init_data[4], SPI_READ_TEST_REG_LSB_SFT2, (size_t)8) ) && + (NULL == memchr(&init_data[4], SPI_READ_TEST_REG_LSB_SFT3, (size_t)8) ) && + (loop_count < ( uint32_t )FEADBEAD_TIMEOUT_MS) && + (cy_rtos_delay_milliseconds( (uint32_t)1 ), (1 == 1) ) ); + + /* Register interrupt handler */ + whd_bus_spi_irq_register(whd_driver); + /* Enable SPI IRQ */ + whd_bus_spi_irq_enable(whd_driver, WHD_TRUE); + + /* Keep/reset defaults for registers 0x0-0x4 except for, 0x0: Change word length to 32bit, + * set endianness, enable wakeup. 0x2: enable interrupt with status. */ +#if defined(IL_BIGENDIAN) + CHECK_RETURN(whd_bus_spi_write_register_value(whd_driver, BUS_FUNCTION, SPI_BUS_CONTROL, (uint8_t)4, + (uint32_t)(WORD_LENGTH_32 | (0 & ENDIAN_BIG) | + (interrupt_polarity & INTERRUPT_POLARITY_HIGH) | WAKE_UP | + (0x4 << (8 * SPI_RESPONSE_DELAY) ) | + ( (0 & STATUS_ENABLE) << (8 * SPI_STATUS_ENABLE) ) | + (INTR_WITH_STATUS << (8 * SPI_STATUS_ENABLE) ) ) ) ); +#else + CHECK_RETURN(whd_bus_spi_write_register_value(whd_driver, BUS_FUNCTION, SPI_BUS_CONTROL, (uint8_t)4, + ( uint32_t )(WORD_LENGTH_32 | ENDIAN_BIG | + (interrupt_polarity & INTERRUPT_POLARITY_HIGH) | + WAKE_UP | (0x4 << (8 * SPI_RESPONSE_DELAY) ) | + ( (0 & STATUS_ENABLE) << (8 * SPI_STATUS_ENABLE) ) | + (INTR_WITH_STATUS << (8 * SPI_STATUS_ENABLE) ) ) ) ); +#endif + whd_driver->bus_gspi_32bit = WHD_TRUE; + CHECK_RETURN(whd_bus_spi_read_register_value(whd_driver, BUS_FUNCTION, SPI_BUS_CONTROL, (uint8_t)4, + (uint8_t *)&data) ); + + if (whd_driver->bus_priv->spi_config.is_spi_normal_mode) + { + /* Reset host SPI interface to re-sync */ + /*host_platform_bus_init( );*/ + } + + /* Check feedbead can be read - i.e. the device is alive */ + data = 0; + CHECK_RETURN(whd_bus_spi_read_register_value(whd_driver, BUS_FUNCTION, SPI_READ_TEST_REGISTER, (uint8_t)4, + (uint8_t *)&data) ); + + if (data != SPI_READ_TEST_REGISTER_VALUE) + { + WPRINT_WHD_ERROR( ("Read %x, instead of 0xFEEDBEAD from the WLAN chip\n", (unsigned int)data) ); + return WHD_SPI_ID_READ_FAIL; + } + + /* Make sure error interrupt bits are clear */ + CHECK_RETURN(whd_bus_spi_write_register_value(whd_driver, BUS_FUNCTION, SPI_INTERRUPT_REGISTER, (uint8_t)1, + ( uint32_t )(DATA_UNAVAILABLE | COMMAND_ERROR | DATA_ERROR | + F1_OVERFLOW) ) ); + + /* Enable a selection of interrupts */ + CHECK_RETURN(whd_bus_spi_write_register_value(whd_driver, BUS_FUNCTION, SPI_INTERRUPT_ENABLE_REGISTER, (uint8_t)2, + ( uint32_t )(F2_F3_FIFO_RD_UNDERFLOW | F2_F3_FIFO_WR_OVERFLOW | + COMMAND_ERROR | DATA_ERROR | F2_PACKET_AVAILABLE | + F1_OVERFLOW) ) ); + + /* Request ALP */ + CHECK_RETURN(whd_bus_spi_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, + SBSDIO_ALP_AVAIL_REQ) ); + + /* Wait until ALP is available */ + loop_count = 0; + while ( ( (result = whd_bus_spi_read_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)2, + (uint8_t *)&data16) ) == WHD_SUCCESS ) && + ( (data16 & SBSDIO_ALP_AVAIL) == 0 ) && + (loop_count < ( uint32_t )ALP_AVAIL_TIMEOUT_MS) ) + { + cy_rtos_delay_milliseconds( (uint32_t)1 ); + loop_count++; + } + if (loop_count >= ( uint32_t )ALP_AVAIL_TIMEOUT_MS) + { + WPRINT_WHD_ERROR( ("ALP Clock timeout\n") ); + return WHD_TIMEOUT; + } + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Can't read SDIO_CHIP_CLOCK_CSR\n") ); + return result; + } + + /* Clear request for ALP */ + CHECK_RETURN(whd_bus_spi_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, + (uint32_t)0) ); + + /* Read the chip id */ + CHECK_RETURN(whd_bus_spi_read_backplane_value(whd_driver, CHIPCOMMON_BASE_ADDRESS, 2, (uint8_t *)&chip_id) ); + whd_chip_set_chip_id(whd_driver, chip_id); + + /* Download the firmware */ + result = whd_spi_download_firmware(whd_driver); + + /* user abort */ + if (result == WHD_UNFINISHED) + { + /* host_platform_reset_wifi (WHD_TRUE); */ + /* host_platform_power_wifi (WHD_FALSE); */ + WPRINT_WHD_ERROR( ("User aborted download of firmware\n") ); + return result; + } + + /* non user abort error */ + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Could not download firmware\n") ); + return result; + } + /* else, successfully downloaded the firmware; continue with waiting for WIFi to live */ + + /* Wait for F2 to be ready */ + loop_count = 0; + while ( ( (result = whd_bus_spi_read_register_value(whd_driver, BUS_FUNCTION, SPI_STATUS_REGISTER, (uint8_t)4, + (uint8_t *)&whd_bus_gspi_status) ) == WHD_SUCCESS ) && + ( (whd_bus_gspi_status & (1 << 5) ) == 0 ) && + (loop_count < ( uint32_t )F2_READY_TIMEOUT_MS) ) + { + cy_rtos_delay_milliseconds( (uint32_t)1 ); + loop_count++; + } + if (loop_count >= ( uint32_t )F2_READY_TIMEOUT_MS) + { + /* If your system fails here, it could be due to incorrect NVRAM variables. + * Check which 'wifi_nvram_image.h' file your platform is using, and + * check that it matches the WLAN device on your platform, including the + * crystal frequency. + */ + WPRINT_WHD_ERROR( ("Timeout while waiting for function 2 to be ready\n") ); + return WHD_TIMEOUT; + } + if (whd_driver->aligned_addr == NULL) + { + if ( (aligned_addr = malloc(WHD_LINK_MTU) ) == NULL ) + { + WPRINT_WHD_ERROR( ("Memory allocation failed for aligned_addr in %s \n", __FUNCTION__) ); + return WHD_MALLOC_FAILURE; + } + whd_driver->aligned_addr = aligned_addr; + } + result = whd_chip_specific_init(whd_driver); + if (result != WHD_SUCCESS) + { + free(whd_driver->aligned_addr); + whd_driver->aligned_addr = NULL; + } + CHECK_RETURN(result); + result = whd_ensure_wlan_bus_is_up(whd_driver); + if (result != WHD_SUCCESS) + { + free(whd_driver->aligned_addr); + whd_driver->aligned_addr = NULL; + } + CHECK_RETURN(result); + return result; +} + +whd_result_t whd_bus_spi_deinit(whd_driver_t whd_driver) +{ + CHECK_RETURN(whd_allow_wlan_bus_to_sleep(whd_driver) ); + + /* put device in reset. */ + //host_platform_reset_wifi (WHD_TRUE); + if (whd_driver->aligned_addr) + { + free(whd_driver->aligned_addr); + whd_driver->aligned_addr = NULL; + } + whd_bus_set_resource_download_halt(whd_driver, WHD_FALSE); + DELAYED_BUS_RELEASE_SCHEDULE (whd_driver, WHD_FALSE); + return WHD_SUCCESS; +} + +whd_bool_t whd_bus_spi_wake_interrupt_present(whd_driver_t whd_driver) +{ + /* functionality is only currently needed and present on SDIO */ + return WHD_FALSE; +} + +whd_result_t whd_bus_spi_wait_for_wlan_event(whd_driver_t whd_driver, cy_semaphore_t *transceive_semaphore) +{ + whd_result_t result = WHD_SUCCESS; + uint32_t timeout_ms = 1; + whd_bt_dev_t btdev = whd_driver->bt_dev; + uint32_t delayed_release_timeout_ms; + + REFERENCE_DEBUG_ONLY_VARIABLE(result); + + delayed_release_timeout_ms = whd_bus_handle_delayed_release(whd_driver); + if (delayed_release_timeout_ms != 0) + { + timeout_ms = delayed_release_timeout_ms; + } + else if ( (btdev && !btdev->intr) ) + { + timeout_ms = BT_POLLING_TIME; + whd_driver->thread_info.bus_interrupt = WHD_TRUE; + } + else + { + result = whd_allow_wlan_bus_to_sleep(whd_driver); + whd_assert("Error setting wlan sleep", (result == WHD_SUCCESS) || (result == WHD_PENDING) ); + + if (result == WHD_SUCCESS) + { + timeout_ms = CY_RTOS_NEVER_TIMEOUT; + } + } + + /* Check if we have run out of bus credits */ + if (whd_sdpcm_get_available_credits(whd_driver) == 0) + { + /* Keep poking the WLAN until it gives us more credits */ + result = whd_bus_spi_poke_wlan(whd_driver); + whd_assert("Poking failed!", result == WHD_SUCCESS); + + result = cy_rtos_get_semaphore(transceive_semaphore, (uint32_t)MIN_OF(timeout_ms, + WHD_THREAD_POKE_TIMEOUT), WHD_FALSE); + } + else + { + result = cy_rtos_get_semaphore(transceive_semaphore, (uint32_t)MIN_OF(timeout_ms, + WHD_THREAD_POLL_TIMEOUT), WHD_FALSE); + } + whd_assert("Could not get whd sleep semaphore\n", (result == CY_RSLT_SUCCESS) || (result == CY_RTOS_TIMEOUT) ); + + return result; +} + +/****************************************************** +* Function definitions for Protocol Common +******************************************************/ + +/* + * Write a value to a register NOT on the backplane + * Prerequisites: value_length <= 4 + */ +whd_result_t whd_bus_spi_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function, uint32_t address, + uint8_t value_length, uint32_t value) +{ + char gspi_internal_buffer[MAX_BUS_HEADER_SIZE + sizeof(uint32_t) + sizeof(uint32_t)] = {0}; + whd_transfer_bytes_packet_t *internal_gspi_packet = (whd_transfer_bytes_packet_t *)gspi_internal_buffer; + + /* Flip the bytes if we're not in 32 bit mode */ + if (whd_driver->bus_gspi_32bit == WHD_FALSE) + { + value = H32TO16LE(value); + } + /* Write the value and value_length into the packet */ + internal_gspi_packet->data[0] = value; + + /* Send it off */ + return whd_bus_spi_transfer_bytes(whd_driver, BUS_WRITE, function, address, value_length, internal_gspi_packet); +} + +/* + * Read the value of a register NOT on the backplane + * Prerequisites: value_length <= 4 + */ +whd_result_t whd_bus_spi_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function, uint32_t address, + uint8_t value_length, uint8_t *value) +{ + uint32_t *data_ptr; + whd_result_t result; + uint8_t padding = 0; + + char gspi_internal_buffer[MAX_BUS_HEADER_SIZE + sizeof(uint32_t) + sizeof(uint32_t)] = {0}; + + /* Clear the receiving part of memory and set the value_length */ + if (function == BACKPLANE_FUNCTION) + { + gspi_backplane_f1_read_packet_t *pkt = + (gspi_backplane_f1_read_packet_t *)(gspi_internal_buffer + MAX_BUS_HEADER_SIZE - + sizeof(whd_bus_gspi_header_t) ); + data_ptr = pkt->data; + padding = 4; /* Add response delay */ + } + else + { + whd_transfer_bytes_packet_t *pkt = (whd_transfer_bytes_packet_t *)gspi_internal_buffer; + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + data_ptr = pkt->data; + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + } + + *data_ptr = 0; + result = + whd_bus_spi_transfer_bytes(whd_driver, BUS_READ, function, address, ( uint16_t )(value_length + padding), + (whd_transfer_bytes_packet_t *)gspi_internal_buffer); + + memcpy(value, data_ptr, value_length); + + return result; +} + +/* + * Write a value to a register on the backplane + * Prerequisites: value_length <= 4 + */ +whd_result_t whd_bus_spi_write_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint32_t value) +{ + CHECK_RETURN(whd_bus_set_backplane_window(whd_driver, address) ); + + address &= SBSDIO_SB_OFT_ADDR_MASK; + + if (register_length == 4) + address |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + return whd_bus_spi_write_register_value(whd_driver, BACKPLANE_FUNCTION, address, register_length, value); +} + +/* + * Read the value of a register on the backplane + * Prerequisites: value_length <= 4 + */ +whd_result_t whd_bus_spi_read_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint8_t *value) +{ + *value = 0; + CHECK_RETURN(whd_bus_set_backplane_window(whd_driver, address) ); + + address &= SBSDIO_SB_OFT_ADDR_MASK; + + if (register_length == 4) + address |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + return whd_bus_spi_read_register_value(whd_driver, BACKPLANE_FUNCTION, address, register_length, value); +} + +whd_result_t whd_bus_spi_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t size, + whd_transfer_bytes_packet_t *packet) +{ + uint32_t *temp; + whd_result_t result; + uint16_t newsize; + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + whd_bus_gspi_header_t *gspi_header = + (whd_bus_gspi_header_t *)( (char *)packet->data - sizeof(whd_bus_gspi_header_t) ); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + size_t transfer_size; + + *gspi_header = + ( whd_bus_gspi_header_t )( ( uint32_t )( (whd_bus_gspi_command_mapping[(int)direction] & 0x1) << 31 ) | + ( uint32_t )( (GSPI_INCREMENT_ADDRESS & 0x1) << 30 ) | + ( uint32_t )( (function & 0x3) << 28 ) | + ( uint32_t )( (address & 0x1FFFF) << 11 ) | ( uint32_t )( (size & 0x7FF) << 0 ) ); + + /* Reshuffle the bits if we're not in 32 bit mode */ + if (whd_driver->bus_gspi_32bit == WHD_FALSE) + { + /* Note: This typecast should always be valid if the buffer + * containing the GSpi packet has been correctly declared as 32-bit aligned */ + temp = (uint32_t *)gspi_header; + *temp = H32TO16LE(*temp); + } + + /* Round size up to 32-bit alignment */ + newsize = (uint16_t)ROUND_UP(size, 4); + + /* Ensure we are clear to write */ + if ( (direction == BUS_WRITE) && (function == WLAN_FUNCTION) ) + { + uint32_t whd_bus_gspi_status; + uint32_t loop_count = 0; + + /* Verify the SDPCM size and stated size match */ + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + uint16_t *frametag_ptr = (uint16_t *)&packet->data; + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + if (size != *frametag_ptr) + { + WPRINT_WHD_DEBUG( ("Error - gSPI size does not match SDPCM size!\n") ); + return WHD_SPI_SIZE_MISMATCH; + } + + /* Wait for WLAN FIFO to be ready to accept data */ + while ( ( (result = + whd_bus_spi_read_register_value(whd_driver, BUS_FUNCTION, SPI_STATUS_REGISTER, (uint8_t)4, + (uint8_t *)&whd_bus_gspi_status) ) == WHD_SUCCESS ) && + ( (whd_bus_gspi_status & (1 << 5) ) == 0 ) && + (loop_count < ( uint32_t )F2_READY_TIMEOUT_LOOPS) ) + { + ++loop_count; + } + + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Failed to read SPI register value in %s at %d \n", __func__, __LINE__) ); + return result; + } + + if (loop_count >= ( uint32_t )F2_READY_TIMEOUT_LOOPS) + { + WPRINT_WHD_DEBUG( ("Timeout waiting for data FIFO to be ready\n") ); + return WHD_TIMEOUT; + } + + } + + transfer_size = (size_t)(newsize + sizeof(whd_bus_gspi_header_t) ); + + /* Send the data */ + if (direction == BUS_READ) + { + result = cyhal_spi_transfer(whd_driver->bus_priv->spi_obj, NULL, + sizeof(whd_bus_gspi_header_t), + (uint8_t *)gspi_header, + transfer_size, 0); + } + else + { + result = cyhal_spi_transfer(whd_driver->bus_priv->spi_obj, (uint8_t *)gspi_header, transfer_size, NULL, + 0, 0); + } + + CHECK_RETURN(result); + return WHD_SUCCESS; +} + +/****************************************************** +* Static Function definitions +******************************************************/ + +static whd_result_t whd_spi_download_firmware(whd_driver_t whd_driver) +{ + uint8_t csr_val; + whd_result_t result; + uint32_t loop_count = 0; + + CHECK_RETURN(whd_disable_device_core(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_NONE) ); + CHECK_RETURN(whd_disable_device_core(whd_driver, SOCRAM_CORE, WLAN_CORE_FLAG_NONE) ); + CHECK_RETURN(whd_reset_device_core(whd_driver, SOCRAM_CORE, WLAN_CORE_FLAG_NONE) ); + + CHECK_RETURN(whd_chip_specific_socsram_init(whd_driver) ); + + CHECK_RETURN(whd_bus_write_wifi_firmware_image(whd_driver) ); + CHECK_RETURN(whd_bus_spi_write_wifi_nvram_image(whd_driver) ); + + /* Take the ARM core out of reset */ + CHECK_RETURN(whd_reset_device_core(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_NONE) ); + result = whd_device_core_is_up(whd_driver, WLAN_ARM_CORE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Could not bring ARM core up\n") ); + return result; + } + + /* Wait until the HT clock is available */ + while ( ( (result = + whd_bus_spi_read_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_CHIP_CLOCK_CSR, (uint8_t)1, + &csr_val) ) == WHD_SUCCESS ) && + ( (csr_val & SBSDIO_HT_AVAIL) == 0 ) && + (loop_count < ( uint32_t )HT_AVAIL_TIMEOUT_MS) ) + { + cy_rtos_delay_milliseconds( (uint32_t)1 ); + loop_count++; + } + if (loop_count >= ( uint32_t )HT_AVAIL_TIMEOUT_MS) + { + return WHD_TIMEOUT; + } + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("HT clock not available\n") ); + return result; + } + + /* Set up the interrupt mask and enable interrupts */ + CHECK_RETURN(whd_bus_spi_write_backplane_value(whd_driver, SDIO_INT_HOST_MASK( + whd_driver), (uint8_t)4, I_HMB_SW_MASK) ); + + /* Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped. */ + return whd_bus_spi_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_FUNCTION2_WATERMARK, (uint8_t)1, + ( uint32_t )SPI_F2_WATERMARK); +} + +whd_result_t whd_bus_spi_wakeup(whd_driver_t whd_driver) +{ + uint32_t spi_bus_reg_value; + + /* Wake up WLAN SPI interface module */ + CHECK_RETURN(whd_bus_spi_read_register_value(whd_driver, BUS_FUNCTION, SPI_BUS_CONTROL, sizeof(uint32_t), + (uint8_t *)&spi_bus_reg_value) ); + spi_bus_reg_value |= ( uint32_t )(WAKE_UP); + return whd_bus_spi_write_register_value(whd_driver, BUS_FUNCTION, SPI_BUS_CONTROL, sizeof(uint32_t), + spi_bus_reg_value); +} + +whd_result_t whd_bus_spi_sleep(whd_driver_t whd_driver) +{ + uint32_t spi_bus_reg_value; + + /* Put SPI interface block to sleep */ + CHECK_RETURN(whd_bus_spi_read_register_value(whd_driver, BUS_FUNCTION, SPI_BUS_CONTROL, sizeof(uint32_t), + (uint8_t *)&spi_bus_reg_value) ); + spi_bus_reg_value &= ~( uint32_t )(WAKE_UP); + return whd_bus_spi_write_register_value(whd_driver, BUS_FUNCTION, SPI_BUS_CONTROL, sizeof(uint32_t), + spi_bus_reg_value); +} + +void whd_bus_spi_init_stats(whd_driver_t whd_driver) +{ + whd_bt_dev_t btdev = whd_driver->bt_dev; + + if (btdev && btdev->intr) + { + whd_result_t res; + /* Enable F1 INT in order to receive interrupt from BT FW with HMB_FC_CHANGED in SPI */ + res = whd_bus_write_register_value(whd_driver, BUS_FUNCTION, (uint32_t)SPI_INTERRUPT_ENABLE_REGISTER, + (uint8_t)2, + ( uint32_t )(F1_INTR | F2_F3_FIFO_RD_UNDERFLOW | F2_F3_FIFO_WR_OVERFLOW | + COMMAND_ERROR | DATA_ERROR | F2_PACKET_AVAILABLE | + F1_OVERFLOW) ); + if (res != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("spi interrupt register failed to enable\n") ); + } + + res = whd_bus_spi_write_backplane_value(whd_driver, SDIO_INT_HOST_MASK( + whd_driver), (uint8_t)4, I_HMB_FC_CHANGE); + if (res != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("sdio int host mask failed to enable\n") ); + } + } +} + +whd_result_t whd_bus_spi_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print) +{ + return WHD_TRUE; +} + +/* Waking the firmware up from Deep Sleep */ +whd_result_t whd_bus_spi_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware) +{ + return WHD_TRUE; +} + +uint8_t whd_bus_spi_backplane_read_padd_size(whd_driver_t whd_driver) +{ + return WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE; +} + +whd_bool_t whd_bus_spi_use_status_report_scheme(whd_driver_t whd_driver) +{ + return WHD_FALSE; +} + +uint32_t whd_bus_spi_get_max_transfer_size(whd_driver_t whd_driver) +{ + return WHD_BUS_SPI_MAX_BACKPLANE_TRANSFER_SIZE; +} + +#if (CYHAL_API_VERSION >= 2) +static void whd_bus_spi_oob_irq_handler(void *arg, cyhal_gpio_event_t event) +#else +static void whd_bus_spi_oob_irq_handler(void *arg, cyhal_gpio_irq_event_t event) +#endif +{ + whd_driver_t whd_driver = (whd_driver_t)arg; + const whd_oob_config_t *config = &whd_driver->bus_priv->spi_config.oob_config; +#if (CYHAL_API_VERSION >= 2) + const cyhal_gpio_event_t expected_event = (config->is_falling_edge == WHD_TRUE) + ? CYHAL_GPIO_IRQ_FALL : CYHAL_GPIO_IRQ_RISE; +#else + const cyhal_gpio_irq_event_t expected_event = (config->is_falling_edge == WHD_TRUE) + ? CYHAL_GPIO_IRQ_FALL : CYHAL_GPIO_IRQ_RISE; +#endif + if (event != expected_event) + { + WPRINT_WHD_ERROR( ("Unexpected interrupt event %d\n", event) ); + + return; + } + + /* call thread notify to wake up WHD thread */ + whd_thread_notify_irq(whd_driver); +} + +/* XXX FIXME */ +#define WLAN_INTR_PRIORITY 1 +whd_result_t whd_bus_spi_irq_register(whd_driver_t whd_driver) +{ + const whd_oob_config_t *config = &whd_driver->bus_priv->spi_config.oob_config; + + cyhal_gpio_init(config->host_oob_pin, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_ANALOG, + (config->is_falling_edge == WHD_TRUE) ? 1 : 0); +#if (CYHAL_API_VERSION >= 2) + static cyhal_gpio_callback_data_t cbdata; + cbdata.callback = whd_bus_spi_oob_irq_handler; + cbdata.callback_arg = whd_driver; + cyhal_gpio_register_callback(config->host_oob_pin, &cbdata); +#else + cyhal_gpio_register_irq(config->host_oob_pin, WLAN_INTR_PRIORITY, whd_bus_spi_oob_irq_handler, + whd_driver); +#endif + return WHD_TRUE; +} + +whd_result_t whd_bus_spi_irq_enable(whd_driver_t whd_driver, whd_bool_t enable) +{ + const whd_oob_config_t *config = &whd_driver->bus_priv->spi_config.oob_config; +#if (CYHAL_API_VERSION >= 2) + const cyhal_gpio_event_t event = + (config->is_falling_edge == WHD_TRUE) ? CYHAL_GPIO_IRQ_FALL : CYHAL_GPIO_IRQ_RISE; + + cyhal_gpio_enable_event(config->host_oob_pin, event, WLAN_INTR_PRIORITY, (enable == WHD_TRUE) ? true : false); +#else + const cyhal_gpio_irq_event_t event = + (config->is_falling_edge == WHD_TRUE) ? CYHAL_GPIO_IRQ_FALL : CYHAL_GPIO_IRQ_RISE; + + cyhal_gpio_irq_enable(config->host_oob_pin, event, (enable == WHD_TRUE) ? true : false); +#endif + return WHD_TRUE; +} + +static whd_result_t whd_bus_spi_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource, + whd_bool_t direct_resource, uint32_t address, uint32_t image_size) +{ + whd_result_t result = WHD_SUCCESS; + uint8_t *image; + uint32_t blocks_count = 0; + uint32_t i; + uint32_t size_out; + uint32_t reset_instr = 0; + + result = whd_get_resource_no_of_blocks(whd_driver, resource, &blocks_count); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Fatal error: download_resource blocks count not known, %s failed at line %d \n", __func__, + __LINE__) ); + goto exit; + } + + for (i = 0; i < blocks_count; i++) + { + CHECK_RETURN(whd_get_resource_block(whd_driver, resource, i, (const uint8_t **)&image, &size_out) ); + if ( (resource == WHD_RESOURCE_WLAN_FIRMWARE) && (reset_instr == 0) ) + { + /* Copy the starting address of the firmware into a global variable */ + reset_instr = *( (uint32_t *)(&image[0]) ); + } + result = whd_bus_transfer_backplane_bytes(whd_driver, BUS_WRITE, address, size_out, &image[0]); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Failed to write firmware image\n", __FUNCTION__) ); + goto exit; + } + address += size_out; + } + + /* Below part of the code is applicable to arm_CR4 type chips only + * The CR4 chips by default firmware is not loaded at 0. So we need + * load the first 32 bytes with the offset of the firmware load address + * which is been copied before during the firmware download + */ + if ( (address != 0) && (reset_instr != 0) ) + { + /* write address 0 with reset instruction */ + result = whd_bus_write_backplane_value(whd_driver, 0, sizeof(reset_instr), reset_instr); + + if (result == WHD_SUCCESS) + { + uint32_t tmp; + + /* verify reset instruction value */ + result = whd_bus_read_backplane_value(whd_driver, 0, sizeof(tmp), (uint8_t *)&tmp); + + if ( (result == WHD_SUCCESS) && (tmp != reset_instr) ) + { + WPRINT_WHD_ERROR( ("%s: Failed to write 0x%08" PRIx32 " to addr 0\n", __FUNCTION__, reset_instr) ); + WPRINT_WHD_ERROR( ("%s: contents of addr 0 is 0x%08" PRIx32 "\n", __FUNCTION__, tmp) ); + return WHD_WLAN_SDIO_ERROR; + } + } + } +exit: return result; +} + +static whd_result_t whd_bus_spi_write_wifi_nvram_image(whd_driver_t whd_driver) +{ + uint32_t img_base; + uint32_t img_end; + uint32_t image_size; + + /* Get the size of the variable image */ + CHECK_RETURN(whd_resource_size(whd_driver, WHD_RESOURCE_WLAN_NVRAM, &image_size) ); + + /* Round up the size of the image */ + image_size = ROUND_UP(image_size, 4); + + /* Write image */ + img_end = GET_C_VAR(whd_driver, CHIP_RAM_SIZE) - 4; + img_base = (img_end - image_size); + img_base += GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS); + + CHECK_RETURN(whd_bus_spi_download_resource(whd_driver, WHD_RESOURCE_WLAN_NVRAM, WHD_FALSE, img_base, image_size) ); + + /* Write the variable image size at the end */ + image_size = (~(image_size / 4) << 16) | (image_size / 4); + + img_end += GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS); + + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, (uint32_t)img_end, 4, image_size) ); + return WHD_SUCCESS; +} + +/* + * Update the backplane window registers + */ +static whd_result_t whd_bus_spi_set_backplane_window(whd_driver_t whd_driver, uint32_t addr, uint32_t *curbase) +{ + whd_result_t result = WHD_BUS_WRITE_REGISTER_ERROR; + uint32_t base = addr & ( (uint32_t) ~BACKPLANE_ADDRESS_MASK ); + const uint32_t upper_32bit_mask = 0xFF000000; + const uint32_t upper_middle_32bit_mask = 0x00FF0000; + const uint32_t lower_middle_32bit_mask = 0x0000FF00; + + if (base == *curbase) + { + return WHD_SUCCESS; + } + if ( (base & upper_32bit_mask) != (*curbase & upper_32bit_mask) ) + { + if (WHD_SUCCESS != + (result = whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_BACKPLANE_ADDRESS_HIGH, + (uint8_t)1, (base >> 24) ) ) ) + { + WPRINT_WHD_ERROR( ("Failed to write register value to the bus, %s failed at %d \n", __func__, + __LINE__) ); + return result; + } + /* clear old */ + *curbase &= ~upper_32bit_mask; + /* set new */ + *curbase |= (base & upper_32bit_mask); + } + + if ( (base & upper_middle_32bit_mask) != + (*curbase & upper_middle_32bit_mask) ) + { + if (WHD_SUCCESS != + (result = whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_BACKPLANE_ADDRESS_MID, + (uint8_t)1, (base >> 16) ) ) ) + { + WPRINT_WHD_ERROR( ("Failed to write register value to the bus, %s failed at %d \n", __func__, + __LINE__) ); + return result; + } + /* clear old */ + *curbase &= ~upper_middle_32bit_mask; + /* set new */ + *curbase |= (base & upper_middle_32bit_mask); + } + + if ( (base & lower_middle_32bit_mask) != + (*curbase & lower_middle_32bit_mask) ) + { + if (WHD_SUCCESS != + (result = whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_BACKPLANE_ADDRESS_LOW, + (uint8_t)1, (base >> 8) ) ) ) + { + WPRINT_WHD_ERROR( ("Failed to write register value to the bus, %s failed at %d \n", __func__, + __LINE__) ); + return result; + } + + /* clear old */ + *curbase &= ~lower_middle_32bit_mask; + /* set new */ + *curbase |= (base & lower_middle_32bit_mask); + } + + return WHD_SUCCESS; +} + +#endif /* (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SPI_INTERFACE) */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_spi_protocol.h b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_spi_protocol.h new file mode 100644 index 00000000..b671f560 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_spi_protocol.h @@ -0,0 +1,103 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "whd.h" +#include "whd_bus_protocol_interface.h" +#include "cy_result.h" +#include "cyhal_spi.h" + +#ifndef INCLUDED_SPI_WHD_BUS_PROTOCOL_H +#define INCLUDED_SPI_WHD_BUS_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************** +* Constants +******************************************************/ + +/****************************************************** +* Structures +******************************************************/ + +typedef uint32_t whd_bus_gspi_header_t; + +#pragma pack(1) + +typedef struct +{ + whd_bus_gspi_header_t gspi_header; +} whd_bus_header_t; + +#pragma pack() + +#define WHD_BUS_SPI_HEADER_SIZE (sizeof(whd_bus_header_t) ) + +#define WHD_BUS_SPI_USE_STATUS_REPORT_SCHEME (1 == 1) + +#define WHD_BUS_SPI_MAX_BACKPLANE_TRANSFER_SIZE (64) /* Max packet size on F1 */ +#define WHD_BUS_SPI_BACKPLANE_READ_PADD_SIZE (4) + +/****************************************************** +* Function declarations +******************************************************/ +extern whd_result_t whd_bus_spi_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer); +extern whd_result_t whd_bus_spi_poke_wlan(whd_driver_t whd_driver); +extern whd_result_t whd_bus_spi_ack_interrupt(whd_driver_t whd_driver, uint32_t intstatus); +extern uint32_t whd_bus_spi_packet_available_to_read(whd_driver_t whd_driver); +extern whd_result_t whd_bus_spi_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer); +extern whd_result_t whd_bus_spi_init(whd_driver_t whd_driver); +extern whd_result_t whd_bus_spi_deinit(whd_driver_t whd_driver); +extern whd_bool_t whd_bus_spi_wake_interrupt_present(whd_driver_t whd_driver); +extern whd_result_t whd_bus_spi_wait_for_wlan_event(whd_driver_t whd_driver, + cy_semaphore_t *transceive_semaphore); +extern whd_result_t whd_bus_spi_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint32_t value); +extern whd_result_t whd_bus_spi_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function, + uint32_t address, uint8_t value_length, uint8_t *value); +extern whd_result_t whd_bus_spi_write_backplane_value(whd_driver_t whd_driver, uint32_t address, + uint8_t register_length, uint32_t value); +extern whd_result_t whd_bus_spi_read_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, + uint8_t *value); +extern whd_result_t whd_bus_spi_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction, + whd_bus_function_t function, uint32_t address, uint16_t size, + whd_transfer_bytes_packet_t *packet); +extern whd_result_t whd_bus_spi_wakeup(whd_driver_t whd_driver); +extern whd_result_t whd_bus_spi_sleep(whd_driver_t whd_driver); +extern void whd_bus_spi_init_stats(whd_driver_t whd_driver); +extern whd_result_t whd_bus_spi_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print); +extern whd_result_t whd_bus_spi_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware); +extern uint8_t whd_bus_spi_backplane_read_padd_size(whd_driver_t whd_driver); +extern whd_bool_t whd_bus_spi_use_status_report_scheme(whd_driver_t whd_driver); +extern uint32_t whd_bus_spi_get_max_transfer_size(whd_driver_t whd_driver); +extern whd_result_t whd_bus_spi_irq_register(whd_driver_t whd_driver); +extern whd_result_t whd_bus_spi_irq_enable(whd_driver_t whd_driver, whd_bool_t enable); +#if (CYHAL_API_VERSION >= 2) +extern void whd_bus_spi_irq_handler(void *handler_arg, cyhal_spi_event_t event); +#else +extern void whd_bus_spi_irq_handler(void *handler_arg, cyhal_spi_irq_event_t event); +#endif +/****************************************************** +* Global variables +******************************************************/ + +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif /* ifndef INCLUDED_SPI_WHD_BUS_PROTOCOL_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_chip_reg.h b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_chip_reg.h new file mode 100644 index 00000000..a856d65f --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_chip_reg.h @@ -0,0 +1,108 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_WHD_CHIP_REG_H_ +#define INCLUDED_WHD_CHIP_REG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************** +* Architecture Constants +******************************************************/ + +/* D11 registers and SHM */ +#define D11_BASE_ADDR 0x18001000 +#define D11_AXI_BASE_ADDR 0xE8000000 +#define D11_SHM_BASE_ADDR (D11_AXI_BASE_ADDR + 0x4000) + +#define D11REG_ADDR(offset) (D11_BASE_ADDR + offset) +#define D11IHR_ADDR(offset) (D11_AXI_BASE_ADDR + 0x400 + (2 * offset) ) +#define D11SHM_ADDR(offset) (D11_SHM_BASE_ADDR + offset) + +#define M_DS1_CTRL_STATUS (0xe0b * 2) + +/* RMC operational modes */ +enum ds1_ctrl_status +{ + DS1_SLEEP = 0, /* DS1_SLEEP */ + MAC_ON = 1, /* MAC_ON */ + RADIO_PHY_ON = 2, /* RADIO_PHY_ON */ + DS1_EXIT = 3 /* DS1_EXIT.*/ +}; + +#define M_DS1_CTRL_SDIO (0xe0c * 2) + +#define C_DS1_CTRL_SDIO_DS1_SLEEP (1 << 0) +#define C_DS1_CTRL_SDIO_MAC_ON (1 << 1) +#define C_DS1_CTRL_SDIO_RADIO_PHY_ON (1 << 2) +#define C_DS1_CTRL_SDIO_DS1_EXIT (1 << 3) +#define C_DS1_CTRL_PROC_DONE (1 << 8) +#define C_DS1_CTRL_REQ_VALID (1 << 9) +/* MacControl register */ +#define D11_MACCONTROL_REG D11REG_ADDR(0x120) +#define D11_MACCONTROL_REG_SIZE 4 +#define D11_MACCONTROL_REG_WAKE (1 << 26) +#define D11_MACCONTROL_CLEAR_WAKE (0xFBFFFFFF) +#define PMU_MINRESMASK (PMU_BASE_ADDRESS + 0x618) +#define DEFAULT_43012_MIN_RES_MASK 0x0f8bfe77 + +/* Backplane architecture */ +#define CHIPCOMMON_BASE_ADDRESS 0x18000000 /* Chipcommon core register region */ +#define I2S0_BASE_ADDRESS 0x18001000 /* I2S0 core register region */ +#define I2S1_BASE_ADDRESS 0x18002000 /* I2S1 core register region */ +#define APPS_ARMCR4_BASE_ADDRESS 0x18003000 /* Apps Cortex-R4 core register region */ +#define DMA_BASE_ADDRESS 0x18004000 /* DMA core register region */ +#define GMAC_BASE_ADDRESS 0x18005000 /* GMAC core register region */ +#define USB20H0_BASE_ADDRESS 0x18006000 /* USB20H0 core register region */ +#define USB20D_BASE_ADDRESS 0x18007000 /* USB20D core register region */ +#define SDIOH_BASE_ADDRESS 0x18008000 /* SDIOH Device core register region */ +#define DOT11MAC_BASE_ADDRESS 0x18001000 + +#define BACKPLANE_ADDRESS_MASK 0x7FFF +#define BACKPLANE_WINDOW_SIZE (BACKPLANE_ADDRESS_MASK + 1) + +#define CHIP_STA_INTERFACE 0 +#define CHIP_AP_INTERFACE 1 +#define CHIP_P2P_INTERFACE 2 + +/* Chipcommon registers */ +#define CHIPCOMMON_CORE_CAPEXT_ADDR ( (uint32_t)(CHIPCOMMON_BASE_ADDRESS + 0x64c) ) +#define CHIPCOMMON_CORE_CAPEXT_SR_SUPPORTED ( (uint32_t)(1 << 1) ) +#define CHIPCOMMON_CORE_RCTL_LOGIC_DISABLE ( (uint32_t)(1 << 27) ) +#define CHIPCOMMON_CORE_RCTL_MACPHY_DISABLE ( (uint32_t)(1 << 26) ) +#define CHIPCOMMON_CORE_RETENTION_CTL ( (uint32_t)(CHIPCOMMON_BASE_ADDRESS + 0x670) ) + +#define CHIPCOMMON_GPIO_CONTROL ( (uint32_t)(CHIPCOMMON_BASE_ADDRESS + 0x6C) ) +#define CHIPCOMMON_SR_CONTROL0 ( (uint32_t)(CHIPCOMMON_BASE_ADDRESS + 0x504) ) +#define CHIPCOMMON_SR_CONTROL1 ( (uint32_t)(CHIPCOMMON_BASE_ADDRESS + 0x508) ) + +/* SOCSRAM core registers */ +#define SOCSRAM_BANKX_INDEX(wd) ( (uint32_t)(GET_C_VAR(wd, SOCSRAM_BASE_ADDRESS) + 0x10) ) +#define SOCSRAM_BANKX_PDA(wd) ( (uint32_t)(GET_C_VAR(wd, SOCSRAM_BASE_ADDRESS) + 0x44) ) + +/* PMU core registers */ +#define RETENTION_CTL(wd) ( (uint32_t)(GET_C_VAR(wd, PMU_BASE_ADDRESS) + 0x670) ) +#define RCTL_MACPHY_DISABLE ( (uint32_t)(1 << 26) ) +#define RCTL_LOGIC_DISABLE ( (uint32_t)(1 << 27) ) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_CHIP_REG_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_sdio.h b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_sdio.h new file mode 100644 index 00000000..1e851537 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_sdio.h @@ -0,0 +1,239 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_WHD_SDIO_H_ +#define INCLUDED_WHD_SDIO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************** +* SDIO Constants +******************************************************/ +/* CurrentSdiodProgGuide r23 */ + +/* Base registers */ +#define SDIO_CORE(wd) ( (uint32_t)(GET_C_VAR(wd, SDIOD_CORE_BASE_ADDRESS) + 0x00) ) +#define SDIO_INT_STATUS(wd) ( (uint32_t)(GET_C_VAR(wd, SDIOD_CORE_BASE_ADDRESS) + 0x20) ) +#define SDIO_TO_SB_MAILBOX(wd) ( (uint32_t)(GET_C_VAR(wd, SDIOD_CORE_BASE_ADDRESS) + 0x40) ) +#define SDIO_TO_SB_MAILBOX_DATA(wd) ( (uint32_t)(GET_C_VAR(wd, SDIOD_CORE_BASE_ADDRESS) + 0x48) ) +#define SDIO_TO_HOST_MAILBOX_DATA(wd) ( (uint32_t)(GET_C_VAR(wd, SDIOD_CORE_BASE_ADDRESS) + 0x4C) ) +#define SDIO_INT_HOST_MASK(wd) ( (uint32_t)(GET_C_VAR(wd, SDIOD_CORE_BASE_ADDRESS) + 0x24) ) +#define SDIO_FUNCTION_INT_MASK(wd) ( (uint32_t)(GET_C_VAR(wd, SDIOD_CORE_BASE_ADDRESS) + 0x34) ) + +/* SDIO Function 0 (SDIO Bus) register addresses */ + +/* SDIO Device CCCR (Card Common Control Register) offsets */ +/* CCCR accesses do not require backpane clock */ +#define SDIOD_CCCR_REV ( (uint32_t)0x00 ) /* CCCR/SDIO Revision */ +#define SDIOD_CCCR_SDREV ( (uint32_t)0x01 ) /* SD Revision */ +#define SDIOD_CCCR_IOEN ( (uint32_t)0x02 ) /* I/O Enable */ +#define SDIOD_CCCR_IORDY ( (uint32_t)0x03 ) /* I/O Ready */ +#define SDIOD_CCCR_INTEN ( (uint32_t)0x04 ) /* Interrupt Enable */ +#define SDIOD_CCCR_INTPEND ( (uint32_t)0x05 ) /* Interrupt Pending */ +#define SDIOD_CCCR_IOABORT ( (uint32_t)0x06 ) /* I/O Abort */ +#define SDIOD_CCCR_BICTRL ( (uint32_t)0x07 ) /* Bus Interface control */ +#define SDIOD_CCCR_CAPABLITIES ( (uint32_t)0x08 ) /* Card Capabilities */ +#define SDIOD_CCCR_CISPTR_0 ( (uint32_t)0x09 ) /* Common CIS Base Address Pointer Register 0 (LSB) */ +#define SDIOD_CCCR_CISPTR_1 ( (uint32_t)0x0A ) /* Common CIS Base Address Pointer Register 1 */ +#define SDIOD_CCCR_CISPTR_2 ( (uint32_t)0x0B ) /* Common CIS Base Address Pointer Register 2 (MSB - only bit 1 valid)*/ +#define SDIOD_CCCR_BUSSUSP ( (uint32_t)0x0C ) /* Bus Suspend. Valid only if SBS is set */ +#define SDIOD_CCCR_FUNCSEL ( (uint32_t)0x0D ) /* Function Select. Valid only if SBS is set */ +#define SDIOD_CCCR_EXECFLAGS ( (uint32_t)0x0E ) /* Exec Flags. Valid only if SBS is set */ +#define SDIOD_CCCR_RDYFLAGS ( (uint32_t)0x0F ) /* Ready Flags. Valid only if SBS is set */ +#define SDIOD_CCCR_BLKSIZE_0 ( (uint32_t)0x10 ) /* Function 0 (Bus) SDIO Block Size Register 0 (LSB) */ +#define SDIOD_CCCR_BLKSIZE_1 ( (uint32_t)0x11 ) /* Function 0 (Bus) SDIO Block Size Register 1 (MSB) */ +#define SDIOD_CCCR_POWER_CONTROL ( (uint32_t)0x12 ) /* Power Control */ +#define SDIOD_CCCR_SPEED_CONTROL ( (uint32_t)0x13 ) /* Bus Speed Select (control device entry into high-speed clocking mode) */ +#define SDIOD_CCCR_UHS_I ( (uint32_t)0x14 ) /* UHS-I Support */ +#define SDIOD_CCCR_DRIVE ( (uint32_t)0x15 ) /* Drive Strength */ +#define SDIOD_CCCR_INTEXT ( (uint32_t)0x16 ) /* Interrupt Extension */ +#define SDIOD_CCCR_BRCM_CARDCAP ( (uint32_t)0xF0 ) /* Brcm Card Capability */ +#define SDIOD_SEP_INT_CTL ( (uint32_t)0xF2 ) /* Separate Interrupt Control*/ +#define SDIOD_CCCR_F1INFO ( (uint32_t)0x100 ) /* Function 1 (Backplane) Info */ +#define SDIOD_CCCR_F1HP ( (uint32_t)0x102 ) /* Function 1 (Backplane) High Power */ +#define SDIOD_CCCR_F1CISPTR_0 ( (uint32_t)0x109 ) /* Function 1 (Backplane) CIS Base Address Pointer Register 0 (LSB) */ +#define SDIOD_CCCR_F1CISPTR_1 ( (uint32_t)0x10A ) /* Function 1 (Backplane) CIS Base Address Pointer Register 1 */ +#define SDIOD_CCCR_F1CISPTR_2 ( (uint32_t)0x10B ) /* Function 1 (Backplane) CIS Base Address Pointer Register 2 (MSB - only bit 1 valid) */ +#define SDIOD_CCCR_F1BLKSIZE_0 ( (uint32_t)0x110 ) /* Function 1 (Backplane) SDIO Block Size Register 0 (LSB) */ +#define SDIOD_CCCR_F1BLKSIZE_1 ( (uint32_t)0x111 ) /* Function 1 (Backplane) SDIO Block Size Register 1 (MSB) */ +#define SDIOD_CCCR_F2INFO ( (uint32_t)0x200 ) /* Function 2 (WLAN Data FIFO) Info */ +#define SDIOD_CCCR_F2HP ( (uint32_t)0x202 ) /* Function 2 (WLAN Data FIFO) High Power */ +#define SDIOD_CCCR_F2CISPTR_0 ( (uint32_t)0x209 ) /* Function 2 (WLAN Data FIFO) CIS Base Address Pointer Register 0 (LSB) */ +#define SDIOD_CCCR_F2CISPTR_1 ( (uint32_t)0x20A ) /* Function 2 (WLAN Data FIFO) CIS Base Address Pointer Register 1 */ +#define SDIOD_CCCR_F2CISPTR_2 ( (uint32_t)0x20B ) /* Function 2 (WLAN Data FIFO) CIS Base Address Pointer Register 2 (MSB - only bit 1 valid) */ +#define SDIOD_CCCR_F2BLKSIZE_0 ( (uint32_t)0x210 ) /* Function 2 (WLAN Data FIFO) SDIO Block Size Register 0 (LSB) */ +#define SDIOD_CCCR_F2BLKSIZE_1 ( (uint32_t)0x211 ) /* Function 2 (WLAN Data FIFO) SDIO Block Size Register 1 (MSB) */ +#define SDIOD_CCCR_F3INFO ( (uint32_t)0x300 ) /* Function 3 (Bluetooth Data FIFO) Info */ +#define SDIOD_CCCR_F3HP ( (uint32_t)0x302 ) /* Function 3 (Bluetooth Data FIFO) High Power */ +#define SDIOD_CCCR_F3CISPTR_0 ( (uint32_t)0x309 ) /* Function 3 (Bluetooth Data FIFO) CIS Base Address Pointer Register 0 (LSB) */ +#define SDIOD_CCCR_F3CISPTR_1 ( (uint32_t)0x30A ) /* Function 3 (Bluetooth Data FIFO) CIS Base Address Pointer Register 1 */ +#define SDIOD_CCCR_F3CISPTR_2 ( (uint32_t)0x30B ) /* Function 3 (Bluetooth Data FIFO) CIS Base Address Pointer Register 2 (MSB - only bit 1 valid) */ +#define SDIOD_CCCR_F3BLKSIZE_0 ( (uint32_t)0x310 ) /* Function 3 (Bluetooth Data FIFO) SDIO Block Size Register 0 (LSB) */ +#define SDIOD_CCCR_F3BLKSIZE_1 ( (uint32_t)0x311 ) /* Function 3 (Bluetooth Data FIFO) SDIO Block Size Register 1 (MSB) */ + + +/* SDIO Function 1 (Backplane) register addresses */ +/* Addresses 0x00000000 - 0x0000FFFF are directly access the backplane + * throught the backplane window. Addresses above 0x0000FFFF are + * registers relating to backplane access, and do not require a backpane + * clock to access them + */ +#define SDIO_GPIO_SELECT ( (uint32_t)0x10005 ) +#define SDIO_GPIO_OUTPUT ( (uint32_t)0x10006 ) +#define SDIO_GPIO_ENABLE ( (uint32_t)0x10007 ) +#define SDIO_FUNCTION2_WATERMARK ( (uint32_t)0x10008 ) +#define SDIO_DEVICE_CONTROL ( (uint32_t)0x10009 ) +#define SDIO_BACKPLANE_ADDRESS_LOW ( (uint32_t)0x1000A ) +#define SDIO_BACKPLANE_ADDRESS_MID ( (uint32_t)0x1000B ) +#define SDIO_BACKPLANE_ADDRESS_HIGH ( (uint32_t)0x1000C ) +#define SDIO_FRAME_CONTROL ( (uint32_t)0x1000D ) +#define SDIO_CHIP_CLOCK_CSR ( (uint32_t)0x1000E ) +#define SDIO_PULL_UP ( (uint32_t)0x1000F ) +#define SDIO_READ_FRAME_BC_LOW ( (uint32_t)0x1001B ) +#define SDIO_READ_FRAME_BC_HIGH ( (uint32_t)0x1001C ) +#define SDIO_WAKEUP_CTRL ( (uint32_t)0x1001E ) +#define SDIO_SLEEP_CSR ( (uint32_t)0x1001F ) +#define I_HMB_SW_MASK ( (uint32_t)0x000000F0 ) +#define I_HMB_FRAME_IND (1 << 6) +#define I_HMB_HOST_INT (1 << 7) +#define I_HMB_FC_CHANGE (1 << 5) +#define FRAME_AVAILABLE_MASK I_HMB_SW_MASK + +/****************************************************** +* Bit Masks +******************************************************/ + +/* SDIOD_CCCR_REV Bits */ +#define SDIO_REV_SDIOID_MASK ( (uint32_t)0xF0 ) /* SDIO spec revision number */ +#define SDIO_REV_CCCRID_MASK ( (uint32_t)0x0F ) /* CCCR format version number */ + +/* SDIOD_CCCR_SDREV Bits */ +#define SD_REV_PHY_MASK ( (uint32_t)0x0F ) /* SD format version number */ + +/* SDIOD_CCCR_IOEN Bits */ +#define SDIO_FUNC_ENABLE_1 ( (uint32_t)0x02 ) /* function 1 I/O enable */ +#define SDIO_FUNC_ENABLE_2 ( (uint32_t)0x04 ) /* function 2 I/O enable */ +#define SDIO_FUNC_ENABLE_3 ( (uint32_t)0x08 ) /* function 3 I/O enable */ + +/* SDIOD_CCCR_IORDY Bits */ +#define SDIO_FUNC_READY_1 ( (uint32_t)0x02 ) /* function 1 I/O ready */ +#define SDIO_FUNC_READY_2 ( (uint32_t)0x04 ) /* function 2 I/O ready */ +#define SDIO_FUNC_READY_3 ( (uint32_t)0x08 ) /* function 3 I/O ready */ + +/* SDIOD_CCCR_INTEN Bits */ +#define INTR_CTL_MASTER_EN ( (uint32_t)0x01 ) /* interrupt enable master */ +#define INTR_CTL_FUNC1_EN ( (uint32_t)0x02 ) /* interrupt enable for function 1 */ +#define INTR_CTL_FUNC2_EN ( (uint32_t)0x04 ) /* interrupt enable for function 2 */ + +/* SDIOD_SEP_INT_CTL Bits */ +#define SEP_INTR_CTL_MASK ( (uint32_t)0x01 ) /* out-of-band interrupt mask */ +#define SEP_INTR_CTL_EN ( (uint32_t)0x02 ) /* out-of-band interrupt output enable */ +#define SEP_INTR_CTL_POL ( (uint32_t)0x04 ) /* out-of-band interrupt polarity */ + +/* SDIOD_CCCR_INTPEND Bits */ +#define INTR_STATUS_FUNC1 ( (uint32_t)0x02 ) /* interrupt pending for function 1 */ +#define INTR_STATUS_FUNC2 ( (uint32_t)0x04 ) /* interrupt pending for function 2 */ +#define INTR_STATUS_FUNC3 ( (uint32_t)0x08 ) /* interrupt pending for function 3 */ + +/* SDIOD_CCCR_IOABORT Bits */ +#define IO_ABORT_RESET_ALL ( (uint32_t)0x08 ) /* I/O card reset */ +#define IO_ABORT_FUNC_MASK ( (uint32_t)0x07 ) /* abort selction: function x */ + +/* SDIOD_CCCR_BICTRL Bits */ +#define BUS_CARD_DETECT_DIS ( (uint32_t)0x80 ) /* Card Detect disable */ +#define BUS_SPI_CONT_INTR_CAP ( (uint32_t)0x40 ) /* support continuous SPI interrupt */ +#define BUS_SPI_CONT_INTR_EN ( (uint32_t)0x20 ) /* continuous SPI interrupt enable */ +#define BUS_SD_DATA_WIDTH_MASK ( (uint32_t)0x03 ) /* bus width mask */ +#define BUS_SD_DATA_WIDTH_4BIT ( (uint32_t)0x02 ) /* bus width 4-bit mode */ +#define BUS_SD_DATA_WIDTH_1BIT ( (uint32_t)0x00 ) /* bus width 1-bit mode */ + +/* SDIOD_CCCR_CAPABLITIES Bits */ +#define SDIO_CAP_4BLS ( (uint32_t)0x80 ) /* 4-bit support for low speed card */ +#define SDIO_CAP_LSC ( (uint32_t)0x40 ) /* low speed card */ +#define SDIO_CAP_E4MI ( (uint32_t)0x20 ) /* enable interrupt between block of data in 4-bit mode */ +#define SDIO_CAP_S4MI ( (uint32_t)0x10 ) /* support interrupt between block of data in 4-bit mode */ +#define SDIO_CAP_SBS ( (uint32_t)0x08 ) /* support suspend/resume */ +#define SDIO_CAP_SRW ( (uint32_t)0x04 ) /* support read wait */ +#define SDIO_CAP_SMB ( (uint32_t)0x02 ) /* support multi-block transfer */ +#define SDIO_CAP_SDC ( (uint32_t)0x01 ) /* Support Direct commands during multi-byte transfer */ + +/* SDIOD_CCCR_POWER_CONTROL Bits */ +#define SDIO_POWER_SMPC ( (uint32_t)0x01 ) /* supports master power control (RO) */ +#define SDIO_POWER_EMPC ( (uint32_t)0x02 ) /* enable master power control (allow > 200mA) (RW) */ + +/* SDIOD_CCCR_SPEED_CONTROL Bits */ +#define SDIO_SPEED_SHS ( (uint32_t)0x01 ) /* supports high-speed [clocking] mode (RO) */ +#define SDIO_SPEED_EHS ( (uint32_t)0x02 ) /* enable high-speed [clocking] mode (RW) */ + +/* SDIOD_CCCR_BRCM_CARDCAP Bits */ +#define SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT ( (uint32_t)0x02 ) /* Supports CMD14 */ +#define SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT ( (uint32_t)0x04 ) /* CMD14 is allowed in FSM command state */ +#define SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC ( (uint32_t)0x08 ) /* sdiod_aos does not decode any command */ + +/* SDIO_FUNCTION_INT_MASK Bits*/ +#define SDIO_FUNC_MASK_F1 ( (uint32_t)0x01 ) /* interrupt mask enable for function 1 */ +#define SDIO_FUNC_MASK_F2 ( (uint32_t)0x02 ) /* interrupt mask enable for function 2 */ + +/* SDIO_DEVICE_CONTROL Bits */ +#define SDIO_DATA_PAD_ISO ( (uint32_t)0x08 ) /* isolate internal SDIO data bus signals */ + +/* SDIO_CHIP_CLOCK_CSR Bits */ +#define SBSDIO_FORCE_ALP ( (uint32_t)0x01 ) /* Force ALP request to backplane */ +#define SBSDIO_FORCE_HT ( (uint32_t)0x02 ) /* Force HT request to backplane */ +#define SBSDIO_FORCE_ILP ( (uint32_t)0x04 ) /* Force ILP request to backplane */ +#define SBSDIO_ALP_AVAIL_REQ ( (uint32_t)0x08 ) /* Make ALP ready (power up xtal) */ +#define SBSDIO_HT_AVAIL_REQ ( (uint32_t)0x10 ) /* Make HT ready (power up PLL) */ +#define SBSDIO_FORCE_HW_CLKREQ_OFF ( (uint32_t)0x20 ) /* Squelch clock requests from HW */ +#define SBSDIO_ALP_AVAIL ( (uint32_t)0x40 ) /* Status: ALP is ready */ +#define SBSDIO_HT_AVAIL ( (uint32_t)0x80 ) /* Status: HT is ready */ +#define SBSDIO_Rev8_HT_AVAIL ( (uint32_t)0x40 ) +#define SBSDIO_Rev8_ALP_AVAIL ( (uint32_t)0x80 ) + +/* SDIO_FRAME_CONTROL Bits */ +#define SFC_RF_TERM ( (uint32_t)(1 << 0) ) /* Read Frame Terminate */ +#define SFC_WF_TERM ( (uint32_t)(1 << 1) ) /* Write Frame Terminate */ +#define SFC_CRC4WOOS ( (uint32_t)(1 << 2) ) /* HW reports CRC error for write out of sync */ +#define SFC_ABORTALL ( (uint32_t)(1 << 3) ) /* Abort cancels all in-progress frames */ + +/* SDIO_TO_SB_MAILBOX bits corresponding to intstatus bits */ +#define SMB_NAK ( (uint32_t)(1 << 0) ) /* To SB Mailbox Frame NAK */ +#define SMB_INT_ACK ( (uint32_t)(1 << 1) ) /* To SB Mailbox Host Interrupt ACK */ +#define SMB_USE_OOB ( (uint32_t)(1 << 2) ) /* To SB Mailbox Use OOB Wakeup */ +#define SMB_DEV_INT ( (uint32_t)(1 << 3) ) /* To SB Mailbox Miscellaneous Interrupt */ + +/* SDIO_WAKEUP_CTRL bits */ +#define SBSDIO_WCTRL_WAKE_TILL_ALP_AVAIL ( (uint32_t)(1 << 0) ) /* WakeTillAlpAvail bit */ +#define SBSDIO_WCTRL_WAKE_TILL_HT_AVAIL ( (uint32_t)(1 << 1) ) /* WakeTillHTAvail bit */ + +/* SDIO_SLEEP_CSR bits */ +#define SBSDIO_SLPCSR_KEEP_SDIO_ON ( (uint32_t)(1 << 0) ) /* KeepSdioOn bit */ +#define SBSDIO_SLPCSR_DEVICE_ON ( (uint32_t)(1 << 1) ) /* DeviceOn bit */ + +/* To hostmail box data */ +#define I_HMB_DATA_NAKHANDLED 0x0001 /* retransmit NAK'd frame */ +#define I_HMB_DATA_DEVREADY 0x0002 /* talk to host after enable */ +#define I_HMB_DATA_FC 0x0004 /* per prio flowcontrol update flag */ +#define I_HMB_DATA_FWREADY 0x0008 /* fw ready for protocol activity */ +#define I_HMB_DATA_FWHALT 0x0010 /* firmware halted */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_SDIO_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_spi.h b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_spi.h new file mode 100644 index 00000000..3bd98fad --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_spi.h @@ -0,0 +1,121 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_WHD_SPI_H_ +#define INCLUDED_WHD_SPI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************** +* SPI Constants +******************************************************/ +/* GSPI v1 */ +#define SPI_FRAME_CONTROL ( (uint32_t)0x1000D ) + +/* Register addresses */ +#define SPI_BUS_CONTROL ( (uint32_t)0x0000 ) +#define SPI_RESPONSE_DELAY ( (uint32_t)0x0001 ) +#define SPI_STATUS_ENABLE ( (uint32_t)0x0002 ) +#define SPI_RESET_BP ( (uint32_t)0x0003 ) /* (corerev >= 1) */ +#define SPI_INTERRUPT_REGISTER ( (uint32_t)0x0004 ) /* 16 bits - Interrupt status */ +#define SPI_INTERRUPT_ENABLE_REGISTER ( (uint32_t)0x0006 ) /* 16 bits - Interrupt mask */ +#define SPI_STATUS_REGISTER ( (uint32_t)0x0008 ) /* 32 bits */ +#define SPI_FUNCTION1_INFO ( (uint32_t)0x000C ) /* 16 bits */ +#define SPI_FUNCTION2_INFO ( (uint32_t)0x000E ) /* 16 bits */ +#define SPI_FUNCTION3_INFO ( (uint32_t)0x0010 ) /* 16 bits */ +#define SPI_READ_TEST_REGISTER ( (uint32_t)0x0014 ) /* 32 bits */ +#define SPI_RESP_DELAY_F0 ( (uint32_t)0x001c ) /* 8 bits (corerev >= 3) */ +#define SPI_RESP_DELAY_F1 ( (uint32_t)0x001d ) /* 8 bits (corerev >= 3) */ +#define SPI_RESP_DELAY_F2 ( (uint32_t)0x001e ) /* 8 bits (corerev >= 3) */ +#define SPI_RESP_DELAY_F3 ( (uint32_t)0x001f ) /* 8 bits (corerev >= 3) */ + +/****************************************************** +* Bit Masks +******************************************************/ + +/* GSPI */ +#define SPI_READ_TEST_REGISTER_VALUE ( (uint32_t)0xFEEDBEAD ) +#define SPI_READ_TEST_REG_LSB ( ( (SPI_READ_TEST_REGISTER_VALUE) ) & 0xff ) +#define SPI_READ_TEST_REG_LSB_SFT1 ( ( (SPI_READ_TEST_REGISTER_VALUE << 1) ) & 0xff ) +#define SPI_READ_TEST_REG_LSB_SFT2 ( ( (SPI_READ_TEST_REGISTER_VALUE << 1) + 1 ) & 0xff ) +#define SPI_READ_TEST_REG_LSB_SFT3 ( ( (SPI_READ_TEST_REGISTER_VALUE + 1) << 1 ) & 0xff ) + +/* SPI_BUS_CONTROL Bits */ +#define WORD_LENGTH_32 ( (uint32_t)0x01 ) /* 0/1 16/32 bit word length */ +#define ENDIAN_BIG ( (uint32_t)0x02 ) /* 0/1 Little/Big Endian */ +#define CLOCK_PHASE ( (uint32_t)0x04 ) /* 0/1 clock phase delay */ +#define CLOCK_POLARITY ( (uint32_t)0x08 ) /* 0/1 Idle state clock polarity is low/high */ +#define HIGH_SPEED_MODE ( (uint32_t)0x10 ) /* 1/0 High Speed mode / Normal mode */ +#define INTERRUPT_POLARITY_HIGH ( (uint32_t)0x20 ) /* 1/0 Interrupt active polarity is high/low */ +#define WAKE_UP ( (uint32_t)0x80 ) /* 0/1 Wake-up command from Host to WLAN */ + +/* SPI_RESPONSE_DELAY Bit mask */ +#define RESPONSE_DELAY_MASK 0xFF /* Configurable rd response delay in multiples of 8 bits */ + +/* SPI_STATUS_ENABLE Bits */ +#define STATUS_ENABLE ( (uint32_t)0x01 ) /* 1/0 Status sent/not sent to host after read/write */ +#define INTR_WITH_STATUS ( (uint32_t)0x02 ) /* 0/1 Do-not / do-interrupt if status is sent */ +#define RESP_DELAY_ALL ( (uint32_t)0x04 ) /* Applicability of resp delay to F1 or all func's read */ +#define DWORD_PKT_LEN_EN ( (uint32_t)0x08 ) /* Packet len denoted in dwords instead of bytes */ +#define CMD_ERR_CHK_EN ( (uint32_t)0x20 ) /* Command error check enable */ +#define DATA_ERR_CHK_EN ( (uint32_t)0x40 ) /* Data error check enable */ + +/* SPI_RESET_BP Bits*/ +#define RESET_ON_WLAN_BP_RESET ( (uint32_t)0x04 ) /* enable reset for WLAN backplane */ +#define RESET_SPI ( (uint32_t)0x80 ) /* reset the above enabled logic */ + +/* SPI_INTERRUPT_REGISTER and SPI_INTERRUPT_ENABLE_REGISTER Bits */ +#define DATA_UNAVAILABLE ( (uint32_t)0x0001 ) /* Requested data not available; Clear by writing a "1" */ +#define F2_F3_FIFO_RD_UNDERFLOW ( (uint32_t)0x0002 ) +#define F2_F3_FIFO_WR_OVERFLOW ( (uint32_t)0x0004 ) +#define COMMAND_ERROR ( (uint32_t)0x0008 ) /* Cleared by writing 1 */ +#define DATA_ERROR ( (uint32_t)0x0010 ) /* Cleared by writing 1 */ +#define F2_PACKET_AVAILABLE ( (uint32_t)0x0020 ) +#define F3_PACKET_AVAILABLE ( (uint32_t)0x0040 ) +#define F1_OVERFLOW ( (uint32_t)0x0080 ) /* Due to last write. Bkplane has pending write requests */ +#define MISC_INTR0 ( (uint32_t)0x0100 ) +#define MISC_INTR1 ( (uint32_t)0x0200 ) +#define MISC_INTR2 ( (uint32_t)0x0400 ) +#define MISC_INTR3 ( (uint32_t)0x0800 ) +#define MISC_INTR4 ( (uint32_t)0x1000 ) +#define F1_INTR ( (uint32_t)0x2000 ) +#define F2_INTR ( (uint32_t)0x4000 ) +#define F3_INTR ( (uint32_t)0x8000 ) + +/* SPI_STATUS_REGISTER Bits */ +#define STATUS_DATA_NOT_AVAILABLE ( (uint32_t)0x00000001 ) +#define STATUS_UNDERFLOW ( (uint32_t)0x00000002 ) +#define STATUS_OVERFLOW ( (uint32_t)0x00000004 ) +#define STATUS_F2_INTR ( (uint32_t)0x00000008 ) +#define STATUS_F3_INTR ( (uint32_t)0x00000010 ) +#define STATUS_F2_RX_READY ( (uint32_t)0x00000020 ) +#define STATUS_F3_RX_READY ( (uint32_t)0x00000040 ) +#define STATUS_HOST_CMD_DATA_ERR ( (uint32_t)0x00000080 ) +#define STATUS_F2_PKT_AVAILABLE ( (uint32_t)0x00000100 ) +#define STATUS_F2_PKT_LEN_MASK ( (uint32_t)0x000FFE00 ) +#define STATUS_F2_PKT_LEN_SHIFT ( (uint32_t)9 ) +#define STATUS_F3_PKT_AVAILABLE ( (uint32_t)0x00100000 ) +#define STATUS_F3_PKT_LEN_MASK ( (uint32_t)0xFFE00000 ) +#define STATUS_F3_PKT_LEN_SHIFT ( (uint32_t)21 ) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_SPI_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_ap.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_ap.h new file mode 100644 index 00000000..84ed8b6e --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_ap.h @@ -0,0 +1,101 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides prototypes / declarations for APSTA functionality + */ +#ifndef INCLUDED_WHD_AP_H +#define INCLUDED_WHD_AP_H + +#include "whd.h" +#include "cyabs_rtos.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************** +* Macros +******************************************************/ +#define AMPDU_RX_FACTOR_8K 0 /* max receive AMPDU length is 8kb */ +#define AMPDU_RX_FACTOR_16K 1 /* max receive AMPDU length is 16kb */ +#define AMPDU_RX_FACTOR_32K 2 /* max receive AMPDU length is 32kb */ +#define AMPDU_RX_FACTOR_64K 3 /* max receive AMPDU length is 64kb */ +#define AMPDU_RX_FACTOR_INVALID 0xff /* invalid rx factor; ignore */ +#define AMPDU_MPDU_AUTO (-1) /* Auto number of mpdu in ampdu */ + + +#define BANDWIDTH_20MHZ (20) /* 802.11n, 802.11ac 20Mhz Bandwidth */ +#define BANDWIDTH_40MHZ (40) /* 802.11n, 802.11ac 40Mhz Bandwidth */ +#define BANDWIDTH_80MHZ (80) /* 802.11ac 80Mhz Bandwidth */ + +#define WHD_WIFI_CONFIG_AP_MAX_ASSOC 5 + +#define CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(buff, \ + sema) if (buff == \ + NULL){ WPRINT_WHD_ERROR( ("Buffer alloc failed in %s at %d \n", \ + __func__, __LINE__) ); \ + whd_assert("Buffer alloc failed\n", 0 == 1); \ + (void)cy_rtos_deinit_semaphore(sema); \ + return WHD_BUFFER_ALLOC_FAIL; } + +#define CHECK_RETURN_WITH_SEMAPHORE(expr, sema) { whd_result_t check_res = (expr); if (check_res != WHD_SUCCESS) \ + { WPRINT_WHD_ERROR( ("Command failed in %s at %d \n", __func__, \ + __LINE__) ); \ + whd_assert("Command failed\n", 0 == 1); \ + (void)cy_rtos_deinit_semaphore(sema); \ + return check_res; } } + +/****************************************************** +* Structures +******************************************************/ +typedef struct whd_ap_int_info +{ + whd_bool_t ap_is_up; + whd_bool_t is_waiting_event; + cy_semaphore_t whd_wifi_sleep_flag; + +} whd_ap_int_info_t; + +/****************************************************** +* Function prototypes +******************************************************/ +extern whd_result_t whd_wifi_set_block_ack_window_size_common(whd_interface_t interface, uint16_t ap_win_size, + uint16_t sta_win_size); +extern whd_result_t whd_wifi_set_ampdu_parameters_common(whd_interface_t interface, uint8_t ba_window_size, + int8_t ampdu_mpdu, uint8_t rx_factor); +extern void whd_wifi_set_ap_is_up(whd_driver_t whd_driver, whd_bool_t new_state); +extern whd_bool_t whd_wifi_get_ap_is_up(whd_driver_t whd_driver); +void whd_ap_info_init(whd_driver_t whd_driver); +whd_result_t whd_wifi_set_block_ack_window_size(whd_interface_t ifp); + + +/** Set the AMPDU parameters for both Soft AP and STA + * + * Sets various AMPDU parameters for Soft AP and STA to ensure that the number of buffers dedicated to AMPDUs does + * not exceed the resources of the chip. Both Soft AP and STA interfaces must be down. + * + * @return WHD_SUCCESS : if the AMPDU parameters were successfully set + * WHD_ERROR : if the AMPDU parameters were not successfully set + */ +extern whd_result_t whd_wifi_set_ampdu_parameters(whd_interface_t ifp); + +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_AP_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_buffer_api.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_buffer_api.h new file mode 100644 index 00000000..726eb8b4 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_buffer_api.h @@ -0,0 +1,150 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides prototypes / declarations for common APSTA functionality + */ +#ifndef _WHD_INTERNAL_BUFFER_API_H_ +#define _WHD_INTERNAL_BUFFER_API_H_ + +#include "whd.h" +#include "whd_int.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Macros +******************************************************/ + +/****************************************************** +* Structures +******************************************************/ + +/****************************************************** +* Function prototypes +******************************************************/ +/** Allocates a packet buffer + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * Attempts to allocate a packet buffer of the size requested. It can do this + * by allocating a pre-existing packet from a pool, using a static buffer, + * or by dynamically allocating memory. The method of allocation does not + * concern WHD, however it must match the way the network stack expects packet + * buffers to be allocated. + * + * @param buffer : A pointer which receives the allocated packet buffer handle + * @param direction : Indicates transmit/receive direction that the packet buffer is + * used for. This may be needed if tx/rx pools are separate. + * @param size : The number of bytes to allocate. + * @param timeout_ms : Maximum period to block for available buffer + * + * @return : WHD_SUCCESS or error code + * + */ +whd_result_t whd_host_buffer_get(whd_driver_t whd_driver, whd_buffer_t *buffer, whd_buffer_dir_t direction, + uint16_t size, uint32_t timeout_ms); + +/** Releases a packet buffer + * + * Implemented in the port layer interface, which will be specific to the + * buffering scheme in use. + * This function is used by WHD to indicate that it no longer requires + * a packet buffer. The buffer can then be released back into a pool for + * reuse, or the dynamically allocated memory can be freed, according to + * how the packet was allocated. + * Returns void since WHD cannot do anything about failures + * + * @param buffer : The handle of the packet buffer to be released + * @param direction : Indicates transmit/receive direction that the packet buffer has + * been used for. This might be needed if tx/rx pools are separate. + * + */ +whd_result_t whd_buffer_release(whd_driver_t whd_driver, whd_buffer_t buffer, whd_buffer_dir_t direction); + +/** Retrieves the current pointer of a packet buffer + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * Since packet buffers usually need to be created with space at the + * front for additional headers, this function allows WHD to get + * the current 'front' location pointer. + * + * @param buffer : The handle of the packet buffer whose pointer is to be retrieved + * + * @return : The packet buffer's current pointer. + */ +uint8_t *whd_buffer_get_current_piece_data_pointer(whd_driver_t whd_driver, whd_buffer_t buffer); + +/** Retrieves the size of a packet buffer + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * Since packet buffers usually need to be created with space at the + * front for additional headers, the memory block used to contain a packet buffer + * will often be larger than the current size of the packet buffer data. + * This function allows WHD to retrieve the current size of a packet buffer's data. + * + * @param buffer : The handle of the packet buffer whose size is to be retrieved + * + * @return : The size of the packet buffer. + */ +uint16_t whd_buffer_get_current_piece_size(whd_driver_t whd_driver, whd_buffer_t buffer); + +/** Sets the current size of a WHD packet + * + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * This function sets the current length of a WHD packet buffer + * + * @param buffer : The packet to be modified + * @param size : The new size of the packet buffer + * + * @return : WHD_SUCCESS or error code + */ +whd_result_t whd_buffer_set_size(whd_driver_t whd_driver, whd_buffer_t buffer, uint16_t size); + +/** Moves the current pointer of a packet buffer + * + * Implemented in the port layer interface which is specific to the buffering scheme in use. + * + * Since packet buffers usually need to be created with space at the front for additional headers, + * this function allows WHD to move the current 'front' location pointer so that it has space to + * add headers to transmit packets, and so that the network stack does not see the internal WHD + * headers on received packets. + * + * @param buffer : A pointer to the handle of the current packet buffer for which the + * current pointer will be moved. On return this may contain a pointer + * to a newly allocated packet buffer which has been daisy chained to + * the front of the given one. This would be the case if the given packet + * buffer didn't have enough space at the front. + * @param add_remove_amount : This is the number of bytes to move the current pointer of the packet + * buffer - a negative value increases the space for headers at the front + * of the packet, a positive value decreases the space. + * + * @return : WHD_SUCCESS or error code + */ +whd_result_t whd_buffer_add_remove_at_front(whd_driver_t whd_driver, whd_buffer_t *buffer, int32_t add_remove_amount); +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif /* ifndef _WHD_INTERNAL_BUFFER_API_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_cdc_bdc.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_cdc_bdc.h new file mode 100644 index 00000000..20aacccb --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_cdc_bdc.h @@ -0,0 +1,179 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_WHD_CDC_BDC_H +#define INCLUDED_WHD_CDC_BDC_H + +#include "whd.h" +#include "cyabs_rtos.h" +#include "whd_events_int.h" +#include "whd_types_int.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Constants +******************************************************/ + +/* CDC flag definition taken from bcmcdc.h */ +#define CDCF_IOC_SET (0x02) /** 0=get, 1=set cmd */ +#define WHD_EVENT_HANDLER_LIST_SIZE (5) /** Maximum number of simultaneously registered event handlers */ +#define WHD_SDALIGN 32 + +/* CDC flag definitions taken from bcmcdc.h */ +#define CDCF_IOC_ERROR (0x01) /** 0=success, 1=ioctl cmd failed */ +#define CDCF_IOC_IF_MASK (0xF000) /** I/F index */ +#define CDCF_IOC_IF_SHIFT (12) /** # of bits of shift for I/F Mask */ +#define CDCF_IOC_ID_MASK (0xFFFF0000) /** used to uniquely id an ioctl req/resp pairing */ +#define CDCF_IOC_ID_SHIFT (16) /** # of bits of shift for ID Mask */ + +#define DATA_AFTER_HEADER(x) ( (void *)(&x[1]) ) + +#define BDC_HEADER_LEN (4) + +/****************************************************** +* Enumerations +******************************************************/ + +typedef enum sdpcm_command_type_enum +{ + CDC_GET = 0x00, + CDC_SET = CDCF_IOC_SET +} cdc_command_type_t; + +/****************************************************** +* Structures +******************************************************/ +#pragma pack(1) +typedef struct +{ + uint32_t cmd; /* ioctl command value */ + uint32_t len; /* lower 16: output buflen; upper 16: input buflen (excludes header) */ + uint32_t flags; /* flag defns given in bcmcdc.h */ + uint32_t status; /* status code returned from the device */ +} cdc_header_t; + +typedef struct +{ + uint8_t flags; /* Flags */ + uint8_t priority; /* 802.1d Priority (low 3 bits) */ + uint8_t flags2; + uint8_t data_offset; /* Offset from end of BDC header to packet data, in 4-uint8_t words. + * Leaves room for optional headers.*/ +} bdc_header_t; + +typedef struct +{ + whd_mac_t destination_address; + whd_mac_t source_address; + uint16_t ethertype; +} ethernet_header_t; + +#pragma pack() + +/** Event list element structure + * + * events : A pointer to a whd_event_num_t array that is terminated with a WLC_E_NONE event + * handler: A pointer to the whd_event_handler_t function that will receive the event + * handler_user_data : User provided data that will be passed to the handler when a matching event occurs + */ +typedef struct +{ + whd_bool_t event_set; + whd_event_num_t events[WHD_MAX_EVENT_SUBSCRIPTION]; + whd_event_handler_t handler; + void *handler_user_data; + uint8_t ifidx; +} event_list_elem_t; + +/** @endcond */ + +typedef struct whd_cdc_info +{ + /* Event list variables */ + event_list_elem_t whd_event_list[WHD_EVENT_HANDLER_LIST_SIZE]; + cy_semaphore_t event_list_mutex; + + /* IOCTL variables*/ + uint16_t requested_ioctl_id; + cy_semaphore_t ioctl_mutex; + whd_buffer_t ioctl_response; + cy_semaphore_t ioctl_sleep; + +} whd_cdc_bdc_info_t; +/** Error list element structure + * + * events : set event of error type + * handler: A pointer to the whd_error_handler_t function that will receive the event + * handler_user_data : User provided data that will be passed to the handler when a matching event occurs + */ +typedef struct +{ + whd_error_handler_t handler; + void *handler_user_data; + whd_bool_t event_set; + uint8_t events; +} error_list_elem_t; + +/** @endcond */ + +typedef struct whd_error_info +{ + /* Event list variables */ + error_list_elem_t whd_event_list[WHD_EVENT_HANDLER_LIST_SIZE]; + cy_semaphore_t event_list_mutex; +} whd_error_info_t; + +/****************************************************** +* Function Declarations +******************************************************/ + +whd_result_t whd_cdc_bdc_info_init(whd_driver_t whd_driver); +void whd_cdc_bdc_info_deinit(whd_driver_t whd_driver); + +whd_result_t whd_cdc_send_iovar(whd_interface_t ifp, cdc_command_type_t type, + whd_buffer_t send_buffer_hnd, + whd_buffer_t *response_buffer_hnd); + +whd_result_t whd_cdc_send_ioctl(whd_interface_t ifp, cdc_command_type_t type, uint32_t command, + whd_buffer_t send_buffer_hnd, + whd_buffer_t *response_buffer_hnd); + +void *whd_cdc_get_iovar_buffer(whd_driver_t whd_driver, + whd_buffer_t *buffer, + uint16_t data_length, + const char *name); +whd_result_t whd_network_send_ethernet_data(whd_interface_t ifp, whd_buffer_t buffer); + +void *whd_cdc_get_ioctl_buffer(whd_driver_t whd_driver, + whd_buffer_t *buffer, + uint16_t data_length); + +void whd_process_cdc(whd_driver_t whd_driver, whd_buffer_t buffer); + +void whd_process_bdc(whd_driver_t whd_driver, whd_buffer_t buffer); + +void whd_process_bdc_event(whd_driver_t whd_driver, whd_buffer_t buffer, uint16_t size); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_CDC_BDC_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_chip.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_chip.h new file mode 100644 index 00000000..15260cfe --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_chip.h @@ -0,0 +1,405 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_WHD_CHIP_H +#define INCLUDED_WHD_CHIP_H + +#include "cyabs_rtos.h" /* For cy_semaphore_t */ + +#include "whd_endian.h" +#include "whd.h" +#include "whd_wifi_api.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Constants +******************************************************/ +#define WHD_WLAN_WAKE_TIMEOUT (10000) +#define WHD_SHARED_MEMORY_POLLING_DELAY (10) +#define SICF_CPUHALT (0x0020) + +/****************************************************** +* Enumerations +******************************************************/ +/** + * Enumerated list of aggregate codes and edit WHD_COUNTRY_AGGREGATE_CUSTOMER for supporting new aggregate + * as per customer like XZ/278 + */ +typedef enum +{ + WHD_COUNTRY_AGGREGATE_XA_0 = MK_CNTRY('X', 'A', 0), + WHD_COUNTRY_AGGREGATE_XT_0 = MK_CNTRY('X', 'T', 0), + WHD_COUNTRY_AGGREGATE_XV_0 = MK_CNTRY('X', 'V', 0), + WHD_COUNTRY_AGGREGATE_CUSTOMER = MK_CNTRY('X', 'Z', 278), +} whd_aggregate_code_t; + +typedef enum +{ + /* Note : If changing this, core_base_address must be changed also */ + WLAN_ARM_CORE = 0, SOCRAM_CORE = 1, SDIOD_CORE = 2 +} device_core_t; + +typedef enum +{ + WLAN_DOWN, WLAN_UP, WLAN_OFF +} wlan_state_t; + +typedef enum +{ + WLAN_CORE_FLAG_NONE, WLAN_CORE_FLAG_CPU_HALT, +} wlan_core_flag_t; + +/** + * Enumeration of AKM (authentication and key management) suites. Table 8-140 802.11mc D3.0. + */ +typedef enum +{ + WHD_AKM_RESERVED = 0, + WHD_AKM_8021X = 1, /**< WPA2 enterprise */ + WHD_AKM_PSK = 2, /**< WPA2 PSK */ + WHD_AKM_FT_8021X = 3, /**< 802.11r Fast Roaming enterprise */ + WHD_AKM_FT_PSK = 4, /**< 802.11r Fast Roaming PSK */ + WHD_AKM_8021X_SHA256 = 5, + WHD_AKM_PSK_SHA256 = 6, + WHD_AKM_TDLS = 7, /**< Tunneled Direct Link Setup */ + WHD_AKM_SAE_SHA256 = 8, + WHD_AKM_FT_SAE_SHA256 = 9, + WHD_AKM_AP_PEER_KEY_SHA256 = 10, + WHD_AKM_SUITEB_8021X_HMAC_SHA256 = 11, + WHD_AKM_SUITEB_8021X_HMAC_SHA384 = 12, + WHD_AKM_SUITEB_FT_8021X_HMAC_SHA384 = 13, +} whd_akm_suite_t; + +/** + * Enumeration of cipher suites. Table 8-138 802.11mc D3.0. + */ +typedef enum +{ + WHD_CIPHER_GROUP = 0, /**< Use group cipher suite */ + WHD_CIPHER_WEP_40 = 1, /**< WEP-40 */ + WHD_CIPHER_TKIP = 2, /**< TKIP */ + WHD_CIPHER_RESERVED = 3, /**< Reserved */ + WHD_CIPHER_CCMP_128 = 4, /**< CCMP-128 - default pairwise and group cipher suite in an RSNA */ + WHD_CIPHER_WEP_104 = 5, /**< WEP-104 - also known as WEP-128 */ + WHD_CIPHER_BIP_CMAC_128 = 6, /**< BIP-CMAC-128 - default management frame cipher suite */ + WHD_CIPHER_GROUP_DISALLOWED = 7, /**< Group address traffic not allowed */ + WHD_CIPHER_GCMP_128 = 8, /**< GCMP-128 - default for 60 GHz STAs */ + WHD_CIPHER_GCMP_256 = 9, /**< GCMP-256 - introduced for Suite B */ + WHD_CIPHER_CCMP_256 = 10, /**< CCMP-256 - introduced for suite B */ + WHD_CIPHER_BIP_GMAC_128 = 11, /**< BIP-GMAC-128 - introduced for suite B */ + WHD_CIPHER_BIP_GMAC_256 = 12, /**< BIP-GMAC-256 - introduced for suite B */ + WHD_CIPHER_BIP_CMAC_256 = 13, /**< BIP-CMAC-256 - introduced for suite B */ +} whd_80211_cipher_t; + +/****************************************************** +* Structures +******************************************************/ + +typedef struct whd_chip_info +{ + uint16_t chip_id; + whd_bool_t save_restore_enable; + uint32_t fwcap_flags; +} whd_chip_info_t; + +typedef struct whd_fwcap +{ + whd_fwcap_id_t feature; + const char *const fwcap_name; +} whd_fwcap_t; + +typedef struct +{ + wlan_state_t state; + whd_country_code_t country_code; + whd_aggregate_code_t aggregate_code; + uint32_t keep_wlan_awake; +} whd_wlan_status_t; + +#pragma pack(1) + +/* 802.11 Information Element structures */ + +/* Country Information */ +#define COUNTRY_INFO_IE_MINIMUM_LENGTH (6) + +typedef struct +{ + uint8_t first_chan_num; + uint8_t num_chans; + uint8_t max_tx_pwr_level; +} country_chan_info_t; + +/* Structures for TLVs with 8-bit type and 8-bit length */ +typedef struct +{ + uint8_t type; + uint8_t length; +} whd_tlv8_header_t; + +typedef struct +{ + uint8_t type; + uint8_t length; + uint8_t data[1]; +} whd_tlv8_data_t; + +typedef struct +{ + whd_tlv8_header_t tlv_header; /* id, length */ + char ccode[2]; /* dot11CountryString MIB octet 1~2, two letter country code */ + uint8_t env; /* dot11CountryString MIB octet 3, indicate indoor/outdoor environment */ + country_chan_info_t country_chan_info[1]; /* At least one country channel info triples */ +} country_info_ie_fixed_portion_t; + +/* Robust Secure Network */ +typedef struct +{ + whd_tlv8_header_t tlv_header; /* id, length */ + uint16_t version; + uint32_t group_key_suite; /* See whd_80211_cipher_t for values */ + uint16_t pairwise_suite_count; + uint32_t pairwise_suite_list[1]; +} rsn_ie_fixed_portion_t; + +#define RSN_IE_MINIMUM_LENGTH (8) + +typedef struct +{ + whd_tlv8_header_t tlv_header; /* id, length */ + uint8_t oui[4]; +} vendor_specific_ie_header_t; + +#define VENDOR_SPECIFIC_IE_MINIMUM_LENGTH (4) + +/* WPA IE */ +typedef struct +{ + vendor_specific_ie_header_t vendor_specific_header; + uint16_t version; + uint32_t multicast_suite; + uint16_t unicast_suite_count; + uint8_t unicast_suite_list[1][4]; +} wpa_ie_fixed_portion_t; + +#define WPA_IE_MINIMUM_LENGTH (12) + +typedef struct +{ + uint16_t akm_suite_count; + uint32_t akm_suite_list[1]; +} akm_suite_portion_t; + +/* RSNX IE */ +typedef struct +{ + whd_tlv8_header_t tlv_header; /* id, length */ + uint8_t data[1]; +} rsnx_ie_t; + +#define DOT11_RSNX_CAP_LEN 1 /* Extended RSN Capabilities length in octets (1 octet) */ +#define DOT11_RSNX_SAE_H2E 5 /* Extended RSN Capabilities */ + +typedef struct +{ + whd_tlv8_header_t tlv_header; /* id, length */ + uint16_t ht_capabilities_info; + uint8_t ampdu_parameters; + uint8_t rx_mcs[10]; + uint16_t rxhighest_supported_data_rate; + uint8_t tx_supported_mcs_set; + uint8_t tx_mcs_info[3]; + uint16_t ht_extended_capabilities; + uint32_t transmit_beam_forming_capabilities; + uint8_t antenna_selection_capabilities; +} ht_capabilities_ie_t; + +#define HT_CAPABILITIES_INFO_LDPC_CODING_CAPABILITY (1 << 0) +#define HT_CAPABILITIES_INFO_SUPPORTED_CHANNEL_WIDTH_SET (1 << 1) +#define HT_CAPABILITIES_INFO_SM_POWER_SAVE_OFFSET (1 << 2) +#define HT_CAPABILITIES_INFO_SM_POWER_SAVE_MASK (3 << 2) +#define HT_CAPABILITIES_INFO_HT_GREENFIELD (1 << 4) +#define HT_CAPABILITIES_INFO_SHORT_GI_FOR_20MHZ (1 << 5) +#define HT_CAPABILITIES_INFO_SHORT_GI_FOR_40MHZ (1 << 6) +#define HT_CAPABILITIES_INFO_TX_STBC (1 << 7) +#define HT_CAPABILITIES_INFO_RX_STBC_OFFSET (1 << 8) +#define HT_CAPABILITIES_INFO_RX_STBC_MASK (3 << 8) +#define HT_CAPABILITIES_INFO_HT_DELAYED_BLOCK_ACK (1 << 10) +#define HT_CAPABILITIES_INFO_MAXIMUM_A_MSDU_LENGTH (1 << 11) +#define HT_CAPABILITIES_INFO_DSSS_CCK_MODE_IN_40MHZ (1 << 12) +/* bit 13 reserved */ +#define HT_CAPABILITIES_INFO_40MHZ_INTOLERANT (1 << 14) +#define HT_CAPABILITIES_INFO_L_SIG_TXOP_PROTECTION_SUPPORT (1 << 15) + +typedef unsigned int uint; +typedef struct +{ + uint buf; + uint buf_size; + uint idx; + uint out_idx; /* output index */ +} hnd_log_t; + +#define CBUF_LEN 128 + +typedef struct +{ + /* Virtual UART + * When there is no UART (e.g. Quickturn), the host should write a complete + * input line directly into cbuf and then write the length into vcons_in. + * This may also be used when there is a real UART (at risk of conflicting with + * the real UART). vcons_out is currently unused. + */ + volatile uint vcons_in; + volatile uint vcons_out; + + /* Output (logging) buffer + * Console output is written to a ring buffer log_buf at index log_idx. + * The host may read the output when it sees log_idx advance. + * Output will be lost if the output wraps around faster than the host polls. + */ + hnd_log_t log; + + /* Console input line buffer + * Characters are read one at a time into cbuf until is received, then + * the buffer is processed as a command line. Also used for virtual UART. + */ + uint cbuf_idx; + char cbuf[CBUF_LEN]; +} hnd_cons_t; + +typedef struct wifi_console +{ + uint count; /* Poll interval msec counter */ + uint log_addr; /* Log struct address (fixed) */ + hnd_log_t log; /* Log struct (host copy) */ + uint bufsize; /* Size of log buffer */ + char *buf; /* Log buffer (host copy) */ + uint last; /* Last buffer read index */ +} wifi_console_t; + +typedef struct +{ + uint flags; + uint trap_addr; + uint assert_exp_addr; + uint assert_file_addr; + uint assert_line; + uint console_addr; + uint msgtrace_addr; + uint fwid; +} wlan_shared_t; + +/* Buffer size to be allocated to read wlan log */ +#define WLAN_LOG_BUF_LEN (4 * 1024) + +#define WHD_IOCTL_LOG_SIZE 64 +#define WHD_IOVAR_STRING_SIZE 128 +#define WHD_MAX_DATA_SIZE 64 + +typedef struct +{ + uint32_t ioct_log; + uint8_t is_this_event; + uint8_t data[WHD_MAX_DATA_SIZE]; + uint32_t data_size; + uint16_t flag; + uint32_t reason; +}whd_ioctl_log_t; + +whd_result_t whd_ioctl_log_add(whd_driver_t whd_driver, uint32_t cmd, whd_buffer_t buffer); +whd_result_t whd_ioctl_log_add_event(whd_driver_t whd_driver, uint32_t cmd, uint16_t flag, uint32_t data); + +whd_result_t whd_ioctl_print(whd_driver_t whd_driver); + +#pragma pack() + +typedef struct whd_internal_info +{ + whd_wlan_status_t whd_wlan_status; + wifi_console_t *c; + wifi_console_t console; + wlan_shared_t sh; + uint32_t console_addr; + whd_scan_result_callback_t scan_result_callback; + whd_scan_result_t *whd_scan_result_ptr; + /* The semaphore used to wait for completion of a join; + * whd_wifi_join_halt uses this to release waiting threads (if any) */ + cy_semaphore_t *active_join_semaphore; + whd_bool_t active_join_mutex_initted; + cy_semaphore_t active_join_mutex; + uint con_lastpos; + whd_bool_t whd_wifi_p2p_go_is_up; + uint32_t whd_join_status[3]; + whd_auth_result_callback_t auth_result_callback; +} whd_internal_info_t; + +#pragma pack(1) + +typedef struct +{ + char abbrev[3]; + uint8_t rev; + uint8_t data[64]; +} whd_country_info_t; + +#pragma pack() + +whd_result_t whd_internal_info_init(whd_driver_t whd_driver); +whd_result_t whd_internal_info_deinit(whd_driver_t whd_driver); + +/****************************************************** +* Function Declarations +******************************************************/ + +extern void whd_wifi_chip_info_init(whd_driver_t whd_driver); +extern whd_result_t whd_wlan_bus_complete_ds_wake(whd_driver_t whd_driver, whd_bool_t wake_from_firmware, + uint32_t wake_event_indication_addr, uint32_t wake_indication_addr, + uint32_t sdio_control_addr); +extern whd_result_t whd_wifi_set_custom_country_code(whd_interface_t ifp, const whd_country_info_t *country_code); + +/* Device core control functions */ +extern whd_result_t whd_disable_device_core(whd_driver_t whd_driver, device_core_t core_id, wlan_core_flag_t core_flag); +extern whd_result_t whd_reset_device_core(whd_driver_t whd_driver, device_core_t core_id, wlan_core_flag_t core_flag); +extern whd_result_t whd_reset_core(whd_driver_t whd_driver, device_core_t core_id, uint32_t bits, uint32_t resetbits); +extern whd_result_t whd_wlan_armcore_run(whd_driver_t whd_driver, device_core_t core_id, wlan_core_flag_t core_flag); +extern whd_result_t whd_device_core_is_up(whd_driver_t whd_driver, device_core_t core_id); + +/* Chip specific functions */ +extern whd_result_t whd_allow_wlan_bus_to_sleep(whd_driver_t whd_driver); +extern whd_result_t whd_ensure_wlan_bus_is_up(whd_driver_t whd_driver); + +extern whd_result_t whd_chip_specific_init(whd_driver_t whd_driver); +extern whd_result_t whd_chip_specific_socsram_init(whd_driver_t whd_driver); +extern whd_result_t whd_wifi_read_wlan_log(whd_driver_t whd_driver, char *buffer, uint32_t buffer_size); +extern whd_result_t whd_wifi_print_whd_log(whd_driver_t whd_driver); +extern whd_result_t whd_wifi_read_wlan_log_unsafe(whd_driver_t whd_driver, uint32_t wlan_shared_address, char *buffer, + uint32_t buffer_size); +extern whd_result_t whd_wifi_read_fw_capabilities(whd_interface_t ifp); +extern void whd_wifi_peek(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, uint8_t *value); +extern void whd_wifi_poke(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, uint32_t value); +extern uint32_t whd_wifi_get_btc_params(whd_driver_t whd_driver, uint32_t address, whd_interface_t interface); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_CHIP_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_chip_constants.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_chip_constants.h new file mode 100644 index 00000000..e415e562 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_chip_constants.h @@ -0,0 +1,91 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_CHIP_CONSTANTS_H_ +#define INCLUDED_CHIP_CONSTANTS_H_ + +#include "whd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WRAPPER_REGISTER_OFFSET (0x100000) +typedef enum chip_var +{ + ARM_CORE_BASE_ADDRESS = 1, + SOCSRAM_BASE_ADDRESS, + SOCSRAM_WRAPPER_BASE_ADDRESS, + SDIOD_CORE_BASE_ADDRESS, + PMU_BASE_ADDRESS, + CHIP_RAM_SIZE, + ATCM_RAM_BASE_ADDRESS, + SOCRAM_SRMEM_SIZE, + CHANSPEC_BAND_MASK, + CHANSPEC_BAND_2G, + CHANSPEC_BAND_5G, + CHANSPEC_BAND_SHIFT, + CHANSPEC_BW_10, + CHANSPEC_BW_20, + CHANSPEC_BW_40, + CHANSPEC_BW_MASK, + CHANSPEC_BW_SHIFT, + CHANSPEC_CTL_SB_LOWER, + CHANSPEC_CTL_SB_UPPER, + CHANSPEC_CTL_SB_NONE, + CHANSPEC_CTL_SB_MASK +} chip_var_t; + +#define VERIFY_RESULT(x) { whd_result_t verify_result = WHD_SUCCESS; verify_result = (x); \ + if (verify_result != WHD_SUCCESS){ \ + WPRINT_WHD_ERROR( ("Function %s failed at line %d \n", __func__, __LINE__) ); \ + return verify_result; } } +#define GET_C_VAR(whd_driver, var) get_whd_var(whd_driver, var) + +uint32_t get_whd_var(whd_driver_t whd_driver, chip_var_t var); + +whd_result_t get_arm_core_base_address(uint16_t, uint32_t *); +whd_result_t get_socsram_base_address(uint16_t, uint32_t *, whd_bool_t); +whd_result_t get_sdiod_core_base_address(uint16_t, uint32_t *); +whd_result_t get_pmu_base_address(uint16_t, uint32_t *); +whd_result_t get_chip_ram_size(uint16_t, uint32_t *); +whd_result_t get_atcm_ram_base_address(uint16_t, uint32_t *); +whd_result_t get_socsram_srmem_size(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_band_mask(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_band_2G(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_band_5G(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_band_shift(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_bw_10(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_bw_20(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_bw_40(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_bw_mask(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_bw_shift(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_ctl_sb_lower(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_ctl_sb_upper(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_ctl_sb_none(uint16_t, uint32_t *); +whd_result_t get_wl_chanspec_ctl_sb_mask(uint16_t, uint32_t *); + +uint32_t whd_chip_set_chip_id(whd_driver_t whd_driver, uint16_t id); +uint16_t whd_chip_get_chip_id(whd_driver_t whd_driver); + +#undef CHIP_FIRMWARE_SUPPORTS_PM_LIMIT_IOVAR + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_CHIP_CONSTANTS_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_clm.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_clm.h new file mode 100644 index 00000000..05990d97 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_clm.h @@ -0,0 +1,44 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides generic clm blob file download functionality + */ +#ifndef _WHD_INTERNAL_CLM_H_ +#define _WHD_INTERNAL_CLM_H_ + +#include "whd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************** +* Macros +******************************************************/ + + +/****************************************************** +* Function prototypes +******************************************************/ +whd_result_t whd_process_clm_data(whd_interface_t ifp); + +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif /* ifndef _WHD_INTERNAL_CLM_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_debug.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_debug.h new file mode 100644 index 00000000..0556b7b9 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_debug.h @@ -0,0 +1,149 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "whd.h" + +#ifndef INCLUDED_WHD_DEBUG_H +#define INCLUDED_WHD_DEBUG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Macros +******************************************************/ +#define WPRINT_ENABLE_WHD_ERROR +/* #define WPRINT_ENABLE_WHD_INFO */ +/* #define WPRINT_ENABLE_WHD_DEBUG */ + +#define WHD_ENABLE_STATS +/*#define WHD_LOGGING_BUFFER_ENABLE*/ + +#if defined (__GNUC__) +#define WHD_TRIGGER_BREAKPOINT( ) do { __asm__ ("bkpt"); } while (0) + +#elif defined (__IAR_SYSTEMS_ICC__) +#define WHD_TRIGGER_BREAKPOINT( ) do { __asm("bkpt 0"); } while (0) + +#else +#define WHD_TRIGGER_BREAKPOINT( ) +#endif + +#ifdef WPRINT_ENABLE_ERROR +#define WPRINT_ERROR(args) do { WPRINT_MACRO(args); } while (0) +#define whd_assert(error_string, assertion) do { if (!(assertion) ){ WHD_TRIGGER_BREAKPOINT(); } } while (0) +#define whd_minor_assert(error_string, \ + assertion) do { if (!(assertion) ) WPRINT_MACRO( (error_string) ); } while (0) +#else +#define whd_assert(error_string, \ + assertion) do { if (!(assertion) ){ WPRINT_MACRO( (error_string) ); } } while (0) +#define whd_minor_assert(error_string, assertion) do { (void)(assertion); } while (0) +#endif + +/****************************************************** +* Print declarations +******************************************************/ +/* IF MFG TEST is enabled then disable all LOGGING VIA UART as + + * this interrupts communication between WL TOOL and MFG Test APP + + * via STDIO UART causing Wrong Message Exchange and failure. + + */ +#if defined(WLAN_MFG_FIRMWARE) || defined(WHD_PRINT_DISABLE) +#define WPRINT_MACRO(args) +#else +#if defined(WHD_LOGGING_BUFFER_ENABLE) +#define WPRINT_MACRO(args) do { whd_buffer_printf args; } while (0 == 1) +#else +#define WPRINT_MACRO(args) do { printf args;} while (0 == 1) +#endif +#endif + + +/* WICED printing macros for Wiced Wi-Fi Driver*/ +#ifdef WPRINT_ENABLE_WHD_INFO +#define WPRINT_WHD_INFO(args) WPRINT_MACRO(args) +#else +#define WPRINT_WHD_INFO(args) +#endif + +#ifdef WPRINT_ENABLE_WHD_DEBUG +#define WPRINT_WHD_DEBUG(args) WPRINT_MACRO(args) +#else +#define WPRINT_WHD_DEBUG(args) +#endif + +#ifdef WPRINT_ENABLE_WHD_ERROR +#define WPRINT_WHD_ERROR(args) WPRINT_MACRO(args); +#else +#define WPRINT_WHD_ERROR(args) +#endif + +#ifdef WPRINT_ENABLE_WHD_DATA_LOG +#define WPRINT_WHD_DATA_LOG(args) WPRINT_MACRO(args) +#else +#define WPRINT_WHD_DATA_LOG(args) +#endif + +#define WHD_STATS_INCREMENT_VARIABLE(whd_driver, var) \ + do { whd_driver->whd_stats.var++; } while (0) + +#define WHD_STATS_CONDITIONAL_INCREMENT_VARIABLE(whd_driver, condition, var) \ + do { if (condition){ whd_driver->whd_stats.var++; }} while (0) + +#if (defined(__GNUC__) && (__GNUC__ >= 6) ) +#define __FUNCTION__ __func__ +#endif + + +void whd_init_stats(whd_driver_t whd_driver); +void whd_print_logbuffer(void); + + +#ifdef WHD_LOGGING_BUFFER_ENABLE +#define LOGGING_BUFFER_SIZE (4 * 1024) +int whd_buffer_printf(const char *format, ...); + +typedef struct +{ + uint32_t buffer_write; + uint32_t buffer_read; + char buffer[LOGGING_BUFFER_SIZE + 1]; + whd_bool_t roll_over; + whd_bool_t over_write; +} whd_logging_t; +#else +#define whd_print_logbuffer() +#endif /* WHD_LOGGING_BUFFER_ENABLE */ + +#ifdef WHD_IOCTL_LOG_ENABLE +#define WHD_IOCTL_LOG_ADD(x, y, z) whd_ioctl_log_add(x, y, z) +#define WHD_IOCTL_LOG_ADD_EVENT(w, x, y, z) whd_ioctl_log_add_event(w, x, y, z) +#define WHD_IOCTL_PRINT(x) whd_ioctl_print(x) +#else +#define WHD_IOCTL_LOG_ADD(x, y, z) +#define WHD_IOCTL_LOG_ADD_EVENT(w, x, y, z) +#define WHD_IOCTL_PRINT(x) +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef INCLUDED_WHD_DEBUG_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_endian.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_endian.h new file mode 100644 index 00000000..f81fc90f --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_endian.h @@ -0,0 +1,68 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Byte order utilities + * + * This file by default provides proper behavior on little-endian architectures. + * On big-endian architectures, IL_BIGENDIAN should be defined. + */ + +#ifndef INCLUDED_WHD_ENDIAN_H +#define INCLUDED_WHD_ENDIAN_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Reverse the bytes in a 16-bit value */ +#define SWAP16(val) \ + ( (uint16_t)( ( ( (uint16_t)(val) & (uint16_t)0x00ffU ) << 8 ) | \ + ( ( (uint16_t)(val) & (uint16_t)0xff00U ) >> 8 ) ) ) + +/* Reverse the bytes in a 32-bit value */ +#define SWAP32(val) \ + ( (uint32_t)( ( ( (uint32_t)(val) & (uint32_t)0x000000ffU ) << 24 ) | \ + ( ( (uint32_t)(val) & (uint32_t)0x0000ff00U ) << 8 ) | \ + ( ( (uint32_t)(val) & (uint32_t)0x00ff0000U ) >> 8 ) | \ + ( ( (uint32_t)(val) & (uint32_t)0xff000000U ) >> 24 ) ) ) + +#ifdef IL_BIGENDIAN +#define htod32(i) SWAP32(i) +#define htod16(i) SWAP16(i) +#define dtoh32(i) SWAP32(i) +#define dtoh16(i) SWAP16(i) +#define hton16(i) (i) +#define hton32(i) (i) +#define ntoh16(i) (i) +#define ntoh32(i) (i) +#else /* IL_BIGENDIAN */ +#define htod32(i) (i) +#define htod16(i) (i) +#define dtoh32(i) (i) +#define dtoh16(i) (i) +#define hton16(i) SWAP16(i) +#define hton32(i) SWAP32(i) +#define ntoh16(i) SWAP16(i) +#define ntoh32(i) SWAP32(i) +#endif /* IL_BIGENDIAN */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* INCLUDED_WHD_ENDIAN_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_events_int.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_events_int.h new file mode 100644 index 00000000..cf88c05f --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_events_int.h @@ -0,0 +1,502 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Header for Event detection + * + * Provides constants and prototypes for functions that allow both + * whd and user applications to receive event callbacks. + */ + +#include "whd.h" + +#ifndef INCLUDED_WHD_EVENTS_INT_H +#define INCLUDED_WHD_EVENTS_INT_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* @cond Typedefs +******************************************************/ + +/** + * Enumerated list of event types + */ +typedef enum +{ + WLC_E_NONE = 0x7FFFFFFE, + WLC_E_SET_SSID = 0 /** indicates status of set SSID */, + WLC_E_JOIN = 1, /** differentiates join IBSS from found (WLC_E_START) IBSS */ + WLC_E_START = 2, /** STA founded an IBSS or AP started a BSS */ + WLC_E_AUTH = 3, /** 802.11 AUTH request */ + WLC_E_AUTH_IND = 4, /** 802.11 AUTH indication */ + WLC_E_DEAUTH = 5, /** 802.11 DEAUTH request */ + WLC_E_DEAUTH_IND = 6, /** 802.11 DEAUTH indication */ + WLC_E_ASSOC = 7, /** 802.11 ASSOC request */ + WLC_E_ASSOC_IND = 8, /** 802.11 ASSOC indication */ + WLC_E_REASSOC = 9, /** 802.11 REASSOC request */ + WLC_E_REASSOC_IND = 10, /** 802.11 REASSOC indication */ + WLC_E_DISASSOC = 11, /** 802.11 DISASSOC request */ + WLC_E_DISASSOC_IND = 12, /** 802.11 DISASSOC indication */ + WLC_E_QUIET_START = 13, /** 802.11h Quiet period started */ + WLC_E_QUIET_END = 14, /** 802.11h Quiet period ended */ + WLC_E_BEACON_RX = 15, /** BEACONS received/lost indication */ + WLC_E_LINK = 16, /** generic link indication */ + WLC_E_MIC_ERROR = 17, /** TKIP MIC error occurred */ + WLC_E_NDIS_LINK = 18, /** NDIS style link indication */ + WLC_E_ROAM = 19, /** roam attempt occurred: indicate status & reason */ + WLC_E_TXFAIL = 20, /** change in dot11FailedCount (txfail) */ + WLC_E_PMKID_CACHE = 21, /** WPA2 pmkid cache indication */ + WLC_E_RETROGRADE_TSF = 22, /** current AP's TSF value went backward */ + WLC_E_PRUNE = 23, /** AP was pruned from join list for reason */ + WLC_E_AUTOAUTH = 24, /** report AutoAuth table entry match for join attempt */ + WLC_E_EAPOL_MSG = 25, /** Event encapsulating an EAPOL message */ + WLC_E_SCAN_COMPLETE = 26, /** Scan results are ready or scan was aborted */ + WLC_E_ADDTS_IND = 27, /** indicate to host addts fail/success */ + WLC_E_DELTS_IND = 28, /** indicate to host delts fail/success */ + WLC_E_BCNSENT_IND = 29, /** indicate to host of beacon transmit */ + WLC_E_BCNRX_MSG = 30, /** Send the received beacon up to the host */ + WLC_E_BCNLOST_MSG = 31, /** indicate to host loss of beacon */ + WLC_E_ROAM_PREP = 32, /** before attempting to roam */ + WLC_E_PFN_NET_FOUND = 33, /** PFN network found event */ + WLC_E_PFN_NET_LOST = 34, /** PFN network lost event */ + WLC_E_RESET_COMPLETE = 35, WLC_E_JOIN_START = 36, WLC_E_ROAM_START = 37, WLC_E_ASSOC_START = 38, + WLC_E_IBSS_ASSOC = 39, WLC_E_RADIO = 40, WLC_E_PSM_WATCHDOG = 41, /** PSM microcode watchdog fired */ + WLC_E_CCX_ASSOC_START = 42, /** CCX association start */ + WLC_E_CCX_ASSOC_ABORT = 43, /** CCX association abort */ + WLC_E_PROBREQ_MSG = 44, /** probe request received */ + WLC_E_SCAN_CONFIRM_IND = 45, WLC_E_PSK_SUP = 46, /** WPA Handshake */ + WLC_E_COUNTRY_CODE_CHANGED = 47, WLC_E_EXCEEDED_MEDIUM_TIME = 48, /** WMMAC excedded medium time */ + WLC_E_ICV_ERROR = 49, /** WEP ICV error occurred */ + WLC_E_UNICAST_DECODE_ERROR = 50, /** Unsupported unicast encrypted frame */ + WLC_E_MULTICAST_DECODE_ERROR = 51, /** Unsupported multicast encrypted frame */ + WLC_E_TRACE = 52, WLC_E_BTA_HCI_EVENT = 53, /** BT-AMP HCI event */ + WLC_E_IF = 54, /** I/F change (for wlan host notification) */ + WLC_E_P2P_DISC_LISTEN_COMPLETE = 55, /** P2P Discovery listen state expires */ + WLC_E_RSSI = 56, /** indicate RSSI change based on configured levels */ + WLC_E_PFN_BEST_BATCHING = 57, /** PFN best network batching event */ + WLC_E_EXTLOG_MSG = 58, WLC_E_ACTION_FRAME = 59, /** Action frame reception */ + WLC_E_ACTION_FRAME_COMPLETE = 60, /** Action frame Tx complete */ + WLC_E_PRE_ASSOC_IND = 61, /** assoc request received */ + WLC_E_PRE_REASSOC_IND = 62, /** re-assoc request received */ + WLC_E_CHANNEL_ADOPTED = 63, /** channel adopted (xxx: obsoleted) */ + WLC_E_AP_STARTED = 64, /** AP started */ + WLC_E_DFS_AP_STOP = 65, /** AP stopped due to DFS */ + WLC_E_DFS_AP_RESUME = 66, /** AP resumed due to DFS */ + WLC_E_WAI_STA_EVENT = 67, /** WAI stations event */ + WLC_E_WAI_MSG = 68, /** event encapsulating an WAI message */ + WLC_E_ESCAN_RESULT = 69, /** escan result event */ + WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE = 70, /** action frame off channel complete *//* NOTE - This used to be WLC_E_WAKE_EVENT */ + WLC_E_PROBRESP_MSG = 71, /** probe response received */ + WLC_E_P2P_PROBREQ_MSG = 72, /** P2P Probe request received */ + WLC_E_DCS_REQUEST = 73, WLC_E_FIFO_CREDIT_MAP = 74, /** credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */ + WLC_E_ACTION_FRAME_RX = 75, /** Received action frame event WITH wl_event_rx_frame_data_t header */ + WLC_E_WAKE_EVENT = 76, /** Wake Event timer fired, used for wake WLAN test mode */ + WLC_E_RM_COMPLETE = 77, /** Radio measurement complete */ + WLC_E_HTSFSYNC = 78, /** Synchronize TSF with the host */ + WLC_E_OVERLAY_REQ = 79, /** request an overlay IOCTL/iovar from the host */ + WLC_E_CSA_COMPLETE_IND = 80, WLC_E_EXCESS_PM_WAKE_EVENT = 81, /** excess PM Wake Event to inform host */ + WLC_E_PFN_SCAN_NONE = 82, /** no PFN networks around */ + WLC_E_PFN_SCAN_ALLGONE = 83, /** last found PFN network gets lost */ + WLC_E_GTK_PLUMBED = 84, WLC_E_ASSOC_IND_NDIS = 85, /** 802.11 ASSOC indication for NDIS only */ + WLC_E_REASSOC_IND_NDIS = 86, /** 802.11 REASSOC indication for NDIS only */ + WLC_E_ASSOC_REQ_IE = 87, WLC_E_ASSOC_RESP_IE = 88, WLC_E_ASSOC_RECREATED = 89, /** association recreated on resume */ + WLC_E_ACTION_FRAME_RX_NDIS = 90, /** rx action frame event for NDIS only */ + WLC_E_AUTH_REQ = 91, /** authentication request received */ + WLC_E_TDLS_PEER_EVENT = 92, /** discovered peer, connected/disconnected peer */ + WLC_E_MESH_DHCP_SUCCESS = 92, /** DHCP handshake successful for a mesh interface */ + WLC_E_SPEEDY_RECREATE_FAIL = 93, /** fast assoc recreation failed */ + WLC_E_NATIVE = 94, /** port-specific event and payload (e.g. NDIS) */ + WLC_E_PKTDELAY_IND = 95, /** event for tx pkt delay suddently jump */ + WLC_E_AWDL_AW = 96, /** AWDL AW period starts */ + WLC_E_AWDL_ROLE = 97, /** AWDL Master/Slave/NE master role event */ + WLC_E_AWDL_EVENT = 98, /** Generic AWDL event */ + WLC_E_NIC_AF_TXS = 99, /** NIC AF txstatus */ + WLC_E_NAN = 100, /** NAN event */ + WLC_E_BEACON_FRAME_RX = 101, WLC_E_SERVICE_FOUND = 102, /** desired service found */ + WLC_E_GAS_FRAGMENT_RX = 103, /** GAS fragment received */ + WLC_E_GAS_COMPLETE = 104, /** GAS sessions all complete */ + WLC_E_P2PO_ADD_DEVICE = 105, /** New device found by p2p offload */ + WLC_E_P2PO_DEL_DEVICE = 106, /** device has been removed by p2p offload */ + WLC_E_WNM_STA_SLEEP = 107, /** WNM event to notify STA enter sleep mode */ + WLC_E_TXFAIL_THRESH = 108, /** Indication of MAC tx failures (exhaustion of 802.11 retries) exceeding threshold(s) */ + WLC_E_PROXD = 109, /** Proximity Detection event */ + WLC_E_IBSS_COALESCE = 110, /** IBSS Coalescing */ + WLC_E_MESH_PAIRED = 110, /** Mesh peer found and paired */ + WLC_E_AWDL_RX_PRB_RESP = 111, /** AWDL RX Probe response */ + WLC_E_AWDL_RX_ACT_FRAME = 112, /** AWDL RX Action Frames */ + WLC_E_AWDL_WOWL_NULLPKT = 113, /** AWDL Wowl nulls */ + WLC_E_AWDL_PHYCAL_STATUS = 114, /** AWDL Phycal status */ + WLC_E_AWDL_OOB_AF_STATUS = 115, /** AWDL OOB AF status */ + WLC_E_AWDL_SCAN_STATUS = 116, /** Interleaved Scan status */ + WLC_E_AWDL_AW_START = 117, /** AWDL AW Start */ + WLC_E_AWDL_AW_END = 118, /** AWDL AW End */ + WLC_E_AWDL_AW_EXT = 119, /** AWDL AW Extensions */ + WLC_E_AWDL_PEER_CACHE_CONTROL = 120, WLC_E_CSA_START_IND = 121, WLC_E_CSA_DONE_IND = 122, + WLC_E_CSA_FAILURE_IND = 123, WLC_E_CCA_CHAN_QUAL = 124, /** CCA based channel quality report */ + WLC_E_BSSID = 125, /** to report change in BSSID while roaming */ + WLC_E_TX_STAT_ERROR = 126, /** tx error indication */ + WLC_E_BCMC_CREDIT_SUPPORT = 127, /** credit check for BCMC supported */ + WLC_E_PSTA_PRIMARY_INTF_IND = 128, /** psta primary interface indication */ + WLC_E_BT_WIFI_HANDOVER_REQ = 130, /* Handover Request Initiated */ + WLC_E_SPW_TXINHIBIT = 131, /* Southpaw TxInhibit notification */ + WLC_E_FBT_AUTH_REQ_IND = 132, /* FBT Authentication Request Indication */ + WLC_E_RSSI_LQM = 133, /* Enhancement addition for WLC_E_RSSI */ + WLC_E_PFN_GSCAN_FULL_RESULT = 134, /* Full probe/beacon (IEs etc) results */ + WLC_E_PFN_SWC = 135, /* Significant change in rssi of bssids being tracked */ + WLC_E_AUTHORIZED = 136, /* a STA been authroized for traffic */ + WLC_E_PROBREQ_MSG_RX = 137, /* probe req with wl_event_rx_frame_data_t header */ + WLC_E_PFN_SCAN_COMPLETE = 138, /* PFN completed scan of network list */ + WLC_E_RMC_EVENT = 139, /* RMC Event */ + WLC_E_DPSTA_INTF_IND = 140, /* DPSTA interface indication */ + WLC_E_RRM = 141, /* RRM Event */ + WLC_E_ULP = 146, /* ULP entry event */ + WLC_E_TKO = 151, /* TCP Keep Alive Offload Event */ + WLC_E_EXT_AUTH_REQ = 187, /* authentication request received */ + WLC_E_EXT_AUTH_FRAME_RX = 188, /* authentication request received */ + WLC_E_MGMT_FRAME_TXSTATUS = 189, /* mgmt frame Tx complete */ + WLC_E_LAST = 190, /* highest val + 1 for range checking */ +} whd_event_num_t; + +/** + * Enumerated list of error types + */ +typedef enum +{ + WLC_ERR_NONE = 0x00, + WLC_ERR_BUS = 0x01, /** indicates BUS got wrong */ + WLC_ERR_FW = 0x02, /** FW halt or crash */ +} whd_error_num_t; + +#define WLC_SUP_STATUS_OFFSET (256) +#define WLC_DOT11_SC_STATUS_OFFSET (512) +/** + * Enumerated list of event status codes + * @note : WLC_SUP values overlap other values, so it is necessary + * to check the event type + */ +typedef enum +{ + WLC_E_STATUS_SUCCESS = 0, /** operation was successful */ + WLC_E_STATUS_FAIL = 1, /** operation failed */ + WLC_E_STATUS_TIMEOUT = 2, /** operation timed out */ + WLC_E_STATUS_NO_NETWORKS = 3, /** failed due to no matching network found */ + WLC_E_STATUS_ABORT = 4, /** operation was aborted */ + WLC_E_STATUS_NO_ACK = 5, /** protocol failure: packet not ack'd */ + WLC_E_STATUS_UNSOLICITED = 6, /** AUTH or ASSOC packet was unsolicited */ + WLC_E_STATUS_ATTEMPT = 7, /** attempt to assoc to an auto auth configuration */ + WLC_E_STATUS_PARTIAL = 8, /** scan results are incomplete */ + WLC_E_STATUS_NEWSCAN = 9, /** scan aborted by another scan */ + WLC_E_STATUS_NEWASSOC = 10, /** scan aborted due to assoc in progress */ + WLC_E_STATUS_11HQUIET = 11, /** 802.11h quiet period started */ + WLC_E_STATUS_SUPPRESS = 12, /** user disabled scanning (WLC_SET_SCANSUPPRESS) */ + WLC_E_STATUS_NOCHANS = 13, /** no allowable channels to scan */ + WLC_E_STATUS_CCXFASTRM = 14, /** scan aborted due to CCX fast roam */ + WLC_E_STATUS_CS_ABORT = 15, /** abort channel select */ + + /* for WLC_SUP messages */ + WLC_SUP_DISCONNECTED = 0 + WLC_SUP_STATUS_OFFSET, WLC_SUP_CONNECTING = 1 + WLC_SUP_STATUS_OFFSET, + WLC_SUP_IDREQUIRED = 2 + WLC_SUP_STATUS_OFFSET, WLC_SUP_AUTHENTICATING = 3 + WLC_SUP_STATUS_OFFSET, + WLC_SUP_AUTHENTICATED = 4 + WLC_SUP_STATUS_OFFSET, WLC_SUP_KEYXCHANGE = 5 + WLC_SUP_STATUS_OFFSET, + WLC_SUP_KEYED = 6 + WLC_SUP_STATUS_OFFSET, WLC_SUP_TIMEOUT = 7 + WLC_SUP_STATUS_OFFSET, + WLC_SUP_LAST_BASIC_STATE = 8 + WLC_SUP_STATUS_OFFSET, + /* Extended supplicant authentication states */ + WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED, /** Waiting to receive handshake msg M1 */ + WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE, /** Preparing to send handshake msg M2 */ + WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE, /** Waiting to receive handshake msg M3 */ + WLC_SUP_KEYXCHANGE_PREP_M4 = 9 + WLC_SUP_STATUS_OFFSET, /** Preparing to send handshake msg M4 */ + WLC_SUP_KEYXCHANGE_WAIT_G1 = 10 + WLC_SUP_STATUS_OFFSET, /** Waiting to receive handshake msg G1 */ + WLC_SUP_KEYXCHANGE_PREP_G2 = 11 + WLC_SUP_STATUS_OFFSET, /** Preparing to send handshake msg G2 */ + + WLC_DOT11_SC_SUCCESS = 0 + WLC_DOT11_SC_STATUS_OFFSET, /* Successful */ + WLC_DOT11_SC_FAILURE = 1 + WLC_DOT11_SC_STATUS_OFFSET, /* Unspecified failure */ + WLC_DOT11_SC_CAP_MISMATCH = 10 + WLC_DOT11_SC_STATUS_OFFSET, /* Cannot support all requested capabilities in the Capability Information field */ + WLC_DOT11_SC_REASSOC_FAIL = 11 + WLC_DOT11_SC_STATUS_OFFSET, /* Reassociation denied due to inability to confirm that association exists */ + WLC_DOT11_SC_ASSOC_FAIL = 12 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to reason outside the scope of this standard */ + WLC_DOT11_SC_AUTH_MISMATCH = 13 + WLC_DOT11_SC_STATUS_OFFSET, /* Responding station does not support the specified authentication algorithm */ + WLC_DOT11_SC_AUTH_SEQ = 14 + WLC_DOT11_SC_STATUS_OFFSET, /* Received an Authentication frame with authentication transaction sequence number out of expected sequence */ + WLC_DOT11_SC_AUTH_CHALLENGE_FAIL = 15 + WLC_DOT11_SC_STATUS_OFFSET, /* Authentication rejected because of challenge failure */ + WLC_DOT11_SC_AUTH_TIMEOUT = 16 + WLC_DOT11_SC_STATUS_OFFSET, /* Authentication rejected due to timeout waiting for next frame in sequence */ + WLC_DOT11_SC_ASSOC_BUSY_FAIL = 17 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied because AP is unable to handle additional associated stations */ + WLC_DOT11_SC_ASSOC_RATE_MISMATCH = 18 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to requesting station not supporting all of the data rates in the BSSBasicRateSet parameter */ + WLC_DOT11_SC_ASSOC_SHORT_REQUIRED = 19 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to requesting station not supporting the Short Preamble option */ + WLC_DOT11_SC_ASSOC_PBCC_REQUIRED = 20 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to requesting station not supporting the PBCC Modulation option */ + WLC_DOT11_SC_ASSOC_AGILITY_REQUIRED = 21 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to requesting station not supporting the Channel Agility option */ + WLC_DOT11_SC_ASSOC_SPECTRUM_REQUIRED = 22 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied because Spectrum Management capability is required. */ + WLC_DOT11_SC_ASSOC_BAD_POWER_CAP = 23 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied because the info in the Power Cap element is unacceptable. */ + WLC_DOT11_SC_ASSOC_BAD_SUP_CHANNELS = 24 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied because the info in the Supported Channel element is unacceptable */ + WLC_DOT11_SC_ASSOC_SHORTSLOT_REQUIRED = 25 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to requesting station not supporting the Short Slot Time option */ + WLC_DOT11_SC_ASSOC_ERPBCC_REQUIRED = 26 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to requesting station not supporting the ER-PBCC Modulation option */ + WLC_DOT11_SC_ASSOC_DSSOFDM_REQUIRED = 27 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to requesting station not supporting the DSS-OFDM option */ + WLC_DOT11_SC_DECLINED = 37 + WLC_DOT11_SC_STATUS_OFFSET, /* request declined */ + WLC_DOT11_SC_INVALID_PARAMS = 38 + WLC_DOT11_SC_STATUS_OFFSET, /* One or more params have invalid values */ + WLC_DOT11_SC_INVALID_AKMP = 43 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to invalid AKMP */ + WLC_DOT11_SC_INVALID_MDID = 54 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to invalid MDID */ + WLC_DOT11_SC_INVALID_FTIE = 55 + WLC_DOT11_SC_STATUS_OFFSET, /* Association denied due to invalid FTIE */ + + WLC_E_STATUS_FORCE_32_BIT = 0x7FFFFFFE /** Force enum to be stored in 32 bit variable */ +} whd_event_status_t; + +#define WLC_E_PRUNE_REASON_OFFSET (256) +#define WLC_E_SUP_REASON_OFFSET (512) +#define WLC_E_DOT11_RC_REASON_OFFSET (768) + +/** + * Enumerated list of event reason codes + * @note : Several values overlap other values, so it is necessary + * to check the event type + */ +typedef enum +{ + /* roam reason codes */ + WLC_E_REASON_INITIAL_ASSOC = 0, /** initial assoc */ + WLC_E_REASON_LOW_RSSI = 1, /** roamed due to low RSSI */ + WLC_E_REASON_DEAUTH = 2, /** roamed due to DEAUTH indication */ + WLC_E_REASON_DISASSOC = 3, /** roamed due to DISASSOC indication */ + WLC_E_REASON_BCNS_LOST = 4, /** roamed due to lost beacons */ + WLC_E_REASON_FAST_ROAM_FAILED = 5, /** roamed due to fast roam failure */ + WLC_E_REASON_DIRECTED_ROAM = 6, /** roamed due to request by AP */ + WLC_E_REASON_TSPEC_REJECTED = 7, /** roamed due to TSPEC rejection */ + WLC_E_REASON_BETTER_AP = 8, /** roamed due to finding better AP */ + + /* NAN sub-events comes as a reason code with event as WLC_E_NAN */ + WLC_E_NAN_EVENT_STATUS_CHG = 9, /* generated on any change in nan_mac status */ + WLC_E_NAN_EVENT_MERGE = 10, /* Merged to a NAN cluster */ + WLC_E_NAN_EVENT_STOP = 11, /* NAN stopped */ + WLC_E_NAN_EVENT_P2P = 12, /* NAN P2P EVENT */ + + /* XXX: Dont use below four events: They will be cleanup, use WL_NAN_EVENT_POST_DISC */ + WLC_E_NAN_EVENT_WINDOW_BEGIN_P2P = 13, /* Event for begin of P2P further availability window */ + WLC_E_NAN_EVENT_WINDOW_BEGIN_MESH = 14, WLC_E_NAN_EVENT_WINDOW_BEGIN_IBSS = 15, + WLC_E_NAN_EVENT_WINDOW_BEGIN_RANGING = 16, WLC_E_NAN_EVENT_POST_DISC = 17, /* Event for post discovery data */ + WLC_E_NAN_EVENT_DATA_IF_ADD = 18, /* Event for Data IF add */ + WLC_E_NAN_EVENT_DATA_PEER_ADD = 19, /* Event for peer add */ + + /* nan 2.0 */ + WLC_E_NAN_EVENT_DATA_IND = 20, /* Data Indication to Host */ + WLC_E_NAN_EVENT_DATA_CONF = 21, /* Data Response to Host */ + WLC_E_NAN_EVENT_SDF_RX = 22, /* entire service discovery frame */ + WLC_E_NAN_EVENT_DATA_END = 23, WLC_E_NAN_EVENT_BCN_RX = 24, /* received beacon payload */ + + /* prune reason codes */ + WLC_E_PRUNE_ENCR_MISMATCH = 1 + WLC_E_PRUNE_REASON_OFFSET, /** encryption mismatch */ + WLC_E_PRUNE_BCAST_BSSID = 2 + WLC_E_PRUNE_REASON_OFFSET, /** AP uses a broadcast BSSID */ + WLC_E_PRUNE_MAC_DENY = 3 + WLC_E_PRUNE_REASON_OFFSET, /** STA's MAC addr is in AP's MAC deny list */ + WLC_E_PRUNE_MAC_NA = 4 + WLC_E_PRUNE_REASON_OFFSET, /** STA's MAC addr is not in AP's MAC allow list */ + WLC_E_PRUNE_REG_PASSV = 5 + WLC_E_PRUNE_REASON_OFFSET, /** AP not allowed due to regulatory restriction */ + WLC_E_PRUNE_SPCT_MGMT = 6 + WLC_E_PRUNE_REASON_OFFSET, /** AP does not support STA locale spectrum mgmt */ + WLC_E_PRUNE_RADAR = 7 + WLC_E_PRUNE_REASON_OFFSET, /** AP is on a radar channel of STA locale */ + WLC_E_RSN_MISMATCH = 8 + WLC_E_PRUNE_REASON_OFFSET, /** STA does not support AP's RSN */ + WLC_E_PRUNE_NO_COMMON_RATES = 9 + WLC_E_PRUNE_REASON_OFFSET, /** No rates in common with AP */ + WLC_E_PRUNE_BASIC_RATES = 10 + WLC_E_PRUNE_REASON_OFFSET, /** STA does not support all basic rates of BSS */ + WLC_E_PRUNE_CCXFAST_PREVAP = 11 + WLC_E_PRUNE_REASON_OFFSET, /** CCX FAST ROAM: prune previous AP */ + WLC_E_PRUNE_CIPHER_NA = 12 + WLC_E_PRUNE_REASON_OFFSET, /** BSS's cipher not supported */ + WLC_E_PRUNE_KNOWN_STA = 13 + WLC_E_PRUNE_REASON_OFFSET, /** AP is already known to us as a STA */ + WLC_E_PRUNE_CCXFAST_DROAM = 14 + WLC_E_PRUNE_REASON_OFFSET, /** CCX FAST ROAM: prune unqualified AP */ + WLC_E_PRUNE_WDS_PEER = 15 + WLC_E_PRUNE_REASON_OFFSET, /** AP is already known to us as a WDS peer */ + WLC_E_PRUNE_QBSS_LOAD = 16 + WLC_E_PRUNE_REASON_OFFSET, /** QBSS LOAD - AAC is too low */ + WLC_E_PRUNE_HOME_AP = 17 + WLC_E_PRUNE_REASON_OFFSET, /** prune home AP */ + WLC_E_PRUNE_AP_BLOCKED = 18 + WLC_E_PRUNE_REASON_OFFSET, /** prune blocked AP */ + WLC_E_PRUNE_NO_DIAG_SUPPORT = 19 + WLC_E_PRUNE_REASON_OFFSET, /** prune due to diagnostic mode not supported */ + + /* WPA failure reason codes carried in the WLC_E_PSK_SUP event */ + WLC_E_SUP_OTHER = 0 + WLC_E_SUP_REASON_OFFSET, /** Other reason */ + WLC_E_SUP_DECRYPT_KEY_DATA = 1 + WLC_E_SUP_REASON_OFFSET, /** Decryption of key data failed */ + WLC_E_SUP_BAD_UCAST_WEP128 = 2 + WLC_E_SUP_REASON_OFFSET, /** Illegal use of ucast WEP128 */ + WLC_E_SUP_BAD_UCAST_WEP40 = 3 + WLC_E_SUP_REASON_OFFSET, /** Illegal use of ucast WEP40 */ + WLC_E_SUP_UNSUP_KEY_LEN = 4 + WLC_E_SUP_REASON_OFFSET, /** Unsupported key length */ + WLC_E_SUP_PW_KEY_CIPHER = 5 + WLC_E_SUP_REASON_OFFSET, /** Unicast cipher mismatch in pairwise key */ + WLC_E_SUP_MSG3_TOO_MANY_IE = 6 + WLC_E_SUP_REASON_OFFSET, /** WPA IE contains > 1 RSN IE in key msg 3 */ + WLC_E_SUP_MSG3_IE_MISMATCH = 7 + WLC_E_SUP_REASON_OFFSET, /** WPA IE mismatch in key message 3 */ + WLC_E_SUP_NO_INSTALL_FLAG = 8 + WLC_E_SUP_REASON_OFFSET, /** INSTALL flag unset in 4-way msg */ + WLC_E_SUP_MSG3_NO_GTK = 9 + WLC_E_SUP_REASON_OFFSET, /** encapsulated GTK missing from msg 3 */ + WLC_E_SUP_GRP_KEY_CIPHER = 10 + WLC_E_SUP_REASON_OFFSET, /** Multicast cipher mismatch in group key */ + WLC_E_SUP_GRP_MSG1_NO_GTK = 11 + WLC_E_SUP_REASON_OFFSET, /** encapsulated GTK missing from group msg 1 */ + WLC_E_SUP_GTK_DECRYPT_FAIL = 12 + WLC_E_SUP_REASON_OFFSET, /** GTK decrypt failure */ + WLC_E_SUP_SEND_FAIL = 13 + WLC_E_SUP_REASON_OFFSET, /** message send failure */ + WLC_E_SUP_DEAUTH = 14 + WLC_E_SUP_REASON_OFFSET, /** received FC_DEAUTH */ + WLC_E_SUP_WPA_PSK_TMO = 15 + WLC_E_SUP_REASON_OFFSET, /** WPA PSK 4-way handshake timeout */ + + DOT11_RC_RESERVED = 0 + WLC_E_DOT11_RC_REASON_OFFSET, /* d11 RC reserved */ + DOT11_RC_UNSPECIFIED = 1 + WLC_E_DOT11_RC_REASON_OFFSET, /* Unspecified reason */ + DOT11_RC_AUTH_INVAL = 2 + WLC_E_DOT11_RC_REASON_OFFSET, /* Previous authentication no longer valid */ + DOT11_RC_DEAUTH_LEAVING = 3 + WLC_E_DOT11_RC_REASON_OFFSET, /* Deauthenticated because sending station is leaving (or has left) IBSS or ESS */ + DOT11_RC_INACTIVITY = 4 + WLC_E_DOT11_RC_REASON_OFFSET, /* Disassociated due to inactivity */ + DOT11_RC_BUSY = 5 + WLC_E_DOT11_RC_REASON_OFFSET, /* Disassociated because AP is unable to handle all currently associated stations */ + DOT11_RC_INVAL_CLASS_2 = 6 + WLC_E_DOT11_RC_REASON_OFFSET, /* Class 2 frame received from nonauthenticated station */ + DOT11_RC_INVAL_CLASS_3 = 7 + WLC_E_DOT11_RC_REASON_OFFSET, /* Class 3 frame received from nonassociated station */ + DOT11_RC_DISASSOC_LEAVING = 8 + WLC_E_DOT11_RC_REASON_OFFSET, /* Disassociated because sending station is leaving (or has left) BSS */ + DOT11_RC_NOT_AUTH = 9 + WLC_E_DOT11_RC_REASON_OFFSET, /* Station requesting (re)association is not * authenticated with responding station */ + DOT11_RC_BAD_PC = 10 + WLC_E_DOT11_RC_REASON_OFFSET, /* Unacceptable power capability element */ + DOT11_RC_BAD_CHANNELS = 11 + WLC_E_DOT11_RC_REASON_OFFSET, /* Unacceptable supported channels element */ + /* 12 is unused */ + /* XXX 13-23 are WPA/802.11i reason codes defined in proto/wpa.h */ + /* 32-39 are QSTA specific reasons added in 11e */ + DOT11_RC_UNSPECIFIED_QOS = 32 + WLC_E_DOT11_RC_REASON_OFFSET, /* unspecified QoS-related reason */ + DOT11_RC_INSUFFCIENT_BW = 33 + WLC_E_DOT11_RC_REASON_OFFSET, /* QAP lacks sufficient bandwidth */ + DOT11_RC_EXCESSIVE_FRAMES = 34 + WLC_E_DOT11_RC_REASON_OFFSET, /* excessive number of frames need ack */ + DOT11_RC_TX_OUTSIDE_TXOP = 35 + WLC_E_DOT11_RC_REASON_OFFSET, /* transmitting outside the limits of txop */ + DOT11_RC_LEAVING_QBSS = 36 + WLC_E_DOT11_RC_REASON_OFFSET, /* QSTA is leaving the QBSS (or restting) */ + DOT11_RC_BAD_MECHANISM = 37 + WLC_E_DOT11_RC_REASON_OFFSET, /* does not want to use the mechanism */ + DOT11_RC_SETUP_NEEDED = 38 + WLC_E_DOT11_RC_REASON_OFFSET, /* mechanism needs a setup */ + DOT11_RC_TIMEOUT = 39 + WLC_E_DOT11_RC_REASON_OFFSET, /* timeout */ + DOT11_RC_MAX = 23 + WLC_E_DOT11_RC_REASON_OFFSET, /* Reason codes > 23 are reserved */ + + WLC_E_REASON_FORCE_32_BIT = 0x7FFFFFFE /** Force enum to be stored in 32 bit variable */ +} whd_event_reason_t; + +typedef enum +{ + WLC_E_NAN_EVENT_START = 1, /* NAN cluster started */ + WLC_E_NAN_EVENT_JOIN = 2, /* Joined to a NAN cluster */ + WLC_E_NAN_EVENT_ROLE = 3, /* Role or State changed */ + WLC_E_NAN_EVENT_SCAN_COMPLETE = 4, WLC_E_NAN_EVENT_DISCOVERY_RESULT = 5, WLC_E_NAN_EVENT_REPLIED = 6, + WLC_E_NAN_EVENT_TERMINATED = 7, /* the instance ID will be present in the ev data */ + WLC_E_NAN_EVENT_RECEIVE = 8 + +} whd_nan_events_t; + +/* Reason codes for LINK */ +#define WLC_E_LINK_BCN_LOSS 1 /** Link down because of beacon loss */ +#define WLC_E_LINK_DISASSOC 2 /** Link down because of disassoc */ +#define WLC_E_LINK_ASSOC_REC 3 /** Link down because assoc recreate failed */ +#define WLC_E_LINK_BSSCFG_DIS 4 /** Link down due to bsscfg down */ + +/** + * Event handler prototype definition + * + * @param[out] whd_event_header_t : whd event header + * @param[out] uint8_t* : event data + * @param[out] handler_user_data : semaphore data + */ +typedef void *(*whd_event_handler_t)(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data); +/** @endcond */ + +/** + * Error handler prototype definition + * + * @param[out] uint8_t : error_type + * @param[out] uint8_t* : event data + * @param[out] handler_user_data : semaphore data + */ +typedef void *(*whd_error_handler_t)(whd_driver_t whd_driver, const uint8_t *error_type, + const uint8_t *event_data, void *handler_user_data); +/** @endcond */ +extern whd_result_t whd_management_set_event_handler_locally(whd_interface_t ifp, + const whd_event_num_t *event_nums, + whd_event_handler_t handler_func, + void *handler_user_data, uint16_t *event_index); + +extern whd_result_t whd_management_set_event_handler(whd_interface_t ifp, const whd_event_num_t *event_nums, + whd_event_handler_t handler_func, + void *handler_user_data, uint16_t *event_index); + +extern uint32_t whd_wifi_set_event_handler(whd_interface_t ifp, const uint32_t *event_type, + whd_event_handler_t handler_func, + void *handler_user_data, uint16_t *event_index); + +extern uint32_t whd_wifi_deregister_event_handler(whd_interface_t ifp, uint16_t event_index); + +extern whd_result_t whd_set_error_handler_locally(whd_driver_t whd_driver, const uint8_t *error_nums, + whd_error_handler_t handler_func, + void *handler_user_data, uint16_t *error_index); + +extern whd_result_t whd_wifi_set_error_handler(whd_interface_t ifp, const uint8_t *error_type, + whd_error_handler_t handler_func, + void *handler_user_data, uint16_t *error_index); + +extern uint32_t whd_wifi_deregister_error_handler(whd_interface_t ifp, uint16_t error_index); + +/** @cond */ + +//extern void* whd_rrm_report_handler( const whd_event_header_t* event_header, const uint8_t* event_data, void* handler_user_data ); + +extern void *whd_nan_scan_handler(const whd_event_header_t *event_header, const uint8_t *event_data, + void *handler_user_data); + +#define WHD_MSG_IFNAME_MAX 16 + +/* Maximum number of events registered at a time */ +#define WHD_MAX_EVENT_SUBSCRIPTION 33 + +#define WHD_EVENT_NOT_REGISTERED 0xFF +/* Enum to index and find the entry of paricular event registered */ +typedef enum +{ + WHD_SCAN_EVENT_ENTRY = 0, + WHD_JOIN_EVENT_ENTRY, + WHD_AP_EVENT_ENTRY, + WHD_P2P_EVENT_ENTRY, + WHD_AUTH_EVENT_ENTRY, + WHD_EVENT_ENTRY_MAX +} whd_event_entry_t; + +#pragma pack(1) +typedef struct whd_event_eth_hdr +{ + uint16_t subtype; /** Vendor specific..32769 */ + uint16_t length; + uint8_t version; /** Version is 0 */ + uint8_t oui[3]; /** OUI */ + uint16_t usr_subtype; /** user specific Data */ +} whd_event_eth_hdr_t; + +typedef struct whd_event_ether_header +{ + whd_mac_t destination_address; + whd_mac_t source_address; + uint16_t ethertype; +} whd_event_ether_header_t; + +struct whd_event_msg +{ + uint16_t version; + uint16_t flags; /* see flags below */ + uint32_t event_type; /* Message (see below) */ + uint32_t status; /* Status code (see below) */ + uint32_t reason; /* Reason code (if applicable) */ + uint32_t auth_type; /* WLC_E_AUTH */ + uint32_t datalen; /* data buf */ + whd_mac_t addr; /* Station address (if applicable) */ + char ifname[WHD_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ + uint8_t ifidx; /* destination OS i/f index */ + uint8_t bsscfgidx; /* source bsscfg index */ +}; + +/* used by driver msgs */ +typedef struct whd_event +{ + whd_event_ether_header_t eth; + whd_event_eth_hdr_t eth_evt_hdr; + whd_event_header_t whd_event; + /* data portion follows */ +} whd_event_t; + +#pragma pack() + +/** @endcond */ + +/** @} */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef INCLUDED_WHD_EVENTS_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_int.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_int.h new file mode 100644 index 00000000..08a6b370 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_int.h @@ -0,0 +1,132 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Header for whd_driver structure + */ + +#ifndef INCLUDED_WHD_INT_H +#define INCLUDED_WHD_INT_H + +#include "whd_thread.h" +#include "whd_sdpcm.h" +#include "whd_cdc_bdc.h" +#include "whd_chip.h" +#include "whd_ap.h" +#include "whd_debug.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct +{ + uint32_t tx_total; /* Total number of TX packets sent from WHD */ + uint32_t rx_total; /* Total number of RX packets received at WHD */ + uint32_t tx_no_mem; /* Number of times WHD could not send due to no buffer */ + uint32_t rx_no_mem; /* Number of times WHD could not receive due to no buffer */ + uint32_t tx_fail; /* Number of times TX packet failed */ + uint32_t no_credit; /* Number of times WHD could not send due to no credit */ + uint32_t flow_control; /* Number of times WHD Flow control is enabled */ + uint32_t internal_host_buffer_fail_with_timeout; /* Internal host buffer get failed after timeout */ +} whd_stats_t; + +#define WHD_INTERFACE_MAX 3 +typedef enum +{ + WHD_INVALID_ROLE = 0, + WHD_STA_ROLE = 1, /**< STA or Client Interface */ + WHD_AP_ROLE = 2, /**< softAP Interface */ + WHD_P2P_ROLE = 3, /**< P2P Interface */ +} whd_interface_role_t; + + +struct whd_interface +{ + whd_driver_t whd_driver; + uint8_t ifidx; + uint8_t bsscfgidx; + + char if_name[WHD_MSG_IFNAME_MAX]; + whd_interface_role_t role; + whd_mac_t mac_addr; + uint8_t event_reg_list[WHD_EVENT_ENTRY_MAX]; + whd_bool_t state; +}; +struct whd_bt_dev +{ + void *bt_data; + void (*bt_int_cb)(void *data); + uint32_t bt_use_count; + whd_bool_t intr; +}; + +struct whd_bt_info +{ + uint32_t bt_buf_reg_addr; + uint32_t host_ctrl_reg_addr; + uint32_t bt_ctrl_reg_addr; + uint32_t wlan_buf_addr; +}; + +struct whd_driver +{ + whd_interface_t iflist[WHD_INTERFACE_MAX]; + uint8_t if2ifp[WHD_INTERFACE_MAX]; + + /* Bus variables */ + struct whd_bus_info *bus_if; + struct whd_bus_priv *bus_priv; + struct whd_bus_common_info *bus_common_info; + whd_bt_dev_t bt_dev; + + whd_buffer_funcs_t *buffer_if; + whd_netif_funcs_t *network_if; + whd_resource_source_t *resource_if; + uint8_t *aligned_addr; + + whd_bool_t bus_gspi_32bit; + + whd_thread_info_t thread_info; + whd_cdc_bdc_info_t cdc_bdc_info; + whd_error_info_t error_info; + whd_sdpcm_info_t sdpcm_info; + whd_internal_info_t internal_info; + whd_ap_int_info_t ap_info; + whd_chip_info_t chip_info; + + whd_stats_t whd_stats; + whd_country_code_t country; + + whd_ioctl_log_t whd_ioctl_log[WHD_IOCTL_LOG_SIZE]; + int whd_ioctl_log_index; + cy_semaphore_t whd_log_mutex; +}; + +whd_result_t whd_add_interface(whd_driver_t whd_driver, uint8_t bsscfgidx, uint8_t ifidx, + const char *name, whd_mac_t *mac_addr, whd_interface_t *ifpp); + +whd_result_t whd_add_primary_interface(whd_driver_t whd_driver, whd_interface_t *ifpp); + +whd_interface_t whd_get_primary_interface(whd_driver_t whd_driver); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* INCLUDED_WHD_INT_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_network_if.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_network_if.h new file mode 100644 index 00000000..6b9bef69 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_network_if.h @@ -0,0 +1,75 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides prototypes / declarations for common APSTA functionality + */ +#ifndef _WHD_INTERNAL_NETWORK_API_H_ +#define _WHD_INTERNAL_NETWORK_API_H_ + +#include "whd.h" +#include "whd_int.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Macros +******************************************************/ + +/****************************************************** +* Structures +******************************************************/ + +/****************************************************** +* Function prototypes +******************************************************/ +/** Called by WHD to pass received data to the network stack + * + * + * Packets received from the Wi-Fi network by WHD are forwarded to by calling function ptr which + * must be implemented in the network interface. Ethernet headers + * are present at the start of these packet buffers. + * + * This function is called asynchronously in the context of the + * WHD thread whenever new data has arrived. + * Packet buffers are allocated within WHD, and ownership is transferred + * to the network stack. The network stack or application is thus + * responsible for releasing the packet buffers. + * Most packet buffering systems have a pointer to the 'current point' within + * the packet buffer. When this function is called, the pointer points + * to the start of the Ethernet header. There is other inconsequential data + * before the Ethernet header. + * + * It is preferable that the (whd_network_process_ethernet_data)() function simply puts + * the received packet on a queue for processing by another thread. This avoids the + * WHD thread being unnecessarily tied up which would delay other packets + * being transmitted or received. + * + * @param interface : The interface on which the packet was received. + * @param buffer : Handle of the packet which has just been received. Responsibility for + * releasing this buffer is transferred from WHD at this point. + * + */ +whd_result_t whd_network_process_ethernet_data(whd_interface_t ifp, whd_buffer_t buffer); +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif /* ifndef _WHD_INTERNAL_NETWORK_API_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_poll.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_poll.h new file mode 100644 index 00000000..dc3d8ca3 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_poll.h @@ -0,0 +1,92 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Header for using WHD with no RTOS or network stack + * + * It is possible to use these WHD without any operating system. To do this, + * the user application is required to periodically use the functions in this + * file to allow WHD to send and receive data across the SPI/SDIO bus. + * + */ + +#include "whd.h" + +#ifndef INCLUDED_WHD_POLL_H +#define INCLUDED_WHD_POLL_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Function declarations +******************************************************/ + + +/** Sends the first queued packet + * + * Checks the queue to determine if there is any packets waiting + * to be sent. If there are, then it sends the first one. + * + * This function is normally used by the WHD Thread, but can be + * called periodically by systems which have no RTOS to ensure + * packets get sent. + * + * @return 1 : packet was sent + * 0 : no packet sent + */ +extern int8_t whd_thread_send_one_packet(whd_driver_t whd_driver); + + +/** Receives a packet if one is waiting + * + * Checks the wifi chip fifo to determine if there is any packets waiting + * to be received. If there are, then it receives the first one, and calls + * the callback @ref whd_sdpcm_process_rx_packet (in whd_sdpcm.c). + * + * This function is normally used by the WHD Thread, but can be + * called periodically by systems which have no RTOS to ensure + * packets get received properly. + * + * @return 1 : packet was received + * 0 : no packet waiting + */ +extern int8_t whd_thread_receive_one_packet(whd_driver_t whd_driver); + + +/** Sends and Receives all waiting packets + * + * Repeatedly calls whd_thread_send_one_packet and whd_thread_receive_one_packet + * to send and receive packets, until there are no more packets waiting to + * be transferred. + * + * This function is normally used by the WHD Thread, but can be + * called periodically by systems which have no RTOS to ensure + * packets get send and received properly. + * + * @return 1 : packet was sent or received + * 0 : no packet was sent or received + */ +extern int8_t whd_thread_poll_all(whd_driver_t whd_driver); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef INCLUDED_WHD_POLL_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_resource_if.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_resource_if.h new file mode 100644 index 00000000..a4ccae15 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_resource_if.h @@ -0,0 +1,57 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides prototypes / declarations for common APSTA functionality + */ +#ifndef _WHD_INTERNAL_RESOURCE_API_H_ +#define _WHD_INTERNAL_RESOURCE_API_H_ + +#include "whd.h" +#include "whd_int.h" +#include "whd_resource_api.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Macros +******************************************************/ + +/****************************************************** +* Structures +******************************************************/ + +/****************************************************** +* Function prototypes +******************************************************/ +uint32_t whd_resource_size(whd_driver_t whd_driver, whd_resource_type_t resource, uint32_t *size_out); +uint32_t whd_get_resource_block_size(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *size_out); +uint32_t whd_get_resource_no_of_blocks(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *block_count); +uint32_t whd_get_resource_block(whd_driver_t whd_driver, whd_resource_type_t type, + uint32_t blockno, const uint8_t **data, uint32_t *size_out); + +uint32_t whd_resource_read(whd_driver_t whd_driver, whd_resource_type_t type, uint32_t offset, + uint32_t size, uint32_t *size_out, void *buffer); + +#ifdef __cplusplus +} /*extern "C" */ +#endif + +#endif /* ifndef _WHD_INTERNAL_RESOURCE_API_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_sdpcm.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_sdpcm.h new file mode 100644 index 00000000..0c72ca65 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_sdpcm.h @@ -0,0 +1,123 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides whd with function prototypes for IOCTL commands, + * and for communicating with the SDPCM module + * + */ + +#ifndef INCLUDED_WHD_SDPCM_H +#define INCLUDED_WHD_SDPCM_H + +#include "whd.h" +#include "whd_events_int.h" +#include "cyabs_rtos.h" +#include "whd_network_types.h" +#include "whd_types_int.h" +#include "whd_cdc_bdc.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Constants +******************************************************/ +typedef enum +{ + DATA_HEADER = 2, + ASYNCEVENT_HEADER = 1, + CONTROL_HEADER = 0 +} sdpcm_header_type_t; + +/****************************************************** +* Macros +******************************************************/ + +#define BUS_HEADER_LEN (12) +#define IOCTL_OFFSET (sizeof(whd_buffer_header_t) + 12 + 16) + +/****************************************************** +* Structures +******************************************************/ +typedef struct whd_sdpcm_info +{ + /* Bus data credit variables */ + uint8_t tx_seq; + uint8_t tx_max; + + + /* Packet send queue variables */ + cy_semaphore_t send_queue_mutex; + whd_buffer_t send_queue_head[5]; + whd_buffer_t send_queue_tail[5]; + uint32_t npkt_in_q[5]; /** 4 AC queues + 1 Contol queue(IOVAR/IOCTLs) */ + uint32_t totpkt_in_q; +} whd_sdpcm_info_t; + +typedef struct +{ + whd_buffer_header_t buffer_header; + uint8_t bus_header[BUS_HEADER_LEN]; +} bus_common_header_t; + +#pragma pack(1) +typedef struct +{ + bus_common_header_t common; + cdc_header_t cdc_header; +} control_header_t; + +typedef struct +{ + bus_common_header_t common; + uint8_t _padding[2]; + bdc_header_t bdc_header; +} data_header_t; +#pragma pack() + +/****************************************************** +* Function declarations +******************************************************/ + +extern void whd_sdpcm_process_rx_packet(whd_driver_t whd_driver, whd_buffer_t buffer); +extern whd_result_t whd_sdpcm_init(whd_driver_t whd_driver); +extern void whd_sdpcm_quit(whd_driver_t whd_driver); +extern void whd_sdpcm_bus_vars_init(whd_driver_t whd_driver); +extern void whd_sdpcm_quit(whd_driver_t whd_driver); +extern whd_bool_t whd_sdpcm_has_tx_packet(whd_driver_t whd_driver); + +extern whd_result_t whd_sdpcm_get_packet_to_send(whd_driver_t whd_driver, whd_buffer_t *buffer); +extern void whd_sdpcm_update_credit(whd_driver_t whd_driver, uint8_t *data); +extern uint8_t whd_sdpcm_get_available_credits(whd_driver_t whd_driver); +extern void whd_update_host_interface_to_bss_index_mapping(whd_driver_t whd_driver, whd_interface_t interface, + uint32_t bssid_index); + +extern whd_result_t whd_send_to_bus(whd_driver_t whd_driver, whd_buffer_t buffer, + sdpcm_header_type_t header_type, uint8_t prio); + +/****************************************************** +* Global variables +******************************************************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_SDPCM_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_thread.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_thread.h new file mode 100644 index 00000000..d9330bda --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_thread.h @@ -0,0 +1,92 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * The whd Thread allows thread safe access to the whd hardware bus + * This is an whd internal file and should not be used by functions outside whd. + * + * This file provides prototypes for functions which allow multiple threads to use the whd hardware bus (SDIO or SPI) + * This is achieved by having a single thread (the "whd Thread") which queues messages to be sent, sending + * them sequentially, as well as receiving messages as they arrive. + * + * Messages to be sent come from the @ref whd_sdpcm_send_common function in whd_sdpcm.c . The messages already + * contain SDPCM headers, but not any bus headers (GSPI), and are passed via a queue + * This function can be called from any thread. + * + * Messages are received by way of a callback supplied by in whd_sdpcm.c - whd_sdpcm_process_rx_packet + * Received messages are delivered in the context of the whd Thread, so the callback function needs to avoid blocking. + * + */ +#include "cyabs_rtos.h" +#include "whd.h" + +#ifndef INCLUDED_WHD_THREAD_H_ +#define INCLUDED_WHD_THREAD_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Constants +******************************************************/ +#define WHD_THREAD_RX_BOUND (20) +#define WHD_MAX_BUS_FAIL (10) + +typedef struct whd_thread_info +{ + + volatile whd_bool_t thread_quit_flag; + volatile whd_bool_t whd_inited; + cy_thread_t whd_thread; + cy_semaphore_t transceive_semaphore; + volatile whd_bool_t bus_interrupt; + void *thread_stack_start; + uint32_t thread_stack_size; + cy_thread_priority_t thread_priority; + +} whd_thread_info_t; + +void whd_thread_info_init(whd_driver_t whd_driver, whd_init_config_t *whd_init_config); + +/** Initialises the whd Thread + * + * Initialises the whd thread, and its flags/semaphores, + * then starts it running + * + * @return whd result code + */ +extern whd_result_t whd_thread_init(whd_driver_t whd_driver); + + +/** Terminates the whd Thread + * + * Sets a flag then wakes the whd Thread to force it to terminate. + * + */ +extern void whd_thread_quit(whd_driver_t whd_driver); + + +extern void whd_thread_notify(whd_driver_t whd_driver); +extern void whd_thread_notify_irq(whd_driver_t whd_driver); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_THREAD_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_thread_internal.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_thread_internal.h new file mode 100644 index 00000000..fec76e75 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_thread_internal.h @@ -0,0 +1,54 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_WHD_THREAD_INTERNAL_H +#define INCLUDED_WHD_THREAD_INTERNAL_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "whd_debug.h" +#include "whd_int.h" + +/****************************************************** +* Macros +******************************************************/ + +#define WHD_WLAN_KEEP_AWAKE(whd_driver) \ + do { \ + whd_result_t verify_result; \ + whd_driver->internal_info.whd_wlan_status.keep_wlan_awake++; \ + verify_result = whd_ensure_wlan_bus_is_up(whd_driver); \ + whd_assert("Could not bring bus up", (verify_result == WHD_SUCCESS) ); \ + } while (0) +#define WHD_WLAN_LET_SLEEP(whd_driver) \ + do { \ + whd_driver->internal_info.whd_wlan_status.keep_wlan_awake--; \ + if (whd_driver->internal_info.whd_wlan_status.keep_wlan_awake == 0) \ + whd_thread_notify(whd_driver); \ + } while (0) +#define WHD_WLAN_MAY_SLEEP() \ + ( (whd_driver->internal_info.whd_wlan_status.keep_wlan_awake == 0) && \ + (whd_driver->internal_info.whd_wlan_status.state == WLAN_UP) ) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_THREAD_INTERNAL_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_types_int.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_types_int.h new file mode 100644 index 00000000..546edcda --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_types_int.h @@ -0,0 +1,439 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Defines common constants used with WHD within src folder + * + */ + +#ifndef INCLUDED_WHD_TYPES_INT_H_ +#define INCLUDED_WHD_TYPES_INT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** +* Macros +******************************************************/ +/** + * The size of an Ethernet header + */ +#define WHD_ETHERNET_SIZE (14) + +/** + * Ethernet Ethertypes + */ +#define WHD_ETHERTYPE_IPv4 0x0800 +#define WHD_ETHERTYPE_IPv6 0x86DD +#define WHD_ETHERTYPE_ARP 0x0806 +#define WHD_ETHERTYPE_RARP 0x8035 +#define WHD_ETHERTYPE_EAPOL 0x888E +#define WHD_ETHERTYPE_DOT1AS 0x88F7 +#define WHD_ETHERTYPE_8021Q 0x8100 + +/* bss_info_cap_t flags */ +#define WL_BSS_FLAGS_FROM_BEACON 0x01 /* bss_info derived from beacon */ +#define WL_BSS_FLAGS_FROM_CACHE 0x02 /* bss_info collected from cache */ +#define WL_BSS_FLAGS_RSSI_ONCHANNEL 0x04 /* rssi info received on channel (vs offchannel) */ +#define WL_BSS_FLAGS_HS20 0x08 /* hotspot 2.0 capable */ +#define WL_BSS_FLAGS_RSSI_INVALID 0x10 /* BSS contains invalid RSSI */ +#define WL_BSS_FLAGS_RSSI_INACCURATE 0x20 /* BSS contains inaccurate RSSI */ +#define WL_BSS_FLAGS_SNR_INVALID 0x40 /* BSS contains invalid SNR */ +#define WL_BSS_FLAGS_NF_INVALID 0x80 /* BSS contains invalid noise floor */ + +#define HT_CAPABILITIES_IE_LENGTH (26) +#define DOT11_OUI_LEN (3)/** Length in bytes of 802.11 OUI*/ +#define DOT11_MGMT_HDR_LEN (24) /* dot11 management header len */ + +#define WHD_ETHER_ADDR_STR_LEN (18) +#define WHD_ETHER_ADDR_LEN (6) + +#define CHECK_IOCTL_BUFFER(buff) if (buff == \ + NULL){ WPRINT_WHD_ERROR( ("Buffer alloc failed in function %s at line %d \n", \ + __func__, __LINE__) ); \ + return WHD_BUFFER_ALLOC_FAIL; } +#define CHECK_PACKET_NULL(buff, err) if (buff == \ + NULL){ WPRINT_WHD_ERROR( ("No register function pointer in %s at line %d \n", \ + __func__, __LINE__) ); \ + return err;} +#define CHECK_PACKET_WITH_NULL_RETURN(buff) if (buff == \ + NULL){ WPRINT_WHD_ERROR( ( \ + "No register function pointer in %s at line %d \n", \ + __func__, __LINE__) ); \ + return;} + +#define CHECK_RETURN(expr) { \ + whd_result_t check_res = (expr); \ + if (check_res != WHD_SUCCESS) \ + { \ + WPRINT_WHD_ERROR( ("Function %s failed at line %d checkres = %u \n", \ + __func__, __LINE__, \ + (unsigned int)check_res) ); \ + return check_res; \ + } \ +} + +#define CHECK_RETURN_UNSUPPORTED_OK(expr) { whd_result_t check_res = (expr); \ + if (check_res != WHD_SUCCESS) \ + { \ + return check_res; \ + } \ +} +#define CHECK_RETURN_UNSUPPORTED_CONTINUE(expr) { whd_result_t check_res = (expr); \ + if (check_res != WHD_SUCCESS && check_res != WHD_WLAN_UNSUPPORTED) \ + { \ + return check_res; \ + } \ +} +#define RETURN_WITH_ASSERT(expr) { whd_result_t check_res = (expr); \ + whd_assert("Command failed\n", check_res == WHD_SUCCESS); \ + return check_res; } + +#define CHECK_RETURN_IGNORE(expr) { whd_result_t check_res = (expr); \ + if (check_res != WHD_SUCCESS) \ + { \ + } \ +} + +#define CHECK_IFP_NULL(ifp) if (ifp == \ + NULL){ WPRINT_WHD_ERROR( ( \ + "Interface is not up/NULL and failed in function %s at line %d \n", \ + __func__, __LINE__) ); \ + return WHD_UNKNOWN_INTERFACE; } + +#define CHECK_DRIVER_NULL(driver) if (driver == \ + NULL){ WPRINT_WHD_ERROR( ( \ + "WHD driver is not up/NULL and failed in function %s at line %d \n", \ + __func__, __LINE__) ); \ + return WHD_DOES_NOT_EXIST; } + +#define MIN_OF(x, y) ( (x) < (y) ? (x) : (y) ) +#define MAX_OF(x, y) ( (x) > (y) ? (x) : (y) ) + +#ifndef ROUND_UP +#define ROUND_UP(x, y) ( (x) % (y) ? (x) + (y) - ( (x) % (y) ) : (x) ) +#endif + +#ifndef DIV_ROUND_UP +#define DIV_ROUND_UP(m, n) ( ( (m) + (n) - 1 ) / (n) ) +#endif + +#define WHD_WRITE_16(pointer, value) (*( (uint16_t *)pointer ) = value) +#define WHD_WRITE_32(pointer, value) (*( (uint32_t *)pointer ) = value) +#define WHD_READ_16(pointer) *( (uint16_t *)pointer ) +#define WHD_READ_32(pointer) *( (uint32_t *)pointer ) + +/** + * Macro for checking for NULL MAC addresses + */ +#define NULL_MAC(a) ( ( ( ( (unsigned char *)a )[0] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[1] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[2] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[3] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[4] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[5] ) == 0 ) ) + +/** + * Macro for checking for Broadcast address + */ +#define BROADCAST_ID(a) ( ( ( ( (unsigned char *)a )[0] ) == 255 ) && \ + ( ( ( (unsigned char *)a )[1] ) == 255 ) && \ + ( ( ( (unsigned char *)a )[2] ) == 255 ) && \ + ( ( ( (unsigned char *)a )[3] ) == 255 ) && \ + ( ( ( (unsigned char *)a )[4] ) == 255 ) && \ + ( ( ( (unsigned char *)a )[5] ) == 255 ) ) + +/* Suppress unused variable warning occurring due to an assert which is disabled in release mode */ +#define REFERENCE_DEBUG_ONLY_VARIABLE(x) ( (void)(x) ) + +/* Suppress unused parameter warning */ +#define UNUSED_PARAMETER(x) ( (void)(x) ) + +/* Suppress unused variable warning */ +#define UNUSED_VARIABLE(x) ( (void)(x) ) + +#if defined (__IAR_SYSTEMS_ICC__) +#define DISABLE_COMPILER_WARNING(x) _Pragma(#x) +#define ENABLE_COMPILER_WARNING(x) _Pragma(#x) +#else +#define DISABLE_COMPILER_WARNING(x) +#define ENABLE_COMPILER_WARNING(x) +#endif + +/****************************************************** +* Type Definitions +******************************************************/ + +/****************************************************** +* Constants +******************************************************/ + +/****************************************************** +* Structures and Enumerations +******************************************************/ +#pragma pack(1) +typedef struct +{ + whd_buffer_queue_ptr_t queue_next; + char bus_header[MAX_BUS_HEADER_SIZE]; +} whd_buffer_header_t; +#pragma pack() + +/* 802.11 Information Element Identification Numbers (as per section 8.4.2.1 of 802.11-2012) */ +typedef enum +{ + DOT11_IE_ID_SSID = 0, + DOT11_IE_ID_SUPPORTED_RATES = 1, + DOT11_IE_ID_FH_PARAMETER_SET = 2, + DOT11_IE_ID_DSSS_PARAMETER_SET = 3, + DOT11_IE_ID_CF_PARAMETER_SET = 4, + DOT11_IE_ID_TIM = 5, + DOT11_IE_ID_IBSS_PARAMETER_SET = 6, + DOT11_IE_ID_COUNTRY = 7, + DOT11_IE_ID_HOPPING_PATTERN_PARAMETERS = 8, + DOT11_IE_ID_HOPPING_PATTERN_TABLE = 9, + DOT11_IE_ID_REQUEST = 10, + DOT11_IE_ID_BSS_LOAD = 11, + DOT11_IE_ID_EDCA_PARAMETER_SET = 12, + DOT11_IE_ID_TSPEC = 13, + DOT11_IE_ID_TCLAS = 14, + DOT11_IE_ID_SCHEDULE = 15, + DOT11_IE_ID_CHALLENGE_TEXT = 16, + /* 17-31 Reserved */ + DOT11_IE_ID_POWER_CONSTRAINT = 32, + DOT11_IE_ID_POWER_CAPABILITY = 33, + DOT11_IE_ID_TPC_REQUEST = 34, + DOT11_IE_ID_TPC_REPORT = 35, + DOT11_IE_ID_SUPPORTED_CHANNELS = 36, + DOT11_IE_ID_CHANNEL_SWITCH_ANNOUNCEMENT = 37, + DOT11_IE_ID_MEASUREMENT_REQUEST = 38, + DOT11_IE_ID_MEASUREMENT_REPORT = 39, + DOT11_IE_ID_QUIET = 40, + DOT11_IE_ID_IBSS_DFS = 41, + DOT11_IE_ID_ERP = 42, + DOT11_IE_ID_TS_DELAY = 43, + DOT11_IE_ID_TCLAS_PROCESSING = 44, + DOT11_IE_ID_HT_CAPABILITIES = 45, + DOT11_IE_ID_QOS_CAPABILITY = 46, + /* 47 Reserved */ + DOT11_IE_ID_RSN = 48, + /* 49 Reserved */ + DOT11_IE_ID_EXTENDED_SUPPORTED_RATES = 50, + DOT11_IE_ID_AP_CHANNEL_REPORT = 51, + DOT11_IE_ID_NEIGHBOR_REPORT = 52, + DOT11_IE_ID_RCPI = 53, + DOT11_IE_ID_MOBILITY_DOMAIN = 54, + DOT11_IE_ID_FAST_BSS_TRANSITION = 55, + DOT11_IE_ID_TIMEOUT_INTERVAL = 56, + DOT11_IE_ID_RIC_DATA = 57, + DOT11_IE_ID_DSE_REGISTERED_LOCATION = 58, + DOT11_IE_ID_SUPPORTED_OPERATING_CLASSES = 59, + DOT11_IE_ID_EXTENDED_CHANNEL_SWITCH_ANNOUNCEMENT = 60, + DOT11_IE_ID_HT_OPERATION = 61, + DOT11_IE_ID_SECONDARY_CHANNEL_OFFSET = 62, + DOT11_IE_ID_BSS_AVERAGE_ACCESS_DELAY = 63, + DOT11_IE_ID_ANTENNA = 64, + DOT11_IE_ID_RSNI = 65, + DOT11_IE_ID_MEASUREMENT_PILOT_TRANSMISSION = 66, + DOT11_IE_ID_BSS_AVAILABLE_ADMISSION_CAPACITY = 67, + DOT11_IE_ID_BSS_AC_ACCESS_DELAY = 68, + DOT11_IE_ID_TIME_ADVERTISEMENT = 69, + DOT11_IE_ID_RM_ENABLED_CAPABILITIES = 70, + DOT11_IE_ID_MULTIPLE_BSSID = 71, + DOT11_IE_ID_20_40_BSS_COEXISTENCE = 72, + DOT11_IE_ID_20_40_BSS_INTOLERANT_CHANNEL_REPORT = 73, + DOT11_IE_ID_OVERLAPPING_BSS_SCAN_PARAMETERS = 74, + DOT11_IE_ID_RIC_DESCRIPTOR = 75, + DOT11_IE_ID_MANAGEMENT_MIC = 76, + DOT11_IE_ID_EVENT_REQUEST = 78, + DOT11_IE_ID_EVENT_REPORT = 79, + DOT11_IE_ID_DIAGNOSTIC_REQUEST = 80, + DOT11_IE_ID_DIAGNOSTIC_REPORT = 81, + DOT11_IE_ID_LOCATION_PARAMETERS = 82, + DOT11_IE_ID_NONTRANSMITTED_BSSID_CAPABILITY = 83, + DOT11_IE_ID_SSID_LIST = 84, + DOT11_IE_ID_MULTIPLE_BSSID_INDEX = 85, + DOT11_IE_ID_FMS_DESCRIPTOR = 86, + DOT11_IE_ID_FMS_REQUEST = 87, + DOT11_IE_ID_FMS_RESPONSE = 88, + DOT11_IE_ID_QOS_TRAFFIC_CAPABILITY = 89, + DOT11_IE_ID_BSS_MAX_IDLE_PERIOD = 90, + DOT11_IE_ID_TFS_REQUEST = 91, + DOT11_IE_ID_TFS_RESPONSE = 92, + DOT11_IE_ID_WNM_SLEEP_MODE = 93, + DOT11_IE_ID_TIM_BROADCAST_REQUEST = 94, + DOT11_IE_ID_TIM_BROADCAST_RESPONSE = 95, + DOT11_IE_ID_COLLOCATED_INTERFERENCE_REPORT = 96, + DOT11_IE_ID_CHANNEL_USAGE = 97, + DOT11_IE_ID_TIME_ZONE = 98, + DOT11_IE_ID_DMS_REQUEST = 99, + DOT11_IE_ID_DMS_RESPONSE = 100, + DOT11_IE_ID_LINK_IDENTIFIER = 101, + DOT11_IE_ID_WAKEUP_SCHEDULE = 102, + /* 103 Reserved */ + DOT11_IE_ID_CHANNEL_SWITCH_TIMING = 104, + DOT11_IE_ID_PTI_CONTROL = 105, + DOT11_IE_ID_TPU_BUFFER_STATUS = 106, + DOT11_IE_ID_INTERWORKING = 107, + DOT11_IE_ID_ADVERTISMENT_PROTOCOL = 108, + DOT11_IE_ID_EXPEDITED_BANDWIDTH_REQUEST = 109, + DOT11_IE_ID_QOS_MAP_SET = 110, + DOT11_IE_ID_ROAMING_CONSORTIUM = 111, + DOT11_IE_ID_EMERGENCY_ALERT_IDENTIFIER = 112, + DOT11_IE_ID_MESH_CONFIGURATION = 113, + DOT11_IE_ID_MESH_ID = 114, + DOT11_IE_ID_MESH_LINK_METRIC_REPORT = 115, + DOT11_IE_ID_CONGESTION_NOTIFICATION = 116, + DOT11_IE_ID_MESH_PEERING_MANAGEMENT = 117, + DOT11_IE_ID_MESH_CHANNEL_SWITCH_PARAMETERS = 118, + DOT11_IE_ID_MESH_AWAKE_WINDOW = 119, + DOT11_IE_ID_BEACON_TIMING = 120, + DOT11_IE_ID_MCCAOP_SETUP_REQUEST = 121, + DOT11_IE_ID_MCCAOP_SETUP_REPLY = 122, + DOT11_IE_ID_MCCAOP_ADVERTISMENT = 123, + DOT11_IE_ID_MCCAOP_TEARDOWN = 124, + DOT11_IE_ID_GANN = 125, + DOT11_IE_ID_RANN = 126, + DOT11_IE_ID_EXTENDED_CAPABILITIES = 127, + /* 128-129 Reserved */ + DOT11_IE_ID_PREQ = 130, + DOT11_IE_ID_PREP = 131, + DOT11_IE_ID_PERR = 132, + /* 133-136 Reserved */ + DOT11_IE_ID_PXU = 137, + DOT11_IE_ID_PXUC = 138, + DOT11_IE_ID_AUTHENTICATED_MESH_PEERING_EXCHANGE = 139, + DOT11_IE_ID_MIC = 140, + DOT11_IE_ID_DESTINATION_URI = 141, + DOT11_IE_ID_U_APSD_COEXISTENCE = 142, + /* 143-173 Reserved */ + DOT11_IE_ID_MCCAOP_ADVERTISMENT_OVERVIEW = 174, + /* 175-220 Reserved */ + DOT11_IE_ID_VENDOR_SPECIFIC = 221, + /* 222-223 Reserved */ + DOT11_IE_ID_RSNX = 244, + /* 225-255 Reserved */ +} dot11_ie_id_t; + +/* 802.11 Status Code */ +typedef enum +{ + DOT11_SC_SUCCESS = 0, + DOT11_SC_FAILURE = 1, + DOT11_SC_TDLS_WAKEUP_SCH_ALT = 2, + DOT11_SC_TDLS_WAKEUP_SCH_REJ = 3, + /* 4 Reserved */ + DOT11_SC_TDLS_SEC_DISABLED = 5, + DOT11_SC_LIFETIME_REJ = 6, + DOT11_SC_NOT_SAME_BSS = 7, + /* 8-9 Reserved */ + DOT11_SC_CAP_MISMATCH = 10, + DOT11_SC_REASSOC_FAIL = 11, + DOT11_SC_ASSOC_FAIL = 12, + DOT11_SC_AUTH_MISMATCH = 13, + DOT11_SC_AUTH_SEQ = 14, + DOT11_SC_AUTH_CHALLENGE_FAIL = 15, + DOT11_SC_AUTH_TIMEOUT = 16, + /* 17-255 Reserved */ +} dot11_sc_t; + +uint32_t whd_wifi_get_iovar_value(whd_interface_t ifp, const char *iovar, uint32_t *value); +uint32_t whd_wifi_set_iovar_buffers(whd_interface_t ifp, const char *iovar, const void **in_buffers, + const uint16_t *lengths, const uint8_t num_buffers); +uint32_t whd_wifi_set_iovar_value(whd_interface_t ifp, const char *iovar, uint32_t value); + +/** Sends an IOVAR command + * + * @param ifp : Pointer to handle instance of whd interface + * @param iovar : IOVAR name + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_iovar_void(whd_interface_t ifp, const char *iovar); + +/** Sends an IOVAR command + * + * @param ifp : Pointer to handle instance of whd interface + * @param iovar : IOVAR name + * @param buffer : Handle for a packet buffer containing the data value to be sent. + * @param buffer_length : Length of out_buffer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_iovar_buffer(whd_interface_t ifp, const char *iovar, void *buffer, uint16_t buffer_length); + +/** Sends an IOVAR command + * + * @param ifp : Pointer to handle instance of whd interface + * @param iovar : IOVAR name + * @param in_buffers : Handle for a packet buffers containing the data value to be sent. + * @param in_buffer_lengths : Length of in_buffers + * @param num_buffers : Number of handle buffers + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_iovar_buffers(whd_interface_t ifp, const char *iovar, const void **in_buffers, + const uint16_t *in_buffer_lengths, const uint8_t num_buffers); + +/** Sends an IOVAR command + * + * @param ifp : Pointer to handle instance of whd interface + * @param iovar : IOVAR name + * @param out_buffer : Pointer to receive the handle for the packet buffer containing the response data value received + * @param out_length : Length of out_buffer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_get_iovar_buffer(whd_interface_t ifp, const char *iovar_name, uint8_t *out_buffer, + uint16_t out_length); + +/** Sends an IOVAR command + * + * @param ifp : Pointer to handle instance of whd interface + * @param iovar : IOVAR name + * @param buffer : Handle for a packet buffer containing the data value to be sent. + * @param buffer_length : Length of out_buffer + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_iovar_buffer(whd_interface_t ifp, const char *iovar, void *buffer, uint16_t buffer_length); + +/** Sends an IOVAR command + * + * @param ifp : Pointer to handle instance of whd interface + * @param iovar : IOVAR name + * @param in_buffers : Handle for a packet buffers containing the data value to be sent. + * @param in_buffer_lengths : Length of in_buffers + * @param num_buffers : Number of handle buffers + * + * @return WHD_SUCCESS or Error code + */ +extern uint32_t whd_wifi_set_iovar_buffers(whd_interface_t ifp, const char *iovar, const void **in_buffers, + const uint16_t *in_buffer_lengths, const uint8_t num_buffers); + +extern uint32_t whd_wifi_set_mac_address(whd_interface_t ifp, whd_mac_t mac); + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef INCLUDED_WHD_TYPES_INT_H_ */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_utils.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_utils.h new file mode 100644 index 00000000..604b0772 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_utils.h @@ -0,0 +1,192 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file WHD utilities + * + * Utilities to help do specialized (not general purpose) WHD specific things + */ +#include "whd_chip.h" +#include "whd_events_int.h" +#include "whd_types_int.h" + +#ifndef INCLUDED_WHD_UTILS_H_ +#define INCLUDED_WHD_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the offset (in bytes) of a member within a structure + */ +#define OFFSET(type, member) ( (uint32_t)&( (type *)0 )->member ) + +/** + * determine size (number of elements) in an array + */ +#define WHD_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]) ) + +/** Searches for a specific WiFi Information Element in a byte array + * + * Traverse a string of 1-byte tag/1-byte length/variable-length value + * triples, returning a pointer to the substring whose first element + * matches tag + * + * @note : This function has been copied directly from the standard Broadcom host driver file wl/exe/wlu.c + * + * + * @param tlv_buf : The byte array containing the Information Elements (IEs) + * @param buflen : The length of the tlv_buf byte array + * @param key : The Information Element tag to search for + * + * @return NULL : if no matching Information Element was found + * Non-Null : Pointer to the start of the matching Information Element + */ + +whd_tlv8_header_t *whd_parse_tlvs(const whd_tlv8_header_t *tlv_buf, uint32_t buflen, dot11_ie_id_t key); + +/** Checks if a WiFi Information Element is a WPA entry + * + * Is this body of this tlvs entry a WPA entry? If + * not update the tlvs buffer pointer/length + * + * @note : This function has been copied directly from the standard Broadcom host driver file wl/exe/wlu.c + * + * @param wpaie : The byte array containing the Information Element (IE) + * @param tlvs : The larger IE array to be updated if not a WPA IE + * @param tlvs_len : The current length of larger IE array + * + * @return WHD_TRUE : if IE matches the WPA OUI (Organizationally Unique Identifier) and its type = 1 + * WHD_FALSE : otherwise + */ +whd_bool_t whd_is_wpa_ie(vendor_specific_ie_header_t *wpaie, whd_tlv8_header_t **tlvs, uint32_t *tlvs_len); + +/** Searches for a specific WiFi Information Element in a byte array + * + * Traverse a string of 1-byte tag/1-byte length/variable-length value + * triples, returning a pointer to the substring whose first element + * matches tag + * + * @note : This function has been copied directly from the standard Broadcom host driver file wl/exe/wlu.c + * + * + * @param tlv_buf : The byte array containing the Information Elements (IEs) + * @param buflen : The length of the tlv_buf byte array + * @param key : The Information Element tag to search for + * + * @return NULL : if no matching Information Element was found + * Non-Null : Pointer to the start of the matching Information Element + */ +whd_tlv8_header_t *whd_parse_dot11_tlvs(const whd_tlv8_header_t *tlv_buf, uint32_t buflen, dot11_ie_id_t key); + +/****************************************************** +* Debug helper functionality +******************************************************/ +#ifdef WPRINT_ENABLE_WHD_DEBUG +const char *whd_event_to_string(whd_event_num_t var); +char *whd_ssid_to_string(uint8_t *value, uint8_t length, char *ssid_buf, uint8_t ssid_buf_len); +const char *whd_status_to_string(whd_event_status_t status); +const char *whd_reason_to_string(whd_event_reason_t reason); +char *whd_ether_ntoa(const uint8_t *ea, char *buf, uint8_t buf_len); +const char *whd_ioctl_to_string(uint32_t ioctl); +#endif /* ifdef WPRINT_ENABLE_WHD_DEBUG */ + +/** + ****************************************************************************** + * Prints partial details of a scan result on a single line + * @param[in] record : A pointer to the whd_scan_result_t record + * + */ +extern void whd_print_scan_result(whd_scan_result_t *record); + +/** + ****************************************************************************** + * Convert a security bitmap to string + * @param[in] security : security of type whd_security_t + * @param[in] out_str : a character array to store output + * @param[in] out_str_len : length of out_str char array + * + */ +extern void whd_convert_security_type_to_string(whd_security_t security, char *out_str, uint16_t out_str_len); + +/*! + ****************************************************************************** + * Convert an IOCTL to a string. + * + * @param[in] cmd The ioct_log value. + * @param[out] ioctl_str The string value after conversion. + * @param[out] ioctl_str_len The string length of the IOCTL string. + * + * @result + */ +void whd_ioctl_info_to_string(uint32_t cmd, char *ioctl_str, uint16_t ioctl_str_len); + +/*! + ****************************************************************************** + * Convert event, status and reason value coming from firmware to string. + * + * @param[in] cmd The event value in numeric form. + * @param[in] flag The status value in numeric form. + * @param[in] reason The reson value in numeric form. + * @param[out] ioctl_str The string representation of event, status and reason. + * @param[out] ioctl_str_len The str_len of ioctl_str. + * + * @result + */ +void whd_event_info_to_string(uint32_t cmd, uint16_t flag, uint32_t reason, char *ioctl_str, uint16_t ioctl_str_len); + +/*! + ****************************************************************************** + * Prints Hexdump and ASCII dump for data passed as argument. + * + * @param[in] data The data which has to be converted into hex and ascii format. + * @param[in] data_len The length of data. + * + * @result + */ +void whd_hexdump(uint8_t *data, uint32_t data_len); + +extern wl_chanspec_t whd_channel_to_wl_band(whd_driver_t whd_driver, uint32_t channel); + +/*! + ****************************************************************************** + * Convert an ipv4 string to a uint32_t. + * + * @param[in] ip4addr : IP address in string format + * @param[in] len : length of the ip address string + * @param[out] dest : IP address format in uint32 + * + * @return + */ +bool whd_str_to_ip(const char *ip4addr, size_t len, void *dest); + +/*! + ****************************************************************************** + * Print binary IPv4 address to a string. + * String must contain enough room for full address, 16 bytes exact. + * @param[in] ip4addr : IPv4 address + * @param[out] p : ipv4 address in string format + * + * @return + */ +uint8_t whd_ip4_to_string(const void *ip4addr, char *p); + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_wifi_p2p.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_wifi_p2p.h new file mode 100644 index 00000000..8057f8a4 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_wifi_p2p.h @@ -0,0 +1,48 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cyabs_rtos.h" /* For semaphores */ +#include "whd.h" + + +#ifndef INCLUDED_WHD_WIFI_P2P_H +#define INCLUDED_WHD_WIFI_P2P_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @cond !ADDTHIS*/ + +/** + * Set whether the p2p GO is up or not + * @param is_up : specify whether the p2p GO is up currently or not + */ +extern void whd_wifi_p2p_set_go_is_up(whd_driver_t whd_driver, whd_bool_t is_up); + +/** + * @return WHD_TRUE if the P2P GO is currently up + */ +extern whd_bool_t whd_wifi_p2p_is_go_up(whd_driver_t whd_driver); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ifndef INCLUDED_WHD_WIFI_P2P_H */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/include/whd_wlioctl.h b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_wlioctl.h new file mode 100644 index 00000000..9382fd0c --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/include/whd_wlioctl.h @@ -0,0 +1,4011 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Custom OID/ioctl definitions for + * 802.11abg Networking Device Driver + */ +#ifndef INCLUDED_WHD_WLIOCTL_H +#define INCLUDED_WHD_WLIOCTL_H + +#ifdef __cplusplus +extern "C" +{ +#endif +/* These are the flags in the BSS Capability Information field as defined in section 7.3.1.4 of IEEE Std 802.11-2007 */ +#define DOT11_CAP_ESS (0x0001) /** Extended service set capability */ +#define DOT11_CAP_IBSS (0x0002) /** Ad-hoc capability (Independent Basic Service Set) */ +#define DOT11_CAP_PRIVACY (0x0010) /** Privacy subfield - indicates data confidentiality is required for all data frames exchanged */ + +#define CH_MAX_2G_CHANNEL (14) /* Max channel in 2G band */ +#define MAX_WFDS_SVC_NAME_LEN (200) /* maximum service_name length */ + +#define MGMT_AUTH_FRAME_DWELL_TIME (100) /* Default Dwell Time(Let FW MSCH have enough left time to piggyback this "mgmt_frame" request within "join" request) */ + +#define ACTION_FRAME_SIZE 1040 +typedef uint16_t chanspec_t; +#define ETHER_ADDR_LEN 6 + +typedef struct ether_addr +{ + uint8_t octet[ETHER_ADDR_LEN]; +} wl_ether_addr_t; +struct wl_ether_header +{ + uint8_t ether_dhost[ETHER_ADDR_LEN]; + uint8_t ether_shost[ETHER_ADDR_LEN]; + uint16_t ether_type; +}; +typedef struct wl_action_frame +{ + wl_ether_addr_t da; + uint16_t len; + uint32_t packetId; + uint8_t data[ACTION_FRAME_SIZE]; +} wl_action_frame_t; + +typedef struct wl_af_params +{ + uint32_t channel; + int32_t dwell_time; + struct ether_addr BSSID; + wl_action_frame_t action_frame; +} wl_af_params_t; + +typedef struct wl_rx_mgmt_data +{ + uint16_t version; + uint16_t channel; + int32_t rssi; + uint32_t mactime; + uint32_t rate; +} wl_rx_mgmt_data_t; + +#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params) + +/* External Auth Code Type(SAE) */ +#define WL_EXTAUTH_START 1 +#define WL_EXTAUTH_ABORT 2 +#define WL_EXTAUTH_FAIL 3 +#define WL_EXTAUTH_SUCCESS 4 + +/* ether types */ +#define ETHER_TYPE_LEN 2 +#define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */ +#define ETHER_TYPE_IP 0x0800 /* IP */ +#define ETHER_TYPE_ARP 0x0806 /* ARP */ +#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ +#define ETHER_TYPE_802_1X 0x888e /* 802.1x */ +#define ETHER_TYPE_WAI 0x88b4 /* WAPI WAI */ +#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */ +#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame) +#define BWL_DEFAULT_PACKING + +#define RWL_ACTION_WIFI_CATEGORY 127 +#define RWL_WIFI_OUI_BYTE1 0x90 +#define RWL_WIFI_OUI_BYTE2 0x4C +#define RWL_WIFI_OUI_BYTE3 0x0F +#define RWL_WIFI_ACTION_FRAME_SIZE sizeof(struct dot11_action_wifi_vendor_specific) +#define RWL_WIFI_DEFAULT 0x00 +#define RWL_WIFI_FIND_MY_PEER 0x09 +#define RWL_WIFI_FOUND_PEER 0x0A +#define RWL_ACTION_WIFI_FRAG_TYPE 0x55 + +typedef struct ssid_info +{ + uint8_t ssid_len; + uint8_t ssid[32]; +} ssid_info_t; +typedef struct cnt_rx +{ + uint32_t cnt_rxundec; + uint32_t cnt_rxframe; +} cnt_rx_t; +#define RWL_REF_MAC_ADDRESS_OFFSET 17 +#define RWL_DUT_MAC_ADDRESS_OFFSET 23 +#define RWL_WIFI_CLIENT_CHANNEL_OFFSET 50 +#define RWL_WIFI_SERVER_CHANNEL_OFFSET 51 +#define WL_BSS_INFO_VERSION 109 +#define MCSSET_LEN 16 + +typedef struct wlc_ssid +{ + uint32_t SSID_len; + uint8_t SSID[32]; +} wlc_ssid_t; +#define WL_BSSTYPE_INFRA 1 +#define WL_BSSTYPE_INDEP 0 +#define WL_BSSTYPE_ANY 2 +#define WL_SCANFLAGS_PASSIVE 0x01 +#define WL_SCANFLAGS_PROHIBITED 0x04 +typedef struct wl_scan_params +{ + wlc_ssid_t ssid; + wl_ether_addr_t bssid; + int8_t bss_type; + int8_t scan_type; + int32_t nprobes; + int32_t active_time; + int32_t passive_time; + int32_t home_time; + int32_t channel_num; + uint16_t channel_list[1]; +} wl_scan_params_t; +#define WL_SCAN_PARAMS_FIXED_SIZE (64) +#define WL_SCAN_PARAMS_COUNT_MASK (0x0000ffff) +#define WL_SCAN_PARAMS_NSSID_SHIFT (16) +#define WL_SCAN_ACTION_START (1) +#define WL_SCAN_ACTION_CONTINUE (2) +#define WL_SCAN_ACTION_ABORT (3) +#define ISCAN_REQ_VERSION (1) +typedef struct wl_iscan_params +{ + uint32_t version; + uint16_t action; + uint16_t scan_duration; + wl_scan_params_t params; +} wl_iscan_params_t; +#define WL_ISCAN_PARAMS_FIXED_SIZE (offsetof(wl_iscan_params_t, params) + sizeof(wlc_ssid_t) ) +typedef struct wl_scan_results +{ + uint32_t buflen; + uint32_t version; + uint32_t count; + wl_bss_info_t bss_info[1]; +} wl_scan_results_t; +#define WL_SCAN_RESULTS_FIXED_SIZE (12) +#define WL_SCAN_RESULTS_SUCCESS (0) +#define WL_SCAN_RESULTS_PARTIAL (1) +#define WL_SCAN_RESULTS_PENDING (2) +#define WL_SCAN_RESULTS_ABORTED (3) +#define WL_SCAN_RESULTS_NO_MEM (4) +#define ESCAN_REQ_VERSION 1 +typedef struct wl_escan_params +{ + uint32_t version; + uint16_t action; + uint16_t sync_id; + wl_scan_params_t params; +} wl_escan_params_t; +#define WL_ESCAN_PARAMS_FIXED_SIZE (offsetof(wl_escan_params_t, params) + sizeof(wlc_ssid_t) ) +typedef struct wl_escan_result +{ + uint32_t buflen; + uint32_t version; + uint16_t sync_id; + uint16_t bss_count; + wl_bss_info_t bss_info[1]; +} wl_escan_result_t; +#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t) ) +typedef struct wl_iscan_results +{ + uint32_t status; + wl_scan_results_t results; +} wl_iscan_results_t; +#define WL_ISCAN_RESULTS_FIXED_SIZE \ + (WL_SCAN_RESULTS_FIXED_SIZE + offsetof(wl_iscan_results_t, results) ) +#define WL_MAXRATES_IN_SET 16 /* max # of rates in a rateset */ +typedef struct wl_rateset +{ + uint32_t count; /* # rates in this set */ + uint8_t rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ +} wl_rateset_t; + +typedef struct wl_rateset_args +{ + uint32_t count; /* # rates in this set */ + uint8_t rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ + uint8_t mcs[WL_MAXRATES_IN_SET]; /* supported mcs index bit map */ +} wl_rateset_args_t; + +#define WL_RSPEC_RATE_MASK 0x000000FF /* rate or HT MCS value */ +#define WL_RSPEC_VHT_MCS_MASK 0x0000000F /* VHT MCS value */ +#define WL_RSPEC_VHT_NSS_MASK 0x000000F0 /* VHT Nss value */ +#define WL_RSPEC_VHT_NSS_SHIFT 4 /* VHT Nss value shift */ +#define WL_RSPEC_TXEXP_MASK 0x00000300 +#define WL_RSPEC_TXEXP_SHIFT 8 +#define WL_RSPEC_BW_MASK 0x00070000 /* bandwidth mask */ +#define WL_RSPEC_BW_SHIFT 16 /* bandwidth shift */ +#define WL_RSPEC_STBC 0x00100000 /* STBC encoding, Nsts = 2 x Nss */ +#define WL_RSPEC_TXBF 0x00200000 /* bit indicates TXBF mode */ +#define WL_RSPEC_LDPC 0x00400000 /* bit indicates adv coding in use */ +#define WL_RSPEC_SGI 0x00800000 /* Short GI mode */ +#define WL_RSPEC_ENCODING_MASK 0x03000000 /* Encoding of Rate/MCS field */ +#define WL_RSPEC_OVERRIDE_RATE 0x40000000 /* bit indicate to override mcs only */ +#define WL_RSPEC_OVERRIDE_MODE 0x80000000 /* bit indicates override both rate & mode */ +#define WL_RSPEC_BW_UNSPECIFIED 0 +#define WL_RSPEC_BW_20MHZ 0x00010000 +#define WL_RSPEC_BW_40MHZ 0x00020000 +#define WL_RSPEC_BW_80MHZ 0x00030000 +#define WL_RSPEC_BW_160MHZ 0x00040000 +#define WL_RSPEC_BW_10MHZ 0x00050000 +#define WL_RSPEC_BW_5MHZ 0x00060000 +#define WL_RSPEC_BW_2P5MHZ 0x00070000 +#define WL_RSPEC_ENCODE_RATE 0x00000000 /* Legacy rate is stored in RSPEC_RATE_MASK */ +#define WL_RSPEC_ENCODE_HT 0x01000000 /* HT MCS is stored in RSPEC_RATE_MASK */ +#define WL_RSPEC_ENCODE_VHT 0x02000000 /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */ + +typedef struct wl_uint32_list +{ + uint32_t count; + uint32_t element[1]; +} wl_uint32_list_t; + +typedef struct wl_join_scan_params +{ + uint8_t scan_type; /* 0 use default, active or passive scan */ + int32_t nprobes; /* -1 use default, number of probes per channel */ + int32_t active_time; /* -1 use default, dwell time per channel for + * active scanning + */ + int32_t passive_time; /* -1 use default, dwell time per channel + * for passive scanning + */ + int32_t home_time; /* -1 use default, dwell time for the home channel + * between channel scans + */ +} wl_join_scan_params_t; + +#define NRATE_MCS_INUSE (0x00000080) +#define NRATE_RATE_MASK (0x0000007f) +#define NRATE_STF_MASK (0x0000ff00) +#define NRATE_STF_SHIFT (8) +#define NRATE_OVERRIDE (0x80000000) +#define NRATE_OVERRIDE_MCS_ONLY (0x40000000) +#define NRATE_SGI_MASK (0x00800000) +#define NRATE_SGI_SHIFT (23) +#define NRATE_LDPC_CODING (0x00400000) +#define NRATE_LDPC_SHIFT (22) +#define NRATE_BCMC_OVERRIDE (0x00200000) +#define NRATE_BCMC_SHIFT (21) +#define NRATE_STF_SISO (0) +#define NRATE_STF_CDD (1) +#define NRATE_STF_STBC (2) +#define NRATE_STF_SDM (3) +#define ANTENNA_NUM_1 (1) +#define ANTENNA_NUM_2 (2) +#define ANTENNA_NUM_3 (3) +#define ANTENNA_NUM_4 (4) +#define ANT_SELCFG_AUTO (0x80) +#define ANT_SELCFG_MASK (0x33) +#define ANT_SELCFG_MAX (4) +#define ANT_SELCFG_TX_UNICAST (0) +#define ANT_SELCFG_RX_UNICAST (1) +#define ANT_SELCFG_TX_DEF (2) +#define ANT_SELCFG_RX_DEF (3) +typedef struct +{ + uint8_t ant_config[ANT_SELCFG_MAX]; + uint8_t num_antcfg; +} wlc_antselcfg_t; +#define HIGHEST_SINGLE_STREAM_MCS (7) +#define WLC_CNTRY_BUF_SZ (4) +typedef struct wl_country +{ + char country_abbrev[WLC_CNTRY_BUF_SZ]; + int32_t rev; + char ccode[WLC_CNTRY_BUF_SZ]; +} wl_country_t; +typedef struct wl_channels_in_country +{ + uint32_t buflen; + uint32_t band; + int8_t country_abbrev[WLC_CNTRY_BUF_SZ]; + uint32_t count; + uint32_t channel[1]; +} wl_channels_in_country_t; +typedef struct wl_country_list +{ + uint32_t buflen; + uint32_t band_set; + uint32_t band; + uint32_t count; + int8_t country_abbrev[1]; +} wl_country_list_t; +#define WL_NUM_RPI_BINS 8 +#define WL_RM_TYPE_BASIC 1 +#define WL_RM_TYPE_CCA 2 +#define WL_RM_TYPE_RPI 3 +#define WL_RM_FLAG_PARALLEL (1 << 0) +#define WL_RM_FLAG_LATE (1 << 1) +#define WL_RM_FLAG_INCAPABLE (1 << 2) +#define WL_RM_FLAG_REFUSED (1 << 3) +typedef struct wl_rm_req_elt +{ + int8_t type; + int8_t flags; + wl_chanspec_t chanspec; + uint32_t token; + uint32_t tsf_h; + uint32_t tsf_l; + uint32_t dur; +} wl_rm_req_elt_t; +typedef struct wl_rm_req +{ + uint32_t token; + uint32_t count; + void *cb; + void *cb_arg; + wl_rm_req_elt_t req[1]; +} wl_rm_req_t; +#define WL_RM_REQ_FIXED_LEN offsetof(wl_rm_req_t, req) +typedef struct wl_rm_rep_elt +{ + int8_t type; + int8_t flags; + wl_chanspec_t chanspec; + uint32_t token; + uint32_t tsf_h; + uint32_t tsf_l; + uint32_t dur; + uint32_t len; + uint8_t data[1]; +} wl_rm_rep_elt_t; +#define WL_RM_REP_ELT_FIXED_LEN 24 +#define WL_RPI_REP_BIN_NUM 8 +typedef struct wl_rm_rpi_rep +{ + uint8_t rpi[WL_RPI_REP_BIN_NUM]; + int8_t rpi_max[WL_RPI_REP_BIN_NUM]; +} wl_rm_rpi_rep_t; +typedef struct wl_rm_rep +{ + uint32_t token; + uint32_t len; + wl_rm_rep_elt_t rep[1]; +} wl_rm_rep_t; +#define WL_RM_REP_FIXED_LEN 8 +#define CRYPTO_ALGO_OFF 0 +#define CRYPTO_ALGO_WEP1 1 +#define CRYPTO_ALGO_TKIP 2 +#define CRYPTO_ALGO_WEP128 3 +#define CRYPTO_ALGO_AES_CCM 4 +#define CRYPTO_ALGO_AES_OCB_MSDU 5 +#define CRYPTO_ALGO_AES_OCB_MPDU 6 +#define CRYPTO_ALGO_NALG 7 +#define WSEC_GEN_MIC_ERROR 0x0001 +#define WSEC_GEN_REPLAY 0x0002 +#define WSEC_GEN_ICV_ERROR 0x0004 +#define WL_SOFT_KEY (1 << 0) +#define WL_PRIMARY_KEY (1 << 1) +#define WL_KF_RES_4 (1 << 4) +#define WL_KF_RES_5 (1 << 5) +#define WL_IBSS_PEER_GROUP_KEY (1 << 6) +#define DOT11_MAX_KEY_SIZE 32 +typedef struct wl_wsec_key +{ + uint32_t index; + uint32_t len; + uint8_t data[DOT11_MAX_KEY_SIZE]; + uint32_t pad_1[18]; + uint32_t algo; + uint32_t flags; + uint32_t pad_2[2]; + int32_t pad_3; + int32_t iv_initialized; + int32_t pad_4; + struct + { + uint32_t hi; + uint16_t lo; + } rxiv; + uint32_t pad_5[2]; + wl_ether_addr_t ea; +} wl_wsec_key_t; +#define WSEC_MIN_PSK_LEN 8 +#define WSEC_MAX_PSK_LEN 64 +#define WSEC_PMK_LEN 32 +#define WSEC_PASSPHRASE (1 << 0) +typedef struct +{ + uint16_t key_len; + uint16_t flags; + uint8_t key[WSEC_MAX_PSK_LEN + 1]; +} wsec_pmk_t; + +#define WSEC_MAX_SAE_PASSWORD_LEN 128 +typedef struct +{ + uint16_t password_len; /* octets in key materials */ + uint8_t password[WSEC_MAX_SAE_PASSWORD_LEN]; /* maximum key len for SAE passphrase */ +} wsec_sae_password_t; + +#define OPEN_AUTH 0x0000 +#define SHARED_AUTH 0x0001 +//#define WEP_ENABLED 0x0001 // moved to whd_types.h +//#define TKIP_ENABLED 0x0002 +//#define AES_ENABLED 0x0004 + +typedef enum +{ + AUTH_ALGO_80211_OPEN = 1, AUTH_ALGO_80211_SHARED_KEY = 2, AUTH_ALGO_WPA = 3, AUTH_ALGO_WPA_PSK = 4, + AUTH_ALGO_WPA_NONE = 5, AUTH_ALGO_RSNA = 6, AUTH_ALGO_RSNA_PSK = 7, +} AUTH_ALGORITHM; + +#define WSEC_SWFLAG 0x0008 +#define CKIP_KP_ENABLED 0x0010 +#define CKIP_MIC_ENABLED 0x0020 +#define SES_OW_ENABLED 0x0040 +#define FIPS_ENABLED 0x0080 +#define SMS4_ENABLED 0x0100 + +#define MFP_NONE 0x0000 +#define MFP_CAPABLE 0x0200 +#define MFP_REQUIRED 0x0400 +#define MFP_SHA256 0x0800 /* a special configuration for STA for WIFI test tool */ + +#define WPA_AUTH_DISABLED 0x0000 +#define WPA_AUTH_NONE 0x0001 +#define WPA_AUTH_UNSPECIFIED 0x0002 +#define WPA_AUTH_PSK 0x0004 +#define WPA_AUTH_CCKM 0x0008 +#define WPA2_AUTH_CCKM 0x0010 +#define WPA2_AUTH_UNSPECIFIED 0x0040 +#define WPA2_AUTH_PSK 0x0080 +#define BRCM_AUTH_PSK 0x0100 +#define BRCM_AUTH_DPT 0x0200 +#define WPA_AUTH_WAPI 0x0400 +#define WPA2_AUTH_MFP 0x1000 /* MFP (11w) in contrast to CCX */ + +#define WPA2_AUTH_1X_SHA256 0x1000 /* 1X with SHA256 key derivation */ +#define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */ +#define WPA2_AUTH_FT 0x4000 /* Fast Transition. */ +#define WPA2_AUTH_PSK_SHA256 0x8000 /* PSK with SHA256 key derivation */ +#define WPA2_AUTH_FILS_SHA256 0x10000 /* FILS with SHA256 key derivation */ +#define WPA2_AUTH_FILS_SHA384 0x20000 /* FILS with SHA384 key derivation */ +#define WPA2_AUTH_IS_FILS(auth) ( (auth) & (WPA2_AUTH_FILS_SHA256 | WPA2_AUTH_FILS_SHA384) ) +#define WPA3_AUTH_SAE_PSK 0x40000 /* SAE authentication with SHA-256 */ +#define WPA3_AUTH_SAE_FBT 0x80000 /* FT authentication over SAE */ +#define WPA3_AUTH_OWE 0x100000 /* OWE */ +#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ + +#define MAXPMKID 16 + +typedef struct _pmkid_cand +{ + wl_ether_addr_t BSSID; + uint8_t preauth; +} pmkid_cand_t; +typedef struct _pmkid_cand_list +{ + uint32_t npmkid_cand; + pmkid_cand_t pmkid_cand[1]; +} pmkid_cand_list_t; +typedef struct wl_led_info +{ + uint32_t index; + uint32_t behavior; + uint8_t activehi; +} wl_led_info_t; +struct wl_dot11_assoc_req +{ + uint16_t capability; + uint16_t listen; +}; +struct wl_dot11_assoc_resp +{ + uint16_t capability; + uint16_t status; + uint16_t aid; +}; +typedef struct wl_assoc_info +{ + uint32_t req_len; + uint32_t resp_len; + uint32_t flags; + struct wl_dot11_assoc_req req; + wl_ether_addr_t reassoc_bssid; + struct wl_dot11_assoc_resp resp; +} wl_assoc_info_t; +#define WLC_ASSOC_REQ_IS_REASSOC 0x01 +typedef struct +{ + uint32_t byteoff; + uint32_t nbytes; + uint16_t buf[1]; +} srom_rw_t; +typedef struct +{ + uint32_t source; + uint32_t byteoff; + uint32_t nbytes; +} cis_rw_t; +#define WLC_CIS_DEFAULT 0 +#define WLC_CIS_SROM 1 +#define WLC_CIS_OTP 2 +typedef struct +{ + uint32_t byteoff; + uint32_t val; + uint32_t size; + uint32_t band; +} rw_reg_t; +#define WL_ATTEN_APP_INPUT_PCL_OFF 0 +#define WL_ATTEN_PCL_ON 1 +#define WL_ATTEN_PCL_OFF 2 +typedef struct +{ + uint16_t auto_ctrl; + uint16_t bb; + uint16_t radio; + uint16_t txctl1; +} atten_t; +struct wme_tx_params_s +{ + uint8_t short_retry; + uint8_t short_fallback; + uint8_t long_retry; + uint8_t long_fallback; + uint16_t max_rate; +}; +typedef struct wme_tx_params_s wme_tx_params_t; +#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT) +#define WL_PWRIDX_PCL_OFF -2 +#define WL_PWRIDX_PCL_ON -1 +#define WL_PWRIDX_LOWER_LIMIT -2 +#define WL_PWRIDX_UPPER_LIMIT 63 +typedef struct +{ + uint32_t val; + wl_ether_addr_t ea; +} scb_val_t; +#define BCM_MAC_STATUS_INDICATION (0x40010200L) +typedef struct +{ + uint16_t ver; + uint16_t len; + uint16_t cap; + uint32_t flags; + uint32_t idle; + wl_ether_addr_t ea; + wl_rateset_t rateset; + uint32_t in; + uint32_t listen_interval_inms; + uint32_t tx_pkts; + uint32_t tx_failures; + uint32_t rx_ucast_pkts; + uint32_t rx_mcast_pkts; + uint32_t tx_rate; + uint32_t rx_rate; +} sta_info_t; +#define WL_OLD_STAINFO_SIZE offsetof(sta_info_t, tx_pkts) +#define WL_STA_VER 2 +#define WL_STA_BRCM 0x1 +#define WL_STA_WME 0x2 +#define WL_STA_ABCAP 0x4 +#define WL_STA_AUTHE 0x8 +#define WL_STA_ASSOC 0x10 +#define WL_STA_AUTHO 0x20 +#define WL_STA_WDS 0x40 +#define WL_STA_WDS_LINKUP 0x80 +#define WL_STA_PS 0x100 +#define WL_STA_APSD_BE 0x200 +#define WL_STA_APSD_BK 0x400 +#define WL_STA_APSD_VI 0x800 +#define WL_STA_APSD_VO 0x1000 +#define WL_STA_N_CAP 0x2000 +#define WL_STA_SCBSTATS 0x4000 +#define WL_WDS_LINKUP WL_STA_WDS_LINKUP +typedef struct channel_info +{ + int32_t hw_channel; + int32_t target_channel; + int32_t scan_channel; +} channel_info_t; +struct mac_list +{ + uint32_t count; + wl_ether_addr_t ea[1]; +}; +typedef struct get_pktcnt +{ + uint32_t rx_good_pkt; + uint32_t rx_bad_pkt; + uint32_t tx_good_pkt; + uint32_t tx_bad_pkt; + uint32_t rx_ocast_good_pkt; +} get_pktcnt_t; +typedef struct wl_ioctl +{ + uint32_t cmd; + void *buf; + uint32_t len; + uint8_t set; + uint32_t used; + uint32_t needed; +} wl_ioctl_t; +typedef struct wlc_rev_info +{ + uint32_t vendorid; + uint32_t deviceid; + uint32_t radiorev; + uint32_t chiprev; + uint32_t corerev; + uint32_t boardid; + uint32_t boardvendor; + uint32_t boardrev; + uint32_t driverrev; + uint32_t ucoderev; + uint32_t bus; + uint32_t chipnum; + uint32_t phytype; + uint32_t phyrev; + uint32_t anarev; +} wlc_rev_info_t; +#define WL_REV_INFO_LEGACY_LENGTH 48 +#define WL_BRAND_MAX 10 +typedef struct wl_instance_info +{ + uint32_t instance; + int8_t brand[WL_BRAND_MAX]; +} wl_instance_info_t; +typedef struct wl_txfifo_sz +{ + uint8_t fifo; + uint8_t size; +} wl_txfifo_sz_t; +#define WLC_IOV_NAME_LEN 30 +typedef struct wlc_iov_trx_s +{ + uint8_t module; + uint8_t type; + int8_t name[WLC_IOV_NAME_LEN]; +} wlc_iov_trx_t; + +/* Event mask ext support */ +typedef enum event_msgs_ext_command +{ + EVENTMSGS_NONE = 0, EVENTMSGS_SET_BIT = 1, EVENTMSGS_RESET_BIT = 2, EVENTMSGS_SET_MASK = 3 +} event_msgs_ext_command_t; + +#define EVENTMSGS_VER 1 + +/* len- for SET it would be mask size from the application to the firmware */ +/* for GET it would be actual firmware mask size */ +/* maxgetsize - is only used for GET. indicate max mask size that the */ +/* application can read from the firmware */ +typedef struct eventmsgs_ext +{ + uint8_t ver; + uint8_t command; + uint8_t len; + uint8_t maxgetsize; + uint8_t mask[1]; +} eventmsgs_ext_t; + +#define IOVAR_STR_BTADDR "bus:btsdiobufaddr" +#define IOVAR_STR_ACTFRAME "actframe" +#define IOVAR_STR_BSS "bss" +#define IOVAR_STR_BSS_RATESET "bss_rateset" +#define IOVAR_STR_CSA "csa" +#define IOVAR_STR_AMPDU_TID "ampdu_tid" +#define IOVAR_STR_APSTA "apsta" +#define IOVAR_STR_ALLMULTI "allmulti" +#define IOVAR_STR_COUNTRY "country" +#define IOVAR_STR_EVENT_MSGS "event_msgs" +#define IOVAR_STR_EVENT_MSGS_EXT "event_msgs_ext" +#define IOVAR_STR_ESCAN "escan" +#define IOVAR_STR_SUP_WPA "sup_wpa" +#define IOVAR_STR_CUR_ETHERADDR "cur_etheraddr" +#define IOVAR_STR_QTXPOWER "qtxpower" +#define IOVAR_STR_MCAST_LIST "mcast_list" +#define IOVAR_STR_PM2_SLEEP_RET "pm2_sleep_ret" +#define IOVAR_STR_PM_LIMIT "pm_limit" +#define IOVAR_STR_LISTEN_INTERVAL_BEACON "bcn_li_bcn" +#define IOVAR_STR_LISTEN_INTERVAL_DTIM "bcn_li_dtim" +#define IOVAR_STR_LISTEN_INTERVAL_ASSOC "assoc_listen" +#define IOVAR_PSPOLL_PERIOD "pspoll_prd" +#define IOVAR_STR_VENDOR_IE "vndr_ie" +#define IOVAR_STR_TX_GLOM "bus:txglom" +#define IOVAR_STR_ACTION_FRAME "actframe" +#define IOVAR_STR_AC_PARAMS_STA "wme_ac_sta" +#define IOVAR_STR_COUNTERS "counters" +#define IOVAR_STR_PKT_FILTER_ADD "pkt_filter_add" +#define IOVAR_STR_PKT_FILTER_DELETE "pkt_filter_delete" +#define IOVAR_STR_PKT_FILTER_ENABLE "pkt_filter_enable" +#define IOVAR_STR_PKT_FILTER_MODE "pkt_filter_mode" +#define IOVAR_STR_PKT_FILTER_LIST "pkt_filter_list" +#define IOVAR_STR_PKT_FILTER_STATS "pkt_filter_stats" +#define IOVAR_STR_PKT_FILTER_CLEAR_STATS "pkt_filter_clear_stats" +#define IOVAR_STR_DUTY_CYCLE_CCK "dutycycle_cck" +#define IOVAR_STR_DUTY_CYCLE_OFDM "dutycycle_ofdm" +#define IOVAR_STR_MKEEP_ALIVE "mkeep_alive" +#define IOVAR_STR_VERSION "ver" +#define IOVAR_STR_SUP_WPA2_EAPVER "sup_wpa2_eapver" +#define IOVAR_STR_ROAM_OFF "roam_off" +#define IOVAR_STR_CLOSEDNET "closednet" +#define IOVAR_STR_P2P_DISC "p2p_disc" +#define IOVAR_STR_P2P_DEV "p2p_dev" +#define IOVAR_STR_P2P_IF "p2p_if" +#define IOVAR_STR_P2P_IFADD "p2p_ifadd" +#define IOVAR_STR_P2P_IFDEL "p2p_ifdel" +#define IOVAR_STR_P2P_IFUPD "p2p_ifupd" +#define IOVAR_STR_P2P_SCAN "p2p_scan" +#define IOVAR_STR_P2P_STATE "p2p_state" +#define IOVAR_STR_P2P_SSID "p2p_ssid" +#define IOVAR_STR_P2P_IP_ADDR "p2p_ip_addr" +#define IOVAR_STR_NRATE "nrate" +#define IOVAR_STR_BGRATE "bg_rate" +#define IOVAR_STR_ARATE "a_rate" +#define IOVAR_STR_NMODE "nmode" +#define IOVAR_STR_MAX_ASSOC "maxassoc" +#define IOVAR_STR_2G_MULTICAST_RATE "2g_mrate" +#define IOVAR_STR_2G_RATE "2g_rate" +#define IOVAR_STR_MPC "mpc" +#define IOVAR_STR_IBSS_JOIN "IBSS_join_only" +#define IOVAR_STR_AMPDU_BA_WINDOW_SIZE "ampdu_ba_wsize" +#define IOVAR_STR_AMPDU_MPDU "ampdu_mpdu" +#define IOVAR_STR_AMPDU_RX "ampdu_rx" +#define IOVAR_STR_AMPDU_RX_FACTOR "ampdu_rx_factor" +#define IOVAR_STR_AMPDU_HOST_REORDER "ampdu_hostreorder" +#define IOVAR_STR_MIMO_BW_CAP "mimo_bw_cap" +#define IOVAR_STR_RMC_ACKREQ "rmc_ackreq" +#define IOVAR_STR_RMC_STATUS "rmc_status" +#define IOVAR_STR_RMC_COUNTS "rmc_stats" +#define IOVAR_STR_RMC_ROLE "rmc_role" +#define IOVAR_STR_HT40_INTOLERANCE "intol40" +#define IOVAR_STR_RAND "rand" +#define IOVAR_STR_SSID "ssid" +#define IOVAR_STR_WSEC "wsec" +#define IOVAR_STR_WPA_AUTH "wpa_auth" +#define IOVAR_STR_INTERFACE_REMOVE "interface_remove" +#define IOVAR_STR_SUP_WPA_TMO "sup_wpa_tmo" +#define IOVAR_STR_JOIN "join" +#define IOVAR_STR_TLV "tlv" +#define IOVAR_STR_NPHY_ANTSEL "nphy_antsel" +#define IOVAR_STR_AVB_TIMESTAMP_ADDR "avb_timestamp_addr" +#define IOVAR_STR_BSS_MAX_ASSOC "bss_maxassoc" +#define IOVAR_STR_RM_REQ "rm_req" +#define IOVAR_STR_RM_REP "rm_rep" +#define IOVAR_STR_PSPRETEND_RETRY_LIMIT "pspretend_retry_limit" +#define IOVAR_STR_PSPRETEND_THRESHOLD "pspretend_threshold" +#define IOVAR_STR_SWDIV_TIMEOUT "swdiv_timeout" +#define IOVAR_STR_RESET_CNTS "reset_cnts" +#define IOVAR_STR_PHYRATE_LOG "phyrate_log" +#define IOVAR_STR_PHYRATE_LOG_SIZE "phyrate_log_size" +#define IOVAR_STR_PHYRATE_LOG_DUMP "phyrate_dump" +#define IOVAR_STR_SCAN_ASSOC_TIME "scan_assoc_time" +#define IOVAR_STR_SCAN_UNASSOC_TIME "scan_unassoc_time" +#define IOVAR_STR_SCAN_PASSIVE_TIME "scan_passive_time" +#define IOVAR_STR_SCAN_HOME_TIME "scan_home_time" +#define IOVAR_STR_SCAN_NPROBES "scan_nprobes" +#define IOVAR_STR_AUTOCOUNTRY "autocountry" +#define IOVAR_STR_CAP "cap" +#define IOVAR_STR_MPDU_PER_AMPDU "ampdu_mpdu" +#define IOVAR_STR_VHT_FEATURES "vht_features" +#define IOVAR_STR_CHANSPEC "chanspec" +#define IOVAR_STR_MGMT_FRAME "mgmt_frame" + +#define IOVAR_STR_WOWL "wowl" +#define IOVAR_STR_WOWL_OS "wowl_os" +#define IOVAR_STR_WOWL_KEEP_ALIVE "wowl_keepalive" +#define IOVAR_STR_WOWL_PATTERN "wowl_pattern" +#define IOVAR_STR_WOWL_PATTERN_CLR "clr" +#define IOVAR_STR_WOWL_PATTERN_ADD "add" +#define IOVAR_STR_WOWL_ARP_HOST_IP "wowl_arp_hostip" +#define IOVAR_STR_ULP_WAIT "ulp_wait" +#define IOVAR_STR_ULP "ulp" + +#define IOVAR_STR_PNO_ON "pfn" +#define IOVAR_STR_PNO_ADD "pfn_add" +#define IOVAR_STR_PNO_SET "pfn_set" +#define IOVAR_STR_PNO_CLEAR "pfnclear" +#define IOVAR_STR_SCAN_CACHE_CLEAR "scancache_clear" +#define MCS_SETLEN 16 + +#define IOVAR_STR_RRM "rrm" +#define IOVAR_STR_RRM_NOISE_REQ "rrm_noise_req" +#define IOVAR_STR_RRM_NBR_REQ "rrm_nbr_req" +#define IOVAR_STR_RRM_LM_REQ "rrm_lm_req" +#define IOVAR_STR_RRM_STAT_REQ "rrm_stat_req" +#define IOVAR_STR_RRM_FRAME_REQ "rrm_frame_req" +#define IOVAR_STR_RRM_CHLOAD_REQ "rrm_chload_req" +#define IOVAR_STR_RRM_BCN_REQ "rrm_bcn_req" +#define IOVAR_STR_RRM_NBR_LIST "rrm_nbr_list" +#define IOVAR_STR_RRM_NBR_ADD "rrm_nbr_add_nbr" +#define IOVAR_STR_RRM_NBR_DEL "rrm_nbr_del_nbr" +#define IOVAR_STR_RRM_BCNREQ_THRTL_WIN "rrm_bcn_req_thrtl_win" +#define IOVAR_STR_RRM_BCNREQ_MAXOFF_TIME "rrm_bcn_req_max_off_chan_time" +#define IOVAR_STR_RRM_BCNREQ_TRFMS_PRD "rrm_bcn_req_traff_meas_per" + +#define IOVAR_STR_WNM "wnm" +#define IOVAR_STR_BSSTRANS_QUERY "wnm_bsstrans_query" +#define IOVAR_STR_BSSTRANS_RESP "wnm_bsstrans_resp" + +#define IOVAR_STR_MESH_ADD_ROUTE "mesh_add_route" +#define IOVAR_STR_MESH_DEL_ROUTE "mesh_del_route" +#define IOVAR_STR_MESH_FIND "mesh_find" +#define IOVAR_STR_MESH_FILTER "mesh_filter" +#define IOVAR_STR_MESH_PEER "mesh_peer" +#define IOVAR_STR_MESH_PEER_STATUS "mesh_peer_status" +#define IOVAR_STR_MESH_DELFILTER "mesh_delfilter" +#define IOVAR_STR_MESH_MAX_PEERS "mesh_max_peers" + +#define IOVAR_STR_FBT_OVER_DS "fbtoverds" +#define IOVAR_STR_FBT_CAPABILITIES "fbt_cap" + +#define IOVAR_STR_MFP "mfp" + +#define IOVAR_STR_OTPRAW "otpraw" +#define IOVAR_NAN "nan" +#define IOVAR_STR_CLMLOAD "clmload" +#define IOVAR_STR_CLMLOAD_STATUS "clmload_status" +#define IOVAR_STR_CLMVER "clmver" +#define IOVAR_STR_MEMUSE "memuse" + +#define IOVAR_STR_LDPC_CAP "ldpc_cap" +#define IOVAR_STR_LDPC_TX "ldpc_tx" +#define IOVAR_STR_SGI_RX "sgi_rx" +#define IOVAR_STR_SGI_TX "sgi_tx" + +#define IOVAR_STR_APIVTW_OVERRIDE "brcmapivtwo" + +#define IOVAR_STR_BWTE_BWTE_GCI_MASK "bwte_gci_mask" +#define IOVAR_STR_BWTE_GCI_SENDMSG "bwte_gci_sendm" +#define IOVAR_STR_WD_DISABLE "wd_disable" +#define IOVAR_STR_DLTRO "dltro" +#define IOVAR_STR_SAE_PASSWORD "sae_password" +#define IOVAR_STR_SAE_PWE_LOOP "sae_max_pwe_loop" +#define IOVAR_STR_PMKID_INFO "pmkid_info" +#define IOVAR_STR_AUTH_STATUS "auth_status" + +#define IOVAR_STR_BTC_LESCAN_PARAMS "btc_lescan_params" + +#define IOVAR_STR_ARP_VERSION "arp_version" +#define IOVAR_STR_ARP_PEERAGE "arp_peerage" +#define IOVAR_STR_ARPOE "arpoe" +#define IOVAR_STR_ARP_OL "arp_ol" +#define IOVAR_STR_ARP_TABLE_CLEAR "arp_table_clear" +#define IOVAR_STR_ARP_HOSTIP "arp_hostip" +#define IOVAR_STR_ARP_HOSTIP_CLEAR "arp_hostip_clear" +#define IOVAR_STR_ARP_STATS "arp_stats" +#define IOVAR_STR_ARP_STATS_CLEAR "arp_stats_clear" +#define IOVAR_STR_TKO "tko" +#define IOVAR_STR_ROAM_TIME_THRESH "roam_time_thresh" + +/* This value derived from the above strings, which appear maxed out in the 20s */ +#define IOVAR_NAME_STR_MAX_SIZE 32 + +#define WLC_IOCTL_MAGIC (0x14e46c77) +#define WLC_IOCTL_VERSION (1) +#define WLC_IOCTL_SMLEN (256) +#define WLC_IOCTL_MEDLEN (1536) +#define WLC_IOCTL_MAXLEN (8192) + +#define WLC_GET_MAGIC ( (uint32_t)0 ) +#define WLC_GET_VERSION ( (uint32_t)1 ) +#define WLC_UP ( (uint32_t)2 ) +#define WLC_DOWN ( (uint32_t)3 ) +#define WLC_GET_LOOP ( (uint32_t)4 ) +#define WLC_SET_LOOP ( (uint32_t)5 ) +#define WLC_DUMP ( (uint32_t)6 ) +#define WLC_GET_MSGLEVEL ( (uint32_t)7 ) +#define WLC_SET_MSGLEVEL ( (uint32_t)8 ) +#define WLC_GET_PROMISC ( (uint32_t)9 ) +#define WLC_SET_PROMISC ( (uint32_t)10 ) +#define WLC_GET_RATE ( (uint32_t)12 ) +#define WLC_GET_INSTANCE ( (uint32_t)14 ) +#define WLC_GET_INFRA ( (uint32_t)19 ) +#define WLC_SET_INFRA ( (uint32_t)20 ) +#define WLC_GET_AUTH ( (uint32_t)21 ) +#define WLC_SET_AUTH ( (uint32_t)22 ) +#define WLC_GET_BSSID ( (uint32_t)23 ) +#define WLC_SET_BSSID ( (uint32_t)24 ) +#define WLC_GET_SSID ( (uint32_t)25 ) +#define WLC_SET_SSID ( (uint32_t)26 ) +#define WLC_RESTART ( (uint32_t)27 ) +#define WLC_GET_CHANNEL ( (uint32_t)29 ) +#define WLC_SET_CHANNEL ( (uint32_t)30 ) +#define WLC_GET_SRL ( (uint32_t)31 ) +#define WLC_SET_SRL ( (uint32_t)32 ) +#define WLC_GET_LRL ( (uint32_t)33 ) +#define WLC_SET_LRL ( (uint32_t)34 ) +#define WLC_GET_PLCPHDR ( (uint32_t)35 ) +#define WLC_SET_PLCPHDR ( (uint32_t)36 ) +#define WLC_GET_RADIO ( (uint32_t)37 ) +#define WLC_SET_RADIO ( (uint32_t)38 ) +#define WLC_GET_PHYTYPE ( (uint32_t)39 ) +#define WLC_DUMP_RATE ( (uint32_t)40 ) +#define WLC_SET_RATE_PARAMS ( (uint32_t)41 ) +#define WLC_GET_KEY ( (uint32_t)44 ) +#define WLC_SET_KEY ( (uint32_t)45 ) +#define WLC_GET_REGULATORY ( (uint32_t)46 ) +#define WLC_SET_REGULATORY ( (uint32_t)47 ) +#define WLC_GET_PASSIVE_SCAN ( (uint32_t)48 ) +#define WLC_SET_PASSIVE_SCAN ( (uint32_t)49 ) +#define WLC_SCAN ( (uint32_t)50 ) +#define WLC_SCAN_RESULTS ( (uint32_t)51 ) +#define WLC_DISASSOC ( (uint32_t)52 ) +#define WLC_REASSOC ( (uint32_t)53 ) +#define WLC_GET_ROAM_TRIGGER ( (uint32_t)54 ) +#define WLC_SET_ROAM_TRIGGER ( (uint32_t)55 ) +#define WLC_GET_ROAM_DELTA ( (uint32_t)56 ) +#define WLC_SET_ROAM_DELTA ( (uint32_t)57 ) +#define WLC_GET_ROAM_SCAN_PERIOD ( (uint32_t)58 ) +#define WLC_SET_ROAM_SCAN_PERIOD ( (uint32_t)59 ) +#define WLC_EVM ( (uint32_t)60 ) +#define WLC_GET_TXANT ( (uint32_t)61 ) +#define WLC_SET_TXANT ( (uint32_t)62 ) +#define WLC_GET_ANTDIV ( (uint32_t)63 ) +#define WLC_SET_ANTDIV ( (uint32_t)64 ) +#define WLC_GET_CLOSED ( (uint32_t)67 ) +#define WLC_SET_CLOSED ( (uint32_t)68 ) +#define WLC_GET_MACLIST ( (uint32_t)69 ) +#define WLC_SET_MACLIST ( (uint32_t)70 ) +#define WLC_GET_RATESET ( (uint32_t)71 ) +#define WLC_SET_RATESET ( (uint32_t)72 ) +#define WLC_LONGTRAIN ( (uint32_t)74 ) +#define WLC_GET_BCNPRD ( (uint32_t)75 ) +#define WLC_SET_BCNPRD ( (uint32_t)76 ) +#define WLC_GET_DTIMPRD ( (uint32_t)77 ) +#define WLC_SET_DTIMPRD ( (uint32_t)78 ) +#define WLC_GET_SROM ( (uint32_t)79 ) +#define WLC_SET_SROM ( (uint32_t)80 ) +#define WLC_GET_WEP_RESTRICT ( (uint32_t)81 ) +#define WLC_SET_WEP_RESTRICT ( (uint32_t)82 ) +#define WLC_GET_COUNTRY ( (uint32_t)83 ) +#define WLC_SET_COUNTRY ( (uint32_t)84 ) +#define WLC_GET_PM ( (uint32_t)85 ) +#define WLC_SET_PM ( (uint32_t)86 ) +#define WLC_GET_WAKE ( (uint32_t)87 ) +#define WLC_SET_WAKE ( (uint32_t)88 ) +#define WLC_GET_FORCELINK ( (uint32_t)90 ) +#define WLC_SET_FORCELINK ( (uint32_t)91 ) +#define WLC_FREQ_ACCURACY ( (uint32_t)92 ) +#define WLC_CARRIER_SUPPRESS ( (uint32_t)93 ) +#define WLC_GET_PHYREG ( (uint32_t)94 ) +#define WLC_SET_PHYREG ( (uint32_t)95 ) +#define WLC_GET_RADIOREG ( (uint32_t)96 ) +#define WLC_SET_RADIOREG ( (uint32_t)97 ) +#define WLC_GET_REVINFO ( (uint32_t)98 ) +#define WLC_GET_UCANTDIV ( (uint32_t)99 ) +#define WLC_SET_UCANTDIV ( (uint32_t)100 ) +#define WLC_R_REG ( (uint32_t)101 ) +#define WLC_W_REG ( (uint32_t)102 ) +#define WLC_GET_MACMODE ( (uint32_t)105 ) +#define WLC_SET_MACMODE ( (uint32_t)106 ) +#define WLC_GET_MONITOR ( (uint32_t)107 ) +#define WLC_SET_MONITOR ( (uint32_t)108 ) +#define WLC_GET_GMODE ( (uint32_t)109 ) +#define WLC_SET_GMODE ( (uint32_t)110 ) +#define WLC_GET_LEGACY_ERP ( (uint32_t)111 ) +#define WLC_SET_LEGACY_ERP ( (uint32_t)112 ) +#define WLC_GET_RX_ANT ( (uint32_t)113 ) +#define WLC_GET_CURR_RATESET ( (uint32_t)114 ) +#define WLC_GET_SCANSUPPRESS ( (uint32_t)115 ) +#define WLC_SET_SCANSUPPRESS ( (uint32_t)116 ) +#define WLC_GET_AP ( (uint32_t)117 ) +#define WLC_SET_AP ( (uint32_t)118 ) +#define WLC_GET_EAP_RESTRICT ( (uint32_t)119 ) +#define WLC_SET_EAP_RESTRICT ( (uint32_t)120 ) +#define WLC_SCB_AUTHORIZE ( (uint32_t)121 ) +#define WLC_SCB_DEAUTHORIZE ( (uint32_t)122 ) +#define WLC_GET_WDSLIST ( (uint32_t)123 ) +#define WLC_SET_WDSLIST ( (uint32_t)124 ) +#define WLC_GET_ATIM ( (uint32_t)125 ) +#define WLC_SET_ATIM ( (uint32_t)126 ) +#define WLC_GET_RSSI ( (uint32_t)127 ) +#define WLC_GET_PHYANTDIV ( (uint32_t)128 ) +#define WLC_SET_PHYANTDIV ( (uint32_t)129 ) +#define WLC_AP_RX_ONLY ( (uint32_t)130 ) +#define WLC_GET_TX_PATH_PWR ( (uint32_t)131 ) +#define WLC_SET_TX_PATH_PWR ( (uint32_t)132 ) +#define WLC_GET_WSEC ( (uint32_t)133 ) +#define WLC_SET_WSEC ( (uint32_t)134 ) +#define WLC_GET_PHY_NOISE ( (uint32_t)135 ) +#define WLC_GET_BSS_INFO ( (uint32_t)136 ) +#define WLC_GET_PKTCNTS ( (uint32_t)137 ) +#define WLC_GET_LAZYWDS ( (uint32_t)138 ) +#define WLC_SET_LAZYWDS ( (uint32_t)139 ) +#define WLC_GET_BANDLIST ( (uint32_t)140 ) +#define WLC_GET_BAND ( (uint32_t)141 ) +#define WLC_SET_BAND ( (uint32_t)142 ) +#define WLC_SCB_DEAUTHENTICATE ( (uint32_t)143 ) +#define WLC_GET_SHORTSLOT ( (uint32_t)144 ) +#define WLC_GET_SHORTSLOT_OVERRIDE ( (uint32_t)145 ) +#define WLC_SET_SHORTSLOT_OVERRIDE ( (uint32_t)146 ) +#define WLC_GET_SHORTSLOT_RESTRICT ( (uint32_t)147 ) +#define WLC_SET_SHORTSLOT_RESTRICT ( (uint32_t)148 ) +#define WLC_GET_GMODE_PROTECTION ( (uint32_t)149 ) +#define WLC_GET_GMODE_PROTECTION_OVERRIDE ( (uint32_t)150 ) +#define WLC_SET_GMODE_PROTECTION_OVERRIDE ( (uint32_t)151 ) +#define WLC_UPGRADE ( (uint32_t)152 ) +#define WLC_GET_IGNORE_BCNS ( (uint32_t)155 ) +#define WLC_SET_IGNORE_BCNS ( (uint32_t)156 ) +#define WLC_GET_SCB_TIMEOUT ( (uint32_t)157 ) +#define WLC_SET_SCB_TIMEOUT ( (uint32_t)158 ) +#define WLC_GET_ASSOCLIST ( (uint32_t)159 ) +#define WLC_GET_CLK ( (uint32_t)160 ) +#define WLC_SET_CLK ( (uint32_t)161 ) +#define WLC_GET_UP ( (uint32_t)162 ) +#define WLC_OUT ( (uint32_t)163 ) +#define WLC_GET_WPA_AUTH ( (uint32_t)164 ) +#define WLC_SET_WPA_AUTH ( (uint32_t)165 ) +#define WLC_GET_UCFLAGS ( (uint32_t)166 ) +#define WLC_SET_UCFLAGS ( (uint32_t)167 ) +#define WLC_GET_PWRIDX ( (uint32_t)168 ) +#define WLC_SET_PWRIDX ( (uint32_t)169 ) +#define WLC_GET_TSSI ( (uint32_t)170 ) +#define WLC_GET_SUP_RATESET_OVERRIDE ( (uint32_t)171 ) +#define WLC_SET_SUP_RATESET_OVERRIDE ( (uint32_t)172 ) +#define WLC_GET_PROTECTION_CONTROL ( (uint32_t)178 ) +#define WLC_SET_PROTECTION_CONTROL ( (uint32_t)179 ) +#define WLC_GET_PHYLIST ( (uint32_t)180 ) +#define WLC_ENCRYPT_STRENGTH ( (uint32_t)181 ) +#define WLC_DECRYPT_STATUS ( (uint32_t)182 ) +#define WLC_GET_KEY_SEQ ( (uint32_t)183 ) +#define WLC_GET_SCAN_CHANNEL_TIME ( (uint32_t)184 ) +#define WLC_SET_SCAN_CHANNEL_TIME ( (uint32_t)185 ) +#define WLC_GET_SCAN_UNASSOC_TIME ( (uint32_t)186 ) +#define WLC_SET_SCAN_UNASSOC_TIME ( (uint32_t)187 ) +#define WLC_GET_SCAN_HOME_TIME ( (uint32_t)188 ) +#define WLC_SET_SCAN_HOME_TIME ( (uint32_t)189 ) +#define WLC_GET_SCAN_NPROBES ( (uint32_t)190 ) +#define WLC_SET_SCAN_NPROBES ( (uint32_t)191 ) +#define WLC_GET_PRB_RESP_TIMEOUT ( (uint32_t)192 ) +#define WLC_SET_PRB_RESP_TIMEOUT ( (uint32_t)193 ) +#define WLC_GET_ATTEN ( (uint32_t)194 ) +#define WLC_SET_ATTEN ( (uint32_t)195 ) +#define WLC_GET_SHMEM ( (uint32_t)196 ) +#define WLC_SET_SHMEM ( (uint32_t)197 ) +#define WLC_SET_WSEC_TEST ( (uint32_t)200 ) +#define WLC_SCB_DEAUTHENTICATE_FOR_REASON ( (uint32_t)201 ) +#define WLC_TKIP_COUNTERMEASURES ( (uint32_t)202 ) +#define WLC_GET_PIOMODE ( (uint32_t)203 ) +#define WLC_SET_PIOMODE ( (uint32_t)204 ) +#define WLC_SET_ASSOC_PREFER ( (uint32_t)205 ) +#define WLC_GET_ASSOC_PREFER ( (uint32_t)206 ) +#define WLC_SET_ROAM_PREFER ( (uint32_t)207 ) +#define WLC_GET_ROAM_PREFER ( (uint32_t)208 ) +#define WLC_SET_LED ( (uint32_t)209 ) +#define WLC_GET_LED ( (uint32_t)210 ) +#define WLC_GET_INTERFERENCE_MODE ( (uint32_t)211 ) +#define WLC_SET_INTERFERENCE_MODE ( (uint32_t)212 ) +#define WLC_GET_CHANNEL_QA ( (uint32_t)213 ) +#define WLC_START_CHANNEL_QA ( (uint32_t)214 ) +#define WLC_GET_CHANNEL_SEL ( (uint32_t)215 ) +#define WLC_START_CHANNEL_SEL ( (uint32_t)216 ) +#define WLC_GET_VALID_CHANNELS ( (uint32_t)217 ) +#define WLC_GET_FAKEFRAG ( (uint32_t)218 ) +#define WLC_SET_FAKEFRAG ( (uint32_t)219 ) +#define WLC_GET_PWROUT_PERCENTAGE ( (uint32_t)220 ) +#define WLC_SET_PWROUT_PERCENTAGE ( (uint32_t)221 ) +#define WLC_SET_BAD_FRAME_PREEMPT ( (uint32_t)222 ) +#define WLC_GET_BAD_FRAME_PREEMPT ( (uint32_t)223 ) +#define WLC_SET_LEAP_LIST ( (uint32_t)224 ) +#define WLC_GET_LEAP_LIST ( (uint32_t)225 ) +#define WLC_GET_CWMIN ( (uint32_t)226 ) +#define WLC_SET_CWMIN ( (uint32_t)227 ) +#define WLC_GET_CWMAX ( (uint32_t)228 ) +#define WLC_SET_CWMAX ( (uint32_t)229 ) +#define WLC_GET_WET ( (uint32_t)230 ) +#define WLC_SET_WET ( (uint32_t)231 ) +#define WLC_GET_PUB ( (uint32_t)232 ) +#define WLC_GET_KEY_PRIMARY ( (uint32_t)235 ) +#define WLC_SET_KEY_PRIMARY ( (uint32_t)236 ) +#define WLC_GET_ACI_ARGS ( (uint32_t)238 ) +#define WLC_SET_ACI_ARGS ( (uint32_t)239 ) +#define WLC_UNSET_CALLBACK ( (uint32_t)240 ) +#define WLC_SET_CALLBACK ( (uint32_t)241 ) +#define WLC_GET_RADAR ( (uint32_t)242 ) +#define WLC_SET_RADAR ( (uint32_t)243 ) +#define WLC_SET_SPECT_MANAGMENT ( (uint32_t)244 ) +#define WLC_GET_SPECT_MANAGMENT ( (uint32_t)245 ) +#define WLC_WDS_GET_REMOTE_HWADDR ( (uint32_t)246 ) +#define WLC_WDS_GET_WPA_SUP ( (uint32_t)247 ) +#define WLC_SET_CS_SCAN_TIMER ( (uint32_t)248 ) +#define WLC_GET_CS_SCAN_TIMER ( (uint32_t)249 ) +#define WLC_MEASURE_REQUEST ( (uint32_t)250 ) +#define WLC_INIT ( (uint32_t)251 ) +#define WLC_SEND_QUIET ( (uint32_t)252 ) +#define WLC_KEEPALIVE ( (uint32_t)253 ) +#define WLC_SEND_PWR_CONSTRAINT ( (uint32_t)254 ) +#define WLC_UPGRADE_STATUS ( (uint32_t)255 ) +#define WLC_CURRENT_PWR ( (uint32_t)256 ) +#define WLC_GET_SCAN_PASSIVE_TIME ( (uint32_t)257 ) +#define WLC_SET_SCAN_PASSIVE_TIME ( (uint32_t)258 ) +#define WLC_LEGACY_LINK_BEHAVIOR ( (uint32_t)259 ) +#define WLC_GET_CHANNELS_IN_COUNTRY ( (uint32_t)260 ) +#define WLC_GET_COUNTRY_LIST ( (uint32_t)261 ) +#define WLC_GET_VAR ( (uint32_t)262 ) +#define WLC_SET_VAR ( (uint32_t)263 ) +#define WLC_NVRAM_GET ( (uint32_t)264 ) +#define WLC_NVRAM_SET ( (uint32_t)265 ) +#define WLC_NVRAM_DUMP ( (uint32_t)266 ) +#define WLC_REBOOT ( (uint32_t)267 ) +#define WLC_SET_WSEC_PMK ( (uint32_t)268 ) +#define WLC_GET_AUTH_MODE ( (uint32_t)269 ) +#define WLC_SET_AUTH_MODE ( (uint32_t)270 ) +#define WLC_GET_WAKEENTRY ( (uint32_t)271 ) +#define WLC_SET_WAKEENTRY ( (uint32_t)272 ) +#define WLC_NDCONFIG_ITEM ( (uint32_t)273 ) +#define WLC_NVOTPW ( (uint32_t)274 ) +#define WLC_OTPW ( (uint32_t)275 ) +#define WLC_IOV_BLOCK_GET ( (uint32_t)276 ) +#define WLC_IOV_MODULES_GET ( (uint32_t)277 ) +#define WLC_SOFT_RESET ( (uint32_t)278 ) +#define WLC_GET_ALLOW_MODE ( (uint32_t)279 ) +#define WLC_SET_ALLOW_MODE ( (uint32_t)280 ) +#define WLC_GET_DESIRED_BSSID ( (uint32_t)281 ) +#define WLC_SET_DESIRED_BSSID ( (uint32_t)282 ) +#define WLC_DISASSOC_MYAP ( (uint32_t)283 ) +#define WLC_GET_NBANDS ( (uint32_t)284 ) +#define WLC_GET_BANDSTATES ( (uint32_t)285 ) +#define WLC_GET_WLC_BSS_INFO ( (uint32_t)286 ) +#define WLC_GET_ASSOC_INFO ( (uint32_t)287 ) +#define WLC_GET_OID_PHY ( (uint32_t)288 ) +#define WLC_SET_OID_PHY ( (uint32_t)289 ) +#define WLC_SET_ASSOC_TIME ( (uint32_t)290 ) +#define WLC_GET_DESIRED_SSID ( (uint32_t)291 ) +#define WLC_GET_CHANSPEC ( (uint32_t)292 ) +#define WLC_GET_ASSOC_STATE ( (uint32_t)293 ) +#define WLC_SET_PHY_STATE ( (uint32_t)294 ) +#define WLC_GET_SCAN_PENDING ( (uint32_t)295 ) +#define WLC_GET_SCANREQ_PENDING ( (uint32_t)296 ) +#define WLC_GET_PREV_ROAM_REASON ( (uint32_t)297 ) +#define WLC_SET_PREV_ROAM_REASON ( (uint32_t)298 ) +#define WLC_GET_BANDSTATES_PI ( (uint32_t)299 ) +#define WLC_GET_PHY_STATE ( (uint32_t)300 ) +#define WLC_GET_BSS_WPA_RSN ( (uint32_t)301 ) +#define WLC_GET_BSS_WPA2_RSN ( (uint32_t)302 ) +#define WLC_GET_BSS_BCN_TS ( (uint32_t)303 ) +#define WLC_GET_INT_DISASSOC ( (uint32_t)304 ) +#define WLC_SET_NUM_PEERS ( (uint32_t)305 ) +#define WLC_GET_NUM_BSS ( (uint32_t)306 ) +#define WLC_GET_WSEC_PMK ( (uint32_t)318 ) +#define WLC_GET_RANDOM_BYTES ( (uint32_t)319 ) +#define WLC_LAST ( (uint32_t)320 ) + +#define EPICTRL_COOKIE 0xABADCEDE +#define CMN_IOCTL_OFF 0x180 +#define WL_OID_BASE 0xFFE41420 +#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE) +#define OID_WL_GET_FORCELINK (WL_OID_BASE + WLC_GET_FORCELINK) +#define OID_WL_SET_FORCELINK (WL_OID_BASE + WLC_SET_FORCELINK) +#define OID_WL_ENCRYPT_STRENGTH (WL_OID_BASE + WLC_ENCRYPT_STRENGTH) +#define OID_WL_DECRYPT_STATUS (WL_OID_BASE + WLC_DECRYPT_STATUS) +#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR) +#define OID_WL_NDCONFIG_ITEM (WL_OID_BASE + WLC_NDCONFIG_ITEM) +#define OID_STA_CHANSPEC (WL_OID_BASE + WLC_GET_CHANSPEC) +#define OID_STA_NBANDS (WL_OID_BASE + WLC_GET_NBANDS) +#define OID_STA_GET_PHY (WL_OID_BASE + WLC_GET_OID_PHY) +#define OID_STA_SET_PHY (WL_OID_BASE + WLC_SET_OID_PHY) +#define OID_STA_ASSOC_TIME (WL_OID_BASE + WLC_SET_ASSOC_TIME) +#define OID_STA_DESIRED_SSID (WL_OID_BASE + WLC_GET_DESIRED_SSID) +#define OID_STA_SET_PHY_STATE (WL_OID_BASE + WLC_SET_PHY_STATE) +#define OID_STA_SCAN_PENDING (WL_OID_BASE + WLC_GET_SCAN_PENDING) +#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING) +#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON) +#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON) +#define OID_STA_GET_PHY_STATE (WL_OID_BASE + WLC_GET_PHY_STATE) +#define OID_STA_INT_DISASSOC (WL_OID_BASE + WLC_GET_INT_DISASSOC) +#define OID_STA_SET_NUM_PEERS (WL_OID_BASE + WLC_SET_NUM_PEERS) +#define OID_STA_GET_NUM_BSS (WL_OID_BASE + WLC_GET_NUM_BSS) +#define WL_DECRYPT_STATUS_SUCCESS 1 +#define WL_DECRYPT_STATUS_FAILURE 2 +#define WL_DECRYPT_STATUS_UNKNOWN 3 +#define WLC_UPGRADE_SUCCESS 0 +#define WLC_UPGRADE_PENDING 1 +typedef struct +{ + int8_t *name; + void *param; +} ndconfig_item_t; +typedef struct _wl_assoc_result +{ + unsigned long associated; + unsigned long NDIS_auth; + unsigned long NDIS_infra; +} wl_assoc_result_t; +#define WL_RADIO_SW_DISABLE (1 << 0) +#define WL_RADIO_HW_DISABLE (1 << 1) +#define WL_RADIO_MPC_DISABLE (1 << 2) +#define WL_RADIO_COUNTRY_DISABLE (1 << 3) +#define WL_TXPWR_OVERRIDE (1U << 31) +#define WL_PHY_PAVARS_LEN (6) +#define WL_DIAG_INTERRUPT (1) +#define WL_DIAG_LOOPBACK (2) +#define WL_DIAG_MEMORY (3) +#define WL_DIAG_LED (4) +#define WL_DIAG_REG (5) +#define WL_DIAG_SROM (6) +#define WL_DIAG_DMA (7) +#define WL_DIAGERR_SUCCESS (0) +#define WL_DIAGERR_FAIL_TO_RUN (1) +#define WL_DIAGERR_NOT_SUPPORTED (2) +#define WL_DIAGERR_INTERRUPT_FAIL (3) +#define WL_DIAGERR_LOOPBACK_FAIL (4) +#define WL_DIAGERR_SROM_FAIL (5) +#define WL_DIAGERR_SROM_BADCRC (6) +#define WL_DIAGERR_REG_FAIL (7) +#define WL_DIAGERR_MEMORY_FAIL (8) +#define WL_DIAGERR_NOMEM (9) +#define WL_DIAGERR_DMA_FAIL (10) +#define WL_DIAGERR_MEMORY_TIMEOUT (11) +#define WL_DIAGERR_MEMORY_BADPATTERN (12) +#define WLC_BAND_AUTO (0) +#define WLC_BAND_5G (1) +#define WLC_BAND_2G (2) +#define WLC_BAND_ALL (3) +#define WL_CHAN_FREQ_RANGE_2G (0) +#define WL_CHAN_FREQ_RANGE_5GL (1) +#define WL_CHAN_FREQ_RANGE_5GM (2) +#define WL_CHAN_FREQ_RANGE_5GH (3) +#define WLC_PHY_TYPE_A (0) +#define WLC_PHY_TYPE_B (1) +#define WLC_PHY_TYPE_G (2) +#define WLC_PHY_TYPE_N (4) +#define WLC_PHY_TYPE_LP (5) +#define WLC_PHY_TYPE_SSN (6) +#define WLC_PHY_TYPE_NULL (0xf) +#define WLC_MACMODE_DISABLED (0) +#define WLC_MACMODE_DENY (1) +#define WLC_MACMODE_ALLOW (2) +#define GMODE_LEGACY_B (0) +#define GMODE_AUTO (1) +#define GMODE_ONLY (2) +#define GMODE_B_DEFERRED (3) +#define GMODE_PERFORMANCE (4) +#define GMODE_LRS (5) +#define GMODE_MAX (6) +#define WLC_PLCP_AUTO (-1) +#define WLC_PLCP_SHORT (0) +#define WLC_PLCP_LONG (1) +#define WLC_PROTECTION_AUTO (-1) +#define WLC_PROTECTION_OFF (0) +#define WLC_PROTECTION_ON (1) +#define WLC_PROTECTION_MMHDR_ONLY (2) +#define WLC_PROTECTION_CTS_ONLY (3) +#define WLC_PROTECTION_CTL_OFF (0) +#define WLC_PROTECTION_CTL_LOCAL (1) +#define WLC_PROTECTION_CTL_OVERLAP (2) +#define WLC_N_PROTECTION_OFF (0) +#define WLC_N_PROTECTION_OPTIONAL (1) +#define WLC_N_PROTECTION_20IN40 (2) +#define WLC_N_PROTECTION_MIXEDMODE (3) +#define WLC_N_PREAMBLE_MIXEDMODE (0) +#define WLC_N_PREAMBLE_GF (1) +#define WLC_N_BW_20ALL (0) +#define WLC_N_BW_40ALL (1) +#define WLC_N_BW_20IN2G_40IN5G (2) +#define WLC_N_TXRX_CHAIN0 (0) +#define WLC_N_TXRX_CHAIN1 (1) +#define WLC_N_SGI_20 (0x01) +#define WLC_N_SGI_40 (0x02) +#define PM_OFF (0) +#define PM_MAX (1) +#define PM_FAST (2) +#define PM_FORCE_OFF (3) +#define INTERFERE_NONE (0) +#define NON_WLAN (1) +#define WLAN_MANUAL (2) +#define WLAN_AUTO (3) +#define AUTO_ACTIVE (1 << 7) +typedef struct wl_aci_args +{ + int32_t enter_aci_thresh; + int32_t exit_aci_thresh; + int32_t usec_spin; + int32_t glitch_delay; + uint16_t nphy_adcpwr_enter_thresh; + uint16_t nphy_adcpwr_exit_thresh; + uint16_t nphy_repeat_ctr; + uint16_t nphy_num_samples; + uint16_t nphy_undetect_window_sz; + uint16_t nphy_b_energy_lo_aci; + uint16_t nphy_b_energy_md_aci; + uint16_t nphy_b_energy_hi_aci; +} wl_aci_args_t; +#define WL_ACI_ARGS_LEGACY_LENGTH 16 +typedef struct +{ + int32_t npulses; + int32_t ncontig; + int32_t min_pw; + int32_t max_pw; + uint16_t thresh0; + uint16_t thresh1; + uint16_t blank; + uint16_t fmdemodcfg; + int32_t npulses_lp; + int32_t min_pw_lp; + int32_t max_pw_lp; + int32_t min_fm_lp; + int32_t max_deltat_lp; + int32_t min_deltat; + int32_t max_deltat; + uint16_t autocorr; + uint16_t st_level_time; + uint16_t t2_min; + uint32_t version; +} wl_radar_args_t; +#define WL_RADAR_ARGS_VERSION 1 +#define WL_RADAR_DETECTOR_OFF 0 +#define WL_RADAR_DETECTOR_ON 1 +#define WL_RADAR_SIMULATED 2 +#define WL_RSSI_ANT_VERSION 1 +#define WL_RSSI_ANT_MAX 4 +typedef struct +{ + uint32_t version; + uint32_t count; + int8_t rssi_ant[WL_RSSI_ANT_MAX]; +} wl_rssi_ant_t; +#define WL_DFS_CACSTATE_IDLE 0 +#define WL_DFS_CACSTATE_PREISM_CAC 1 +#define WL_DFS_CACSTATE_ISM 2 +#define WL_DFS_CACSTATE_CSA 3 +#define WL_DFS_CACSTATE_POSTISM_CAC 4 +#define WL_DFS_CACSTATE_PREISM_OOC 5 +#define WL_DFS_CACSTATE_POSTISM_OOC 6 +#define WL_DFS_CACSTATES 7 +typedef struct +{ + uint32_t state; + uint32_t duration; + wl_chanspec_t chanspec_cleared; + uint16_t pad; +} wl_dfs_status_t; +#define NUM_PWRCTRL_RATES 12 +typedef struct +{ + uint8_t txpwr_band_max[NUM_PWRCTRL_RATES]; + uint8_t txpwr_limit[NUM_PWRCTRL_RATES]; + uint8_t txpwr_local_max; + uint8_t txpwr_local_constraint; + uint8_t txpwr_chan_reg_max; + uint8_t txpwr_target[2][NUM_PWRCTRL_RATES]; + uint8_t txpwr_est_Pout[2]; + uint8_t txpwr_opo[NUM_PWRCTRL_RATES]; + uint8_t txpwr_bphy_cck_max[NUM_PWRCTRL_RATES]; + uint8_t txpwr_bphy_ofdm_max; + uint8_t txpwr_aphy_max[NUM_PWRCTRL_RATES]; + int8_t txpwr_antgain[2]; + uint8_t txpwr_est_Pout_gofdm; +} tx_power_legacy_t; +#define WL_TX_POWER_RATES 45 +#define WL_TX_POWER_CCK_FIRST 0 +#define WL_TX_POWER_CCK_NUM 4 +#define WL_TX_POWER_OFDM_FIRST 4 +#define WL_TX_POWER_OFDM_NUM 8 +#define WL_TX_POWER_MCS_SISO_NUM 8 +#define WL_TX_POWER_MCS20_FIRST 12 +#define WL_TX_POWER_MCS20_NUM 16 +#define WL_TX_POWER_MCS40_FIRST 28 +#define WL_TX_POWER_MCS40_NUM 17 +#define WL_TX_POWER_MCS20SISO_NUM 8 +#define WL_TX_POWER_MCS40_LAST 44 +#define WL_TX_POWER_F_ENABLED 1 +#define WL_TX_POWER_F_HW 2 +#define WL_TX_POWER_F_MIMO 4 +#define WL_TX_POWER_F_SISO 8 +#define WL_TX_POWER_F_40M_CAP 16 + +#define MAX_QTX_POWER 32 +typedef struct +{ + uint32_t flags; + wl_chanspec_t chanspec; + wl_chanspec_t local_chanspec; + uint8_t local_max; + uint8_t local_constraint; + int8_t antgain[2]; + uint8_t rf_cores; + uint8_t est_Pout[4]; + uint8_t est_Pout_cck; + uint8_t user_limit[WL_TX_POWER_RATES]; + uint8_t reg_limit[WL_TX_POWER_RATES]; + uint8_t board_limit[WL_TX_POWER_RATES]; + uint8_t target[WL_TX_POWER_RATES]; +} tx_power_t; +typedef struct tx_inst_power +{ + uint8_t txpwr_est_Pout[2]; + uint8_t txpwr_est_Pout_gofdm; +} tx_inst_power_t; +#define WLC_MEASURE_TPC 1 +#define WLC_MEASURE_CHANNEL_BASIC 2 +#define WLC_MEASURE_CHANNEL_CCA 3 +#define WLC_MEASURE_CHANNEL_RPI 4 +#define SPECT_MNGMT_OFF 0 +#define SPECT_MNGMT_LOOSE_11H 1 +#define SPECT_MNGMT_STRICT_11H 2 +#define SPECT_MNGMT_STRICT_11D 3 +#define SPECT_MNGMT_LOOSE_11H_D 4 +#define WL_CHAN_VALID_HW (1 << 0) +#define WL_CHAN_VALID_SW (1 << 1) +#define WL_CHAN_BAND_5G (1 << 2) +#define WL_CHAN_RADAR (1 << 3) +#define WL_CHAN_INACTIVE (1 << 4) +#define WL_CHAN_PASSIVE (1 << 5) +#define WL_CHAN_RESTRICTED (1 << 6) +#define WL_BTC_DISABLE 0 +#define WL_BTC_ENABLE (1 << 0) +#define WL_BTC_PREMPT (1 << 1) +#define WL_BTC_PARTIAL (1 << 2) +#define WL_BTC_DEFAULT (1 << 3) +#define WL_BTC_HYBRID (WL_BTC_ENABLE | WL_BTC_PARTIAL) +#define WL_INF_BTC_DISABLE 0 +#define WL_INF_BTC_ENABLE 1 +#define WL_INF_BTC_AUTO 3 +#define WL_BTC_DEFWIRE 0 +#define WL_BTC_2WIRE 2 +#define WL_BTC_3WIRE 3 +#define WL_BTC_4WIRE 4 +#define WL_BTC_FLAG_PREMPT (1 << 0) +#define WL_BTC_FLAG_BT_DEF (1 << 1) +#define WL_BTC_FLAG_ACTIVE_PROT (1 << 2) +#define WL_BTC_FLAG_SIM_RSP (1 << 3) +#define WL_BTC_FLAG_PS_PROTECT (1 << 4) +#define WL_BTC_FLAG_SIM_TX_LP (1 << 5) +#define WL_BTC_FLAG_ECI (1 << 6) +#define WL_ERROR_VAL 0x00000001 +#define WL_TRACE_VAL 0x00000002 +#define WL_PRHDRS_VAL 0x00000004 +#define WL_PRPKT_VAL 0x00000008 +#define WL_INFORM_VAL 0x00000010 +#define WL_TMP_VAL 0x00000020 +#define WL_OID_VAL 0x00000040 +#define WL_RATE_VAL 0x00000080 +#define WL_ASSOC_VAL 0x00000100 +#define WL_PRUSR_VAL 0x00000200 +#define WL_PS_VAL 0x00000400 +#define WL_TXPWR_VAL 0x00000800 +#define WL_PORT_VAL 0x00001000 +#define WL_DUAL_VAL 0x00002000 +#define WL_WSEC_VAL 0x00004000 +#define WL_WSEC_DUMP_VAL 0x00008000 +#define WL_LOG_VAL 0x00010000 +#define WL_NRSSI_VAL 0x00020000 +#define WL_LOFT_VAL 0x00040000 +#define WL_REGULATORY_VAL 0x00080000 +#define WL_PHYCAL_VAL 0x00100000 +#define WL_RADAR_VAL 0x00200000 +#define WL_MPC_VAL 0x00400000 +#define WL_APSTA_VAL 0x00800000 +#define WL_DFS_VAL 0x01000000 +#define WL_BA_VAL 0x02000000 +#define WL_NITRO_VAL 0x04000000 +#define WL_MBSS_VAL 0x04000000 +#define WL_CAC_VAL 0x08000000 +#define WL_AMSDU_VAL 0x10000000 +#define WL_AMPDU_VAL 0x20000000 +#define WL_FFPLD_VAL 0x40000000 +#define WL_NIN_VAL 0x80000000 +#define WL_DPT_VAL 0x00000001 +#define WL_SCAN_VAL 0x00000002 +#define WL_WOWL_VAL 0x00000004 +#define WL_COEX_VAL 0x00000008 +#define WL_RTDC_VAL 0x00000010 +#define WL_BTA_VAL 0x00000040 +#define WL_LED_NUMGPIO 16 +#define WL_LED_OFF 0 +#define WL_LED_ON 1 +#define WL_LED_ACTIVITY 2 +#define WL_LED_RADIO 3 +#define WL_LED_ARADIO 4 +#define WL_LED_BRADIO 5 +#define WL_LED_BGMODE 6 +#define WL_LED_WI1 7 +#define WL_LED_WI2 8 +#define WL_LED_WI3 9 +#define WL_LED_ASSOC 10 +#define WL_LED_INACTIVE 11 +#define WL_LED_ASSOCACT 12 +#define WL_LED_NUMBEHAVIOR 13 +#define WL_LED_BEH_MASK 0x7f +#define WL_LED_AL_MASK 0x80 +#define WL_NUMCHANNELS 64 +#define WL_NUMCHANSPECS 100 +#define WL_WDS_WPA_ROLE_AUTH 0 +#define WL_WDS_WPA_ROLE_SUP 1 +#define WL_WDS_WPA_ROLE_AUTO 255 +#define WL_EVENTING_MASK_LEN 16 + +#define VNDR_IE_CMD_LEN 4 +#define VNDR_IE_BEACON_FLAG 0x1 +#define VNDR_IE_PRBRSP_FLAG 0x2 +#define VNDR_IE_ASSOCRSP_FLAG 0x4 +#define VNDR_IE_AUTHRSP_FLAG 0x8 +#define VNDR_IE_PRBREQ_FLAG 0x10 +#define VNDR_IE_ASSOCREQ_FLAG 0x20 +#define VNDR_IE_CUSTOM_FLAG 0x100 +#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32_t) ) +struct wl_vndr_ie +{ + uint8_t id; + uint8_t len; + uint8_t oui[3]; + uint8_t data[1]; +}; +typedef struct wl_vndr_ie wl_vndr_ie_t; +typedef struct +{ + uint32_t pktflag; + wl_vndr_ie_t vndr_ie_data; +} vndr_ie_info_t; +typedef struct +{ + int32_t iecount; + vndr_ie_info_t vndr_ie_list[1]; +} vndr_ie_buf_t; +typedef struct +{ + int8_t cmd[VNDR_IE_CMD_LEN]; + vndr_ie_buf_t vndr_ie_buffer; +} vndr_ie_setbuf_t; +#define WL_JOIN_PREF_RSSI 1 +#define WL_JOIN_PREF_WPA 2 +#define WL_JOIN_PREF_BAND 3 +#define WLJP_BAND_ASSOC_PREF 255 +#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00" +struct tsinfo_arg +{ + uint8_t octets[3]; +}; +#define NREINITREASONCOUNT 8 +/* XXX NREINITREASONCOUNT is 8 in other branches. + * Any change to this will break wl tool compatibility with other branches + * #define NREINITREASONCOUNT WL_REINIT_RC_LAST + */ + +#define NFIFO 6 +#define WL_CNT_T_VERSION 6 +#define WL_CNT_EXT_T_VERSION 1 +#define WL_PHYRATE_LOG_SIZE 1200 +typedef struct +{ + uint16_t version; /**< see definition of WL_CNT_T_VERSION */ + uint16_t datalen; /**< length of data including all paddings. */ + uint8_t data[1]; /**< variable length payload: + * 1 or more bcm_xtlv_t type of tuples. + * each tuple is padded to multiple of 4 bytes. + * 'datalen' field of this structure includes all paddings. + */ +} wl_cnt_info_t; +/** wlc layer counters */ +typedef struct +{ + /* transmit stat counters */ + uint32_t txframe; /**< tx data frames */ + uint32_t txbyte; /**< tx data bytes */ + uint32_t txretrans; /**< tx mac retransmits */ + uint32_t txerror; /**< tx data errors (derived: sum of others) */ + uint32_t txctl; /**< tx management frames */ + uint32_t txprshort; /**< tx short preamble frames */ + uint32_t txserr; /**< tx status errors */ + uint32_t txnobuf; /**< tx out of buffers errors */ + uint32_t txnoassoc; /**< tx discard because we're not associated */ + uint32_t txrunt; /**< tx runt frames */ + uint32_t txchit; /**< tx header cache hit (fastpath) */ + uint32_t txcmiss; /**< tx header cache miss (slowpath) */ + + /* transmit chip error counters */ + uint32_t txuflo; /**< tx fifo underflows */ + uint32_t txphyerr; /**< tx phy errors (indicated in tx status) */ + uint32_t txphycrs; /**< PR8861/8963 counter */ + + /* receive stat counters */ + uint32_t rxframe; /**< rx data frames */ + uint32_t rxbyte; /**< rx data bytes */ + uint32_t rxerror; /**< rx data errors (derived: sum of others) */ + uint32_t rxctl; /**< rx management frames */ + uint32_t rxnobuf; /**< rx out of buffers errors */ + uint32_t rxnondata; /**< rx non data frames in the data channel errors */ + uint32_t rxbadds; /**< rx bad DS errors */ + uint32_t rxbadcm; /**< rx bad control or management frames */ + uint32_t rxfragerr; /**< rx fragmentation errors */ + uint32_t rxrunt; /**< rx runt frames */ + uint32_t rxgiant; /**< rx giant frames */ + uint32_t rxnoscb; /**< rx no scb error */ + uint32_t rxbadproto; /**< rx invalid frames */ + uint32_t rxbadsrcmac; /**< rx frames with Invalid Src Mac */ + uint32_t rxbadda; /**< rx frames tossed for invalid da */ + uint32_t rxfilter; /**< rx frames filtered out */ + + /* receive chip error counters */ + uint32_t rxoflo; /**< rx fifo overflow errors */ + uint32_t rxuflo[NFIFO]; /**< rx dma descriptor underflow errors */ + + uint32_t d11cnt_txrts_off; /**< d11cnt txrts value when reset d11cnt */ + uint32_t d11cnt_rxcrc_off; /**< d11cnt rxcrc value when reset d11cnt */ + uint32_t d11cnt_txnocts_off; /**< d11cnt txnocts value when reset d11cnt */ + + /* misc counters */ + uint32_t dmade; /**< tx/rx dma descriptor errors */ + uint32_t dmada; /**< tx/rx dma data errors */ + uint32_t dmape; /**< tx/rx dma descriptor protocol errors */ + uint32_t reset; /**< reset count */ + uint32_t tbtt; /**< cnts the TBTT int's */ + uint32_t txdmawar; /**< # occurrences of PR15420 workaround */ + uint32_t pkt_callback_reg_fail; /**< callbacks register failure */ + + /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ + uint32_t txfrag; /**< dot11TransmittedFragmentCount */ + uint32_t txmulti; /**< dot11MulticastTransmittedFrameCount */ + uint32_t txfail; /**< dot11FailedCount */ + uint32_t txretry; /**< dot11RetryCount */ + uint32_t txretrie; /**< dot11MultipleRetryCount */ + uint32_t rxdup; /**< dot11FrameduplicateCount */ + uint32_t txrts; /**< dot11RTSSuccessCount */ + uint32_t txnocts; /**< dot11RTSFailureCount */ + uint32_t txnoack; /**< dot11ACKFailureCount */ + uint32_t rxfrag; /**< dot11ReceivedFragmentCount */ + uint32_t rxmulti; /**< dot11MulticastReceivedFrameCount */ + uint32_t rxcrc; /**< dot11FCSErrorCount */ + uint32_t txfrmsnt; /**< dot11TransmittedFrameCount (bogus MIB?) */ + uint32_t rxundec; /**< dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill; /**< TKIPLocalMICFailures */ + uint32_t tkipcntrmsr; /**< TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay; /**< TKIPReplays */ + uint32_t ccmpfmterr; /**< CCMPFormatErrors */ + uint32_t ccmpreplay; /**< CCMPReplays */ + uint32_t ccmpundec; /**< CCMPDecryptErrors */ + uint32_t fourwayfail; /**< FourWayHandshakeFailures */ + uint32_t wepundec; /**< dot11WEPUndecryptableCount */ + uint32_t wepicverr; /**< dot11WEPICVErrorCount */ + uint32_t decsuccess; /**< DecryptSuccessCount */ + uint32_t tkipicverr; /**< TKIPICVErrorCount */ + uint32_t wepexcluded; /**< dot11WEPExcludedCount */ + + uint32_t txchanrej; /**< Tx frames suppressed due to channel rejection */ + uint32_t psmwds; /**< Count PSM watchdogs */ + uint32_t phywatchdog; /**< Count Phy watchdogs (triggered by ucode) */ + + /* MBSS counters, AP only */ + uint32_t prq_entries_handled; /**< PRQ entries read in */ + uint32_t prq_undirected_entries; /**< which were bcast bss & ssid */ + uint32_t prq_bad_entries; /**< which could not be translated to info */ + uint32_t atim_suppress_count; /**< TX suppressions on ATIM fifo */ + uint32_t bcn_template_not_ready; /**< Template marked in use on send bcn ... */ + uint32_t bcn_template_not_ready_done; /**< ...but "DMA done" interrupt rcvd */ + uint32_t late_tbtt_dpc; /**< TBTT DPC did not happen in time */ + + /* per-rate receive stat counters */ + uint32_t rx1mbps; /**< packets rx at 1Mbps */ + uint32_t rx2mbps; /**< packets rx at 2Mbps */ + uint32_t rx5mbps5; /**< packets rx at 5.5Mbps */ + uint32_t rx6mbps; /**< packets rx at 6Mbps */ + uint32_t rx9mbps; /**< packets rx at 9Mbps */ + uint32_t rx11mbps; /**< packets rx at 11Mbps */ + uint32_t rx12mbps; /**< packets rx at 12Mbps */ + uint32_t rx18mbps; /**< packets rx at 18Mbps */ + uint32_t rx24mbps; /**< packets rx at 24Mbps */ + uint32_t rx36mbps; /**< packets rx at 36Mbps */ + uint32_t rx48mbps; /**< packets rx at 48Mbps */ + uint32_t rx54mbps; /**< packets rx at 54Mbps */ + uint32_t rx108mbps; /**< packets rx at 108mbps */ + uint32_t rx162mbps; /**< packets rx at 162mbps */ + uint32_t rx216mbps; /**< packets rx at 216 mbps */ + uint32_t rx270mbps; /**< packets rx at 270 mbps */ + uint32_t rx324mbps; /**< packets rx at 324 mbps */ + uint32_t rx378mbps; /**< packets rx at 378 mbps */ + uint32_t rx432mbps; /**< packets rx at 432 mbps */ + uint32_t rx486mbps; /**< packets rx at 486 mbps */ + uint32_t rx540mbps; /**< packets rx at 540 mbps */ + + uint32_t rfdisable; /**< count of radio disables */ + + uint32_t txexptime; /**< Tx frames suppressed due to timer expiration */ + + uint32_t txmpdu_sgi; /**< count for sgi transmit */ + uint32_t rxmpdu_sgi; /**< count for sgi received */ + uint32_t txmpdu_stbc; /**< count for stbc transmit */ + uint32_t rxmpdu_stbc; /**< count for stbc received */ + + uint32_t rxundec_mcst; /**< dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill_mcst; /**< TKIPLocalMICFailures */ + uint32_t tkipcntrmsr_mcst; /**< TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay_mcst; /**< TKIPReplays */ + uint32_t ccmpfmterr_mcst; /**< CCMPFormatErrors */ + uint32_t ccmpreplay_mcst; /**< CCMPReplays */ + uint32_t ccmpundec_mcst; /**< CCMPDecryptErrors */ + uint32_t fourwayfail_mcst; /**< FourWayHandshakeFailures */ + uint32_t wepundec_mcst; /**< dot11WEPUndecryptableCount */ + uint32_t wepicverr_mcst; /**< dot11WEPICVErrorCount */ + uint32_t decsuccess_mcst; /**< DecryptSuccessCount */ + uint32_t tkipicverr_mcst; /**< TKIPICVErrorCount */ + uint32_t wepexcluded_mcst; /**< dot11WEPExcludedCount */ + + uint32_t dma_hang; /**< count for dma hang */ + uint32_t reinit; /**< count for reinit */ + + uint32_t pstatxucast; /**< count of ucast frames xmitted on all psta assoc */ + uint32_t pstatxnoassoc; /**< count of txnoassoc frames xmitted on all psta assoc */ + uint32_t pstarxucast; /**< count of ucast frames received on all psta assoc */ + uint32_t pstarxbcmc; /**< count of bcmc frames received on all psta */ + uint32_t pstatxbcmc; /**< count of bcmc frames transmitted on all psta */ + + uint32_t cso_passthrough; /**< hw cso required but passthrough */ + uint32_t cso_normal; /**< hw cso hdr for normal process */ + uint32_t chained; /**< number of frames chained */ + uint32_t chainedsz1; /**< number of chain size 1 frames */ + uint32_t unchained; /**< number of frames not chained */ + uint32_t maxchainsz; /**< max chain size so far */ + uint32_t currchainsz; /**< current chain size */ + uint32_t pciereset; /**< Secondary Bus Reset issued by driver */ + uint32_t cfgrestore; /**< configspace restore by driver */ + uint32_t reinitreason[NREINITREASONCOUNT]; /**< reinitreason counters; 0: Unknown reason */ + uint32_t rxrtry; + uint32_t rxmpdu_mu; /**< Number of MU MPDUs received */ + + /* detailed control/management frames */ + uint32_t txbar; /**< Number of TX BAR */ + uint32_t rxbar; /**< Number of RX BAR */ + uint32_t txpspoll; /**< Number of TX PS-poll */ + uint32_t rxpspoll; /**< Number of RX PS-poll */ + uint32_t txnull; /**< Number of TX NULL_DATA */ + uint32_t rxnull; /**< Number of RX NULL_DATA */ + uint32_t txqosnull; /**< Number of TX NULL_QoSDATA */ + uint32_t rxqosnull; /**< Number of RX NULL_QoSDATA */ + uint32_t txassocreq; /**< Number of TX ASSOC request */ + uint32_t rxassocreq; /**< Number of RX ASSOC request */ + uint32_t txreassocreq; /**< Number of TX REASSOC request */ + uint32_t rxreassocreq; /**< Number of RX REASSOC request */ + uint32_t txdisassoc; /**< Number of TX DISASSOC */ + uint32_t rxdisassoc; /**< Number of RX DISASSOC */ + uint32_t txassocrsp; /**< Number of TX ASSOC response */ + uint32_t rxassocrsp; /**< Number of RX ASSOC response */ + uint32_t txreassocrsp; /**< Number of TX REASSOC response */ + uint32_t rxreassocrsp; /**< Number of RX REASSOC response */ + uint32_t txauth; /**< Number of TX AUTH */ + uint32_t rxauth; /**< Number of RX AUTH */ + uint32_t txdeauth; /**< Number of TX DEAUTH */ + uint32_t rxdeauth; /**< Number of RX DEAUTH */ + uint32_t txprobereq; /**< Number of TX probe request */ + uint32_t rxprobereq; /**< Number of RX probe request */ + uint32_t txprobersp; /**< Number of TX probe response */ + uint32_t rxprobersp; /**< Number of RX probe response */ + uint32_t txaction; /**< Number of TX action frame */ + uint32_t rxaction; /**< Number of RX action frame */ + uint32_t ampdu_wds; /**< Number of AMPDU watchdogs */ + uint32_t txlost; /**< Number of lost packets reported in txs */ + uint32_t txdatamcast; /**< Number of TX multicast data packets */ + uint32_t txdatabcast; /**< Number of TX broadcast data packets */ + uint32_t psmxwds; /**< Number of PSMx watchdogs */ + uint32_t rxback; + uint32_t txback; + uint32_t p2p_tbtt; /**< Number of P2P TBTT Events */ + uint32_t p2p_tbtt_miss; /**< Number of P2P TBTT Events Miss */ + uint32_t txqueue_start; + uint32_t txqueue_end; + uint32_t txbcast; /* Broadcast TransmittedFrameCount */ + uint32_t txdropped; /* tx dropped pkts */ + uint32_t rxbcast; /* BroadcastReceivedFrameCount */ + uint32_t rxdropped; /* rx dropped pkts (derived: sum of others) */ + /* XXX: Do not remove or rename inthe middle of this struct. + * All counter variables have to be of uint32_t. + * Please follow the instruction in + * http://hwnbu-twiki.sj.broadcom.com/bin/view/Mwgroup/WlCounters#Counter_Edition + */ +} wl_cnt_ver_30_t; +typedef struct +{ + uint16_t version; /* see definition of WL_CNT_T_VERSION */ + uint16_t length; /* length of entire structure */ + + /* transmit stat counters */ + uint32_t txframe; /* tx data frames */ + uint32_t txbyte; /* tx data bytes */ + uint32_t txretrans; /* tx mac retransmits */ + uint32_t txerror; /* tx data errors (derived: sum of others) */ + uint32_t txctl; /* tx management frames */ + uint32_t txprshort; /* tx short preamble frames */ + uint32_t txserr; /* tx status errors */ + uint32_t txnobuf; /* tx out of buffers errors */ + uint32_t txnoassoc; /* tx discard because we're not associated */ + uint32_t txrunt; /* tx runt frames */ + uint32_t txchit; /* tx header cache hit (fastpath) */ + uint32_t txcmiss; /* tx header cache miss (slowpath) */ + + /* transmit chip error counters */ + uint32_t txuflo; /* tx fifo underflows */ + uint32_t txphyerr; /* tx phy errors (indicated in tx status) */ + uint32_t txphycrs; /* PR8861/8963 counter */ + + /* receive stat counters */ + uint32_t rxframe; /* rx data frames */ + uint32_t rxbyte; /* rx data bytes */ + uint32_t rxerror; /* rx data errors (derived: sum of others) */ + uint32_t rxctl; /* rx management frames */ + uint32_t rxnobuf; /* rx out of buffers errors */ + uint32_t rxnondata; /* rx non data frames in the data channel errors */ + uint32_t rxbadds; /* rx bad DS errors */ + uint32_t rxbadcm; /* rx bad control or management frames */ + uint32_t rxfragerr; /* rx fragmentation errors */ + uint32_t rxrunt; /* rx runt frames */ + uint32_t rxgiant; /* rx giant frames */ + uint32_t rxnoscb; /* rx no scb error */ + uint32_t rxbadproto; /* rx invalid frames */ + uint32_t rxbadsrcmac; /* rx frames with Invalid Src Mac */ + uint32_t rxbadda; /* rx frames tossed for invalid da */ + uint32_t rxfilter; /* rx frames filtered out */ + + /* receive chip error counters */ + uint32_t rxoflo; /* rx fifo overflow errors */ + uint32_t rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ + + uint32_t d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ + uint32_t d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ + uint32_t d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ + + /* misc counters */ + uint32_t dmade; /* tx/rx dma descriptor errors */ + uint32_t dmada; /* tx/rx dma data errors */ + uint32_t dmape; /* tx/rx dma descriptor protocol errors */ + uint32_t reset; /* reset count */ + uint32_t tbtt; /* cnts the TBTT int's */ + uint32_t txdmawar; /* # occurrences of PR15420 workaround */ + uint32_t pkt_callback_reg_fail; /* callbacks register failure */ + + /* MAC counters: 32-bit version of d11.h's macstat_t */ + uint32_t txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, + * Control Management (includes retransmissions) + */ + uint32_t txrtsfrm; /* number of RTS sent out by the MAC */ + uint32_t txctsfrm; /* number of CTS sent out by the MAC */ + uint32_t txackfrm; /* number of ACK frames sent out */ + uint32_t txdnlfrm; /* Not used */ + uint32_t txbcnfrm; /* beacons transmitted */ + uint32_t txfunfl[8]; /* per-fifo tx underflows */ + uint32_t txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS + * or BCN) + */ + uint32_t txphyerror; /* Transmit phy error, type of error is reported in tx-status for + * driver enqueued frames + */ + uint32_t rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ + uint32_t rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ + uint32_t rxinvmachdr; /* Either the protocol version != 0 or frame type not + * data/control/management + */ + uint32_t rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ + uint32_t rxbadplcp; /* parity check of the PLCP header failed */ + uint32_t rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ + uint32_t rxstrt; /* Number of received frames with a good PLCP + * (i.e. passing parity check) + */ + uint32_t rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ + uint32_t rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ + uint32_t rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ + uint32_t rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ + uint32_t rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ + uint32_t rxackucast; /* number of ucast ACKS received (good FCS) */ + uint32_t rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ + uint32_t rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ + uint32_t rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ + uint32_t rxrtsocast; /* number of received RTS not addressed to the MAC */ + uint32_t rxctsocast; /* number of received CTS not addressed to the MAC */ + uint32_t rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ + uint32_t rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ + uint32_t rxcfrmmcast; /* number of RX Control multicast frames received by the MAC + * (unlikely to see these) + */ + uint32_t rxbeaconmbss; /* beacons received from member of BSS */ + uint32_t rxdfrmucastobss; /* number of unicast frames addressed to the MAC from + * other BSS (WDS FRAME) + */ + uint32_t rxbeaconobss; /* beacons received from other BSS */ + uint32_t rxrsptmout; /* Number of response timeouts for transmitted frames + * expecting a response + */ + uint32_t bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ + uint32_t rxf0ovfl; /* Number of receive fifo 0 overflows */ + uint32_t rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ + uint32_t rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ + uint32_t txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ + uint32_t pmqovfl; /* Number of PMQ overflows */ + uint32_t rxcgprqfrm; /* Number of received Probe requests that made it into + * the PRQ fifo + */ + uint32_t rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ + uint32_t txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did + * not get ACK + */ + uint32_t txcgprssuc; /* Tx Probe Response Success (ACK was received) */ + uint32_t prs_timeout; /* Number of probe requests that were dropped from the PRQ + * fifo because a probe response could not be sent out within + * the time limit defined in M_PRS_MAXTIME + */ + uint32_t rxnack; /* XXX Number of NACKS received (Afterburner) */ + uint32_t frmscons; /* XXX Number of frames completed without transmission because of an + * Afterburner re-queue + */ + uint32_t txnack; /* XXX Number of NACKs transmitted (Afterburner) */ + uint32_t txglitch_nack; /* obsolete */ + uint32_t txburst; /* obsolete */ + + /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ + uint32_t txfrag; /* dot11TransmittedFragmentCount */ + uint32_t txmulti; /* dot11MulticastTransmittedFrameCount */ + uint32_t txfail; /* dot11FailedCount */ + uint32_t txretry; /* dot11RetryCount */ + uint32_t txretrie; /* dot11MultipleRetryCount */ + uint32_t rxdup; /* dot11FrameduplicateCount */ + uint32_t txrts; /* dot11RTSSuccessCount */ + uint32_t txnocts; /* dot11RTSFailureCount */ + uint32_t txnoack; /* dot11ACKFailureCount */ + uint32_t rxfrag; /* dot11ReceivedFragmentCount */ + uint32_t rxmulti; /* dot11MulticastReceivedFrameCount */ + uint32_t rxcrc; /* dot11FCSErrorCount */ + uint32_t txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ + uint32_t rxundec; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill; /* TKIPLocalMICFailures */ + uint32_t tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay; /* TKIPReplays */ + uint32_t ccmpfmterr; /* CCMPFormatErrors */ + uint32_t ccmpreplay; /* CCMPReplays */ + uint32_t ccmpundec; /* CCMPDecryptErrors */ + uint32_t fourwayfail; /* FourWayHandshakeFailures */ + uint32_t wepundec; /* dot11WEPUndecryptableCount */ + uint32_t wepicverr; /* dot11WEPICVErrorCount */ + uint32_t decsuccess; /* DecryptSuccessCount */ + uint32_t tkipicverr; /* TKIPICVErrorCount */ + uint32_t wepexcluded; /* dot11WEPExcludedCount */ + + uint32_t rxundec_mcst; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill_mcst; /* TKIPLocalMICFailures */ + uint32_t tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay_mcst; /* TKIPReplays */ + uint32_t ccmpfmterr_mcst; /* CCMPFormatErrors */ + uint32_t ccmpreplay_mcst; /* CCMPReplays */ + uint32_t ccmpundec_mcst; /* CCMPDecryptErrors */ + uint32_t fourwayfail_mcst; /* FourWayHandshakeFailures */ + uint32_t wepundec_mcst; /* dot11WEPUndecryptableCount */ + uint32_t wepicverr_mcst; /* dot11WEPICVErrorCount */ + uint32_t decsuccess_mcst; /* DecryptSuccessCount */ + uint32_t tkipicverr_mcst; /* TKIPICVErrorCount */ + uint32_t wepexcluded_mcst; /* dot11WEPExcludedCount */ + + uint32_t txchanrej; /* Tx frames suppressed due to channel rejection */ + uint32_t txexptime; /* Tx frames suppressed due to timer expiration */ + uint32_t psmwds; /* Count PSM watchdogs */ + uint32_t phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ + + /* MBSS counters, AP only */ + uint32_t prq_entries_handled; /* PRQ entries read in */ + uint32_t prq_undirected_entries; /* which were bcast bss & ssid */ + uint32_t prq_bad_entries; /* which could not be translated to info */ + uint32_t atim_suppress_count; /* TX suppressions on ATIM fifo */ + uint32_t bcn_template_not_ready; /* Template marked in use on send bcn ... */ + uint32_t bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ + uint32_t late_tbtt_dpc; /* TBTT DPC did not happen in time */ + + /* per-rate receive stat counters */ + uint32_t rx1mbps; /* packets rx at 1Mbps */ + uint32_t rx2mbps; /* packets rx at 2Mbps */ + uint32_t rx5mbps5; /* packets rx at 5.5Mbps */ + uint32_t rx6mbps; /* packets rx at 6Mbps */ + uint32_t rx9mbps; /* packets rx at 9Mbps */ + uint32_t rx11mbps; /* packets rx at 11Mbps */ + uint32_t rx12mbps; /* packets rx at 12Mbps */ + uint32_t rx18mbps; /* packets rx at 18Mbps */ + uint32_t rx24mbps; /* packets rx at 24Mbps */ + uint32_t rx36mbps; /* packets rx at 36Mbps */ + uint32_t rx48mbps; /* packets rx at 48Mbps */ + uint32_t rx54mbps; /* packets rx at 54Mbps */ + uint32_t rx108mbps; /* packets rx at 108mbps */ + uint32_t rx162mbps; /* packets rx at 162mbps */ + uint32_t rx216mbps; /* packets rx at 216 mbps */ + uint32_t rx270mbps; /* packets rx at 270 mbps */ + uint32_t rx324mbps; /* packets rx at 324 mbps */ + uint32_t rx378mbps; /* packets rx at 378 mbps */ + uint32_t rx432mbps; /* packets rx at 432 mbps */ + uint32_t rx486mbps; /* packets rx at 486 mbps */ + uint32_t rx540mbps; /* packets rx at 540 mbps */ + + /* pkteng rx frame stats */ + uint32_t pktengrxducast; /* unicast frames rxed by the pkteng code */ + uint32_t pktengrxdmcast; /* multicast frames rxed by the pkteng code */ + + uint32_t rfdisable; /* count of radio disables */ + uint32_t bphy_rxcrsglitch; /* PHY count of bphy glitches */ + + uint32_t txmpdu_sgi; /* count for sgi transmit */ + uint32_t rxmpdu_sgi; /* count for sgi received */ + uint32_t txmpdu_stbc; /* count for stbc transmit */ + uint32_t rxmpdu_stbc; /* count for stbc received */ +} wl_cnt_ver_six_t; + +typedef struct +{ + uint16_t version; /* see definition of WL_CNT_T_VERSION */ + uint16_t length; /* length of entire structure */ + + /* transmit stat counters */ + uint32_t txframe; /* tx data frames */ + uint32_t txbyte; /* tx data bytes */ + uint32_t txretrans; /* tx mac retransmits */ + uint32_t txerror; /* tx data errors (derived: sum of others) */ + uint32_t txctl; /* tx management frames */ + uint32_t txprshort; /* tx short preamble frames */ + uint32_t txserr; /* tx status errors */ + uint32_t txnobuf; /* tx out of buffers errors */ + uint32_t txnoassoc; /* tx discard because we're not associated */ + uint32_t txrunt; /* tx runt frames */ + uint32_t txchit; /* tx header cache hit (fastpath) */ + uint32_t txcmiss; /* tx header cache miss (slowpath) */ + + /* transmit chip error counters */ + uint32_t txuflo; /* tx fifo underflows */ + uint32_t txphyerr; /* tx phy errors (indicated in tx status) */ + uint32_t txphycrs; /* PR8861/8963 counter */ + + /* receive stat counters */ + uint32_t rxframe; /* rx data frames */ + uint32_t rxbyte; /* rx data bytes */ + uint32_t rxerror; /* rx data errors (derived: sum of others) */ + uint32_t rxctl; /* rx management frames */ + uint32_t rxnobuf; /* rx out of buffers errors */ + uint32_t rxnondata; /* rx non data frames in the data channel errors */ + uint32_t rxbadds; /* rx bad DS errors */ + uint32_t rxbadcm; /* rx bad control or management frames */ + uint32_t rxfragerr; /* rx fragmentation errors */ + uint32_t rxrunt; /* rx runt frames */ + uint32_t rxgiant; /* rx giant frames */ + uint32_t rxnoscb; /* rx no scb error */ + uint32_t rxbadproto; /* rx invalid frames */ + uint32_t rxbadsrcmac; /* rx frames with Invalid Src Mac */ + uint32_t rxbadda; /* rx frames tossed for invalid da */ + uint32_t rxfilter; /* rx frames filtered out */ + + /* receive chip error counters */ + uint32_t rxoflo; /* rx fifo overflow errors */ + uint32_t rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ + + uint32_t d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ + uint32_t d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ + uint32_t d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ + + /* misc counters */ + uint32_t dmade; /* tx/rx dma descriptor errors */ + uint32_t dmada; /* tx/rx dma data errors */ + uint32_t dmape; /* tx/rx dma descriptor protocol errors */ + uint32_t reset; /* reset count */ + uint32_t tbtt; /* cnts the TBTT int's */ + uint32_t txdmawar; /* # occurrences of PR15420 workaround */ + uint32_t pkt_callback_reg_fail; /* callbacks register failure */ + + /* MAC counters: 32-bit version of d11.h's macstat_t */ + uint32_t txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, + * Control Management (includes retransmissions) + */ + uint32_t txrtsfrm; /* number of RTS sent out by the MAC */ + uint32_t txctsfrm; /* number of CTS sent out by the MAC */ + uint32_t txackfrm; /* number of ACK frames sent out */ + uint32_t txdnlfrm; /* Not used */ + uint32_t txbcnfrm; /* beacons transmitted */ + uint32_t txfunfl[8]; /* per-fifo tx underflows */ + uint32_t txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS + * or BCN) + */ + uint32_t txphyerror; /* Transmit phy error, type of error is reported in tx-status for + * driver enqueued frames + */ + uint32_t rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ + uint32_t rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ + uint32_t rxinvmachdr; /* Either the protocol version != 0 or frame type not + * data/control/management + */ + uint32_t rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ + uint32_t rxbadplcp; /* parity check of the PLCP header failed */ + uint32_t rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ + uint32_t rxstrt; /* Number of received frames with a good PLCP + * (i.e. passing parity check) + */ + uint32_t rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ + uint32_t rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ + uint32_t rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ + uint32_t rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ + uint32_t rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ + uint32_t rxackucast; /* number of ucast ACKS received (good FCS) */ + uint32_t rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ + uint32_t rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ + uint32_t rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ + uint32_t rxrtsocast; /* number of received RTS not addressed to the MAC */ + uint32_t rxctsocast; /* number of received CTS not addressed to the MAC */ + uint32_t rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ + uint32_t rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ + uint32_t rxcfrmmcast; /* number of RX Control multicast frames received by the MAC + * (unlikely to see these) + */ + uint32_t rxbeaconmbss; /* beacons received from member of BSS */ + uint32_t rxdfrmucastobss; /* number of unicast frames addressed to the MAC from + * other BSS (WDS FRAME) + */ + uint32_t rxbeaconobss; /* beacons received from other BSS */ + uint32_t rxrsptmout; /* Number of response timeouts for transmitted frames + * expecting a response + */ + uint32_t bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ + uint32_t rxf0ovfl; /* Number of receive fifo 0 overflows */ + uint32_t rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ + uint32_t rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ + uint32_t txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ + uint32_t pmqovfl; /* Number of PMQ overflows */ + uint32_t rxcgprqfrm; /* Number of received Probe requests that made it into + * the PRQ fifo + */ + uint32_t rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ + uint32_t txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did + * not get ACK + */ + uint32_t txcgprssuc; /* Tx Probe Response Success (ACK was received) */ + uint32_t prs_timeout; /* Number of probe requests that were dropped from the PRQ + * fifo because a probe response could not be sent out within + * the time limit defined in M_PRS_MAXTIME + */ + uint32_t rxnack; /* obsolete */ + uint32_t frmscons; /* obsolete */ + uint32_t txnack; /* obsolete */ + uint32_t txglitch_nack; /* obsolete */ + uint32_t txburst; /* obsolete */ + + /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ + uint32_t txfrag; /* dot11TransmittedFragmentCount */ + uint32_t txmulti; /* dot11MulticastTransmittedFrameCount */ + uint32_t txfail; /* dot11FailedCount */ + uint32_t txretry; /* dot11RetryCount */ + uint32_t txretrie; /* dot11MultipleRetryCount */ + uint32_t rxdup; /* dot11FrameduplicateCount */ + uint32_t txrts; /* dot11RTSSuccessCount */ + uint32_t txnocts; /* dot11RTSFailureCount */ + uint32_t txnoack; /* dot11ACKFailureCount */ + uint32_t rxfrag; /* dot11ReceivedFragmentCount */ + uint32_t rxmulti; /* dot11MulticastReceivedFrameCount */ + uint32_t rxcrc; /* dot11FCSErrorCount */ + uint32_t txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ + uint32_t rxundec; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill; /* TKIPLocalMICFailures */ + uint32_t tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay; /* TKIPReplays */ + uint32_t ccmpfmterr; /* CCMPFormatErrors */ + uint32_t ccmpreplay; /* CCMPReplays */ + uint32_t ccmpundec; /* CCMPDecryptErrors */ + uint32_t fourwayfail; /* FourWayHandshakeFailures */ + uint32_t wepundec; /* dot11WEPUndecryptableCount */ + uint32_t wepicverr; /* dot11WEPICVErrorCount */ + uint32_t decsuccess; /* DecryptSuccessCount */ + uint32_t tkipicverr; /* TKIPICVErrorCount */ + uint32_t wepexcluded; /* dot11WEPExcludedCount */ + + uint32_t txchanrej; /* Tx frames suppressed due to channel rejection */ + uint32_t psmwds; /* Count PSM watchdogs */ + uint32_t phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ + + /* MBSS counters, AP only */ + uint32_t prq_entries_handled; /* PRQ entries read in */ + uint32_t prq_undirected_entries; /* which were bcast bss & ssid */ + uint32_t prq_bad_entries; /* which could not be translated to info */ + uint32_t atim_suppress_count; /* TX suppressions on ATIM fifo */ + uint32_t bcn_template_not_ready; /* Template marked in use on send bcn ... */ + uint32_t bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ + uint32_t late_tbtt_dpc; /* TBTT DPC did not happen in time */ + + /* per-rate receive stat counters */ + uint32_t rx1mbps; /* packets rx at 1Mbps */ + uint32_t rx2mbps; /* packets rx at 2Mbps */ + uint32_t rx5mbps5; /* packets rx at 5.5Mbps */ + uint32_t rx6mbps; /* packets rx at 6Mbps */ + uint32_t rx9mbps; /* packets rx at 9Mbps */ + uint32_t rx11mbps; /* packets rx at 11Mbps */ + uint32_t rx12mbps; /* packets rx at 12Mbps */ + uint32_t rx18mbps; /* packets rx at 18Mbps */ + uint32_t rx24mbps; /* packets rx at 24Mbps */ + uint32_t rx36mbps; /* packets rx at 36Mbps */ + uint32_t rx48mbps; /* packets rx at 48Mbps */ + uint32_t rx54mbps; /* packets rx at 54Mbps */ + uint32_t rx108mbps; /* packets rx at 108mbps */ + uint32_t rx162mbps; /* packets rx at 162mbps */ + uint32_t rx216mbps; /* packets rx at 216 mbps */ + uint32_t rx270mbps; /* packets rx at 270 mbps */ + uint32_t rx324mbps; /* packets rx at 324 mbps */ + uint32_t rx378mbps; /* packets rx at 378 mbps */ + uint32_t rx432mbps; /* packets rx at 432 mbps */ + uint32_t rx486mbps; /* packets rx at 486 mbps */ + uint32_t rx540mbps; /* packets rx at 540 mbps */ + + /* pkteng rx frame stats */ + uint32_t pktengrxducast; /* unicast frames rxed by the pkteng code */ + uint32_t pktengrxdmcast; /* multicast frames rxed by the pkteng code */ + + uint32_t rfdisable; /* count of radio disables */ + uint32_t bphy_rxcrsglitch; /* PHY count of bphy glitches */ + + uint32_t txexptime; /* Tx frames suppressed due to timer expiration */ + + uint32_t txmpdu_sgi; /* count for sgi transmit */ + uint32_t rxmpdu_sgi; /* count for sgi received */ + uint32_t txmpdu_stbc; /* count for stbc transmit */ + uint32_t rxmpdu_stbc; /* count for stbc received */ + + uint32_t rxundec_mcst; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill_mcst; /* TKIPLocalMICFailures */ + uint32_t tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay_mcst; /* TKIPReplays */ + uint32_t ccmpfmterr_mcst; /* CCMPFormatErrors */ + uint32_t ccmpreplay_mcst; /* CCMPReplays */ + uint32_t ccmpundec_mcst; /* CCMPDecryptErrors */ + uint32_t fourwayfail_mcst; /* FourWayHandshakeFailures */ + uint32_t wepundec_mcst; /* dot11WEPUndecryptableCount */ + uint32_t wepicverr_mcst; /* dot11WEPICVErrorCount */ + uint32_t decsuccess_mcst; /* DecryptSuccessCount */ + uint32_t tkipicverr_mcst; /* TKIPICVErrorCount */ + uint32_t wepexcluded_mcst; /* dot11WEPExcludedCount */ + + uint32_t dma_hang; /* count for stbc received */ +} wl_cnt_ver_seven_t; + +typedef struct +{ + uint16_t version; /* see definition of WL_CNT_T_VERSION */ + uint16_t length; /* length of entire structure */ + + /* transmit stat counters */ + uint32_t txframe; /* tx data frames */ + uint32_t txbyte; /* tx data bytes */ + uint32_t txretrans; /* tx mac retransmits */ + uint32_t txerror; /* tx data errors (derived: sum of others) */ + uint32_t txctl; /* tx management frames */ + uint32_t txprshort; /* tx short preamble frames */ + uint32_t txserr; /* tx status errors */ + uint32_t txnobuf; /* tx out of buffers errors */ + uint32_t txnoassoc; /* tx discard because we're not associated */ + uint32_t txrunt; /* tx runt frames */ + uint32_t txchit; /* tx header cache hit (fastpath) */ + uint32_t txcmiss; /* tx header cache miss (slowpath) */ + + /* transmit chip error counters */ + uint32_t txuflo; /* tx fifo underflows */ + uint32_t txphyerr; /* tx phy errors (indicated in tx status) */ + uint32_t txphycrs; /* PR8861/8963 counter */ + + /* receive stat counters */ + uint32_t rxframe; /* rx data frames */ + uint32_t rxbyte; /* rx data bytes */ + uint32_t rxerror; /* rx data errors (derived: sum of others) */ + uint32_t rxctl; /* rx management frames */ + uint32_t rxnobuf; /* rx out of buffers errors */ + uint32_t rxnondata; /* rx non data frames in the data channel errors */ + uint32_t rxbadds; /* rx bad DS errors */ + uint32_t rxbadcm; /* rx bad control or management frames */ + uint32_t rxfragerr; /* rx fragmentation errors */ + uint32_t rxrunt; /* rx runt frames */ + uint32_t rxgiant; /* rx giant frames */ + uint32_t rxnoscb; /* rx no scb error */ + uint32_t rxbadproto; /* rx invalid frames */ + uint32_t rxbadsrcmac; /* rx frames with Invalid Src Mac */ + uint32_t rxbadda; /* rx frames tossed for invalid da */ + uint32_t rxfilter; /* rx frames filtered out */ + + /* receive chip error counters */ + uint32_t rxoflo; /* rx fifo overflow errors */ + uint32_t rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ + + uint32_t d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ + uint32_t d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ + uint32_t d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ + + /* misc counters */ + uint32_t dmade; /* tx/rx dma descriptor errors */ + uint32_t dmada; /* tx/rx dma data errors */ + uint32_t dmape; /* tx/rx dma descriptor protocol errors */ + uint32_t reset; /* reset count */ + uint32_t tbtt; /* cnts the TBTT int's */ + uint32_t txdmawar; /* # occurrences of PR15420 workaround */ + uint32_t pkt_callback_reg_fail; /* callbacks register failure */ + + /* MAC counters: 32-bit version of d11.h's macstat_t */ + uint32_t txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, + * Control Management (includes retransmissions) + */ + uint32_t txrtsfrm; /* number of RTS sent out by the MAC */ + uint32_t txctsfrm; /* number of CTS sent out by the MAC */ + uint32_t txackfrm; /* number of ACK frames sent out */ + uint32_t txdnlfrm; /* Not used */ + uint32_t txbcnfrm; /* beacons transmitted */ + uint32_t txfunfl[6]; /* per-fifo tx underflows */ + uint32_t rxtoolate; /* receive too late */ + uint32_t txfbw; /* transmit at fallback bw (dynamic bw) */ + uint32_t txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS + * or BCN) + */ + uint32_t txphyerror; /* Transmit phy error, type of error is reported in tx-status for + * driver enqueued frames + */ + uint32_t rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ + uint32_t rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ + uint32_t rxinvmachdr; /* Either the protocol version != 0 or frame type not + * data/control/management + */ + uint32_t rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ + uint32_t rxbadplcp; /* parity check of the PLCP header failed */ + uint32_t rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ + uint32_t rxstrt; /* Number of received frames with a good PLCP + * (i.e. passing parity check) + */ + uint32_t rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ + uint32_t rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ + uint32_t rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ + uint32_t rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ + uint32_t rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ + uint32_t rxackucast; /* number of ucast ACKS received (good FCS) */ + uint32_t rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ + uint32_t rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ + uint32_t rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ + uint32_t rxrtsocast; /* number of received RTS not addressed to the MAC */ + uint32_t rxctsocast; /* number of received CTS not addressed to the MAC */ + uint32_t rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ + uint32_t rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ + uint32_t rxcfrmmcast; /* number of RX Control multicast frames received by the MAC + * (unlikely to see these) + */ + uint32_t rxbeaconmbss; /* beacons received from member of BSS */ + uint32_t rxdfrmucastobss; /* number of unicast frames addressed to the MAC from + * other BSS (WDS FRAME) + */ + uint32_t rxbeaconobss; /* beacons received from other BSS */ + uint32_t rxrsptmout; /* Number of response timeouts for transmitted frames + * expecting a response + */ + uint32_t bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ + uint32_t rxf0ovfl; /* Number of receive fifo 0 overflows */ + uint32_t rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ + uint32_t rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ + uint32_t txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ + uint32_t pmqovfl; /* Number of PMQ overflows */ + uint32_t rxcgprqfrm; /* Number of received Probe requests that made it into + * the PRQ fifo + */ + uint32_t rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ + uint32_t txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did + * not get ACK + */ + uint32_t txcgprssuc; /* Tx Probe Response Success (ACK was received) */ + uint32_t prs_timeout; /* Number of probe requests that were dropped from the PRQ + * fifo because a probe response could not be sent out within + * the time limit defined in M_PRS_MAXTIME + */ + uint32_t rxnack; /* obsolete */ + uint32_t frmscons; /* obsolete */ + uint32_t txnack; /* obsolete */ + uint32_t rxback; /* blockack rxcnt */ + uint32_t txback; /* blockack txcnt */ + + /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ + uint32_t txfrag; /* dot11TransmittedFragmentCount */ + uint32_t txmulti; /* dot11MulticastTransmittedFrameCount */ + uint32_t txfail; /* dot11FailedCount */ + uint32_t txretry; /* dot11RetryCount */ + uint32_t txretrie; /* dot11MultipleRetryCount */ + uint32_t rxdup; /* dot11FrameduplicateCount */ + uint32_t txrts; /* dot11RTSSuccessCount */ + uint32_t txnocts; /* dot11RTSFailureCount */ + uint32_t txnoack; /* dot11ACKFailureCount */ + uint32_t rxfrag; /* dot11ReceivedFragmentCount */ + uint32_t rxmulti; /* dot11MulticastReceivedFrameCount */ + uint32_t rxcrc; /* dot11FCSErrorCount */ + uint32_t txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ + uint32_t rxundec; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill; /* TKIPLocalMICFailures */ + uint32_t tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay; /* TKIPReplays */ + uint32_t ccmpfmterr; /* CCMPFormatErrors */ + uint32_t ccmpreplay; /* CCMPReplays */ + uint32_t ccmpundec; /* CCMPDecryptErrors */ + uint32_t fourwayfail; /* FourWayHandshakeFailures */ + uint32_t wepundec; /* dot11WEPUndecryptableCount */ + uint32_t wepicverr; /* dot11WEPICVErrorCount */ + uint32_t decsuccess; /* DecryptSuccessCount */ + uint32_t tkipicverr; /* TKIPICVErrorCount */ + uint32_t wepexcluded; /* dot11WEPExcludedCount */ + + uint32_t txchanrej; /* Tx frames suppressed due to channel rejection */ + uint32_t psmwds; /* Count PSM watchdogs */ + uint32_t phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ + + /* MBSS counters, AP only */ + uint32_t prq_entries_handled; /* PRQ entries read in */ + uint32_t prq_undirected_entries; /* which were bcast bss & ssid */ + uint32_t prq_bad_entries; /* which could not be translated to info */ + uint32_t atim_suppress_count; /* TX suppressions on ATIM fifo */ + uint32_t bcn_template_not_ready; /* Template marked in use on send bcn ... */ + uint32_t bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ + uint32_t late_tbtt_dpc; /* TBTT DPC did not happen in time */ + + /* per-rate receive stat counters */ + uint32_t rx1mbps; /* packets rx at 1Mbps */ + uint32_t rx2mbps; /* packets rx at 2Mbps */ + uint32_t rx5mbps5; /* packets rx at 5.5Mbps */ + uint32_t rx6mbps; /* packets rx at 6Mbps */ + uint32_t rx9mbps; /* packets rx at 9Mbps */ + uint32_t rx11mbps; /* packets rx at 11Mbps */ + uint32_t rx12mbps; /* packets rx at 12Mbps */ + uint32_t rx18mbps; /* packets rx at 18Mbps */ + uint32_t rx24mbps; /* packets rx at 24Mbps */ + uint32_t rx36mbps; /* packets rx at 36Mbps */ + uint32_t rx48mbps; /* packets rx at 48Mbps */ + uint32_t rx54mbps; /* packets rx at 54Mbps */ + uint32_t rx108mbps; /* packets rx at 108mbps */ + uint32_t rx162mbps; /* packets rx at 162mbps */ + uint32_t rx216mbps; /* packets rx at 216 mbps */ + uint32_t rx270mbps; /* packets rx at 270 mbps */ + uint32_t rx324mbps; /* packets rx at 324 mbps */ + uint32_t rx378mbps; /* packets rx at 378 mbps */ + uint32_t rx432mbps; /* packets rx at 432 mbps */ + uint32_t rx486mbps; /* packets rx at 486 mbps */ + uint32_t rx540mbps; /* packets rx at 540 mbps */ + + /* pkteng rx frame stats */ + uint32_t pktengrxducast; /* unicast frames rxed by the pkteng code */ + uint32_t pktengrxdmcast; /* multicast frames rxed by the pkteng code */ + + uint32_t rfdisable; /* count of radio disables */ + uint32_t bphy_rxcrsglitch; /* PHY count of bphy glitches */ + uint32_t bphy_badplcp; + + uint32_t txexptime; /* Tx frames suppressed due to timer expiration */ + + uint32_t txmpdu_sgi; /* count for sgi transmit */ + uint32_t rxmpdu_sgi; /* count for sgi received */ + uint32_t txmpdu_stbc; /* count for stbc transmit */ + uint32_t rxmpdu_stbc; /* count for stbc received */ + + uint32_t rxundec_mcst; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill_mcst; /* TKIPLocalMICFailures */ + uint32_t tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay_mcst; /* TKIPReplays */ + uint32_t ccmpfmterr_mcst; /* CCMPFormatErrors */ + uint32_t ccmpreplay_mcst; /* CCMPReplays */ + uint32_t ccmpundec_mcst; /* CCMPDecryptErrors */ + uint32_t fourwayfail_mcst; /* FourWayHandshakeFailures */ + uint32_t wepundec_mcst; /* dot11WEPUndecryptableCount */ + uint32_t wepicverr_mcst; /* dot11WEPICVErrorCount */ + uint32_t decsuccess_mcst; /* DecryptSuccessCount */ + uint32_t tkipicverr_mcst; /* TKIPICVErrorCount */ + uint32_t wepexcluded_mcst; /* dot11WEPExcludedCount */ + + uint32_t dma_hang; /* count for dma hang */ + uint32_t reinit; /* count for reinit */ + + uint32_t pstatxucast; /* count of ucast frames xmitted on all psta assoc */ + uint32_t pstatxnoassoc; /* count of txnoassoc frames xmitted on all psta assoc */ + uint32_t pstarxucast; /* count of ucast frames received on all psta assoc */ + uint32_t pstarxbcmc; /* count of bcmc frames received on all psta */ + uint32_t pstatxbcmc; /* count of bcmc frames transmitted on all psta */ + + uint32_t cso_passthrough; /* hw cso required but passthrough */ + uint32_t cso_normal; /* hw cso hdr for normal process */ + uint32_t chained; /* number of frames chained */ + uint32_t chainedsz1; /* number of chain size 1 frames */ + uint32_t unchained; /* number of frames not chained */ + uint32_t maxchainsz; /* max chain size so far */ + uint32_t currchainsz; /* current chain size */ + + uint32_t rxdrop20s; /* drop secondary cnt */ + +} wl_cnt_ver_eight_t; + +/* per-rate receive stat counters subset of full counters */ +typedef struct +{ + uint32_t rx1mbps; /* packets rx at 1Mbps */ + uint32_t rx2mbps; /* packets rx at 2Mbps */ + uint32_t rx5mbps5; /* packets rx at 5.5Mbps */ + uint32_t rx6mbps; /* packets rx at 6Mbps */ + uint32_t rx9mbps; /* packets rx at 9Mbps */ + uint32_t rx11mbps; /* packets rx at 11Mbps */ + uint32_t rx12mbps; /* packets rx at 12Mbps */ + uint32_t rx18mbps; /* packets rx at 18Mbps */ + uint32_t rx24mbps; /* packets rx at 24Mbps */ + uint32_t rx36mbps; /* packets rx at 36Mbps */ + uint32_t rx48mbps; /* packets rx at 48Mbps */ + uint32_t rx54mbps; /* packets rx at 54Mbps */ + uint32_t rx108mbps; /* packets rx at 108mbps */ + uint32_t rx162mbps; /* packets rx at 162mbps */ + uint32_t rx216mbps; /* packets rx at 216 mbps */ + uint32_t rx270mbps; /* packets rx at 270 mbps */ +} whd_phyrate_counters_t; + +typedef struct +{ + uint32_t count; + uint8_t log[WL_PHYRATE_LOG_SIZE]; +} whd_phyrate_log_t; + +typedef struct +{ + uint16_t version; /* see definition of WL_CNT_T_VERSION */ + uint16_t length; /* length of entire structure */ + + /* transmit stat counters */ + uint32_t txframe; /* tx data frames */ + uint32_t txbyte; /* tx data bytes */ + uint32_t txretrans; /* tx mac retransmits */ + uint32_t txerror; /* tx data errors (derived: sum of others) */ + uint32_t txctl; /* tx management frames */ + uint32_t txprshort; /* tx short preamble frames */ + uint32_t txserr; /* tx status errors */ + uint32_t txnobuf; /* tx out of buffers errors */ + uint32_t txnoassoc; /* tx discard because we're not associated */ + uint32_t txrunt; /* tx runt frames */ + uint32_t txchit; /* tx header cache hit (fastpath) */ + uint32_t txcmiss; /* tx header cache miss (slowpath) */ + + /* transmit chip error counters */ + uint32_t txuflo; /* tx fifo underflows */ + uint32_t txphyerr; /* tx phy errors (indicated in tx status) */ + uint32_t txphycrs; /* PR8861/8963 counter */ + + /* receive stat counters */ + uint32_t rxframe; /* rx data frames */ + uint32_t rxbyte; /* rx data bytes */ + uint32_t rxerror; /* rx data errors (derived: sum of others) */ + uint32_t rxctl; /* rx management frames */ + uint32_t rxnobuf; /* rx out of buffers errors */ + uint32_t rxnondata; /* rx non data frames in the data channel errors */ + uint32_t rxbadds; /* rx bad DS errors */ + uint32_t rxbadcm; /* rx bad control or management frames */ + uint32_t rxfragerr; /* rx fragmentation errors */ + uint32_t rxrunt; /* rx runt frames */ + uint32_t rxgiant; /* rx giant frames */ + uint32_t rxnoscb; /* rx no scb error */ + uint32_t rxbadproto; /* rx invalid frames */ + uint32_t rxbadsrcmac; /* rx frames with Invalid Src Mac */ + uint32_t rxbadda; /* rx frames tossed for invalid da */ + uint32_t rxfilter; /* rx frames filtered out */ + + /* receive chip error counters */ + uint32_t rxoflo; /* rx fifo overflow errors */ + uint32_t rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ + + uint32_t d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ + uint32_t d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ + uint32_t d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ + + /* misc counters */ + uint32_t dmade; /* tx/rx dma descriptor errors */ + uint32_t dmada; /* tx/rx dma data errors */ + uint32_t dmape; /* tx/rx dma descriptor protocol errors */ + uint32_t reset; /* reset count */ + uint32_t tbtt; /* cnts the TBTT int's */ + uint32_t txdmawar; /* # occurrences of PR15420 workaround */ + uint32_t pkt_callback_reg_fail; /* callbacks register failure */ + + /* MAC counters: 32-bit version of d11.h's macstat_t */ + uint32_t txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, + * Control Management (includes retransmissions) + */ + uint32_t txrtsfrm; /* number of RTS sent out by the MAC */ + uint32_t txctsfrm; /* number of CTS sent out by the MAC */ + uint32_t txackfrm; /* number of ACK frames sent out */ + uint32_t txdnlfrm; /* Not used */ + uint32_t txbcnfrm; /* beacons transmitted */ + uint32_t txfunfl[6]; /* per-fifo tx underflows */ + uint32_t rxtoolate; /* receive too late */ + uint32_t txfbw; /* transmit at fallback bw (dynamic bw) */ + uint32_t txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS + * or BCN) + */ + uint32_t txphyerror; /* Transmit phy error, type of error is reported in tx-status for + * driver enqueued frames + */ + uint32_t rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ + uint32_t rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ + uint32_t rxinvmachdr; /* Either the protocol version != 0 or frame type not + * data/control/management + */ + uint32_t rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ + uint32_t rxbadplcp; /* parity check of the PLCP header failed */ + uint32_t rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ + uint32_t rxstrt; /* Number of received frames with a good PLCP + * (i.e. passing parity check) + */ + uint32_t rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ + uint32_t rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ + uint32_t rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ + uint32_t rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ + uint32_t rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ + uint32_t rxackucast; /* number of ucast ACKS received (good FCS) */ + uint32_t rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ + uint32_t rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ + uint32_t rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ + uint32_t rxrtsocast; /* number of received RTS not addressed to the MAC */ + uint32_t rxctsocast; /* number of received CTS not addressed to the MAC */ + uint32_t rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ + uint32_t rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ + uint32_t rxcfrmmcast; /* number of RX Control multicast frames received by the MAC + * (unlikely to see these) + */ + uint32_t rxbeaconmbss; /* beacons received from member of BSS */ + uint32_t rxdfrmucastobss; /* number of unicast frames addressed to the MAC from + * other BSS (WDS FRAME) + */ + uint32_t rxbeaconobss; /* beacons received from other BSS */ + uint32_t rxrsptmout; /* Number of response timeouts for transmitted frames + * expecting a response + */ + uint32_t bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ + uint32_t rxf0ovfl; /* Number of receive fifo 0 overflows */ + uint32_t rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ + uint32_t rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ + uint32_t txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ + uint32_t pmqovfl; /* Number of PMQ overflows */ + uint32_t rxcgprqfrm; /* Number of received Probe requests that made it into + * the PRQ fifo + */ + uint32_t rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ + uint32_t txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did + * not get ACK + */ + uint32_t txcgprssuc; /* Tx Probe Response Success (ACK was received) */ + uint32_t prs_timeout; /* Number of probe requests that were dropped from the PRQ + * fifo because a probe response could not be sent out within + * the time limit defined in M_PRS_MAXTIME + */ + uint32_t rxnack; /* obsolete */ + uint32_t frmscons; /* obsolete */ + uint32_t txnack; /* obsolete */ + uint32_t rxback; /* blockack rxcnt */ + uint32_t txback; /* blockack txcnt */ + + /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ + uint32_t txfrag; /* dot11TransmittedFragmentCount */ + uint32_t txmulti; /* dot11MulticastTransmittedFrameCount */ + uint32_t txfail; /* dot11FailedCount */ + uint32_t txretry; /* dot11RetryCount */ + uint32_t txretrie; /* dot11MultipleRetryCount */ + uint32_t rxdup; /* dot11FrameduplicateCount */ + uint32_t txrts; /* dot11RTSSuccessCount */ + uint32_t txnocts; /* dot11RTSFailureCount */ + uint32_t txnoack; /* dot11ACKFailureCount */ + uint32_t rxfrag; /* dot11ReceivedFragmentCount */ + uint32_t rxmulti; /* dot11MulticastReceivedFrameCount */ + uint32_t rxcrc; /* dot11FCSErrorCount */ + uint32_t txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ + uint32_t rxundec; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill; /* TKIPLocalMICFailures */ + uint32_t tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay; /* TKIPReplays */ + uint32_t ccmpfmterr; /* CCMPFormatErrors */ + uint32_t ccmpreplay; /* CCMPReplays */ + uint32_t ccmpundec; /* CCMPDecryptErrors */ + uint32_t fourwayfail; /* FourWayHandshakeFailures */ + uint32_t wepundec; /* dot11WEPUndecryptableCount */ + uint32_t wepicverr; /* dot11WEPICVErrorCount */ + uint32_t decsuccess; /* DecryptSuccessCount */ + uint32_t tkipicverr; /* TKIPICVErrorCount */ + uint32_t wepexcluded; /* dot11WEPExcludedCount */ + + uint32_t txchanrej; /* Tx frames suppressed due to channel rejection */ + uint32_t psmwds; /* Count PSM watchdogs */ + uint32_t phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ + + /* MBSS counters, AP only */ + uint32_t prq_entries_handled; /* PRQ entries read in */ + uint32_t prq_undirected_entries; /* which were bcast bss & ssid */ + uint32_t prq_bad_entries; /* which could not be translated to info */ + uint32_t atim_suppress_count; /* TX suppressions on ATIM fifo */ + uint32_t bcn_template_not_ready; /* Template marked in use on send bcn ... */ + uint32_t bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ + uint32_t late_tbtt_dpc; /* TBTT DPC did not happen in time */ + + /* per-rate receive stat counters */ + uint32_t rx1mbps; /* packets rx at 1Mbps */ + uint32_t rx2mbps; /* packets rx at 2Mbps */ + uint32_t rx5mbps5; /* packets rx at 5.5Mbps */ + uint32_t rx6mbps; /* packets rx at 6Mbps */ + uint32_t rx9mbps; /* packets rx at 9Mbps */ + uint32_t rx11mbps; /* packets rx at 11Mbps */ + uint32_t rx12mbps; /* packets rx at 12Mbps */ + uint32_t rx18mbps; /* packets rx at 18Mbps */ + uint32_t rx24mbps; /* packets rx at 24Mbps */ + uint32_t rx36mbps; /* packets rx at 36Mbps */ + uint32_t rx48mbps; /* packets rx at 48Mbps */ + uint32_t rx54mbps; /* packets rx at 54Mbps */ + uint32_t rx108mbps; /* packets rx at 108mbps */ + uint32_t rx162mbps; /* packets rx at 162mbps */ + uint32_t rx216mbps; /* packets rx at 216 mbps */ + uint32_t rx270mbps; /* packets rx at 270 mbps */ + uint32_t rx324mbps; /* packets rx at 324 mbps */ + uint32_t rx378mbps; /* packets rx at 378 mbps */ + uint32_t rx432mbps; /* packets rx at 432 mbps */ + uint32_t rx486mbps; /* packets rx at 486 mbps */ + uint32_t rx540mbps; /* packets rx at 540 mbps */ + + /* pkteng rx frame stats */ + uint32_t pktengrxducast; /* unicast frames rxed by the pkteng code */ + uint32_t pktengrxdmcast; /* multicast frames rxed by the pkteng code */ + + uint32_t rfdisable; /* count of radio disables */ + uint32_t bphy_rxcrsglitch; /* PHY count of bphy glitches */ + uint32_t bphy_badplcp; + + uint32_t txexptime; /* Tx frames suppressed due to timer expiration */ + + uint32_t txmpdu_sgi; /* count for sgi transmit */ + uint32_t rxmpdu_sgi; /* count for sgi received */ + uint32_t txmpdu_stbc; /* count for stbc transmit */ + uint32_t rxmpdu_stbc; /* count for stbc received */ + + uint32_t rxundec_mcst; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32_t tkipmicfaill_mcst; /* TKIPLocalMICFailures */ + uint32_t tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ + uint32_t tkipreplay_mcst; /* TKIPReplays */ + uint32_t ccmpfmterr_mcst; /* CCMPFormatErrors */ + uint32_t ccmpreplay_mcst; /* CCMPReplays */ + uint32_t ccmpundec_mcst; /* CCMPDecryptErrors */ + uint32_t fourwayfail_mcst; /* FourWayHandshakeFailures */ + uint32_t wepundec_mcst; /* dot11WEPUndecryptableCount */ + uint32_t wepicverr_mcst; /* dot11WEPICVErrorCount */ + uint32_t decsuccess_mcst; /* DecryptSuccessCount */ + uint32_t tkipicverr_mcst; /* TKIPICVErrorCount */ + uint32_t wepexcluded_mcst; /* dot11WEPExcludedCount */ + + uint32_t dma_hang; /* count for dma hang */ + uint32_t reinit; /* count for reinit */ + + uint32_t pstatxucast; /* count of ucast frames xmitted on all psta assoc */ + uint32_t pstatxnoassoc; /* count of txnoassoc frames xmitted on all psta assoc */ + uint32_t pstarxucast; /* count of ucast frames received on all psta assoc */ + uint32_t pstarxbcmc; /* count of bcmc frames received on all psta */ + uint32_t pstatxbcmc; /* count of bcmc frames transmitted on all psta */ + + uint32_t cso_passthrough; /* hw cso required but passthrough */ + uint32_t cso_normal; /* hw cso hdr for normal process */ + uint32_t chained; /* number of frames chained */ + uint32_t chainedsz1; /* number of chain size 1 frames */ + uint32_t unchained; /* number of frames not chained */ + uint32_t maxchainsz; /* max chain size so far */ + uint32_t currchainsz; /* current chain size */ + uint32_t rxdrop20s; /* drop secondary cnt */ + uint32_t pciereset; /* Secondary Bus Reset issued by driver */ + uint32_t cfgrestore; /* configspace restore by driver */ + uint32_t reinitreason[8]; /* reinitreason counters; 0: Unknown reason */ + uint32_t rxrtry; /* num of received packets with retry bit on */ +} wl_cnt_ver_ten_t; + +typedef struct +{ + uint16_t version; + uint16_t length; + uint32_t rxampdu_sgi; + uint32_t rxampdu_stbc; + uint32_t rxmpdu_sgi; + uint32_t rxmpdu_stbc; + uint32_t rxmcs0_40M; + uint32_t rxmcs1_40M; + uint32_t rxmcs2_40M; + uint32_t rxmcs3_40M; + uint32_t rxmcs4_40M; + uint32_t rxmcs5_40M; + uint32_t rxmcs6_40M; + uint32_t rxmcs7_40M; + uint32_t rxmcs32_40M; + uint32_t txfrmsnt_20Mlo; + uint32_t txfrmsnt_20Mup; + uint32_t txfrmsnt_40M; + uint32_t rx_20ul; +} wl_cnt_ext_t; +#define WL_RXDIV_STATS_T_VERSION 1 +typedef struct +{ + uint16_t version; + uint16_t length; + uint32_t rxant[4]; +} wl_rxdiv_stats_t; +#define WL_DELTA_STATS_T_VERSION 1 +typedef struct +{ + uint16_t version; + uint16_t length; + uint32_t txframe; + uint32_t txbyte; + uint32_t txretrans; + uint32_t txfail; + uint32_t rxframe; + uint32_t rxbyte; + uint32_t rx1mbps; + uint32_t rx2mbps; + uint32_t rx5mbps5; + uint32_t rx6mbps; + uint32_t rx9mbps; + uint32_t rx11mbps; + uint32_t rx12mbps; + uint32_t rx18mbps; + uint32_t rx24mbps; + uint32_t rx36mbps; + uint32_t rx48mbps; + uint32_t rx54mbps; + uint32_t rx108mbps; + uint32_t rx162mbps; + uint32_t rx216mbps; + uint32_t rx270mbps; + uint32_t rx324mbps; + uint32_t rx378mbps; + uint32_t rx432mbps; + uint32_t rx486mbps; + uint32_t rx540mbps; +} wl_delta_stats_t; +#define WL_WME_CNT_VERSION 1 +typedef struct +{ + uint32_t packets; + uint32_t bytes; +} wl_traffic_stats_t; +#define AC_COUNT 4 +typedef struct +{ + uint16_t version; + uint16_t length; + wl_traffic_stats_t tx[AC_COUNT]; + wl_traffic_stats_t tx_failed[AC_COUNT]; + wl_traffic_stats_t rx[AC_COUNT]; + wl_traffic_stats_t rx_failed[AC_COUNT]; + wl_traffic_stats_t forward[AC_COUNT]; + wl_traffic_stats_t tx_expired[AC_COUNT]; +} wl_wme_cnt_t; + +#define WL_MKEEP_ALIVE_VERSION 1 +#define WL_MKEEP_ALIVE_FIXED_LEN offsetof(wl_mkeep_alive_pkt_t, data) +#define WL_MKEEP_ALIVE_PRECISION 500 + +#define WLC_BA_CNT_VERSION 1 +typedef struct wlc_ba_cnt +{ + uint16_t version; + uint16_t length; + uint32_t txpdu; + uint32_t txsdu; + uint32_t txfc; + uint32_t txfci; + uint32_t txretrans; + uint32_t txbatimer; + uint32_t txdrop; + uint32_t txaddbareq; + uint32_t txaddbaresp; + uint32_t txdelba; + uint32_t txba; + uint32_t txbar; + uint32_t txpad[4]; + uint32_t rxpdu; + uint32_t rxqed; + uint32_t rxdup; + uint32_t rxnobuf; + uint32_t rxaddbareq; + uint32_t rxaddbaresp; + uint32_t rxdelba; + uint32_t rxba; + uint32_t rxbar; + uint32_t rxinvba; + uint32_t rxbaholes; + uint32_t rxunexp; + uint32_t rxpad[4]; +} wlc_ba_cnt_t; +struct ampdu_tid_control +{ + uint8_t tid; + uint8_t enable; +}; +struct wl_msglevel2 +{ + uint32_t low; + uint32_t high; +}; +struct ampdu_ea_tid +{ + wl_ether_addr_t ea; + uint8_t tid; +}; +struct ampdu_retry_tid +{ + uint8_t tid; + uint8_t retry; +}; +struct ampdu_ba_sizes +{ + uint8_t ba_tx_wsize; + uint8_t ba_rx_wsize; +}; +#define DPT_DISCOVERY_MANUAL 0x01 +#define DPT_DISCOVERY_AUTO 0x02 +#define DPT_DISCOVERY_SCAN 0x04 +#define DPT_PATHSEL_AUTO 0 +#define DPT_PATHSEL_DIRECT 1 +#define DPT_PATHSEL_APPATH 2 +#define DPT_DENY_LIST_ADD 1 +#define DPT_DENY_LIST_REMOVE 2 +#define DPT_MANUAL_EP_CREATE 1 +#define DPT_MANUAL_EP_MODIFY 2 +#define DPT_MANUAL_EP_DELETE 3 +typedef struct dpt_iovar +{ + wl_ether_addr_t ea; + uint8_t mode; + uint32_t pad; +} dpt_iovar_t; +#define DPT_STATUS_ACTIVE 0x01 +#define DPT_STATUS_AES 0x02 +#define DPT_STATUS_FAILED 0x04 +#define DPT_FNAME_LEN 48 +typedef struct dpt_status +{ + uint8_t status; + uint8_t fnlen; + uint8_t name[DPT_FNAME_LEN]; + uint32_t rssi; + sta_info_t sta; +} dpt_status_t; +typedef struct dpt_list +{ + uint32_t num; + dpt_status_t status[1]; +} dpt_list_t; +typedef struct dpt_fname +{ + uint8_t len; + uint8_t name[DPT_FNAME_LEN]; +} dpt_fname_t; +#define BDD_FNAME_LEN 32 +typedef struct bdd_fname +{ + uint8_t len; + uint8_t name[BDD_FNAME_LEN]; +} bdd_fname_t; +struct ts_list +{ + int32_t count; + struct tsinfo_arg tsinfo[1]; +}; +typedef struct tspec_arg +{ + uint16_t version; + uint16_t length; + uint32_t flag; + struct tsinfo_arg tsinfo; + uint16_t nom_msdu_size; + uint16_t max_msdu_size; + uint32_t min_srv_interval; + uint32_t max_srv_interval; + uint32_t inactivity_interval; + uint32_t suspension_interval; + uint32_t srv_start_time; + uint32_t min_data_rate; + uint32_t mean_data_rate; + uint32_t peak_data_rate; + uint32_t max_burst_size; + uint32_t delay_bound; + uint32_t min_phy_rate; + uint16_t surplus_bw; + uint16_t medium_time; + uint8_t dialog_token; +} tspec_arg_t; +typedef struct tspec_per_sta_arg +{ + wl_ether_addr_t ea; + struct tspec_arg ts; +} tspec_per_sta_arg_t; +typedef struct wme_max_bandwidth +{ + uint32_t ac[AC_COUNT]; +} wme_max_bandwidth_t; +#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t) ) +#define TSPEC_ARG_VERSION 2 +#define TSPEC_ARG_LENGTH 55 +#define TSPEC_DEFAULT_DIALOG_TOKEN 42 +#define TSPEC_DEFAULT_SBW_FACTOR 0x3000 +#define TSPEC_PENDING 0 +#define TSPEC_ACCEPTED 1 +#define TSPEC_REJECTED 2 +#define TSPEC_UNKNOWN 3 +#define TSPEC_STATUS_MASK 7 +#define WL_WLAN_ASSOC_REASON_NORMAL_NETWORK 0 +#define WL_WLAN_ASSOC_REASON_ROAM_FROM_CELLULAR_NETWORK 1 +#define WL_WLAN_ASSOC_REASON_ROAM_FROM_LAN 2 +#define WL_WLAN_ASSOC_REASON_MAX 2 +#define WL_SWFL_ABBFL 0x0001 +#define WL_SWFL_ABENCORE 0x0002 +#define WL_SWFL_NOHWRADIO 0x0004 +#define WL_LIFETIME_MAX 0xFFFF +typedef struct wl_lifetime +{ + uint32_t ac; + uint32_t lifetime; +} wl_lifetime_t; +typedef struct wl_chan_switch +{ + uint8_t mode; + uint8_t count; + wl_chanspec_t chspec; + uint8_t reg; +} wl_chan_switch_t; +#define WLC_ROAM_TRIGGER_DEFAULT 0 +#define WLC_ROAM_TRIGGER_BANDWIDTH 1 +#define WLC_ROAM_TRIGGER_DISTANCE 2 +#define WLC_ROAM_TRIGGER_MAX_VALUE 2 +enum +{ + PFN_LIST_ORDER, PFN_RSSI +}; +#define SORT_CRITERIA_BIT 0 +#define AUTO_NET_SWITCH_BIT 1 +#define ENABLE_BKGRD_SCAN_BIT 2 +#define IMMEDIATE_SCAN_BIT 3 +#define AUTO_CONNECT_BIT 4 +#define IMMEDIATE_EVENT_BIT 8 +#define SUPPRESS_SSID_BIT 9 +#define ENABLE_NET_OFFLOAD_BIT 10 +#define SORT_CRITERIA_MASK 0x01 +#define AUTO_NET_SWITCH_MASK 0x02 +#define ENABLE_BKGRD_SCAN_MASK 0x04 +#define IMMEDIATE_SCAN_MASK 0x08 +#define AUTO_CONNECT_MASK 0x10 +#define PFN_VERSION 2 + +/* PFN network info structure */ +typedef struct wl_pfn_subnet_info +{ + struct ether_addr BSSID; + uint8_t channel; /* channel number only */ + uint8_t SSID_len; + uint8_t SSID[32]; +} wl_pfn_subnet_info_t; + +typedef struct wl_pfn_net_info +{ + wl_pfn_subnet_info_t pfnsubnet; + int16_t RSSI; /* receive signal strength (in dBm) */ + uint16_t timestamp; /* age in seconds */ +} wl_pfn_net_info_t; + +/* used to report exactly one scan result */ +/* plus reports detailed scan info in bss_info */ +typedef struct wl_pfn_scanresult +{ + uint32_t version; + uint32_t status; + uint32_t count; + wl_pfn_net_info_t netinfo; + wl_bss_info_t bss_info; +} wl_pfn_scanresult_t; + +/* PFN data structure */ +typedef struct wl_pfn_param +{ + int32_t version; /* PNO parameters version */ + int32_t scan_freq; /* Scan frequency */ + int32_t lost_network_timeout; /* Timeout in sec. to declare + * discovered network as lost + */ + int16_t flags; /* Bit field to control features + * of PFN such as sort criteria auto + * enable switch and background scan + */ + int16_t rssi_margin; /* Margin to avoid jitter for choosing a + * PFN based on RSSI sort criteria + */ + uint8_t bestn; /* number of best networks in each scan */ + uint8_t mscan; /* number of scans recorded */ + uint8_t repeat; /* Minimum number of scan intervals + * before scan frequency changes in adaptive scan + */ + uint8_t exp; /* Exponent of 2 for maximum scan interval */ + + int32_t slow_freq; /* slow scan period */ +} wl_pfn_param_t; + +typedef struct wl_pfn_bssid +{ + struct ether_addr macaddr; + /* Bit4: suppress_lost, Bit3: suppress_found */ + uint16_t flags; +} wl_pfn_bssid_t; + +typedef struct wl_pfn_cfg +{ + uint32_t reporttype; + int32_t channel_num; + uint16_t channel_list[WL_NUMCHANNELS]; + uint32_t flags; +} wl_pfn_cfg_t; + +/* for use with wl_pfn.flags */ +#define WL_PFN_HIDDEN_MASK 0x4 +#define WL_PFN_SUPPRESSLOST_MASK 0x10 + +typedef struct wl_pfn +{ + wlc_ssid_t ssid; /* ssid name and its length */ + int32_t flags; /* bit2: hidden */ + int32_t infra; /* BSS Vs IBSS */ + int32_t auth; /* Open Vs Closed */ + int32_t wpa_auth; /* WPA type */ + int32_t wsec; /* wsec value */ +} wl_pfn_t; + +#define TOE_TX_CSUM_OL 0x00000001 +#define TOE_RX_CSUM_OL 0x00000002 +#define TOE_ERRTEST_TX_CSUM 0x00000001 +#define TOE_ERRTEST_RX_CSUM 0x00000002 +#define TOE_ERRTEST_RX_CSUM2 0x00000004 +struct toe_ol_stats_t +{ + uint32_t tx_summed; + uint32_t tx_iph_fill; + uint32_t tx_tcp_fill; + uint32_t tx_udp_fill; + uint32_t tx_icmp_fill; + uint32_t rx_iph_good; + uint32_t rx_iph_bad; + uint32_t rx_tcp_good; + uint32_t rx_tcp_bad; + uint32_t rx_udp_good; + uint32_t rx_udp_bad; + uint32_t rx_icmp_good; + uint32_t rx_icmp_bad; + uint32_t tx_tcp_errinj; + uint32_t tx_udp_errinj; + uint32_t tx_icmp_errinj; + uint32_t rx_tcp_errinj; + uint32_t rx_udp_errinj; + uint32_t rx_icmp_errinj; +}; +#define ARP_OL_AGENT 0x00000001 +#define ARP_OL_SNOOP 0x00000002 +#define ARP_OL_HOST_AUTO_REPLY 0x00000004 +#define ARP_OL_PEER_AUTO_REPLY 0x00000008 +#define ARP_ERRTEST_REPLY_PEER 0x1 +#define ARP_ERRTEST_REPLY_HOST 0x2 +#define ARP_MULTIHOMING_MAX 8 +typedef struct arp_ol_stats +{ + uint32_t host_ip_entries; + uint32_t host_ip_overflow; + uint32_t arp_table_entries; + uint32_t arp_table_overflow; + uint32_t host_request; + uint32_t host_reply; + uint32_t host_service; + uint32_t peer_request; + uint32_t peer_request_drop; + uint32_t peer_reply; + uint32_t peer_reply_drop; + uint32_t peer_service; +}arp_ol_stats_t; +typedef struct wl_keep_alive_pkt +{ + uint32_t period_msec; + uint16_t len_bytes; + uint8_t data[1]; +} wl_keep_alive_pkt_t; +#define WL_KEEP_ALIVE_FIXED_LEN offsetof(wl_keep_alive_pkt_t, data) +typedef enum wl_pkt_filter_type +{ + WL_PKT_FILTER_TYPE_PATTERN_MATCH +} wl_pkt_filter_type_t; +#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t +typedef struct wl_pkt_filter_pattern +{ + uint32_t offset; + uint32_t size_bytes; + uint8_t mask_and_pattern[1]; +} wl_pkt_filter_pattern_t; +typedef struct wl_pkt_filter +{ + uint32_t id; + uint32_t type; + uint32_t negate_match; + union + { + wl_pkt_filter_pattern_t pattern; + } u; +} wl_pkt_filter_t; +#define WL_PKT_FILTER_FIXED_LEN offsetof(wl_pkt_filter_t, u) +#define WL_PKT_FILTER_PATTERN_FIXED_LEN offsetof(wl_pkt_filter_pattern_t, mask_and_pattern) +typedef struct wl_pkt_filter_enable +{ + uint32_t id; + uint32_t enable; +} wl_pkt_filter_enable_t; +typedef struct wl_pkt_filter_list +{ + uint32_t num; + wl_pkt_filter_t filter[1]; +} wl_pkt_filter_list_t; +#define WL_PKT_FILTER_LIST_FIXED_LEN offsetof(wl_pkt_filter_list_t, filter) +typedef struct wl_pkt_filter_stats +{ + uint32_t num_pkts_matched; + uint32_t num_pkts_forwarded; + uint32_t num_pkts_discarded; +} wl_pkt_filter_stats_t; +typedef struct wl_seq_cmd_ioctl +{ + uint32_t cmd; + uint32_t len; +} wl_seq_cmd_ioctl_t; +#define WL_SEQ_CMD_ALIGN_BYTES 4 +#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \ + ( ( (cmd) == WLC_GET_MAGIC ) || \ + ( (cmd) == WLC_GET_VERSION ) || \ + ( (cmd) == WLC_GET_AP ) || \ + ( (cmd) == WLC_GET_INSTANCE ) ) +#define WL_PKTENG_PER_TX_START 0x01 +#define WL_PKTENG_PER_TX_STOP 0x02 +#define WL_PKTENG_PER_RX_START 0x04 +#define WL_PKTENG_PER_RX_WITH_ACK_START 0x05 +#define WL_PKTENG_PER_TX_WITH_ACK_START 0x06 +#define WL_PKTENG_PER_RX_STOP 0x08 +#define WL_PKTENG_PER_MASK 0xff +#define WL_PKTENG_SYNCHRONOUS 0x100 +typedef struct wl_pkteng +{ + uint32_t flags; + uint32_t delay; + uint32_t nframes; + uint32_t length; + uint8_t seqno; + wl_ether_addr_t dest; + wl_ether_addr_t src; +} wl_pkteng_t; +#define NUM_80211b_RATES 4 +#define NUM_80211ag_RATES 8 +#define NUM_80211n_RATES 32 +#define NUM_80211_RATES (NUM_80211b_RATES + NUM_80211ag_RATES + NUM_80211n_RATES) +typedef struct wl_pkteng_stats +{ + uint32_t lostfrmcnt; + int32_t rssi; + int32_t snr; + uint16_t rxpktcnt[NUM_80211_RATES + 1]; +} wl_pkteng_stats_t; +typedef struct wl_sslpnphy_papd_debug_data +{ + uint8_t psat_pwr; + uint8_t psat_indx; + uint8_t final_idx; + uint8_t start_idx; + int32_t min_phase; + int32_t voltage; + int8_t temperature; +} wl_sslpnphy_papd_debug_data_t; +typedef struct wl_sslpnphy_debug_data +{ + int16_t papdcompRe[64]; + int16_t papdcompIm[64]; +} wl_sslpnphy_debug_data_t; +typedef struct wl_sslpnphy_spbdump_data +{ + uint16_t tbl_length; + int16_t spbreal[256]; + int16_t spbimg[256]; +} wl_sslpnphy_spbdump_data_t; +typedef struct wl_sslpnphy_percal_debug_data +{ + uint32_t cur_idx; + uint32_t tx_drift; + uint8_t prev_cal_idx; + uint32_t percal_ctr; + int32_t nxt_cal_idx; + uint32_t force_1idxcal; + uint32_t onedxacl_req; + int32_t last_cal_volt; + int8_t last_cal_temp; + uint32_t vbat_ripple; + uint32_t exit_route; + int32_t volt_winner; +} wl_sslpnphy_percal_debug_data_t; +#define WL_WOWL_MAGIC (1 << 0) +#define WL_WOWL_NET (1 << 1) +#define WL_WOWL_DIS (1 << 2) +#define WL_WOWL_RETR (1 << 3) +#define WL_WOWL_BCN (1 << 4) +#define WL_WOWL_TST (1 << 5) +#define WL_WOWL_TRAFFIC (1 << 12) +#define WL_WOWL_BCAST (1 << 15) +#define WL_WOWL_GTK (0x441f) +#define WL_WOWL_DEAUTH (0x1F) +#define WL_WOWL_ALL (0x541E) + +#define MAGIC_PKT_MINLEN 102 +typedef struct +{ + uint32_t masksize; + uint32_t offset; + uint32_t patternoffset; + uint32_t patternsize; +} wl_wowl_pattern_t; +typedef struct +{ + uint32_t count; + wl_wowl_pattern_t pattern[1]; +} wl_wowl_pattern_list_t; +typedef struct +{ + uint8_t pci_wakeind; + uint16_t ucode_wakeind; +} wl_wowl_wakeind_t; +typedef struct wl_txrate_class +{ + uint8_t init_rate; + uint8_t min_rate; + uint8_t max_rate; +} wl_txrate_class_t; +#define WL_DELAYMODE_DEFER 0 +#define WL_DELAYMODE_FORCE 1 +#define WL_DELAYMODE_AUTO 2 +#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT 100 +#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN 5 +#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX 1000 +#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT 20 +#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN 10 +#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX 1000 +#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT 300 +#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN 10 +#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX 900 +#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT 5 +#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN 5 +#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX 100 +#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT 200 +#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN 200 +#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX 10000 +#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT 20 +#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN 20 +#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX 10000 +#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT 25 +#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN 0 +#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX 100 +typedef struct wl_obss_scan_arg +{ + int16_t passive_dwell; + int16_t active_dwell; + int16_t bss_widthscan_interval; + int16_t passive_total; + int16_t active_total; + int16_t chanwidth_transition_delay; + int16_t activity_threshold; +} wl_obss_scan_arg_t; +#define WL_OBSS_SCAN_PARAM_LEN sizeof(wl_obss_scan_arg_t) +#define WL_MIN_NUM_OBSS_SCAN_ARG 7 +#define WL_COEX_INFO_MASK 0x07 +#define WL_COEX_INFO_REQ 0x01 +#define WL_COEX_40MHZ_INTOLERANT 0x02 +#define WL_COEX_WIDTH20 0x04 +typedef struct wl_action_obss_coex_req +{ + uint8_t info; + uint8_t num; + uint8_t ch_list[1]; +} wl_action_obss_coex_req_t; +#define MAX_RSSI_LEVELS 8 +typedef struct wl_rssi_event +{ + uint32_t rate_limit_msec; + uint8_t num_rssi_levels; + int8_t rssi_levels[MAX_RSSI_LEVELS]; +} wl_rssi_event_t; +#define WLFEATURE_DISABLE_11N 0x00000001 +#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 +#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 +#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 +#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 +#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 +#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 +#define WLFEATURE_DISABLE_11N_GF 0x00000080 + +#pragma pack(1) + +typedef struct sta_prbreq_wps_ie_hdr +{ + wl_ether_addr_t staAddr; + uint16_t ieLen; +} sta_prbreq_wps_ie_hdr_t; + +typedef struct sta_prbreq_wps_ie_data +{ + sta_prbreq_wps_ie_hdr_t hdr; + uint8_t ieData[1]; +} sta_prbreq_wps_ie_data_t; + +typedef struct sta_prbreq_wps_ie_list +{ + uint32_t totLen; + uint8_t ieDataList[1]; +} sta_prbreq_wps_ie_list_t; + +/* EDCF related items from 802.11.h */ + +/* ACI from 802.11.h */ +#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */ +#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */ +#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */ +#define EDCF_ACM_MASK 0x10 /* ACM mask */ +#define EDCF_ACI_MASK 0x60 /* ACI mask */ +#define EDCF_ACI_SHIFT 5 /* ACI shift */ +#define EDCF_AIFSN_SHIFT 12 /* 4 MSB(0xFFF) in ifs_ctl for AC idx */ + +/* ECW from 802.11.h */ +#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */ +#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */ +#define EDCF_ECW2CW(exp) ( (1 << (exp) ) - 1 ) +#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */ +#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */ +#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */ + +/* TXOP from 802.11.h */ +#define EDCF_TXOP_MIN 0 /* TXOP minimum value */ +#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */ +#define EDCF_TXOP2USEC(txop) ( (txop) << 5 ) + +#define EDCF_ACPARAM +struct edcf_acparam +{ + uint8_t ACI; + uint8_t ECW; + uint16_t TXOP; /* stored in network order (ls octet first) */ +}; +typedef struct edcf_acparam edcf_acparam_t; + +/* Stop packing structures */ +#pragma pack() + +/* discovery state */ +typedef struct wl_p2p_disc_st +{ + uint8_t state; /* see p2p_discovery_state_t */ + uint16_t chanspec; /* valid in listen state */ + uint16_t dwell_time_ms; /* valid in listen state, in ms */ +} wl_p2p_disc_st_t; + +/* scan request */ +typedef struct wl_p2p_scan +{ + uint8_t type; /* 'S' for WLC_SCAN, 'E' for "escan" */ + uint8_t reserved[3]; + /* scan or escan parms... */ +} wl_p2p_scan_t; + +/* escan request */ +typedef struct +{ + uint8_t type; /* 'S' for WLC_SCAN, 'E' for "escan" */ + uint8_t reserved[3]; + + /* escan params */ + wl_escan_params_t escan; +} wl_p2p_escan_t; + +/* i/f request */ +typedef struct wl_p2p_if +{ + struct ether_addr mac_address; + uint8_t interface_type; + uint16_t chan_spec; +} wl_p2p_if_t; + +/* i/f query */ +typedef struct wl_p2p_ifq +{ + uint32_t bsscfgidx; + char ifname[16]; +} wl_p2p_ifq_t; + +/* OppPS & CTWindow */ +typedef struct wl_p2p_ops +{ + uint8_t ops; /* 0: disable 1: enable */ + uint8_t ctw; /* >= 10 */ +} wl_p2p_ops_t; + +/* absence and presence request */ +typedef struct wl_p2p_sched_desc +{ + uint32_t start; + uint32_t interval; + uint32_t duration; + uint32_t count; /* see count */ +} wl_p2p_sched_desc_t; + +typedef struct wl_p2p_sched +{ + uint8_t type; /* see schedule type */ + uint8_t action; /* see schedule action */ + uint8_t option; /* see schedule option */ + wl_p2p_sched_desc_t desc[1]; +} wl_p2p_sched_t; + +/* schedule type */ +#define WL_P2P_SCHED_TYPE_ABS 0 /* Scheduled Absence */ +#define WL_P2P_SCHED_TYPE_REQ_ABS 1 /* Requested Absence */ +#define WL_P2P_SCHED_TYPE_REQ_PSC 2 /* Requested Presence */ + +/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */ +#define WL_P2P_SCHED_ACTION_NONE 0 /* no action */ +#define WL_P2P_SCHED_ACTION_DOZE 1 /* doze */ +#define WL_P2P_SCHED_ACTION_RESET 255 /* reset */ + +/* schedule option - WL_P2P_SCHED_TYPE_ABS */ +#define WL_P2P_SCHED_OPTION_NORMAL 0 /* normal start/interval/duration/count in time */ +#define WL_P2P_SCHED_OPTION_BCNPCT 1 /* percentage of beacon interval */ + +typedef struct wl_p2p_wfds_hash +{ + uint32_t advt_id; + uint16_t nw_cfg_method; + uint8_t wfds_hash[6]; + uint8_t name_len; + uint8_t service_name[MAX_WFDS_SVC_NAME_LEN]; +} wl_p2p_wfds_hash_t; + +#define P2P_IP_ALLOC_LEN 12 +/* Definitions for Reliable Multicast */ +/* NOTE: RMC structures should not be packed */ + +#define WL_RMC_CNT_VERSION (1) +#define WL_RMC_TR_VERSION (1) +#define WL_RMC_MAX_CLIENT (32) +#define WL_RMC_FLAG_INBLACKLIST (1) +#define WL_RMC_FLAG_ACTIVEACKER (2) +#define WL_RMC_FLAG_RELMCAST (4) +#define WL_RMC_FLAG_MASTER_TX (8) +#define WL_RMC_MAX_TABLE_ENTRY (8) + +#define WL_RMC_VER (1) +#define WL_RMC_INDEX_ACK_ALL (255) +#define WL_RMC_NUM_OF_MC_STREAMS (4) +#define WL_RMC_MAX_TRS_PER_GROUP (1) +#define WL_RMC_MAX_TRS_IN_ACKALL (1) +#define WL_RMC_ACK_MCAST0 (0x02) +#define WL_RMC_ACK_MCAST_ALL (0x01) +#define WL_RMC_ACTF_TIME_MIN (300) /* time in ms */ +#define WL_RMC_ACTF_TIME_MAX (20000) /* time in ms */ +#define WL_RMC_MAX_NUM_TRS (32) /* maximun transmitters allowed */ +#define WL_RMC_ARTMO_MIN (350) /* time in ms */ +#define WL_RMC_ARTMO_MAX (40000) /* time in ms */ + +enum rmc_opcodes +{ + RELMCAST_ENTRY_OP_DISABLE = 0, /* Disable multi-cast group */ + RELMCAST_ENTRY_OP_DELETE = 1, /* Delete multi-cast group */ + RELMCAST_ENTRY_OP_ENABLE = 2, /* Enable multi-cast group */ + RELMCAST_ENTRY_OP_ACK_ALL = 3 /* Enable ACK ALL bit in AMT */ +}; + +/* RMC operational modes */ +enum rmc_modes +{ + WL_RMC_MODE_RECEIVER = 0, /* Receiver mode by default */ + WL_RMC_MODE_TRANSMITTER = 1, /* Transmitter mode using wl ackreq */ + WL_RMC_MODE_INITIATOR = 2 /* Initiator mode using wl ackreq */ +}; + +/* Each RMC mcast client info */ +typedef struct wl_relmcast_client +{ + uint8_t flag; /* status of client such as AR, R, or blacklisted */ + int16_t rssi; /* rssi value of RMC client */ + struct ether_addr addr; /* mac address of RMC client */ +} wl_relmcast_client_t; + +/* RMC Counters */ +typedef struct wl_rmc_cnts +{ + uint16_t version; /* see definition of WL_CNT_T_VERSION */ + uint16_t length; /* length of entire structure */ + uint16_t dupcnt; /* counter for duplicate rmc MPDU */ + uint16_t ackreq_err; /* counter for wl ackreq error */ + uint16_t af_tx_err; /* error count for action frame transmit */ + uint16_t null_tx_err; /* error count for rmc null frame transmit */ + uint16_t af_unicast_tx_err; /* error count for rmc unicast frame transmit */ + uint16_t mc_no_amt_slot; /* No mcast AMT entry available */ + /* Unused. Keep for rom compatibility */ + uint16_t mc_no_glb_slot; /* No mcast entry available in global table */ + uint16_t mc_not_mirrored; /* mcast group is not mirrored */ + uint16_t mc_existing_tr; /* mcast group is already taken by transmitter */ + uint16_t mc_exist_in_amt; /* mcast group is already programmed in amt */ + /* Unused. Keep for rom compatibility */ + uint16_t mc_not_exist_in_gbl; /* mcast group is not in global table */ + uint16_t mc_not_exist_in_amt; /* mcast group is not in AMT table */ + uint16_t mc_utilized; /* mcast addressed is already taken */ + uint16_t mc_taken_other_tr; /* multi-cast addressed is already taken */ + uint32_t rmc_rx_frames_mac; /* no of mc frames received from mac */ + uint32_t rmc_tx_frames_mac; /* no of mc frames transmitted to mac */ + uint32_t mc_null_ar_cnt; /* no. of times NULL AR is received */ + uint32_t mc_ar_role_selected; /* no. of times took AR role */ + uint32_t mc_ar_role_deleted; /* no. of times AR role cancelled */ + uint32_t mc_noacktimer_expired; /* no. of times noack timer expired */ + uint16_t mc_no_wl_clk; /* no wl clk detected when trying to access amt */ + uint16_t mc_tr_cnt_exceeded; /* No of transmitters in the network exceeded */ +} wl_rmc_cnts_t; + +/* RMC Status */ +typedef struct wl_relmcast_st +{ + uint8_t ver; /* version of RMC */ + uint8_t num; /* number of clients detected by transmitter */ + wl_relmcast_client_t clients[WL_RMC_MAX_CLIENT]; + uint16_t err; /* error status (used in infra) */ + uint16_t actf_time; /* action frame time period */ +} wl_relmcast_status_t; + +/* Entry for each STA/node */ +typedef struct wl_rmc_entry +{ + /* operation on multi-cast entry such add, + * delete, ack-all + */ + int8_t flag; + struct ether_addr addr; /* multi-cast group mac address */ +} wl_rmc_entry_t; + +/* RMC table */ +typedef struct wl_rmc_entry_table +{ + uint8_t index; /* index to a particular mac entry in table */ + uint8_t opcode; /* opcodes or operation on entry */ + wl_rmc_entry_t entry[WL_RMC_MAX_TABLE_ENTRY]; +} wl_rmc_entry_table_t; + +typedef struct wl_rmc_trans_elem +{ + struct ether_addr tr_mac; /* transmitter mac */ + struct ether_addr ar_mac; /* ar mac */ + uint16_t artmo; /* AR timeout */ + uint8_t amt_idx; /* amt table entry */ + uint16_t flag; /* entry will be acked, not acked, programmed, full etc */ +} wl_rmc_trans_elem_t; + +/* RMC transmitters */ +typedef struct wl_rmc_trans_in_network +{ + uint8_t ver; /* version of RMC */ + uint8_t num_tr; /* number of transmitters in the network */ + wl_rmc_trans_elem_t trs[WL_RMC_MAX_NUM_TRS]; +} wl_rmc_trans_in_network_t; + +/* To update vendor specific ie for RMC */ +typedef struct wl_rmc_vsie +{ + uint8_t oui[3]; + uint16_t payload; /* IE Data Payload */ +} wl_rmc_vsie_t; + +/* WLC_E_ULP event data */ +#define WL_ULP_EVENT_VERSION 1 +#define WL_ULP_DISABLE_CONSOLE 1 /* Disable console message on ULP entry */ +#define WL_ULP_UCODE_DOWNLOAD 2 /* Download ULP ucode file */ +#define WL_ULP_ENTRY 3 /* inform ulp entry to Host during warmboot */ + +typedef struct wl_ulp_event +{ + uint16_t version; + uint16_t ulp_dongle_action; +} wl_ulp_event_t; + +/* clm download */ +#define DLOAD_HANDLER_VER 1 /* Downloader version */ +#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */ +#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */ + +#define DL_CRC_NOT_INUSE 0x0001 +#define DL_BEGIN 0x0002 +#define DL_END 0x0004 + +enum +{ + DL_TYPE_UCODE = 1, DL_TYPE_CLM = 2 +}; + +struct wl_dload_data +{ + uint16_t flag; + uint16_t dload_type; + uint32_t len; + uint32_t crc; + uint8_t data[1]; +}; +typedef struct wl_dload_data wl_dload_data_t; + +struct wl_clm_dload_info +{ + uint32_t ds_id; + uint32_t clm_total_len; + uint32_t num_chunks; + uint32_t chunk_len; + uint32_t chunk_offset; + uint8_t data_chunk[1]; +}; +typedef struct wl_clm_dload_info wl_clm_dload_info_t; + +#pragma pack(1) +typedef struct mesh_peer_info +{ + uint16_t mesh_peer_prot_id; + uint16_t local_link_id; + uint16_t peer_link_id; + uint16_t peer_aid; + uint8_t state; +} mesh_peer_info_t; + +typedef struct mesh_peer_info_ext +{ + mesh_peer_info_t peer_info; + uint16_t local_aid; + struct ether_addr ea; + uint32_t entry_state; + int32_t rssi; +} mesh_peer_info_ext_t; + +typedef struct mesh_peer_info_dump +{ + uint32_t buflen; + uint32_t version; + uint32_t count; /* number of results */ + mesh_peer_info_ext_t mpi_ext[1]; +} mesh_peer_info_dump_t; + +#define WL_CHANSPEC_CTL_SB_LLL 0x0000 +#define WL_CHANSPEC_CTL_SB_LLU 0x0100 +#define WL_CHANSPEC_CTL_SB_LUL 0x0200 +#define WL_CHANSPEC_CTL_SB_LUU 0x0300 +#define WL_CHANSPEC_CTL_SB_ULL 0x0400 +#define WL_CHANSPEC_CTL_SB_ULU 0x0500 +#define WL_CHANSPEC_CTL_SB_UUL 0x0600 +#define WL_CHANSPEC_CTL_SB_UUU 0x0700 +#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL +#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU +#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL +#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU +#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL +#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU +#define INVCHANSPEC 255 +#define WL_CHANSPEC_CTL_SB_SHIFT 8 +#define WL_CHANSPEC_BW_5 0x0000 +#define WL_CHANSPEC_BW_80 0x2000 +#define WL_CHANSPEC_BW_160 0x2800 +#define WL_CHANSPEC_BW_8080 0x3000 + +struct ether_addr; +struct wl_join_scan_params; + +typedef struct wl_assoc_params +{ + struct ether_addr bssid; + uint16_t bssid_cnt; + uint32_t chanspec_num; + chanspec_t chanspec_list[1]; +} wl_assoc_params_t; +#define WL_ASSOC_PARAMS_FIXED_SIZE (sizeof(wl_assoc_params_t) - sizeof(wl_chanspec_t) ) +typedef wl_assoc_params_t wl_reassoc_params_t; +#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE +typedef wl_assoc_params_t wl_join_assoc_params_t; +#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE +typedef struct wl_join_params +{ + wlc_ssid_t ssid; + struct wl_assoc_params params; +} wl_join_params_t; +#define WL_JOIN_PARAMS_FIXED_SIZE (sizeof(wl_join_params_t) - sizeof(wl_chanspec_t) ) + +/* extended join params */ +typedef struct wl_extjoin_params +{ + wlc_ssid_t ssid; /* {0, ""}: wildcard scan */ + struct wl_join_scan_params scan_params; + wl_join_assoc_params_t assoc_params; /* optional field, but it must include the fixed portion + * of the wl_join_assoc_params_t struct when it does + * present. + */ +} wl_extjoin_params_t; +#define WL_EXTJOIN_PARAMS_FIXED_SIZE (sizeof(wl_extjoin_params_t) - sizeof(chanspec_t) ) + +#define WLC_SET_CUSTOM_COUNTRY ( (uint32_t)320 ) + +/* WLC_GET_AUTH, WLC_SET_AUTH values */ +#define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ +#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ +#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ +#define WL_AUTH_SAE 3 /* Simultaneous Authentication of Equals (SAE) */ + +/** ARP offload statistics */ +struct whd_arp_stats_s +{ + uint32_t version; /**< WLAN version */ + uint32_t peerage; /**< Current peer age-out time */ + uint32_t arpoe; /**< Agent enabled state */ + uint32_t features_enabled; /**< ARP Feature Flags @ref CY_ARP_OL_AGENT_ENABLE, etc. */ + arp_ol_stats_t stats; /**< Current stats */ + uint32_t host_ip_list[ARP_MULTIHOMING_MAX]; /**< host_ip addresses in one call */ +}; + +#pragma pack() + +/* TCP Keepalive offload related defintions should not be added inside + * pragma pack to avoid functionality breakage. + */ +/* + * TCP keepalive offload definitions + */ +#define MAX_TKO_CONN 4 +#define IPV4_ADDR_LEN 4 /* IPV4 address length */ + +/* Default TCP Keepalive retry parameters. */ +#define TCP_KEEPALIVE_OFFLOAD_INTERVAL_SEC (20) +#define TCP_KEEPALIVE_OFFLOAD_RETRY_COUNT (3) +#define TCP_KEEPALIVE_OFFLOAD_RETRY_INTERVAL_SEC (3) + +/* common iovar struct */ +typedef struct wl_tko +{ + uint16_t subcmd_id; /* subcommand id */ + uint16_t len; /* total length of data[] */ + uint8_t data[1]; /* subcommand data */ +} wl_tko_t; + +/* subcommand ids */ +#define WL_TKO_SUBCMD_MAX_TCP 0 /* max TCP connections supported */ +#define WL_TKO_SUBCMD_PARAM 1 /* configure offload common parameters */ +#define WL_TKO_SUBCMD_CONNECT 2 /* TCP connection info */ +#define WL_TKO_SUBCMD_ENABLE 3 /* enable/disable */ +#define WL_TKO_SUBCMD_STATUS 4 /* TCP connection status */ + +/* WL_TKO_SUBCMD_MAX_CONNECT subcommand data */ +typedef struct wl_tko_max_tcp +{ + uint8_t max; /* max TCP connections supported */ + uint8_t pad[3]; /* 4-byte struct alignment */ +} wl_tko_max_tcp_t; + +/* WL_TKO_SUBCMD_PARAM subcommand data */ +typedef struct wl_tko_param +{ + uint16_t interval; /* keepalive tx interval (secs) */ + uint16_t retry_interval; /* keepalive retry interval (secs) */ + uint16_t retry_count; /* retry_count */ + uint8_t pad[2]; /* 4-byte struct alignment */ +} wl_tko_param_t; + +/* WL_TKO_SUBCMD_CONNECT subcommand data + * invoke with unique 'index' for each TCP connection + */ +typedef struct wl_tko_connect +{ + uint8_t index; /* TCP connection index, 0 to max-1 */ + uint8_t ip_addr_type; /* 0 - IPv4, 1 - IPv6 */ + uint16_t local_port; /* local port */ + uint16_t remote_port; /* remote port */ + uint32_t local_seq; /* local sequence number */ + uint32_t remote_seq; /* remote sequence number */ + uint16_t request_len; /* TCP keepalive request packet length */ + uint16_t response_len; /* TCP keepalive response packet length */ + uint8_t data[1]; /* variable length field containing local/remote IPv4/IPv6, + * TCP keepalive request packet, TCP keepalive response packet + * For IPv4, length is 4 * 2 + request_length + response_length + * offset 0 - local IPv4 + * offset 4 - remote IPv4 + * offset 8 - TCP keepalive request packet + * offset 8+request_length - TCP keepalive response packet + * For IPv6, length is 16 * 2 + request_length + response_length + * offset 0 - local IPv6 + * offset 16 - remote IPv6 + * offset 32 - TCP keepalive request packet + * offset 32+request_length - TCP keepalive response packet + */ +} wl_tko_connect_t; + +/* WL_TKO_SUBCMD_CONNECT subcommand data to GET configured info for specific index */ +typedef struct wl_tko_get_connect +{ + uint8_t index; /* TCP connection index, 0 to max-1 */ + uint8_t pad[3]; /* 4-byte struct alignment */ +} wl_tko_get_connect_t; + +typedef struct wl_tko_enable +{ + uint8_t enable; /* 1 - enable, 0 - disable */ + uint8_t pad[3]; /* 4-byte struct alignment */ +} wl_tko_enable_t; + +/* WL_TKO_SUBCMD_STATUS subcommand data */ +/* must be invoked before tko is disabled else status is unavailable */ +typedef struct wl_tko_status +{ + uint8_t count; /* number of status entries (i.e. equals + * max TCP connections supported) + */ + uint8_t status[1]; /* variable length field contain status for + * each TCP connection index + */ +} wl_tko_status_t; +/** Get/Set TKO intervals & retrys */ +struct whd_tko_retry +{ + uint16_t tko_interval; /**< How often to send (in seconds) */ + uint16_t tko_retry_count; /**< Max times to retry if original fails */ + uint16_t tko_retry_interval; /**< Wait time between retries (in seconds) */ +}; + +/** Status values used in conjunction with whd_tko_status_t */ +typedef enum +{ + TKO_STATUS_NORMAL = 0, /**< TCP connection normal, no error */ + TKO_STATUS_NO_RESPONSE = 1, /**< no response to TCP keepalive */ + TKO_STATUS_NO_TCP_ACK_FLAG = 2, /**< TCP ACK flag not set */ + TKO_STATUS_UNEXPECT_TCP_FLAG = 3, /**< unexpect TCP flags set other than ACK */ + TKO_STATUS_SEQ_NUM_INVALID = 4, /**< ACK != sequence number */ + TKO_STATUS_REMOTE_SEQ_NUM_INVALID = 5, /**< SEQ > remote sequence number */ + TKO_STATUS_TCP_DATA = 6, /**< TCP data available */ + TKO_STATUS_UNAVAILABLE = 255, /**< not used/configured */ +} tko_status_t; + +/** Status of each TCP connection */ +struct whd_tko_status +{ + uint8_t count; /**< number of status entries */ + uint8_t status[MAX_TKO_CONN]; /**< each TCP status */ +}; + +/** Struct to query FW for current TKO configuation */ +struct whd_tko_connect +{ + uint8_t index; /**< TCP connection index, 0 to max-1 */ + uint8_t ip_addr_type; /**< 0 - IPv4, 1 - IPv6 */ + uint16_t local_port; /**< local port */ + uint16_t remote_port; /**< remote port */ + uint32_t local_seq; /**< local sequence number */ + uint32_t remote_seq; /**< remote sequence number */ + uint16_t request_len; /**< TCP keepalive request packet length */ + uint16_t response_len; /**< TCP keepalive response packet length */ + uint8_t data[1]; /**< variable length field containing local/remote IPv4/IPv6, + * TCP keepalive request packet, TCP keepalive response packet + * For IPv4, length is 4 * 2 + request_length + response_length + * offset 0 - local IPv4 + * offset 4 - remote IPv4 + * offset 8 - TCP keepalive request packet + * offset 8+request_length - TCP keepalive response packet + * For IPv6, length is 16 * 2 + request_length + response_length + * offset 0 - local IPv6 + * offset 16 - remote IPv6 + * offset 32 - TCP keepalive request packet + * offset 32+request_length - TCP keepalive response packet + */ +}; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_ap.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_ap.c new file mode 100644 index 00000000..4258a36f --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_ap.c @@ -0,0 +1,715 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides generic APSTA functionality that chip specific files use + */ +#include "whd_debug.h" +#include "whd_ap.h" +#include "bus_protocols/whd_chip_reg.h" +#include "whd_chip_constants.h" +#include "whd_chip.h" +#include "whd_sdpcm.h" +#include "whd_thread_internal.h" +#include "whd_events_int.h" +#include "whd_int.h" +#include "whd_utils.h" +#include "whd_wifi_api.h" +#include "whd_buffer_api.h" +#include "whd_wlioctl.h" + +/****************************************************** +** @cond Constants +*******************************************************/ + +#define WLC_EVENT_MSG_LINK (0x01) +#define RATE_SETTING_11_MBPS (11000000 / 500000) +#define AMPDU_AP_DEFAULT_BA_WSIZE 8 +#define AMPDU_STA_DEFAULT_BA_WSIZE 8 +#define AMPDU_STA_DEFAULT_MPDU 4 /* STA default num MPDU per AMPDU */ +#define PWE_LOOP_COUNT 5 +/****************************************************** +** Enumerations +*******************************************************/ +typedef enum +{ + BSS_AP = 3, + BSS_STA = 2, + BSS_UP = 1, + BSS_DOWN = 0 +} bss_arg_option_t; + +/****************************************************** + * * Function Declarations + * ******************************************************/ +static void *whd_handle_apsta_event(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data); + +/****************************************************** + * Variables Definitions + *****************************************************/ +static const whd_event_num_t apsta_events[] = { WLC_E_IF, WLC_E_LINK, WLC_E_NONE }; +/****************************************************** +* Function Definitions +******************************************************/ + +void whd_ap_info_init(whd_driver_t whd_driver) +{ + whd_driver->ap_info.ap_is_up = WHD_FALSE; + whd_driver->ap_info.is_waiting_event = WHD_FALSE; +} + +void whd_wifi_set_ap_is_up(whd_driver_t whd_driver, whd_bool_t new_state) +{ + if (whd_driver->ap_info.ap_is_up != new_state) + { + whd_driver->ap_info.ap_is_up = new_state; + } +} + +whd_bool_t whd_wifi_get_ap_is_up(whd_driver_t whd_driver) +{ + return whd_driver->ap_info.ap_is_up; +} + +whd_result_t whd_wifi_set_block_ack_window_size_common(whd_interface_t ifp, uint16_t ap_win_size, uint16_t sta_win_size) +{ + whd_result_t retval; + uint16_t block_ack_window_size = ap_win_size; + + /* If the AP interface is already up then don't change the Block Ack window size */ + if (ifp->role == WHD_AP_ROLE) + { + return WHD_SUCCESS; + } + + if (ifp->role == WHD_STA_ROLE) + { + block_ack_window_size = sta_win_size; + } + + retval = whd_wifi_set_iovar_value(ifp, IOVAR_STR_AMPDU_BA_WINDOW_SIZE, ( uint32_t )block_ack_window_size); + + whd_assert("set_block_ack_window_size: Failed to set block ack window size\r\n", retval == WHD_SUCCESS); + + return retval; +} + +whd_result_t whd_wifi_set_ampdu_parameters_common(whd_interface_t ifp, uint8_t ba_window_size, int8_t ampdu_mpdu, + uint8_t rx_factor) +{ + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_AMPDU_BA_WINDOW_SIZE, ba_window_size) ); + + /* Set number of MPDUs available for AMPDU */ + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_AMPDU_MPDU, ( uint32_t )ampdu_mpdu) ); + + if (rx_factor != AMPDU_RX_FACTOR_INVALID) + { + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_AMPDU_RX_FACTOR, rx_factor) ); + } + return WHD_SUCCESS; +} + +/** Sets the chip specific AMPDU parameters for AP and STA + * For SDK 3.0, and beyond, each chip will need it's own function for setting AMPDU parameters. + */ +whd_result_t whd_wifi_set_ampdu_parameters(whd_interface_t ifp) +{ + whd_driver_t whd_driver = ifp->whd_driver; + /* Get the chip number */ + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + + if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) ) + { + return whd_wifi_set_ampdu_parameters_common(ifp, AMPDU_STA_DEFAULT_BA_WSIZE, AMPDU_MPDU_AUTO, + AMPDU_RX_FACTOR_64K); + } + else if ( (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) ) + { + return whd_wifi_set_ampdu_parameters_common(ifp, AMPDU_STA_DEFAULT_BA_WSIZE, AMPDU_MPDU_AUTO, + AMPDU_RX_FACTOR_INVALID); + } + else + { + return whd_wifi_set_ampdu_parameters_common(ifp, AMPDU_STA_DEFAULT_BA_WSIZE, AMPDU_STA_DEFAULT_MPDU, + AMPDU_RX_FACTOR_8K); + } +} + +/* All chips */ +static void *whd_handle_apsta_event(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data) +{ + whd_driver_t whd_driver = ifp->whd_driver; + whd_ap_int_info_t *ap; + + UNUSED_PARAMETER(event_header); + UNUSED_PARAMETER(event_data); + UNUSED_PARAMETER(handler_user_data); + + ap = &whd_driver->ap_info; + + if (ap->is_waiting_event == WHD_TRUE) + { + if ( (event_header->event_type == (whd_event_num_t)WLC_E_LINK) || + (event_header->event_type == WLC_E_IF) ) + { + whd_result_t result; + result = cy_rtos_set_semaphore(&ap->whd_wifi_sleep_flag, WHD_FALSE); + WPRINT_WHD_DEBUG( ("%s failed to post AP link semaphore at %d\n", __func__, __LINE__) ); + REFERENCE_DEBUG_ONLY_VARIABLE(result); + } + } + return handler_user_data; +} + +/* All chips */ +uint32_t whd_wifi_init_ap(whd_interface_t ifp, whd_ssid_t *ssid, whd_security_t auth_type, + const uint8_t *security_key, uint8_t key_length, uint8_t channel) +{ + whd_driver_t whd_driver; + whd_bool_t wait_for_interface = WHD_FALSE; + whd_result_t result; + whd_buffer_t response; + whd_buffer_t buffer; + whd_interface_t prim_ifp; + whd_ap_int_info_t *ap; + uint32_t *data; + uint32_t bss_index; + uint16_t wlan_chip_id; + uint32_t auth_mfp = WL_MFP_NONE; + uint16_t event_entry = (uint16_t)0xFF; + + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* Get the Chip Number */ + wlan_chip_id = whd_chip_get_chip_id(whd_driver); + + if ( (auth_type & WEP_ENABLED) != 0 ) + { + WPRINT_WHD_ERROR( ("WEP auth type is not allowed , %s failed at line %d \n", __func__, __LINE__) ); + return WHD_WEP_NOT_ALLOWED; + } + + if ( (auth_type & WPA3_SECURITY) && + ( (wlan_chip_id == 43430) || (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) || + (wlan_chip_id == 43012) ) ) + { + WPRINT_WHD_ERROR( ("WPA3 is not supported, %s failed at line %d \n", __func__, __LINE__) ); + return WHD_UNSUPPORTED; + } + + ap = &whd_driver->ap_info; + + prim_ifp = whd_get_primary_interface(whd_driver); + if (prim_ifp == NULL) + { + WPRINT_WHD_ERROR( ("%s failed at %d \n", __func__, __LINE__) ); + return WHD_UNKNOWN_INTERFACE; + } + + if (ssid->length > (size_t)SSID_NAME_SIZE) + { + WPRINT_WHD_ERROR( ("%s: failure: SSID length(%u) error\n", __func__, ssid->length) ); + return WHD_WLAN_BADSSIDLEN; + } + + /* Turn off APSTA when creating AP mode on primary interface */ + if (ifp == prim_ifp) + { + CHECK_RETURN(whd_wifi_set_ioctl_buffer(prim_ifp, WLC_DOWN, NULL, 0) ); + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_APSTA); + CHECK_IOCTL_BUFFER(data); + *data = 0; + result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + if ( (result != WHD_SUCCESS) && (result != WHD_WLAN_UNSUPPORTED) ) + { + WPRINT_WHD_ERROR( ("Could not turn off apsta\n") ); + return result; + } + CHECK_RETURN(whd_wifi_set_ioctl_buffer(prim_ifp, WLC_UP, NULL, 0) ); + } + + bss_index = ifp->bsscfgidx; + + ifp->role = WHD_AP_ROLE; + + if ( ( (auth_type == WHD_SECURITY_WPA_TKIP_PSK) || (auth_type == WHD_SECURITY_WPA2_AES_PSK) || + (auth_type == WHD_SECURITY_WPA2_MIXED_PSK) ) && + ( (key_length < (uint8_t)WSEC_MIN_PSK_LEN) || (key_length > (uint8_t)WSEC_MAX_PSK_LEN) ) ) + { + WPRINT_WHD_ERROR( ("Error: WPA security key length must be between %d and %d\n", WSEC_MIN_PSK_LEN, + WSEC_MAX_PSK_LEN) ); + return WHD_WPA_KEYLEN_BAD; + } + + if ( (whd_wifi_get_ap_is_up(whd_driver) == WHD_TRUE) ) + { + WPRINT_WHD_ERROR( ("Error: Soft AP or Wi-Fi Direct group owner already up\n") ); + return WHD_AP_ALREADY_UP; + } + + /* Query bss state (does it exist? if so is it UP?) */ + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_BSS); + CHECK_IOCTL_BUFFER(data); + + if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *data = htod32( (uint32_t)CHIP_AP_INTERFACE ); + } + else + { + *data = htod32( (uint32_t)bss_index ); + } + + if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + if (whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) != WHD_SUCCESS) + { + /* Note: We don't need to release the response packet since the iovar failed */ + wait_for_interface = WHD_TRUE; + } + else + { + /* Check if the BSS is already UP, if so return */ + uint32_t *data2 = (uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(data2, WHD_NO_REGISTER_FUNCTION_POINTER); + *data2 = dtoh32 (*data2); + if (*data2 == (uint32_t)BSS_UP) + { + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + whd_wifi_set_ap_is_up(whd_driver, WHD_TRUE); + ap->is_waiting_event = WHD_FALSE; + return WHD_SUCCESS; + } + else + { + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + } + } + } + + if (whd_cdc_send_iovar(prim_ifp, CDC_GET, buffer, &response) != WHD_SUCCESS) + { + /* Note: We don't need to release the response packet since the iovar failed */ + wait_for_interface = WHD_TRUE; + } + else + { + /* Check if the BSS is already UP, if so return */ + uint32_t *data2 = (uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(data2, WHD_NO_REGISTER_FUNCTION_POINTER); + *data2 = dtoh32 (*data2); + if (*data2 == (uint32_t)BSS_UP) + { + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + whd_wifi_set_ap_is_up(whd_driver, WHD_TRUE); + ap->is_waiting_event = WHD_FALSE; + return WHD_SUCCESS; + } + else + { + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + } + } + + CHECK_RETURN(cy_rtos_init_semaphore(&ap->whd_wifi_sleep_flag, 1, 0) ); + + ap->is_waiting_event = WHD_TRUE; + /* Register for interested events */ + CHECK_RETURN_WITH_SEMAPHORE(whd_management_set_event_handler(ifp, apsta_events, whd_handle_apsta_event, + NULL, &event_entry), &ap->whd_wifi_sleep_flag); + if (event_entry >= WHD_EVENT_HANDLER_LIST_SIZE) + { + WPRINT_WHD_DEBUG( ("Event handler registration failed for AP events in function %s and line %d\n", + __func__, __LINE__) ); + return WHD_UNFINISHED; + } + ifp->event_reg_list[WHD_AP_EVENT_ENTRY] = event_entry; + + if (wait_for_interface == WHD_TRUE) + { + CHECK_RETURN_WITH_SEMAPHORE(cy_rtos_get_semaphore(&ap->whd_wifi_sleep_flag, (uint32_t)10000, + WHD_FALSE), &ap->whd_wifi_sleep_flag); + } + ap->is_waiting_event = WHD_FALSE; + + if (prim_ifp == ifp) + { + /* Set AP mode */ + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4); + CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag); + *data = 1; /* Turn on AP */ + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_AP, buffer, 0), + &ap->whd_wifi_sleep_flag); + } + + if (NULL_MAC(ifp->mac_addr.octet) ) + { + /* Change the AP MAC address to be different from STA MAC */ + if ( (result = whd_wifi_get_mac_address(prim_ifp, &ifp->mac_addr) ) != WHD_SUCCESS ) + { + WPRINT_WHD_INFO ( (" Get STA MAC address failed result=%" PRIu32 "\n", result) ); + return result; + } + else + { + WPRINT_WHD_INFO ( (" Get STA MAC address success\n") ); + } + } + + if ( (result = whd_wifi_set_mac_address(ifp, ifp->mac_addr) ) != WHD_SUCCESS ) + { + WPRINT_WHD_INFO ( (" Set AP MAC address failed result=%" PRIu32 "\n", result) ); + return result; + } + + /* Set the SSID */ + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)40, "bsscfg:" IOVAR_STR_SSID); + CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag); + if (wlan_chip_id == 4334) + { + data[0] = htod32( (uint32_t)CHIP_AP_INTERFACE ); /* Set the bsscfg index */ + } + else + { + data[0] = htod32(bss_index); /* Set the bsscfg index */ + } + data[1] = htod32(ssid->length); /* Set the ssid length */ + memcpy(&data[2], (uint8_t *)ssid->value, ssid->length); + if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag); + } + else + { + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag); + } + + /* Set the channel */ + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4); + CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag); + *data = htod32(channel); + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_CHANNEL, buffer, 0), + &ap->whd_wifi_sleep_flag); + + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_WSEC); + CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag); + if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + data[0] = htod32( (uint32_t)CHIP_AP_INTERFACE ); + } + else + { + data[0] = htod32(bss_index); + } + if ( (auth_type & WPS_ENABLED) != 0 ) + { + data[1] = htod32( (uint32_t)( (auth_type & (~WPS_ENABLED) ) | SES_OW_ENABLED ) ); + } + else + { + data[1] = htod32( (uint32_t)auth_type & 0xFF ); + } + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag); + if (auth_type == WHD_SECURITY_WPA3_SAE) + { + auth_mfp = WL_MFP_REQUIRED; + + } + else if (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) + { + auth_mfp = WL_MFP_CAPABLE; + } + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_MFP, auth_mfp) ); + + if (wlan_chip_id == 4334) + { + if (auth_type != WHD_SECURITY_OPEN) + { + wsec_pmk_t *psk; + + /* Set the wpa auth */ + data = + (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_WPA_AUTH); + CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag); + data[0] = htod32( (uint32_t)CHIP_AP_INTERFACE ); + data[1] = htod32( (uint32_t)(auth_type == WHD_SECURITY_WPA_TKIP_PSK) ? + (WPA_AUTH_PSK) : (WPA2_AUTH_PSK | WPA_AUTH_PSK) ); + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag); + + /* Set the passphrase */ + psk = (wsec_pmk_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wsec_pmk_t) ); + CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(psk, &ap->whd_wifi_sleep_flag); + memcpy(psk->key, security_key, key_length); + psk->key_len = htod16(key_length); + psk->flags = htod16( (uint16_t)WSEC_PASSPHRASE ); + CHECK_RETURN(cy_rtos_delay_milliseconds(1) ); + /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */ + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WSEC_PMK, buffer, 0), + &ap->whd_wifi_sleep_flag); + } + } + else + { + if (auth_type != WHD_SECURITY_OPEN) + { + wsec_pmk_t *psk; + + /* Set the wpa auth */ + data = + (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_WPA_AUTH); + CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag); + if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + data[0] = htod32( (uint32_t)CHIP_AP_INTERFACE ); + } + else + { + data[0] = htod32(bss_index); + } + if ( (auth_type == WHD_SECURITY_WPA3_SAE) || (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) ) + { + data[1] = + htod32( (uint32_t)( (auth_type == + WHD_SECURITY_WPA3_SAE) ? (WPA3_AUTH_SAE_PSK) : (WPA3_AUTH_SAE_PSK | + WPA2_AUTH_PSK) ) ); + } + else + { + data[1] = + htod32( (uint32_t)(auth_type == + WHD_SECURITY_WPA_TKIP_PSK) ? (WPA_AUTH_PSK) : (WPA2_AUTH_PSK | WPA_AUTH_PSK) ); + } + if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag); + } + else + { + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0), + &ap->whd_wifi_sleep_flag); + } + if ( (auth_type == WHD_SECURITY_WPA3_SAE) && (whd_driver->chip_info.fwcap_flags & (1 << WHD_FWCAP_SAE) ) ) + { + whd_wifi_sae_password(ifp, security_key, key_length); + } + else + { + if ( (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) && + (whd_driver->chip_info.fwcap_flags & (1 << WHD_FWCAP_SAE) ) ) + { + whd_wifi_sae_password(ifp, security_key, key_length); + } + /* Set the passphrase */ + psk = (wsec_pmk_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wsec_pmk_t) ); + CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(psk, &ap->whd_wifi_sleep_flag); + memcpy(psk->key, security_key, key_length); + psk->key_len = htod16(key_length); + psk->flags = htod16( (uint16_t)WSEC_PASSPHRASE ); + CHECK_RETURN(cy_rtos_delay_milliseconds(1) ); + /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */ + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WSEC_PMK, buffer, + 0), &ap->whd_wifi_sleep_flag); + } + } + } + + /* Adjust PWE Loop Count(WPA3-R1 Compatibility Issue) */ + if (auth_type & WPA3_SECURITY) + { + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_SAE_PWE_LOOP); + CHECK_IOCTL_BUFFER(data); + *data = htod32( (uint32_t)PWE_LOOP_COUNT ); + if (whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) != WHD_SUCCESS) + { + WPRINT_WHD_DEBUG( ("Some chipsets might not support PWE_LOOP_CNT..Ignore result\n") ); + } + } + + /* Set the multicast transmission rate to 11 Mbps rather than the default 1 Mbps */ + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_2G_MULTICAST_RATE); + CHECK_IOCTL_BUFFER(data); + *data = htod32( (uint32_t)RATE_SETTING_11_MBPS ); + if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL); + whd_assert("start_ap: Failed to set multicast transmission rate\r\n", result == WHD_SUCCESS); + } + else + { + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL), &ap->whd_wifi_sleep_flag); + } + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_start_ap(whd_interface_t ifp) +{ + whd_buffer_t buffer; + uint32_t *data; + whd_ap_int_info_t *ap; + whd_interface_t prim_ifp; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + prim_ifp = whd_get_primary_interface(whd_driver); + + if (prim_ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + ap = &whd_driver->ap_info; + ap->is_waiting_event = WHD_TRUE; + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, IOVAR_STR_BSS); + CHECK_IOCTL_BUFFER_WITH_SEMAPHORE(data, &ap->whd_wifi_sleep_flag); + data[0] = htod32(ifp->bsscfgidx); + data[1] = htod32( (uint32_t)BSS_UP ); + CHECK_RETURN_WITH_SEMAPHORE(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0), &ap->whd_wifi_sleep_flag); + + /* Wait until AP is brought up */ + CHECK_RETURN_WITH_SEMAPHORE(cy_rtos_get_semaphore(&ap->whd_wifi_sleep_flag, (uint32_t)10000, + WHD_FALSE), &ap->whd_wifi_sleep_flag); + ap->is_waiting_event = WHD_FALSE; + + whd_wifi_set_ap_is_up(whd_driver, WHD_TRUE); + return WHD_SUCCESS; +} + +uint32_t whd_wifi_stop_ap(whd_interface_t ifp) +{ + uint32_t *data; + whd_buffer_t buffer; + whd_buffer_t response; + whd_result_t result; + whd_result_t result2; + whd_interface_t prim_ifp; + whd_driver_t whd_driver; + whd_ap_int_info_t *ap; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + ap = &whd_driver->ap_info; + + prim_ifp = whd_get_primary_interface(whd_driver); + + if (prim_ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + /* Get Chip Number */ + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + /* Query bss state (does it exist? if so is it UP?) */ + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_BSS); + CHECK_IOCTL_BUFFER(data); + *data = ifp->bsscfgidx; + + result = whd_cdc_send_iovar(prim_ifp, CDC_GET, buffer, &response); + if (result == WHD_WLAN_NOTFOUND) + { + /* AP interface does not exist - i.e. it is down */ + whd_wifi_set_ap_is_up(whd_driver, WHD_FALSE); + return WHD_SUCCESS; + } + + CHECK_RETURN(result); + + *data = dtoh32(*(uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response) ); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + if (data[0] != (uint32_t)BSS_UP) + { + /* AP interface indicates it is not up - i.e. it is down */ + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + whd_wifi_set_ap_is_up(whd_driver, WHD_FALSE); + return WHD_SUCCESS; + } + + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + ap->is_waiting_event = WHD_TRUE; + /* set BSS down */ + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, IOVAR_STR_BSS); + CHECK_IOCTL_BUFFER(data); + data[0] = htod32(ifp->bsscfgidx); + data[1] = htod32( (uint32_t)BSS_DOWN ); + CHECK_RETURN(whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0) ); + + /* Wait until AP is brought down */ + result = cy_rtos_get_semaphore(&ap->whd_wifi_sleep_flag, (uint32_t)10000, WHD_FALSE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error getting a semaphore, %s failed at %d \n", __func__, __LINE__) ); + goto sema_fail; + } + + /* Disable AP mode only if AP is on primary interface */ + if (prim_ifp == ifp) + { + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4); + CHECK_IOCTL_BUFFER(data); + *data = 0; + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_AP, buffer, 0) ); + if ( (wlan_chip_id != 43430) && (wlan_chip_id != 43439) && + (wlan_chip_id != 43909) && (wlan_chip_id != 43907) && + (wlan_chip_id != 54907) ) + { + result = cy_rtos_get_semaphore(&ap->whd_wifi_sleep_flag, (uint32_t)10000, WHD_FALSE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error getting a semaphore, %s failed at %d \n", __func__, __LINE__) ); + goto sema_fail; + } + } + } + +sema_fail: + ap->is_waiting_event = WHD_FALSE; + result2 = cy_rtos_deinit_semaphore(&ap->whd_wifi_sleep_flag); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error getting a semaphore, %s failed at %d \n", __func__, __LINE__) ); + return result; + } + if (result2 != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error deleting semaphore, %s failed at %d \n", __func__, __LINE__) ); + return result2; + } + + CHECK_RETURN(whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_AP_EVENT_ENTRY]) ); + ifp->event_reg_list[WHD_AP_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED; + whd_wifi_set_ap_is_up(whd_driver, WHD_FALSE); + + ifp->role = WHD_INVALID_ROLE; + return WHD_SUCCESS; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_buffer_api.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_buffer_api.c new file mode 100644 index 00000000..0aded5fe --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_buffer_api.c @@ -0,0 +1,219 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides generic APSTA functionality that chip specific files use + */ + +#include "whd_debug.h" +#include "whd_buffer_api.h" + +/****************************************************** +** @cond Constants +*******************************************************/ + +/****************************************************** +** Enumerations +*******************************************************/ + +/****************************************************** +** Function Declarations +*******************************************************/ + +/****************************************************** + * Variables Definitions + *****************************************************/ + +/****************************************************** +* Function Definitions +******************************************************/ +/** Allocates a packet buffer + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * Attempts to allocate a packet buffer of the size requested. It can do this + * by allocating a pre-existing packet from a pool, using a static buffer, + * or by dynamically allocating memory. The method of allocation does not + * concern WHD, however it must match the way the network stack expects packet + * buffers to be allocated. + * + * @param buffer : A pointer which receives the allocated packet buffer handle + * @param direction : Indicates transmit/receive direction that the packet buffer is + * used for. This may be needed if tx/rx pools are separate. + * @param size : The number of bytes to allocate. + * @param timeout_ms : Maximum period to block for available buffer + * + * @return : WHD_SUCCESS or error code + * + */ +whd_result_t whd_host_buffer_get(whd_driver_t whd_driver, whd_buffer_t *buffer, whd_buffer_dir_t direction, + uint16_t size, uint32_t timeout_ms) +{ + if (whd_driver->buffer_if->whd_host_buffer_get) + { + return whd_driver->buffer_if->whd_host_buffer_get(buffer, direction, size, timeout_ms); + } + else + { + WPRINT_WHD_INFO( ("Function pointers not provided .\n") ); + } + + return WHD_WLAN_NOFUNCTION; +} + +/** Releases a packet buffer + * + * Implemented in the port layer interface, which will be specific to the + * buffering scheme in use. + * This function is used by WHD to indicate that it no longer requires + * a packet buffer. The buffer can then be released back into a pool for + * reuse, or the dynamically allocated memory can be freed, according to + * how the packet was allocated. + * Returns void since WHD cannot do anything about failures + * + * @param buffer : The handle of the packet buffer to be released + * @param direction : Indicates transmit/receive direction that the packet buffer has + * been used for. This might be needed if tx/rx pools are separate. + * + */ +whd_result_t whd_buffer_release(whd_driver_t whd_driver, whd_buffer_t buffer, whd_buffer_dir_t direction) +{ + if (whd_driver->buffer_if->whd_buffer_release) + { + whd_driver->buffer_if->whd_buffer_release(buffer, direction); + return WHD_SUCCESS; + } + else + { + WPRINT_WHD_INFO( ("Function pointers not provided .\n") ); + } + + return WHD_WLAN_NOFUNCTION; +} + +/** Retrieves the current pointer of a packet buffer + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * Since packet buffers usually need to be created with space at the + * front for additional headers, this function allows WHD to get + * the current 'front' location pointer. + * + * @param buffer : The handle of the packet buffer whose pointer is to be retrieved + * + * @return : The packet buffer's current pointer. + */ +uint8_t *whd_buffer_get_current_piece_data_pointer(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + if (whd_driver->buffer_if->whd_buffer_get_current_piece_data_pointer) + { + return whd_driver->buffer_if->whd_buffer_get_current_piece_data_pointer(buffer); + } + else + { + WPRINT_WHD_INFO( ("Function pointers not provided .\n") ); + } + + return NULL; +} + +/** Retrieves the size of a packet buffer + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * Since packet buffers usually need to be created with space at the + * front for additional headers, the memory block used to contain a packet buffer + * will often be larger than the current size of the packet buffer data. + * This function allows WHD to retrieve the current size of a packet buffer's data. + * + * @param buffer : The handle of the packet buffer whose size is to be retrieved + * + * @return : The size of the packet buffer. + */ +uint16_t whd_buffer_get_current_piece_size(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + if (whd_driver->buffer_if->whd_buffer_get_current_piece_size) + { + return whd_driver->buffer_if->whd_buffer_get_current_piece_size(buffer); + } + else + { + WPRINT_WHD_INFO( ("Function pointers not provided .\n") ); + } + + return 0; +} + +/** Sets the current size of a WHD packet + * + * + * Implemented in the port layer interface which is specific to the + * buffering scheme in use. + * This function sets the current length of a WHD packet buffer + * + * @param buffer : The packet to be modified + * @param size : The new size of the packet buffer + * + * @return : WHD_SUCCESS or error code + */ +whd_result_t whd_buffer_set_size(whd_driver_t whd_driver, whd_buffer_t buffer, uint16_t size) +{ + if (whd_driver->buffer_if->whd_buffer_set_size) + { + return whd_driver->buffer_if->whd_buffer_set_size(buffer, size); + } + else + { + WPRINT_WHD_INFO( ("Function pointers not provided .\n") ); + } + + return WHD_WLAN_NOFUNCTION; +} + +/** Moves the current pointer of a packet buffer + * + * Implemented in the port layer interface which is specific to the buffering scheme in use. + * + * Since packet buffers usually need to be created with space at the front for additional headers, + * this function allows WHD to move the current 'front' location pointer so that it has space to + * add headers to transmit packets, and so that the network stack does not see the internal WHD + * headers on received packets. + * + * @param buffer : A pointer to the handle of the current packet buffer for which the + * current pointer will be moved. On return this may contain a pointer + * to a newly allocated packet buffer which has been daisy chained to + * the front of the given one. This would be the case if the given packet + * buffer didn't have enough space at the front. + * @param add_remove_amount : This is the number of bytes to move the current pointer of the packet + * buffer - a negative value increases the space for headers at the front + * of the packet, a positive value decreases the space. + * + * @return : WHD_SUCCESS or error code + */ +whd_result_t whd_buffer_add_remove_at_front(whd_driver_t whd_driver, whd_buffer_t *buffer, int32_t add_remove_amount) +{ + if (whd_driver->buffer_if->whd_buffer_add_remove_at_front) + { + return whd_driver->buffer_if->whd_buffer_add_remove_at_front(buffer, add_remove_amount); + } + else + { + WPRINT_WHD_INFO( ("Function pointers not provided .\n") ); + } + + return WHD_WLAN_NOFUNCTION; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_cdc_bdc.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_cdc_bdc.c new file mode 100644 index 00000000..7e23fb8b --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_cdc_bdc.c @@ -0,0 +1,759 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "whd_int.h" +#include "whd_cdc_bdc.h" +#include "whd_events_int.h" +#include "cyabs_rtos.h" +#include "whd_network_types.h" +#include "whd_types_int.h" +#include "whd_wlioctl.h" +#include "whd_thread_internal.h" +#include "whd_buffer_api.h" +#include "whd_network_if.h" + +/****************************************************** +* Constants +******************************************************/ + +#define BDC_PROTO_VER (2) /** Version number of BDC header */ +#define BDC_FLAG_VER_SHIFT (4) /** Number of bits to shift BDC version number in the flags field */ +#define BDC_FLAG2_IF_MASK (0x0f) + +#define ETHER_TYPE_BRCM (0x886C) /** Broadcom Ethertype for identifying event packets - Copied from DHD include/proto/ethernet.h */ +#define BRCM_OUI "\x00\x10\x18" /** Broadcom OUI (Organizationally Unique Identifier): Used in the proprietary(221) IE (Information Element) in all Broadcom devices */ + +/* QoS related definitions (type of service) */ +#define IPV4_DSCP_OFFSET (15) /** Offset for finding the DSCP field in an IPv4 header */ + +#define IOCTL_OFFSET (sizeof(whd_buffer_header_t) + 12 + 16) +#define WHD_IOCTL_PACKET_TIMEOUT (0xFFFFFFFF) +#define WHD_IOCTL_TIMEOUT_MS (5000) /** Need to give enough time for coming out of Deep sleep (was 400) */ +#define WHD_IOCTL_MAX_TX_PKT_LEN (1500) +#define ALIGNED_ADDRESS ( (uint32_t)0x3 ) + +/****************************************************** +* Macros +******************************************************/ + +/****************************************************** +* Local Structures +******************************************************/ + +/****************************************************** +* Static Variables +******************************************************/ + +static const uint8_t dscp_to_wmm_qos[] = +{ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */ + 1, 1, 1, 1, 1, 1, 1, /* 8 - 14 */ + 1, 1, 1, 1, 1, 1, 1, /* 15 - 21 */ + 1, 1, 0, 0, 0, 0, 0, /* 22 - 28 */ + 0, 0, 0, 5, 5, 5, 5, /* 29 - 35 */ + 5, 5, 5, 5, 5, 5, 5, /* 36 - 42 */ + 5, 5, 5, 5, 5, 7, 7, /* 43 - 49 */ + 7, 7, 7, 7, 7, 7, 7, /* 50 - 56 */ + 7, 7, 7, 7, 7, 7, 7, /* 57 - 63 */ +}; + +/****************************************************** +* Static Function Prototypes +******************************************************/ + +static uint8_t whd_map_dscp_to_priority(whd_driver_t whd_driver, uint8_t dscp_val); + +/****************************************************** +* Static Functions +******************************************************/ + +/** Map a DSCP value from an IP header to a WMM QoS priority + * + * @param dscp_val : DSCP value from IP header + * + * @return wmm_qos : WMM priority + * + */ +static uint8_t whd_map_dscp_to_priority(whd_driver_t whd_driver, uint8_t val) +{ + uint8_t dscp_val = (uint8_t)(val >> 2); /* DSCP field is the high 6 bits of the second byte of an IPv4 header */ + + return dscp_to_wmm_qos[dscp_val]; +} + +void whd_cdc_bdc_info_deinit(whd_driver_t whd_driver) +{ + whd_cdc_bdc_info_t *cdc_bdc_info = &whd_driver->cdc_bdc_info; + whd_error_info_t *error_info = &whd_driver->error_info; + + /* Delete the sleep mutex */ + (void)cy_rtos_deinit_semaphore(&cdc_bdc_info->ioctl_sleep); + + /* Delete the queue mutex. */ + (void)cy_rtos_deinit_semaphore(&cdc_bdc_info->ioctl_mutex); + + /* Delete the event list management mutex */ + (void)cy_rtos_deinit_semaphore(&cdc_bdc_info->event_list_mutex); + + /* Delete the error list management mutex */ + (void)cy_rtos_deinit_semaphore(&error_info->event_list_mutex); +} + +whd_result_t whd_cdc_bdc_info_init(whd_driver_t whd_driver) +{ + whd_cdc_bdc_info_t *cdc_bdc_info = &whd_driver->cdc_bdc_info; + whd_error_info_t *error_info = &whd_driver->error_info; + + /* Create the mutex protecting the packet send queue */ + if (cy_rtos_init_semaphore(&cdc_bdc_info->ioctl_mutex, 1, 0) != WHD_SUCCESS) + { + return WHD_SEMAPHORE_ERROR; + } + if (cy_rtos_set_semaphore(&cdc_bdc_info->ioctl_mutex, WHD_FALSE) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + return WHD_SEMAPHORE_ERROR; + } + + /* Create the event flag which signals the whd thread needs to wake up */ + if (cy_rtos_init_semaphore(&cdc_bdc_info->ioctl_sleep, 1, 0) != WHD_SUCCESS) + { + cy_rtos_deinit_semaphore(&cdc_bdc_info->ioctl_mutex); + return WHD_SEMAPHORE_ERROR; + } + + /* Create semaphore to protect event list management */ + if (cy_rtos_init_semaphore(&cdc_bdc_info->event_list_mutex, 1, 0) != WHD_SUCCESS) + { + cy_rtos_deinit_semaphore(&cdc_bdc_info->ioctl_sleep); + cy_rtos_deinit_semaphore(&cdc_bdc_info->ioctl_mutex); + return WHD_SEMAPHORE_ERROR; + } + if (cy_rtos_set_semaphore(&cdc_bdc_info->event_list_mutex, WHD_FALSE) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + return WHD_SEMAPHORE_ERROR; + } + + /* Initialise the list of event handler functions */ + memset(cdc_bdc_info->whd_event_list, 0, sizeof(cdc_bdc_info->whd_event_list) ); + + /* Create semaphore to protect event list management */ + if (cy_rtos_init_semaphore(&error_info->event_list_mutex, 1, 0) != WHD_SUCCESS) + { + return WHD_SEMAPHORE_ERROR; + } + + if (cy_rtos_set_semaphore(&error_info->event_list_mutex, WHD_FALSE) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + return WHD_SEMAPHORE_ERROR; + } + + /* Initialise the list of error handler functions */ + memset(error_info->whd_event_list, 0, sizeof(error_info->whd_event_list) ); + + return WHD_SUCCESS; +} + +/** Sends an IOCTL command + * + * Sends a I/O Control command to the Broadcom 802.11 device. + * The data which is set or retrieved must be in a format structure which is appropriate for the particular + * I/O control being sent. These structures can only be found in the DHD source code such as wl/exe/wlu.c. + * The I/O control will always respond with a packet buffer which may contain data in a format specific to + * the I/O control being used. + * + * @Note: The caller is responsible for releasing the response buffer. + * @Note: The function blocks until the IOCTL has completed + * @Note: Only one IOCTL may happen simultaneously. + * + * @param type : CDC_SET or CDC_GET - indicating whether to set or get the I/O control + * @param send_buffer_hnd : A handle for a packet buffer containing the data value to be sent. + * @param response_buffer_hnd : A pointer which will receive the handle for the packet buffer + * containing the response data value received. + * @param interface : Which interface to send the iovar to (WHD_STA_INTERFACE or WHD_AP_INTERFACE) + * + * @return WHD result code + */ +whd_result_t whd_cdc_send_ioctl(whd_interface_t ifp, cdc_command_type_t type, uint32_t command, + whd_buffer_t send_buffer_hnd, + whd_buffer_t *response_buffer_hnd) +{ + + uint32_t data_length; + uint32_t flags; + uint32_t requested_ioctl_id; + uint32_t status; + whd_result_t retval; + control_header_t *send_packet; + cdc_header_t *cdc_header; + uint32_t bss_index = ifp->bsscfgidx; + whd_driver_t whd_driver = ifp->whd_driver; + whd_cdc_bdc_info_t *cdc_bdc_info = &whd_driver->cdc_bdc_info; + + /* Validate the command value */ + if (command > INT_MAX) + { + WPRINT_WHD_ERROR( ("The ioctl command value is invalid\n") ); + return WHD_BADARG; + } + + /* Acquire mutex which prevents multiple simultaneous IOCTLs */ + retval = cy_rtos_get_semaphore(&cdc_bdc_info->ioctl_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE); + if (retval != WHD_SUCCESS) + { + CHECK_RETURN(whd_buffer_release(whd_driver, send_buffer_hnd, WHD_NETWORK_TX) ); + return retval; + } + + /* Count request ioctl ID after acquiring ioctl mutex */ + requested_ioctl_id = (uint32_t)(++cdc_bdc_info->requested_ioctl_id); + + /* Get the data length and cast packet to a CDC BUS header */ + data_length = + (uint32_t)(whd_buffer_get_current_piece_size(whd_driver, + send_buffer_hnd) - sizeof(bus_common_header_t) - + sizeof(cdc_header_t) ); + + send_packet = (control_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, send_buffer_hnd); + CHECK_PACKET_NULL(send_packet, WHD_NO_REGISTER_FUNCTION_POINTER); + WHD_IOCTL_LOG_ADD(ifp->whd_driver, command, send_buffer_hnd); + + /* Check if IOCTL is actually IOVAR */ + if ( (command == WLC_SET_VAR) || (command == WLC_GET_VAR) ) + { + uint8_t *data = (uint8_t *)DATA_AFTER_HEADER(send_packet); + uint8_t *ptr = data; + + /* Calculate the offset added to compensate for IOVAR string creating unaligned data section */ + while (*ptr == 0) + { + ptr++; + } + if (data != ptr) + { + data_length -= (uint32_t)(ptr - data); + memmove(data, ptr, data_length); + CHECK_RETURN(whd_buffer_set_size(whd_driver, send_buffer_hnd, + (uint16_t)(data_length + sizeof(bus_common_header_t) + + sizeof(cdc_header_t) ) ) ); + } + } + + /* Prepare the CDC header */ + send_packet->cdc_header.cmd = htod32(command); + send_packet->cdc_header.len = htod32(data_length); + + send_packet->cdc_header.flags = ( (requested_ioctl_id << CDCF_IOC_ID_SHIFT) + & CDCF_IOC_ID_MASK ) | type | bss_index << CDCF_IOC_IF_SHIFT; + send_packet->cdc_header.flags = htod32(send_packet->cdc_header.flags); + + send_packet->cdc_header.status = 0; + + /* Manufacturing test can receive big buffers, but sending big buffers causes a wlan firmware error */ + /* Even though data portion needs to be truncated, cdc_header should have the actual length of the ioctl packet */ + if (whd_buffer_get_current_piece_size(whd_driver, send_buffer_hnd) > WHD_IOCTL_MAX_TX_PKT_LEN) + { + CHECK_RETURN(whd_buffer_set_size(whd_driver, send_buffer_hnd, WHD_IOCTL_MAX_TX_PKT_LEN) ); + } + + /* Store the length of the data and the IO control header and pass "down" */ + CHECK_RETURN(whd_send_to_bus(whd_driver, send_buffer_hnd, CONTROL_HEADER, 8) ); + + + /* Wait till response has been received */ + retval = cy_rtos_get_semaphore(&cdc_bdc_info->ioctl_sleep, (uint32_t)WHD_IOCTL_TIMEOUT_MS, WHD_FALSE); + if (retval != WHD_SUCCESS) + { + /* Release the mutex since ioctl response will no longer be referenced. */ + CHECK_RETURN(cy_rtos_set_semaphore(&cdc_bdc_info->ioctl_mutex, WHD_FALSE) ); + return retval; + } + + cdc_header = (cdc_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, cdc_bdc_info->ioctl_response); + CHECK_PACKET_NULL(cdc_header, WHD_NO_REGISTER_FUNCTION_POINTER); + flags = dtoh32(cdc_header->flags); + status = dtoh32(cdc_header->status); + /* Check if the caller wants the response */ + if (response_buffer_hnd != NULL) + { + *response_buffer_hnd = cdc_bdc_info->ioctl_response; + CHECK_RETURN(whd_buffer_add_remove_at_front(whd_driver, response_buffer_hnd, sizeof(cdc_header_t) ) ); + } + else + { + CHECK_RETURN(whd_buffer_release(whd_driver, cdc_bdc_info->ioctl_response, WHD_NETWORK_RX) ); + } + + cdc_bdc_info->ioctl_response = NULL; + + /* Release the mutex since ioctl response will no longer be referenced. */ + CHECK_RETURN(cy_rtos_set_semaphore(&cdc_bdc_info->ioctl_mutex, WHD_FALSE) ); + + /* Check whether the IOCTL response indicates it failed. */ + if ( (flags & CDCF_IOC_ERROR) != 0 ) + { + if (response_buffer_hnd != NULL) + { + CHECK_RETURN(whd_buffer_release(whd_driver, *response_buffer_hnd, WHD_NETWORK_RX) ); + *response_buffer_hnd = NULL; + } + if (status) + return WHD_RESULT_CREATE( (WLAN_ENUM_OFFSET - status) ); + else + return WHD_IOCTL_FAIL; + } + + return WHD_SUCCESS; +} + +/** Sets/Gets an I/O Variable (IOVar) + * + * This function either sets or retrieves the value of an I/O variable from the Broadcom 802.11 device. + * The data which is set or retrieved must be in a format structure which is appropriate for the particular + * I/O variable being accessed. These structures can only be found in the DHD source code such as wl/exe/wlu.c. + * + * @Note: The function blocks until the I/O variable read/write has completed + * + * @param type : CDC_SET or CDC_GET - indicating whether to set or get the I/O variable value + * @param send_buffer_hnd : A handle for a packet buffer containing the data value to be sent. + * @param response_buffer_hnd : A pointer which will receive the handle for the packet buffer + * containing the response data value received. + * @param interface : Which interface to send the iovar to (AP or STA) + * + * @return WHD result code + */ +whd_result_t whd_cdc_send_iovar(whd_interface_t ifp, cdc_command_type_t type, + whd_buffer_t send_buffer_hnd, + whd_buffer_t *response_buffer_hnd) +{ + if (type == CDC_SET) + { + return whd_cdc_send_ioctl(ifp, CDC_SET, (uint32_t)WLC_SET_VAR, send_buffer_hnd, response_buffer_hnd); + } + else + { + return whd_cdc_send_ioctl(ifp, CDC_GET, (uint32_t)WLC_GET_VAR, send_buffer_hnd, response_buffer_hnd); + } +} + +/** A helper function to easily acquire and initialise a buffer destined for use as an iovar + * + * @param buffer : A pointer to a whd_buffer_t object where the created buffer will be stored + * @param data_length : The length of space reserved for user data + * @param name : The name of the iovar + * + * @return A pointer to the start of user data with data_length space available + */ +void *whd_cdc_get_iovar_buffer(whd_driver_t whd_driver, + whd_buffer_t *buffer, + uint16_t data_length, + const char *name) +{ + uint32_t name_length = (uint32_t)strlen(name) + 1; /* + 1 for terminating null */ + uint32_t name_length_alignment_offset = (64 - name_length) % sizeof(uint32_t); + + if (whd_host_buffer_get(whd_driver, buffer, WHD_NETWORK_TX, + (uint16_t)(IOCTL_OFFSET + data_length + name_length + name_length_alignment_offset), + (uint32_t)WHD_IOCTL_PACKET_TIMEOUT) == WHD_SUCCESS) + { + uint8_t *data = whd_buffer_get_current_piece_data_pointer(whd_driver, *buffer); + CHECK_PACKET_NULL(data, NULL); + data = data + IOCTL_OFFSET; + memset(data, 0, name_length_alignment_offset); + memcpy(data + name_length_alignment_offset, name, name_length); + return (data + name_length + name_length_alignment_offset); + } + else + { + WPRINT_WHD_ERROR( ("Error - failed to allocate a packet buffer for IOVAR\n") ); + return NULL; + } +} + +/** Sends a data packet. + * + * This function should be called by the bottom of the network stack in order for it + * to send an ethernet frame. + * The function prepends a BDC header, before sending to @ref whd_send_to_bus where + * the BUS header will be added + * + * @param buffer : The ethernet packet buffer to be sent + * @param interface : the interface over which to send the packet (AP or STA) + * + * @return WHD result code + */ +whd_result_t whd_network_send_ethernet_data(whd_interface_t ifp, whd_buffer_t buffer) +{ + data_header_t *packet; + whd_result_t result; + uint8_t *dscp = NULL; + uint8_t priority = 0; + uint8_t whd_tos_map[8] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; + whd_driver_t whd_driver = ifp->whd_driver; + ethernet_header_t *ethernet_header = (ethernet_header_t *)whd_buffer_get_current_piece_data_pointer( + whd_driver, buffer); + uint16_t ether_type; + CHECK_PACKET_NULL(ethernet_header, WHD_NO_REGISTER_FUNCTION_POINTER); + ether_type = ntoh16(ethernet_header->ethertype); + if ( (ether_type == WHD_ETHERTYPE_IPv4) || (ether_type == WHD_ETHERTYPE_DOT1AS) ) + { + dscp = (uint8_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer) + IPV4_DSCP_OFFSET; + } + + WPRINT_WHD_DATA_LOG( ("Wcd:> DATA pkt 0x%08lX len %d\n", (unsigned long)buffer, + (int)whd_buffer_get_current_piece_size(whd_driver, buffer) ) ); + + + /* Add link space at front of packet */ + result = whd_buffer_add_remove_at_front(whd_driver, &buffer, -(int)(sizeof(data_header_t) ) ); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_DEBUG( ("Unable to adjust header space\n") ); + result = whd_buffer_release(ifp->whd_driver, buffer, WHD_NETWORK_TX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + return WHD_BUFFER_ALLOC_FAIL; + } + + packet = (data_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + CHECK_PACKET_NULL(packet, WHD_NO_REGISTER_FUNCTION_POINTER); + if (ifp->bsscfgidx > WHD_INTERFACE_MAX) + { + WPRINT_WHD_DEBUG( ("No interface for packet send\n") ); + result = whd_buffer_release(ifp->whd_driver, buffer, WHD_NETWORK_TX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + return WHD_UNKNOWN_INTERFACE; + } + + /* Prepare the BDC header */ + packet->bdc_header.flags = 0; + packet->bdc_header.flags = (uint8_t)(BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); + /* If it's an IPv4 packet set the BDC header priority based on the DSCP field */ + if ( ( (ether_type == WHD_ETHERTYPE_IPv4) || (ether_type == WHD_ETHERTYPE_DOT1AS) ) && (dscp != NULL) ) + { + if (*dscp != 0) /* If it's equal 0 then it's best effort traffic and nothing needs to be done */ + { + priority = whd_map_dscp_to_priority(whd_driver, *dscp); + } + } + + /* If STA interface, re-map prio to the prio allowed by the AP, regardless of whether it's an IPv4 packet */ + if (ifp->role == WHD_STA_ROLE) + { + packet->bdc_header.priority = whd_tos_map[priority]; + } + else + { + packet->bdc_header.priority = priority; + } + + packet->bdc_header.flags2 = ifp->bsscfgidx; + packet->bdc_header.data_offset = 0; + + /* Add the length of the BDC header and pass "down" */ + return whd_send_to_bus(whd_driver, buffer, DATA_HEADER, packet->bdc_header.priority); + +} + +/** A helper function to easily acquire and initialise a buffer destined for use as an ioctl + * + * @param buffer : A pointer to a whd_buffer_t object where the created buffer will be stored + * @param data_length : The length of space reserved for user data + * + * @return A pointer to the start of user data with data_length space available + */ +void *whd_cdc_get_ioctl_buffer(whd_driver_t whd_driver, + whd_buffer_t *buffer, + uint16_t data_length) +{ + if ( (uint32_t)IOCTL_OFFSET + data_length > USHRT_MAX ) + { + WPRINT_WHD_ERROR( ("The reserved ioctl buffer length is over %u\n", USHRT_MAX) ); + return NULL; + } + if (whd_host_buffer_get(whd_driver, buffer, WHD_NETWORK_TX, (uint16_t)(IOCTL_OFFSET + data_length), + (uint32_t)WHD_IOCTL_PACKET_TIMEOUT) == WHD_SUCCESS) + { + return (whd_buffer_get_current_piece_data_pointer(whd_driver, *buffer) + IOCTL_OFFSET); + } + else + { + WPRINT_WHD_ERROR( ("Error - failed to allocate a packet buffer for IOCTL\n") ); + return NULL; + } +} + +/** Processes CDC header information received in the RX packet and sets IOCTL response buffer + * + * @param whd_driver : WHD driver instance + * @param buffer : A pointer to a whd_buffer_t object where the created buffer will be stored + */ + +void whd_process_cdc(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + uint32_t flags; + uint16_t id; + whd_cdc_bdc_info_t *cdc_bdc_info = &whd_driver->cdc_bdc_info; + whd_result_t result; + cdc_header_t *cdc_header = (cdc_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + whd_result_t ioctl_mutex_res; + CHECK_PACKET_WITH_NULL_RETURN(cdc_header); + flags = dtoh32(cdc_header->flags); + id = (uint16_t)( (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT ); + + /* Validate request ioctl ID and check if whd_cdc_send_ioctl is still waiting for response*/ + if ( ( (ioctl_mutex_res = cy_rtos_get_semaphore(&cdc_bdc_info->ioctl_mutex, 0, WHD_FALSE) ) != WHD_SUCCESS ) && + (id == cdc_bdc_info->requested_ioctl_id) ) + { + /* Save the response packet in a variable */ + cdc_bdc_info->ioctl_response = buffer; + + WPRINT_WHD_DATA_LOG( ("Wcd:< Procd pkt 0x%08lX: IOCTL Response\n", (unsigned long)buffer) ); + + /* Wake the thread which sent the IOCTL/IOVAR so that it will resume */ + result = cy_rtos_set_semaphore(&cdc_bdc_info->ioctl_sleep, WHD_FALSE); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + + } + else + { + WPRINT_WHD_ERROR( ("Received buffer request ID: %d (expectation: %d)\n", + id, cdc_bdc_info->requested_ioctl_id) ); + if (ioctl_mutex_res == WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("whd_cdc_send_ioctl is already timed out, drop the buffer\n") ); + result = cy_rtos_set_semaphore(&cdc_bdc_info->ioctl_mutex, WHD_FALSE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + } + } + else + { + WPRINT_WHD_ERROR( ("Received a response for a different IOCTL - retry\n") ); + } + + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + } +} + +/** Processes BDC header information received in the RX packet and sends data to network stack + * + * @param whd_driver : WHD driver instance + * @param buffer : A pointer to a whd_buffer_t object where the created buffer will be stored + */ + +void whd_process_bdc(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + int32_t headers_len_below_payload; + uint32_t ip_data_start_add; + uint32_t bssid_index; + whd_interface_t ifp; + whd_result_t result; + bdc_header_t *bdc_header = (bdc_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + CHECK_PACKET_WITH_NULL_RETURN(bdc_header); + /* Calculate where the payload is */ + headers_len_below_payload = + (int32_t)( (int32_t)BDC_HEADER_LEN + (int32_t)(bdc_header->data_offset << 2) ); + + /* Move buffer pointer past gSPI, BUS, BCD headers and padding, + * so that the network stack or 802.11 monitor sees only the payload */ + if (WHD_SUCCESS != whd_buffer_add_remove_at_front(whd_driver, &buffer, headers_len_below_payload) ) + { + WPRINT_WHD_ERROR( ("No space for headers without chaining. this should never happen\n") ); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + + return; + } + + /* It is preferable to have IP data at address aligned to 4 bytes. IP data startes after ethernet header */ + ip_data_start_add = + (uint32_t )whd_buffer_get_current_piece_data_pointer(whd_driver, buffer) + WHD_ETHERNET_SIZE; + if ( ( (ip_data_start_add >> 2) << 2 ) != ip_data_start_add ) + { + WPRINT_WHD_DATA_LOG( ("IP data not aligned to 4 bytes %lx\n", ip_data_start_add) ); + } + + WPRINT_WHD_DATA_LOG( ("Wcd:< Procd pkt 0x%08lX\n", (unsigned long)buffer) ); + bssid_index = (uint32_t)(bdc_header->flags2 & BDC_FLAG2_IF_MASK); + ifp = whd_driver->iflist[bssid_index]; + + /* Send packet to bottom of network stack */ + result = whd_network_process_ethernet_data(ifp, buffer); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("%s failed at %d \n", __func__, __LINE__) ); +} + +/** Processes BDC header information and extracts the event packets + * Event Packets are decoded to determine which event occurred, and the event handler list is consulted + * and the appropriate event handler is called + * + * @param whd_driver : WHD driver instance + * @param buffer : A pointer to a whd_buffer_t object where the created buffer will be stored + * @param size : Size of the complete packet received from WLAN device + */ +void whd_process_bdc_event(whd_driver_t whd_driver, whd_buffer_t buffer, uint16_t size) +{ + uint16_t ether_type; + whd_event_header_t *whd_event; + whd_event_t *event, *aligned_event = (whd_event_t *)whd_driver->aligned_addr; + whd_cdc_bdc_info_t *cdc_bdc_info = &whd_driver->cdc_bdc_info; + whd_result_t result; + bdc_header_t *bdc_header = (bdc_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + uint16_t i; + uint16_t j; + uint32_t datalen, addr; + + CHECK_PACKET_WITH_NULL_RETURN(bdc_header); + event = (whd_event_t *)&bdc_header[bdc_header->data_offset + 1]; + + ether_type = ntoh16(event->eth.ethertype); + + /* If frame is truly an event, it should have EtherType equal to the Broadcom type. */ + if (ether_type != (uint16_t)ETHER_TYPE_BRCM) + { + WPRINT_WHD_DEBUG( ("Error - received a channel 1 packet which was not BRCM ethertype\n") ); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + return; + } + + /* If ethertype is correct, the contents of the ethernet packet + * are a structure of type bcm_event_t + */ + + /* Check that the OUI matches the Broadcom OUI */ + if (0 != memcmp(BRCM_OUI, &event->eth_evt_hdr.oui[0], (size_t)DOT11_OUI_LEN) ) + { + WPRINT_WHD_DEBUG( ("Event OUI mismatch\n") ); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + return; + } + + whd_event = &event->whd_event; + + /* Search for the event type in the list of event handler functions + * event data is stored in network endianness + */ + whd_event->flags = ntoh16(whd_event->flags); + whd_event->event_type = (whd_event_num_t)ntoh32(whd_event->event_type); + whd_event->status = (whd_event_status_t)ntoh32(whd_event->status); + whd_event->reason = (whd_event_reason_t)ntoh32(whd_event->reason); + whd_event->auth_type = ntoh32(whd_event->auth_type); + whd_event->datalen = ntoh32(whd_event->datalen); + + /* Ensure data length is correct */ + if (whd_event->datalen > + (uint32_t)(size - ( (char *)DATA_AFTER_HEADER(event) - (char *)bdc_header ) ) ) + { + WPRINT_WHD_ERROR( ( + "Error - (data length received [%d] > expected data length [%d]). Bus header packet size = [%d]. Ignoring the packet\n", + (int)whd_event->datalen, + size - ( (char *)DATA_AFTER_HEADER(event) - (char *)bdc_header ), + size) ); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + + return; + } + + /* This is necessary because people who defined event statuses and reasons overlapped values. */ + if (whd_event->event_type == WLC_E_PSK_SUP) + { + whd_event->status = (whd_event_status_t)( (int)whd_event->status + WLC_SUP_STATUS_OFFSET ); + whd_event->reason = (whd_event_reason_t)( (int)whd_event->reason + WLC_E_SUP_REASON_OFFSET ); + } + else if (whd_event->event_type == WLC_E_PRUNE) + { + whd_event->reason = (whd_event_reason_t)( (int)whd_event->reason + WLC_E_PRUNE_REASON_OFFSET ); + } + else if ( (whd_event->event_type == WLC_E_DISASSOC) || (whd_event->event_type == WLC_E_DEAUTH) ) + { + whd_event->status = (whd_event_status_t)( (int)whd_event->status + WLC_DOT11_SC_STATUS_OFFSET ); + whd_event->reason = (whd_event_reason_t)( (int)whd_event->reason + WLC_E_DOT11_RC_REASON_OFFSET ); + } + + /* do any needed debug logging of event */ + WHD_IOCTL_LOG_ADD_EVENT(whd_driver, whd_event->event_type, whd_event->status, + whd_event->reason); + + if (cy_rtos_get_semaphore(&cdc_bdc_info->event_list_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE) != WHD_SUCCESS) + { + WPRINT_WHD_DEBUG( ("Failed to obtain mutex for event list access!\n") ); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + return; + } + + datalen = whd_event->datalen; + /* use memcpy to get aligned event message */ + addr = (uint32_t )DATA_AFTER_HEADER(event); + if (aligned_event && (addr & ALIGNED_ADDRESS) ) + { + memcpy(aligned_event, (whd_event_t *)addr, datalen); + } + else + { + aligned_event = (whd_event_t *)addr; + } + for (i = 0; i < (uint16_t)WHD_EVENT_HANDLER_LIST_SIZE; i++) + { + if (cdc_bdc_info->whd_event_list[i].event_set) + { + for (j = 0; cdc_bdc_info->whd_event_list[i].events[j] != WLC_E_NONE; ++j) + { + if ( (cdc_bdc_info->whd_event_list[i].events[j] == whd_event->event_type) && + (cdc_bdc_info->whd_event_list[i].ifidx == whd_event->ifidx) ) + { + /* Correct event type has been found - call the handler function and exit loop */ + cdc_bdc_info->whd_event_list[i].handler_user_data = + cdc_bdc_info->whd_event_list[i].handler(whd_driver->iflist[whd_event->bsscfgidx], + whd_event, + (uint8_t *)aligned_event, + cdc_bdc_info->whd_event_list[i].handler_user_data); + break; + } + } + } + } + + result = cy_rtos_set_semaphore(&cdc_bdc_info->event_list_mutex, WHD_FALSE); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + + WPRINT_WHD_DATA_LOG( ("Wcd:< Procd pkt 0x%08lX: Evnt %d (%d bytes)\n", (unsigned long)buffer, + (int)whd_event->event_type, size) ); + + /* Release the event packet buffer */ + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_chip.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_chip.c new file mode 100644 index 00000000..cdc46731 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_chip.c @@ -0,0 +1,1536 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "bus_protocols/whd_chip_reg.h" +#include "bus_protocols/whd_sdio.h" +#include "bus_protocols/whd_bus_common.h" +#include "bus_protocols/whd_bus_protocol_interface.h" +#include "whd_chip_constants.h" +#include "whd_cdc_bdc.h" +#include "whd_thread_internal.h" +#include "whd_buffer_api.h" +#include "whd_debug.h" +#include "whd_utils.h" +#include "whd_wifi_api.h" +#include "whd_chip.h" +#include "whd.h" +#include "whd_wlioctl.h" + +/****************************************************** +* Macros +******************************************************/ +#define SPINWAIT_POLL_PERIOD 10 + +#define SPINWAIT(exp, us) { \ + uint countdown = (us) + (SPINWAIT_POLL_PERIOD - 1); \ + while ( (exp) && (countdown >= SPINWAIT_POLL_PERIOD) ){ \ + cy_rtos_delay_milliseconds(SPINWAIT_POLL_PERIOD); \ + countdown -= SPINWAIT_POLL_PERIOD; \ + } \ +} +/****************************************************** +* Constants +******************************************************/ + +#define PLATFORM_WLAN_RAM_BASE (0x0) +#define WLAN_BUS_UP_ATTEMPTS (1000) +#define HT_AVAIL_WAIT_MS (1) +#define KSO_WAIT_MS (1) +#define KSO_WAKE_MS (3) +#define MAX_KSO_ATTEMPTS (64) +#define MAX_CAPS_BUFFER_SIZE (768) + +#define AI_IOCTRL_OFFSET (0x408) +#define SICF_FGC (0x0002) +#define SICF_CLOCK_EN (0x0001) +#define AI_RESETCTRL_OFFSET (0x800) +#define AI_RESETSTATUS_OFFSET (0x804) +#define AIRC_RESET (1) +#define WRAPPER_REGISTER_OFFSET (0x100000) + +#define WLAN_SHARED_VERSION_MASK (0x00ff) +#define WLAN_SHARED_VERSION (0x0001) +#define WPRINT_WHD_DEBUG_DS(args) WPRINT_WHD_DEBUG(args) + +/****************************************************** +* Structures +******************************************************/ + +/****************************************************** +* Variables +******************************************************/ +static const whd_fwcap_t whd_fwcap_map[] = +{ + {WHD_FWCAP_SAE, "sae "}, + {WHD_FWCAP_SAE_EXT, "sae_ext "}, +}; + +/****************************************************** +* Static Function Declarations +******************************************************/ +static whd_bool_t whd_is_fw_sr_capable(whd_driver_t whd_driver); +static whd_result_t whd_kso_enable(whd_driver_t whd_driver, whd_bool_t enable); +static uint32_t whd_get_core_address(whd_driver_t whd_driver, device_core_t core_id); + +static whd_result_t whd_enable_save_restore(whd_driver_t whd_driver); + +/****************************************************** +* Function definitions +******************************************************/ +whd_result_t whd_internal_info_init(whd_driver_t whd_driver) +{ + whd_internal_info_t *internal_info = &whd_driver->internal_info; + + internal_info->whd_wlan_status.state = WLAN_OFF; + internal_info->whd_wlan_status.country_code = WHD_COUNTRY_AUSTRALIA; + internal_info->whd_wlan_status.aggregate_code = WHD_COUNTRY_AGGREGATE_XV_0; + internal_info->whd_wlan_status.keep_wlan_awake = 0; + internal_info->console_addr = 0; + internal_info->scan_result_callback = NULL; + internal_info->whd_scan_result_ptr = NULL; + internal_info->active_join_mutex_initted = WHD_FALSE; + internal_info->active_join_semaphore = NULL; + internal_info->con_lastpos = 0; + internal_info->whd_wifi_p2p_go_is_up = WHD_FALSE; + + /* Create the mutex protecting whd_log structure */ + if (cy_rtos_init_semaphore(&whd_driver->whd_log_mutex, 1, 0) != WHD_SUCCESS) + { + return WHD_SEMAPHORE_ERROR; + } + if (cy_rtos_set_semaphore(&whd_driver->whd_log_mutex, WHD_FALSE) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + return WHD_SEMAPHORE_ERROR; + } + return WHD_SUCCESS; +} + +whd_result_t whd_internal_info_deinit(whd_driver_t whd_driver) +{ + /* Delete the whd_log mutex */ + (void)cy_rtos_deinit_semaphore(&whd_driver->whd_log_mutex); + return WHD_SUCCESS; +} + +/* + * Returns the base address of the core identified by the provided coreId + */ +uint32_t whd_get_core_address(whd_driver_t whd_driver, device_core_t core_id) +{ + if (core_id == WLAN_ARM_CORE) + { + return GET_C_VAR(whd_driver, ARM_CORE_BASE_ADDRESS); + } + else if (core_id == SOCRAM_CORE) + { + return GET_C_VAR(whd_driver, SOCSRAM_WRAPPER_BASE_ADDRESS); + } + else if (core_id == SDIOD_CORE) + { + return GET_C_VAR(whd_driver, SDIOD_CORE_BASE_ADDRESS); + } + else + { + WPRINT_WHD_ERROR( ("%s:%d Invalid core ID(%d)\n", __FUNCTION__, __LINE__, core_id) ); + } + + return WHD_BADARG; + +} + +/* + * Returns WHD_SUCCESS is the core identified by the provided coreId is up, otherwise WHD result code + */ +whd_result_t whd_device_core_is_up(whd_driver_t whd_driver, device_core_t core_id) +{ + uint8_t regdata; + uint32_t base; + whd_result_t result; + + base = whd_get_core_address(whd_driver, core_id); + + /* Read the IO control register */ + result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, ®data); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + /* Verify that the clock is enabled and something else is not on */ + if ( (regdata & (SICF_FGC | SICF_CLOCK_EN) ) != ( uint8_t )SICF_CLOCK_EN ) + { + return WHD_CORE_CLOCK_NOT_ENABLED; + } + + /* Read the reset control and verify it is not in reset */ + result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, ®data); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + if ( (regdata & AIRC_RESET) != 0 ) + { + return WHD_CORE_IN_RESET; + } + + return WHD_SUCCESS; +} + +/* + * Resets the core identified by the provided coreId + */ +whd_result_t whd_reset_core(whd_driver_t whd_driver, device_core_t core_id, uint32_t bits, uint32_t resetbits) +{ + uint32_t base = whd_get_core_address(whd_driver, core_id); + whd_result_t result; + uint8_t regdata; + uint32_t loop_counter = 10; + /* ensure there are no pending backplane operations */ + SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1, + ®data) ) == WHD_SUCCESS ) && regdata != 0 ), 300 ); + + /* put core into reset state */ + result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, ( uint32_t )AIRC_RESET); + (void)cy_rtos_delay_milliseconds( (uint32_t)10 ); /* Ignore return - nothing can be done if it fails */ + + /* ensure there are no pending backplane operations */ + SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1, + ®data) ) == WHD_SUCCESS ) && regdata != 0 ), 300 ); + + result = whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, + (bits | resetbits | SICF_FGC | SICF_CLOCK_EN) ); + + /* ensure there are no pending backplane operations */ + SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1, + ®data) ) == WHD_SUCCESS ) && regdata != 0 ), 300 ); + + while ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, + ®data) ) == WHD_SUCCESS ) && regdata != 0 && + --loop_counter != 0 ) + { + /* ensure there are no pending backplane operations */ + SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1, + ®data) ) == WHD_SUCCESS ) && regdata != 0 ), 300 ); + /* take core out of reset */ + result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, (uint32_t)0); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + /* ensure there are no pending backplane operations */ + SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1, + ®data) ) == WHD_SUCCESS ) && regdata != 0 ), 300 ); + } + + result = whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, (bits | SICF_CLOCK_EN) ); + + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); /* Ignore return - nothing can be done if it fails */ + + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + return WHD_SUCCESS; +} + +/* + * Disables the core identified by the provided coreId + */ +whd_result_t whd_disable_device_core(whd_driver_t whd_driver, device_core_t core_id, wlan_core_flag_t core_flag) +{ + uint32_t base = whd_get_core_address(whd_driver, core_id); + whd_result_t result; + uint8_t junk; + uint8_t regdata; + + /* Read the reset control */ + result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, &junk); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + /* Read the reset control and check if it is already in reset */ + result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, ®data); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + if ( (regdata & AIRC_RESET) != 0 ) + { + /* Core already in reset */ + return WHD_SUCCESS; + } + + /* Write 0 to the IO control and read it back */ + result = + whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, + (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); + + result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, ( uint32_t )AIRC_RESET); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); + + return result; +} + +/* + * Resets the core identified by the provided coreId + */ +whd_result_t whd_reset_device_core(whd_driver_t whd_driver, device_core_t core_id, wlan_core_flag_t core_flag) +{ + uint32_t base = whd_get_core_address(whd_driver, core_id); + whd_result_t result; + uint8_t junk; + + result = whd_disable_device_core(whd_driver, core_id, core_flag); + if (result != WHD_SUCCESS) + { + return result; + } + + result = + whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, + ( uint32_t )(SICF_FGC | SICF_CLOCK_EN | + ( (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0 ) ) ); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, 0); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); + + result = + whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, + ( uint32_t )(SICF_CLOCK_EN | + ( (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0 ) ) ); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ) + return result; + } + + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); + + return result; +} + +/* + * Release ARM core to run instructions + */ +whd_result_t whd_wlan_armcore_run(whd_driver_t whd_driver, device_core_t core_id, wlan_core_flag_t core_flag) +{ + uint32_t base = whd_get_core_address(whd_driver, core_id); + whd_result_t result; + uint8_t junk; + + /* Only work for WLAN arm core! */ + if (WLAN_ARM_CORE != core_id) + { + return WHD_UNSUPPORTED; + } + + result = + whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, + ( uint32_t )(SICF_FGC | SICF_CLOCK_EN | + ( (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0 ) ) ); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ) + return result; + } + + result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ) + return result; + } + + result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, 0); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ) + return result; + } + + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); + + result = + whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, + ( uint32_t )(SICF_CLOCK_EN | + ( (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0 ) ) ); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ); + return result; + } + + (void)cy_rtos_delay_milliseconds( (uint32_t)1 ); + + return result; +} + +whd_result_t whd_wifi_read_wlan_log_unsafe(whd_driver_t whd_driver, uint32_t wlan_shared_address, char *buffer, + uint32_t buffer_size) +{ + char ch; + uint32_t n; + uint32_t index; + uint32_t address; + whd_result_t result = WHD_WLAN_ERROR; + whd_internal_info_t *internal_info = &whd_driver->internal_info; + wifi_console_t *c = internal_info->c; + + c = &internal_info->console; + + if (internal_info->console_addr == 0) + { + uint shared_addr; + + address = wlan_shared_address; + result = whd_bus_read_backplane_value(whd_driver, address, 4, (uint8_t *)&shared_addr); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ); + goto done; + } + + result = whd_bus_transfer_backplane_bytes(whd_driver, BUS_READ, shared_addr, sizeof(wlan_shared_t), + (uint8_t *)&internal_info->sh); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_transfer_backplane_bytes failed\n", __FUNCTION__, __LINE__) ); + goto done; + } + + internal_info->sh.flags = dtoh32(internal_info->sh.flags); + internal_info->sh.trap_addr = dtoh32(internal_info->sh.trap_addr); + internal_info->sh.assert_exp_addr = dtoh32(internal_info->sh.assert_exp_addr); + internal_info->sh.assert_file_addr = dtoh32(internal_info->sh.assert_file_addr); + internal_info->sh.assert_line = dtoh32(internal_info->sh.assert_line); + internal_info->sh.console_addr = dtoh32(internal_info->sh.console_addr); + internal_info->sh.msgtrace_addr = dtoh32(internal_info->sh.msgtrace_addr); + + if ( (internal_info->sh.flags & WLAN_SHARED_VERSION_MASK) != WLAN_SHARED_VERSION ) + { + WPRINT_WHD_ERROR( ("Readconsole: WLAN shared version is not valid sh.flags %x\n\r", + internal_info->sh.flags) ); + result = WHD_WLAN_INVALID; + goto done; + } + internal_info->console_addr = internal_info->sh.console_addr; + } + + /* Read console log struct */ + address = internal_info->console_addr + offsetof(hnd_cons_t, log); + result = whd_bus_transfer_backplane_bytes(whd_driver, BUS_READ, address, sizeof(c->log), (uint8_t *)&c->log); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_transfer_backplane_bytes failed\n", __FUNCTION__, __LINE__) ); + goto done; + } + + /* Allocate console buffer (one time only) */ + if (c->buf == NULL) + { + c->bufsize = dtoh32(c->log.buf_size); + c->buf = malloc(c->bufsize); + if (c->buf == NULL) + { + WPRINT_WHD_ERROR( ("%s:%d c->buf IS null \n", __FUNCTION__, __LINE__) ); + result = WHD_WLAN_NOMEM; + goto done; + } + } + + /* Retrieve last read position */ + c->last = whd_driver->internal_info.con_lastpos; + + index = dtoh32(c->log.idx); + + /* Protect against corrupt value */ + if (index > c->bufsize) + { + WPRINT_WHD_ERROR( ("%s:%d index > c->bufsize \n", __FUNCTION__, __LINE__) ); + result = WHD_WLAN_BUFTOOSHORT; + goto done; + } + + /* Skip reading the console buffer if the index pointer has not moved */ + if (index == c->last) + { + result = WHD_SUCCESS; + goto done; + } + + /* Read the console buffer */ + /* xxx this could optimize and read only the portion of the buffer needed, but + * it would also have to handle wrap-around. + */ + address = dtoh32(c->log.buf); + result = whd_bus_transfer_backplane_bytes(whd_driver, BUS_READ, address, c->bufsize, (uint8_t *)c->buf); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_transfer_backplane_bytes failed\n", __FUNCTION__, __LINE__) ); + goto done; + } + + while (c->last != index) + { + for (n = 0; n < buffer_size - 2; n++) + { + if (c->last == index) + { + /* This would output a partial line. Instead, back up + * the buffer pointer and output this line next time around. + */ + if (c->last >= n) + { + c->last -= n; + } + else + { + c->last = c->bufsize - n; + } + /* Save last read position */ + whd_driver->internal_info.con_lastpos = c->last; + + result = WHD_SUCCESS; + goto done; + } + ch = c->buf[c->last]; + c->last = (c->last + 1) % c->bufsize; + if (ch == '\n') + { + break; + } + buffer[n] = ch; + } + if (n > 0) + { + if (buffer[n - 1] == '\r') + n--; + buffer[n] = 0; + WPRINT_MACRO( ("CONSOLE: %s\n", buffer) ); + } + } + /* Save last read position */ + whd_driver->internal_info.con_lastpos = c->last; + result = WHD_SUCCESS; + +done: return result; +} + +void whd_wifi_peek(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, uint8_t *value) +{ + uint8_t status; + + WHD_WLAN_KEEP_AWAKE(whd_driver); + + status = whd_bus_read_backplane_value(whd_driver, address, register_length, value); + + if (status != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error reading interrupt status\n", __FUNCTION__) ); + } + + WHD_WLAN_LET_SLEEP(whd_driver); +} + +void whd_wifi_poke(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, uint32_t value) +{ + uint8_t status; + + WHD_WLAN_KEEP_AWAKE(whd_driver); + + status = whd_bus_write_backplane_value(whd_driver, address, register_length, value); + + if (status != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Error clearing the interrupt status\n", __FUNCTION__) ); + } + + WHD_WLAN_LET_SLEEP(whd_driver); +} + +whd_result_t whd_ioctl_log_add(whd_driver_t whd_driver, uint32_t cmd, whd_buffer_t buffer) +{ + uint8_t *data = NULL; + size_t data_size = whd_buffer_get_current_piece_size(whd_driver, buffer); + + data = whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + CHECK_IOCTL_BUFFER(data); + CHECK_RETURN(cy_rtos_get_semaphore(&whd_driver->whd_log_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE) ); + data = data + IOCTL_OFFSET; + data_size = data_size - IOCTL_OFFSET; + whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].ioct_log = cmd; + whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].is_this_event = 0; + whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].data_size = MIN_OF( + WHD_MAX_DATA_SIZE, data_size); + memset(whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].data, 0, + WHD_MAX_DATA_SIZE); + memcpy(whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].data, data, + whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].data_size); + + whd_driver->whd_ioctl_log_index++; + CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->whd_log_mutex, WHD_FALSE) ); + return WHD_SUCCESS; +} + +whd_result_t whd_ioctl_log_add_event(whd_driver_t whd_driver, uint32_t cmd, uint16_t flag, uint32_t reason) +{ + CHECK_RETURN(cy_rtos_get_semaphore(&whd_driver->whd_log_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE) ); + whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].is_this_event = 1; + whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].ioct_log = cmd; + whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].flag = flag; + whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].reason = reason; + + whd_driver->whd_ioctl_log_index++; + CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->whd_log_mutex, WHD_FALSE) ); + return WHD_SUCCESS; +} + +whd_result_t whd_ioctl_print(whd_driver_t whd_driver) +{ + int i; + uint8_t *data = NULL; + size_t iovar_string_size = 0; + + CHECK_RETURN(cy_rtos_get_semaphore(&whd_driver->whd_log_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE) ); + for (i = 0; i < WHD_IOCTL_LOG_SIZE; i++) + { + char iovar[WHD_IOVAR_STRING_SIZE] = {0}; + data = whd_driver->whd_ioctl_log[i].data; + + if ( (whd_driver->whd_ioctl_log[i].ioct_log == WLC_SET_VAR) || + (whd_driver->whd_ioctl_log[i].ioct_log == WLC_GET_VAR) ) + { + /* refer to whd_cdc_get_iovar_buffer() */ + while (!*data) + { + whd_driver->whd_ioctl_log[i].data_size--; + data++; + } + + if (strlen( (char *)data ) <= WHD_IOVAR_STRING_SIZE) + strncpy(iovar, (char *)data, strlen( (char *)data ) ); + + iovar_string_size = strlen( (const char *)data ); + iovar[iovar_string_size] = '\0'; + data += (iovar_string_size + 1); + whd_driver->whd_ioctl_log[i].data_size -= (iovar_string_size + 1); + } + if (whd_driver->whd_ioctl_log[i].is_this_event == 1) + { + whd_event_info_to_string(whd_driver->whd_ioctl_log[i].ioct_log, whd_driver->whd_ioctl_log[i].flag, + whd_driver->whd_ioctl_log[i].reason, iovar, sizeof(iovar) - 1); + WPRINT_MACRO( ("\n<- E:%" PRIu32 "\t\t\tS:%d\t\t\t\tR:%" PRIu32 "\n%s\n", + whd_driver->whd_ioctl_log[i].ioct_log, + whd_driver->whd_ioctl_log[i].flag, whd_driver->whd_ioctl_log[i].reason, iovar) ); + } + else if (whd_driver->whd_ioctl_log[i].ioct_log == WLC_SET_VAR) + { + WPRINT_MACRO( ("\n-> %s\n", iovar) ); + whd_hexdump(data, whd_driver->whd_ioctl_log[i].data_size); + } + else if (whd_driver->whd_ioctl_log[i].ioct_log == WLC_GET_VAR) + { + WPRINT_MACRO( ("\n<- %s\n", iovar) ); + whd_hexdump(data, whd_driver->whd_ioctl_log[i].data_size); + } + else if (whd_driver->whd_ioctl_log[i].ioct_log != 0) + { + whd_ioctl_info_to_string(whd_driver->whd_ioctl_log[i].ioct_log, iovar, sizeof(iovar) - 1); + WPRINT_MACRO( ("\n%s:%" PRIu32 "\n", iovar, whd_driver->whd_ioctl_log[i].ioct_log) ); + whd_hexdump(data, whd_driver->whd_ioctl_log[i].data_size); + } + } + + memset(whd_driver->whd_ioctl_log, 0, sizeof(whd_driver->whd_ioctl_log) ); + whd_driver->whd_ioctl_log_index = 0; + CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->whd_log_mutex, WHD_FALSE) ); + return WHD_SUCCESS; +} + +void whd_wifi_chip_info_init(whd_driver_t whd_driver) +{ + whd_driver->chip_info.save_restore_enable = WHD_FALSE; +} + +whd_result_t whd_wifi_set_custom_country_code(whd_interface_t ifp, const whd_country_info_t *country_code) +{ + whd_driver_t whd_driver = ifp->whd_driver; + + /* Get chip number */ + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + if (wlan_chip_id == 43362) + { + whd_buffer_t buffer; + whd_result_t result; + whd_country_info_t *data; + data = (whd_country_info_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, + (uint16_t)sizeof(whd_country_info_t) + 10); + if (data == NULL) + { + whd_assert("Could not get buffer for IOCTL", 0 != 0); + return WHD_BUFFER_ALLOC_FAIL; + } + memcpy(data, country_code, sizeof(whd_country_info_t) ); + result = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_CUSTOM_COUNTRY, buffer, NULL); + return result; + } + else + { + UNUSED_PARAMETER(country_code); + return WHD_UNSUPPORTED; + } +} + +whd_result_t whd_chip_specific_socsram_init(whd_driver_t whd_driver) +{ + /* Get chip number */ + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + if ( (wlan_chip_id == 43430) || (wlan_chip_id == 43439) ) + { + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, SOCSRAM_BANKX_INDEX(whd_driver), 4, 0x3) ); + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, SOCSRAM_BANKX_PDA(whd_driver), 4, 0) ); + return WHD_SUCCESS; + } + else + { + return WHD_SUCCESS; + } +} + +whd_result_t whd_chip_specific_init(whd_driver_t whd_driver) +{ + /* Get chip number */ + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43362) ) + { + return WHD_SUCCESS; + } + else + { + return whd_enable_save_restore(whd_driver); + } +} + +whd_result_t whd_allow_wlan_bus_to_sleep(whd_driver_t whd_driver) +{ + /* Get chip number */ + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + whd_bt_dev_t btdev = whd_driver->bt_dev; + if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43362) ) + { + /* Clear HT clock request */ + if (whd_bus_is_up(whd_driver) == WHD_TRUE) + { + whd_bus_set_state(whd_driver, WHD_FALSE); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR, + (uint8_t)1, 0) ); + /* Bus specific sleep routine */ + return whd_bus_sleep(whd_driver); + } + else + { + return WHD_SUCCESS; + } + } + else + { + /* Clear HT clock request */ + if (whd_bus_is_up(whd_driver) == WHD_TRUE) + { + whd_bus_set_state(whd_driver, WHD_FALSE); + if (whd_driver->chip_info.save_restore_enable == WHD_FALSE) + { + return whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR, + (uint8_t)1, 0); + } + else + { + if (btdev && btdev->bt_int_cb) + { + return WHD_SUCCESS; + } + return whd_kso_enable(whd_driver, WHD_FALSE); + } + } + else + { + return WHD_SUCCESS; + } + } +} + +whd_result_t whd_wifi_read_wlan_log(whd_driver_t whd_driver, char *buffer, uint32_t buffer_size) +{ + whd_result_t result; + uint32_t wlan_shared_address; + uint16_t wlan_chip_id = 0; + + CHECK_DRIVER_NULL(whd_driver); + + WHD_IOCTL_PRINT(whd_driver); + + wlan_chip_id = whd_chip_get_chip_id(whd_driver); + if (wlan_chip_id == 43362) + { + return whd_wifi_read_wlan_log_unsafe(whd_driver, ( (GET_C_VAR(whd_driver, CHIP_RAM_SIZE) + + PLATFORM_WLAN_RAM_BASE) - 4 ), buffer, buffer_size); + } + else if ( (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) ) + { + result = whd_ensure_wlan_bus_is_up(whd_driver); + if (result != WHD_SUCCESS) + { + return result; + } + result = whd_wifi_read_wlan_log_unsafe(whd_driver, ( (GET_C_VAR(whd_driver, CHIP_RAM_SIZE) + + GET_C_VAR(whd_driver, + ATCM_RAM_BASE_ADDRESS) ) - 4 ), buffer, + buffer_size); + whd_thread_notify(whd_driver); + return result; + } + else if ( (wlan_chip_id == 4334) || (wlan_chip_id == 4390) ) + { + return WHD_UNSUPPORTED; + } + else + { + /* Backplane access needs HT clock. So, disabling bus sleep */ + WHD_WLAN_KEEP_AWAKE(whd_driver); + /* FW populates the last word of RAM with wlan_shared_t struct address */ + wlan_shared_address = PLATFORM_WLAN_RAM_BASE + GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS) + + GET_C_VAR(whd_driver, CHIP_RAM_SIZE) - 4; + if (!GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS) && (whd_is_fw_sr_capable(whd_driver) == WHD_TRUE) ) + { + wlan_shared_address -= GET_C_VAR(whd_driver, SOCRAM_SRMEM_SIZE); + } + result = whd_wifi_read_wlan_log_unsafe(whd_driver, wlan_shared_address, buffer, buffer_size); + WHD_WLAN_LET_SLEEP(whd_driver); + return result; + } + +} + +uint32_t whd_wifi_print_whd_log(whd_driver_t whd_driver) +{ + whd_result_t result; + char *buffer = NULL; + + CHECK_DRIVER_NULL(whd_driver); + + WHD_IOCTL_PRINT(whd_driver); + + if ( (buffer = malloc(WLAN_LOG_BUF_LEN) ) == NULL ) + { + WPRINT_WHD_ERROR( ("Memory allocation failed for log buffer in %s \n", __FUNCTION__) ); + return WHD_MALLOC_FAILURE; + } + + result = whd_wifi_read_wlan_log(whd_driver, buffer, WLAN_LOG_BUF_LEN); + if (result == WHD_SUCCESS) + { + whd_print_logbuffer(); // This is not supported yet. + } + free(buffer); + CHECK_RETURN(result); + return result; +} + +whd_result_t whd_wifi_read_fw_capabilities(whd_interface_t ifp) +{ + whd_result_t result; + char caps[MAX_CAPS_BUFFER_SIZE]; + whd_fwcap_id_t id; + + CHECK_IFP_NULL(ifp); + whd_driver_t whd_driver = ifp->whd_driver; + + result = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_CAP, (uint8_t *)caps, sizeof(caps) ); + CHECK_RETURN(result); + + for (uint32_t i = 0; i < WHD_ARRAY_SIZE(whd_fwcap_map); i++) + { + if (strstr(caps, whd_fwcap_map[i].fwcap_name) ) + { + id = whd_fwcap_map[i].feature; + WPRINT_WHD_DEBUG( ("Enabling FW Capabilities: %s\n", whd_fwcap_map[i].fwcap_name) ); + whd_driver->chip_info.fwcap_flags |= (1 << id); + } + } + return WHD_SUCCESS; +} + +whd_result_t whd_ensure_wlan_bus_is_up(whd_driver_t whd_driver) +{ + uint8_t csr = 0; + uint32_t attempts = ( uint32_t )WLAN_BUS_UP_ATTEMPTS; + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + + /* Ensure HT clock is up */ + if (whd_bus_is_up(whd_driver) == WHD_TRUE) + { + return WHD_SUCCESS; + } + + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) ) + { + /* Bus specific wakeup routine */ + CHECK_RETURN(whd_bus_wakeup(whd_driver) ); + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR, + (uint8_t)1, (uint32_t)SBSDIO_HT_AVAIL_REQ) ); + do + { + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR, + (uint8_t)1, &csr) ); + --attempts; + } while ( ( (csr & SBSDIO_HT_AVAIL) == 0 ) && (attempts != 0) && + (cy_rtos_delay_milliseconds( (uint32_t)1 ), 1 == 1) ); + + if (attempts == 0) + { + WPRINT_WHD_ERROR( ("SDIO bus failed to come up , %s failed at %d \n", __func__, __LINE__) ); + return WHD_SDIO_BUS_UP_FAIL; + } + else + { + whd_bus_set_state(whd_driver, WHD_TRUE); + return WHD_SUCCESS; + } + } + else if ( (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) ) + { + //To-Do + /* M2M power save mode */ + //M2M_POWERSAVE_COMM_TX_BEGIN + return WHD_SUCCESS; + } + else + { + if (whd_driver->chip_info.save_restore_enable == WHD_FALSE) + { + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR, + (uint8_t)1, (uint32_t)SBSDIO_HT_AVAIL_REQ) ); + do + { + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR, + (uint8_t)sizeof(csr), &csr) ); + --attempts; + } while ( ( (csr & SBSDIO_HT_AVAIL) == 0 ) && (attempts != 0) && + (cy_rtos_delay_milliseconds( ( uint32_t )HT_AVAIL_WAIT_MS ), 1 == 1) ); + + if (attempts == 0) + { + WPRINT_WHD_ERROR( ("SDIO bus failed to come up , %s failed at %d \n", __func__, __LINE__) ); + return WHD_SDIO_BUS_UP_FAIL; + } + else + { + whd_bus_set_state(whd_driver, WHD_TRUE); + return WHD_SUCCESS; + } + } + else + { + if (whd_kso_enable(whd_driver, WHD_TRUE) == WHD_SUCCESS) + { + whd_bus_set_state(whd_driver, WHD_TRUE); + return WHD_SUCCESS; + } + else + { + WPRINT_WHD_ERROR( ("SDIO bus failed to come up , %s failed at %d \n", __func__, __LINE__) ); + return WHD_SDIO_BUS_UP_FAIL; + } + } + } +} + +static whd_bool_t whd_is_fw_sr_capable(whd_driver_t whd_driver) +{ + uint32_t core_capext; + uint32_t retention_ctl = 0; + uint32_t srctrl = 0; + whd_bool_t save_restore_capable = WHD_FALSE; + whd_result_t result = WHD_SUCCESS; + + /* Get chip number */ + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + + if ( (wlan_chip_id == 43430) || (wlan_chip_id == 43439) ) + { + /* check if fw initialized sr engine */ + if (whd_bus_read_backplane_value(whd_driver, (uint32_t)CHIPCOMMON_SR_CONTROL1, (uint8_t)4, + (uint8_t *)&srctrl) != WHD_SUCCESS) + { + return WHD_FALSE; + } + if (srctrl != 0) + { + return WHD_TRUE; + } + else + { + return WHD_FALSE; + } + } + else if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + /* check if fw initialized sr engine */ + result = whd_bus_read_backplane_value(whd_driver, (uint32_t)CHIPCOMMON_CORE_CAPEXT_ADDR, (uint8_t)4, + (uint8_t *)&core_capext); + if (result != WHD_SUCCESS) + { + return WHD_FALSE; + } + + if ( (core_capext & CHIPCOMMON_CORE_CAPEXT_SR_SUPPORTED) != 0 ) + { + result = whd_bus_read_backplane_value(whd_driver, (uint32_t)CHIPCOMMON_CORE_RETENTION_CTL, (uint8_t)4, + (uint8_t *)&retention_ctl); + if (result != WHD_SUCCESS) + { + return WHD_FALSE; + } + if ( (retention_ctl & (CHIPCOMMON_CORE_RCTL_MACPHY_DISABLE | CHIPCOMMON_CORE_RCTL_LOGIC_DISABLE) ) == 0 ) + { + save_restore_capable = WHD_TRUE; + } + } + return save_restore_capable; + } + else + { + /* check if fw initialized sr engine */ + result = + whd_bus_read_backplane_value(whd_driver, (uint32_t)RETENTION_CTL( + whd_driver), (uint8_t)sizeof(retention_ctl), + (uint8_t *)&retention_ctl); + if (result != WHD_SUCCESS) + { + return WHD_FALSE; + } + if ( (retention_ctl & (RCTL_MACPHY_DISABLE | RCTL_LOGIC_DISABLE) ) == 0 ) + { + save_restore_capable = WHD_TRUE; + } + return save_restore_capable; + } +} + +static whd_result_t whd_enable_save_restore(whd_driver_t whd_driver) +{ + uint8_t data; + /* Get chip number */ + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + + if (whd_is_fw_sr_capable(whd_driver) == WHD_TRUE) + { + if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) ) + { + /* Configure WakeupCtrl register to set AlpAvail request bit in chipClockCSR register + * after the sdiod core is powered on. + */ + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_WAKEUP_CTRL, + (uint8_t)sizeof(data), &data) ); + data |= SBSDIO_WCTRL_WAKE_TILL_ALP_AVAIL; + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_WAKEUP_CTRL, + (uint8_t)sizeof(data), data) ); + } + else + { + /* Configure WakeupCtrl register to set HtAvail request bit in chipClockCSR register + * after the sdiod core is powered on. + */ + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_WAKEUP_CTRL, + (uint8_t)1, &data) ); + data |= SBSDIO_WCTRL_WAKE_TILL_HT_AVAIL; + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_WAKEUP_CTRL, + (uint8_t)1, data) ); + } + + /* Set brcmCardCapability to noCmdDecode mode. + * It makes sdiod_aos to wakeup host for any activity of cmd line, even though + * module won't decode cmd or respond + */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, (uint32_t)SDIOD_CCCR_BRCM_CARDCAP, + (uint8_t)1, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC) ); + if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) ) + { + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR, + (uint8_t)1, SBSDIO_HT_AVAIL_REQ) ); + } + else + { + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR, + (uint8_t)1, (uint32_t)SBSDIO_FORCE_HT) ); + } + + /* Enable KeepSdioOn (KSO) bit for normal operation */ + if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) ) + { + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, + (uint8_t)sizeof(data), &data) ); + } + else + { + CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, + (uint8_t)1, &data) ); + } + if ( (data & SBSDIO_SLPCSR_KEEP_SDIO_ON) == 0 ) + { + data |= SBSDIO_SLPCSR_KEEP_SDIO_ON; + if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) ) + { + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, + (uint8_t)sizeof(data), data) ); + } + else + { + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, + (uint8_t)1, data) ); + } + } + + /* SPI bus can be configured for sleep by default. + * KSO bit solely controls the wlan chip sleep + */ + CHECK_RETURN(whd_bus_sleep(whd_driver) ); + + /* Put SPI interface block to sleep */ + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_PULL_UP, (uint8_t)1, 0xf) ); + + whd_driver->chip_info.save_restore_enable = WHD_TRUE; + } + else + { + whd_driver->chip_info.save_restore_enable = WHD_FALSE; + } + + return WHD_SUCCESS; +} + +static whd_result_t whd_kso_enable(whd_driver_t whd_driver, whd_bool_t enable) +{ + uint8_t write_value = 0; + uint8_t read_value = 0; + uint8_t compare_value; + uint8_t bmask; + uint32_t attempts = ( uint32_t )MAX_KSO_ATTEMPTS; + whd_result_t result; + /* Get chip number */ + + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + if (enable == WHD_TRUE) + { + write_value |= SBSDIO_SLPCSR_KEEP_SDIO_ON; + } + + /* 1st KSO write goes to AOS wake up core if device is asleep */ + /* Possibly device might not respond to this cmd. So, don't check return value here */ + if ( (wlan_chip_id == 43430) || (wlan_chip_id == 43439) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + /* 2 Sequential writes to KSO bit are required for SR module to wakeup, both write can fail */ + CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, + (uint8_t)1, + write_value) ); + CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, + (uint8_t)1, + write_value) ); + if (enable == WHD_TRUE) + { + /* device WAKEUP through KSO: + * write bit 0 & read back until + * both bits 0(kso bit) & 1 (dev on status) are set + */ + compare_value = SBSDIO_SLPCSR_KEEP_SDIO_ON | SBSDIO_SLPCSR_DEVICE_ON; + bmask = compare_value; + } + else + { + /* Put device to sleep, turn off KSO */ + compare_value = 0; + /* Check for bit0 only, bit1(devon status) may not get cleared right away */ + bmask = SBSDIO_SLPCSR_KEEP_SDIO_ON; + } + } + else + { + CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, + (uint8_t)1, write_value) ); + + /* In case of 43012 chip, the chip could go down immediately after KSO bit is cleared. + * So the further reads of KSO register could fail. Thereby just bailing out immediately + * after clearing KSO bit, to avoid polling of KSO bit. + */ + if (enable == WHD_FALSE) + { + return WHD_SUCCESS; + } + + /* 2 Sequential writes to KSO bit are required for SR module to wakeup */ + CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, + (uint8_t)1, write_value) ); + + /* device WAKEUP through KSO: + * write bit 0 & read back until + * both bits 0(kso bit) & 1 (dev on status) are set + */ + compare_value = SBSDIO_SLPCSR_KEEP_SDIO_ON | SBSDIO_SLPCSR_DEVICE_ON; + bmask = compare_value; + } + + while (attempts != 0) + { + /* Reliable KSO bit set/clr: + * Sdiod sleep write access appears to be in sync with PMU 32khz clk + * just one write attempt may fail,(same is with read ?) + * in any case, read it back until it matches written value + */ + result = whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, (uint8_t)1, + &read_value); + if ( ( (read_value & bmask) == compare_value ) && (result == WHD_SUCCESS) && (read_value != 0xFF) ) + { + break; + } + + cy_rtos_delay_milliseconds( ( uint32_t )KSO_WAIT_MS ); + + CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, + (uint8_t)1, write_value) ); + attempts--; + } + + if (attempts == 0) + { + WPRINT_WHD_ERROR( ("SDIO bus failed to come up , %s failed at %d \n", __func__, __LINE__) ); + return WHD_SDIO_BUS_UP_FAIL; + } + else + { + return WHD_SUCCESS; + } +} + +void whd_wlan_wake_from_host(whd_driver_t whd_driver); + +void whd_wlan_wake_from_host(whd_driver_t whd_driver) +{ + uint32_t val32 = 0; + whd_result_t result; + + result = whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, D11_MACCONTROL_REG_SIZE, (uint8_t *)&val32); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ); + } + WPRINT_WHD_DEBUG( ("%s: %d:before: maccontrol: 0x%08x\n", __FUNCTION__, __LINE__, (unsigned int)val32) ); + + val32 = val32 | D11_MACCONTROL_REG_WAKE; + result = whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, D11_MACCONTROL_REG_SIZE, val32); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) ); + } + result = whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, D11_MACCONTROL_REG_SIZE, (uint8_t *)&val32); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) ) + } + WPRINT_WHD_DEBUG( ("%s: %d:after: maccontrol: 0x%08x\n", __FUNCTION__, __LINE__, (unsigned int)val32) ); +} + +whd_result_t whd_wlan_bus_complete_ds_wake(whd_driver_t whd_driver, whd_bool_t wake_from_firmware, + uint32_t wake_event_indication_addr, uint32_t wake_indication_addr, + uint32_t sdio_control_addr) +{ + uint32_t val = 0; + uint32_t val1 = 0; + uint32_t count = 0; + int32_t timeout = 0; + /* Get chip number */ + + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + + if (wlan_chip_id == 43012) + { + WPRINT_WHD_DEBUG_DS( ("%s: enter: wake_fr_fw=%d\n", __func__, (int )wake_from_firmware) ); + + /* Need to do for all wake causes */ + while (WHD_SUCCESS != + whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1, SDIO_FUNC_ENABLE_1) ) + { + WPRINT_WHD_DEBUG( ("Retry IOEN write\n") ); + cy_rtos_delay_milliseconds(10); + } + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(wake_event_indication_addr), 2, + (uint8_t *)&val) ); + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(wake_indication_addr), 2, (uint8_t *)&val) ); + + if (WHD_TRUE == wake_from_firmware) + { + WPRINT_WHD_DEBUG_DS( ("%s: CCCR written\n", __func__) ); + + /* Read DS1 CTRL STATUS SHM to Check whether HOST MAIL BOX interrupt is triggered due to TX/RX + * For RX Cases , Value will be DS1_SLEEP + * For TX Cases, Value will be MAC ON or RADIO_PHY_ON + */ + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_STATUS), (uint8_t)2, + (uint8_t *)&val) ); + if (val == DS1_SLEEP) + { + /* HUDI communication to inform D11 to Process and Exit DS1 not required for D11 Wake cases + * Simply update PMU Resource Mask and Re-download firmware for this case + */ + WPRINT_WHD_DEBUG_DS( ("%s: D11 wake detected\n", __func__) ); + + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, PMU_MINRESMASK, 1, + DEFAULT_43012_MIN_RES_MASK) ); + + return WHD_SUCCESS; + } + + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), 2, + C_DS1_CTRL_SDIO_DS1_EXIT | C_DS1_CTRL_REQ_VALID) ); + WPRINT_WHD_DEBUG_DS( ("%s: SDIO ctl written\n", __func__) ); + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), (uint8_t)2, + (uint8_t *)&val) ); + WPRINT_WHD_DEBUG_DS( ("%s: M_DS1_CTRL_SDIO = [%x]\n", __func__, (int )val) ); + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, (uint8_t)2, (uint8_t *)&val1) ); + WPRINT_WHD_DEBUG_DS( ("%s: before setting wake = [%x]\n", __func__, (int )val1) ); + + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, 2, + val1 | D11_MACCONTROL_REG_WAKE) ); + WPRINT_WHD_DEBUG_DS( ("%s: After setting wake= [%x]\n", __func__, (int )val1) ); + + while (!(val & C_DS1_CTRL_PROC_DONE) ) + { + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), (uint8_t)2, + (uint8_t *)&val) ); + count++; + if (count == 1000) + { + WPRINT_WHD_ERROR( ("%s: sdio timed out! Aborting\n", __func__) ); + return WHD_TIMEOUT; + } + } + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), (uint8_t)2, + (uint8_t *)&val) ); + WPRINT_WHD_DEBUG_DS( ("%s: M_DS1_CTRL_SDIO after poll = [%x]\n", __func__, (int )val) ); + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, (uint8_t)2, (uint8_t *)&val1) ); + WPRINT_WHD_DEBUG_DS( ("%s: D11_MACCONTROL_REG before Clear = [%x]\n", __func__, (int )val1) ); + + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, 2, + val1 & D11_MACCONTROL_CLEAR_WAKE) ); + WPRINT_WHD_DEBUG_DS( ("%s: D11_MACCONTROL_REG after Clear = [%x]\n", __func__, (int )val1) ); + + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, PMU_MINRESMASK, 1, DEFAULT_43012_MIN_RES_MASK) ); + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, PMU_MINRESMASK, (uint8_t)1, (uint8_t *)&val1) ); + + WPRINT_WHD_DEBUG_DS( ("%s: PMU_MINRESMASK = [%x]\n", __func__, (int )val1) ); + } + else + { + while (WHD_SUCCESS != whd_ensure_wlan_bus_is_up(whd_driver) ) + { + WPRINT_WHD_DEBUG_DS( ("Retrying bus is up\n") ); + } + + WPRINT_WHD_DEBUG_DS( ("write backplane\n") ); + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(sdio_control_addr), 2, (uint8_t *)&val) ); + + while (WHD_SUCCESS != + whd_bus_write_backplane_value(whd_driver, D11SHM_ADDR(sdio_control_addr), 2, + val | C_DS1_CTRL_SDIO_DS1_EXIT | C_DS1_CTRL_REQ_VALID) ) + { + WPRINT_WHD_DEBUG_DS( ("Retrying backplane write; addr=%x\n", + (unsigned int )D11SHM_ADDR(sdio_control_addr) ) ); + cy_rtos_delay_milliseconds(100); + } + + WPRINT_WHD_DEBUG_DS( ("wake host\n") ); + whd_wlan_wake_from_host(whd_driver); + + WPRINT_WHD_DEBUG_DS( ("poll for timeout\n") ); + /* Poll for PROC_DONE to be set by ucode; timeout after a good amount of time */ + for (timeout = WHD_WLAN_WAKE_TIMEOUT * 10, val = 0; timeout >= 0; + timeout -= WHD_SHARED_MEMORY_POLLING_DELAY) + { + whd_result_t read_result = + whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(sdio_control_addr), 2, (uint8_t *)&val); + + if ( (WHD_SUCCESS != read_result) || !( (val) & C_DS1_CTRL_PROC_DONE ) ) + { + cy_rtos_delay_milliseconds (WHD_SHARED_MEMORY_POLLING_DELAY); + } + else + { + /* success! */ + WPRINT_WHD_DEBUG_DS( ("Ucode has posted DONE\n") ); + break; + } + } + + WPRINT_WHD_DEBUG_DS( ("%s: %d: 0x%08x\n", __func__, __LINE__, (unsigned int)val) ); + + if ( (timeout < 0) && !(val & C_DS1_CTRL_PROC_DONE) ) + { + WPRINT_WHD_ERROR( ("%s: Failed to enter DS1 Exit state!\n", __func__) ); + return WHD_TIMEOUT; + } + } + WPRINT_WHD_DEBUG_DS( ("successfully completed DS wake sequence\n") ); + return WHD_SUCCESS; + } + else + { + UNUSED_PARAMETER(wake_from_firmware); + UNUSED_PARAMETER(wake_event_indication_addr); + UNUSED_PARAMETER(wake_indication_addr); + UNUSED_PARAMETER(sdio_control_addr); + + WPRINT_WHD_DEBUG( ("%s: enter\n", __FUNCTION__) ); + + CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1, + SDIO_FUNC_ENABLE_1) ); + WPRINT_WHD_DEBUG( ("%s: CCCR written\n", __FUNCTION__) ); + + /* Read DS1 CTRL STATUS SHM to Check whether HOST MAIL BOX interrupt is triggered due to TX/RX + * For RX Cases , Value will be DS1_SLEEP + * For TX Cases, Value will be MAC ON or RADIO_PHY_ON + */ + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_STATUS), (uint8_t)2, + (uint8_t *)&val) ); + if (val == DS1_SLEEP) + { + /* HUDI communication to inform D11 to Process and Exit DS1 not required for D11 Wake cases + * Simply update PMU Resource Mask and Re-download firmware for this case + */ + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, PMU_MINRESMASK, 1, DEFAULT_43012_MIN_RES_MASK) ); + return WHD_SUCCESS; + } + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), 2, + C_DS1_CTRL_SDIO_DS1_EXIT | C_DS1_CTRL_REQ_VALID) ); + WPRINT_WHD_DEBUG( ("%s: SDIO ctl written\n", __FUNCTION__) ); + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR( + M_DS1_CTRL_SDIO), (uint8_t)2, (uint8_t *)&val) ); + WPRINT_WHD_DEBUG( ("%s: M_DS1_CTRL_SDIO = [%x]\n", __FUNCTION__, (int)val) ); + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, (uint8_t)2, (uint8_t *)&val1) ); + WPRINT_WHD_DEBUG( ("%s: before setting wake = [%x]\n", __FUNCTION__, (int)val1) ); + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, 2, + val1 | D11_MACCONTROL_REG_WAKE) ); + WPRINT_WHD_DEBUG( ("%s: After setting wake= [%x]\n", __FUNCTION__, (int)val1) ); + + while (!(val & C_DS1_CTRL_PROC_DONE) ) + { + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), (uint8_t)2, + (uint8_t *)&val) ); + count++; + if (count == 1000) + { + WPRINT_WHD_ERROR( ("%s: sdio timed out! Aborting\n", __FUNCTION__) ); + return WHD_TIMEOUT; + } + } + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR( + M_DS1_CTRL_SDIO), (uint8_t)2, (uint8_t *)&val) ); + WPRINT_WHD_DEBUG( ("%s: M_DS1_CTRL_SDIO after poll = [%x]\n", __FUNCTION__, (int)val) ); + + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, (uint8_t)2, (uint8_t *)&val1) ); + WPRINT_WHD_DEBUG( ("%s: D11_MACCONTROL_REG before Clear = [%x]\n", __FUNCTION__, (int)val1) ); + + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, 2, + val1 & D11_MACCONTROL_CLEAR_WAKE) ); + WPRINT_WHD_DEBUG( ("%s: D11_MACCONTROL_REG after Clear = [%x]\n", __FUNCTION__, (int)val1) ); + + CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, PMU_MINRESMASK, 1, DEFAULT_43012_MIN_RES_MASK) ); + CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, PMU_MINRESMASK, (uint8_t)1, (uint8_t *)&val1) ); + WPRINT_WHD_DEBUG( ("%s: PMU_MINRESMASK = [%x]\n", __FUNCTION__, (int)val1) ); + return WHD_SUCCESS; + } +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_chip_constants.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_chip_constants.c new file mode 100644 index 00000000..128a9bed --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_chip_constants.c @@ -0,0 +1,447 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "whd_chip_constants.h" +#include "whd_wlioctl.h" +#include "whd_int.h" +#include "whd_types_int.h" +#include "bus_protocols/whd_chip_reg.h" + +/****************************************************** +* Function Definitions +******************************************************/ + +uint32_t whd_chip_set_chip_id(whd_driver_t whd_driver, uint16_t id) +{ + whd_driver->chip_info.chip_id = id; + + return 0; +} + +uint16_t whd_chip_get_chip_id(whd_driver_t whd_driver) +{ + return whd_driver->chip_info.chip_id; +} + +uint32_t get_whd_var(whd_driver_t whd_driver, chip_var_t var) +{ + uint32_t val = 0; + + uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver); + switch (var) + { + case ARM_CORE_BASE_ADDRESS: + CHECK_RETURN(get_arm_core_base_address(wlan_chip_id, &val) ); + break; + case SOCSRAM_BASE_ADDRESS: + CHECK_RETURN(get_socsram_base_address(wlan_chip_id, &val, false) ); + break; + case SOCSRAM_WRAPPER_BASE_ADDRESS: + CHECK_RETURN(get_socsram_base_address(wlan_chip_id, &val, true) ); + break; + case SDIOD_CORE_BASE_ADDRESS: + CHECK_RETURN(get_sdiod_core_base_address(wlan_chip_id, &val) ); + break; + case PMU_BASE_ADDRESS: + CHECK_RETURN(get_pmu_base_address(wlan_chip_id, &val) ); + break; + case CHIP_RAM_SIZE: + CHECK_RETURN(get_chip_ram_size(wlan_chip_id, &val) ); + break; + case ATCM_RAM_BASE_ADDRESS: + CHECK_RETURN(get_atcm_ram_base_address(wlan_chip_id, &val) ); + break; + case SOCRAM_SRMEM_SIZE: + CHECK_RETURN(get_socsram_srmem_size(wlan_chip_id, &val) ); + break; + case CHANSPEC_BAND_MASK: + CHECK_RETURN(get_wl_chanspec_band_mask(wlan_chip_id, &val) ); + break; + case CHANSPEC_BAND_2G: + CHECK_RETURN(get_wl_chanspec_band_2G(wlan_chip_id, &val) ); + break; + case CHANSPEC_BAND_5G: + CHECK_RETURN(get_wl_chanspec_band_5G(wlan_chip_id, &val) ); + break; + case CHANSPEC_BAND_SHIFT: + CHECK_RETURN(get_wl_chanspec_band_shift(wlan_chip_id, &val) ); + break; + case CHANSPEC_BW_10: + CHECK_RETURN(get_wl_chanspec_bw_10(wlan_chip_id, &val) ); + break; + case CHANSPEC_BW_20: + CHECK_RETURN(get_wl_chanspec_bw_20(wlan_chip_id, &val) ); + break; + case CHANSPEC_BW_40: + CHECK_RETURN(get_wl_chanspec_bw_40(wlan_chip_id, &val) ); + break; + case CHANSPEC_BW_MASK: + CHECK_RETURN(get_wl_chanspec_bw_mask(wlan_chip_id, &val) ); + break; + case CHANSPEC_BW_SHIFT: + CHECK_RETURN(get_wl_chanspec_bw_shift(wlan_chip_id, &val) ); + break; + case CHANSPEC_CTL_SB_LOWER: + CHECK_RETURN(get_wl_chanspec_ctl_sb_lower(wlan_chip_id, &val) ); + break; + case CHANSPEC_CTL_SB_UPPER: + CHECK_RETURN(get_wl_chanspec_ctl_sb_upper(wlan_chip_id, &val) ); + break; + case CHANSPEC_CTL_SB_NONE: + CHECK_RETURN(get_wl_chanspec_ctl_sb_none(wlan_chip_id, &val) ); + break; + case CHANSPEC_CTL_SB_MASK: + CHECK_RETURN(get_wl_chanspec_ctl_sb_mask(wlan_chip_id, &val) ); + break; + default: + break; + } + return val; +} + +whd_result_t get_arm_core_base_address(uint16_t wlan_chip_id, uint32_t *addr) +{ + switch (wlan_chip_id) + { + case 0x4373: + *addr = 0x18002000 + WRAPPER_REGISTER_OFFSET; + break; + case 43012: + case 43430: + case 43439: + *addr = 0x18003000 + WRAPPER_REGISTER_OFFSET; + break; + case 43909: + case 43907: + case 54907: + *addr = 0x18011000 + WRAPPER_REGISTER_OFFSET; + break; + default: + return WHD_BADARG; + } + return WHD_SUCCESS; +} + +whd_result_t get_socsram_base_address(uint16_t wlan_chip_id, uint32_t *addr, whd_bool_t wrapper) +{ + uint32_t offset = 0; + if (wrapper) + { + offset = WRAPPER_REGISTER_OFFSET; + } + switch (wlan_chip_id) + { + case 43012: + case 43430: + case 43439: + *addr = 0x18004000 + offset; + break; + default: + return WHD_BADARG; + } + return WHD_SUCCESS; +} + +whd_result_t get_sdiod_core_base_address(uint16_t wlan_chip_id, uint32_t *addr) +{ + switch (wlan_chip_id) + { + case 0x4373: + *addr = 0x18005000; + break; + case 43012: + case 43430: + case 43439: + *addr = 0x18002000; + break; + default: + return WHD_BADARG; + } + return WHD_SUCCESS; +} + +whd_result_t get_pmu_base_address(uint16_t wlan_chip_id, uint32_t *addr) +{ + switch (wlan_chip_id) + { + case 0x4373: + case 43430: + case 43439: + *addr = CHIPCOMMON_BASE_ADDRESS; + break; + case 43012: + *addr = 0x18012000; + break; + case 43909: + case 43907: + case 54907: + *addr = 0x18011000; + break; + default: + return WHD_BADARG; + } + return WHD_SUCCESS; +} + +whd_result_t get_chip_ram_size(uint16_t wlan_chip_id, uint32_t *size) +{ + *size = 0; + if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) || (wlan_chip_id == 43430) || + (wlan_chip_id == 43439) ) + { + *size = (512 * 1024); + } + else if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4390) ) + { + *size = 0x3C000; + } + else if ( (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) ) + { + *size = 0x90000; + } + else if (wlan_chip_id == 43012) + { + *size = 0xA0000; + } + else if (wlan_chip_id == 0x4373) + { + *size = 0xE0000; + } + else + { + *size = 0x80000; + } + return WHD_SUCCESS; +} + +whd_result_t get_atcm_ram_base_address(uint16_t wlan_chip_id, uint32_t *size) +{ + *size = 0; + if (wlan_chip_id == 0x4373) + { + *size = 0x160000; + } + else if ( (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) ) + { + *size = 0x1B0000; + } + else + { + *size = 0; + } + return WHD_SUCCESS; +} + +whd_result_t get_socsram_srmem_size(uint16_t wlan_chip_id, uint32_t *mem_size) +{ + *mem_size = 0; + if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *mem_size = (32 * 1024); + } + else if ( (wlan_chip_id == 43430) || (wlan_chip_id == 43439) ) + { + *mem_size = (64 * 1024); + } + else + { + *mem_size = 0; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_band_mask(uint16_t wlan_chip_id, uint32_t *band_mask) +{ + *band_mask = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *band_mask = 0xf000; + } + else + { + *band_mask = 0xc000; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_band_2G(uint16_t wlan_chip_id, uint32_t *band_2g) +{ + *band_2g = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *band_2g = 0x2000; + } + else + { + *band_2g = 0x0000; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_band_5G(uint16_t wlan_chip_id, uint32_t *band_5g) +{ + *band_5g = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *band_5g = 0x1000; + } + else + { + *band_5g = 0xc000; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_band_shift(uint16_t wlan_chip_id, uint32_t *band_shift) +{ + *band_shift = 0; + if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *band_shift = 12; + } + else + { + *band_shift = 14; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_bw_10(uint16_t wlan_chip_id, uint32_t *bw_10) +{ + *bw_10 = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *bw_10 = 0x0400; + } + else + { + *bw_10 = 0x0800; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_bw_20(uint16_t wlan_chip_id, uint32_t *bw_20) +{ + *bw_20 = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *bw_20 = 0x0800; + } + else + { + *bw_20 = 0x1000; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_bw_40(uint16_t wlan_chip_id, uint32_t *bw_40) +{ + *bw_40 = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *bw_40 = 0x0C00; + } + else + { + *bw_40 = 0x1800; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_bw_mask(uint16_t wlan_chip_id, uint32_t *bw_mask) +{ + *bw_mask = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *bw_mask = 0x0C00; + } + else + { + *bw_mask = 0x3800; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_bw_shift(uint16_t wlan_chip_id, uint32_t *bw_shift) +{ + *bw_shift = 0; + if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *bw_shift = 10; + } + else + { + *bw_shift = 11; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_ctl_sb_lower(uint16_t wlan_chip_id, uint32_t *sb_lower) +{ + *sb_lower = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *sb_lower = 0x0100; + } + else + { + *sb_lower = WL_CHANSPEC_CTL_SB_LLL; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_ctl_sb_upper(uint16_t wlan_chip_id, uint32_t *sb_upper) +{ + *sb_upper = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *sb_upper = 0x0200; + } + else + { + *sb_upper = WL_CHANSPEC_CTL_SB_LLU; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_ctl_sb_none(uint16_t wlan_chip_id, uint32_t *sb_none) +{ + *sb_none = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *sb_none = 0x0300; + } + else + { + *sb_none = WL_CHANSPEC_CTL_SB_LLL; + } + return WHD_SUCCESS; +} + +whd_result_t get_wl_chanspec_ctl_sb_mask(uint16_t wlan_chip_id, uint32_t *sb_mask) +{ + *sb_mask = 0; + if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) ) + { + *sb_mask = 0x0300; + } + else + { + *sb_mask = 0x0700; + } + return WHD_SUCCESS; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_clm.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_clm.c new file mode 100644 index 00000000..c6dbc144 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_clm.c @@ -0,0 +1,172 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides generic clm blob file download functionality + */ + +#include +#include "whd_clm.h" +#include "whd_wlioctl.h" +#include "whd_cdc_bdc.h" +#include "whd_debug.h" +#include "whd_int.h" +#include "whd_buffer_api.h" +#include "whd_resource_if.h" +#include "whd_resource_api.h" +#include "whd_types_int.h" + +/****************************************************** +* @cond Constants +******************************************************/ + +/* + Generic interface for downloading required data onto the dongle + */ +static whd_result_t +whd_download_wifi_clm_image(whd_interface_t ifp, const char *iovar, uint16_t flag, uint16_t dload_type, + unsigned char *dload_buf, uint32_t len) +{ + wl_dload_data_t *dload_ptr = (wl_dload_data_t *)dload_buf; + uint32_t dload_data_offset; + whd_buffer_t buffer; + uint8_t *iov_data; + whd_driver_t whd_driver = ifp->whd_driver; + + dload_data_offset = offsetof(wl_dload_data_t, data); + dload_ptr->flag = htod16( (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT) | flag ); + dload_ptr->dload_type = htod16(dload_type); + dload_ptr->len = htod32(len - dload_data_offset); + + dload_ptr->crc = 0; + + whd_assert("dload buffer too large", len < 0xffffffff - 8); + len = len + 8 - (len % 8); + + iov_data = (uint8_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, iovar); + CHECK_IOCTL_BUFFER(iov_data); + memcpy(iov_data, (uint8_t *)dload_ptr, len); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); + return WHD_SUCCESS; +} + +whd_result_t whd_process_clm_data(whd_interface_t ifp) +{ + whd_result_t ret = WHD_SUCCESS; + uint32_t clm_blob_size; + uint32_t size2alloc, data_offset; + unsigned char *chunk_buf; + uint16_t dl_flag = DL_BEGIN; + uint32_t chunk_len; + uint32_t size_read; + uint8_t *image; + uint32_t blocks_count = 0; + uint16_t datalen = 0; + uint32_t i, j, num_buff; + uint32_t transfer_progress; + whd_driver_t whd_driver = ifp->whd_driver; + + /* clm file size is the initial datalen value which is decremented */ + ret = whd_resource_size(whd_driver, WHD_RESOURCE_WLAN_CLM, &clm_blob_size); + + if (ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Fatal error: download_resource doesn't exist\n") ); + return ret; + } + + ret = whd_get_resource_no_of_blocks(whd_driver, WHD_RESOURCE_WLAN_CLM, &blocks_count); + if (ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Fatal error: download_resource blocks count not know\n") ); + return ret; + } + + data_offset = offsetof(wl_dload_data_t, data); + size2alloc = data_offset + BLOCK_SIZE; + + + if ( (chunk_buf = (unsigned char *)malloc(size2alloc) ) != NULL ) + { + memset(chunk_buf, 0, size2alloc); + transfer_progress = 0; + for (i = 0; i < blocks_count; i++) + { + whd_get_resource_block(whd_driver, WHD_RESOURCE_WLAN_CLM, i, (const uint8_t **)&image, &size_read); + + num_buff = (size_read + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (blocks_count != 1) + transfer_progress = 0; + + for (j = 0; j < num_buff; j++) + { + if (size_read >= BLOCK_SIZE) + chunk_len = BLOCK_SIZE; + else + chunk_len = size_read; + memcpy(chunk_buf + data_offset, &image[transfer_progress], chunk_len); + + if (datalen + chunk_len == clm_blob_size) + { + dl_flag |= DL_END; + } + + ret = whd_download_wifi_clm_image(ifp, IOVAR_STR_CLMLOAD, dl_flag, DL_TYPE_CLM, chunk_buf, + data_offset + chunk_len); + dl_flag &= (uint16_t) ~DL_BEGIN; + transfer_progress += chunk_len; + size_read = size_read - chunk_len; + datalen += chunk_len; + } + } + + free(chunk_buf); + if (ret != WHD_SUCCESS) + { + whd_result_t ret_clmload_status; + whd_buffer_t buffer; + whd_buffer_t response; + void *data; + + WPRINT_WHD_DEBUG( ("clmload (%" PRIu32 " byte file) failed with return %" PRIu32 "; ", clm_blob_size, + ret) ); + data = (int *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, 4, IOVAR_STR_CLMLOAD_STATUS); + CHECK_IOCTL_BUFFER(data); + ret_clmload_status = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response); + if (ret_clmload_status != WHD_SUCCESS) + { + WPRINT_WHD_DEBUG( ("clmload_status failed with return %lu\n", ret_clmload_status) ); + } + else + { + uint8_t *clmload_status = (uint8_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + if (clmload_status != NULL) + { + WPRINT_WHD_DEBUG( ("clmload_status is %d\n", *clmload_status) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + } + } + } + } + else + { + WPRINT_WHD_ERROR( ("Memory allocation failure, %s failed at %d \n", __func__, __LINE__) ); + ret = WHD_MALLOC_FAILURE; + } + + return ret; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_debug.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_debug.c new file mode 100644 index 00000000..93668731 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_debug.c @@ -0,0 +1,61 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "whd_debug.h" +#include "whd_int.h" +#include "bus_protocols/whd_bus_protocol_interface.h" + +/****************************************************** +* Constants +******************************************************/ + +/****************************************************** +* Structures +******************************************************/ + +/****************************************************** +* Variables +******************************************************/ + +/****************************************************** +* Function definitions +******************************************************/ +void whd_init_stats(whd_driver_t whd_driver) +{ + memset(&whd_driver->whd_stats, 0, sizeof(whd_driver->whd_stats) ); +} + +uint32_t whd_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print) +{ + CHECK_DRIVER_NULL(whd_driver); + + WPRINT_MACRO( ("WHD Stats.. \n" + "tx_total:%" PRIu32 ", rx_total:%" PRIu32 ", tx_no_mem:%" PRIu32 ", rx_no_mem:%" PRIu32 "\n" + "tx_fail:%" PRIu32 ", no_credit:%" PRIu32 ", flow_control:%" PRIu32 "\n", + whd_driver->whd_stats.tx_total, whd_driver->whd_stats.rx_total, + whd_driver->whd_stats.tx_no_mem, whd_driver->whd_stats.rx_no_mem, + whd_driver->whd_stats.tx_fail, whd_driver->whd_stats.no_credit, + whd_driver->whd_stats.flow_control) ); + + if (reset_after_print == WHD_TRUE) + { + memset(&whd_driver->whd_stats, 0, sizeof(whd_driver->whd_stats) ); + } + + CHECK_RETURN(whd_bus_print_stats(whd_driver, reset_after_print) ); + return WHD_SUCCESS; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_events.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_events.c new file mode 100644 index 00000000..e80271ae --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_events.c @@ -0,0 +1,656 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "whd_int.h" +#include "whd_cdc_bdc.h" +#include "whd_events_int.h" +#include "cyabs_rtos.h" +#include "whd_network_types.h" +#include "whd_types_int.h" +#include "whd_wlioctl.h" +#include "whd_thread_internal.h" +#include "whd_buffer_api.h" + +/****************************************************** +* Constants +******************************************************/ +/****************************************************** +* Macros +******************************************************/ +/* bit map related macros */ +#define NBBY 8 /* 8 bits per byte */ +#define setbit(a, i) ( ( (uint8_t *)a )[(int)(i) / (int)(NBBY)] |= (uint8_t)(1 << ( (i) % NBBY ) ) ) +#define clrbit(a, i) ( ( (uint8_t *)a )[(int)(i) / (int)(NBBY)] &= (uint8_t) ~(1 << ( (i) % NBBY ) ) ) +#define isset(a, i) ( ( (const uint8_t *)a )[(int)(i) / (int)(NBBY)]& (1 << ( (i) % NBBY ) ) ) +#define isclr(a, i) ( ( ( (const uint8_t *)a )[(int)(i) / (int)(NBBY)]& (1 << ( (i) % NBBY ) ) ) == 0 ) + +/****************************************************** +* Local Structures +******************************************************/ + +/****************************************************** +* Static Variables +******************************************************/ + +/****************************************************** +* Static Function Prototypes +******************************************************/ +/* helper function for event messages ext API */ +static uint8_t *whd_management_alloc_event_msgs_buffer(whd_interface_t ifp, whd_buffer_t *buffer); +static uint8_t whd_find_number_of_events(const whd_event_num_t *event_nums); + +/****************************************************** +* Static Functions +******************************************************/ + +static uint8_t whd_find_number_of_events(const whd_event_num_t *event_nums) +{ + uint8_t count = 0; + + while (*event_nums != WLC_E_NONE) + { + count++; + event_nums++; + + if (count >= WHD_MAX_EVENT_SUBSCRIPTION) + return 0; + } + return count + 1; +} + +/** + * Registers locally a handler to receive event callbacks. + * Does not notify Wi-Fi about event subscription change. + * Can be used to refresh local callbacks (e.g. after deep-sleep) + * if Wi-Fi is already notified about them. + * + * This function registers a callback handler to be notified when + * a particular event is received. + * + * @note : Currently there is a limit to the number of simultaneously + * registered events + * + * @param ifp Pointer to handle instance of whd interface + * @param event_nums An array of event types that is to trigger the handler. + * The array must be terminated with a WLC_E_NONE event + * See @ref whd_event_num_t for available events + * @param handler_func A function pointer to the new handler callback, + * or NULL if callbacks are to be disabled for the given event type + * @param handler_user_data A pointer value which will be passed to the event handler function + * at the time an event is triggered (NULL is allowed) + * @param[out] *event_index entry where the event handler is registered in the list + * + * @return WHD result code + */ +whd_result_t whd_management_set_event_handler_locally(whd_interface_t ifp, const whd_event_num_t *event_nums, + whd_event_handler_t handler_func, + void *handler_user_data, uint16_t *event_index) +{ + uint16_t entry = (uint16_t)0xFF; + uint16_t i; + whd_driver_t whd_driver = ifp->whd_driver; + whd_cdc_bdc_info_t *cdc_bdc_info = &whd_driver->cdc_bdc_info; + uint8_t num_of_events; + num_of_events = whd_find_number_of_events(event_nums); + + if (num_of_events <= 1) + { + WPRINT_WHD_ERROR( ("Exceeded the maximum event subscription/no event subscribed\n") ); + return WHD_UNFINISHED; + } + + /* Find an existing matching entry OR the next empty entry */ + for (i = 0; i < (uint16_t)WHD_EVENT_HANDLER_LIST_SIZE; i++) + { + /* Find a matching event list OR the first empty event entry */ + if (!(memcmp(cdc_bdc_info->whd_event_list[i].events, event_nums, + num_of_events * (sizeof(whd_event_num_t) ) ) ) ) + { + /* Check if all the data already matches */ + if ( (cdc_bdc_info->whd_event_list[i].handler == handler_func) && + (cdc_bdc_info->whd_event_list[i].handler_user_data == handler_user_data) && + (cdc_bdc_info->whd_event_list[i].ifidx == ifp->ifidx) ) + { + /* send back the entry where the handler is added */ + *event_index = i; + return WHD_SUCCESS; + } + } + else if ( (entry == (uint16_t)0xFF) && (cdc_bdc_info->whd_event_list[i].event_set == WHD_FALSE) ) + { + entry = i; + } + } + + /* Check if handler function was provided */ + if (handler_func != NULL) + { + /* Check if an empty entry was not found */ + if (entry == (uint16_t)0xFF) + { + WPRINT_WHD_DEBUG( ("Out of space in event handlers table - try increasing WHD_EVENT_HANDLER_LIST_SIZE\n") ); + return WHD_OUT_OF_EVENT_HANDLER_SPACE; + } + + /* Add the new handler in at the free space */ + memcpy (cdc_bdc_info->whd_event_list[entry].events, event_nums, num_of_events * (sizeof(whd_event_num_t) ) ); + cdc_bdc_info->whd_event_list[entry].handler = handler_func; + cdc_bdc_info->whd_event_list[entry].handler_user_data = handler_user_data; + cdc_bdc_info->whd_event_list[entry].ifidx = ifp->ifidx; + cdc_bdc_info->whd_event_list[entry].event_set = WHD_TRUE; + + /* send back the entry where the handler is added */ + *event_index = entry; + } + else + { + WPRINT_WHD_ERROR( ("Event handler callback function is NULL/not provided to register\n") ); + return WHD_BADARG; + } + + return WHD_SUCCESS; +} + +/* Registers locally a handler to receive error callbacks. + * Does not notify Wi-Fi about event subscription change. + * Can be used to refresh local callbacks (e.g. after deep-sleep) + * if Wi-Fi is already notified about them. + * + * This function registers a callback handler to be notified when + * a particular event is received. + * + * @note : Currently there is a limit to the number of simultaneously + * registered events + * + * @param whd_driver Pointer to handle instance of driver + * @param error_nums An error types that is to trigger the handler. + * See @ref whd_error_num_t for available events + * @param handler_func A function pointer to the new handler callback, + * or NULL if callbacks are to be disabled for the given event type + * @param handler_user_data A pointer value which will be passed to the event handler function + * at the time an event is triggered (NULL is allowed) + * @param[out] *error_index entry where the error handler is registered in the list + * + * @return WHD result code + */ +whd_result_t whd_set_error_handler_locally(whd_driver_t whd_driver, const uint8_t *error_nums, + whd_error_handler_t handler_func, + void *handler_user_data, uint16_t *error_index) +{ + uint16_t entry = (uint16_t)0xFF; + uint16_t i; + whd_result_t res; + whd_error_info_t *error_info = &whd_driver->error_info; + + + /* Find an existing matching entry OR the next empty entry */ + for (i = 0; i < (uint16_t)WHD_EVENT_HANDLER_LIST_SIZE; i++) + { + uint8_t events = error_info->whd_event_list[i].events; + /* Find a matching event list OR the first empty event entry */ + if (events & *error_nums) + { + /* Check if all the data already matches */ + if (error_info->whd_event_list[i].handler != NULL) + { + handler_func = error_info->whd_event_list[i].handler; + handler_user_data = error_info->whd_event_list[i].handler_user_data; + res = cy_rtos_get_semaphore(&error_info->event_list_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE); + if (res != WHD_SUCCESS) + { + return res; + } + handler_func(whd_driver, error_nums, NULL, handler_user_data); + CHECK_RETURN(cy_rtos_set_semaphore(&error_info->event_list_mutex, WHD_FALSE) ); + return WHD_SUCCESS; + } + } + else if ( (entry == (uint16_t)0xFF) && (error_info->whd_event_list[i].event_set == WHD_FALSE) ) + { + entry = i; + } + } + /* Check if handler function was provided */ + if (handler_func != NULL) + { + /* Check if an empty entry was not found */ + if (entry == (uint16_t)0xFF) + { + WPRINT_WHD_DEBUG( ("Out of space in error handlers table - try increasing WHD_EVENT_HANDLER_LIST_SIZE\n") ); + return WHD_OUT_OF_EVENT_HANDLER_SPACE; + } + /* Add the new handler in at the free space */ + error_info->whd_event_list[entry].events = *error_nums; + error_info->whd_event_list[entry].handler = handler_func; + error_info->whd_event_list[entry].handler_user_data = handler_user_data; + error_info->whd_event_list[entry].event_set = WHD_TRUE; + /* send back the entry where the handler is added */ + *error_index = entry; + } + else + { + WPRINT_WHD_ERROR( ("Error handler callback function is NULL/not provided to register\n") ); + return WHD_BADARG; + } + + return WHD_SUCCESS; +} + +/* allocates memory for the needed iovar and returns a pointer to the event mask */ +static uint8_t *whd_management_alloc_event_msgs_buffer(whd_interface_t ifp, whd_buffer_t *buffer) +{ + uint16_t i; + uint16_t j; + whd_bool_t use_extended_evt = WHD_FALSE; + uint32_t max_event = 0; + eventmsgs_ext_t *eventmsgs_ext_data = NULL; + uint32_t *data = NULL; + whd_driver_t whd_driver = ifp->whd_driver; + whd_cdc_bdc_info_t *cdc_bdc_info = &whd_driver->cdc_bdc_info; + + /* Check to see if event that's set requires more than 128 bit */ + for (i = 0; i < (uint16_t)WHD_EVENT_HANDLER_LIST_SIZE; i++) + { + if (cdc_bdc_info->whd_event_list[i].event_set) + { + for (j = 0; cdc_bdc_info->whd_event_list[i].events[j] != WLC_E_NONE; j++) + { + uint32_t event_value = cdc_bdc_info->whd_event_list[i].events[j]; + if (event_value > 127) + { + use_extended_evt = WHD_TRUE; + if (event_value > max_event) + { + max_event = event_value; + } + /* keep going to get highest value */ + } + } + } + } + + if (WHD_FALSE == use_extended_evt) + { + /* use old iovar for backwards compat */ + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, buffer, (uint16_t)WL_EVENTING_MASK_LEN + 4, + "bsscfg:" IOVAR_STR_EVENT_MSGS); + + if (NULL == data) + { + return NULL; + } + + data[0] = ifp->bsscfgidx; + + return (uint8_t *)&data[1]; + } + else + { + uint8_t mask_len = (uint8_t)( (max_event + 8) / 8 ); + data = + (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, buffer, + (uint16_t)(sizeof(eventmsgs_ext_t) + mask_len + 4), + "bsscfg:" IOVAR_STR_EVENT_MSGS_EXT); + + if (NULL == data) + { + return NULL; + } + + data[0] = ifp->bsscfgidx; + + eventmsgs_ext_data = (eventmsgs_ext_t *)&data[1]; + + memset(eventmsgs_ext_data, 0, sizeof(*eventmsgs_ext_data) ); + eventmsgs_ext_data->ver = EVENTMSGS_VER; + eventmsgs_ext_data->command = EVENTMSGS_SET_MASK; + eventmsgs_ext_data->len = mask_len; + return eventmsgs_ext_data->mask; + } +} + +/** + * Registers a handler to receive event callbacks. + * Subscribe locally and notify Wi-Fi about subscription. + * + * This function registers a callback handler to be notified when + * a particular event is received. + * + * @note : Currently there is a limit to the number of simultaneously + * registered events + * + * @param ifp Pointer to handle instance of whd interface + * @param event_nums An array of event types that is to trigger the handler. + * The array must be terminated with a WLC_E_NONE event + * See @ref whd_event_num_t for available events + * @param handler_func A function pointer to the new handler callback + * @param handler_user_data A pointer value which will be passed to the event handler function + * at the time an event is triggered (NULL is allowed) + * @param[out] *event_index entry where the event handler is registered in the list + * + * @return WHD result code + */ +whd_result_t whd_management_set_event_handler(whd_interface_t ifp, const whd_event_num_t *event_nums, + whd_event_handler_t handler_func, + void *handler_user_data, uint16_t *event_index) +{ + whd_buffer_t buffer; + uint8_t *event_mask; + uint16_t i; + uint16_t j; + whd_result_t res; + whd_driver_t whd_driver; + whd_cdc_bdc_info_t *cdc_bdc_info; + whd_interface_t prim_ifp; + + if (ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + if (!event_nums || !event_index) + { + WPRINT_WHD_ERROR( ("Event list to be registered is NULL/Event index is NULL") ); + return WHD_BADARG; + } + + whd_driver = ifp->whd_driver; + cdc_bdc_info = &whd_driver->cdc_bdc_info; + prim_ifp = whd_get_primary_interface(whd_driver); + + if (prim_ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + /* Acquire mutex preventing multiple threads accessing the handler at the same time */ + res = cy_rtos_get_semaphore(&cdc_bdc_info->event_list_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE); + if (res != WHD_SUCCESS) + { + return res; + } + + /* Set event handler locally */ + res = whd_management_set_event_handler_locally(ifp, event_nums, handler_func, handler_user_data, event_index); + if (res != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error in setting event handler locally, %s failed at %d \n", __func__, __LINE__) ); + goto set_event_handler_exit; + } + + /* Send the new event mask value to the wifi chip */ + event_mask = whd_management_alloc_event_msgs_buffer(ifp, &buffer); + + if (NULL == event_mask) + { + res = WHD_BUFFER_UNAVAILABLE_PERMANENT; + WPRINT_WHD_ERROR( ("Buffer unavailable permanently, %s failed at %d \n", __func__, __LINE__) ); + goto set_event_handler_exit; + } + + /* Keep the wlan awake while we set the event_msgs */ + WHD_WLAN_KEEP_AWAKE(whd_driver); + + /* Set the event bits for each event from every handler */ + memset(event_mask, 0, (size_t)WL_EVENTING_MASK_LEN); + for (i = 0; i < (uint16_t)WHD_EVENT_HANDLER_LIST_SIZE; i++) + { + if (cdc_bdc_info->whd_event_list[i].event_set) + { + for (j = 0; cdc_bdc_info->whd_event_list[i].events[j] != WLC_E_NONE; j++) + { + setbit(event_mask, cdc_bdc_info->whd_event_list[i].events[j]); + } + } + } + + res = whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0); + if (res != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: send event_msgs(iovar) failed\n", __func__) ); + } + + /* set the event_list_mutex here after sending iovar. + * we get event_list_mutex -> ioctl_mutex, make sure we didn't have any thread, having ioctl_mutex -> event_list_mutex path. + * Otherwise it may cause deadlock + */ + CHECK_RETURN(cy_rtos_set_semaphore(&cdc_bdc_info->event_list_mutex, WHD_FALSE) ); + + /* The wlan chip can sleep from now on */ + WHD_WLAN_LET_SLEEP(whd_driver); + return WHD_SUCCESS; + +set_event_handler_exit: + CHECK_RETURN(cy_rtos_set_semaphore(&cdc_bdc_info->event_list_mutex, WHD_FALSE) ); + return res; +} + +whd_result_t whd_wifi_set_event_handler(whd_interface_t ifp, const uint32_t *event_type, + whd_event_handler_t handler_func, + void *handler_user_data, uint16_t *event_index) +{ + whd_buffer_t buffer; + uint8_t *event_mask; + uint16_t i; + uint16_t j; + whd_result_t res; + whd_driver_t whd_driver; + whd_cdc_bdc_info_t *cdc_bdc_info; + whd_interface_t prim_ifp; + + if (ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + if (!event_type || !event_index) + { + WPRINT_WHD_ERROR( ("Event list to be registered is NULL/Event index is NULL") ); + return WHD_BADARG; + } + + whd_driver = ifp->whd_driver; + cdc_bdc_info = &whd_driver->cdc_bdc_info; + prim_ifp = whd_get_primary_interface(whd_driver); + + if (prim_ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + /* Acquire mutex preventing multiple threads accessing the handler at the same time */ + res = cy_rtos_get_semaphore(&cdc_bdc_info->event_list_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE); + if (res != WHD_SUCCESS) + { + return res; + } + + /* Set event handler locally */ + res = whd_management_set_event_handler_locally(ifp, (whd_event_num_t *)event_type, handler_func, handler_user_data, + event_index); + if (res != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error in setting event handler locally, %s failed at %d \n", __func__, __LINE__) ); + goto set_event_handler_exit; + } + + /* Send the new event mask value to the wifi chip */ + event_mask = whd_management_alloc_event_msgs_buffer(ifp, &buffer); + + if (NULL == event_mask) + { + res = WHD_BUFFER_UNAVAILABLE_PERMANENT; + WPRINT_WHD_ERROR( ("Buffer unavailable permanently, %s failed at %d \n", __func__, __LINE__) ); + goto set_event_handler_exit; + } + + /* Keep the wlan awake while we set the event_msgs */ + WHD_WLAN_KEEP_AWAKE(whd_driver); + + /* Set the event bits for each event from every handler */ + memset(event_mask, 0, (size_t)WL_EVENTING_MASK_LEN); + for (i = 0; i < (uint16_t)WHD_EVENT_HANDLER_LIST_SIZE; i++) + { + if (cdc_bdc_info->whd_event_list[i].event_set) + { + for (j = 0; cdc_bdc_info->whd_event_list[i].events[j] != WLC_E_NONE; j++) + { + setbit(event_mask, cdc_bdc_info->whd_event_list[i].events[j]); + } + } + } + + res = whd_cdc_send_iovar(prim_ifp, CDC_SET, buffer, 0); + if (res != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: send event_msgs(iovar) failed\n", __func__) ); + } + + /* set the event_list_mutex here after sending iovar. + * we get event_list_mutex -> ioctl_mutex, make sure we didn't have any thread, having ioctl_mutex -> event_list_mutex path. + * Otherwise it may cause deadlock + */ + CHECK_RETURN(cy_rtos_set_semaphore(&cdc_bdc_info->event_list_mutex, WHD_FALSE) ); + + /* The wlan chip can sleep from now on */ + WHD_WLAN_LET_SLEEP(whd_driver); + return WHD_SUCCESS; + +set_event_handler_exit: + CHECK_RETURN(cy_rtos_set_semaphore(&cdc_bdc_info->event_list_mutex, WHD_FALSE) ); + return res; +} + +/** + * Registers a handler to receive error callbacks. + * Subscribe locally and notify Wi-Fi about subscription. + * + * This function registers a callback handler to be notified when + * a particular event is received. + * + * @note : Currently there is a limit to the number of simultaneously + * registered events + * + * @param ifp Pointer to handle instance of whd interface + * @param event_nums An numbers of event type that is to trigger the handler. + * See @ref whd_error_num_t for available events + * @param handler_func A function pointer to the new handler callback + * @param handler_user_data A pointer value which will be passed to the event handler function + * at the time an event is triggered (NULL is allowed) + * @param[out] *error_index entry where the error handler is registered in the list + * + * @return WHD result code + */ +whd_result_t whd_wifi_set_error_handler(whd_interface_t ifp, const uint8_t *error_nums, + whd_error_handler_t handler_func, + void *handler_user_data, uint16_t *error_index) +{ + whd_result_t res; + whd_driver_t whd_driver; + whd_interface_t prim_ifp; + if (ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + if (!error_nums || !error_index) + { + WPRINT_WHD_ERROR( ("Error list to be registered is NULL/Error index is NULL \n") ); + return WHD_BADARG; + } + + whd_driver = ifp->whd_driver; + prim_ifp = whd_get_primary_interface(whd_driver); + if (prim_ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + /* Set event handler locally */ + res = whd_set_error_handler_locally(whd_driver, error_nums, handler_func, handler_user_data, + error_index); + if (res != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error in setting event handler locally, %s failed at %d \n", __func__, __LINE__) ); + return res; + } + + + return WHD_SUCCESS; + +} + +uint32_t whd_wifi_deregister_event_handler(whd_interface_t ifp, uint16_t event_index) +{ + whd_driver_t whd_driver; + whd_cdc_bdc_info_t *cdc_bdc_info; + + if (ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + whd_driver = ifp->whd_driver; + cdc_bdc_info = &whd_driver->cdc_bdc_info; + + if (event_index < WHD_EVENT_HANDLER_LIST_SIZE) + { + memset(cdc_bdc_info->whd_event_list[event_index].events, 0xFF, + (sizeof(cdc_bdc_info->whd_event_list[event_index].events) ) ); + cdc_bdc_info->whd_event_list[event_index].handler = NULL; + cdc_bdc_info->whd_event_list[event_index].handler_user_data = NULL; + cdc_bdc_info->whd_event_list[event_index].event_set = WHD_FALSE; + return WHD_SUCCESS; + } + if (event_index == 0xFF) + { + WPRINT_WHD_INFO( ("Event handler not registered \n") ); + return WHD_SUCCESS; + } + WPRINT_WHD_DEBUG( ("Invalid event index received to deregister the event handler \n") ); + return WHD_BADARG; +} + +uint32_t whd_wifi_deregister_error_handler(whd_interface_t ifp, uint16_t error_index) +{ + whd_driver_t whd_driver; + whd_error_info_t *error_info; + + if (ifp == NULL) + { + return WHD_UNKNOWN_INTERFACE; + } + + whd_driver = ifp->whd_driver; + error_info = &whd_driver->error_info; + + if (error_index < WHD_EVENT_HANDLER_LIST_SIZE) + { + error_info->whd_event_list[error_index].events = 0; + error_info->whd_event_list[error_index].handler = NULL; + error_info->whd_event_list[error_index].handler_user_data = NULL; + error_info->whd_event_list[error_index].event_set = WHD_FALSE; + return WHD_SUCCESS; + } + if (error_index == 0xFF) + { + WPRINT_WHD_INFO( ("Error handler not registered \n") ); + return WHD_SUCCESS; + } + WPRINT_WHD_DEBUG( ("Invalid error index received to deregister the event handler \n") ); + return WHD_BADARG; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_logging.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_logging.c new file mode 100644 index 00000000..4e94bab7 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_logging.c @@ -0,0 +1,111 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "whd_debug.h" + +#ifdef WHD_LOGGING_BUFFER_ENABLE + +#ifndef LOGGING_BUFFER_SIZE +#error LOGGING_BUFFER_SIZE is not defined +#endif /* LOGGING_BUFFER_SIZE */ +whd_logging_t logbuf; + +int whd_buffer_printf(const char *format, ...) +{ + int potential_num_written = 0; + va_list args; + va_start (args, format); + + potential_num_written = vsnprintf (&(logbuf.buffer[logbuf.buffer_write]), + (size_t)(LOGGING_BUFFER_SIZE - (logbuf.buffer_write) ) + 1, format, args); + + if (potential_num_written > (int)(LOGGING_BUFFER_SIZE - (logbuf.buffer_write) ) ) + { + /* full print did not fit in buffer - wipe what was just written + and reprint at start of buffer + */ + memset(&(logbuf.buffer[logbuf.buffer_write]), 0xf, (size_t)(LOGGING_BUFFER_SIZE - (logbuf.buffer_write) ) ); + + logbuf.buffer_write = 0; + potential_num_written = vsnprintf (&(logbuf.buffer[logbuf.buffer_write]), + (size_t)(LOGGING_BUFFER_SIZE - (logbuf.buffer_write) ) + 1, format, args); + + logbuf.buffer_write += (unsigned)potential_num_written; + logbuf.buffer_write %= LOGGING_BUFFER_SIZE; + + if (logbuf.roll_over) + logbuf.over_write = WHD_TRUE; + + logbuf.roll_over = WHD_TRUE; + + if ( (logbuf.roll_over) && (logbuf.buffer_read < (logbuf.buffer_write) ) ) + { + logbuf.buffer_read = logbuf.buffer_write; + } + if (logbuf.over_write && (logbuf.buffer_read != (logbuf.buffer_write) ) ) + { + logbuf.buffer_read = (logbuf.buffer_write); + } + } + else + { + logbuf.buffer_write += (unsigned)potential_num_written; + + if ( (logbuf.buffer_write) >= LOGGING_BUFFER_SIZE ) + { + logbuf.buffer_write %= LOGGING_BUFFER_SIZE; + + if (logbuf.roll_over) + logbuf.over_write = WHD_TRUE; + + logbuf.roll_over = WHD_TRUE; + } + + if (logbuf.roll_over && (logbuf.buffer_read < logbuf.buffer_write) ) + { + logbuf.buffer_read = logbuf.buffer_write; + } + if (logbuf.over_write && (logbuf.buffer_read != logbuf.buffer_write) ) + { + logbuf.buffer_read = logbuf.buffer_write; + } + } + + va_end (args); + return potential_num_written; +} + +void whd_print_logbuffer(void) +{ + while (logbuf.roll_over || logbuf.over_write || (logbuf.buffer_read != logbuf.buffer_write) ) + { + logbuf.roll_over = logbuf.over_write = WHD_FALSE; + + while (logbuf.buffer[logbuf.buffer_read] == 0xf) + { + logbuf.buffer_read = (logbuf.buffer_read + 1) % LOGGING_BUFFER_SIZE; + } + + putchar(logbuf.buffer[logbuf.buffer_read]); + logbuf.buffer_read = (logbuf.buffer_read + 1) % LOGGING_BUFFER_SIZE; + } +} + +#endif /* ifdef WHD_LOGGING_BUFFER_ENABLE */ diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_management.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_management.c new file mode 100644 index 00000000..ed207d45 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_management.c @@ -0,0 +1,522 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Implements initialisation and other management functions for WHD system + * + */ + +#include +#include +#include "bus_protocols/whd_bus_common.h" +#include "bus_protocols/whd_bus_protocol_interface.h" +#include "whd_debug.h" +#include "whd_events_int.h" +#include "whd_int.h" +#include "whd_chip.h" +#include "whd_sdpcm.h" +#include "whd_wifi_api.h" +#include "whd_clm.h" +#include "whd_wlioctl.h" +#include "whd_types_int.h" +#include "whd_chip_constants.h" + +/****************************************************** +* Constants +******************************************************/ + +#define MAX_POST_SET_COUNTRY_RETRY 3 + +#define MINIMUM_WHD_STACK_SIZE (1024 + 1200 + 2500) + +#define DEFAULT_PM2_SLEEP_RET_TIME 200 +/****************************************************** +* Static Variables +******************************************************/ + +/****************************************************** +* Function definitions +******************************************************/ +whd_result_t whd_management_wifi_platform_init(whd_driver_t whd_driver, whd_country_code_t country, + whd_bool_t resume_after_deep_sleep); +void whd_wifi_bus_irq_handle(void *handler_arg, uint32_t event); + +whd_interface_t whd_get_primary_interface(whd_driver_t whd_driver) +{ + if (whd_driver->iflist[0] != NULL) + { + return whd_driver->iflist[0]; + } + return NULL; +} + +whd_result_t whd_add_interface(whd_driver_t whd_driver, uint8_t bsscfgidx, uint8_t ifidx, + const char *name, whd_mac_t *mac_addr, whd_interface_t *ifpp) +{ + whd_interface_t ifp; + + if (!whd_driver || !ifpp) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + if (bsscfgidx < WHD_INTERFACE_MAX) + { + if (whd_driver->iflist[bsscfgidx] != NULL) + { + *ifpp = whd_driver->iflist[bsscfgidx]; + return WHD_SUCCESS; + } + + if ( (ifp = (whd_interface_t)malloc(sizeof(struct whd_interface) ) ) != NULL ) + { + memset(ifp, 0, (sizeof(struct whd_interface) ) ); + *ifpp = ifp; + ifp->whd_driver = whd_driver; + + /* Add a interface name */ + /* strncpy doesn't terminate with null if the src string is long */ + ifp->if_name[WHD_MSG_IFNAME_MAX - 1] = '\0'; + strncpy(ifp->if_name, name, sizeof(ifp->if_name) - 1); + memset(ifp->event_reg_list, WHD_EVENT_NOT_REGISTERED, sizeof(ifp->event_reg_list) ); + /* Primary interface takes 0 as default */ + ifp->ifidx = ifidx; + ifp->bsscfgidx = bsscfgidx; + + if (mac_addr != NULL) + memcpy(ifp->mac_addr.octet, mac_addr->octet, sizeof(whd_mac_t) ); + else + memset(ifp->mac_addr.octet, 0, sizeof(whd_mac_t) ); + + whd_driver->iflist[bsscfgidx] = ifp; + whd_driver->if2ifp[ifidx] = bsscfgidx; + } + else + { + return WHD_MALLOC_FAILURE; + } + + return WHD_SUCCESS; + } + return WHD_INVALID_INTERFACE; +} + +whd_result_t whd_add_primary_interface(whd_driver_t whd_driver, whd_interface_t *ifpp) +{ + return whd_add_interface(whd_driver, 0, 0, "wlan0", NULL, ifpp); +} + +uint32_t whd_add_secondary_interface(whd_driver_t whd_driver, whd_mac_t *mac_addr, whd_interface_t *ifpp) +{ + return whd_add_interface(whd_driver, 1, 1, "wlan1", mac_addr, ifpp); +} + +uint32_t whd_init(whd_driver_t *whd_driver_ptr, whd_init_config_t *whd_init_config, + whd_resource_source_t *resource_ops, whd_buffer_funcs_t *buffer_ops, + whd_netif_funcs_t *network_ops) +{ + whd_driver_t whd_drv; + + if (!whd_driver_ptr || !buffer_ops || !network_ops || !resource_ops || !whd_init_config) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + if (whd_init_config->thread_stack_size < MINIMUM_WHD_STACK_SIZE) + { + WPRINT_WHD_INFO( ("Stack size is less than minimum stack size required.\n") ); + return WHD_WLAN_BUFTOOSHORT; + } + + if ( (whd_drv = (whd_driver_t)malloc(sizeof(struct whd_driver) ) ) != NULL ) + { + memset(whd_drv, 0, sizeof(struct whd_driver) ); + *whd_driver_ptr = whd_drv; + whd_drv->buffer_if = buffer_ops; + whd_drv->network_if = network_ops; + whd_drv->resource_if = resource_ops; + whd_bus_common_info_init(whd_drv); + whd_thread_info_init(whd_drv, whd_init_config); + whd_cdc_bdc_info_init(whd_drv); + whd_internal_info_init(whd_drv); + whd_ap_info_init(whd_drv); + //whd_wifi_sleep_info_init(whd_drv); + whd_wifi_chip_info_init(whd_drv); + + whd_drv->bus_gspi_32bit = WHD_FALSE; + + if (whd_init_config->country == 0) + whd_drv->country = WHD_COUNTRY_UNITED_STATES; + else + whd_drv->country = whd_init_config->country; + } + else + { + return WHD_MALLOC_FAILURE; + } + return WHD_SUCCESS; +} + +uint32_t whd_deinit(whd_interface_t ifp) +{ + uint8_t i; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + whd_driver = ifp->whd_driver; + + if (whd_driver->internal_info.whd_wlan_status.state != WLAN_OFF) + { + WPRINT_WHD_ERROR( ("Could not deinit whd because wifi power is on\n") ); + return WHD_WLAN_NOTDOWN; + } + + if ( (whd_driver->bus_priv != NULL) || (whd_driver->bus_if != NULL) ) + { + WPRINT_WHD_ERROR( ("Could not deinit whd because bus is attaced\n") ); + return WHD_WLAN_NOTDOWN; + } + + for (i = 0; i < WHD_INTERFACE_MAX; i++) + { + if (whd_driver->iflist[i] != NULL) + { + free(whd_driver->iflist[i]); + whd_driver->iflist[i] = NULL; + } + } + + whd_cdc_bdc_info_deinit(whd_driver); + whd_internal_info_deinit(whd_driver); + whd_bus_common_info_deinit(whd_driver); + free(whd_driver); + + return WHD_SUCCESS; +} + +/** + * Initialize Wi-Fi platform + * + * - Initializes the required parts of the hardware platform + * i.e. pins for SDIO/SPI, interrupt, reset, power etc. + * + * - Initializes the WHD thread which arbitrates access + * to the SDIO/SPI bus + * + * @return WHD_SUCCESS if initialization is successful, error code otherwise + */ + +whd_result_t whd_management_wifi_platform_init(whd_driver_t whd_driver, whd_country_code_t country, + whd_bool_t resume_after_deep_sleep) +{ + whd_result_t retval; + + whd_driver->internal_info.whd_wlan_status.country_code = country; + + if (resume_after_deep_sleep == WHD_TRUE) + { + retval = ( whd_result_t )whd_bus_resume_after_deep_sleep(whd_driver); + } + else + { + whd_bus_init_stats(whd_driver); + retval = ( whd_result_t )whd_bus_init(whd_driver); + } + + if (retval != WHD_SUCCESS) + { + /* May have been due to user abort */ + WPRINT_WHD_INFO( ("Could not initialize bus\n") ); + return retval; + } + + /* WLAN device is now powered up. Change state from OFF to DOWN */ + whd_driver->internal_info.whd_wlan_status.state = WLAN_DOWN; + + + retval = whd_thread_init(whd_driver); + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Could not initialize WHD thread\n") ); + return retval; + } + + return WHD_SUCCESS; +} + +/** + * Turn on the Wi-Fi device + * + * - Initialize Wi-Fi device + * + * - Program various WiFi parameters and modes + * + * @return WHD_SUCCESS if initialization is successful, error code otherwise + */ +uint32_t whd_wifi_on(whd_driver_t whd_driver, whd_interface_t *ifpp) +{ + wl_country_t *country_struct; + uint32_t *ptr; + whd_result_t retval; + whd_buffer_t buffer; + uint8_t *event_mask; + uint32_t *data; + uint32_t counter; + whd_interface_t ifp; + uint16_t wlan_chip_id = 0; + + if (!whd_driver || !ifpp) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + if (whd_driver->internal_info.whd_wlan_status.state == WLAN_UP) + { + return WHD_SUCCESS; + } + + whd_init_stats(whd_driver); + + + retval = whd_management_wifi_platform_init(whd_driver, whd_driver->country, WHD_FALSE); + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_INFO( ("Could not initialize wifi platform\n") ); + return retval; + } + + whd_add_primary_interface(whd_driver, ifpp); + ifp = *ifpp; + + /* Download blob file if exists */ + retval = whd_process_clm_data(ifp); + if (retval != WHD_SUCCESS) + { + WPRINT_MACRO( ("****************************************************\n" + "** ERROR: WLAN: could not download clm_blob file\n" + "** FATAL ERROR: system unusable, CLM blob file not found or corrupted.\n" + "****************************************************\n") ); + return retval; + } + + retval = whd_bus_share_bt_init(whd_driver); + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_INFO( ("Shared bus for bt is fail\n") ); + } + + /* Get FW Capability */ + retval = whd_wifi_read_fw_capabilities(ifp); + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_INFO( ("Get FW Capabilities Fail\n") ); + } + + /* Turn off SDPCM TX Glomming */ + /* Note: This is only required for later chips. + * The 4319 has glomming off by default however the 43362 has it on by default. + */ + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)4, IOVAR_STR_TX_GLOM); + if (data == NULL) + { + whd_assert("Could not get buffer for IOVAR", 0 != 0); + return WHD_BUFFER_ALLOC_FAIL; + } + *data = 0; + retval = whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + if ( (retval != WHD_SUCCESS) && (retval != WHD_WLAN_UNSUPPORTED) ) + { + /* Note: System may time out here if bus interrupts are not working properly */ + WPRINT_WHD_ERROR( ("Could not turn off TX glomming\n") ); + return retval; + } + + /* Turn APSTA on */ + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)sizeof(*data), IOVAR_STR_APSTA); + if (data == NULL) + { + whd_assert("Could not get buffer for IOVAR", 0 != 0); + return WHD_BUFFER_ALLOC_FAIL; + } + *data = htod32( (uint32_t)1 ); + /* This will fail on manufacturing test build since it does not have APSTA available */ + retval = whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + if (retval == WHD_WLAN_UNSUPPORTED) + { + WPRINT_WHD_DEBUG( ("Firmware does not support APSTA\n") ); + } + else if (retval != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Could not turn on APSTA\n") ); + return retval; + } + + /* Send set country command */ + /* This is the first time that the WLAN chip is required to respond + * in it's normal run mode. + * If you are porting a new system and it stalls here, it could + * be one of the following problems: + * - Bus interrupt not triggering properly - the WLAN chip is unable to signal the host that there is data available. + * - Timing problems - if the timeouts on semaphores are not working correctly, then the + * system might think that the IOCTL has timed out much faster than it should do. + * + */ + + country_struct = (wl_country_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)sizeof(wl_country_t), + IOVAR_STR_COUNTRY); + if (country_struct == NULL) + { + whd_assert("Could not get buffer for IOCTL", 0 != 0); + return WHD_BUFFER_ALLOC_FAIL; + } + memset(country_struct, 0, sizeof(wl_country_t) ); + + ptr = (uint32_t *)country_struct->ccode; + *ptr = (uint32_t)whd_driver->internal_info.whd_wlan_status.country_code & 0x0000ffff; + ptr = (uint32_t *)country_struct->country_abbrev; + *ptr = (uint32_t)whd_driver->internal_info.whd_wlan_status.country_code & 0x0000ffff; + country_struct->rev = (int32_t)( (whd_driver->internal_info.whd_wlan_status.country_code & 0xffff0000) >> 16 ); + + /* if regrev is 0 then set regrev to -1 so the FW will use any NVRAM/OTP configured aggregate + * to choose the regrev. If there is no aggregate configured then the FW will try to use regrev 0. + */ + if (country_struct->rev == 0) + { + country_struct->rev = (int32_t)htod32(-1); + } + retval = whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + if (retval != WHD_SUCCESS) + { + /* Could not set wifi country */ + WPRINT_WHD_ERROR( ("Could not set Country code\n") ); + return retval; + } + + /* NOTE: The set country command requires time to process on the WLAN firmware and + * the following IOCTL may fail on initial attempts therefore we try a few times */ + + /* Set the event mask, indicating initially we do not want any asynchronous events */ + for (counter = 0, retval = WHD_PENDING; retval != WHD_SUCCESS && counter < (uint32_t)MAX_POST_SET_COUNTRY_RETRY; + ++counter) + { + event_mask = (uint8_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)WL_EVENTING_MASK_LEN, + IOVAR_STR_EVENT_MSGS); + if (event_mask == NULL) + { + whd_assert("Could not get buffer for IOVAR", 0 != 0); + return WHD_BUFFER_ALLOC_FAIL; + } + memset(event_mask, 0, (size_t)WL_EVENTING_MASK_LEN); + retval = whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + } + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Could not set Event mask\n") ); + return retval; + } + + /* Send UP command */ + CHECK_RETURN(whd_wifi_set_up(ifp) ); + + wlan_chip_id = whd_chip_get_chip_id(whd_driver); + /* WAR: Disable WLAN PM/mpc for 43907 low power issue */ + if ( (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) ) + { + retval = whd_wifi_disable_powersave(ifp); + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Failed to disable PM for 43907\n") ); + return retval; + } + retval = whd_wifi_set_iovar_value(ifp, IOVAR_STR_MPC, 0); + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Failed to disable mpc for 43907\n") ); + return retval; + } + } + else + { + whd_wifi_enable_powersave_with_throughput(ifp, DEFAULT_PM2_SLEEP_RET_TIME); + } + + /* Set the GMode */ + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4); + if (data == NULL) + { + whd_assert("Could not get buffer for IOCTL", 0 != 0); + return WHD_BUFFER_ALLOC_FAIL; + } + *data = htod32( (uint32_t)GMODE_AUTO ); + retval = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_GMODE, buffer, 0); + if (retval != WHD_SUCCESS) + { + /* Note: System may time out here if bus interrupts are not working properly */ + WPRINT_WHD_ERROR( ("Error setting gmode\n") ); + return retval; + } + + return WHD_SUCCESS; +} + +/** + * Turn off the Wi-Fi device + * + * - De-Initialises the required parts of the hardware platform + * i.e. pins for SDIO/SPI, interrupt, reset, power etc. + * + * - De-Initialises the WHD thread which arbitrates access + * to the SDIO/SPI bus + * + * @return WHD_SUCCESS if deinitialization is successful, error code otherwise + */ +uint32_t whd_wifi_off(whd_interface_t ifp) +{ + whd_result_t retval; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + if (whd_driver->internal_info.whd_wlan_status.state == WLAN_OFF) + { + return WHD_SUCCESS; + } + + /* Set wlc down before turning off the device */ + CHECK_RETURN(whd_wifi_set_ioctl_buffer(ifp, WLC_DOWN, NULL, 0) ); + whd_driver->internal_info.whd_wlan_status.state = WLAN_DOWN; + + /* Disable SDIO/SPI interrupt */ + whd_bus_irq_enable(whd_driver, WHD_FALSE); + whd_thread_quit(whd_driver); + + retval = whd_bus_deinit(whd_driver); + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_DEBUG( ("Error de-initializing bus\n") ); + return retval; + } + + whd_driver->internal_info.whd_wlan_status.state = WLAN_OFF; + return WHD_SUCCESS; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_network_if.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_network_if.c new file mode 100644 index 00000000..a7521a11 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_network_if.c @@ -0,0 +1,84 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides generic APSTA functionality that chip specific files use + */ + +#include "whd_debug.h" +#include "whd_network_if.h" + +/****************************************************** + * * @cond Constants + * ******************************************************/ + +/****************************************************** + * * Enumerations + * ******************************************************/ + +/****************************************************** +** Function Declarations +*******************************************************/ + +/****************************************************** + * Variables Definitions + *****************************************************/ + +/****************************************************** +* Function Definitions +******************************************************/ +/** Called by WHD to pass received data to the network stack + * + * + * Packets received from the Wi-Fi network by WHD are forwarded to by calling function ptr which + * must be implemented in the network interface. Ethernet headers + * are present at the start of these packet buffers. + * + * This function is called asynchronously in the context of the + * WHD thread whenever new data has arrived. + * Packet buffers are allocated within WHD, and ownership is transferred + * to the network stack. The network stack or application is thus + * responsible for releasing the packet buffers. + * Most packet buffering systems have a pointer to the 'current point' within + * the packet buffer. When this function is called, the pointer points + * to the start of the Ethernet header. There is other inconsequential data + * before the Ethernet header. + * + * It is preferable that the (whd_network_process_ethernet_data)() function simply puts + * the received packet on a queue for processing by another thread. This avoids the + * WHD thread being unnecessarily tied up which would delay other packets + * being transmitted or received. + * + * @param interface : The interface on which the packet was received. + * @param buffer : Handle of the packet which has just been received. Responsibility for + * releasing this buffer is transferred from WHD at this point. + * + */ +whd_result_t whd_network_process_ethernet_data(whd_interface_t ifp, whd_buffer_t buffer) +{ + whd_driver_t whd_driver = ifp->whd_driver; + if (whd_driver->network_if->whd_network_process_ethernet_data) + { + whd_driver->network_if->whd_network_process_ethernet_data(ifp, buffer); + return WHD_SUCCESS; + } + else + { + WPRINT_WHD_INFO( ("Function pointers not provided .\n") ); + } + return WHD_WLAN_NOFUNCTION; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_resource_if.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_resource_if.c new file mode 100644 index 00000000..eeeac479 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_resource_if.c @@ -0,0 +1,117 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides generic APSTA functionality that chip specific files use + */ + +#include "whd_debug.h" +#include "whd_int.h" +#include "whd_resource_if.h" + +/****************************************************** + * * @cond Constants + * ******************************************************/ + +/****************************************************** + * * Enumerations + * ******************************************************/ + +/****************************************************** + * * Function Declarations + * ******************************************************/ + +/****************************************************** + * Variables Definitions + *****************************************************/ + +/****************************************************** +* Function Definitions +******************************************************/ +uint32_t whd_resource_size(whd_driver_t whd_driver, whd_resource_type_t resource, uint32_t *size_out) +{ + if (whd_driver->resource_if->whd_resource_size) + { + return whd_driver->resource_if->whd_resource_size(whd_driver, resource, size_out); + } + else + { + WPRINT_WHD_ERROR( ("Function pointers not provided .\n") ); + } + + return WHD_WLAN_NOFUNCTION; +} + +uint32_t whd_get_resource_block_size(whd_driver_t whd_driver, whd_resource_type_t type, uint32_t *size_out) +{ + + if (whd_driver->resource_if->whd_get_resource_block_size) + { + return whd_driver->resource_if->whd_get_resource_block_size(whd_driver, type, size_out); + } + else + { + WPRINT_WHD_ERROR( ("Function pointers not provided .\n") ); + } + + return WHD_WLAN_NOFUNCTION; +} + +uint32_t whd_get_resource_no_of_blocks(whd_driver_t whd_driver, whd_resource_type_t type, uint32_t *block_count) +{ + if (whd_driver->resource_if->whd_get_resource_no_of_blocks) + { + return whd_driver->resource_if->whd_get_resource_no_of_blocks(whd_driver, type, block_count); + } + else + { + WPRINT_WHD_ERROR( ("Function pointers not provided .\n") ); + } + + return WHD_WLAN_NOFUNCTION; +} + +uint32_t whd_get_resource_block(whd_driver_t whd_driver, whd_resource_type_t type, + uint32_t blockno, const uint8_t **data, uint32_t *size_out) +{ + + if (whd_driver->resource_if->whd_get_resource_block) + { + return whd_driver->resource_if->whd_get_resource_block(whd_driver, type, blockno, data, size_out); + } + else + { + WPRINT_WHD_ERROR( ("Function pointers not provided .\n") ); + } + + return WHD_WLAN_NOFUNCTION; +} + +uint32_t whd_resource_read(whd_driver_t whd_driver, whd_resource_type_t type, uint32_t offset, + uint32_t size, uint32_t *size_out, void *buffer) +{ + if (whd_driver->resource_if->whd_resource_read) + { + return whd_driver->resource_if->whd_resource_read(whd_driver, type, offset, size, size_out, buffer); + } + else + { + WPRINT_WHD_ERROR( ("Function pointers not provided .\n") ); + } + + return WHD_WLAN_NOFUNCTION; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_sdpcm.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_sdpcm.c new file mode 100644 index 00000000..ad04f4eb --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_sdpcm.c @@ -0,0 +1,688 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Provides an implementation of the Broadcom SDPCM protocol. + * The Broadcom SDPCM protocol provides multiplexing of Wireless Data frames, + * I/O Control functions (IOCTL), and Asynchronous Event signalling. + * It is required when communicating with Broadcom 802.11 devices. + * + */ +#include "whd_sdpcm.h" +#include "bus_protocols/whd_bus_protocol_interface.h" +#include "whd_endian.h" +#include "whd_chip_constants.h" +#include "whd_chip.h" +#include "whd_thread_internal.h" +#include "whd_debug.h" +#include "whd_events_int.h" +#include "whd_wifi_api.h" +#include "whd_buffer_api.h" +#include "whd_network_if.h" +#include "whd_wlioctl.h" +#include "whd_types_int.h" +#include "whd_endian.h" + +/****************************************************** +* @cond Constants +******************************************************/ + +#define ETHER_TYPE_BRCM (0x886C) /** Broadcom Ethertype for identifying event packets - Copied from DHD include/proto/ethernet.h */ +#define BRCM_OUI "\x00\x10\x18" /** Broadcom OUI (Organizationally Unique Identifier): Used in the proprietary(221) IE (Information Element) in all Broadcom devices */ +#define BCM_MSG_IFNAME_MAX (16) /** Maximum length of an interface name in a wl_event_msg_t structure*/ + +#define BDC_FLAG2_IF_MASK (0x0f) + +#define SDPCM_HEADER_LEN (12) + +/* Event flags */ +#define WLC_EVENT_MSG_LINK (0x01) /** link is up */ +#define WLC_EVENT_MSG_FLUSHTXQ (0x02) /** flush tx queue on MIC error */ +#define WLC_EVENT_MSG_GROUP (0x04) /** group MIC error */ +#define WLC_EVENT_MSG_UNKBSS (0x08) /** unknown source bsscfg */ +#define WLC_EVENT_MSG_UNKIF (0x10) /** unknown source OS i/f */ + +/* WMM constants */ +#define MAX_8021P_PRIO 8 +#define MAX_WMM_AC 4 +#define AC_QUEUE_SIZE 64 + +/****************************************************** +* Macros +******************************************************/ + +/****************************************************** +* Local Structures +******************************************************/ + +#pragma pack(1) + +/* + * Sdio bus specific header consists of 3 parts: + * hardware header, hardware extension header and software header + * - hardware header (frame tag) - 4 bytes + * - hardware extension header - 8 bytes + * - software header - 8 bytes + */ +/* + * Sdio bus specific header - Software header + */ +typedef struct +{ + uint8_t sequence; /* Rx/Tx sequence number */ + uint8_t channel_and_flags; /* 4 MSB Channel number, 4 LSB arbitrary flag */ + uint8_t next_length; /* Length of next data frame, reserved for Tx */ + uint8_t header_length; /* Data offset */ + uint8_t wireless_flow_control; /* Flow control bits, reserved for Tx */ + uint8_t bus_data_credit; /* Maximum Sequence number allowed by firmware for Tx */ + uint8_t _reserved[2]; /* Reserved */ +} sdpcm_sw_header_t; + +/* + * SDPCM header definitions + */ +typedef struct +{ + uint16_t frametag[2]; + sdpcm_sw_header_t sw_header; +} sdpcm_header_t; + +typedef struct bcmeth_hdr +{ + uint16_t subtype; /** Vendor specific..32769 */ + uint16_t length; + uint8_t version; /** Version is 0 */ + uint8_t oui[3]; /** Broadcom OUI */ + uint16_t usr_subtype; /** user specific Data */ +} sdpcm_bcmeth_header_t; + +/* these fields are stored in network order */ +typedef struct +{ + + uint16_t version; /** Version 1 has fields up to ifname. + * Version 2 has all fields including ifidx and bss_cfg_idx */ + uint16_t flags; /** see flags */ + uint32_t event_type; /** Message */ + uint32_t status; /** Status code */ + uint32_t reason; /** Reason code (if applicable) */ + uint32_t auth_type; /** WLC_E_AUTH */ + uint32_t datalen; /** data buf */ + whd_mac_t addr; /** Station address (if applicable) */ + char ifname[BCM_MSG_IFNAME_MAX]; /** name of the packet incoming interface */ + uint8_t ifidx; /** destination OS i/f index */ + uint8_t bss_cfg_idx; /** source bsscfg index */ +} sdpcm_raw_event_header_t; + +/* used by driver msgs */ +typedef struct bcm_event +{ + ethernet_header_t ether; + sdpcm_bcmeth_header_t bcmeth; + union + { + whd_event_header_t whd; + sdpcm_raw_event_header_t raw; + } event; +} sdpcm_bcm_event_t; + +#pragma pack() + +/****************************************************** +* Static Variables +******************************************************/ +/** 802.1p Priority to WMM AC Mapping + * + * prio 0, 3: Background(0) + * prio 1, 2: Best Effor(1) + * prio 4, 5: Video(2) + * prio 6, 7: Voice(3) + * prio 8 : Control(4)(ex: IOVAR/IOCTL) + */ +static const uint8_t prio_to_ac[9] = {1, 0, 0, 1, 2, 2, 3, 3, 4}; + +/****************************************************** +* SDPCM Logging +* +* Enable this section to allow logging of SDPCM packets +* into a buffer for later perusal +* +* See sdpcm_log and next_sdpcm_log_pos +* +******************************************************/ +/** @cond */ + +#if 0 + +#define SDPCM_LOG_SIZE 30 +#define SDPCM_LOG_HEADER_SIZE (0x60) + +typedef enum { UNUSED, LOG_TX, LOG_RX } sdpcm_log_direction_t; +typedef enum { IOCTL, DATA, EVENT } sdpcm_log_type_t; + +typedef struct SDPCM_log_entry_struct +{ + sdpcm_log_direction_t direction; + sdpcm_log_type_t type; + unsigned long time; + unsigned long length; + unsigned char header[SDPCM_LOG_HEADER_SIZE]; +}sdpcm_log_entry_t; + +static int next_sdpcm_log_pos = 0; +static sdpcm_log_entry_t sdpcm_log[SDPCM_LOG_SIZE]; + +static void add_sdpcm_log_entry(sdpcm_log_direction_t dir, sdpcm_log_type_t type, unsigned long length, char *eth_data) +{ + + sdpcm_log[next_sdpcm_log_pos].direction = dir; + sdpcm_log[next_sdpcm_log_pos].type = type; + cy_rtos_get_time(&sdpcm_log[next_sdpcm_log_pos].time); + sdpcm_log[next_sdpcm_log_pos].length = length; + memcpy(sdpcm_log[next_sdpcm_log_pos].header, eth_data, SDPCM_LOG_HEADER_SIZE); + next_sdpcm_log_pos++; + if (next_sdpcm_log_pos >= SDPCM_LOG_SIZE) + { + next_sdpcm_log_pos = 0; + } +} + +#else +#define add_sdpcm_log_entry(dir, type, length, eth_data) +#endif + +/** @endcond */ + +/****************************************************** +* Static Function Prototypes +******************************************************/ +static whd_buffer_t whd_sdpcm_get_next_buffer_in_queue(whd_driver_t whd_driver, whd_buffer_t buffer); +static void whd_sdpcm_set_next_buffer_in_queue(whd_driver_t whd_driver, whd_buffer_t buffer, + whd_buffer_t prev_buffer); +extern void whd_wifi_log_event(whd_driver_t whd_driver, const whd_event_header_t *event_header, + const uint8_t *event_data); +/****************************************************** +* Function definitions +******************************************************/ + +/** Initialises the SDPCM protocol handler + * + * Initialises mutex and semaphore flags needed by the SDPCM handler. + * Also initialises the list of event handlers. This function is called + * from the @ref whd_thread_init function. + * + * @return WHD result code + */ + +whd_result_t whd_sdpcm_init(whd_driver_t whd_driver) +{ + whd_sdpcm_info_t *sdpcm_info = &whd_driver->sdpcm_info; + int ac; + + /* Create the sdpcm packet queue semaphore */ + if (cy_rtos_init_semaphore(&sdpcm_info->send_queue_mutex, 1, 0) != WHD_SUCCESS) + { + return WHD_SEMAPHORE_ERROR; + } + if (cy_rtos_set_semaphore(&sdpcm_info->send_queue_mutex, WHD_FALSE) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + return WHD_SEMAPHORE_ERROR; + } + + /* Packet send queue variables */ + for (ac = 0; ac <= MAX_WMM_AC; ac++) + { + sdpcm_info->send_queue_head[ac] = (whd_buffer_t)NULL; + sdpcm_info->send_queue_tail[ac] = (whd_buffer_t)NULL; + sdpcm_info->npkt_in_q[ac] = 0; + } + sdpcm_info->totpkt_in_q = 0; + + whd_sdpcm_bus_vars_init(whd_driver); + + return WHD_SUCCESS; +} + +/* Re-initialize the bus variables after deep sleep */ +void whd_sdpcm_bus_vars_init(whd_driver_t whd_driver) +{ + whd_sdpcm_info_t *sdpcm_info = &whd_driver->sdpcm_info; + + /* Bus data credit variables */ + sdpcm_info->tx_seq = 0; + sdpcm_info->tx_max = (uint8_t)1; +} + +/** Initialises the SDPCM protocol handler + * + * De-initialises mutex and semaphore flags needed by the SDPCM handler. + * This function is called from the @ref whd_thread_func function when it is exiting. + */ +void whd_sdpcm_quit(whd_driver_t whd_driver) +{ + whd_sdpcm_info_t *sdpcm_info = &whd_driver->sdpcm_info; + whd_result_t result; + int ac; + + /* Delete the SDPCM queue mutex */ + (void)cy_rtos_deinit_semaphore(&sdpcm_info->send_queue_mutex); /* Ignore return - not much can be done about failure */ + + /* Free any left over packets in the queue */ + for (ac = 0; ac <= MAX_WMM_AC; ac++) + { + while (sdpcm_info->send_queue_head[ac] != NULL) + { + whd_buffer_t buf = whd_sdpcm_get_next_buffer_in_queue(whd_driver, sdpcm_info->send_queue_head[ac]); + result = whd_buffer_release(whd_driver, sdpcm_info->send_queue_head[ac], WHD_NETWORK_TX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + sdpcm_info->send_queue_head[ac] = buf; + } + sdpcm_info->npkt_in_q[ac] = 0; + } + sdpcm_info->totpkt_in_q = 0; +} + +void whd_sdpcm_update_credit(whd_driver_t whd_driver, uint8_t *data) +{ + sdpcm_sw_header_t *header = (sdpcm_sw_header_t *)(data + 4); + whd_sdpcm_info_t *sdpcm_info = &whd_driver->sdpcm_info; + uint8_t tx_seq_max; + + if ( (header->channel_and_flags & 0x0f) < (uint8_t)3 ) + { + tx_seq_max = header->bus_data_credit; + WPRINT_WHD_DATA_LOG( ("credit update to %d\n ", tx_seq_max) ); + if (tx_seq_max - sdpcm_info->tx_seq > 0x40) + { + WPRINT_WHD_ERROR( ("update credit error\n") ); + tx_seq_max = sdpcm_info->tx_seq + 2; + } + sdpcm_info->tx_max = tx_seq_max; + } + + whd_bus_set_flow_control(whd_driver, header->wireless_flow_control); +} + +/** Processes and directs incoming SDPCM packets + * + * This function receives SDPCM packets from the Broadcom 802.11 device and decodes the SDPCM header + * to determine where the packet should be directed. + * + * Control packets (IOCTL/IOVAR) / Data Packets/ Event Packets are passed to CDC/BDC layer + * and the appropriate event handler is called. + * + * @param buffer : The SDPCM packet buffer received from the Broadcom 802.11 device + * + */ +void whd_sdpcm_process_rx_packet(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + bus_common_header_t *packet; + uint16_t size; + uint16_t size_inv; + sdpcm_header_t sdpcm_header; + whd_result_t result; + + packet = (bus_common_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + CHECK_PACKET_WITH_NULL_RETURN(packet); + memcpy(&sdpcm_header, packet->bus_header, BUS_HEADER_LEN); + + sdpcm_header.frametag[0] = dtoh16(sdpcm_header.frametag[0]); + sdpcm_header.frametag[1] = dtoh16(sdpcm_header.frametag[1]); + + /* Extract the total SDPCM packet size from the first two frametag bytes */ + size = sdpcm_header.frametag[0]; + + /* Check that the second two frametag bytes are the binary inverse of the size */ + size_inv = (uint16_t) ~size; /* Separate variable due to GCC Bug 38341 */ + if (sdpcm_header.frametag[1] != size_inv) + { + WPRINT_WHD_DEBUG( ("Received a packet with a frametag which is wrong\n") ); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + return; + } + + /* Check whether the packet is big enough to contain the SDPCM header (or) it's too big to handle */ + if ( (size < (uint16_t)SDPCM_HEADER_LEN) || (size > whd_buffer_get_current_piece_size(whd_driver, buffer) ) ) + { + whd_minor_assert("Packet size invalid", 0 == 1); + WPRINT_WHD_DEBUG( ( + "Received a packet that is too small to contain anything useful (or) too big. Packet Size = [%d]\n", + size) ); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + return; + } + + /* Get address of packet->sdpcm_header.frametag indirectly to avoid IAR's unaligned address warning */ + whd_sdpcm_update_credit(whd_driver, + (uint8_t *)&sdpcm_header.sw_header - sizeof(sdpcm_header.frametag) ); + + if (size == (uint16_t)SDPCM_HEADER_LEN) + { + /* This is a flow control update packet with no data - release it. */ + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + + return; + } + + /* Check the SDPCM channel to decide what to do with packet. */ + switch (sdpcm_header.sw_header.channel_and_flags & 0x0f) + { + case CONTROL_HEADER: /* IOCTL/IOVAR reply packet */ + { + add_sdpcm_log_entry(LOG_RX, IOCTL, whd_buffer_get_current_piece_size(whd_driver, buffer), + (char *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer) ); + + /* Check that packet size is big enough to contain the CDC header as well as the SDPCM header */ + if (sdpcm_header.frametag[0] < + (sizeof(sdpcm_header.frametag) + sizeof(sdpcm_sw_header_t) + sizeof(cdc_header_t) ) ) + { + /* Received a too-short SDPCM packet! */ + WPRINT_WHD_DEBUG( ("Received a too-short SDPCM packet!\n") ); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + + break; + } + + /* Move SDPCM header and Buffer header to pass onto next layer */ + whd_buffer_add_remove_at_front(whd_driver, &buffer, + (int32_t)(sizeof(whd_buffer_header_t) + + sdpcm_header.sw_header.header_length) ); + + whd_process_cdc(whd_driver, buffer); + } + + break; + + case DATA_HEADER: + { + /* Check that the packet is big enough to contain SDPCM & BDC headers */ + if (sdpcm_header.frametag[0] <= + (sizeof(sdpcm_header.frametag) + sizeof(sdpcm_sw_header_t) + sizeof(bdc_header_t) ) ) + { + WPRINT_WHD_ERROR( ("Packet too small to contain SDPCM + BDC headers\n") ); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + + break; + } + + /* Move SDPCM header and Buffer header to pass onto next layer */ + whd_buffer_add_remove_at_front(whd_driver, &buffer, + (int32_t)(sizeof(whd_buffer_header_t) + + sdpcm_header.sw_header.header_length) ); + + whd_process_bdc(whd_driver, buffer); + + } + break; + + case ASYNCEVENT_HEADER: + { + + /* Move SDPCM header and Buffer header to pass onto next layer */ + whd_buffer_add_remove_at_front(whd_driver, &buffer, + (int32_t)(sizeof(whd_buffer_header_t) + + sdpcm_header.sw_header.header_length) ); + + whd_process_bdc_event(whd_driver, buffer, size); + } + break; + + default: + whd_minor_assert("SDPCM packet of unknown channel received - dropping packet", 0 != 0); + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_RX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + break; + } +} + +whd_bool_t whd_sdpcm_has_tx_packet(whd_driver_t whd_driver) +{ + if (whd_driver->sdpcm_info.totpkt_in_q > 0) + { + return WHD_TRUE; + } + + return WHD_FALSE; +} + +whd_result_t whd_sdpcm_get_packet_to_send(whd_driver_t whd_driver, whd_buffer_t *buffer) +{ + bus_common_header_t *packet; + sdpcm_header_t sdpcm_header; + whd_sdpcm_info_t *sdpcm_info = &whd_driver->sdpcm_info; + whd_result_t result; + int ac; + + if (sdpcm_info->totpkt_in_q <= 0) + { + return WHD_NO_PACKET_TO_SEND; + } + + /* Check if we're being flow controlled for Data packet only. */ + if ( (whd_bus_is_flow_controlled(whd_driver) == WHD_TRUE) && (sdpcm_info->npkt_in_q[MAX_WMM_AC] == 0) ) + { + WHD_STATS_INCREMENT_VARIABLE(whd_driver, flow_control); + return WHD_FLOW_CONTROLLED; + } + + /* Check if we have enough bus data credits spare */ + if ( ( (uint8_t)(sdpcm_info->tx_max - sdpcm_info->tx_seq) == 0 ) || + ( ( (uint8_t)(sdpcm_info->tx_max - sdpcm_info->tx_seq) & 0x80 ) != 0 ) ) + { + WHD_STATS_INCREMENT_VARIABLE(whd_driver, no_credit); + return WHD_NO_CREDITS; + } + + /* There is a packet waiting to be sent - send it then fix up queue and release packet */ + if (cy_rtos_get_semaphore(&sdpcm_info->send_queue_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE) != WHD_SUCCESS) + { + /* Could not obtain mutex, push back the flow control semaphore */ + WPRINT_WHD_ERROR( ("Error manipulating a semaphore, %s failed at %d \n", __func__, __LINE__) ); + return WHD_SEMAPHORE_ERROR; + } + + for (ac = MAX_WMM_AC; ac >= 0; ac--) + { + if (sdpcm_info->send_queue_head[ac] != NULL) + { + break; + } + } + if (ac < 0) + { + WPRINT_WHD_ERROR( ("NO pkt available in queue, %s failed at %d\n", __func__, __LINE__) ); + return WHD_NO_PACKET_TO_SEND; + } + /* Pop the head off and set the new send_queue head */ + *buffer = sdpcm_info->send_queue_head[ac]; + sdpcm_info->send_queue_head[ac] = whd_sdpcm_get_next_buffer_in_queue(whd_driver, *buffer); + if (sdpcm_info->send_queue_head[ac] == NULL) + { + sdpcm_info->send_queue_tail[ac] = NULL; + } + sdpcm_info->npkt_in_q[ac]--; + sdpcm_info->totpkt_in_q--; + result = cy_rtos_set_semaphore(&sdpcm_info->send_queue_mutex, WHD_FALSE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + } + + /* Set the sequence number */ + packet = (bus_common_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, *buffer); + CHECK_PACKET_NULL(packet, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy(&sdpcm_header, packet->bus_header, BUS_HEADER_LEN); + sdpcm_header.sw_header.sequence = sdpcm_info->tx_seq; + memcpy(packet->bus_header, &sdpcm_header, BUS_HEADER_LEN); + sdpcm_info->tx_seq++; + + return WHD_SUCCESS; +} + +/** Returns the number of bus credits available + * + * @return The number of bus credits available + */ +uint8_t whd_sdpcm_get_available_credits(whd_driver_t whd_driver) +{ + uint8_t tx_max = whd_driver->sdpcm_info.tx_max; + uint8_t tx_seq = whd_driver->sdpcm_info.tx_seq; + if ( ( (uint8_t)(tx_max - tx_seq) & 0x80 ) != 0 ) + { + return 0; + } + return (uint8_t)(tx_max - tx_seq); +} + +/** Writes SDPCM headers and sends packet to WHD Thread + * + * Prepends the given packet with a new SDPCM header, + * then passes the packet to the WHD thread via a queue + * + * This function is called by @ref whd_network_send_ethernet_data and @ref whd_cdc_send_ioctl + * + * @param buffer : The handle of the packet buffer to send + * @param header_type : DATA_HEADER, ASYNCEVENT_HEADER or CONTROL_HEADER - indicating what type of SDPCM packet this is. + * + * @return WHD result code + */ +whd_result_t whd_send_to_bus(whd_driver_t whd_driver, whd_buffer_t buffer, + sdpcm_header_type_t header_type, uint8_t prio) +{ + uint16_t size; + uint8_t *data = NULL; + bus_common_header_t *packet = + (bus_common_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + sdpcm_header_t sdpcm_header; + whd_sdpcm_info_t *sdpcm_info = &whd_driver->sdpcm_info; + whd_result_t result; + int ac; + + CHECK_PACKET_NULL(packet, WHD_NO_REGISTER_FUNCTION_POINTER); + size = whd_buffer_get_current_piece_size(whd_driver, buffer); + + size = (uint16_t)(size - (uint16_t)sizeof(whd_buffer_header_t) ); + + /* Prepare the SDPCM header */ + memset( (uint8_t *)&sdpcm_header, 0, sizeof(sdpcm_header_t) ); + sdpcm_header.sw_header.channel_and_flags = (uint8_t)header_type; + sdpcm_header.sw_header.header_length = + (header_type == DATA_HEADER) ? sizeof(sdpcm_header_t) + 2 : sizeof(sdpcm_header_t); + sdpcm_header.sw_header.sequence = 0; /* Note: The real sequence will be written later */ + sdpcm_header.frametag[0] = size; + sdpcm_header.frametag[1] = (uint16_t) ~size; + + memcpy(packet->bus_header, &sdpcm_header, BUS_HEADER_LEN); + data = whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + add_sdpcm_log_entry(LOG_TX, (header_type == DATA_HEADER) ? DATA : (header_type == CONTROL_HEADER) ? IOCTL : EVENT, + whd_buffer_get_current_piece_size(whd_driver, buffer), + (char *)data); + + /* Add the length of the SDPCM header and pass "down" */ + if (cy_rtos_get_semaphore(&sdpcm_info->send_queue_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE) != WHD_SUCCESS) + { + /* Could not obtain mutex */ + /* Fatal error */ + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_TX); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + return WHD_SEMAPHORE_ERROR; + } + + /* The input priority should not higher than MAX_8021P_PRIO(7) */ + if (prio > MAX_8021P_PRIO) + { + prio = MAX_8021P_PRIO; + } + ac = prio_to_ac[prio]; + + if ( (header_type == DATA_HEADER) && (sdpcm_info->npkt_in_q[ac] > AC_QUEUE_SIZE) ) + { + result = whd_buffer_release(whd_driver, buffer, WHD_NETWORK_TX); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("buffer release failed in %s at %d \n", __func__, __LINE__) ); + } + result = cy_rtos_set_semaphore(&sdpcm_info->send_queue_mutex, WHD_FALSE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + } + whd_thread_notify(whd_driver); + return WHD_BUFFER_ALLOC_FAIL; + } + + whd_sdpcm_set_next_buffer_in_queue(whd_driver, NULL, buffer); + if (sdpcm_info->send_queue_tail[ac] != NULL) + { + whd_sdpcm_set_next_buffer_in_queue(whd_driver, buffer, sdpcm_info->send_queue_tail[ac]); + } + sdpcm_info->send_queue_tail[ac] = buffer; + if (sdpcm_info->send_queue_head[ac] == NULL) + { + sdpcm_info->send_queue_head[ac] = buffer; + } + sdpcm_info->npkt_in_q[ac]++; + sdpcm_info->totpkt_in_q++; + result = cy_rtos_set_semaphore(&sdpcm_info->send_queue_mutex, WHD_FALSE); + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + + whd_thread_notify(whd_driver); + + return WHD_SUCCESS; +} + +/****************************************************** +* Static Functions +******************************************************/ + +static whd_buffer_t whd_sdpcm_get_next_buffer_in_queue(whd_driver_t whd_driver, whd_buffer_t buffer) +{ + whd_buffer_header_t *packet = (whd_buffer_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, buffer); + return packet->queue_next; +} + +/** Sets the next buffer in the send queue + * + * The send queue is a linked list of packet buffers where the 'next' pointer + * is stored in the first 4 bytes of the buffer content. + * This function sets that pointer. + * + * @param buffer : handle of packet in the send queue + * prev_buffer : handle of new packet whose 'next' pointer will point to 'buffer' + */ +static void whd_sdpcm_set_next_buffer_in_queue(whd_driver_t whd_driver, whd_buffer_t buffer, whd_buffer_t prev_buffer) +{ + whd_buffer_header_t *packet = + (whd_buffer_header_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, prev_buffer); + packet->queue_next = buffer; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_thread.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_thread.c new file mode 100644 index 00000000..6cb737ef --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_thread.c @@ -0,0 +1,363 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Allows thread safe access to the WHD WiFi Driver (WHD) hardware bus + * + * This file provides functions which allow multiple threads to use the WHD hardware bus (SDIO or SPI) + * This is achieved by having a single thread (the "WHD Thread") which queues messages to be sent, sending + * them sequentially, as well as receiving messages as they arrive. + * + * Messages to be sent come from the @ref whd_sdpcm_send_common function in whd_sdpcm.c . The messages already + * contain SDPCM headers, but not any bus headers (GSPI), and are passed to the whd_thread_send_data function. + * This function can be called from any thread. + * + * Messages are received by way of a callback supplied by in SDPCM.c - whd_sdpcm_process_rx_packet + * Received messages are delivered in the context of the WHD Thread, so the callback function needs to avoid blocking. + * + * It is also possible to use these functions without any operating system, by periodically calling the whd_thread_send_one_packet, + * @ref whd_thread_receive_one_packet or @ref whd_thread_poll_all functions + * + */ +#include "stdlib.h" +#include "whd_debug.h" +#include "whd_thread.h" +#include "bus_protocols/whd_bus_protocol_interface.h" +#include "cyabs_rtos.h" +#include "whd_int.h" +#include "whd_chip.h" +#include "whd_poll.h" +#include "whd_sdpcm.h" +#include "whd_buffer_api.h" +#include "whd_chip_constants.h" + +/****************************************************** +* Static Function Prototypes +******************************************************/ +static void whd_thread_func(cy_thread_arg_t thread_input); + +/****************************************************** +* Global Functions +******************************************************/ +void whd_thread_info_init(whd_driver_t whd_driver, whd_init_config_t *whd_init_config) +{ + memset(&whd_driver->thread_info, 0, sizeof(whd_driver->thread_info) ); + whd_driver->thread_info.thread_stack_start = whd_init_config->thread_stack_start; + whd_driver->thread_info.thread_stack_size = whd_init_config->thread_stack_size; + whd_driver->thread_info.thread_priority = (cy_thread_priority_t)whd_init_config->thread_priority; +} + +/** Initialises the WHD Thread + * + * Initialises the WHD thread, and its flags/semaphores, + * then starts it running + * + * @return WHD_SUCCESS : if initialisation succeeds + * otherwise, a result code + */ +whd_result_t whd_thread_init(whd_driver_t whd_driver) +{ + whd_result_t retval; + + retval = whd_sdpcm_init(whd_driver); + + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Could not initialize SDPCM codec\n") ); + /* Lint: Reachable after hitting assert & globals not defined due to error */ + return retval; + } + + /* Create the event flag which signals the WHD thread needs to wake up */ + retval = cy_rtos_init_semaphore(&whd_driver->thread_info.transceive_semaphore, 1, 0); + if (retval != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Could not initialize WHD thread semaphore\n") ); + /* Lint: Reachable after hitting assert & globals not defined due to error */ + return retval; + } + + retval = cy_rtos_create_thread(&whd_driver->thread_info.whd_thread, (cy_thread_entry_fn_t)whd_thread_func, + "WHD", whd_driver->thread_info.thread_stack_start, + whd_driver->thread_info.thread_stack_size, + whd_driver->thread_info.thread_priority, (cy_thread_arg_t)whd_driver); + if (retval != WHD_SUCCESS) + { + /* Could not start WHD main thread */ + WPRINT_WHD_ERROR( ("Could not start WHD thread\n") ); + return retval; + } + + /* Ready now. Indicate it here and in thread, whatever be executed first. */ + whd_driver->thread_info.whd_inited = WHD_TRUE; + + return WHD_SUCCESS; +} + +/** Sends the first queued packet + * + * Checks the queue to determine if there is any packets waiting + * to be sent. If there are, then it sends the first one. + * + * This function is normally used by the WHD Thread, but can be + * called periodically by systems which have no RTOS to ensure + * packets get sent. + * + * @return 1 : packet was sent + * 0 : no packet sent + */ +int8_t whd_thread_send_one_packet(whd_driver_t whd_driver) +{ + whd_buffer_t tmp_buf_hnd = NULL; + whd_result_t result; + + if (whd_sdpcm_get_packet_to_send(whd_driver, &tmp_buf_hnd) != WHD_SUCCESS) + { + /* Failed to get a packet */ + return 0; + } + + /* Ensure the wlan backplane bus is up */ + result = whd_ensure_wlan_bus_is_up(whd_driver); + if (result != WHD_SUCCESS) + { + whd_assert("Could not bring bus back up", 0 != 0); + CHECK_RETURN(whd_buffer_release(whd_driver, tmp_buf_hnd, WHD_NETWORK_TX) ); + return 0; + } + + WPRINT_WHD_DATA_LOG( ("Wcd:> Sending pkt 0x%08lX\n", (unsigned long)tmp_buf_hnd) ); + if (whd_bus_send_buffer(whd_driver, tmp_buf_hnd) != WHD_SUCCESS) + { + WHD_STATS_INCREMENT_VARIABLE(whd_driver, tx_fail); + return 0; + } + + WHD_STATS_INCREMENT_VARIABLE(whd_driver, tx_total); + return (int8_t)1; +} + +/** Receives a packet if one is waiting + * + * Checks the wifi chip fifo to determine if there is any packets waiting + * to be received. If there are, then it receives the first one, and calls + * the callback @ref whd_sdpcm_process_rx_packet (in whd_sdpcm.c). + * + * This function is normally used by the WHD Thread, but can be + * called periodically by systems which have no RTOS to ensure + * packets get received properly. + * + * @return 1 : packet was received + * 0 : no packet waiting + */ +int8_t whd_thread_receive_one_packet(whd_driver_t whd_driver) +{ + /* Check if there is a packet ready to be received */ + whd_buffer_t recv_buffer; + if (whd_bus_read_frame(whd_driver, &recv_buffer) != WHD_SUCCESS) + { + /* Failed to read a packet */ + return 0; + } + + if (recv_buffer != NULL) /* Could be null if it was only a credit update */ + { + + WPRINT_WHD_DATA_LOG( ("Wcd:< Rcvd pkt 0x%08lX\n", (unsigned long)recv_buffer) ); + WHD_STATS_INCREMENT_VARIABLE(whd_driver, rx_total); + + /* Send received buffer up to SDPCM layer */ + whd_sdpcm_process_rx_packet(whd_driver, recv_buffer); + } + return (int8_t)1; +} + +/** Sends and Receives all waiting packets + * + * Calls whd_thread_send_one_packet and whd_thread_receive_one_packet + * once to send and receive packets, until there are no more packets waiting to + * be transferred. + * + * This function is normally used by the WHD Thread, but can be + * called periodically by systems which have no RTOS to ensure + * packets get send and received properly. + * + * Note: do not loop in here, to avoid overwriting previously rx-ed packets + */ +int8_t whd_thread_poll_all(whd_driver_t whd_driver) +{ + int8_t result = 0; + result |= whd_thread_send_one_packet(whd_driver); + result |= whd_thread_receive_one_packet(whd_driver); + return result; +} + +/** Terminates the WHD Thread + * + * Sets a flag then wakes the WHD Thread to force it to terminate. + * + */ +void whd_thread_quit(whd_driver_t whd_driver) +{ + whd_thread_info_t *thread_info = &whd_driver->thread_info; + whd_result_t result; + + /* signal main thread and wake it */ + thread_info->thread_quit_flag = WHD_TRUE; + result = cy_rtos_set_semaphore(&thread_info->transceive_semaphore, WHD_FALSE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) ); + } + + /* Wait for the WHD thread to end */ + cy_rtos_join_thread(&thread_info->whd_thread); + /* Delete the semaphore */ + /* Ignore return - not much can be done about failure */ + (void)cy_rtos_deinit_semaphore(&thread_info->transceive_semaphore); +} + +/** + * Informs WHD of an interrupt + * + * This function should be called from the SDIO/SPI interrupt function + * and usually indicates newly received data is available. + * It wakes the WHD Thread, forcing it to check the send/receive + * + */ +/* ignore failure since there is nothing that can be done about it in a ISR */ +void whd_thread_notify_irq(whd_driver_t whd_driver) +{ + whd_driver->thread_info.bus_interrupt = WHD_TRUE; + + /* just wake up the main thread and let it deal with the data */ + if (whd_driver->thread_info.whd_inited == WHD_TRUE) + { + (void)cy_rtos_set_semaphore(&whd_driver->thread_info.transceive_semaphore, WHD_TRUE); + } +} + +void whd_thread_notify(whd_driver_t whd_driver) +{ + /* just wake up the main thread and let it deal with the data */ + if (whd_driver->thread_info.whd_inited == WHD_TRUE) + { + /* Ignore return - not much can be done about failure */ + (void)cy_rtos_set_semaphore(&whd_driver->thread_info.transceive_semaphore, WHD_FALSE); + } +} + +/****************************************************** +* Static Functions +******************************************************/ + +/** The WHD Thread function + * + * This is the main loop of the WHD Thread. + * It simply calls @ref whd_thread_poll_all to send/receive all waiting packets, then goes + * to sleep. The sleep has a 100ms timeout, causing the send/receive queues to be + * checked 10 times per second in case an interrupt is missed. + * Once the quit flag has been set, flags/mutexes are cleaned up, and the function exits. + * + * @param thread_input : unused parameter needed to match thread prototype. + * + */ +static void whd_thread_func(cy_thread_arg_t thread_input) +{ + int8_t rx_status; + int8_t tx_status; + uint8_t rx_cnt, rx_over_bound = 0; + uint8_t bus_fail = 0; + uint8_t error_type; + uint32_t status; + + whd_driver_t whd_driver = ( whd_driver_t )thread_input; + whd_thread_info_t *thread_info = &whd_driver->thread_info; + + WPRINT_WHD_DATA_LOG( ("Started whd Thread\n") ); + + /* Interrupts may be enabled inside thread. To make sure none lost set flag now. */ + thread_info->whd_inited = WHD_TRUE; + + while (thread_info->thread_quit_flag != WHD_TRUE) + { + rx_cnt = 0; + /* Check if we were woken by interrupt */ + if ( (thread_info->bus_interrupt == WHD_TRUE) || + (whd_bus_use_status_report_scheme(whd_driver) ) ) + { + thread_info->bus_interrupt = WHD_FALSE; + + /* Check if the interrupt indicated there is a packet to read */ + status = whd_bus_packet_available_to_read(whd_driver); + if ( ( (status != 0) && (status != WHD_BUS_FAIL) ) || rx_over_bound ) + { + rx_over_bound = 0; + /* Receive all available packets */ + do + { + rx_status = whd_thread_receive_one_packet(whd_driver); + rx_cnt++; + } while (rx_status != 0 && rx_cnt < WHD_THREAD_RX_BOUND); + bus_fail = 0; + } + else + { + if (status == WHD_BUS_FAIL) + { + bus_fail++; + } + } + } + + /* Send all queued packets */ + do + { + tx_status = whd_thread_send_one_packet(whd_driver); + } while (tx_status != 0); + + if (rx_cnt >= WHD_THREAD_RX_BOUND) + { + thread_info->bus_interrupt = WHD_TRUE; + rx_over_bound = 1; + continue; + } + if (bus_fail > WHD_MAX_BUS_FAIL) + { + WPRINT_WHD_ERROR( ("%s: Error bus_fail over %d times\n", __FUNCTION__, WHD_MAX_BUS_FAIL) ); + error_type = WLC_ERR_BUS; + whd_set_error_handler_locally(whd_driver, &error_type, NULL, NULL, NULL); + } + + /* Sleep till WLAN do something */ + whd_bus_wait_for_wlan_event(whd_driver, &thread_info->transceive_semaphore); + WPRINT_WHD_DATA_LOG( ("whd Thread: Woke\n") ); + } + + /* Set flag before releasing objects */ + thread_info->whd_inited = WHD_FALSE; + + /* Reset the quit flag */ + thread_info->thread_quit_flag = WHD_FALSE; + + whd_sdpcm_quit(whd_driver); + + WPRINT_WHD_DATA_LOG( ("Stopped whd Thread\n") ); + + /* Ignore return - not much can be done about failure */ + (void)cy_rtos_exit_thread(); +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_utils.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_utils.c new file mode 100644 index 00000000..0aa985c7 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_utils.c @@ -0,0 +1,1169 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file WHD utilities + * + * Utilities to help do specialized (not general purpose) WHD specific things + */ +#include "whd_debug.h" +#include "whd_utils.h" +#include "whd_chip_constants.h" +#include "whd_endian.h" +#include "whd_int.h" +#include "whd_wlioctl.h" + +#define UNSIGNED_CHAR_TO_CHAR(uch) ( (uch)& 0x7f ) + +#define RSPEC_KBPS_MASK (0x7f) +#define RSPEC_500KBPS(rate) ( (rate)& RSPEC_KBPS_MASK ) +#define RSPEC_TO_KBPS(rate) (RSPEC_500KBPS( (rate) ) * (unsigned int)500) + +#define OTP_WORD_SIZE 16 /* Word size in bits */ +#define WPA_OUI_TYPE1 "\x00\x50\xF2\x01" /** WPA OUI */ + +/****************************************************** +* Static Variables +******************************************************/ +whd_tlv8_data_t *whd_tlv_find_tlv8(const uint8_t *message, uint32_t message_length, uint8_t type); + +whd_tlv8_data_t *whd_tlv_find_tlv8(const uint8_t *message, uint32_t message_length, uint8_t type) +{ + while (message_length != 0) + { + uint8_t current_tlv_type = message[0]; + uint16_t current_tlv_length = (uint16_t)(message[1] + 2); + + /* Check if we've overrun the buffer */ + if (current_tlv_length > message_length) + { + return NULL; + } + + /* Check if we've found the type we are looking for */ + if (current_tlv_type == type) + { + return (whd_tlv8_data_t *)message; + } + + /* Skip current TLV */ + message += current_tlv_length; + message_length -= current_tlv_length; + } + return 0; +} + +whd_tlv8_header_t *whd_parse_tlvs(const whd_tlv8_header_t *tlv_buf, uint32_t buflen, + dot11_ie_id_t key) +{ + return (whd_tlv8_header_t *)whd_tlv_find_tlv8( (const uint8_t *)tlv_buf, buflen, key ); +} + +whd_bool_t whd_is_wpa_ie(vendor_specific_ie_header_t *wpaie, whd_tlv8_header_t **tlvs, uint32_t *tlvs_len) +{ + whd_tlv8_header_t *prev_tlvs = *tlvs; + whd_tlv8_header_t *new_tlvs = *tlvs; + vendor_specific_ie_header_t *ie = wpaie; + + /* If the contents match the WPA_OUI and type=1 */ + if ( (ie->tlv_header.length >= (uint8_t)VENDOR_SPECIFIC_IE_MINIMUM_LENGTH) && + (memcmp(ie->oui, WPA_OUI_TYPE1, sizeof(ie->oui) ) == 0) ) + { + /* Found the WPA IE */ + return WHD_TRUE; + } + + /* calculate the next ie address */ + new_tlvs = (whd_tlv8_header_t *)( ( (uint8_t *)ie ) + ie->tlv_header.length + sizeof(whd_tlv8_header_t) ); + + /* check the rest of length of buffer */ + if (*tlvs_len < (uint32_t)( ( (uint8_t *)new_tlvs ) - ( (uint8_t *)prev_tlvs ) ) ) + { + /* set rest of length to zero to avoid buffer overflow */ + *tlvs_len = 0; + } + else + { + /* point to the next ie */ + *tlvs = new_tlvs; + + /* tlvs now points to the beginning of next IE pointer, and *ie points to one or more TLV further + * down from the *prev_tlvs. So the tlvs_len need to be adjusted by prev_tlvs instead of *ie */ + *tlvs_len -= (uint32_t)( ( (uint8_t *)*tlvs ) - ( (uint8_t *)prev_tlvs ) ); + } + + return WHD_FALSE; +} + +whd_tlv8_header_t *whd_parse_dot11_tlvs(const whd_tlv8_header_t *tlv_buf, uint32_t buflen, dot11_ie_id_t key) +{ + return (whd_tlv8_header_t *)whd_tlv_find_tlv8( (const uint8_t *)tlv_buf, buflen, key ); +} + +#ifdef WPRINT_ENABLE_WHD_DEBUG +char *whd_ssid_to_string(uint8_t *value, uint8_t length, char *ssid_buf, uint8_t ssid_buf_len) +{ + memset(ssid_buf, 0, ssid_buf_len); + + if (ssid_buf_len > 0) + { + memcpy(ssid_buf, value, ssid_buf_len < length ? ssid_buf_len : length); + } + + return ssid_buf; +} + +/* When adding new events, update this switch statement to print correct string */ +#define CASE_RETURN_STRING(value) case value: \ + return # value; + +#define CASE_RETURN(value) case value: \ + break; + +const char *whd_event_to_string(whd_event_num_t value) +{ + switch (value) + { + CASE_RETURN_STRING(WLC_E_ULP) + CASE_RETURN(WLC_E_BT_WIFI_HANDOVER_REQ) + CASE_RETURN(WLC_E_SPW_TXINHIBIT) + CASE_RETURN(WLC_E_FBT_AUTH_REQ_IND) + CASE_RETURN(WLC_E_RSSI_LQM) + CASE_RETURN(WLC_E_PFN_GSCAN_FULL_RESULT) + CASE_RETURN(WLC_E_PFN_SWC) + CASE_RETURN(WLC_E_AUTHORIZED) + CASE_RETURN(WLC_E_PROBREQ_MSG_RX) + CASE_RETURN(WLC_E_RMC_EVENT) + CASE_RETURN(WLC_E_DPSTA_INTF_IND) + CASE_RETURN_STRING(WLC_E_NONE) + CASE_RETURN_STRING(WLC_E_SET_SSID) + CASE_RETURN(WLC_E_PFN_BEST_BATCHING) + CASE_RETURN(WLC_E_JOIN) + CASE_RETURN(WLC_E_START) + CASE_RETURN_STRING(WLC_E_AUTH) + CASE_RETURN(WLC_E_AUTH_IND) + CASE_RETURN(WLC_E_DEAUTH) + CASE_RETURN_STRING(WLC_E_DEAUTH_IND) + CASE_RETURN(WLC_E_ASSOC) + CASE_RETURN(WLC_E_ASSOC_IND) + CASE_RETURN(WLC_E_REASSOC) + CASE_RETURN(WLC_E_REASSOC_IND) + CASE_RETURN(WLC_E_DISASSOC) + CASE_RETURN_STRING(WLC_E_DISASSOC_IND) + CASE_RETURN(WLC_E_ROAM) + CASE_RETURN(WLC_E_ROAM_PREP) + CASE_RETURN(WLC_E_ROAM_START) + CASE_RETURN(WLC_E_QUIET_START) + CASE_RETURN(WLC_E_QUIET_END) + CASE_RETURN(WLC_E_BEACON_RX) + CASE_RETURN_STRING(WLC_E_LINK) + CASE_RETURN_STRING(WLC_E_RRM) + CASE_RETURN(WLC_E_MIC_ERROR) + CASE_RETURN(WLC_E_NDIS_LINK) + CASE_RETURN(WLC_E_TXFAIL) + CASE_RETURN(WLC_E_PMKID_CACHE) + CASE_RETURN(WLC_E_RETROGRADE_TSF) + CASE_RETURN(WLC_E_PRUNE) + CASE_RETURN(WLC_E_AUTOAUTH) + CASE_RETURN(WLC_E_EAPOL_MSG) + CASE_RETURN(WLC_E_SCAN_COMPLETE) + CASE_RETURN(WLC_E_ADDTS_IND) + CASE_RETURN(WLC_E_DELTS_IND) + CASE_RETURN(WLC_E_BCNSENT_IND) + CASE_RETURN(WLC_E_BCNRX_MSG) + CASE_RETURN(WLC_E_BCNLOST_MSG) + CASE_RETURN_STRING(WLC_E_PFN_NET_FOUND) + CASE_RETURN(WLC_E_PFN_NET_LOST) + CASE_RETURN(WLC_E_RESET_COMPLETE) + CASE_RETURN(WLC_E_JOIN_START) + CASE_RETURN(WLC_E_ASSOC_START) + CASE_RETURN(WLC_E_IBSS_ASSOC) + CASE_RETURN(WLC_E_RADIO) + CASE_RETURN(WLC_E_PSM_WATCHDOG) + CASE_RETURN(WLC_E_CCX_ASSOC_START) + CASE_RETURN(WLC_E_CCX_ASSOC_ABORT) + CASE_RETURN(WLC_E_PROBREQ_MSG) + CASE_RETURN(WLC_E_SCAN_CONFIRM_IND) + CASE_RETURN_STRING(WLC_E_PSK_SUP) + CASE_RETURN(WLC_E_COUNTRY_CODE_CHANGED) + CASE_RETURN(WLC_E_EXCEEDED_MEDIUM_TIME) + CASE_RETURN(WLC_E_ICV_ERROR) + CASE_RETURN(WLC_E_UNICAST_DECODE_ERROR) + CASE_RETURN(WLC_E_MULTICAST_DECODE_ERROR) + CASE_RETURN(WLC_E_TRACE) + CASE_RETURN(WLC_E_BTA_HCI_EVENT) + CASE_RETURN(WLC_E_IF) + CASE_RETURN(WLC_E_P2P_DISC_LISTEN_COMPLETE) + CASE_RETURN(WLC_E_RSSI) + CASE_RETURN_STRING(WLC_E_PFN_SCAN_COMPLETE) + CASE_RETURN(WLC_E_EXTLOG_MSG) + CASE_RETURN(WLC_E_ACTION_FRAME) + CASE_RETURN(WLC_E_ACTION_FRAME_COMPLETE) + CASE_RETURN(WLC_E_PRE_ASSOC_IND) + CASE_RETURN(WLC_E_PRE_REASSOC_IND) + CASE_RETURN(WLC_E_CHANNEL_ADOPTED) + CASE_RETURN(WLC_E_AP_STARTED) + CASE_RETURN(WLC_E_DFS_AP_STOP) + CASE_RETURN(WLC_E_DFS_AP_RESUME) + CASE_RETURN(WLC_E_WAI_STA_EVENT) + CASE_RETURN(WLC_E_WAI_MSG) + CASE_RETURN_STRING(WLC_E_ESCAN_RESULT) + CASE_RETURN(WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE) + CASE_RETURN(WLC_E_PROBRESP_MSG) + CASE_RETURN(WLC_E_P2P_PROBREQ_MSG) + CASE_RETURN(WLC_E_DCS_REQUEST) + CASE_RETURN(WLC_E_FIFO_CREDIT_MAP) + CASE_RETURN(WLC_E_ACTION_FRAME_RX) + CASE_RETURN(WLC_E_WAKE_EVENT) + CASE_RETURN(WLC_E_RM_COMPLETE) + CASE_RETURN(WLC_E_HTSFSYNC) + CASE_RETURN(WLC_E_OVERLAY_REQ) + CASE_RETURN_STRING(WLC_E_CSA_COMPLETE_IND) + CASE_RETURN(WLC_E_EXCESS_PM_WAKE_EVENT) + CASE_RETURN(WLC_E_PFN_SCAN_NONE) + CASE_RETURN(WLC_E_PFN_SCAN_ALLGONE) + CASE_RETURN(WLC_E_GTK_PLUMBED) + CASE_RETURN(WLC_E_ASSOC_IND_NDIS) + CASE_RETURN(WLC_E_REASSOC_IND_NDIS) + CASE_RETURN(WLC_E_ASSOC_REQ_IE) + CASE_RETURN(WLC_E_ASSOC_RESP_IE) + CASE_RETURN(WLC_E_ASSOC_RECREATED) + CASE_RETURN(WLC_E_ACTION_FRAME_RX_NDIS) + CASE_RETURN(WLC_E_AUTH_REQ) + CASE_RETURN(WLC_E_TDLS_PEER_EVENT) + CASE_RETURN(WLC_E_SPEEDY_RECREATE_FAIL) + CASE_RETURN(WLC_E_NATIVE) + CASE_RETURN(WLC_E_PKTDELAY_IND) + CASE_RETURN(WLC_E_AWDL_AW) + CASE_RETURN(WLC_E_AWDL_ROLE) + CASE_RETURN(WLC_E_AWDL_EVENT) + CASE_RETURN(WLC_E_NIC_AF_TXS) + CASE_RETURN(WLC_E_NAN) + CASE_RETURN(WLC_E_BEACON_FRAME_RX) + CASE_RETURN(WLC_E_SERVICE_FOUND) + CASE_RETURN(WLC_E_GAS_FRAGMENT_RX) + CASE_RETURN(WLC_E_GAS_COMPLETE) + CASE_RETURN(WLC_E_P2PO_ADD_DEVICE) + CASE_RETURN(WLC_E_P2PO_DEL_DEVICE) + CASE_RETURN(WLC_E_WNM_STA_SLEEP) + CASE_RETURN(WLC_E_TXFAIL_THRESH) + CASE_RETURN(WLC_E_PROXD) + CASE_RETURN(WLC_E_IBSS_COALESCE) + CASE_RETURN(WLC_E_AWDL_RX_PRB_RESP) + CASE_RETURN(WLC_E_AWDL_RX_ACT_FRAME) + CASE_RETURN(WLC_E_AWDL_WOWL_NULLPKT) + CASE_RETURN(WLC_E_AWDL_PHYCAL_STATUS) + CASE_RETURN(WLC_E_AWDL_OOB_AF_STATUS) + CASE_RETURN(WLC_E_AWDL_SCAN_STATUS) + CASE_RETURN(WLC_E_AWDL_AW_START) + CASE_RETURN(WLC_E_AWDL_AW_END) + CASE_RETURN(WLC_E_AWDL_AW_EXT) + CASE_RETURN(WLC_E_AWDL_PEER_CACHE_CONTROL) + CASE_RETURN(WLC_E_CSA_START_IND) + CASE_RETURN(WLC_E_CSA_DONE_IND) + CASE_RETURN(WLC_E_CSA_FAILURE_IND) + CASE_RETURN(WLC_E_CCA_CHAN_QUAL) + CASE_RETURN(WLC_E_BSSID) + CASE_RETURN(WLC_E_TX_STAT_ERROR) + CASE_RETURN(WLC_E_BCMC_CREDIT_SUPPORT) + CASE_RETURN(WLC_E_PSTA_PRIMARY_INTF_IND) + case WLC_E_LAST: + default: + return "Unknown"; + + break; + } + + return "Unknown"; +} + +const char *whd_status_to_string(whd_event_status_t status) +{ + switch (status) + { + CASE_RETURN_STRING(WLC_E_STATUS_SUCCESS) + CASE_RETURN_STRING(WLC_E_STATUS_FAIL) + CASE_RETURN_STRING(WLC_E_STATUS_TIMEOUT) + CASE_RETURN_STRING(WLC_E_STATUS_NO_NETWORKS) + CASE_RETURN_STRING(WLC_E_STATUS_ABORT) + CASE_RETURN_STRING(WLC_E_STATUS_NO_ACK) + CASE_RETURN_STRING(WLC_E_STATUS_UNSOLICITED) + CASE_RETURN_STRING(WLC_E_STATUS_ATTEMPT) + CASE_RETURN_STRING(WLC_E_STATUS_PARTIAL) + CASE_RETURN_STRING(WLC_E_STATUS_NEWSCAN) + CASE_RETURN_STRING(WLC_E_STATUS_NEWASSOC) + CASE_RETURN_STRING(WLC_E_STATUS_11HQUIET) + CASE_RETURN_STRING(WLC_E_STATUS_SUPPRESS) + CASE_RETURN_STRING(WLC_E_STATUS_NOCHANS) + CASE_RETURN_STRING(WLC_E_STATUS_CCXFASTRM) + CASE_RETURN_STRING(WLC_E_STATUS_CS_ABORT) + CASE_RETURN_STRING(WLC_SUP_DISCONNECTED) + CASE_RETURN_STRING(WLC_SUP_CONNECTING) + CASE_RETURN_STRING(WLC_SUP_IDREQUIRED) + CASE_RETURN_STRING(WLC_SUP_AUTHENTICATING) + CASE_RETURN_STRING(WLC_SUP_AUTHENTICATED) + CASE_RETURN_STRING(WLC_SUP_KEYXCHANGE) + CASE_RETURN_STRING(WLC_SUP_KEYED) + CASE_RETURN_STRING(WLC_SUP_TIMEOUT) + CASE_RETURN_STRING(WLC_SUP_LAST_BASIC_STATE) + CASE_RETURN_STRING(WLC_SUP_KEYXCHANGE_PREP_M4) + CASE_RETURN_STRING(WLC_SUP_KEYXCHANGE_WAIT_G1) + CASE_RETURN_STRING(WLC_SUP_KEYXCHANGE_PREP_G2) + CASE_RETURN_STRING(WLC_DOT11_SC_SUCCESS) + CASE_RETURN_STRING(WLC_DOT11_SC_FAILURE) + CASE_RETURN_STRING(WLC_DOT11_SC_CAP_MISMATCH) + CASE_RETURN_STRING(WLC_DOT11_SC_REASSOC_FAIL) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_FAIL) + CASE_RETURN_STRING(WLC_DOT11_SC_AUTH_MISMATCH) + CASE_RETURN_STRING(WLC_DOT11_SC_AUTH_SEQ) + CASE_RETURN_STRING(WLC_DOT11_SC_AUTH_CHALLENGE_FAIL) + CASE_RETURN_STRING(WLC_DOT11_SC_AUTH_TIMEOUT) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_BUSY_FAIL) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_RATE_MISMATCH) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_SHORT_REQUIRED) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_PBCC_REQUIRED) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_AGILITY_REQUIRED) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_SPECTRUM_REQUIRED) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_BAD_POWER_CAP) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_BAD_SUP_CHANNELS) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_SHORTSLOT_REQUIRED) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_ERPBCC_REQUIRED) + CASE_RETURN_STRING(WLC_DOT11_SC_ASSOC_DSSOFDM_REQUIRED) + CASE_RETURN_STRING(WLC_DOT11_SC_DECLINED) + CASE_RETURN_STRING(WLC_DOT11_SC_INVALID_PARAMS) + CASE_RETURN_STRING(WLC_DOT11_SC_INVALID_AKMP) + CASE_RETURN_STRING(WLC_DOT11_SC_INVALID_MDID) + CASE_RETURN_STRING(WLC_DOT11_SC_INVALID_FTIE) + case WLC_E_STATUS_FORCE_32_BIT: + default: + break; + } + return "Unknown"; +} + +const char *whd_reason_to_string(whd_event_reason_t reason) +{ + switch (reason) + { + CASE_RETURN_STRING(WLC_E_REASON_INITIAL_ASSOC) + CASE_RETURN_STRING(WLC_E_REASON_LOW_RSSI) + CASE_RETURN_STRING(WLC_E_REASON_DEAUTH) + CASE_RETURN_STRING(WLC_E_REASON_DISASSOC) + CASE_RETURN_STRING(WLC_E_REASON_BCNS_LOST) + CASE_RETURN_STRING(WLC_E_REASON_FAST_ROAM_FAILED) + CASE_RETURN_STRING(WLC_E_REASON_DIRECTED_ROAM) + CASE_RETURN_STRING(WLC_E_REASON_TSPEC_REJECTED) + CASE_RETURN_STRING(WLC_E_REASON_BETTER_AP) + CASE_RETURN_STRING(WLC_E_PRUNE_ENCR_MISMATCH) + CASE_RETURN_STRING(WLC_E_PRUNE_BCAST_BSSID) + CASE_RETURN_STRING(WLC_E_PRUNE_MAC_DENY) + CASE_RETURN_STRING(WLC_E_PRUNE_MAC_NA) + CASE_RETURN_STRING(WLC_E_PRUNE_REG_PASSV) + CASE_RETURN_STRING(WLC_E_PRUNE_SPCT_MGMT) + CASE_RETURN_STRING(WLC_E_PRUNE_RADAR) + CASE_RETURN_STRING(WLC_E_RSN_MISMATCH) + CASE_RETURN_STRING(WLC_E_PRUNE_NO_COMMON_RATES) + CASE_RETURN_STRING(WLC_E_PRUNE_BASIC_RATES) + CASE_RETURN_STRING(WLC_E_PRUNE_CCXFAST_PREVAP) + CASE_RETURN_STRING(WLC_E_PRUNE_CIPHER_NA) + CASE_RETURN_STRING(WLC_E_PRUNE_KNOWN_STA) + CASE_RETURN_STRING(WLC_E_PRUNE_CCXFAST_DROAM) + CASE_RETURN_STRING(WLC_E_PRUNE_WDS_PEER) + CASE_RETURN_STRING(WLC_E_PRUNE_QBSS_LOAD) + CASE_RETURN_STRING(WLC_E_PRUNE_HOME_AP) + CASE_RETURN_STRING(WLC_E_PRUNE_AP_BLOCKED) + CASE_RETURN_STRING(WLC_E_PRUNE_NO_DIAG_SUPPORT) + CASE_RETURN_STRING(WLC_E_SUP_OTHER) + CASE_RETURN_STRING(WLC_E_SUP_DECRYPT_KEY_DATA) + CASE_RETURN_STRING(WLC_E_SUP_BAD_UCAST_WEP128) + CASE_RETURN_STRING(WLC_E_SUP_BAD_UCAST_WEP40) + CASE_RETURN_STRING(WLC_E_SUP_UNSUP_KEY_LEN) + CASE_RETURN_STRING(WLC_E_SUP_PW_KEY_CIPHER) + CASE_RETURN_STRING(WLC_E_SUP_MSG3_TOO_MANY_IE) + CASE_RETURN_STRING(WLC_E_SUP_MSG3_IE_MISMATCH) + CASE_RETURN_STRING(WLC_E_SUP_NO_INSTALL_FLAG) + CASE_RETURN_STRING(WLC_E_SUP_MSG3_NO_GTK) + CASE_RETURN_STRING(WLC_E_SUP_GRP_KEY_CIPHER) + CASE_RETURN_STRING(WLC_E_SUP_GRP_MSG1_NO_GTK) + CASE_RETURN_STRING(WLC_E_SUP_GTK_DECRYPT_FAIL) + CASE_RETURN_STRING(WLC_E_SUP_SEND_FAIL) + CASE_RETURN_STRING(WLC_E_SUP_DEAUTH) + CASE_RETURN_STRING(WLC_E_SUP_WPA_PSK_TMO) + CASE_RETURN_STRING(DOT11_RC_RESERVED) + CASE_RETURN_STRING(DOT11_RC_UNSPECIFIED) + CASE_RETURN_STRING(DOT11_RC_AUTH_INVAL) + CASE_RETURN_STRING(DOT11_RC_DEAUTH_LEAVING) + CASE_RETURN_STRING(DOT11_RC_INACTIVITY) + CASE_RETURN_STRING(DOT11_RC_BUSY) + CASE_RETURN_STRING(DOT11_RC_INVAL_CLASS_2) + CASE_RETURN_STRING(DOT11_RC_INVAL_CLASS_3) + CASE_RETURN_STRING(DOT11_RC_DISASSOC_LEAVING) + CASE_RETURN_STRING(DOT11_RC_NOT_AUTH) + CASE_RETURN_STRING(DOT11_RC_BAD_PC) + CASE_RETURN_STRING(DOT11_RC_BAD_CHANNELS) + CASE_RETURN_STRING(DOT11_RC_UNSPECIFIED_QOS) + CASE_RETURN_STRING(DOT11_RC_INSUFFCIENT_BW) + CASE_RETURN_STRING(DOT11_RC_EXCESSIVE_FRAMES) + CASE_RETURN_STRING(DOT11_RC_TX_OUTSIDE_TXOP) + CASE_RETURN_STRING(DOT11_RC_LEAVING_QBSS) + CASE_RETURN_STRING(DOT11_RC_BAD_MECHANISM) + CASE_RETURN_STRING(DOT11_RC_SETUP_NEEDED) + CASE_RETURN_STRING(DOT11_RC_TIMEOUT) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_STATUS_CHG) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_MERGE) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_STOP) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_P2P) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_WINDOW_BEGIN_P2P) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_WINDOW_BEGIN_MESH) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_WINDOW_BEGIN_IBSS) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_WINDOW_BEGIN_RANGING) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_POST_DISC) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_DATA_IF_ADD) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_DATA_PEER_ADD) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_DATA_IND) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_DATA_CONF) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_SDF_RX) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_DATA_END) + CASE_RETURN_STRING(WLC_E_NAN_EVENT_BCN_RX) + case DOT11_RC_MAX: + case WLC_E_REASON_FORCE_32_BIT: + default: + break; + } + + return "Unknown"; +} + +char *whd_ether_ntoa(const uint8_t *ea, char *buf, uint8_t buf_len) +{ + const char hex[] = + { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + char *output = buf; + const uint8_t *octet = ea; + + if (buf_len < WHD_ETHER_ADDR_STR_LEN) + { + if (buf_len > 0) + { + /* buffer too short */ + buf[0] = '\0'; + } + return buf; + } + + for (; octet != &ea[WHD_ETHER_ADDR_LEN]; octet++) + { + *output++ = hex[(*octet >> 4) & 0xf]; + *output++ = hex[*octet & 0xf]; + *output++ = ':'; + } + + *(output - 1) = '\0'; + + return buf; +} + +const char *whd_ioctl_to_string(uint32_t ioctl) +{ + switch (ioctl) + { + CASE_RETURN_STRING(WLC_GET_MAGIC) + CASE_RETURN_STRING(WLC_GET_VERSION) + CASE_RETURN_STRING(WLC_UP) + CASE_RETURN_STRING(WLC_DOWN) + CASE_RETURN_STRING(WLC_GET_LOOP) + CASE_RETURN_STRING(WLC_SET_LOOP) + CASE_RETURN_STRING(WLC_DUMP) + CASE_RETURN_STRING(WLC_GET_MSGLEVEL) + CASE_RETURN_STRING(WLC_SET_MSGLEVEL) + CASE_RETURN_STRING(WLC_GET_PROMISC) + CASE_RETURN_STRING(WLC_SET_PROMISC) + CASE_RETURN_STRING(WLC_GET_RATE) + CASE_RETURN_STRING(WLC_GET_INSTANCE) + CASE_RETURN_STRING(WLC_GET_INFRA) + CASE_RETURN_STRING(WLC_SET_INFRA) + CASE_RETURN_STRING(WLC_GET_AUTH) + CASE_RETURN_STRING(WLC_SET_AUTH) + CASE_RETURN_STRING(WLC_GET_BSSID) + CASE_RETURN_STRING(WLC_SET_BSSID) + CASE_RETURN_STRING(WLC_GET_SSID) + CASE_RETURN_STRING(WLC_SET_SSID) + CASE_RETURN_STRING(WLC_RESTART) + CASE_RETURN_STRING(WLC_GET_CHANNEL) + CASE_RETURN_STRING(WLC_SET_CHANNEL) + CASE_RETURN_STRING(WLC_GET_SRL) + CASE_RETURN_STRING(WLC_SET_SRL) + CASE_RETURN_STRING(WLC_GET_LRL) + CASE_RETURN_STRING(WLC_SET_LRL) + CASE_RETURN_STRING(WLC_GET_PLCPHDR) + CASE_RETURN_STRING(WLC_SET_PLCPHDR) + CASE_RETURN_STRING(WLC_GET_RADIO) + CASE_RETURN_STRING(WLC_SET_RADIO) + CASE_RETURN_STRING(WLC_GET_PHYTYPE) + CASE_RETURN_STRING(WLC_DUMP_RATE) + CASE_RETURN_STRING(WLC_SET_RATE_PARAMS) + CASE_RETURN_STRING(WLC_GET_KEY) + CASE_RETURN_STRING(WLC_SET_KEY) + CASE_RETURN_STRING(WLC_GET_REGULATORY) + CASE_RETURN_STRING(WLC_SET_REGULATORY) + CASE_RETURN_STRING(WLC_GET_PASSIVE_SCAN) + CASE_RETURN_STRING(WLC_SET_PASSIVE_SCAN) + CASE_RETURN_STRING(WLC_SCAN) + CASE_RETURN_STRING(WLC_SCAN_RESULTS) + CASE_RETURN_STRING(WLC_DISASSOC) + CASE_RETURN_STRING(WLC_REASSOC) + CASE_RETURN_STRING(WLC_GET_ROAM_TRIGGER) + CASE_RETURN_STRING(WLC_SET_ROAM_TRIGGER) + CASE_RETURN_STRING(WLC_GET_ROAM_DELTA) + CASE_RETURN_STRING(WLC_SET_ROAM_DELTA) + CASE_RETURN_STRING(WLC_GET_ROAM_SCAN_PERIOD) + CASE_RETURN_STRING(WLC_SET_ROAM_SCAN_PERIOD) + CASE_RETURN_STRING(WLC_EVM) + CASE_RETURN_STRING(WLC_GET_TXANT) + CASE_RETURN_STRING(WLC_SET_TXANT) + CASE_RETURN_STRING(WLC_GET_ANTDIV) + CASE_RETURN_STRING(WLC_SET_ANTDIV) + CASE_RETURN_STRING(WLC_GET_CLOSED) + CASE_RETURN_STRING(WLC_SET_CLOSED) + CASE_RETURN_STRING(WLC_GET_MACLIST) + CASE_RETURN_STRING(WLC_SET_MACLIST) + CASE_RETURN_STRING(WLC_GET_RATESET) + CASE_RETURN_STRING(WLC_SET_RATESET) + CASE_RETURN_STRING(WLC_LONGTRAIN) + CASE_RETURN_STRING(WLC_GET_BCNPRD) + CASE_RETURN_STRING(WLC_SET_BCNPRD) + CASE_RETURN_STRING(WLC_GET_DTIMPRD) + CASE_RETURN_STRING(WLC_SET_DTIMPRD) + CASE_RETURN_STRING(WLC_GET_SROM) + CASE_RETURN_STRING(WLC_SET_SROM) + CASE_RETURN_STRING(WLC_GET_WEP_RESTRICT) + CASE_RETURN_STRING(WLC_SET_WEP_RESTRICT) + CASE_RETURN_STRING(WLC_GET_COUNTRY) + CASE_RETURN_STRING(WLC_SET_COUNTRY) + CASE_RETURN_STRING(WLC_GET_PM) + CASE_RETURN_STRING(WLC_SET_PM) + CASE_RETURN_STRING(WLC_GET_WAKE) + CASE_RETURN_STRING(WLC_SET_WAKE) + CASE_RETURN_STRING(WLC_GET_FORCELINK) + CASE_RETURN_STRING(WLC_SET_FORCELINK) + CASE_RETURN_STRING(WLC_FREQ_ACCURACY) + CASE_RETURN_STRING(WLC_CARRIER_SUPPRESS) + CASE_RETURN_STRING(WLC_GET_PHYREG) + CASE_RETURN_STRING(WLC_SET_PHYREG) + CASE_RETURN_STRING(WLC_GET_RADIOREG) + CASE_RETURN_STRING(WLC_SET_RADIOREG) + CASE_RETURN_STRING(WLC_GET_REVINFO) + CASE_RETURN_STRING(WLC_GET_UCANTDIV) + CASE_RETURN_STRING(WLC_SET_UCANTDIV) + CASE_RETURN_STRING(WLC_R_REG) + CASE_RETURN_STRING(WLC_W_REG) + CASE_RETURN_STRING(WLC_GET_MACMODE) + CASE_RETURN_STRING(WLC_SET_MACMODE) + CASE_RETURN_STRING(WLC_GET_MONITOR) + CASE_RETURN_STRING(WLC_SET_MONITOR) + CASE_RETURN_STRING(WLC_GET_GMODE) + CASE_RETURN_STRING(WLC_SET_GMODE) + CASE_RETURN_STRING(WLC_GET_LEGACY_ERP) + CASE_RETURN_STRING(WLC_SET_LEGACY_ERP) + CASE_RETURN_STRING(WLC_GET_RX_ANT) + CASE_RETURN_STRING(WLC_GET_CURR_RATESET) + CASE_RETURN_STRING(WLC_GET_SCANSUPPRESS) + CASE_RETURN_STRING(WLC_SET_SCANSUPPRESS) + CASE_RETURN_STRING(WLC_GET_AP) + CASE_RETURN_STRING(WLC_SET_AP) + CASE_RETURN_STRING(WLC_GET_EAP_RESTRICT) + CASE_RETURN_STRING(WLC_SET_EAP_RESTRICT) + CASE_RETURN_STRING(WLC_SCB_AUTHORIZE) + CASE_RETURN_STRING(WLC_SCB_DEAUTHORIZE) + CASE_RETURN_STRING(WLC_GET_WDSLIST) + CASE_RETURN_STRING(WLC_SET_WDSLIST) + CASE_RETURN_STRING(WLC_GET_ATIM) + CASE_RETURN_STRING(WLC_SET_ATIM) + CASE_RETURN_STRING(WLC_GET_RSSI) + CASE_RETURN_STRING(WLC_GET_PHYANTDIV) + CASE_RETURN_STRING(WLC_SET_PHYANTDIV) + CASE_RETURN_STRING(WLC_AP_RX_ONLY) + CASE_RETURN_STRING(WLC_GET_TX_PATH_PWR) + CASE_RETURN_STRING(WLC_SET_TX_PATH_PWR) + CASE_RETURN_STRING(WLC_GET_WSEC) + CASE_RETURN_STRING(WLC_SET_WSEC) + CASE_RETURN_STRING(WLC_GET_PHY_NOISE) + CASE_RETURN_STRING(WLC_GET_BSS_INFO) + CASE_RETURN_STRING(WLC_GET_PKTCNTS) + CASE_RETURN_STRING(WLC_GET_LAZYWDS) + CASE_RETURN_STRING(WLC_SET_LAZYWDS) + CASE_RETURN_STRING(WLC_GET_BANDLIST) + CASE_RETURN_STRING(WLC_GET_BAND) + CASE_RETURN_STRING(WLC_SET_BAND) + CASE_RETURN_STRING(WLC_SCB_DEAUTHENTICATE) + CASE_RETURN_STRING(WLC_GET_SHORTSLOT) + CASE_RETURN_STRING(WLC_GET_SHORTSLOT_OVERRIDE) + CASE_RETURN_STRING(WLC_SET_SHORTSLOT_OVERRIDE) + CASE_RETURN_STRING(WLC_GET_SHORTSLOT_RESTRICT) + CASE_RETURN_STRING(WLC_SET_SHORTSLOT_RESTRICT) + CASE_RETURN_STRING(WLC_GET_GMODE_PROTECTION) + CASE_RETURN_STRING(WLC_GET_GMODE_PROTECTION_OVERRIDE) + CASE_RETURN_STRING(WLC_SET_GMODE_PROTECTION_OVERRIDE) + CASE_RETURN_STRING(WLC_UPGRADE) + CASE_RETURN_STRING(WLC_GET_IGNORE_BCNS) + CASE_RETURN_STRING(WLC_SET_IGNORE_BCNS) + CASE_RETURN_STRING(WLC_GET_SCB_TIMEOUT) + CASE_RETURN_STRING(WLC_SET_SCB_TIMEOUT) + CASE_RETURN_STRING(WLC_GET_ASSOCLIST) + CASE_RETURN_STRING(WLC_GET_CLK) + CASE_RETURN_STRING(WLC_SET_CLK) + CASE_RETURN_STRING(WLC_GET_UP) + CASE_RETURN_STRING(WLC_OUT) + CASE_RETURN_STRING(WLC_GET_WPA_AUTH) + CASE_RETURN_STRING(WLC_SET_WPA_AUTH) + CASE_RETURN_STRING(WLC_GET_UCFLAGS) + CASE_RETURN_STRING(WLC_SET_UCFLAGS) + CASE_RETURN_STRING(WLC_GET_PWRIDX) + CASE_RETURN_STRING(WLC_SET_PWRIDX) + CASE_RETURN_STRING(WLC_GET_TSSI) + CASE_RETURN_STRING(WLC_GET_SUP_RATESET_OVERRIDE) + CASE_RETURN_STRING(WLC_SET_SUP_RATESET_OVERRIDE) + CASE_RETURN_STRING(WLC_GET_PROTECTION_CONTROL) + CASE_RETURN_STRING(WLC_SET_PROTECTION_CONTROL) + CASE_RETURN_STRING(WLC_GET_PHYLIST) + CASE_RETURN_STRING(WLC_ENCRYPT_STRENGTH) + CASE_RETURN_STRING(WLC_DECRYPT_STATUS) + CASE_RETURN_STRING(WLC_GET_KEY_SEQ) + CASE_RETURN_STRING(WLC_GET_SCAN_CHANNEL_TIME) + CASE_RETURN_STRING(WLC_SET_SCAN_CHANNEL_TIME) + CASE_RETURN_STRING(WLC_GET_SCAN_UNASSOC_TIME) + CASE_RETURN_STRING(WLC_SET_SCAN_UNASSOC_TIME) + CASE_RETURN_STRING(WLC_GET_SCAN_HOME_TIME) + CASE_RETURN_STRING(WLC_SET_SCAN_HOME_TIME) + CASE_RETURN_STRING(WLC_GET_SCAN_NPROBES) + CASE_RETURN_STRING(WLC_SET_SCAN_NPROBES) + CASE_RETURN_STRING(WLC_GET_PRB_RESP_TIMEOUT) + CASE_RETURN_STRING(WLC_SET_PRB_RESP_TIMEOUT) + CASE_RETURN_STRING(WLC_GET_ATTEN) + CASE_RETURN_STRING(WLC_SET_ATTEN) + CASE_RETURN_STRING(WLC_GET_SHMEM) + CASE_RETURN_STRING(WLC_SET_SHMEM) + CASE_RETURN_STRING(WLC_SET_WSEC_TEST) + CASE_RETURN_STRING(WLC_SCB_DEAUTHENTICATE_FOR_REASON) + CASE_RETURN_STRING(WLC_TKIP_COUNTERMEASURES) + CASE_RETURN_STRING(WLC_GET_PIOMODE) + CASE_RETURN_STRING(WLC_SET_PIOMODE) + CASE_RETURN_STRING(WLC_SET_ASSOC_PREFER) + CASE_RETURN_STRING(WLC_GET_ASSOC_PREFER) + CASE_RETURN_STRING(WLC_SET_ROAM_PREFER) + CASE_RETURN_STRING(WLC_GET_ROAM_PREFER) + CASE_RETURN_STRING(WLC_SET_LED) + CASE_RETURN_STRING(WLC_GET_LED) + CASE_RETURN_STRING(WLC_GET_INTERFERENCE_MODE) + CASE_RETURN_STRING(WLC_SET_INTERFERENCE_MODE) + CASE_RETURN_STRING(WLC_GET_CHANNEL_QA) + CASE_RETURN_STRING(WLC_START_CHANNEL_QA) + CASE_RETURN_STRING(WLC_GET_CHANNEL_SEL) + CASE_RETURN_STRING(WLC_START_CHANNEL_SEL) + CASE_RETURN_STRING(WLC_GET_VALID_CHANNELS) + CASE_RETURN_STRING(WLC_GET_FAKEFRAG) + CASE_RETURN_STRING(WLC_SET_FAKEFRAG) + CASE_RETURN_STRING(WLC_GET_PWROUT_PERCENTAGE) + CASE_RETURN_STRING(WLC_SET_PWROUT_PERCENTAGE) + CASE_RETURN_STRING(WLC_SET_BAD_FRAME_PREEMPT) + CASE_RETURN_STRING(WLC_GET_BAD_FRAME_PREEMPT) + CASE_RETURN_STRING(WLC_SET_LEAP_LIST) + CASE_RETURN_STRING(WLC_GET_LEAP_LIST) + CASE_RETURN_STRING(WLC_GET_CWMIN) + CASE_RETURN_STRING(WLC_SET_CWMIN) + CASE_RETURN_STRING(WLC_GET_CWMAX) + CASE_RETURN_STRING(WLC_SET_CWMAX) + CASE_RETURN_STRING(WLC_GET_WET) + CASE_RETURN_STRING(WLC_SET_WET) + CASE_RETURN_STRING(WLC_GET_KEY_PRIMARY) + CASE_RETURN_STRING(WLC_SET_KEY_PRIMARY) + CASE_RETURN_STRING(WLC_GET_ACI_ARGS) + CASE_RETURN_STRING(WLC_SET_ACI_ARGS) + CASE_RETURN_STRING(WLC_UNSET_CALLBACK) + CASE_RETURN_STRING(WLC_SET_CALLBACK) + CASE_RETURN_STRING(WLC_GET_RADAR) + CASE_RETURN_STRING(WLC_SET_RADAR) + CASE_RETURN_STRING(WLC_SET_SPECT_MANAGMENT) + CASE_RETURN_STRING(WLC_GET_SPECT_MANAGMENT) + CASE_RETURN_STRING(WLC_WDS_GET_REMOTE_HWADDR) + CASE_RETURN_STRING(WLC_WDS_GET_WPA_SUP) + CASE_RETURN_STRING(WLC_SET_CS_SCAN_TIMER) + CASE_RETURN_STRING(WLC_GET_CS_SCAN_TIMER) + CASE_RETURN_STRING(WLC_MEASURE_REQUEST) + CASE_RETURN_STRING(WLC_INIT) + CASE_RETURN_STRING(WLC_SEND_QUIET) + CASE_RETURN_STRING(WLC_KEEPALIVE) + CASE_RETURN_STRING(WLC_SEND_PWR_CONSTRAINT) + CASE_RETURN_STRING(WLC_UPGRADE_STATUS) + CASE_RETURN_STRING(WLC_GET_SCAN_PASSIVE_TIME) + CASE_RETURN_STRING(WLC_SET_SCAN_PASSIVE_TIME) + CASE_RETURN_STRING(WLC_LEGACY_LINK_BEHAVIOR) + CASE_RETURN_STRING(WLC_GET_CHANNELS_IN_COUNTRY) + CASE_RETURN_STRING(WLC_GET_COUNTRY_LIST) + CASE_RETURN_STRING(WLC_GET_VAR) + CASE_RETURN_STRING(WLC_SET_VAR) + CASE_RETURN_STRING(WLC_NVRAM_GET) + CASE_RETURN_STRING(WLC_NVRAM_SET) + CASE_RETURN_STRING(WLC_NVRAM_DUMP) + CASE_RETURN_STRING(WLC_REBOOT) + CASE_RETURN_STRING(WLC_SET_WSEC_PMK) + CASE_RETURN_STRING(WLC_GET_AUTH_MODE) + CASE_RETURN_STRING(WLC_SET_AUTH_MODE) + CASE_RETURN_STRING(WLC_GET_WAKEENTRY) + CASE_RETURN_STRING(WLC_SET_WAKEENTRY) + CASE_RETURN_STRING(WLC_NDCONFIG_ITEM) + CASE_RETURN_STRING(WLC_NVOTPW) + CASE_RETURN_STRING(WLC_OTPW) + CASE_RETURN_STRING(WLC_IOV_BLOCK_GET) + CASE_RETURN_STRING(WLC_IOV_MODULES_GET) + CASE_RETURN_STRING(WLC_SOFT_RESET) + CASE_RETURN_STRING(WLC_GET_ALLOW_MODE) + CASE_RETURN_STRING(WLC_SET_ALLOW_MODE) + CASE_RETURN_STRING(WLC_GET_DESIRED_BSSID) + CASE_RETURN_STRING(WLC_SET_DESIRED_BSSID) + CASE_RETURN_STRING(WLC_DISASSOC_MYAP) + CASE_RETURN_STRING(WLC_GET_NBANDS) + CASE_RETURN_STRING(WLC_GET_BANDSTATES) + CASE_RETURN_STRING(WLC_GET_WLC_BSS_INFO) + CASE_RETURN_STRING(WLC_GET_ASSOC_INFO) + CASE_RETURN_STRING(WLC_GET_OID_PHY) + CASE_RETURN_STRING(WLC_SET_OID_PHY) + CASE_RETURN_STRING(WLC_SET_ASSOC_TIME) + CASE_RETURN_STRING(WLC_GET_DESIRED_SSID) + CASE_RETURN_STRING(WLC_GET_CHANSPEC) + CASE_RETURN_STRING(WLC_GET_ASSOC_STATE) + CASE_RETURN_STRING(WLC_SET_PHY_STATE) + CASE_RETURN_STRING(WLC_GET_SCAN_PENDING) + CASE_RETURN_STRING(WLC_GET_SCANREQ_PENDING) + CASE_RETURN_STRING(WLC_GET_PREV_ROAM_REASON) + CASE_RETURN_STRING(WLC_SET_PREV_ROAM_REASON) + CASE_RETURN_STRING(WLC_GET_BANDSTATES_PI) + CASE_RETURN_STRING(WLC_GET_PHY_STATE) + CASE_RETURN_STRING(WLC_GET_BSS_WPA_RSN) + CASE_RETURN_STRING(WLC_GET_BSS_WPA2_RSN) + CASE_RETURN_STRING(WLC_GET_BSS_BCN_TS) + CASE_RETURN_STRING(WLC_GET_INT_DISASSOC) + CASE_RETURN_STRING(WLC_SET_NUM_PEERS) + CASE_RETURN_STRING(WLC_GET_NUM_BSS) + CASE_RETURN_STRING(WLC_GET_WSEC_PMK) + CASE_RETURN_STRING(WLC_GET_RANDOM_BYTES) + CASE_RETURN_STRING(WLC_LAST) + default: + return "Unknown Command"; + } +} + +#endif /* WPRINT_ENABLE_WHD_DEBUG */ + +void whd_convert_security_type_to_string(whd_security_t security, char *out_str, uint16_t out_str_len) +{ + if (security == WHD_SECURITY_OPEN) + { + strncat(out_str, " Open", out_str_len); + } + if (security & WEP_ENABLED) + { + strncat(out_str, " WEP", out_str_len); + } + if (security & WPA3_SECURITY) + { + strncat(out_str, " WPA3", out_str_len); + } + if (security & WPA2_SECURITY) + { + strncat(out_str, " WPA2", out_str_len); + } + if (security & WPA_SECURITY) + { + strncat(out_str, " WPA", out_str_len); + } + if (security & AES_ENABLED) + { + strncat(out_str, " AES", out_str_len); + } + if (security & TKIP_ENABLED) + { + strncat(out_str, " TKIP", out_str_len); + } + if (security & SHARED_ENABLED) + { + strncat(out_str, " SHARED", out_str_len); + } + if (security & ENTERPRISE_ENABLED) + { + strncat(out_str, " Enterprise", out_str_len); + } + if (security & WPS_ENABLED) + { + strncat(out_str, " WPS", out_str_len); + } + if (security & FBT_ENABLED) + { + strncat(out_str, " FBT", out_str_len); + } + if (security & IBSS_ENABLED) + { + strncat(out_str, " IBSS", out_str_len); + } + if (security == WHD_SECURITY_UNKNOWN) + { + strncat(out_str, " Unknown", out_str_len); + } + if (!(security & ENTERPRISE_ENABLED) && (security != WHD_SECURITY_OPEN) && + (security != WHD_SECURITY_UNKNOWN) ) + { + strncat(out_str, " PSK", out_str_len); + } +} + +/*! + ****************************************************************************** + * Prints partial details of a scan result on a single line + * + * @param[in] record A pointer to the whd_scan_result_t record + * + */ + +void whd_print_scan_result(whd_scan_result_t *record) +{ + const char *str = NULL; + char sec_type_string[40] = { 0 }; + + switch (record->bss_type) + { + case WHD_BSS_TYPE_ADHOC: + str = "Adhoc"; + break; + + case WHD_BSS_TYPE_INFRASTRUCTURE: + str = "Infra"; + break; + + case WHD_BSS_TYPE_ANY: + str = "Any"; + break; + + case WHD_BSS_TYPE_MESH: + case WHD_BSS_TYPE_UNKNOWN: + str = "Unknown"; + break; + + default: + str = "?"; + break; + } + + UNUSED_PARAMETER(str); + WPRINT_MACRO( ("%5s ", str) ); + WPRINT_MACRO( ("%02X:%02X:%02X:%02X:%02X:%02X ", record->BSSID.octet[0], record->BSSID.octet[1], + record->BSSID.octet[2], record->BSSID.octet[3], record->BSSID.octet[4], + record->BSSID.octet[5]) ); + + if (record->flags & WHD_SCAN_RESULT_FLAG_RSSI_OFF_CHANNEL) + { + WPRINT_MACRO( ("OFF ") ); + } + else + { + WPRINT_MACRO( ("%d ", record->signal_strength) ); + } + + if (record->max_data_rate < 100000) + { + WPRINT_MACRO( (" %.1f ", (double)(record->max_data_rate / 1000.0) ) ); + } + else + { + WPRINT_MACRO( ("%.1f ", (double)(record->max_data_rate / 1000.0) ) ); + } + WPRINT_MACRO( (" %3d ", record->channel) ); + + whd_convert_security_type_to_string(record->security, sec_type_string, (sizeof(sec_type_string) - 1) ); + + WPRINT_MACRO( ("%-20s ", sec_type_string) ); + WPRINT_MACRO( (" %-32s ", record->SSID.value) ); + + if (record->ccode[0] != '\0') + { + WPRINT_MACRO( ("%c%c ", record->ccode[0], record->ccode[1]) ); + } + else + { + WPRINT_MACRO( (" ") ); + } + + if (record->flags & WHD_SCAN_RESULT_FLAG_BEACON) + { + WPRINT_MACRO( (" %-15s", " BEACON") ); + } + else + { + WPRINT_MACRO( (" %-15s", " PROBE ") ); + } + WPRINT_MACRO( ("\n") ); +} + +void whd_hexdump(uint8_t *data, uint32_t data_len) +{ + uint32_t i; + uint8_t buff[17] = {0}; + + UNUSED_PARAMETER(buff); + for (i = 0; i < data_len; i++) + { + if ( (i % 16) == 0 ) + { + if (i != 0) + { + WPRINT_MACRO( (" %s\n", buff) ); + } + WPRINT_MACRO( ("%04" PRIx32 " ", i) ); + } + WPRINT_MACRO( (" %02x", data[i]) ); + + if ( (data[i] < 0x20) || (data[i] > 0x7e) ) + { + buff[i % 16] = '.'; + } + else + { + buff[i % 16] = data[i]; + } + buff[(i % 16) + 1] = '\0'; + } + while ( (i % 16) != 0 ) + { + WPRINT_MACRO( (" ") ); + i++; + } + WPRINT_MACRO( (" %s\n", buff) ); +} + +void whd_ioctl_info_to_string(uint32_t cmd, char *ioctl_str, uint16_t ioctl_str_len) +{ + if (cmd == 2) + { + strncpy(ioctl_str, "WLC_UP", ioctl_str_len); + } + else if (cmd == 20) + { + strncpy(ioctl_str, "WLC_SET_INFRA", ioctl_str_len); + } + else if (cmd == 22) + { + strncpy(ioctl_str, "WLC_SET_AUTH", ioctl_str_len); + } + else if (cmd == 26) + { + strncpy(ioctl_str, "WLC_SET_SSID", ioctl_str_len); + } + else if (cmd == 52) + { + strncpy(ioctl_str, "WLC_DISASSOC", ioctl_str_len); + } + else if (cmd == 55) + { + strncpy(ioctl_str, "WLC_SET_ROAM_TRIGGER", ioctl_str_len); + } + else if (cmd == 57) + { + strncpy(ioctl_str, "WLC_SET_ROAM_DELTA", ioctl_str_len); + } + else if (cmd == 59) + { + strncpy(ioctl_str, "WLC_SET_ROAM_SCAN_PERIOD", ioctl_str_len); + } + else if (cmd == 110) + { + strncpy(ioctl_str, "WLC_SET_GMODE", ioctl_str_len); + } + else if (cmd == 116) + { + strncpy(ioctl_str, "WLC_SET_SCANSUPPRESS", ioctl_str_len); + } + else if (cmd == 134) + { + strncpy(ioctl_str, "WLC_SET_WSEC", ioctl_str_len); + } + else if (cmd == 165) + { + strncpy(ioctl_str, "WLC_SET_WPA_AUTH", ioctl_str_len); + } + else if (cmd == 268) + { + strncpy(ioctl_str, "WLC_SET_WSEC_PMK", ioctl_str_len); + } + ioctl_str[ioctl_str_len] = '\0'; +} + +void whd_event_info_to_string(uint32_t cmd, uint16_t flag, uint32_t reason, char *ioctl_str, uint16_t ioctl_str_len) +{ + if (cmd == 0) + { + strncpy(ioctl_str, "WLC_E_SET_SSID", ioctl_str_len); + } + else if (cmd == 3) + { + strncpy(ioctl_str, "WLC_E_AUTH ", ioctl_str_len); + } + else if (cmd == 16) + { + strncpy(ioctl_str, "WLC_E_LINK ", ioctl_str_len); + } + else if (cmd == 46) + { + strncpy(ioctl_str, "WLC_E_PSK_SUP ", ioctl_str_len); + } + else if (cmd == 54) + { + strncpy(ioctl_str, "WLC_E_IF ", ioctl_str_len); + } + else if (cmd == 69) + { + strncpy(ioctl_str, "WLC_E_ESCAN_RESULT", ioctl_str_len); + } + + if (flag == 0) + { + strncat(ioctl_str, " WLC_E_STATUS_SUCCESS", ioctl_str_len); + } + if (flag == 8) + { + strncat(ioctl_str, " WLC_E_STATUS_PARTIAL", ioctl_str_len); + } + else if (flag == 262) + { + strncat(ioctl_str, " WLC_SUP_KEYED ", ioctl_str_len); + } + + if (reason == 0) + { + strncat(ioctl_str, " WLC_E_REASON_INITIAL_ASSOC", ioctl_str_len); + } + else if (reason == 512) + { + strncat(ioctl_str, " WLC_E_SUP_OTHER", ioctl_str_len); + } + ioctl_str[ioctl_str_len] = '\0'; +} + +bool whd_str_to_ip(const char *ip4addr, size_t len, void *dest) +{ + uint8_t *addr = dest; + + if (len > 16) // Too long, not possible + { + return false; + } + + uint8_t stringLength = 0, byteCount = 0; + + //Iterate over each component of the IP. The exit condition is in the middle of the loop + while (true) + { + + //No valid character (IPv4 addresses don't have implicit 0, that is x.y..z being read as x.y.0.z) + if ( (stringLength == len) || (ip4addr[stringLength] < '0') || (ip4addr[stringLength] > '9') ) + { + return false; + } + + //For each component, we convert it to the raw value + uint16_t byte = 0; + while (stringLength < len && ip4addr[stringLength] >= '0' && ip4addr[stringLength] <= '9') + { + byte *= 10; + byte += ip4addr[stringLength++] - '0'; + + //We go over the maximum value for an IPv4 component + if (byte > 0xff) + { + return false; + } + } + + //Append the component + addr[byteCount++] = (uint8_t)byte; + + //If we're at the end, we leave the loop. It's the only way to reach the `true` output + if (byteCount == 4) + { + break; + } + + //If the next character is invalid, we return false + if ( (stringLength == len) || (ip4addr[stringLength++] != '.') ) + { + return false; + } + } + + return stringLength == len || ip4addr[stringLength] == '\0'; +} + +static void whd_ipv4_itoa(char *string, uint8_t byte) +{ + char *baseString = string; + + //Write the digits to the buffer from the least significant to the most + // This is the incorrect order but we will swap later + do + { + *string++ = '0' + byte % 10; + byte /= 10; + } while (byte); + + //We put the final \0, then go back one step on the last digit for the swap + *string-- = '\0'; + + //We now swap the digits + while (baseString < string) + { + uint8_t tmp = *string; + *string-- = *baseString; + *baseString++ = tmp; + } +} + +uint8_t whd_ip4_to_string(const void *ip4addr, char *p) +{ + uint8_t outputPos = 0; + const uint8_t *byteArray = ip4addr; + + for (uint8_t component = 0; component < 4; ++component) + { + //Convert the byte to string + whd_ipv4_itoa(&p[outputPos], byteArray[component]); + + //Move outputPos to the end of the string + while (p[outputPos] != '\0') + { + outputPos += 1; + } + + //Append a dot if this is not the last digit + if (component < 3) + { + p[outputPos++] = '.'; + } + } + // Return length of generated string, excluding the terminating null character + return outputPos; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_wifi.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_wifi.c new file mode 100644 index 00000000..422449c1 --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_wifi.c @@ -0,0 +1,110 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * + * Implements functions called by WHD user APIs, but not directly exposed to user + * + * This file provides functions which are not directly exposed to user but, called by end-user functions which allow actions such as + * seting the MAC address, getting channel info, etc + */ + +#include "whd_ap.h" +#include "whd_chip_constants.h" +#include "whd_debug.h" +#include "whd_events_int.h" +#include "whd_cdc_bdc.h" +#include "whd_thread_internal.h" +#include "whd_utils.h" +#include "whd_wifi_api.h" +#include "whd_wlioctl.h" + +/****************************************************** +* @cond Constants +******************************************************/ +#define MAC_ADDRESS_LOCALLY_ADMINISTERED_BIT 0x02 + +/****************************************************** +* Local Structures +******************************************************/ + + + +/****************************************************** +* Variables +******************************************************/ +void (*whd_wifi_link_update_callback)(void) = NULL; + +/****************************************************** +* Function definitions +******************************************************/ + +uint32_t whd_wifi_set_mac_address(whd_interface_t ifp, whd_mac_t mac) +{ + whd_buffer_t buffer; + uint32_t *data; + whd_driver_t whd_driver = ifp->whd_driver; + + /* AP interface needs to come up with MAC different from STA */ +#ifdef APOLLO_AUDIO + + /* Work around the issue of asking API to set one address and it sets a different address. + * This will cause any comparison of set and get mac address to fail. TODO: move twiddling this + * bit to a higher level. + */ + if (0) +#else + if (ifp->role == WHD_AP_ROLE) +#endif + { + whd_mac_t ap_mac_address; + + memcpy(&ap_mac_address, &mac, sizeof(whd_mac_t) ); + if (ap_mac_address.octet[0] & MAC_ADDRESS_LOCALLY_ADMINISTERED_BIT) + { + ap_mac_address.octet[0] &= (uint8_t) ~(MAC_ADDRESS_LOCALLY_ADMINISTERED_BIT); + } + else + { + ap_mac_address.octet[0] |= MAC_ADDRESS_LOCALLY_ADMINISTERED_BIT; + } + + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(whd_mac_t), IOVAR_STR_CUR_ETHERADDR); + CHECK_IOCTL_BUFFER(data); + memcpy(data, &ap_mac_address, sizeof(whd_mac_t) ); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); + + if (memcmp(&mac, &ap_mac_address, sizeof(whd_mac_t) ) != 0) + { + WPRINT_WHD_INFO( (" STA MAC address : %02x:%02x:%02x:%02x:%02x:%02x \n" + " AP MAC address : %02x:%02x:%02x:%02x:%02x:%02x \n", + mac.octet[0], mac.octet[1], mac.octet[2], + mac.octet[3], mac.octet[4], mac.octet[3], + ap_mac_address.octet[0], ap_mac_address.octet[1], ap_mac_address.octet[2], + ap_mac_address.octet[3], ap_mac_address.octet[4], ap_mac_address.octet[3]) ); + } + } + else + { + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(whd_mac_t), IOVAR_STR_CUR_ETHERADDR); + CHECK_IOCTL_BUFFER(data); + memcpy(data, &mac, sizeof(whd_mac_t) ); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); + } + + return WHD_SUCCESS; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_wifi_api.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_wifi_api.c new file mode 100644 index 00000000..4b1d03aa --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_wifi_api.c @@ -0,0 +1,4819 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * Implements user functions for controlling the Wi-Fi system + * + * This file provides end-user functions which allow actions such as scanning for + * Wi-Fi networks, joining Wi-Fi networks, getting the MAC address, etc + * + */ + +#include +#include "whd_version.h" +#include "whd_chip_constants.h" +#include "whd_cdc_bdc.h" +#include "whd_thread_internal.h" +#include "whd_debug.h" +#include "whd_utils.h" +#include "whd_wifi_api.h" +#include "whd_buffer_api.h" +#include "whd_wlioctl.h" +#include "whd_types.h" +#include "whd_types_int.h" + +/****************************************************** +* Constants +******************************************************/ +#define WL_CHANSPEC_CHAN_MASK (0x00ff) +#define CHSPEC_CHANNEL(chspec) ( (uint8_t)( (chspec) & WL_CHANSPEC_CHAN_MASK ) ) +#define CH20MHZ_CHSPEC(channel) (chanspec_t)( (chanspec_t)(channel) | GET_C_VAR(whd_driver, CHANSPEC_BW_20) | \ + GET_C_VAR(whd_driver, CHANSPEC_CTL_SB_NONE) | \ + ( ( (channel) <= CH_MAX_2G_CHANNEL ) ? GET_C_VAR(whd_driver, \ + CHANSPEC_BAND_2G) \ + : GET_C_VAR(whd_driver, CHANSPEC_BAND_5G) ) ) + +#define MAX_SUPPORTED_MCAST_ENTRIES (10) +#define WLC_EVENT_MSG_LINK (0x01) + +#define JOIN_ASSOCIATED (uint32_t)(1 << 0) +#define JOIN_AUTHENTICATED (uint32_t)(1 << 1) +#define JOIN_LINK_READY (uint32_t)(1 << 2) +#define JOIN_SECURITY_COMPLETE (uint32_t)(1 << 3) +#define JOIN_SSID_SET (uint32_t)(1 << 4) +#define JOIN_NO_NETWORKS (uint32_t)(1 << 5) +#define JOIN_EAPOL_KEY_M1_TIMEOUT (uint32_t)(1 << 6) +#define JOIN_EAPOL_KEY_M3_TIMEOUT (uint32_t)(1 << 7) +#define JOIN_EAPOL_KEY_G1_TIMEOUT (uint32_t)(1 << 8) +#define JOIN_EAPOL_KEY_FAILURE (uint32_t)(1 << 9) + +#define JOIN_SECURITY_FLAGS_MASK (JOIN_SECURITY_COMPLETE | JOIN_EAPOL_KEY_M1_TIMEOUT | JOIN_EAPOL_KEY_M3_TIMEOUT | \ + JOIN_EAPOL_KEY_G1_TIMEOUT | JOIN_EAPOL_KEY_FAILURE) + +#define DEFAULT_JOIN_ATTEMPT_TIMEOUT (9000) /* Overall join attempt timeout in milliseconds.(FW will do "full scan"[~2.8 seconds] + "psk-to-pmk"[2.x seconds] + "join"[5 seconds timer in FW]) */ +#define DEFAULT_EAPOL_KEY_PACKET_TIMEOUT (2500) /* Timeout when waiting for EAPOL key packet M1 or M3 in milliseconds.*/ + /* Some APs may be slow to provide M1 and 1000 ms is not long enough for edge of cell. */ +#ifndef DEFAULT_PM2_SLEEP_RET_TIME +#define DEFAULT_PM2_SLEEP_RET_TIME (200) +#endif + +#define PM2_SLEEP_RET_TIME_MIN (10) /* Minimum return-to-sleep in milliseconds */ +#define PM2_SLEEP_RET_TIME_MAX (2000) /* Maximum return-to-sleep in milliseconds */ +#define NULL_FRAMES_WITH_PM_SET_LIMIT (100) /* NULL_FRAMES_WITH_PM_SET_LIMIT */ +#define RSPEC_KBPS_MASK (0x7f) +#define RSPEC_500KBPS(rate) ( (rate) & RSPEC_KBPS_MASK ) +#define RSPEC_TO_KBPS(rate) (RSPEC_500KBPS( (rate) ) * (uint32_t)500) +#define UNSIGNED_CHAR_TO_CHAR(uch) ( (uch) & 0x7f ) +#define ETHER_ISMULTI(ea) ( ( (const uint8_t *)(ea) )[0] & 1 ) + +#define KEY_MAX_LEN (64) /* Maximum key length */ +#define KEY_MIN_LEN (8) /* Minimum key length */ +#define BT_CTRL_REG_ADDR (0x18000c7c) +#define HOST_CTRL_REG_ADDR (0x18000d6c) +#define BT_BUF_REG_ADDR (0x18000c78) +/****************************************************** +* Local Structures +******************************************************/ + +#pragma pack(1) + +typedef struct +{ + uint32_t entry_count; + whd_mac_t macs[1]; +} mcast_list_t; + +typedef struct +{ + int32_t rssi; + whd_mac_t macs; +} client_rssi_t; + +typedef struct +{ + whd_sync_scan_result_t *aps; + uint32_t count; + uint32_t offset; + cy_semaphore_t scan_semaphore; +} whd_scan_userdata_t; + +#pragma pack() + +/****************************************************** +* Static Variables +******************************************************/ + +/* LOOK: !!!When adding events below, please modify whd_event_to_string!!! */ +const whd_event_num_t join_events[] = +{ + WLC_E_SET_SSID, WLC_E_LINK, WLC_E_AUTH, WLC_E_DEAUTH_IND, WLC_E_DISASSOC_IND, WLC_E_PSK_SUP, WLC_E_CSA_COMPLETE_IND, + WLC_E_NONE +}; +static const whd_event_num_t scan_events[] = { WLC_E_ESCAN_RESULT, WLC_E_NONE }; +static const whd_event_num_t auth_events[] = +{ WLC_E_EXT_AUTH_REQ, WLC_E_EXT_AUTH_FRAME_RX, WLC_E_NONE }; + +/* Values are in 100's of Kbit/sec (1 = 100Kbit/s). Arranged as: + * [Bit index] + * [0] = 20Mhz only + * [0] = Long GI + * [1] = Short GI + * [1] = 40MHz support + * [0] = Long GI + * [1] = Short GI + */ +static const uint16_t mcs_data_rate_lookup_table[32][2][2] = +{ + [0] = + { + { 65, 72}, + { 135, 150} + }, + [1] = + { + { 130, 144}, + { 270, 300} + }, + [2] = + { + { 195, 217}, + { 405, 450} + }, + [3] = + { + { 260, 289}, + { 540, 600} + }, + [4] = + { + { 390, 433}, + { 810, 900} + }, + [5] = + { + { 520, 578}, + { 1080, 1200} + }, + [6] = + { + { 585, 650}, + { 1215, 1350} + }, + [7] = + { + { 650, 722}, + { 1350, 1500} + }, + [8] = + { + { 130, 144}, + { 270, 300} + }, + [9] = + { + { 260, 289}, + { 540, 600} + }, + [10] = + { + { 390, 433}, + { 810, 900} + }, + [11] = + { + { 520, 578}, + { 1080, 1200} + }, + [12] = + { + { 780, 867}, + { 1620, 1800} + }, + [13] = + { + { 1040, 1156}, + { 2160, 2400} + }, + [14] = + { + { 1170, 1300}, + { 2430, 2700} + }, + [15] = + { + { 1300, 1444}, + { 2700, 3000} + }, + [16] = + { + { 195, 217}, + { 405, 450} + }, + [17] = + { + { 390, 433}, + { 810, 900} + }, + [18] = + { + { 585, 650}, + { 1215, 1350} + }, + [19] = + { + { 780, 867}, + { 1620, 1800} + }, + [20] = + { + { 1170, 1300}, + { 2430, 2700} + }, + [21] = + { + { 1560, 1733}, + { 3240, 3600} + }, + [22] = + { + { 1755, 1950}, + { 3645, 4050} + }, + [23] = + { + { 1950, 2167}, + { 4050, 4500} + }, + [24] = + { + { 260, 288}, + { 540, 600} + }, + [25] = + { + { 520, 576}, + { 1080, 1200} + }, + [26] = + { + { 780, 868}, + { 1620, 1800} + }, + [27] = + { + { 1040, 1156}, + { 2160, 2400} + }, + [28] = + { + { 1560, 1732}, + { 3240, 3600} + }, + [29] = + { + { 2080, 2312}, + { 4320, 4800} + }, + [30] = + { + { 2340, 2600}, + { 4860, 5400} + }, + [31] = + { + { 2600, 2888}, + { 5400, 6000} + }, +}; + + +/****************************************************** +* Static Function prototypes +******************************************************/ +static void *whd_wifi_join_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data); +static void *whd_wifi_scan_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, + void *handler_user_data); +static uint32_t whd_wifi_prepare_join(whd_interface_t ifp, + whd_security_t security, + const uint8_t *security_key, + uint8_t key_length, + cy_semaphore_t *semaphore); +static uint32_t whd_wifi_check_join_status(whd_interface_t ifp); +static void whd_wifi_active_join_deinit(whd_interface_t ifp, cy_semaphore_t *stack_semaphore, + whd_result_t result); +static uint32_t whd_wifi_active_join_init(whd_interface_t ifp, whd_security_t auth_type, + const uint8_t *security_key, uint8_t key_length, + cy_semaphore_t *semaphore); + +/** Sets the current EAPOL key timeout for the given interface + * + * @param interface : the interface for which we want to set the EAPOL key timeout + * eapol_key_timeout : EAPOL key timeout value + * + * @return WHD_SUCCESS : if success + * Error code : error code to indicate the type of error + */ +static uint32_t whd_wifi_set_supplicant_key_timeout(whd_interface_t ifp, int32_t eapol_key_timeout); + +/****************************************************** +* Function definitions +******************************************************/ +uint32_t whd_get_bt_info(whd_driver_t whd_driver, whd_bt_info_t bt_info); + +inline wl_chanspec_t whd_channel_to_wl_band(whd_driver_t whd_driver, uint32_t channel) +{ + return ( ( (channel) <= CH_MAX_2G_CHANNEL ) ? (uint16_t)GET_C_VAR(whd_driver, CHANSPEC_BAND_2G) : + (uint16_t)GET_C_VAR(whd_driver, CHANSPEC_BAND_5G) ); +} + +uint32_t whd_wifi_set_up(whd_interface_t ifp) +{ + whd_mac_t mac; + char version[200]; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + if (whd_driver->internal_info.whd_wlan_status.state == WLAN_UP) + { + WPRINT_WHD_INFO( ("whd_wifi_set_up: already up.\n") ); + return WHD_SUCCESS; + } + + /* Send UP command */ + CHECK_RETURN(whd_wifi_set_ioctl_buffer(ifp, WLC_UP, NULL, 0) ); + + if (whd_wifi_get_mac_address(ifp, &mac) == WHD_SUCCESS) + { + WPRINT_MACRO( ("WLAN MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\n", mac.octet[0], mac.octet[1], mac.octet[2], + mac.octet[3], mac.octet[4], mac.octet[5]) ); + } + + if (whd_wifi_get_wifi_version(ifp, version, sizeof(version) ) == WHD_SUCCESS) + { + WPRINT_MACRO( ("WLAN Firmware : %s", version) ); + } + + /* minimize bootloader usage and start time from UART output */ + if (whd_wifi_get_clm_version(ifp, version, sizeof(version) ) == WHD_SUCCESS) + { + WPRINT_MACRO( ("WLAN CLM : %s\n", version) ); + } + + WPRINT_MACRO( ("WHD VERSION : " WHD_VERSION) ); + WPRINT_MACRO( (" : " WHD_BRANCH) ); +#if defined(__ARMCC_VERSION) + WPRINT_MACRO( (" : ARM CLANG %u", __ARMCC_VERSION) ); +#elif defined(__ICCARM__) + WPRINT_MACRO( (" : IAR %u", __VER__) ); +#elif defined(__GNUC__) + WPRINT_MACRO( (" : GCC %u.%u", __GNUC__, __GNUC_MINOR__) ); +#else + WPRINT_MACRO( (" : UNKNOWN CC") ); +#endif + WPRINT_MACRO( (" : " WHD_DATE "\n") ); + + /* Update wlan status */ + whd_driver->internal_info.whd_wlan_status.state = WLAN_UP; + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_set_down(whd_interface_t ifp) +{ + whd_driver_t whd_driver = ifp->whd_driver; + + if (whd_driver->internal_info.whd_wlan_status.state != WLAN_UP) + { + WPRINT_WHD_INFO( ("whd_wifi_set_down: already down.\n") ); + return WHD_INTERFACE_NOT_UP; + } + + /* Send DOWN command */ + CHECK_RETURN(whd_wifi_set_ioctl_buffer(ifp, WLC_DOWN, NULL, 0) ); + + /* Update wlan status */ + whd_driver->internal_info.whd_wlan_status.state = WLAN_DOWN; + + return WHD_SUCCESS; +} + +uint32_t whd_get_bt_info(whd_driver_t whd_driver, whd_bt_info_t bt_info) +{ + whd_result_t result; + whd_interface_t ifp; + uint32_t addr = 0; + + ifp = whd_get_primary_interface(whd_driver); + + CHECK_IFP_NULL(ifp); + + memset(bt_info, 0, sizeof(struct whd_bt_info) ); + bt_info->bt_ctrl_reg_addr = BT_CTRL_REG_ADDR; + bt_info->host_ctrl_reg_addr = HOST_CTRL_REG_ADDR; + bt_info->bt_buf_reg_addr = BT_BUF_REG_ADDR; + result = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_BTADDR, (uint8_t *)&addr, sizeof(uint32_t) ); + if (result == WHD_SUCCESS) + { + bt_info->wlan_buf_addr = addr; + } + return WHD_SUCCESS; +} + +uint32_t whd_wifi_set_channel(whd_interface_t ifp, uint32_t channel) +{ + whd_buffer_t buffer; + uint32_t *data; + wl_chan_switch_t *chan_switch; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* Map P2P interface to either STA or AP interface depending if it's running as group owner or client */ + if (ifp->role == WHD_P2P_ROLE) + { + if (whd_driver->internal_info.whd_wifi_p2p_go_is_up == WHD_TRUE) + { + ifp->role = WHD_AP_ROLE; + } + else + { + ifp->role = WHD_STA_ROLE; + } + } + + switch (ifp->role) + { + case WHD_STA_ROLE: + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(uint32_t) ); + CHECK_IOCTL_BUFFER(data); + *data = htod32(channel); + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_SET_CHANNEL, buffer, NULL) ); + break; + + case WHD_AP_ROLE: + chan_switch = (wl_chan_switch_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(wl_chan_switch_t), + IOVAR_STR_CSA); + CHECK_IOCTL_BUFFER(chan_switch); + chan_switch->chspec = + ( wl_chanspec_t )(GET_C_VAR(whd_driver, + CHANSPEC_BW_20) | GET_C_VAR(whd_driver, CHANSPEC_CTL_SB_NONE) | channel); + chan_switch->chspec |= whd_channel_to_wl_band(whd_driver, channel); + chan_switch->chspec = htod16(chan_switch->chspec); + chan_switch->count = 1; + chan_switch->mode = 1; + chan_switch->reg = 0; + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) ); + break; + case WHD_P2P_ROLE: + case WHD_INVALID_ROLE: + default: + whd_assert("Bad interface", 0 != 0); + return WHD_UNKNOWN_INTERFACE; + } + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_get_channel(whd_interface_t ifp, uint32_t *channel) +{ + whd_buffer_t buffer; + whd_buffer_t response; + channel_info_t *channel_info; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + if (channel == NULL) + return WHD_BADARG; + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + CHECK_IOCTL_BUFFER(whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(channel_info_t) ) ); + + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_CHANNEL, buffer, &response) ); + + channel_info = (channel_info_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(channel_info, WHD_NO_REGISTER_FUNCTION_POINTER); + *channel = (uint32_t)channel_info->hw_channel; + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + return WHD_SUCCESS; +} + +uint32_t whd_wifi_enable_supplicant(whd_interface_t ifp, whd_security_t auth_type) +{ + whd_buffer_t buffer; + uint32_t *data; + uint32_t bss_index = 0; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* Map the interface to a BSS index */ + bss_index = ifp->bsscfgidx; + + /* Set supplicant variable - mfg app doesn't support these iovars, so don't care if return fails */ + data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA); + CHECK_IOCTL_BUFFER(data); + data[0] = bss_index; + data[1] = (uint32_t)( ( ( (auth_type & WPA_SECURITY) != 0 ) || + ( (auth_type & WPA2_SECURITY) != 0 ) || + (auth_type & WPA3_SECURITY) != 0 ) ? 1 : 0 ); + (void)whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_set_supplicant_key_timeout(whd_interface_t ifp, int32_t eapol_key_timeout) +{ + whd_buffer_t buffer; + int32_t *data; + uint32_t bss_index = 0; + whd_driver_t whd_driver = (whd_driver_t)ifp->whd_driver; + + /* Map the interface to a BSS index */ + bss_index = ifp->bsscfgidx; + + data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA_TMO); + CHECK_IOCTL_BUFFER(data); + data[0] = (int32_t)bss_index; + data[1] = eapol_key_timeout; + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_set_passphrase(whd_interface_t ifp, const uint8_t *security_key, uint8_t key_length) +{ + whd_buffer_t buffer; + whd_driver_t whd_driver; + wsec_pmk_t *psk; + + if (!ifp || !security_key || (key_length < KEY_MIN_LEN) || (key_length > KEY_MAX_LEN) ) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + whd_driver = ifp->whd_driver; + CHECK_DRIVER_NULL(whd_driver); + + psk = (wsec_pmk_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wsec_pmk_t) ); + CHECK_IOCTL_BUFFER(psk); + + memset(psk, 0, sizeof(wsec_pmk_t) ); + memcpy(psk->key, security_key, key_length); + psk->key_len = htod16(key_length); + psk->flags = htod16( (uint16_t)WSEC_PASSPHRASE ); + + /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */ + CHECK_RETURN(cy_rtos_delay_milliseconds(1) ); + + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WSEC_PMK, buffer, 0) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_sae_password(whd_interface_t ifp, const uint8_t *security_key, uint8_t key_length) +{ + whd_buffer_t buffer; + whd_driver_t whd_driver; + wsec_sae_password_t *sae_password; + + if (!ifp || !security_key || (key_length == 0) || (key_length > WSEC_MAX_SAE_PASSWORD_LEN) ) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + whd_driver = ifp->whd_driver; + CHECK_DRIVER_NULL(whd_driver); + + sae_password = (wsec_sae_password_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, + sizeof(wsec_sae_password_t), + IOVAR_STR_SAE_PASSWORD); + CHECK_IOCTL_BUFFER(sae_password); + memset(sae_password, 0, sizeof(wsec_sae_password_t) ); + memcpy(sae_password->password, security_key, key_length); + sae_password->password_len = htod16(key_length); + /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */ + cy_rtos_delay_milliseconds(1); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_enable_sup_set_passphrase(whd_interface_t ifp, const uint8_t *security_key_psk, uint8_t psk_length, + whd_security_t auth_type) +{ + whd_buffer_t buffer; + uint32_t *data; + uint32_t bss_index = 0; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + if ( (psk_length > (uint8_t)WSEC_MAX_PSK_LEN) || + (psk_length < (uint8_t)WSEC_MIN_PSK_LEN) ) + { + return WHD_INVALID_KEY; + } + + /* Map the interface to a BSS index */ + bss_index = ifp->bsscfgidx; + + /* Set supplicant variable - mfg app doesn't support these iovars, so don't care if return fails */ + data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA); + CHECK_IOCTL_BUFFER(data); + data[0] = bss_index; + data[1] = (uint32_t)( ( ( (auth_type & WPA_SECURITY) != 0 ) || + ( (auth_type & WPA2_SECURITY) != 0 ) || + (auth_type & WPA3_SECURITY) != 0 ) ? 1 : 0 ); + (void)whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + + CHECK_RETURN(whd_wifi_set_passphrase(ifp, security_key_psk, psk_length) ); + + return WHD_SUCCESS; +} + +whd_result_t whd_wifi_set_pmk(whd_interface_t ifp, const uint8_t *security_key, uint8_t key_length) +{ + whd_buffer_t buffer; + whd_driver_t whd_driver; + wsec_pmk_t *pmk; + uint32_t i; + + if (!ifp || !security_key || (key_length != WSEC_PMK_LEN) ) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + whd_driver = ifp->whd_driver; + CHECK_DRIVER_NULL(whd_driver); + + pmk = (wsec_pmk_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wsec_pmk_t) ); + CHECK_IOCTL_BUFFER(pmk); + + memset(pmk, 0, sizeof(wsec_pmk_t) ); + for (i = 0; i < key_length; i++) + { + snprintf( (char *)&pmk->key[2 * i], 3, "%02x", security_key[i] ); + } + pmk->key_len = htod16(key_length << 1); + pmk->flags = htod16( (uint16_t)WSEC_PASSPHRASE ); + + /* Delay required to allow radio firmware to be ready to receive PMK and avoid intermittent failure */ + CHECK_RETURN(cy_rtos_delay_milliseconds(1) ); + + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WSEC_PMK, buffer, 0) ); + + return WHD_SUCCESS; +} + +whd_result_t whd_wifi_set_pmksa(whd_interface_t ifp, const pmkid_t *pmkid) +{ + whd_buffer_t buffer; + whd_buffer_t response; + uint16_t cnt; + pmkid_list_t *orig_pmkid_list; + pmkid_list_t *new_pmkid_list; + whd_driver_t whd_driver; + + if (!ifp || !pmkid) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* Get the current pmkid_list list */ + CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer, + sizeof(uint32_t) + MAXPMKID * + sizeof(pmkid_t), IOVAR_STR_PMKID_INFO) ); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + + /* Verify address is not currently registered */ + orig_pmkid_list = (pmkid_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(orig_pmkid_list, WHD_NO_REGISTER_FUNCTION_POINTER); + orig_pmkid_list->npmkid = dtoh32(orig_pmkid_list->npmkid); + for (cnt = 0; cnt < orig_pmkid_list->npmkid; ++cnt) + { + /* Check if any address matches */ + if (!memcmp(pmkid->BSSID.octet, orig_pmkid_list->pmkid[cnt].BSSID.octet, sizeof(whd_mac_t) ) ) + { + break; + } + } + + if (cnt == MAXPMKID) + { + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + WPRINT_WHD_ERROR( ("Too manay PMKSA entrie cached %" PRIu32 "\n", orig_pmkid_list->npmkid) ); + return WHD_WLAN_NORESOURCE; + } + + /* Add Extra Space for New PMKID and write the new multicast list */ + if (cnt == orig_pmkid_list->npmkid) + { + new_pmkid_list = (pmkid_list_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, + ( uint16_t )(sizeof(uint32_t) + + (orig_pmkid_list->npmkid + 1) * + sizeof(pmkid_t) ), IOVAR_STR_PMKID_INFO); + CHECK_IOCTL_BUFFER(new_pmkid_list); + new_pmkid_list->npmkid = orig_pmkid_list->npmkid + 1; + memcpy(new_pmkid_list->pmkid, orig_pmkid_list->pmkid, orig_pmkid_list->npmkid * sizeof(pmkid_t) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + memcpy(&new_pmkid_list->pmkid[new_pmkid_list->npmkid - 1], pmkid, sizeof(pmkid_t) ); + new_pmkid_list->npmkid = htod32(new_pmkid_list->npmkid); + } + else + /* Replace Old PMKID for New PMKID under same BSSID and write the new multicast list */ + { + new_pmkid_list = (pmkid_list_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, + ( uint16_t )(sizeof(uint32_t) + + (orig_pmkid_list->npmkid) * + sizeof(pmkid_t) ), IOVAR_STR_PMKID_INFO); + CHECK_IOCTL_BUFFER(new_pmkid_list); + new_pmkid_list->npmkid = orig_pmkid_list->npmkid; + memcpy(new_pmkid_list->pmkid, orig_pmkid_list->pmkid, orig_pmkid_list->npmkid * sizeof(pmkid_t) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + memcpy(&new_pmkid_list->pmkid[cnt], pmkid, sizeof(pmkid_t) ); + new_pmkid_list->npmkid = htod32(new_pmkid_list->npmkid); + } + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); +} + +whd_result_t whd_wifi_set_roam_time_threshold(whd_interface_t ifp, uint32_t roam_time_threshold) +{ + if (!ifp || !roam_time_threshold) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + return whd_wifi_set_iovar_value(ifp, IOVAR_STR_ROAM_TIME_THRESH, roam_time_threshold); +} + +whd_result_t whd_wifi_get_roam_time_threshold(whd_interface_t ifp, uint32_t *roam_time_threshold) +{ + CHECK_IFP_NULL(ifp); + + return whd_wifi_get_iovar_value(ifp, IOVAR_STR_ROAM_TIME_THRESH, roam_time_threshold); +} + +uint32_t whd_wifi_get_rssi(whd_interface_t ifp, int32_t *rssi) +{ + CHECK_IFP_NULL(ifp); + + if (rssi == NULL) + return WHD_BADARG; + if (ifp->role == WHD_STA_ROLE) + { + return whd_wifi_get_ioctl_buffer(ifp, WLC_GET_RSSI, (uint8_t *)rssi, sizeof(*rssi) ); + } + return WHD_BADARG; +} + +uint32_t whd_wifi_get_ap_client_rssi(whd_interface_t ifp, int32_t *rssi, const whd_mac_t *client_mac) +{ + whd_buffer_t buffer; + whd_buffer_t response; + uint8_t *data = NULL; + client_rssi_t *client_rssi; + whd_driver_t whd_driver = ifp->whd_driver; + + /* WLAN expects buffer size to be 4-byte aligned */ + client_rssi = + (client_rssi_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, ROUND_UP(sizeof(client_rssi_t), + sizeof(uint32_t) ) ); + CHECK_IOCTL_BUFFER(client_rssi); + + memcpy(&client_rssi->macs, client_mac, sizeof(*client_mac) ); + client_rssi->rssi = 0; + + CHECK_RETURN_UNSUPPORTED_OK(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_RSSI, buffer, &response) ); + data = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy(rssi, data, sizeof(int32_t) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + return WHD_SUCCESS; +} + +/** Callback for join events + * This is called when the WLC_E_SET_SSID event is received, + * indicating that the system has joined successfully. + * Wakes the thread which was doing the join, allowing it to resume. + */ +static void *whd_wifi_join_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, + void *handler_user_data) +{ + cy_semaphore_t *semaphore = (cy_semaphore_t *)handler_user_data; + whd_bool_t join_attempt_complete = WHD_FALSE; + whd_driver_t whd_driver = ifp->whd_driver; + whd_result_t result; + + UNUSED_PARAMETER(event_data); + + if (event_header->bsscfgidx >= WHD_INTERFACE_MAX) + { + WPRINT_WHD_DEBUG( ("%s: event_header: Bad interface\n", __FUNCTION__) ); + return NULL; + } + + switch (event_header->event_type) + { + case WLC_E_PSK_SUP: + /* Ignore WLC_E_PSK_SUP event if link is not up */ + if ( (whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] & JOIN_LINK_READY) != 0 ) + { + if (event_header->status == WLC_SUP_KEYED) + { + /* Successful WPA key exchange */ + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] &= ~JOIN_SECURITY_FLAGS_MASK; + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_SECURITY_COMPLETE; + } + else + { + /* join has completed with an error */ + join_attempt_complete = WHD_TRUE; + if ( (event_header->status == WLC_SUP_KEYXCHANGE_WAIT_M1) && + (event_header->reason == WLC_E_SUP_WPA_PSK_TMO) ) + { + /* A timeout waiting for M1 may occur at the edge of the cell or if the AP is particularly slow. */ + WPRINT_WHD_DEBUG( ("Supplicant M1 timeout event\n") ); + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_EAPOL_KEY_M1_TIMEOUT; + } + else if ( (event_header->status == WLC_SUP_KEYXCHANGE_WAIT_M3) && + (event_header->reason == WLC_E_SUP_WPA_PSK_TMO) ) + { + /* A timeout waiting for M3 is an indicator that the passphrase may be incorrect. */ + WPRINT_WHD_DEBUG( ("Supplicant M3 timeout event\n") ); + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_EAPOL_KEY_M3_TIMEOUT; + } + else if ( (event_header->status == WLC_SUP_KEYXCHANGE_WAIT_G1) && + (event_header->reason == WLC_E_SUP_WPA_PSK_TMO) ) + { + /* A timeout waiting for G1 (group key) may occur at the edge of the cell. */ + WPRINT_WHD_DEBUG( ("Supplicant G1 timeout event\n") ); + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_EAPOL_KEY_G1_TIMEOUT; + } + else + { + WPRINT_WHD_DEBUG( ("Unsuccessful supplicant event; status=0x%" PRIu32 "\n", + event_header->status) ); + /* Unknown failure during EAPOL key handshake */ + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_EAPOL_KEY_FAILURE; + } + } + } + break; + + case WLC_E_SET_SSID: + if (event_header->status == WLC_E_STATUS_SUCCESS) + { + /* SSID has been successfully set. */ + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_SSID_SET; + } + /* We don't bail out on this event or things like WPS won't work if the AP is rebooting after configuration */ + else if (event_header->status == WLC_E_STATUS_NO_NETWORKS) + { + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_NO_NETWORKS; + } + else + { + join_attempt_complete = WHD_TRUE; + } + break; + + case WLC_E_LINK: + if ( (event_header->flags & WLC_EVENT_MSG_LINK) != 0 ) + { + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_LINK_READY; + } + else + { + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] &= ~JOIN_LINK_READY; + } + break; + + case WLC_E_DEAUTH_IND: + case WLC_E_DISASSOC_IND: + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] &= + ~(JOIN_AUTHENTICATED | JOIN_LINK_READY); + break; + + case WLC_E_AUTH: + if (event_header->status == WLC_E_STATUS_SUCCESS) + { + whd_driver->internal_info.whd_join_status[event_header->bsscfgidx] |= JOIN_AUTHENTICATED; + } + else if (event_header->status == WLC_E_STATUS_UNSOLICITED) + { + WPRINT_WHD_DEBUG( ("Ignore UNSOLICITED pkt event\n") ); + } + else + { + /* We cannot authenticate. Perhaps we're blocked or at the edge of a cell. */ + join_attempt_complete = WHD_TRUE; + } + break; + + case WLC_E_CSA_COMPLETE_IND: + if (event_header->datalen >= sizeof(wl_chan_switch_t) ) + { + wl_chan_switch_t *wl_csa = (wl_chan_switch_t *)event_data; + UNUSED_PARAMETER(wl_csa); + WPRINT_WHD_INFO( ("CSA event => chan %d\n", (dtoh16(wl_csa->chspec) & 0xff) ) ); + } + break; + + /* Note - These are listed to keep gcc pedantic checking happy */ + case WLC_E_RRM: + case WLC_E_NONE: + case WLC_E_ROAM: + case WLC_E_JOIN: + case WLC_E_START: + case WLC_E_AUTH_IND: + case WLC_E_DEAUTH: + case WLC_E_ASSOC: + case WLC_E_ASSOC_IND: + case WLC_E_REASSOC: + case WLC_E_REASSOC_IND: + case WLC_E_DISASSOC: + case WLC_E_QUIET_START: + case WLC_E_QUIET_END: + case WLC_E_BEACON_RX: + case WLC_E_MIC_ERROR: + case WLC_E_NDIS_LINK: + case WLC_E_TXFAIL: + case WLC_E_PMKID_CACHE: + case WLC_E_RETROGRADE_TSF: + case WLC_E_PRUNE: + case WLC_E_AUTOAUTH: + case WLC_E_EAPOL_MSG: + case WLC_E_SCAN_COMPLETE: + case WLC_E_ADDTS_IND: + case WLC_E_DELTS_IND: + case WLC_E_BCNSENT_IND: + case WLC_E_BCNRX_MSG: + case WLC_E_BCNLOST_MSG: + case WLC_E_ROAM_PREP: + case WLC_E_PFN_NET_FOUND: + case WLC_E_PFN_NET_LOST: + case WLC_E_RESET_COMPLETE: + case WLC_E_JOIN_START: + case WLC_E_ROAM_START: + case WLC_E_ASSOC_START: + case WLC_E_IBSS_ASSOC: + case WLC_E_RADIO: + case WLC_E_PSM_WATCHDOG: + case WLC_E_CCX_ASSOC_START: + case WLC_E_CCX_ASSOC_ABORT: + case WLC_E_PROBREQ_MSG: + case WLC_E_SCAN_CONFIRM_IND: + case WLC_E_COUNTRY_CODE_CHANGED: + case WLC_E_EXCEEDED_MEDIUM_TIME: + case WLC_E_ICV_ERROR: + case WLC_E_UNICAST_DECODE_ERROR: + case WLC_E_MULTICAST_DECODE_ERROR: + case WLC_E_TRACE: + case WLC_E_BTA_HCI_EVENT: + case WLC_E_IF: + case WLC_E_PFN_BEST_BATCHING: + case WLC_E_RSSI: + case WLC_E_EXTLOG_MSG: + case WLC_E_ACTION_FRAME: + case WLC_E_ACTION_FRAME_COMPLETE: + case WLC_E_PRE_ASSOC_IND: + case WLC_E_PRE_REASSOC_IND: + case WLC_E_CHANNEL_ADOPTED: + case WLC_E_AP_STARTED: + case WLC_E_DFS_AP_STOP: + case WLC_E_DFS_AP_RESUME: + case WLC_E_WAI_STA_EVENT: + case WLC_E_WAI_MSG: + case WLC_E_ESCAN_RESULT: + case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE: + case WLC_E_PROBRESP_MSG: + case WLC_E_P2P_PROBREQ_MSG: + case WLC_E_DCS_REQUEST: + case WLC_E_FIFO_CREDIT_MAP: + case WLC_E_ACTION_FRAME_RX: + case WLC_E_WAKE_EVENT: + case WLC_E_RM_COMPLETE: + case WLC_E_HTSFSYNC: + case WLC_E_OVERLAY_REQ: + case WLC_E_EXCESS_PM_WAKE_EVENT: + case WLC_E_PFN_SCAN_NONE: + case WLC_E_PFN_SCAN_ALLGONE: + case WLC_E_GTK_PLUMBED: + case WLC_E_ASSOC_IND_NDIS: + case WLC_E_REASSOC_IND_NDIS: + case WLC_E_ASSOC_REQ_IE: + case WLC_E_ASSOC_RESP_IE: + case WLC_E_ASSOC_RECREATED: + case WLC_E_ACTION_FRAME_RX_NDIS: + case WLC_E_AUTH_REQ: + case WLC_E_TDLS_PEER_EVENT: + case WLC_E_SPEEDY_RECREATE_FAIL: + case WLC_E_NATIVE: + case WLC_E_PKTDELAY_IND: + case WLC_E_AWDL_AW: + case WLC_E_AWDL_ROLE: + case WLC_E_AWDL_EVENT: + case WLC_E_NIC_AF_TXS: + case WLC_E_NAN: + case WLC_E_BEACON_FRAME_RX: + case WLC_E_SERVICE_FOUND: + case WLC_E_GAS_FRAGMENT_RX: + case WLC_E_GAS_COMPLETE: + case WLC_E_P2PO_ADD_DEVICE: + case WLC_E_P2PO_DEL_DEVICE: + case WLC_E_WNM_STA_SLEEP: + case WLC_E_TXFAIL_THRESH: + case WLC_E_PROXD: + case WLC_E_IBSS_COALESCE: + case WLC_E_AWDL_RX_PRB_RESP: + case WLC_E_AWDL_RX_ACT_FRAME: + case WLC_E_AWDL_WOWL_NULLPKT: + case WLC_E_AWDL_PHYCAL_STATUS: + case WLC_E_AWDL_OOB_AF_STATUS: + case WLC_E_AWDL_SCAN_STATUS: + case WLC_E_AWDL_AW_START: + case WLC_E_AWDL_AW_END: + case WLC_E_AWDL_AW_EXT: + case WLC_E_AWDL_PEER_CACHE_CONTROL: + case WLC_E_CSA_START_IND: + case WLC_E_CSA_DONE_IND: + case WLC_E_CSA_FAILURE_IND: + case WLC_E_CCA_CHAN_QUAL: + case WLC_E_BSSID: + case WLC_E_TX_STAT_ERROR: + case WLC_E_BCMC_CREDIT_SUPPORT: + case WLC_E_PSTA_PRIMARY_INTF_IND: + case WLC_E_P2P_DISC_LISTEN_COMPLETE: + case WLC_E_BT_WIFI_HANDOVER_REQ: + case WLC_E_SPW_TXINHIBIT: + case WLC_E_FBT_AUTH_REQ_IND: + case WLC_E_RSSI_LQM: + case WLC_E_PFN_GSCAN_FULL_RESULT: + case WLC_E_PFN_SWC: + case WLC_E_AUTHORIZED: + case WLC_E_PROBREQ_MSG_RX: + case WLC_E_PFN_SCAN_COMPLETE: + case WLC_E_RMC_EVENT: + case WLC_E_DPSTA_INTF_IND: + case WLC_E_ULP: + case WLC_E_LAST: + default: + whd_assert("Received event which was not registered\n", 0 != 0); + break; + } + + if (whd_wifi_is_ready_to_transceive(ifp) == WHD_SUCCESS) + { + join_attempt_complete = WHD_TRUE; + } + + if (join_attempt_complete == WHD_TRUE) + { + if (semaphore != NULL) + { + result = cy_rtos_get_semaphore(&whd_driver->internal_info.active_join_mutex, CY_RTOS_NEVER_TIMEOUT, + WHD_FALSE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Get semaphore failed in %s at %d \n", __func__, __LINE__) ); + } + if (whd_driver->internal_info.active_join_semaphore != NULL) + { + whd_assert("Unexpected semaphore\n", whd_driver->internal_info.active_join_semaphore == semaphore); + result = cy_rtos_set_semaphore(whd_driver->internal_info.active_join_semaphore, WHD_FALSE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Set semaphore failed in %s at %d \n", __func__, __LINE__) ); + } + } + result = cy_rtos_set_semaphore(&whd_driver->internal_info.active_join_mutex, WHD_FALSE); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Set semaphore failed in %s at %d \n", __func__, __LINE__) ); + } + } + return NULL; + } + else + { + return handler_user_data; + } +} + +/* Do any needed preparation prior to launching a join */ +static uint32_t whd_wifi_active_join_init(whd_interface_t ifp, whd_security_t auth_type, const uint8_t *security_key, + uint8_t key_length, cy_semaphore_t *semaphore) +{ + whd_driver_t whd_driver = ifp->whd_driver; + + if (whd_driver->internal_info.active_join_mutex_initted == WHD_FALSE) + { + CHECK_RETURN(cy_rtos_init_semaphore(&whd_driver->internal_info.active_join_mutex, 1, 0) ); + whd_driver->internal_info.active_join_mutex_initted = WHD_TRUE; + CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->internal_info.active_join_mutex, WHD_FALSE) ); + } + + CHECK_RETURN(cy_rtos_get_semaphore(&whd_driver->internal_info.active_join_mutex, CY_RTOS_NEVER_TIMEOUT, + WHD_FALSE) ); + whd_driver->internal_info.active_join_semaphore = semaphore; + CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->internal_info.active_join_mutex, WHD_FALSE) ); + + CHECK_RETURN(whd_wifi_prepare_join(ifp, auth_type, security_key, key_length, semaphore) ); + return WHD_SUCCESS; +} + +static uint32_t whd_wifi_prepare_join(whd_interface_t ifp, whd_security_t auth_type, + const uint8_t *security_key, uint8_t key_length, + cy_semaphore_t *semaphore) +{ + whd_buffer_t buffer; + uint32_t auth_mfp = WL_MFP_NONE; + whd_result_t retval = WHD_SUCCESS; + whd_result_t check_result = WHD_SUCCESS; + uint32_t *data; + uint32_t *wpa_auth; + uint32_t bss_index = 0; + uint32_t auth; + whd_driver_t whd_driver = ifp->whd_driver; + uint16_t event_entry = 0xFF; + + (void)bss_index; + if ( (auth_type == WHD_SECURITY_WPA2_FBT_ENT) || (auth_type == WHD_SECURITY_IBSS_OPEN) || + (auth_type == WHD_SECURITY_WPA2_FBT_PSK) ) + { + return WHD_UNKNOWN_SECURITY_TYPE; + } + else if ( (auth_type & WEP_ENABLED) != 0 ) + { + return WHD_WEP_NOT_ALLOWED; + } + if ( ( ( (key_length > (uint8_t)WSEC_MAX_PSK_LEN) || (key_length < (uint8_t)WSEC_MIN_PSK_LEN) ) && + ( (auth_type == WHD_SECURITY_WPA_TKIP_PSK) || (auth_type == WHD_SECURITY_WPA_AES_PSK) || + (auth_type == WHD_SECURITY_WPA2_AES_PSK) || (auth_type == WHD_SECURITY_WPA2_TKIP_PSK) || + (auth_type == WHD_SECURITY_WPA2_MIXED_PSK) ) ) || + ( (key_length > (uint8_t)WSEC_MAX_SAE_PASSWORD_LEN) && + ( (auth_type == WHD_SECURITY_WPA3_SAE) || (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) ) ) ) + { + return WHD_INVALID_KEY; + } + + (void)auth_type, (void)security_key, (void)key_length, (void)semaphore; + + /* Clear the current join status */ + whd_driver->internal_info.whd_join_status[ifp->bsscfgidx] = 0; + + /* Setting wsec will overwrite mfp setting in older branches, store value before setting wsec */ + CHECK_RETURN(whd_wifi_get_iovar_value(ifp, IOVAR_STR_MFP, &auth_mfp) ); + + /* Set Wireless Security Type */ + CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_WSEC, (uint32_t)(auth_type & 0xFF) ) ); + + /* Map the interface to a BSS index */ + bss_index = ifp->bsscfgidx; + + /* Set supplicant variable - mfg app doesn't support these iovars, so don't care if return fails */ + data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA); + CHECK_IOCTL_BUFFER(data); + data[0] = htod32(bss_index); + data[1] = + htod32( ( uint32_t )( ( ( (auth_type & WPA_SECURITY) != 0 ) || ( (auth_type & WPA2_SECURITY) != 0 ) || + (auth_type & WPA3_SECURITY) != 0 ) ? 1 : 0 ) ); + (void)whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + + /* Set the EAPOL version to whatever the AP is using (-1) */ + data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)8, "bsscfg:" IOVAR_STR_SUP_WPA2_EAPVER); + CHECK_IOCTL_BUFFER(data); + data[0] = htod32(bss_index); + data[1] = htod32( ( uint32_t )-1 ); + (void)whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + + /* Send WPA Key */ + switch (auth_type) + { + case WHD_SECURITY_OPEN: + case WHD_SECURITY_WPS_SECURE: + break; + + case WHD_SECURITY_WPA_TKIP_PSK: + case WHD_SECURITY_WPA_AES_PSK: + case WHD_SECURITY_WPA_MIXED_PSK: + case WHD_SECURITY_WPA2_AES_PSK: + case WHD_SECURITY_WPA2_TKIP_PSK: + case WHD_SECURITY_WPA2_MIXED_PSK: + case WHD_SECURITY_WPA2_WPA_AES_PSK: + case WHD_SECURITY_WPA2_WPA_MIXED_PSK: + /* Set the EAPOL key packet timeout value, otherwise unsuccessful supplicant events aren't reported. If the IOVAR is unsupported then continue. */ + CHECK_RETURN_UNSUPPORTED_CONTINUE(whd_wifi_set_supplicant_key_timeout(ifp, + DEFAULT_EAPOL_KEY_PACKET_TIMEOUT) ); + CHECK_RETURN(whd_wifi_set_passphrase(ifp, security_key, key_length) ); + break; + + case WHD_SECURITY_WPA3_SAE: + case WHD_SECURITY_WPA3_WPA2_PSK: + if (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) + { + CHECK_RETURN(whd_wifi_enable_sup_set_passphrase(ifp, security_key, key_length, auth_type) ); + } + /* Set the EAPOL key packet timeout value, otherwise unsuccessful supplicant events aren't reported. If the IOVAR is unsupported then continue. */ + CHECK_RETURN_UNSUPPORTED_CONTINUE(whd_wifi_set_supplicant_key_timeout(ifp, + DEFAULT_EAPOL_KEY_PACKET_TIMEOUT) ); + if (whd_driver->chip_info.fwcap_flags & (1 << WHD_FWCAP_SAE) ) + { + CHECK_RETURN(whd_wifi_sae_password(ifp, security_key, key_length) ); + } + break; + + case WHD_SECURITY_WPA_TKIP_ENT: + case WHD_SECURITY_WPA_AES_ENT: + case WHD_SECURITY_WPA_MIXED_ENT: + case WHD_SECURITY_WPA2_TKIP_ENT: + case WHD_SECURITY_WPA2_AES_ENT: + case WHD_SECURITY_WPA2_MIXED_ENT: + /* Disable eapol timer by setting to value 0 */ + CHECK_RETURN_UNSUPPORTED_CONTINUE(whd_wifi_set_supplicant_key_timeout(ifp, 0) ); + break; +#if 0 + case WHD_SECURITY_WPA2_FBT_ENT: + /* Disable eapol timer by setting to value 0 */ + CHECK_RETURN_UNSUPPORTED_CONTINUE(whd_wifi_set_supplicant_key_timeout(ifp, 0) ); + break; +#endif + case WHD_SECURITY_FORCE_32_BIT: + case WHD_SECURITY_UNKNOWN: + default: + whd_assert("whd_wifi_prepare_join: Unsupported security type\n", 0 != 0); + break; + } + /* Set infrastructure mode */ + CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_INFRA, ( (auth_type & IBSS_ENABLED) == 0 ) ? 1 : 0) ); + + if ( (auth_type == WHD_SECURITY_WPA3_SAE) || (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) ) + { + auth = WL_AUTH_SAE; + } + else + { + auth = WL_AUTH_OPEN_SYSTEM; + } + CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_AUTH, auth) ); + + /* From PMF cert test plan, + * 2.2 Out of Box Requirements + * When WPA2 security is enabled on the DUT, then by defaults the DUT shall: + * Enable Robust Management Frame Protection Capable (MFPC) functionality + */ + if (auth_type == WHD_SECURITY_WPA3_SAE) + { + auth_mfp = WL_MFP_REQUIRED; + } + else if ( (auth_type == WHD_SECURITY_WPA3_WPA2_PSK) || (auth_type & WPA2_SECURITY) ) + { + auth_mfp = WL_MFP_CAPABLE; + } + + check_result = whd_wifi_set_iovar_value(ifp, IOVAR_STR_MFP, auth_mfp); + if (check_result != WHD_SUCCESS) + { + WPRINT_WHD_DEBUG( ("Older chipsets might not support MFP..Ignore result\n") ); + } + + /* Set WPA authentication mode */ + wpa_auth = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4); + CHECK_IOCTL_BUFFER(wpa_auth); + + switch (auth_type) + { +#if 0 + case WHD_SECURITY_IBSS_OPEN: + /* IBSS does not get authenticated onto an AP */ + whd_driver->internal_info.whd_join_status[ifp->bsscfgidx] |= JOIN_AUTHENTICATED; +#endif + /* intentional fall-thru */ + /* Disables Eclipse static analysis warning */ + /* no break */ + /* Fall-Through */ + case WHD_SECURITY_OPEN: + case WHD_SECURITY_WPS_SECURE: + *wpa_auth = WPA_AUTH_DISABLED; + /* Open Networks do not have to complete security */ + whd_driver->internal_info.whd_join_status[ifp->bsscfgidx] |= JOIN_SECURITY_COMPLETE; + break; + + case WHD_SECURITY_WPA_TKIP_PSK: + case WHD_SECURITY_WPA_AES_PSK: + case WHD_SECURITY_WPA_MIXED_PSK: + *wpa_auth = (uint32_t)WPA_AUTH_PSK; + break; + + case WHD_SECURITY_WPA2_AES_PSK: + case WHD_SECURITY_WPA2_TKIP_PSK: + case WHD_SECURITY_WPA2_MIXED_PSK: + case WHD_SECURITY_WPA2_WPA_AES_PSK: + case WHD_SECURITY_WPA2_WPA_MIXED_PSK: + *wpa_auth = (uint32_t)WPA2_AUTH_PSK; + break; + + case WHD_SECURITY_WPA3_SAE: + case WHD_SECURITY_WPA3_WPA2_PSK: + *wpa_auth = (uint32_t)WPA3_AUTH_SAE_PSK; + break; + + case WHD_SECURITY_WPA_TKIP_ENT: + case WHD_SECURITY_WPA_AES_ENT: + case WHD_SECURITY_WPA_MIXED_ENT: + *wpa_auth = (uint32_t)WPA_AUTH_UNSPECIFIED; + break; + + case WHD_SECURITY_WPA2_TKIP_ENT: + case WHD_SECURITY_WPA2_AES_ENT: + case WHD_SECURITY_WPA2_MIXED_ENT: + *wpa_auth = (uint32_t)WPA2_AUTH_UNSPECIFIED; + break; +#if 0 + case WHD_SECURITY_WPA2_FBT_ENT: + *wpa_auth = ( uint32_t )(WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT); + break; +#endif + case WHD_SECURITY_UNKNOWN: + case WHD_SECURITY_FORCE_32_BIT: + default: + WPRINT_WHD_DEBUG( ("Unsupported Security type\n") ); + *wpa_auth = WPA_AUTH_DISABLED; + break; + } + *wpa_auth = htod32(*wpa_auth); + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_WPA_AUTH, buffer, 0) ); + + if (ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED) + { + whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY]); + ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED; + } + + CHECK_RETURN(whd_management_set_event_handler(ifp, join_events, whd_wifi_join_events_handler, (void *)semaphore, + &event_entry) ); + if (event_entry >= WHD_EVENT_ENTRY_MAX) + { + WPRINT_WHD_ERROR( ("Join events registration failed in function %s and line %d", __func__, __LINE__) ); + return WHD_UNFINISHED; + } + ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] = event_entry; + whd_assert("Set join Event handler failed\n", retval == WHD_SUCCESS); + + return WHD_SUCCESS; +} + +/* do any needed tear down after join + * @param stack_semaphore - semaphore used to control execution if client_semaphore is NULL + * @param client_semaphore - semaphore used to control execution if client passes this in + */ +static void whd_wifi_active_join_deinit(whd_interface_t ifp, cy_semaphore_t *stack_semaphore, whd_result_t result) +{ + whd_driver_t whd_driver = ifp->whd_driver; + whd_result_t val; + /* deinit join specific variables, with protection from mutex */ + + val = cy_rtos_get_semaphore(&whd_driver->internal_info.active_join_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE); + if (val != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("Get semaphore failed in %s at %d \n", __func__, __LINE__) ); + + whd_driver->internal_info.active_join_semaphore = NULL; + + cy_rtos_deinit_semaphore(stack_semaphore); + + if (WHD_SUCCESS != result) + { + WPRINT_WHD_INFO( ("Failed join (err %" PRIu32 ")\n", result) ); + ifp->role = WHD_INVALID_ROLE; + } + + val = cy_rtos_set_semaphore(&whd_driver->internal_info.active_join_mutex, WHD_FALSE); + if (val != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("Get semaphore failed in %s at %d \n", __func__, __LINE__) ); + + /* we forced the chip to be up during join, now let it sleep */ + WHD_WLAN_LET_SLEEP(whd_driver); +} + +static uint32_t whd_wifi_join_wait_for_complete(whd_interface_t ifp, cy_semaphore_t *semaphore) +{ + whd_result_t result; + uint32_t start_time; + uint32_t current_time; + whd_bool_t done = WHD_FALSE; + + cy_rtos_get_time(&start_time); + + while (!done) + { + result = cy_rtos_get_semaphore(semaphore, DEFAULT_JOIN_ATTEMPT_TIMEOUT / 10, WHD_FALSE); + whd_assert("Get semaphore failed", (result == CY_RSLT_SUCCESS) || (result == CY_RTOS_TIMEOUT) ); + REFERENCE_DEBUG_ONLY_VARIABLE(result); + + result = whd_wifi_is_ready_to_transceive(ifp); + if (result == WHD_SUCCESS) + { + break; + } + + cy_rtos_get_time(¤t_time); + done = (whd_bool_t)( (current_time - start_time) >= DEFAULT_JOIN_ATTEMPT_TIMEOUT ); + } + + if (result != WHD_SUCCESS) + { + CHECK_RETURN(whd_wifi_leave(ifp) ); + WPRINT_WHD_INFO( ("%s: not ready to transceive (err %" PRIu32 "); left network\n", __func__, result) ); + } + + return result; +} + +static uint32_t whd_wifi_check_join_status(whd_interface_t ifp) +{ + whd_driver_t whd_driver = ifp->whd_driver; + + if ( (uint32_t)ifp->bsscfgidx >= WHD_INTERFACE_MAX ) + { + WPRINT_WHD_ERROR( ("%s: Bad interface %d\n", __FUNCTION__, ifp->bsscfgidx) ); + return WHD_INVALID_JOIN_STATUS; + } + switch (whd_driver->internal_info.whd_join_status[ifp->bsscfgidx]) + { + case JOIN_NO_NETWORKS: + return WHD_NETWORK_NOT_FOUND; + + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_EAPOL_KEY_M1_TIMEOUT: + return WHD_EAPOL_KEY_PACKET_M1_TIMEOUT; + + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_EAPOL_KEY_M3_TIMEOUT: + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET | JOIN_EAPOL_KEY_M3_TIMEOUT: + return WHD_EAPOL_KEY_PACKET_M3_TIMEOUT; + + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_EAPOL_KEY_G1_TIMEOUT: + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET | JOIN_EAPOL_KEY_G1_TIMEOUT: + return WHD_EAPOL_KEY_PACKET_G1_TIMEOUT; + + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_EAPOL_KEY_FAILURE: + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET | JOIN_EAPOL_KEY_FAILURE: + return WHD_EAPOL_KEY_FAILURE; + + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET | JOIN_SECURITY_COMPLETE: + return WHD_SUCCESS; + + case 0: + case JOIN_SECURITY_COMPLETE: /* For open/WEP */ + return WHD_NOT_AUTHENTICATED; + + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SECURITY_COMPLETE: + return WHD_JOIN_IN_PROGRESS; + + case JOIN_AUTHENTICATED | JOIN_LINK_READY: + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SSID_SET: + return WHD_NOT_KEYED; + + default: + return WHD_INVALID_JOIN_STATUS; + } +} + +uint32_t whd_wifi_join_specific(whd_interface_t ifp, const whd_scan_result_t *ap, const uint8_t *security_key, + uint8_t key_length) +{ + whd_buffer_t buffer; + cy_semaphore_t join_semaphore; + whd_result_t result; + wl_extjoin_params_t *ext_join_params; + wl_join_params_t *join_params; + whd_security_t security = ap->security; + uint16_t wl_band_for_channel = 0; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* Keep WLAN awake while joining */ + WHD_WLAN_KEEP_AWAKE(whd_driver); + ifp->role = WHD_STA_ROLE; + + if (ap->bss_type == WHD_BSS_TYPE_MESH) + { + return WHD_UNSUPPORTED; + } + + if (ap->bss_type == WHD_BSS_TYPE_ADHOC) + { + security |= IBSS_ENABLED; + } + + if (NULL_MAC(ap->BSSID.octet) ) + { + WPRINT_WHD_ERROR( ("NULL address is not allowed/valid\n") ); + return WHD_BADARG; + } + + if (BROADCAST_ID(ap->BSSID.octet) ) + { + WPRINT_WHD_ERROR( ("Broadcast address is not allowed/valid in join with specific BSSID of AP\n") ); + return WHD_BADARG; + } + + if ( (ap->SSID.length == 0) || (ap->SSID.length > (size_t)SSID_NAME_SIZE) ) + { + WPRINT_WHD_ERROR( ("%s: failure: SSID length error\n", __func__) ); + return WHD_WLAN_BADSSIDLEN; + } + + CHECK_RETURN(cy_rtos_init_semaphore(&join_semaphore, 1, 0) ); + result = whd_wifi_active_join_init(ifp, security, security_key, key_length, &join_semaphore); + + if (result == WHD_SUCCESS) + { + /* Check if soft AP is running, if so, move its current channel to the the destination AP */ + if ( (ifp->role == WHD_AP_ROLE) && (whd_wifi_is_ready_to_transceive(ifp) == WHD_SUCCESS) ) + { + uint32_t current_softap_channel = 0; + CHECK_RETURN(whd_wifi_get_channel(ifp, ¤t_softap_channel) ); + if (current_softap_channel != ap->channel) + { + CHECK_RETURN(whd_wifi_set_channel(ifp, ap->channel) ); + WPRINT_WHD_DEBUG( ("WARN: moving soft-AP channel from %" PRIu32 " to %d due to STA join\n", + current_softap_channel, ap->channel) ); + cy_rtos_delay_milliseconds(100); + } + } + + else + { + if (ap->bss_type == WHD_BSS_TYPE_ADHOC) + { + CHECK_RETURN(whd_wifi_set_channel(ifp, ap->channel) ); + } + } + + /* Join network */ + ext_join_params = + (wl_extjoin_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(wl_extjoin_params_t), "join"); + CHECK_IOCTL_BUFFER(ext_join_params); + memset(ext_join_params, 0, sizeof(wl_extjoin_params_t) ); + + ext_join_params->ssid.SSID_len = ap->SSID.length; + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + memcpy(ext_join_params->ssid.SSID, ap->SSID.value, ext_join_params->ssid.SSID_len); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + memcpy(&ext_join_params->assoc_params.bssid, &ap->BSSID, sizeof(whd_mac_t) ); + ext_join_params->scan_params.scan_type = 0; + ext_join_params->scan_params.active_time = -1; + ext_join_params->scan_params.home_time = -1; + ext_join_params->scan_params.nprobes = -1; + ext_join_params->scan_params.passive_time = -1; + ext_join_params->assoc_params.bssid_cnt = 0; + if (ap->channel) + { + ext_join_params->assoc_params.chanspec_num = (uint32_t)1; + ext_join_params->assoc_params.chanspec_list[0] = + (wl_chanspec_t)htod16( (ap->channel | + GET_C_VAR(whd_driver, CHANSPEC_BW_20) | GET_C_VAR(whd_driver, + CHANSPEC_CTL_SB_NONE) ) ); + + /* set band properly */ + wl_band_for_channel = whd_channel_to_wl_band(whd_driver, ap->channel); + + ext_join_params->assoc_params.chanspec_list[0] |= wl_band_for_channel; + } + result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0); + + WPRINT_WHD_INFO( ("%s: set_ssid result (err %" PRIu32 "); left network\n", __func__, result) ); + + /* Some firmware, e.g. for 4390, does not support the join IOVAR, so use the older IOCTL call instead */ + if (result == WHD_WLAN_UNSUPPORTED) + { + join_params = + (wl_join_params_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wl_join_params_t) ); + CHECK_IOCTL_BUFFER(join_params); + memset(join_params, 0, sizeof(wl_join_params_t) ); + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + memcpy(&join_params->ssid, &ext_join_params->ssid, sizeof(wlc_ssid_t) ); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + memcpy(&join_params->params.bssid, &ap->BSSID, sizeof(whd_mac_t) ); + join_params->params.bssid_cnt = 0; + if (ap->channel) + { + join_params->params.chanspec_num = (uint32_t)1; + join_params->params.chanspec_list[0] = + (wl_chanspec_t)htod16( (ap->channel | + GET_C_VAR(whd_driver, + CHANSPEC_BW_20) | GET_C_VAR(whd_driver, CHANSPEC_CTL_SB_NONE) ) ); + + /* set band properly */ + join_params->params.chanspec_list[0] |= wl_band_for_channel; + } + result = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_SSID, buffer, 0); + } + + if (result == WHD_SUCCESS) + { + + uint16_t chip_id = whd_chip_get_chip_id(whd_driver); + + CHECK_RETURN(whd_wifi_join_wait_for_complete(ifp, &join_semaphore) ); + + if (chip_id == 0x4373) + { + /* For 11 AC MAX throughput set the frame burst and MPDU per AMPDU */ + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_MPDU_PER_AMPDU, 16) ); + } + + } + else + { + WPRINT_WHD_INFO( ("%s:3 not ready to transceive (err %" PRIu32 "); left network\n", __func__, result) ); + } + } + else + { + WPRINT_WHD_INFO( ("%s: active join init failed: (%" PRIu32 ")\n", __FUNCTION__, result) ); + } + /* clean up from the join attempt */ + whd_wifi_active_join_deinit(ifp, &join_semaphore, result); + + CHECK_RETURN(result); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_join(whd_interface_t ifp, const whd_ssid_t *ssid, whd_security_t auth_type, + const uint8_t *security_key, uint8_t key_length) +{ + cy_semaphore_t join_sema; + whd_result_t result; + whd_buffer_t buffer; + wlc_ssid_t *ssid_params; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + if (ssid == NULL) + { + WPRINT_WHD_ERROR( ("%s: failure: ssid is null\n", __func__) ); + return WHD_BADARG; + } + + if ( (ssid->length == 0) || (ssid->length > (size_t)SSID_NAME_SIZE) ) + { + WPRINT_WHD_ERROR( ("%s: failure: SSID length error\n", __func__) ); + return WHD_WLAN_BADSSIDLEN; + } + + /* Keep WLAN awake while joining */ + WHD_WLAN_KEEP_AWAKE(whd_driver); + ifp->role = WHD_STA_ROLE; + + CHECK_RETURN(cy_rtos_init_semaphore(&join_sema, 1, 0) ); + result = whd_wifi_active_join_init(ifp, auth_type, security_key, key_length, &join_sema); + + if (result == WHD_SUCCESS) + { + /* Join network */ + ssid_params = (struct wlc_ssid *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(wlc_ssid_t) ); + CHECK_IOCTL_BUFFER(ssid_params); + memset(ssid_params, 0, sizeof(wlc_ssid_t) ); + ssid_params->SSID_len = htod32(ssid->length); + memcpy(ssid_params->SSID, ssid->value, ssid_params->SSID_len); + result = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_SSID, buffer, 0); + + if (result == WHD_SUCCESS) + { + CHECK_RETURN(whd_wifi_join_wait_for_complete(ifp, &join_sema) ); + } + } + + /* clean up from the join attempt */ + whd_wifi_active_join_deinit(ifp, &join_sema, result); + + return result; +} + +uint32_t whd_wifi_leave(whd_interface_t ifp) +{ + whd_result_t result = WHD_SUCCESS; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* If interface is greater than max return error */ + if (ifp->bsscfgidx >= WHD_INTERFACE_MAX) + { + WPRINT_WHD_ERROR( ("%s: Bad interface 2\n", __FUNCTION__) ); + return WHD_BADARG; + } + if (ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED) + { + CHECK_RETURN(whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY]) ); + ifp->event_reg_list[WHD_JOIN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED; + } + + /* Disassociate from AP */ + result = whd_wifi_set_ioctl_buffer(ifp, WLC_DISASSOC, NULL, 0); + + if (result != WHD_SUCCESS) + { + WPRINT_WHD_DEBUG( ("whd_sdpcm_send_ioctl(WLC_DISASSOC) failed:%" PRIu32 "\r\n", result) ); + } + + whd_driver->internal_info.whd_join_status[ifp->bsscfgidx] = 0; + ifp->role = WHD_INVALID_ROLE; + + if (whd_driver->internal_info.active_join_mutex_initted == WHD_TRUE) + { + cy_rtos_deinit_semaphore(&whd_driver->internal_info.active_join_mutex); + whd_driver->internal_info.active_join_mutex_initted = WHD_FALSE; + } + if (whd_driver->internal_info.active_join_semaphore) + { + cy_rtos_deinit_semaphore(whd_driver->internal_info.active_join_semaphore); + whd_driver->internal_info.active_join_semaphore = NULL; + } + + + return WHD_SUCCESS; +} + +/** Handles scan result events + * + * This function receives scan record events, and parses them into a better format, then passes the results + * to the user application. + * + * @param event_header : The event details + * @param event_data : The data for the event which contains the scan result structure + * @param handler_user_data: data which will be passed to user application + * + * @returns : handler_user_data parameter + * + */ +static void *whd_wifi_scan_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, + void *handler_user_data) +{ + whd_scan_result_t *record; + wl_escan_result_t *eresult; + wl_bss_info_t *bss_info; + uint16_t chanspec; + uint32_t version; + whd_tlv8_header_t *cp; + uint32_t len; + uint16_t ie_offset; + uint32_t bss_info_length; + country_info_ie_fixed_portion_t *country_info_ie; + rsn_ie_fixed_portion_t *rsnie; + wpa_ie_fixed_portion_t *wpaie = NULL; + rsnx_ie_t *rsnxie = NULL; + uint8_t rate_num; + ht_capabilities_ie_t *ht_capabilities_ie = NULL; + uint32_t count_tmp = 0; + uint16_t temp16; + uint16_t bss_count; + whd_driver_t whd_driver = ifp->whd_driver; + + if (whd_driver->internal_info.scan_result_callback == NULL) + { + return handler_user_data; + } + + if (event_header->status == WLC_E_STATUS_SUCCESS) + { + whd_driver->internal_info.scan_result_callback(NULL, handler_user_data, WHD_SCAN_COMPLETED_SUCCESSFULLY); + whd_driver->internal_info.scan_result_callback = NULL; + whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY]); + ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED; + return handler_user_data; + } + if ( (event_header->status == WLC_E_STATUS_NEWSCAN) || (event_header->status == WLC_E_STATUS_NEWASSOC) || + (event_header->status == WLC_E_STATUS_ABORT) ) + { + whd_driver->internal_info.scan_result_callback(NULL, handler_user_data, WHD_SCAN_ABORTED); + whd_driver->internal_info.scan_result_callback = NULL; + whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY]); + ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED; + return handler_user_data; + } + + if (event_header->status != WLC_E_STATUS_PARTIAL) + { + return handler_user_data; + } + + eresult = (wl_escan_result_t *)event_data; + bss_info = &eresult->bss_info[0]; + bss_count = dtoh16(eresult->bss_count); + + version = dtoh32(WHD_READ_32(&bss_info->version) ); + whd_minor_assert("wl_bss_info_t has wrong version", version == WL_BSS_INFO_VERSION); + + /* PNO bss info doesn't contain the correct bss info version */ + if (version != WL_BSS_INFO_VERSION) + { + whd_minor_assert("Invalid bss_info version returned by firmware\n", version != WL_BSS_INFO_VERSION); + + return handler_user_data; + } + + whd_minor_assert("More than one result returned by firmware", bss_count == 1); + if (bss_count != 1) + { + return handler_user_data; + } + + /* + * check the SSID length and bssinfo ie offset for buffer overflow + */ + bss_info->ie_offset = dtoh16(bss_info->ie_offset); + bss_info->ie_length = dtoh32(bss_info->ie_length); + if ( (bss_info->SSID_len > sizeof(bss_info->SSID) ) || (bss_info->ie_offset < sizeof(wl_bss_info_t) ) || + (bss_info->ie_offset > (sizeof(wl_bss_info_t) + bss_info->ie_length) ) ) + { + WPRINT_WHD_ERROR( ("Invalid bss length check %s: SSID_len:%d,ie_len:%" PRIu32 ",ie_off:%d\n", __FUNCTION__, + bss_info->SSID_len, bss_info->ie_length, bss_info->ie_offset) ); + whd_minor_assert(" bss length check failed\n", bss_info->SSID_len != sizeof(bss_info->SSID) ); + return handler_user_data; + } + + /* Safe to access *whd_scan_result_ptr, as whd_scan_result_ptr == NULL case is handled above */ + record = (whd_scan_result_t *)(whd_driver->internal_info.whd_scan_result_ptr); + + /* Clear the last scan result data */ + memset(record, 0, sizeof(whd_scan_result_t) ); + + /* + * Totally ignore off channel results. This can only happen with DSSS (1 and 2 Mb). It is better to + * totally ignore it when it happens. It is hard to argue it is "significant" given that it can't + * happen in 5G with OFDM (or other 2G modulations). This is left here so that it could be + * passed as a scan result for debugging only. + */ + if (!(bss_info->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ) + { + record->flags |= WHD_SCAN_RESULT_FLAG_RSSI_OFF_CHANNEL; + /* Comment out this return statement to pass along an off channel result for debugging */ + return handler_user_data; + } + + /* Copy the SSID into the output record structure */ + record->SSID.length = (uint8_t)MIN_OF(sizeof(record->SSID.value), bss_info->SSID_len); + memset(record->SSID.value, 0, sizeof(record->SSID.value) ); + memcpy(record->SSID.value, bss_info->SSID, record->SSID.length); + + /* Copy the BSSID into the output record structure */ + memcpy( (void *)record->BSSID.octet, (const void *)bss_info->BSSID.octet, sizeof(bss_info->BSSID.octet) ); + + /* Copy the RSSI into the output record structure */ + record->signal_strength = ( int16_t )dtoh16( (WHD_READ_16(&bss_info->RSSI) ) ); + + /* Find maximum data rate and put it in the output record structure */ + record->max_data_rate = 0; + count_tmp = WHD_READ_32(&bss_info->rateset.count); + if (count_tmp > 16) + { + count_tmp = 16; + } + +#ifdef WPRINT_ENABLE_WHD_DEBUG + /* print out scan results info */ + { + char ea_buf[WHD_ETHER_ADDR_STR_LEN]; + char ssid_buf[SSID_NAME_SIZE + 1]; + + WPRINT_WHD_DEBUG( ("Scan result: channel=%d signal=%d ssid=%s bssid=%s\n", record->channel, + record->signal_strength, + whd_ssid_to_string(record->SSID.value, record->SSID.length, ssid_buf, + (uint8_t)sizeof(ssid_buf) ), + whd_ether_ntoa( (const uint8_t *)bss_info->BSSID.octet, ea_buf, sizeof(ea_buf) ) ) ); + } +#endif /* WPRINT_ENABLE_WHD_DEBUG */ + + for (rate_num = 0; rate_num < count_tmp; rate_num++) + { + uint32_t rate = RSPEC_TO_KBPS(bss_info->rateset.rates[rate_num]); + if (record->max_data_rate < rate) + { + record->max_data_rate = rate; + } + } + + bss_info->capability = dtoh16(bss_info->capability); + + /* Write the BSS type into the output record structure */ + record->bss_type = + ( (bss_info->capability & DOT11_CAP_ESS) != + 0 ) ? WHD_BSS_TYPE_INFRASTRUCTURE : ( (bss_info->capability & DOT11_CAP_IBSS) != + 0 ) ? WHD_BSS_TYPE_ADHOC : WHD_BSS_TYPE_UNKNOWN; + + /* Determine the network security. + * Some of this section has been copied from the standard broadcom host driver file wl/exe/wlu.c function wl_dump_wpa_rsn_ies + */ + + ie_offset = WHD_READ_16(&bss_info->ie_offset); + cp = (whd_tlv8_header_t *)( ( (uint8_t *)bss_info ) + ie_offset ); + len = WHD_READ_32(&bss_info->ie_length); + bss_info_length = WHD_READ_32(&bss_info->length); + + record->ie_ptr = (uint8_t *)cp; + record->ie_len = len; + + /* Validate the length of the IE section */ + if ( (ie_offset > bss_info_length) || (len > bss_info_length - ie_offset) ) + { + whd_minor_assert("Invalid ie length", 1 == 0); + return handler_user_data; + } + + /* Find an RSN IE (Robust-Security-Network Information-Element) */ + rsnie = (rsn_ie_fixed_portion_t *)whd_parse_dot11_tlvs(cp, len, DOT11_IE_ID_RSN); + + /* Find a WPA IE */ + if (rsnie == NULL) + { + whd_tlv8_header_t *parse = cp; + uint32_t parse_len = len; + while ( (wpaie = + (wpa_ie_fixed_portion_t *)whd_parse_tlvs(parse, parse_len, DOT11_IE_ID_VENDOR_SPECIFIC) ) != 0 ) + { + if (whd_is_wpa_ie( (vendor_specific_ie_header_t *)wpaie, &parse, &parse_len ) != WHD_FALSE) + { + break; + } + } + } + + temp16 = WHD_READ_16(&bss_info->capability); + + /* Check if AP is configured for RSN */ + if ( (rsnie != NULL) && + (rsnie->tlv_header.length >= RSN_IE_MINIMUM_LENGTH + rsnie->pairwise_suite_count * sizeof(uint32_t) ) ) + { + uint16_t a; + uint32_t group_key_suite; + akm_suite_portion_t *akm_suites; + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + akm_suites = (akm_suite_portion_t *)&(rsnie->pairwise_suite_list[rsnie->pairwise_suite_count]); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + for (a = 0; a < akm_suites->akm_suite_count; ++a) + { + uint32_t akm_suite_list_item = ntoh32(akm_suites->akm_suite_list[a]) & 0xFF; + if (akm_suite_list_item == (uint32_t)WHD_AKM_PSK) + { + record->security |= WPA2_SECURITY; + } + if (akm_suite_list_item == (uint32_t)WHD_AKM_SAE_SHA256) + { + record->security |= WPA3_SECURITY; + } + if (akm_suite_list_item == (uint32_t)WHD_AKM_8021X) + { + record->security |= WPA2_SECURITY; + record->security |= ENTERPRISE_ENABLED; + } + if (akm_suite_list_item == (uint32_t)WHD_AKM_FT_8021X) + { + record->security |= WPA2_SECURITY; + record->security |= FBT_ENABLED; + record->security |= ENTERPRISE_ENABLED; + } + if (akm_suite_list_item == (uint32_t)WHD_AKM_FT_PSK) + { + record->security |= WPA2_SECURITY; + record->security |= FBT_ENABLED; + } + } + + group_key_suite = ntoh32(rsnie->group_key_suite) & 0xFF; + /* Check the RSN contents to see if there are any references to TKIP cipher (2) in the group key or pairwise keys, */ + /* If so it must be mixed mode. */ + if (group_key_suite == (uint32_t)WHD_CIPHER_TKIP) + { + record->security |= TKIP_ENABLED; + } + if (group_key_suite == (uint32_t)WHD_CIPHER_CCMP_128) + { + record->security |= AES_ENABLED; + } + + for (a = 0; a < rsnie->pairwise_suite_count; ++a) + { + uint32_t pairwise_suite_list_item = ntoh32(rsnie->pairwise_suite_list[a]) & 0xFF; + if (pairwise_suite_list_item == (uint32_t)WHD_CIPHER_TKIP) + { + record->security |= TKIP_ENABLED; + } + + if (pairwise_suite_list_item == (uint32_t)WHD_CIPHER_CCMP_128) + { + record->security |= AES_ENABLED; + } + } + } + /* Check if AP is configured for WPA */ + else if ( (wpaie != NULL) && + (wpaie->vendor_specific_header.tlv_header.length >= + WPA_IE_MINIMUM_LENGTH + wpaie->unicast_suite_count * sizeof(uint32_t) ) ) + { + uint16_t a; + uint32_t group_key_suite; + akm_suite_portion_t *akm_suites; + + record->security = (whd_security_t)WPA_SECURITY; + group_key_suite = ntoh32(wpaie->multicast_suite) & 0xFF; + if (group_key_suite == (uint32_t)WHD_CIPHER_TKIP) + { + record->security |= TKIP_ENABLED; + } + if (group_key_suite == (uint32_t)WHD_CIPHER_CCMP_128) + { + record->security |= AES_ENABLED; + } + + akm_suites = (akm_suite_portion_t *)&(wpaie->unicast_suite_list[wpaie->unicast_suite_count]); + for (a = 0; a < akm_suites->akm_suite_count; ++a) + { + uint32_t akm_suite_list_item = ntoh32(akm_suites->akm_suite_list[a]) & 0xFF; + if (akm_suite_list_item == (uint32_t)WHD_AKM_8021X) + { + record->security |= ENTERPRISE_ENABLED; + } + } + + for (a = 0; a < wpaie->unicast_suite_count; ++a) + { + if (wpaie->unicast_suite_list[a][3] == (uint32_t)WHD_CIPHER_CCMP_128) + { + record->security |= AES_ENABLED; + } + } + } + /* Check if AP is configured for WEP, that is, if the capabilities field indicates privacy, then security supports WEP */ + else if ( (temp16 & DOT11_CAP_PRIVACY) != 0 ) + { + record->security = WHD_SECURITY_WEP_PSK; + } + else + { + /* Otherwise no security */ + record->security = WHD_SECURITY_OPEN; + } + + /* Find a RSNX IE */ + rsnxie = (rsnx_ie_t *)whd_parse_tlvs(cp, len, DOT11_IE_ID_RSNX); + if ( (rsnxie != NULL) && (rsnxie->tlv_header.length == DOT11_RSNX_CAP_LEN) && + (rsnxie->data[0] & (1 << DOT11_RSNX_SAE_H2E) ) ) + { + record->flags |= WHD_SCAN_RESULT_FLAG_SAE_H2E; + } + + /* Update the maximum data rate with 11n rates from the HT Capabilities IE */ + ht_capabilities_ie = (ht_capabilities_ie_t *)whd_parse_tlvs(cp, len, DOT11_IE_ID_HT_CAPABILITIES); + if ( (ht_capabilities_ie != NULL) && (ht_capabilities_ie->tlv_header.length == HT_CAPABILITIES_IE_LENGTH) ) + { + uint8_t a; + uint8_t supports_40mhz = + (ht_capabilities_ie->ht_capabilities_info & HT_CAPABILITIES_INFO_SUPPORTED_CHANNEL_WIDTH_SET) != 0 ? 1 : 0; + uint8_t short_gi[2] = + { (ht_capabilities_ie->ht_capabilities_info & HT_CAPABILITIES_INFO_SHORT_GI_FOR_20MHZ) != 0 ? 1 : 0, + (ht_capabilities_ie->ht_capabilities_info & HT_CAPABILITIES_INFO_SHORT_GI_FOR_40MHZ) != 0 ? 1 : 0 }; + + /* Find highest bit from MCS info */ + for (a = 31; a != 0xFF; --a) + { + if ( (ht_capabilities_ie->rx_mcs[a / 8] & (1 << (a % 8) ) ) != 0 ) + { + break; + } + } + if (a != 0xFF) + { + record->max_data_rate = + ( uint32_t )(100UL * mcs_data_rate_lookup_table[a][supports_40mhz][short_gi[supports_40mhz]]); + } + } + + if (bss_info->flags & WL_BSS_FLAGS_FROM_BEACON) + { + record->flags |= WHD_SCAN_RESULT_FLAG_BEACON; + } + + /* Get the channel for pre-N and control channel for n/HT or later */ + chanspec = dtoh16(WHD_READ_16(&bss_info->chanspec) ); + if (bss_info->n_cap) + { + /* Check control channel first.The channel that chanspec reports is the center frequency which might not be the same as + * the 20 MHz channel that the beacons is on (primary or control channel) if it's an 802.11n/AC 40MHz or wider channel. + */ + record->channel = bss_info->ctl_ch; + } + else + { + /* 11 a/b/g and 20MHz bandwidth only */ + record->channel = ( ( uint8_t )(chanspec & WL_CHANSPEC_CHAN_MASK) ); + } + + /* Find country info IE (Country-Information Information-Element) */ + country_info_ie = (country_info_ie_fixed_portion_t *)whd_parse_dot11_tlvs(cp, len, DOT11_IE_ID_COUNTRY); + if ( (country_info_ie != NULL) && (country_info_ie->tlv_header.length >= COUNTRY_INFO_IE_MINIMUM_LENGTH) ) + { + record->ccode[0] = UNSIGNED_CHAR_TO_CHAR(country_info_ie->ccode[0]); + record->ccode[1] = UNSIGNED_CHAR_TO_CHAR(country_info_ie->ccode[1]); + } + record->band = + ( (chanspec & + GET_C_VAR(whd_driver, + CHANSPEC_BAND_MASK) ) == + GET_C_VAR(whd_driver, CHANSPEC_BAND_2G) ? WHD_802_11_BAND_2_4GHZ : WHD_802_11_BAND_5GHZ ); + + whd_driver->internal_info.scan_result_callback(&whd_driver->internal_info.whd_scan_result_ptr, handler_user_data, + WHD_SCAN_INCOMPLETE); + + /* whd_driver->internal_info.scan_result_callback() can make whd_scan_result_ptr to NULL */ + if (whd_driver->internal_info.whd_scan_result_ptr == NULL) + { + whd_driver->internal_info.scan_result_callback(NULL, handler_user_data, WHD_SCAN_ABORTED); + whd_driver->internal_info.scan_result_callback = NULL; + whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY]); + ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED; + } + + return handler_user_data; +} + +/** Handles auth result events + * + * This function receives scan record events, and parses them into a better format, then passes the results + * to the user application. + * + * @param event_header : The event details + * @param event_data : The data for the event which contains the auth result structure + * @param handler_user_data: data which will be passed to user application + * + * @returns : handler_user_data parameter + * + */ +static void *whd_wifi_auth_events_handler(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, + void *handler_user_data) +{ + whd_driver_t whd_driver = ifp->whd_driver; + whd_scan_result_t *record; + + if (whd_driver->internal_info.auth_result_callback == NULL) + { + WPRINT_WHD_ERROR( ("No set callback function in %s at %d \n", __func__, __LINE__) ); + return handler_user_data; + } + if (event_header->event_type == WLC_E_EXT_AUTH_REQ) + { + uint8_t flag = 0; + if (whd_driver->internal_info.whd_scan_result_ptr) + { + record = (whd_scan_result_t *)(whd_driver->internal_info.whd_scan_result_ptr); + if (record->flags & WHD_SCAN_RESULT_FLAG_SAE_H2E) + flag = 1; + else + flag = 0; + + } + whd_driver->internal_info.auth_result_callback( (void *)event_data, sizeof(whd_auth_req_status_t), + WHD_AUTH_EXT_REQ, &flag, handler_user_data ); + return handler_user_data; + } + else if (event_header->event_type == WLC_E_EXT_AUTH_FRAME_RX) + { + uint32_t mgmt_frame_len; + wl_rx_mgmt_data_t *rxframe; + uint8_t *frame; + + mgmt_frame_len = event_header->datalen - sizeof(wl_rx_mgmt_data_t); + rxframe = (wl_rx_mgmt_data_t *)event_data; + frame = (uint8_t *)(rxframe + 1); + whd_driver->internal_info.auth_result_callback( (void *)frame, mgmt_frame_len, WHD_AUTH_EXT_FRAME_RX, NULL, + handler_user_data ); + return handler_user_data; + + } + + return handler_user_data; +} + +static void whd_scan_count_handler(whd_scan_result_t **result_ptr, void *user_data, whd_scan_status_t status) +{ + uint32_t result; + whd_scan_userdata_t *scan_userdata = (whd_scan_userdata_t *)user_data; + + /* finished scan, either successfully or through an abort */ + if (status != WHD_SCAN_INCOMPLETE) + { + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + result = cy_rtos_set_semaphore(&scan_userdata->scan_semaphore, WHD_FALSE); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("Set semaphore failed in %s at %d \n", __func__, __LINE__) ); + return; + } + + /* just count the available networks */ + scan_userdata->offset += 1; + + memset(*result_ptr, 0, sizeof(whd_scan_result_t) ); + return; +} + +static void whd_scan_result_handler(whd_scan_result_t **result_ptr, void *user_data, whd_scan_status_t status) +{ + uint32_t result; + whd_sync_scan_result_t *record; + whd_scan_userdata_t *scan_userdata = (whd_scan_userdata_t *)user_data; + whd_scan_result_t *current_result; + + /* Safe to access *scan_userdata. This static function registered only from whd_wifi_scan_synch and + * not exposed for general use. The user_data is valid when passed in from whd_wifi_scan_synch. + */ + + /* finished scan, either successfully or through an abort */ + if (status != WHD_SCAN_INCOMPLETE) + { + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + result = cy_rtos_set_semaphore(&scan_userdata->scan_semaphore, WHD_FALSE); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + if (result != WHD_SUCCESS) + WPRINT_WHD_ERROR( ("Set semaphore failed in %s at %d \n", __func__, __LINE__) ); + return; + } + + /* can't really keep anymore scan results */ + if (scan_userdata->offset == scan_userdata->count) + { + /*Offset and the count requested is reached. return with out saving the record details */ + memset(*result_ptr, 0, sizeof(whd_scan_result_t) ); + return; + } + + /* Safe to access *result_ptr as result_ptr should only be NULL if the scan has completed or + * been aborted, which is handled above + */ + current_result = (whd_scan_result_t *)(*result_ptr); + + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + /* Safe to access *scan_userdata, as noted above */ + record = (whd_sync_scan_result_t *)(&scan_userdata->aps[scan_userdata->offset]); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + + /* Copy the SSID into the output record structure */ + record->SSID.length = current_result->SSID.length; + memset(record->SSID.value, 0, sizeof(record->SSID.value) ); + memcpy(record->SSID.value, current_result->SSID.value, record->SSID.length); + + /* Copy the BSSID into the output record structure */ + memcpy( (void *)record->BSSID.octet, (const void *)current_result->BSSID.octet, + sizeof(current_result->BSSID.octet) ); + + record->security = current_result->security; + record->signal_strength = current_result->signal_strength; + record->channel = current_result->channel; + + scan_userdata->offset += 1; + memset(*result_ptr, 0, sizeof(whd_scan_result_t) ); + return; +} + +uint32_t whd_wifi_scan_synch(whd_interface_t ifp, + whd_sync_scan_result_t *scan_result, + uint32_t *count + ) +{ + uint32_t result; + whd_scan_result_t *scan_result_ptr; + whd_scan_userdata_t scan_userdata; + scan_userdata.count = *count; + scan_userdata.aps = scan_result; + scan_userdata.offset = 0; + + if (!ifp || !scan_result) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + CHECK_RETURN(cy_rtos_init_semaphore(&scan_userdata.scan_semaphore, 1, 0) ); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + + whd_scan_result_callback_t handler = (*count == 0) + ? whd_scan_count_handler : whd_scan_result_handler; + + scan_result_ptr = (whd_scan_result_t *)malloc(sizeof(whd_scan_result_t) ); + if (scan_result_ptr == NULL) + { + goto error; + } + memset(scan_result_ptr, 0, sizeof(whd_scan_result_t) ); + + if (whd_wifi_scan(ifp, WHD_SCAN_TYPE_ACTIVE, WHD_BSS_TYPE_ANY, NULL, NULL, NULL, NULL, + handler, (whd_scan_result_t *)scan_result_ptr, &scan_userdata) != WHD_SUCCESS) + { + WPRINT_WHD_INFO( ("Failed scan \n") ); + goto error; + } + + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + result = cy_rtos_get_semaphore(&scan_userdata.scan_semaphore, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + whd_assert("Get semaphore failed", (result == CY_RSLT_SUCCESS) || (result == CY_RTOS_TIMEOUT) ); + + DISABLE_COMPILER_WARNING(diag_suppress = Pa039) + result = cy_rtos_deinit_semaphore(&scan_userdata.scan_semaphore); + ENABLE_COMPILER_WARNING(diag_suppress = Pa039) + if (WHD_SUCCESS != result) + { + WPRINT_WHD_INFO( ("Failed join (err %" PRIu32 ")\n", result) ); + } + if (scan_result_ptr != NULL) + { + free(scan_result_ptr); + scan_result_ptr = NULL; + } + *count = scan_userdata.offset; + + return WHD_SUCCESS; + +error: + if (scan_result_ptr != NULL) + { + free(scan_result_ptr); + scan_result_ptr = NULL; + } + + return WHD_MALLOC_FAILURE; +} + +/* + * NOTE: search references of function wlu_get in wl/exe/wlu.c to find what format the returned IOCTL data is. + */ +uint32_t whd_wifi_scan(whd_interface_t ifp, + whd_scan_type_t scan_type, + whd_bss_type_t bss_type, + const whd_ssid_t *optional_ssid, + const whd_mac_t *optional_mac, + const uint16_t *optional_channel_list, + const whd_scan_extended_params_t *optional_extended_params, + whd_scan_result_callback_t callback, + whd_scan_result_t *result_ptr, + void *user_data + ) +{ + whd_buffer_t buffer; + wl_escan_params_t *scan_params; + uint16_t param_size = offsetof(wl_escan_params_t, params) + WL_SCAN_PARAMS_FIXED_SIZE; + uint16_t channel_list_size = 0; + whd_driver_t whd_driver = ifp->whd_driver; + uint16_t event_entry = 0xFF; + + whd_assert("Bad args", callback != NULL); + + if ( (result_ptr == NULL) || (callback == NULL) ) + { + return WHD_BADARG; + } + + if (!( (scan_type == WHD_SCAN_TYPE_ACTIVE) || (scan_type == WHD_SCAN_TYPE_PASSIVE) || + (scan_type == WHD_SCAN_TYPE_PROHIBITED_CHANNELS) || (scan_type == WHD_SCAN_TYPE_NO_BSSID_FILTER) ) ) + return WHD_BADARG; + + if (!( (bss_type == WHD_BSS_TYPE_INFRASTRUCTURE) || (bss_type == WHD_BSS_TYPE_ADHOC) || + (bss_type == WHD_BSS_TYPE_ANY) ) ) + return WHD_BADARG; + + /* Determine size of channel_list, and add it to the parameter size so correct sized buffer can be allocated */ + if (optional_channel_list != NULL) + { + /* Look for entry with channel number 0, which suggests the end of channel_list */ + for (channel_list_size = 0; optional_channel_list[channel_list_size] != 0; channel_list_size++) + { + } + param_size = ( uint16_t )(param_size + channel_list_size * sizeof(uint16_t) ); + } + + if (ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED) + { + whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY]); + ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED; + } + CHECK_RETURN(whd_management_set_event_handler(ifp, scan_events, whd_wifi_scan_events_handler, user_data, + &event_entry) ); + if (event_entry >= WHD_MAX_EVENT_SUBSCRIPTION) + { + WPRINT_WHD_ERROR( ("scan_events registration failed in function %s and line %d", __func__, __LINE__) ); + return WHD_UNFINISHED; + } + ifp->event_reg_list[WHD_SCAN_EVENT_ENTRY] = event_entry; + /* Allocate a buffer for the IOCTL message */ + scan_params = (wl_escan_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, param_size, IOVAR_STR_ESCAN); + CHECK_IOCTL_BUFFER(scan_params); + + /* Clear the scan parameters structure */ + memset(scan_params, 0, param_size); + + /* Fill in the appropriate details of the scan parameters structure */ + scan_params->version = htod32(ESCAN_REQ_VERSION); + scan_params->action = htod16(WL_SCAN_ACTION_START); + scan_params->params.scan_type = (int8_t)scan_type; + scan_params->params.bss_type = (int8_t)bss_type; + + /* Fill out the SSID parameter if provided */ + if (optional_ssid != NULL) + { + scan_params->params.ssid.SSID_len = htod32(optional_ssid->length); + memcpy(scan_params->params.ssid.SSID, optional_ssid->value, scan_params->params.ssid.SSID_len); + } + + /* Fill out the BSSID parameter if provided */ + if (optional_mac != NULL) + { + memcpy(scan_params->params.bssid.octet, optional_mac, sizeof(whd_mac_t) ); + } + else + { + memset(scan_params->params.bssid.octet, 0xff, sizeof(whd_mac_t) ); + } + + /* Fill out the extended parameters if provided */ + if (optional_extended_params != NULL) + { + scan_params->params.nprobes = (int32_t)htod32(optional_extended_params->number_of_probes_per_channel); + scan_params->params.active_time = + (int32_t)htod32(optional_extended_params->scan_active_dwell_time_per_channel_ms); + scan_params->params.passive_time = (int32_t)htod32( + optional_extended_params->scan_passive_dwell_time_per_channel_ms); + scan_params->params.home_time = (int32_t)htod32( + optional_extended_params->scan_home_channel_dwell_time_between_channels_ms); + } + else + { + scan_params->params.nprobes = (int32_t)htod32(-1); + scan_params->params.active_time = (int32_t)htod32(-1); + scan_params->params.passive_time = (int32_t)htod32(-1); + scan_params->params.home_time = (int32_t)htod32(-1); + } + + /* Copy the channel list parameter if provided */ + if ( (channel_list_size > 0) && (optional_channel_list != NULL) ) + { + int i; + + for (i = 0; i < channel_list_size; i++) + { + scan_params->params.channel_list[i] = htod16(CH20MHZ_CHSPEC(optional_channel_list[i]) ); + } + scan_params->params.channel_num = (int32_t)htod32(channel_list_size); + } + + whd_driver->internal_info.scan_result_callback = callback; + whd_driver->internal_info.whd_scan_result_ptr = result_ptr; + + /* Send the Incremental Scan IOVAR message - blocks until the response is received */ + + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_stop_scan(whd_interface_t ifp) +{ + whd_buffer_t buffer; + wl_escan_params_t *scan_params; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + whd_driver = ifp->whd_driver; + CHECK_DRIVER_NULL(whd_driver) + + /* Allocate a buffer for the IOCTL message */ + scan_params = (wl_escan_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(wl_escan_params_t), + IOVAR_STR_ESCAN); + CHECK_IOCTL_BUFFER(scan_params); + /* Clear the scan parameters structure */ + memset(scan_params, 0, sizeof(wl_escan_params_t) ); + + /* Fill in the appropriate details of the scan parameters structure */ + scan_params->version = htod32(ESCAN_REQ_VERSION); + scan_params->action = htod16(WL_SCAN_ACTION_ABORT); + + /* Send the Scan IOVAR message to abort scan*/ + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_SET, buffer, 0) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_external_auth_request(whd_interface_t ifp, + whd_auth_result_callback_t callback, + void *result_ptr, + void *user_data + ) +{ + CHECK_IFP_NULL(ifp); + whd_driver_t whd_driver = ifp->whd_driver; + uint16_t event_entry = 0xFF; + + whd_assert("Bad args", callback != NULL); + + if (ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED) + { + whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY]); + ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED; + } + CHECK_RETURN(whd_management_set_event_handler(ifp, auth_events, whd_wifi_auth_events_handler, user_data, + &event_entry) ); + if (event_entry >= WHD_MAX_EVENT_SUBSCRIPTION) + { + WPRINT_WHD_ERROR( ("auth_events registration failed in function %s and line %d", __func__, __LINE__) ); + return WHD_UNFINISHED; + } + ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] = event_entry; + + + whd_driver->internal_info.auth_result_callback = callback; + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_stop_external_auth_request(whd_interface_t ifp) +{ + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + whd_driver = ifp->whd_driver; + CHECK_DRIVER_NULL(whd_driver) + + if (ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] != WHD_EVENT_NOT_REGISTERED) + { + whd_wifi_deregister_event_handler(ifp, ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY]); + ifp->event_reg_list[WHD_AUTH_EVENT_ENTRY] = WHD_EVENT_NOT_REGISTERED; + } + whd_driver->internal_info.auth_result_callback = NULL; + return WHD_SUCCESS; +} + +uint32_t whd_wifi_deauth_sta(whd_interface_t ifp, whd_mac_t *mac, whd_dot11_reason_code_t reason) +{ + whd_result_t result; + scb_val_t *scb_val; + whd_buffer_t buffer1; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + if (mac == NULL) + { + uint8_t *buffer = NULL; + whd_maclist_t *clients = NULL; + const whd_mac_t *current; + wl_bss_info_t ap_info; + whd_security_t sec; + uint32_t max_clients = 0; + size_t size = 0; + + result = whd_wifi_ap_get_max_assoc(ifp, &max_clients); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Failed to get max number of associated clients\n") ); + max_clients = 5; + } + + size = (sizeof(uint32_t) + (max_clients * sizeof(whd_mac_t) ) ); + buffer = calloc(1, size); + + if (buffer == NULL) + { + WPRINT_WHD_ERROR( ("Unable to allocate memory for associated clients list, %s failed at line %d \n", + __func__, __LINE__) ); + return WHD_MALLOC_FAILURE; + } + + clients = (whd_maclist_t *)buffer; + clients->count = max_clients; + memset(&ap_info, 0, sizeof(wl_bss_info_t) ); + + result = whd_wifi_get_associated_client_list(ifp, clients, (uint16_t)size); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Failed to get client list, %s failed at line %d \n", __func__, __LINE__) ); + free(buffer); + return result; + } + + current = &clients->mac_list[0]; + result = whd_wifi_get_ap_info(ifp, &ap_info, &sec); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Function %s failed at line %d \n", __func__, __LINE__) ); + free(buffer); + return result; + } + + + while ( (clients->count > 0) && (!(NULL_MAC(current->octet) ) ) ) + { + if (memcmp(current->octet, &(ap_info.BSSID), sizeof(whd_mac_t) ) != 0) + { + WPRINT_WHD_INFO( ("Deauthenticating STA MAC: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", current->octet[0], + current->octet[1], current->octet[2], current->octet[3], current->octet[4], + current->octet[5]) ); + + scb_val = (scb_val_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer1, sizeof(scb_val_t) ); + if (scb_val == NULL) + { + WPRINT_WHD_ERROR( ("Buffer alloc failed in function %s at line %d \n", __func__, __LINE__) ); + free(buffer); + return WHD_BUFFER_ALLOC_FAIL; + } + memset( (char *)scb_val, 0, sizeof(scb_val_t) ); + memcpy( (char *)&scb_val->ea, (char *)current, sizeof(whd_mac_t) ); + scb_val->val = (uint32_t)reason; + result = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SCB_DEAUTHENTICATE_FOR_REASON, buffer1, 0); + + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Failed to deauth client\n") ); + } + } + + --clients->count; + ++current; + } + + free(buffer); + + return WHD_SUCCESS; + } + + scb_val = (scb_val_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer1, sizeof(scb_val_t) ); + CHECK_IOCTL_BUFFER(scb_val); + memset( (char *)scb_val, 0, sizeof(scb_val_t) ); + memcpy( (char *)&scb_val->ea, (char *)mac, sizeof(whd_mac_t) ); + scb_val->val = (uint32_t)reason; + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SCB_DEAUTHENTICATE_FOR_REASON, buffer1, 0) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_get_mac_address(whd_interface_t ifp, whd_mac_t *mac) +{ + whd_buffer_t buffer; + whd_buffer_t response; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + if (mac == NULL) + return WHD_BADARG; + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(whd_mac_t), IOVAR_STR_CUR_ETHERADDR) ); + + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + + memcpy(mac, whd_buffer_get_current_piece_data_pointer(whd_driver, response), sizeof(whd_mac_t) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_get_bssid(whd_interface_t ifp, whd_mac_t *bssid) +{ + whd_buffer_t buffer; + whd_buffer_t response; + whd_result_t result; + whd_driver_t whd_driver; + uint8_t *data = NULL; + CHECK_IFP_NULL(ifp); + + if (bssid == NULL) + return WHD_BADARG; + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + if ( (ifp->role == WHD_STA_ROLE) || (ifp->role == WHD_AP_ROLE) ) + { + memset(bssid, 0, sizeof(whd_mac_t) ); + CHECK_IOCTL_BUFFER(whd_cdc_get_ioctl_buffer(whd_driver, &buffer, sizeof(whd_mac_t) ) ); + if ( (result = + whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_BSSID, buffer, &response) ) == WHD_SUCCESS ) + { + data = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy(bssid->octet, data, sizeof(whd_mac_t) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + } + return result; + } + else if (ifp->role == WHD_INVALID_ROLE) + { + WPRINT_WHD_ERROR( ("STA not associated with AP\n") ); + return WHD_WLAN_NOTASSOCIATED; + } + else + { + return WHD_UNSUPPORTED; + } +} + +uint32_t whd_wifi_ap_get_max_assoc(whd_interface_t ifp, uint32_t *max_assoc) +{ + if (!ifp || !max_assoc) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + return whd_wifi_get_iovar_value(ifp, IOVAR_STR_MAX_ASSOC, max_assoc); +} + +uint32_t whd_wifi_get_associated_client_list(whd_interface_t ifp, void *client_list_buffer, uint16_t buffer_length) +{ + whd_buffer_t buffer; + whd_buffer_t response; + whd_result_t result; + whd_maclist_t *data = NULL; + uint8_t *pdata = NULL; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* Check if soft AP interface is up, if not, return a count of 0 as a result */ + result = whd_wifi_is_ready_to_transceive(ifp); + if ( (result == WHD_SUCCESS) && (ifp->role == WHD_AP_ROLE) ) + { + data = (whd_maclist_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, buffer_length); + CHECK_IOCTL_BUFFER(data); + memset(data, 0, buffer_length); + data->count = htod32( ( (whd_maclist_t *)client_list_buffer )->count ); + + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_ASSOCLIST, buffer, &response) ); + pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy(client_list_buffer, (void *)pdata, + (size_t)MIN_OF(whd_buffer_get_current_piece_size(whd_driver, response), buffer_length) ); + + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + } + else if (result == WHD_INTERFACE_NOT_UP) + { + /* not up, so can't have associated clients */ + ( (whd_maclist_t *)client_list_buffer )->count = 0; + } + else + { + WPRINT_WHD_ERROR( ("Invalid Interface\n") ); + return WHD_INVALID_INTERFACE; + } + return result; +} + +uint32_t whd_wifi_get_ap_info(whd_interface_t ifp, wl_bss_info_t *ap_info, whd_security_t *security) +{ + whd_buffer_t buffer; + whd_buffer_t response; + uint32_t *data; + uint8_t *pdata = NULL; + uint32_t security_value; /* hold misc security values */ + whd_driver_t whd_driver; + CHECK_IFP_NULL(ifp); + + if ( (ap_info == NULL) || (security == NULL) ) + return WHD_BADARG; + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + /* Read the BSS info */ + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, WLC_IOCTL_SMLEN); + CHECK_IOCTL_BUFFER(data); + *data = WLC_IOCTL_SMLEN; + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_BSS_INFO, buffer, &response) ); + pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy(ap_info, (void *)(pdata + 4), sizeof(wl_bss_info_t) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + /* Read the WSEC setting */ + CHECK_RETURN(whd_wifi_get_ioctl_value(ifp, WLC_GET_WSEC, &security_value) ); + security_value = security_value & SECURITY_MASK; + *security = ( whd_security_t )(security_value); + + if (*security == WHD_SECURITY_WEP_PSK) + { + /* Read the WEP auth setting */ + CHECK_RETURN(whd_wifi_get_ioctl_value(ifp, WLC_GET_AUTH, &security_value) ); + + if (security_value == SHARED_AUTH) + { + *security |= SHARED_ENABLED; + } + } + else if ( (*security & (TKIP_ENABLED | AES_ENABLED) ) != 0 ) + { + /* Read the WPA auth setting */ + CHECK_RETURN(whd_wifi_get_ioctl_value(ifp, WLC_GET_WPA_AUTH, &security_value) ); + + if (security_value == WPA2_AUTH_PSK) + { + *security |= WPA2_SECURITY; + } + else if (security_value == WPA_AUTH_PSK) + { + *security |= WPA_SECURITY; + } + } + else if (*security != WHD_SECURITY_OPEN) + { + *security = WHD_SECURITY_UNKNOWN; + WPRINT_WHD_ERROR( ("Unknown security type, %s failed at line %d \n", __func__, __LINE__) ); + return WHD_UNKNOWN_SECURITY_TYPE; + } + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_enable_powersave(whd_interface_t ifp) +{ + whd_buffer_t buffer; + uint32_t *data; + whd_driver_t whd_driver; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* Set legacy powersave mode - PM1 */ + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4); + CHECK_IOCTL_BUFFER(data); + *data = htod32( (uint32_t)PM1_POWERSAVE_MODE ); + + RETURN_WITH_ASSERT(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_PM, buffer, NULL) ); +} + +uint32_t whd_wifi_get_powersave_mode(whd_interface_t ifp, uint32_t *value) +{ + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + if (value == NULL) + return WHD_BADARG; + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + return whd_wifi_get_ioctl_value(ifp, WLC_GET_PM, value); +} + +uint32_t whd_wifi_enable_powersave_with_throughput(whd_interface_t ifp, uint16_t return_to_sleep_delay_ms) +{ + whd_buffer_t buffer; + uint32_t *data; + whd_driver_t whd_driver; + uint16_t chip_id; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + if (return_to_sleep_delay_ms < PM2_SLEEP_RET_TIME_MIN) + { + WPRINT_WHD_ERROR( ("Delay too short, %s failed at line %d \n", __func__, __LINE__) ); + return WHD_DELAY_TOO_SHORT; + } + else if (return_to_sleep_delay_ms > PM2_SLEEP_RET_TIME_MAX) + { + WPRINT_WHD_ERROR( ("Delay too long, %s failed at line %d \n", __func__, __LINE__) ); + return WHD_DELAY_TOO_LONG; + } + + /* Set the maximum time to wait before going back to sleep */ + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_PM2_SLEEP_RET, + (uint32_t)(return_to_sleep_delay_ms / 10) * 10) ); + chip_id = whd_chip_get_chip_id(whd_driver); + + if (chip_id == 43362) + { + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_PM_LIMIT, NULL_FRAMES_WITH_PM_SET_LIMIT) ); + } + + /* set PM2 fast return to sleep powersave mode */ + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4); + CHECK_IOCTL_BUFFER(data); + *data = htod32( (uint32_t)PM2_POWERSAVE_MODE ); + + RETURN_WITH_ASSERT(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_PM, buffer, NULL) ); +} + +uint32_t whd_wifi_disable_powersave(whd_interface_t ifp) +{ + whd_buffer_t buffer; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + uint32_t *data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)4); + + CHECK_IOCTL_BUFFER(data); + *data = htod32( (uint32_t)NO_POWERSAVE_MODE ); + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_PM, buffer, NULL) ); + return WHD_SUCCESS; +} + +uint32_t whd_wifi_register_multicast_address(whd_interface_t ifp, const whd_mac_t *mac) +{ + whd_buffer_t buffer; + whd_buffer_t response; + uint16_t a; + mcast_list_t *orig_mcast_list; + mcast_list_t *new_mcast_list; + whd_driver_t whd_driver; + + if (!ifp || !mac || !ETHER_ISMULTI(mac) ) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* Get the current multicast list */ + CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer, + sizeof(uint32_t) + MAX_SUPPORTED_MCAST_ENTRIES * + sizeof(whd_mac_t), IOVAR_STR_MCAST_LIST) ); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + + /* Verify address is not currently registered */ + orig_mcast_list = (mcast_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(orig_mcast_list, WHD_NO_REGISTER_FUNCTION_POINTER); + orig_mcast_list->entry_count = dtoh32(orig_mcast_list->entry_count); + for (a = 0; a < orig_mcast_list->entry_count; ++a) + { + /* Check if any address matches */ + if (0 == memcmp(mac, &orig_mcast_list->macs[a], sizeof(whd_mac_t) ) ) + { + /* A matching address has been found so we can stop now. */ + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + return WHD_SUCCESS; + } + } + + /* Add the provided address to the list and write the new multicast list */ + new_mcast_list = (mcast_list_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, + ( uint16_t )(sizeof(uint32_t) + + (orig_mcast_list->entry_count + 1) * + sizeof(whd_mac_t) ), + IOVAR_STR_MCAST_LIST); + CHECK_IOCTL_BUFFER(new_mcast_list); + new_mcast_list->entry_count = orig_mcast_list->entry_count; + memcpy(new_mcast_list->macs, orig_mcast_list->macs, orig_mcast_list->entry_count * sizeof(whd_mac_t) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + memcpy(&new_mcast_list->macs[new_mcast_list->entry_count], mac, sizeof(whd_mac_t) ); + ++new_mcast_list->entry_count; + new_mcast_list->entry_count = htod32(new_mcast_list->entry_count); + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); + +} + +uint32_t whd_wifi_unregister_multicast_address(whd_interface_t ifp, const whd_mac_t *mac) +{ + whd_buffer_t buffer; + whd_buffer_t response; + uint16_t a; + mcast_list_t *orig_mcast_list; + whd_driver_t whd_driver; + + if (!ifp || !mac || !ETHER_ISMULTI(mac) ) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + /* Get the current multicast list */ + CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer, + sizeof(uint32_t) + MAX_SUPPORTED_MCAST_ENTRIES * + sizeof(whd_mac_t), IOVAR_STR_MCAST_LIST) ); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + + /* Find the address, assuming it is part of the list */ + orig_mcast_list = (mcast_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + orig_mcast_list->entry_count = dtoh32(orig_mcast_list->entry_count); + if (orig_mcast_list->entry_count != 0) + { + mcast_list_t *new_mcast_list = (mcast_list_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, + ( uint16_t )(sizeof(uint32_t) + + (orig_mcast_list-> + entry_count - 1) * + sizeof(whd_mac_t) ), + IOVAR_STR_MCAST_LIST); + CHECK_IOCTL_BUFFER(new_mcast_list); + + for (a = 0; a < orig_mcast_list->entry_count; ++a) + { + WPRINT_WHD_INFO( ("MAC: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", orig_mcast_list->macs[a].octet[0], + orig_mcast_list->macs[a].octet[1], orig_mcast_list->macs[a].octet[2], + orig_mcast_list->macs[a].octet[3], orig_mcast_list->macs[a].octet[4], + orig_mcast_list->macs[a].octet[5]) ); + if (0 == memcmp(mac, &orig_mcast_list->macs[a], sizeof(whd_mac_t) ) ) + { + /* Copy the existing list up to the matching address */ + memcpy(new_mcast_list->macs, orig_mcast_list->macs, a * sizeof(whd_mac_t) ); + + /* Skip the current address and copy the remaining entries */ + memcpy(&new_mcast_list->macs[a], &orig_mcast_list->macs[a + 1], + ( size_t )(orig_mcast_list->entry_count - a - 1) * sizeof(whd_mac_t) ); + + new_mcast_list->entry_count = orig_mcast_list->entry_count - 1; + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + new_mcast_list->entry_count = htod32(new_mcast_list->entry_count); + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); + } + } + /* There was something in the list, but the request MAC wasn't there */ + CHECK_RETURN(whd_buffer_release(whd_driver, buffer, WHD_NETWORK_TX) ); + } + /* If we get here than the address wasn't in the list or the list was empty */ + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + WPRINT_WHD_ERROR( ("whd_wifi_unregister_multicast_address address not registered yet \n") ); + return WHD_DOES_NOT_EXIST; +} + +uint32_t whd_wifi_set_listen_interval(whd_interface_t ifp, uint8_t listen_interval, + whd_listen_interval_time_unit_t time_unit) +{ + uint8_t listen_interval_dtim; + + CHECK_IFP_NULL(ifp); + + switch (time_unit) + { + case WHD_LISTEN_INTERVAL_TIME_UNIT_DTIM: + { + listen_interval_dtim = listen_interval; + break; + } + case WHD_LISTEN_INTERVAL_TIME_UNIT_BEACON: + { + /* If the wake interval measured in DTIMs is set to 0, the wake interval is measured in beacon periods */ + listen_interval_dtim = 0; + + /* The wake period is measured in beacon periods, set the value as required */ + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_LISTEN_INTERVAL_BEACON, listen_interval) ); + break; + } + default: + WPRINT_WHD_ERROR( ("whd_wifi_set_listen_interval: Invalid Time unit specified \n") ); + return WHD_BADARG; + } + + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_LISTEN_INTERVAL_DTIM, listen_interval_dtim) ); + + CHECK_RETURN(whd_wifi_set_iovar_value(ifp, IOVAR_STR_LISTEN_INTERVAL_ASSOC, listen_interval) ); + + return WHD_SUCCESS; + +} + +uint32_t whd_wifi_get_listen_interval(whd_interface_t ifp, whd_listen_interval_t *li) +{ + whd_buffer_t buffer; + whd_buffer_t response; + int *data; + uint8_t *pdata = NULL; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + if (li == NULL) + return WHD_BADARG; + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + data = (int *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, 4, IOVAR_STR_LISTEN_INTERVAL_BEACON); + CHECK_IOCTL_BUFFER(data); + memset(data, 0, 1); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy( (uint8_t *)&(li->beacon), (char *)pdata, 1 ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + data = (int *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, 4, IOVAR_STR_LISTEN_INTERVAL_DTIM); + CHECK_IOCTL_BUFFER(data); + memset(data, 0, 1); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy( (uint8_t *)&(li->dtim), (char *)pdata, 1 ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + data = (int *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, 4, IOVAR_STR_LISTEN_INTERVAL_ASSOC); + CHECK_IOCTL_BUFFER(data); + memset(data, 0, 4); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy( (uint16_t *)&(li->assoc), (char *)pdata, 2 ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_is_ready_to_transceive(whd_interface_t ifp) +{ + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + switch (ifp->role) + { + case WHD_AP_ROLE: + return (whd_wifi_get_ap_is_up(whd_driver) == WHD_TRUE) ? WHD_SUCCESS : WHD_INTERFACE_NOT_UP; + + case WHD_STA_ROLE: + return whd_wifi_check_join_status(ifp); + + /* Disables Eclipse static analysis warning */ + /* No break needed due to returns in all case paths */ + /* no break */ + /* Fall Through */ + case WHD_P2P_ROLE: + case WHD_INVALID_ROLE: + + default: + return WHD_UNKNOWN_INTERFACE; + } +} + +uint32_t whd_wifi_get_acparams(whd_interface_t ifp, edcf_acparam_t *acp) +{ + whd_buffer_t buffer; + whd_buffer_t response; + whd_driver_t whd_driver; + uint8_t *pdata = NULL; + + if (!ifp || !acp) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + int *data = (int *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, 64, IOVAR_STR_AC_PARAMS_STA); + + CHECK_IOCTL_BUFFER(data); + memset(data, 0, 64); + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy( (char *)acp, (char *)pdata, (sizeof(edcf_acparam_t) * 4) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_get_channels(whd_interface_t ifp, whd_list_t *channel_list) +{ + whd_buffer_t buffer; + whd_buffer_t response; + whd_list_t *list; + whd_driver_t whd_driver; + uint16_t buffer_length; + + if (!ifp || !channel_list) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + if (!channel_list->count) + { + WPRINT_WHD_ERROR( ("channel_list->count is zero and max channel is %d in func %s at line %d \n", + WL_NUMCHANNELS, __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + buffer_length = sizeof(uint32_t) * (WL_NUMCHANNELS + 1); + + list = (whd_list_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, buffer_length); + CHECK_IOCTL_BUFFER(list); + + memset(list, 0, buffer_length); + list->count = htod32(WL_NUMCHANNELS); + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_VALID_CHANNELS, buffer, &response) ); + + list = (whd_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + memcpy(channel_list, list, + (size_t)MIN_OF(whd_buffer_get_current_piece_size(whd_driver, response), + (sizeof(uint32_t) * (channel_list->count + 1) ) ) ); + + whd_buffer_release(whd_driver, response, WHD_NETWORK_RX); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_manage_custom_ie(whd_interface_t ifp, whd_custom_ie_action_t action, const uint8_t *oui, + uint8_t subtype, const void *data, uint16_t length, uint16_t which_packets) +{ + whd_buffer_t buffer; + vndr_ie_setbuf_t *ie_setbuf; + uint32_t *iovar_data; + whd_driver_t whd_driver; + + if (!ifp || !oui || !data) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + /* VNDR_IE = OUI + subtype + data_length */ + if (VNDR_IE_MAX_LEN < WIFI_IE_OUI_LENGTH + 1 + length) + { + WPRINT_WHD_ERROR( ("Invalid length :%u in func %s\n", length, __func__) ); + return WHD_WLAN_BADARG; + } + + if (which_packets & VENDOR_IE_UNKNOWN) + { + WPRINT_WHD_ERROR( ("Unsupported packet ID(%x) in func %s\n", which_packets, __func__) ); + return WHD_WLAN_BADARG; + } + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + whd_assert("Bad Args", oui != NULL); + + iovar_data = + (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)(sizeof(vndr_ie_setbuf_t) + length + 4), + "bsscfg:" IOVAR_STR_VENDOR_IE); + CHECK_IOCTL_BUFFER(iovar_data); + *iovar_data = ifp->bsscfgidx; + ie_setbuf = (vndr_ie_setbuf_t *)(iovar_data + 1); + + /* Copy the vndr_ie SET command ("add"/"del") to the buffer */ + if (action == WHD_ADD_CUSTOM_IE) + { + memcpy( (char *)ie_setbuf->cmd, "add", 3 ); + } + else + { + memcpy( (char *)ie_setbuf->cmd, "del", 3 ); + } + ie_setbuf->cmd[3] = 0; + + /* Set the values */ + ie_setbuf->vndr_ie_buffer.iecount = (int32_t)htod32(1); + + ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag = htod32(which_packets); + ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = 0xdd; + ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = + ( uint8_t )(length + sizeof(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui) + 1); /* +1: one byte for sub type */ + + /* Stop lint warning about vndr_ie_list array element not yet being defined */ + memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, oui, (size_t)WIFI_IE_OUI_LENGTH); + + ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0] = subtype; + + memcpy(&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[1], data, length); + + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); +} + +uint32_t whd_wifi_send_action_frame(whd_interface_t ifp, whd_af_params_t *af_params) +{ + whd_buffer_t buffer; + whd_af_params_t *af_frame; + whd_driver_t whd_driver; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + if ( (af_params == NULL) || (af_params->action_frame.len > ACTION_FRAME_SIZE) ) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + af_frame = (whd_af_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, WL_WIFI_AF_PARAMS_SIZE, + IOVAR_STR_ACTION_FRAME); + CHECK_IOCTL_BUFFER (af_frame); + memcpy(af_frame, af_params, WL_WIFI_AF_PARAMS_SIZE); + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); +} + +whd_result_t whd_wifi_send_auth_frame(whd_interface_t ifp, whd_auth_params_t *auth_params) +{ + whd_buffer_t buffer; + whd_auth_params_t *auth_frame; + whd_driver_t whd_driver; + uint16_t auth_frame_len; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + if (auth_params == NULL) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + /* FW doesn't need MAC Header Length */ + auth_params->len -= DOT11_MGMT_HDR_LEN; + auth_frame_len = OFFSET(whd_auth_params_t, data) + auth_params->len; + auth_frame = (whd_auth_params_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, auth_frame_len, + IOVAR_STR_MGMT_FRAME); + CHECK_IOCTL_BUFFER (auth_frame); + memcpy(auth_frame, auth_params, OFFSET(whd_auth_params_t, data) ); + memcpy(auth_frame->data, &auth_params->data[DOT11_MGMT_HDR_LEN], auth_params->len); + auth_frame->dwell_time = MGMT_AUTH_FRAME_DWELL_TIME; + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); +} + +uint32_t whd_wifi_set_ioctl_value(whd_interface_t ifp, uint32_t ioctl, uint32_t value) +{ + whd_buffer_t buffer; + uint32_t *data; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)sizeof(value) ); + CHECK_IOCTL_BUFFER(data); + *data = htod32(value); + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, ioctl, buffer, 0) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_get_ioctl_value(whd_interface_t ifp, uint32_t ioctl, uint32_t *value) +{ + whd_buffer_t buffer; + whd_buffer_t response; + whd_driver_t whd_driver; + uint8_t *data = NULL; + + if (value == NULL) + return WHD_BADARG; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + CHECK_IOCTL_BUFFER(whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)sizeof(*value) ) ); + CHECK_RETURN_UNSUPPORTED_OK(whd_cdc_send_ioctl(ifp, CDC_GET, ioctl, buffer, &response) ); + data = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + *value = dtoh32(*(uint32_t *)data); + + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_set_ioctl_buffer(whd_interface_t ifp, uint32_t ioctl, void *in_buffer, uint16_t in_buffer_length) +{ + whd_buffer_t buffer; + uint32_t *data; + whd_driver_t whd_driver = ifp->whd_driver; + + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, in_buffer_length); + CHECK_IOCTL_BUFFER(data); + + memcpy(data, in_buffer, in_buffer_length); + + CHECK_RETURN(whd_cdc_send_ioctl(ifp, CDC_SET, ioctl, buffer, NULL) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_get_ioctl_buffer(whd_interface_t ifp, uint32_t ioctl, uint8_t *out_buffer, uint16_t out_length) +{ + whd_buffer_t buffer; + uint32_t *data; + whd_buffer_t response; + whd_result_t result; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + data = (uint32_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer, out_length); + CHECK_IOCTL_BUFFER(data); + memcpy(data, out_buffer, out_length); + + result = whd_cdc_send_ioctl(ifp, CDC_GET, ioctl, buffer, &response); + + /* it worked: copy the result to the output buffer */ + if (WHD_SUCCESS == result) + { + data = (uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + *data = dtoh32(*data); + memcpy(out_buffer, data, out_length); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + } + + CHECK_RETURN(result); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_set_iovar_void(whd_interface_t ifp, const char *iovar) +{ + whd_buffer_t buffer; + whd_driver_t whd_driver = ifp->whd_driver; + + whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)0, iovar); + + return whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL); +} + +uint32_t whd_wifi_set_iovar_value(whd_interface_t ifp, const char *iovar, uint32_t value) +{ + whd_buffer_t buffer; + uint32_t *data; + whd_driver_t whd_driver = ifp->whd_driver; + + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)sizeof(value), iovar); + CHECK_IOCTL_BUFFER(data); + *data = htod32(value); + return whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL); +} + +uint32_t whd_wifi_get_iovar_value(whd_interface_t ifp, const char *iovar, uint32_t *value) +{ + whd_buffer_t buffer; + whd_buffer_t response; + whd_driver_t whd_driver = ifp->whd_driver; + uint8_t *data = NULL; + + if (value == NULL) + return WHD_BADARG; + + CHECK_IOCTL_BUFFER(whd_cdc_get_iovar_buffer(whd_driver, &buffer, 4, iovar) ); + CHECK_RETURN_UNSUPPORTED_OK(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + data = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + *value = dtoh32(*(uint32_t *)data); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_set_iovar_buffer(whd_interface_t ifp, const char *iovar, void *in_buffer, uint16_t in_buffer_length) +{ + return whd_wifi_set_iovar_buffers(ifp, iovar, (const void **)&in_buffer, (const uint16_t *)&in_buffer_length, 1); +} + +uint32_t whd_wifi_get_iovar_buffer(whd_interface_t ifp, const char *iovar_name, uint8_t *out_buffer, + uint16_t out_length) +{ + uint32_t *data; + whd_buffer_t buffer; + whd_buffer_t response; + whd_result_t result; + whd_driver_t whd_driver = ifp->whd_driver; + + data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)out_length, iovar_name); + CHECK_IOCTL_BUFFER(data); + + result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response); + + /* it worked: copy the result to the output buffer */ + if (WHD_SUCCESS == result) + { + data = (uint32_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + *data = dtoh32(*data); + memcpy(out_buffer, data, out_length); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + } + + return result; +} + +/* + * format an iovar buffer + */ +static whd_result_t +whd_iovar_mkbuf(const char *name, char *data, uint32_t datalen, char *iovar_buf, uint16_t buflen) +{ + uint32_t iovar_len; + + iovar_len = strlen(name) + 1; + + /* check for overflow */ + if ( (iovar_len + datalen) > buflen ) + { + return WHD_BADARG; + } + + /* copy data to the buffer past the end of the iovar name string */ + if (datalen > 0) + memmove(&iovar_buf[iovar_len], data, datalen); + + /* copy the name to the beginning of the buffer */ + strncpy(iovar_buf, name, (iovar_len - 1) ); + + return WHD_SUCCESS; +} + +whd_result_t whd_wifi_get_iovar_buffer_with_param(whd_interface_t ifp, const char *iovar_name, void *param, + uint32_t paramlen, uint8_t *out_buffer, uint32_t out_length) +{ + uint32_t *data; + whd_buffer_t buffer; + whd_buffer_t response; + whd_result_t result; + whd_driver_t whd_driver; + + if (!ifp || !iovar_name || !param || !out_buffer) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", + __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + whd_driver = (whd_driver_t)ifp->whd_driver; + + /* Format the input string */ + result = whd_iovar_mkbuf(iovar_name, param, paramlen, (char *)out_buffer, (uint16_t)out_length); + if (result != WHD_SUCCESS) + return result; + + data = whd_cdc_get_ioctl_buffer(whd_driver, &buffer, (uint16_t)out_length); + + if (data == NULL) + return WHD_WLAN_NOMEM; + + memcpy(data, out_buffer, out_length); + + result = (whd_result_t)whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_VAR, buffer, &response); + + if (result == WHD_SUCCESS) + { + memcpy(out_buffer, whd_buffer_get_current_piece_data_pointer(whd_driver, response), + (size_t)MIN_OF(whd_buffer_get_current_piece_size(whd_driver, response), out_length) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + } + + return result; +} + +uint32_t whd_wifi_set_iovar_buffers(whd_interface_t ifp, const char *iovar, const void **in_buffers, + const uint16_t *lengths, const uint8_t num_buffers) +{ + whd_buffer_t buffer; + uint32_t *data; + int tot_in_buffer_length = 0; + uint8_t buffer_num = 0; + whd_driver_t whd_driver = ifp->whd_driver; + + /* get total length of all buffers: they will be copied into memory one after the other. */ + for (; buffer_num < num_buffers; buffer_num++) + { + tot_in_buffer_length += lengths[buffer_num]; + } + + /* get a valid buffer */ + data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)tot_in_buffer_length, iovar); + CHECK_IOCTL_BUFFER(data); + + /* copy all data into buffer */ + for (buffer_num = 0; buffer_num < num_buffers; buffer_num++) + { + memcpy(data, in_buffers[buffer_num], lengths[buffer_num]); + data += lengths[buffer_num]; + } + + /* send iovar */ + return whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL); +} + +uint32_t whd_wifi_get_clm_version(whd_interface_t ifp, char *version, uint8_t length) +{ + whd_result_t result; + + CHECK_IFP_NULL(ifp); + + if (version == NULL) + return WHD_BADARG; + + version[0] = '\0'; + + result = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_CLMVER, (uint8_t *)version, length); + if ( (result == WHD_SUCCESS) && version[0] ) + { + uint8_t version_length; + char *p; + + version_length = strlen(version); + + /* -2 becase \0 termination needs a char and strlen doesn't include length of \0 */ + if (version_length > length - 2) + version_length = length - 2; + version[version_length + 1] = '\0'; + + /* Replace all newline/linefeed characters with space character */ + p = version; + while ( (p = strchr(p, '\n') ) != NULL ) + { + *p = ' '; + } + } + + CHECK_RETURN(result); + return WHD_SUCCESS; +} + +uint32_t whd_wifi_get_wifi_version(whd_interface_t ifp, char *buf, uint8_t length) +{ + whd_result_t result; + uint8_t ver_len; + + CHECK_IFP_NULL(ifp); + + if (buf == NULL) + return WHD_BADARG; + + result = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_VERSION, (uint8_t *)buf, length); + + ver_len = strlen(buf); + + if (ver_len > length - 2) + ver_len = length - 2; + + if ( (ver_len > 1) && (buf[ver_len + 1] == '\n') ) + { + buf[ver_len + 1] = '\0'; + } + + CHECK_RETURN(result); + return WHD_SUCCESS; +} + +uint32_t whd_network_get_ifidx_from_ifp(whd_interface_t ifp, uint8_t *ifidx) +{ + CHECK_IFP_NULL(ifp); + + if (!ifidx) + return WHD_BADARG; + + *ifidx = ifp->ifidx; + + return WHD_SUCCESS; +} + +uint32_t whd_network_get_bsscfgidx_from_ifp(whd_interface_t ifp, uint8_t *bsscfgidx) +{ + CHECK_IFP_NULL(ifp); + + if (!bsscfgidx) + return WHD_BADARG; + + *bsscfgidx = ifp->bsscfgidx; + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_ap_set_beacon_interval(whd_interface_t ifp, uint16_t interval) +{ + CHECK_IFP_NULL(ifp); + + CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_BCNPRD, interval) ); + return WHD_SUCCESS; +} + +uint32_t whd_wifi_ap_set_dtim_interval(whd_interface_t ifp, uint16_t interval) +{ + CHECK_IFP_NULL(ifp); + + CHECK_RETURN(whd_wifi_set_ioctl_value(ifp, WLC_SET_DTIMPRD, interval) ); + return WHD_SUCCESS; +} + +uint32_t whd_wifi_get_bss_info(whd_interface_t ifp, wl_bss_info_t *bi) +{ + whd_buffer_t buffer, response; + uint32_t result; + uint8_t *data; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + if (bi == NULL) + return WHD_BADARG; + + if (whd_cdc_get_ioctl_buffer(whd_driver, &buffer, WLC_IOCTL_SMLEN) == NULL) + { + WPRINT_WHD_INFO( ("%s: Unable to malloc WLC_GET_BSS_INFO buffer\n", __FUNCTION__) ); + return WHD_SUCCESS; + } + result = whd_cdc_send_ioctl(ifp, CDC_GET, WLC_GET_BSS_INFO, buffer, &response); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_INFO( ("%s: WLC_GET_BSS_INFO Failed\n", __FUNCTION__) ); + return result; + } + data = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(data, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy(bi, data + 4, sizeof(wl_bss_info_t) ); + + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + + return WHD_SUCCESS; +} + +uint32_t whd_wifi_set_coex_config(whd_interface_t ifp, whd_coex_config_t *coex_config) +{ + CHECK_IFP_NULL(ifp); + + if (coex_config == NULL) + return WHD_BADARG; + + return whd_wifi_set_iovar_buffer(ifp, IOVAR_STR_BTC_LESCAN_PARAMS, &coex_config->le_scan_params, + sizeof(whd_btc_lescan_params_t) ); +} + +whd_result_t whd_wifi_set_auth_status(whd_interface_t ifp, whd_auth_req_status_t *params) +{ + whd_buffer_t buffer; + whd_driver_t whd_driver; + whd_auth_req_status_t *auth_status; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + if (params == NULL) + { + WPRINT_WHD_ERROR( ("Invalid param in func %s at line %d \n", __func__, __LINE__) ); + return WHD_WLAN_BADARG; + } + + auth_status = (whd_auth_req_status_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(whd_auth_req_status_t), + IOVAR_STR_AUTH_STATUS); + CHECK_IOCTL_BUFFER (auth_status); + memcpy(auth_status, params, sizeof(whd_auth_req_status_t) ); + if (params->flags == DOT11_SC_SUCCESS) + { + auth_status->flags = WL_EXTAUTH_SUCCESS; + } + else + { + auth_status->flags = WL_EXTAUTH_FAIL; + } + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); +} + +whd_result_t whd_wifi_get_fwcap(whd_interface_t ifp, uint32_t *value) +{ + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + CHECK_DRIVER_NULL(whd_driver); + + *value = whd_driver->chip_info.fwcap_flags; + return WHD_SUCCESS; +} + +/* + * ARP Offload version + * ARP version in the WLAN Firmware + * + * @param[in] ifp - whd interface Instance + * @param[out] version - pointer to store version # + * + * @return @ref whd_result_t + */ +whd_result_t whd_arp_version(whd_interface_t ifp, uint32_t *value) +{ + CHECK_IFP_NULL(ifp); + + return whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARP_VERSION, value); +} + +whd_result_t whd_arp_peerage_get(whd_interface_t ifp, uint32_t *value) +{ + CHECK_IFP_NULL(ifp); + + return whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARP_PEERAGE, value); +} + +whd_result_t whd_arp_peerage_set(whd_interface_t ifp, uint32_t value) +{ + CHECK_IFP_NULL(ifp); + + return whd_wifi_set_iovar_value(ifp, IOVAR_STR_ARP_PEERAGE, value); +} + +whd_result_t whd_arp_arpoe_get(whd_interface_t ifp, uint32_t *value) +{ + CHECK_IFP_NULL(ifp); + + return whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARPOE, value); +} + +whd_result_t whd_arp_arpoe_set(whd_interface_t ifp, uint32_t value) +{ + CHECK_IFP_NULL(ifp); + + return whd_wifi_set_iovar_value(ifp, IOVAR_STR_ARPOE, value); +} + +whd_result_t whd_arp_cache_clear(whd_interface_t ifp) +{ + whd_result_t whd_ret; + CHECK_IFP_NULL(ifp); + + whd_ret = whd_wifi_set_iovar_void(ifp, IOVAR_STR_ARP_TABLE_CLEAR); + return whd_ret; +} + +whd_result_t whd_arp_features_get(whd_interface_t ifp, uint32_t *features) +{ + if ( (ifp == NULL) || (features == NULL) ) + { + return WHD_BADARG; + } + + if (whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_ARP_OL, (uint8_t *)features, sizeof(uint32_t) ) != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s() failed to get arp_ol for features\n", __func__) ); + return WHD_IOCTL_FAIL; + } + + return WHD_SUCCESS; +} + +whd_result_t whd_arp_features_set(whd_interface_t ifp, uint32_t features) +{ + CHECK_IFP_NULL(ifp); + + return whd_wifi_set_iovar_buffer(ifp, IOVAR_STR_ARP_OL, (uint8_t *)&features, sizeof(features) ); +} + +whd_result_t whd_arp_features_print(uint32_t features, const char *title) +{ + if (title != NULL) + { + WPRINT_MACRO( ("%s\n", title) ); + } + WPRINT_MACRO( (" features : 0x%x\n", (int)features) ); + WPRINT_MACRO( (" agent_enabled: (0x%x) %s\n", (int)(features & ARP_OL_AGENT), + (features & ARP_OL_AGENT) ? "Enabled" : " disabled") ); + WPRINT_MACRO( (" snoop_enabled: (0x%x) %s\n", (int)(features & ARP_OL_SNOOP), + (features & ARP_OL_SNOOP) ? "Enabled" : " disabled") ); + WPRINT_MACRO( (" host_auto_reply_enabled: (0x%x) %s\n", (int)(features & ARP_OL_HOST_AUTO_REPLY), + (features & ARP_OL_HOST_AUTO_REPLY) ? "Enabled" : " disabled") ); + WPRINT_MACRO( (" peer_auto_reply_enabled: (0x%x) %s\n", (int)(features & ARP_OL_PEER_AUTO_REPLY), + (features & ARP_OL_PEER_AUTO_REPLY) ? "Enabled" : " disabled") ); + + return WHD_SUCCESS; +} + +whd_result_t whd_arp_hostip_list_add(whd_interface_t ifp, uint32_t *host_ipv4_list, uint32_t count) +{ + uint32_t filled = 0; + uint32_t current_ipv4_list[ARP_MULTIHOMING_MAX]; + CHECK_IFP_NULL(ifp); + + whd_result_t whd_ret = WHD_SUCCESS; + if (host_ipv4_list == NULL) + { + WPRINT_WHD_ERROR( ("%s() BAD ARGS ifp:%p host_ipv4_list:%u count %d\n", __func__, ifp, (int)host_ipv4_list, + (int)count) ); + return WHD_BADARG; + } + /* check if unique */ + whd_ret = whd_arp_hostip_list_get(ifp, ARP_MULTIHOMING_MAX, current_ipv4_list, &filled); + if ( (whd_ret == WHD_SUCCESS) && (filled > 0) ) + { + uint32_t curr_index; + uint32_t new_index; + + for (curr_index = 0; curr_index < filled; curr_index++) + { + for (new_index = 0; new_index < count; new_index++) + { + WPRINT_WHD_DEBUG( ("%s() curr:%ld of %ld curr:0x%lx new:%ld of %ld:0x%lx\n", __func__, curr_index, + filled, current_ipv4_list[curr_index], + new_index, count, host_ipv4_list[new_index]) ); + if (current_ipv4_list[curr_index] == host_ipv4_list[new_index]) + { + /* decrement count */ + count--; + if (new_index < count) + { + /* copy next one down */ + WPRINT_WHD_DEBUG( ("move %ld (+1) of %ld \n", new_index, count) ); + host_ipv4_list[new_index] = host_ipv4_list[new_index + 1]; + + } + break; + } + } + } + } + else if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_DEBUG( ("%s() whd_arp_hostip_list_get() failed:%d\n", __func__, (int)whd_ret) ); + } + + if (count > 0) + { + uint32_t new_index; + WPRINT_WHD_DEBUG( ("%s() whd_wifi_set_iovar_buffer( %p, %lx)\n", __func__, host_ipv4_list, count) ); + for (new_index = 0; new_index < count; new_index++) + { + WPRINT_WHD_DEBUG( (" 0x%lx\n", host_ipv4_list[new_index]) ); + } + whd_ret = whd_wifi_set_iovar_buffer(ifp, IOVAR_STR_ARP_HOSTIP, host_ipv4_list, (count * sizeof(uint32_t) ) ); + if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("Failed to set arp_hostip 0x%x error:%d\n", (int)host_ipv4_list[0], (int)whd_ret) ); + } + } + return whd_ret; +} + +whd_result_t whd_arp_hostip_list_add_string(whd_interface_t ifp, const char *ip_addr) +{ + /* convert string to uint32_t */ + uint32_t addr; + CHECK_IFP_NULL(ifp); + + whd_str_to_ip(ip_addr, strlen(ip_addr), &addr); + + return whd_arp_hostip_list_add(ifp, &addr, 1); +} + +whd_result_t whd_arp_hostip_list_clear_id(whd_interface_t ifp, uint32_t ipv4_addr) +{ + whd_result_t whd_ret; + uint32_t filled; + uint32_t host_ipv4_list[ARP_MULTIHOMING_MAX]; + CHECK_IFP_NULL(ifp); + + if (ipv4_addr == 0x00l) + { + return WHD_BADARG; + } + memset(host_ipv4_list, 0x00, sizeof(host_ipv4_list) ); + whd_ret = whd_arp_hostip_list_get(ifp, ARP_MULTIHOMING_MAX, host_ipv4_list, &filled); + if ( (whd_ret == WHD_SUCCESS) && (filled > 0) ) + { + uint32_t index; + + /* clear the list in the WLAN processor */ + whd_ret = whd_wifi_set_iovar_void(ifp, IOVAR_STR_ARP_HOSTIP_CLEAR); + if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%d %s() whd_wifi_set_iovar_void() failed:%d\n", __LINE__, __func__, (int)whd_ret) ); + return whd_ret; + } + + /* remove the one address from the list and re-write arp_hostip list */ + for (index = 0; index < filled; index++) + { + WPRINT_WHD_DEBUG( ("%d %s() drop() 0x%lx == 0x%lx ? %s\n", __LINE__, __func__, host_ipv4_list[index], + ipv4_addr, (host_ipv4_list[index] == ipv4_addr) ? "DROP" : "") ); + if (host_ipv4_list[index] == ipv4_addr) + { + uint32_t drop; + /* drop this one, move rest up */ + for (drop = index; drop < (filled - 1); drop++) + { + host_ipv4_list[drop] = host_ipv4_list[drop + 1]; + } + filled--; + /* IP addresses must be added one at a time */ + for (drop = 0; drop < filled; drop++) + { + whd_ret = whd_arp_hostip_list_add(ifp, &host_ipv4_list[drop], sizeof(uint32_t) ); + } + break; + } + } + } + else if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_DEBUG( ("%s() whd_arp_hostip_list_get() failed:%d\n", __func__, (int)whd_ret) ); + } + return WHD_SUCCESS; +} + +whd_result_t whd_arp_hostip_list_clear_id_string(whd_interface_t ifp, const char *ip_addr) +{ + /* convert string to uint32_t */ + uint32_t addr; + CHECK_IFP_NULL(ifp); + + whd_str_to_ip(ip_addr, strlen(ip_addr), &addr); + + return whd_arp_hostip_list_clear_id(ifp, addr); +} + +whd_result_t whd_arp_hostip_list_clear(whd_interface_t ifp) +{ + CHECK_IFP_NULL(ifp); + return whd_wifi_set_iovar_void(ifp, IOVAR_STR_ARP_HOSTIP_CLEAR); +} + +whd_result_t whd_arp_hostip_list_get(whd_interface_t ifp, uint32_t count, uint32_t *host_ipv4_list, uint32_t *filled) +{ + whd_result_t whd_ret = WHD_SUCCESS; + uint32_t temp[ARP_MULTIHOMING_MAX]; + arp_ol_stats_t arp_stats; /* WL struct, not ours! */ + CHECK_IFP_NULL(ifp); + + if ( (host_ipv4_list == NULL) || (filled == NULL) ) + { + return WHD_BADARG; + } + + /* set up the buffer to retrieve the stats data */ + memset(&arp_stats, 0x00, sizeof(arp_ol_stats_t) ); + whd_ret = whd_wifi_get_iovar_buffer(ifp, "arp_stats", (uint8_t *)&arp_stats, sizeof(arp_ol_stats_t) ); + if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s() failed to get arp_stats\n", __func__) ); + return WHD_IOCTL_FAIL; + } + + *filled = 0; + whd_ret = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_ARP_HOSTIP, (uint8_t *)&temp, sizeof(temp) ); + /* transfer the info */ + if (whd_ret == WHD_SUCCESS) + { + uint32_t index; + for (index = 0; (index < count) && (index < arp_stats.host_ip_entries); index++) + { + /* only IPv4 !!! */ + if (htod32(temp[index]) != 0L) + { + host_ipv4_list[*filled] = temp[index]; + *filled = *filled + 1; + } + } + } + return whd_ret; +} + +whd_result_t whd_arp_stats_clear(whd_interface_t ifp) +{ + whd_result_t whd_ret; + CHECK_IFP_NULL(ifp); + whd_ret = whd_wifi_set_iovar_void(ifp, IOVAR_STR_ARP_STATS_CLEAR); + return whd_ret; +} + +whd_result_t whd_arp_stats_get(whd_interface_t ifp, whd_arp_stats_t *arp_stats) +{ + whd_result_t whd_ret; + uint32_t filled; + static whd_arp_stats_t arp_stats_test; /* read twice to make sure we match */ + CHECK_IFP_NULL(ifp); + + if (arp_stats == NULL) + { + return WHD_BADARG; + } + + /* set up the buffer to retreive the data */ + memcpy(&arp_stats_test, arp_stats, sizeof(whd_arp_stats_t) ); + memset(arp_stats, 0xFF, sizeof(whd_arp_stats_t) ); + + /* read multiple times to make sure we got valid data */ + do + { + /* get them until they match */ + whd_ret = + whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_ARP_STATS, (uint8_t *)&arp_stats->stats, + sizeof(arp_ol_stats_t) ); + if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s() failed to get arp_stats\n", __func__) ); + return WHD_IOCTL_FAIL; + } + /* get all feature info in one call */ + whd_ret = + whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_ARP_OL, (uint8_t *)&arp_stats->features_enabled, + sizeof(arp_stats->features_enabled) ); + if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s() failed to get arp_ol\n", __func__) ); + return WHD_IOCTL_FAIL; + } + whd_ret = whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARP_VERSION, &(arp_stats->version) ); + if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s() failed to get arp_version\n", __func__) ); + return WHD_IOCTL_FAIL; + } + whd_ret = whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARP_PEERAGE, &(arp_stats->peerage) ); + if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s() failed to get arp_peerage\n", __func__) ); + return WHD_IOCTL_FAIL; + } + whd_ret = whd_wifi_get_iovar_value(ifp, IOVAR_STR_ARPOE, &(arp_stats->arpoe) ); + if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s() failed to get some settings\n", __func__) ); + return WHD_IOCTL_FAIL; + } + + /* set endian correctly */ + arp_stats->stats.host_ip_entries = dtoh32(arp_stats->stats.host_ip_entries); + arp_stats->stats.host_ip_overflow = dtoh32(arp_stats->stats.host_ip_overflow); + arp_stats->stats.arp_table_entries = dtoh32(arp_stats->stats.arp_table_entries); + arp_stats->stats.arp_table_overflow = dtoh32(arp_stats->stats.arp_table_overflow); + arp_stats->stats.host_request = dtoh32(arp_stats->stats.host_request); + arp_stats->stats.host_reply = dtoh32(arp_stats->stats.host_reply); + arp_stats->stats.host_service = dtoh32(arp_stats->stats.host_service); + arp_stats->stats.peer_request = dtoh32(arp_stats->stats.peer_request); + arp_stats->stats.peer_request_drop = dtoh32(arp_stats->stats.peer_request_drop); + arp_stats->stats.peer_reply = dtoh32(arp_stats->stats.peer_reply); + arp_stats->stats.peer_reply_drop = dtoh32(arp_stats->stats.peer_reply_drop); + arp_stats->stats.peer_service = dtoh32(arp_stats->stats.peer_service); + + whd_ret = whd_arp_hostip_list_get(ifp, ARP_MULTIHOMING_MAX, arp_stats->host_ip_list, &filled); + if (whd_ret != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s() failed to get host_ip_list\n", __func__) ); + return WHD_IOCTL_FAIL; + } + + if (memcmp(&arp_stats_test, arp_stats, sizeof(whd_arp_stats_t) ) == 0) + { + break; + } + + memcpy(&arp_stats_test, arp_stats, sizeof(whd_arp_stats_t) ); + } while (1); + + return whd_ret; +} + +whd_result_t whd_arp_stats_print(whd_arp_stats_t *arp_stats, const char *title) +{ + uint32_t index; + + if (arp_stats == NULL) + { + return WHD_BADARG; + } + + if (title != NULL) + { + WPRINT_MACRO( ("%s\n", title) ); + } + WPRINT_MACRO( (" version: 0x%lx\n", (unsigned long int)arp_stats->version) ); + WPRINT_MACRO( (" host_ip_entries: %d\n", (int)arp_stats->stats.host_ip_entries) ); + WPRINT_MACRO( (" host_ip_overflow: %d\n", (int)arp_stats->stats.host_ip_overflow) ); + WPRINT_MACRO( (" arp_table_entries: %d\n", (int)arp_stats->stats.arp_table_entries) ); + WPRINT_MACRO( (" arp_table_overflow: %d\n", (int)arp_stats->stats.arp_table_overflow) ); + WPRINT_MACRO( (" host_request: %d\n", (int)arp_stats->stats.host_request) ); + WPRINT_MACRO( (" host_reply: %d\n", (int)arp_stats->stats.host_reply) ); + WPRINT_MACRO( (" host_service: %d\n", (int)arp_stats->stats.host_service) ); + WPRINT_MACRO( (" peer_request: %d\n", (int)arp_stats->stats.peer_request) ); + WPRINT_MACRO( (" peer_request_drop: %d\n", (int)arp_stats->stats.peer_request_drop) ); + WPRINT_MACRO( (" peer_reply: %d\n", (int)arp_stats->stats.peer_reply) ); + WPRINT_MACRO( (" peer_reply_drop: %d\n", (int)arp_stats->stats.peer_reply_drop) ); + WPRINT_MACRO( (" peer_service: %d\n", (int)arp_stats->stats.peer_service) ); + WPRINT_MACRO( (" peerage: %d\n", (int)arp_stats->peerage) ); + WPRINT_MACRO( (" arpoe: %d %s\n", (int)arp_stats->arpoe, + (arp_stats->arpoe != 0) ? "Enabled" : " disabled") ); + + whd_arp_features_print(arp_stats->features_enabled, NULL); + + if (arp_stats->stats.host_ip_entries > 0) + { + WPRINT_MACRO( ("WLAN Device Host IP entries\n") ); + for (index = 0; index < arp_stats->stats.host_ip_entries; index++) + { + uint32_t ipv4_addr = arp_stats->host_ip_list[index]; + char ipv4_string[32]; + memset(ipv4_string, 0x00, sizeof(ipv4_string) ); + whd_ip4_to_string(&ipv4_addr, ipv4_string); + WPRINT_MACRO( (" %d of %d IPV4: 0x%x %s\n", (int)index, (int)arp_stats->stats.host_ip_entries, + (int)arp_stats->host_ip_list[index], ipv4_string) ); + } + } + return WHD_SUCCESS; +} + +whd_result_t +whd_wifi_toggle_packet_filter(whd_interface_t ifp, uint8_t filter_id, whd_bool_t enable) +{ + whd_buffer_t buffer; + whd_driver_t whd_driver; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + wl_pkt_filter_enable_t *data = (wl_pkt_filter_enable_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, + sizeof(wl_pkt_filter_enable_t), + IOVAR_STR_PKT_FILTER_ENABLE); + CHECK_IOCTL_BUFFER(data); + data->id = (uint32_t)filter_id; + data->enable = (uint32_t)enable; + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); +} + +whd_result_t +whd_pf_enable_packet_filter(whd_interface_t ifp, uint8_t filter_id) +{ + return whd_wifi_toggle_packet_filter(ifp, filter_id, WHD_TRUE); +} + +whd_result_t +whd_pf_disable_packet_filter(whd_interface_t ifp, uint8_t filter_id) +{ + return whd_wifi_toggle_packet_filter(ifp, filter_id, WHD_FALSE); +} + +whd_result_t +whd_pf_add_packet_filter(whd_interface_t ifp, const whd_packet_filter_t *settings) +{ + wl_pkt_filter_t *packet_filter; + whd_driver_t whd_driver; + whd_buffer_t buffer; + uint32_t buffer_length = + (uint32_t)( (2 * (uint32_t)settings->mask_size) + WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN ); + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + packet_filter = (wl_pkt_filter_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)buffer_length, + IOVAR_STR_PKT_FILTER_ADD); + CHECK_IOCTL_BUFFER(packet_filter); + + /* Copy filter entries */ + packet_filter->id = settings->id; + packet_filter->type = 0; + packet_filter->negate_match = settings->rule; + packet_filter->u.pattern.offset = (uint32_t)settings->offset; + packet_filter->u.pattern.size_bytes = settings->mask_size; + + /* Copy mask */ + memcpy(packet_filter->u.pattern.mask_and_pattern, settings->mask, settings->mask_size); + + /* Copy filter pattern */ + memcpy(packet_filter->u.pattern.mask_and_pattern + settings->mask_size, settings->pattern, settings->mask_size); + + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); +} + +whd_result_t +whd_pf_remove_packet_filter(whd_interface_t ifp, uint8_t filter_id) +{ + whd_buffer_t buffer; + whd_driver_t whd_driver; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + uint32_t *data = (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(uint32_t), + IOVAR_STR_PKT_FILTER_DELETE); + CHECK_IOCTL_BUFFER(data); + *data = (uint32_t)filter_id; + RETURN_WITH_ASSERT(whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL) ); +} + +whd_result_t +whd_pf_get_packet_filter_stats(whd_interface_t ifp, uint8_t filter_id, whd_pkt_filter_stats_t *stats) +{ + whd_buffer_t buffer; + whd_buffer_t response; + whd_driver_t whd_driver; + uint8_t *pdata; + + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + uint32_t *data = + (uint32_t *)whd_cdc_get_iovar_buffer(whd_driver, &buffer, sizeof(uint32_t) + sizeof(wl_pkt_filter_stats_t), + IOVAR_STR_PKT_FILTER_STATS); + CHECK_IOCTL_BUFFER(data); + + memset(data, 0, sizeof(uint32_t) + sizeof(wl_pkt_filter_stats_t) ); + *data = (uint32_t)filter_id; + + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy( (char *)stats, (char *)pdata, (sizeof(wl_pkt_filter_stats_t) ) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_TX) ); + + return WHD_SUCCESS; +} + +whd_result_t +whd_wifi_clear_packet_filter_stats(whd_interface_t ifp, uint32_t filter_id) +{ + RETURN_WITH_ASSERT(whd_wifi_set_iovar_value(ifp, IOVAR_STR_PKT_FILTER_CLEAR_STATS, (uint32_t)filter_id) ); +} + +whd_result_t +whd_pf_get_packet_filter_mask_and_pattern(whd_interface_t ifp, uint8_t filter_id, uint32_t max_size, uint8_t *mask, + uint8_t *pattern, uint32_t *size_out) +{ + whd_bool_t enabled_list; + whd_driver_t whd_driver; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + for (enabled_list = WHD_FALSE; enabled_list <= WHD_TRUE; enabled_list++) + { + + whd_buffer_t buffer; + whd_buffer_t response; + uint32_t *data; + wl_pkt_filter_list_t *filter_list; + wl_pkt_filter_t *filter_ptr; + uint32_t i; + wl_pkt_filter_t *in_filter; + + data = whd_cdc_get_iovar_buffer(whd_driver, &buffer, PACKET_FILTER_LIST_BUFFER_MAX_LEN, + IOVAR_STR_PKT_FILTER_LIST); + CHECK_IOCTL_BUFFER(data); + *data = (uint32_t)enabled_list; + + CHECK_RETURN(whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response) ); + + filter_list = (wl_pkt_filter_list_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + filter_ptr = filter_list->filter; + for (i = 0; i < filter_list->num; i++) + { + in_filter = filter_ptr; + + if (in_filter->id == filter_id) + { + *size_out = MIN_OF(in_filter->u.pattern.size_bytes, max_size); + memcpy (mask, in_filter->u.pattern.mask_and_pattern, *size_out); + memcpy (pattern, in_filter->u.pattern.mask_and_pattern + in_filter->u.pattern.size_bytes, *size_out); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_RX) ); + if (*size_out < in_filter->u.pattern.size_bytes) + { + return WHD_PARTIAL_RESULTS; + } + return WHD_SUCCESS; + } + + /* Update WL filter pointer */ + filter_ptr = + (wl_pkt_filter_t *)( (char *)filter_ptr + + (WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * + in_filter->u.pattern.size_bytes) ); + + /* WLAN returns word-aligned filter list */ + filter_ptr = (wl_pkt_filter_t *)ROUND_UP( (unsigned long)filter_ptr, 4 ); + } + } + return WHD_FILTER_NOT_FOUND; +} + +/* Set/Get TKO retry & interval parameters */ +whd_result_t +whd_tko_param(whd_interface_t ifp, whd_tko_retry_t *whd_retry, uint8_t set) +{ + uint32_t len = 0; + uint8_t *data = NULL; + wl_tko_t *tko = NULL; + whd_buffer_t buffer; + whd_buffer_t response; + wl_tko_param_t *wl_param_p = NULL; + whd_result_t result = WHD_SUCCESS; + whd_driver_t whd_driver; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + len = (int)(WHD_PAYLOAD_MTU - strlen(IOVAR_STR_TKO) - 1); + data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO); + if (data == NULL) + { + WPRINT_WHD_ERROR( ("%s: Failed to get iovar buf\n", __func__) ); + return WHD_IOCTL_FAIL; + } + + tko = (wl_tko_t *)data; + tko->subcmd_id = WL_TKO_SUBCMD_PARAM; + tko->len = TKO_DATA_OFFSET; + wl_param_p = (wl_tko_param_t *)tko->data; + tko->len += sizeof(wl_tko_param_t); + + tko->subcmd_id = htod16(tko->subcmd_id); + tko->len = htod16(tko->len); + + if (set) + { + /* SET parameters */ + + /* Set defaults if needed */ + wl_param_p->interval = whd_retry->tko_interval == + 0 ? TCP_KEEPALIVE_OFFLOAD_INTERVAL_SEC : whd_retry->tko_interval; + wl_param_p->retry_count = whd_retry->tko_retry_count == + 0 ? TCP_KEEPALIVE_OFFLOAD_RETRY_COUNT : whd_retry->tko_retry_count; + wl_param_p->retry_interval = whd_retry->tko_retry_interval == + 0 ? TCP_KEEPALIVE_OFFLOAD_RETRY_INTERVAL_SEC : whd_retry->tko_retry_interval; + + result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: Cannot set params\n", __func__) ); + } + } + else + { + /* GET paramters */ + wl_tko_param_t tko_param_real; + + result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response); + if (result == WHD_SUCCESS) + { + wl_param_p = &tko_param_real; + memcpy( (char *)wl_param_p, + (char *)whd_buffer_get_current_piece_data_pointer(whd_driver, response) + TKO_DATA_OFFSET, + (sizeof(wl_tko_param_t) ) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_TX) ); + + /* Copy items from wl level struct to higher level struct */ + whd_retry->tko_interval = wl_param_p->interval; + whd_retry->tko_retry_interval = wl_param_p->retry_interval; + whd_retry->tko_retry_count = wl_param_p->retry_count; + } + else + { + WPRINT_WHD_ERROR( ("%s: Cannot get params.\n", __func__) ); + } + } + + return result; +} + +/* Query Status */ +whd_result_t +whd_tko_get_status(whd_interface_t ifp, whd_tko_status_t *whd_status) +{ + whd_result_t result = WHD_SUCCESS; + uint32_t len = 0; + uint8_t *data = NULL; + wl_tko_t *tko = NULL; + whd_buffer_t buffer; + whd_buffer_t response; + whd_driver_t whd_driver; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + /* Get a buffer */ + len = (int)(100 - strlen(IOVAR_STR_TKO) - 1); + data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO); + CHECK_IOCTL_BUFFER(data); + + /* Fill buffer with request */ + tko = (wl_tko_t *)data; + tko->subcmd_id = WL_TKO_SUBCMD_STATUS; + tko->len = TKO_DATA_OFFSET; + + tko->len += sizeof(wl_tko_status_t); + + tko->subcmd_id = htod16(tko->subcmd_id); + tko->len = htod16(tko->len); + + /* Make request and get result */ + result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: send iovar failed\n", __func__) ); + return result; + } + + /* Parse result */ + tko = (wl_tko_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + if (tko) + { + len = htod16(tko->len); + + if (len >= MAX_TKO_CONN + 1) /* MAX_TKO status's + 1 for the count */ + { + memcpy(whd_status, tko->data, MAX_TKO_CONN + 1); + } + } + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_TX) ); + return result; +} + +/* Query FW for number tko max tcp connections */ +whd_result_t +whd_tko_max_assoc(whd_interface_t ifp, uint8_t *max) +{ + uint32_t len = 0; + uint8_t *data = NULL; + uint8_t *pdata = NULL; + wl_tko_t *tko = NULL; + whd_buffer_t buffer; + whd_buffer_t response; + wl_tko_max_tcp_t *tko_max_tcp = NULL; + wl_tko_max_tcp_t tcp_result; + whd_driver_t whd_driver; + whd_result_t result = WHD_SUCCESS; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + len = (int)(100 - strlen(IOVAR_STR_TKO) - 1); + data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO); + CHECK_IOCTL_BUFFER(data); + + tko = (wl_tko_t *)data; + + tko->subcmd_id = WL_TKO_SUBCMD_MAX_TCP; + tko->len = TKO_DATA_OFFSET; + + tko_max_tcp = (wl_tko_max_tcp_t *)tko->data; + tko->len += sizeof(wl_tko_max_tcp_t); + + tko->subcmd_id = htod16(tko->subcmd_id); + tko->len = htod16(tko->len); + + result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: send iovar failed\n", __func__) ); + return result; + } + tko_max_tcp = &tcp_result; + pdata = whd_buffer_get_current_piece_data_pointer(whd_driver, response); + CHECK_PACKET_NULL(pdata, WHD_NO_REGISTER_FUNCTION_POINTER); + memcpy( (char *)tko_max_tcp, + (char *)pdata + TKO_DATA_OFFSET, + (sizeof(wl_tko_max_tcp_t) ) ); + CHECK_RETURN(whd_buffer_release(whd_driver, response, WHD_NETWORK_TX) ); + + *max = tko_max_tcp->max; + return WHD_SUCCESS; +} + +/* Exercise GET of wl_tko_connect_t IOVAR */ +/* Given a index, return info about that index */ +whd_result_t +whd_tko_get_FW_connect(whd_interface_t ifp, uint8_t index, whd_tko_connect_t *whd_connect, uint16_t buflen) +{ + uint32_t len = 0; + uint8_t *data = NULL; + wl_tko_t *tko = NULL; + wl_tko_connect_t *connect = NULL; + whd_result_t result = WHD_SUCCESS; + whd_buffer_t response; + whd_buffer_t buffer; + whd_driver_t whd_driver; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + CHECK_DRIVER_NULL(whd_driver); + + len = (int)(WHD_PAYLOAD_MTU - strlen(IOVAR_STR_TKO) - 1); + data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO); + CHECK_IOCTL_BUFFER(data); + + tko = (wl_tko_t *)data; + + tko->subcmd_id = WL_TKO_SUBCMD_CONNECT; + tko->len = offsetof(wl_tko_t, data); + connect = (wl_tko_connect_t *)tko->data; + connect->index = index; + + tko->subcmd_id = htod16(tko->subcmd_id); + tko->len = htod16(tko->len); + + result = whd_cdc_send_iovar(ifp, CDC_GET, buffer, &response); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: send iovar failed\n", __func__) ); + return result; + } + tko = (wl_tko_t *)whd_buffer_get_current_piece_data_pointer(whd_driver, response); + tko->subcmd_id = dtoh16(tko->subcmd_id); + tko->len = dtoh16(tko->len); + + if (tko->subcmd_id != WL_TKO_SUBCMD_CONNECT) + { + WPRINT_WHD_ERROR( ("%s: IOVAR returned garbage!\n", __func__) ); + return WHD_BADARG; + } + connect = (wl_tko_connect_t *)tko->data; + if (tko->len >= sizeof(*connect) ) + { + connect->local_port = dtoh16(connect->local_port); + connect->remote_port = dtoh16(connect->remote_port); + connect->local_seq = dtoh32(connect->local_seq); + connect->remote_seq = dtoh32(connect->remote_seq); + if (connect->ip_addr_type != 0) + { + WPRINT_WHD_ERROR( ("%s: Address type not IPV4\n", __func__) ); + return WHD_BADARG; + } + if (connect->ip_addr_type == 0) + { + /* IPv4 */ + uint16_t mylen; + mylen = sizeof(wl_tko_connect_t) + (2 * IPV4_ADDR_LEN) + connect->request_len + connect->response_len; + if (buflen < mylen) + { + WPRINT_WHD_ERROR( ("%s: Buf len (%d) too small , need %d\n", __func__, buflen, mylen) ); + return WHD_BADARG; + } + + /* + * Assumes whd_tko_connect_t and wl_tko_connect_t are the same. + * If/when they become different (due to different FW versions, etc) than + * this may have to be copied field by field instead. + */ + memcpy(whd_connect, connect, MIN_OF(mylen, buflen) ); + } + } + return WHD_SUCCESS; +} + +whd_result_t +whd_tko_toggle(whd_interface_t ifp, whd_bool_t enable) +{ + uint32_t len = 0; + uint8_t *data = NULL; + wl_tko_t *tko = NULL; + whd_buffer_t buffer; + wl_tko_enable_t *tko_enable = NULL; + whd_driver_t whd_driver; + whd_result_t result; + CHECK_IFP_NULL(ifp); + + whd_driver = ifp->whd_driver; + + + + len = (int)(WHD_PAYLOAD_MTU - strlen(IOVAR_STR_TKO) - 1); + data = (uint8_t * )whd_cdc_get_iovar_buffer(whd_driver, &buffer, (uint16_t)len, IOVAR_STR_TKO); + CHECK_IOCTL_BUFFER(data); + + tko = (wl_tko_t *)data; + + tko->subcmd_id = WL_TKO_SUBCMD_ENABLE; + tko->len = TKO_DATA_OFFSET; + + tko_enable = (wl_tko_enable_t *)tko->data; + tko_enable->enable = enable; + + tko->len += sizeof(wl_tko_enable_t); + + tko->subcmd_id = htod16(tko->subcmd_id); + tko->len = htod16(tko->len); + + /* invoke SET iovar */ + result = whd_cdc_send_iovar(ifp, CDC_SET, buffer, NULL); + if (result != WHD_SUCCESS) + { + WPRINT_WHD_ERROR( ("%s: tko %s FAILED\n", __func__, (enable == WHD_TRUE ? "enable" : "disable") ) ); + return result; + } + else + { + WPRINT_WHD_ERROR( ("%s: Successfully %s\n", __func__, (enable == WHD_TRUE ? "enabled" : "disabled") ) ); + } + return result; +} diff --git a/wifi-host-driver/WiFi_Host_Driver/src/whd_wifi_p2p.c b/wifi-host-driver/WiFi_Host_Driver/src/whd_wifi_p2p.c new file mode 100644 index 00000000..d2c81eef --- /dev/null +++ b/wifi-host-driver/WiFi_Host_Driver/src/whd_wifi_p2p.c @@ -0,0 +1,44 @@ +/* + * Copyright 2022, Cypress Semiconductor Corporation (an Infineon company) + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "whd_ap.h" +#include "whd_chip_constants.h" +#include "whd_debug.h" +#include "whd_events_int.h" +#include "whd_sdpcm.h" +#include "whd_thread_internal.h" +#include "whd_utils.h" +#include "whd_wifi_api.h" +#include "whd_wifi_p2p.h" + + +/****************************************************** +* @cond Constants +******************************************************/ + +whd_bool_t whd_wifi_p2p_is_go_up(whd_driver_t whd_driver) +{ + return whd_driver->internal_info.whd_wifi_p2p_go_is_up; +} + +void whd_wifi_p2p_set_go_is_up(whd_driver_t whd_driver, whd_bool_t is_up) +{ + if (whd_driver->internal_info.whd_wifi_p2p_go_is_up != is_up) + { + whd_driver->internal_info.whd_wifi_p2p_go_is_up = is_up; + } +} diff --git a/wifi-host-driver/generated_mac_address.txt b/wifi-host-driver/generated_mac_address.txt new file mode 100644 index 00000000..7d25f87d --- /dev/null +++ b/wifi-host-driver/generated_mac_address.txt @@ -0,0 +1,9 @@ +/* + * This file is used to set the MAC address in NVRAM. + * The MAC address of the Wi-Fi device may be configured in OTP and/or in NVRAM. + * If both OTP and NVRAM contains the MAC address then OTP programmed MAC address will be used. + * PSOC boards are usually programmed with OTP MAC address. + * MAC address is printed during WHD power up + */ + +#define NVRAM_GENERATED_MAC_ADDRESS "macaddr=00:A0:50:f8:70:8f" diff --git a/wifi-host-driver/version.xml b/wifi-host-driver/version.xml new file mode 100644 index 00000000..607b63d2 --- /dev/null +++ b/wifi-host-driver/version.xml @@ -0,0 +1 @@ +2.5.0.15307 diff --git a/zephyr/blobs/license.txt b/zephyr/blobs/license.txt new file mode 100644 index 00000000..01d5e585 --- /dev/null +++ b/zephyr/blobs/license.txt @@ -0,0 +1,211 @@ +CYPRESS (AN INFINEON COMPANY) END USER LICENSE AGREEMENT + +PLEASE READ THIS END USER LICENSE AGREEMENT ("Agreement") CAREFULLY BEFORE +DOWNLOADING, INSTALLING, COPYING, OR USING THIS SOFTWARE AND ACCOMPANYING +DOCUMENTATION. BY DOWNLOADING, INSTALLING, COPYING OR USING THE SOFTWARE, +YOU ARE AGREEING TO BE BOUND BY THIS AGREEMENT. IF YOU DO NOT AGREE TO ALL +OF THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN AND DO NOT USE THE SOFTWARE. +IF YOU HAVE PURCHASED THIS LICENSE TO THE SOFTWARE, YOUR RIGHT TO RETURN THE +SOFTWARE EXPIRES 30 DAYS AFTER YOUR PURCHASE AND APPLIES ONLY TO THE ORIGINAL +PURCHASER. + +1. Definitions. + + "Software" means this software and any accompanying documentation, + including any upgrades, updates, bug fixes or modified versions provided + to you by Cypress. + + "Source Code" means software in human-readable form. + + "Binary Code" means the software in binary code form such as object code or + an executable. + + "Development Tools" means software that is intended to be installed on a + personal computer and used to create programming code for Firmware, + Drivers, or Host Applications. Examples of Development Tools are + Cypress's PSoC Creator software, Cypress's AIROC SDKs, and Cypress's + ModusToolbox software. + + "Firmware" means software that executes on a Cypress hardware product. + + "Driver" means software that enables the use of a Cypress hardware product + on a particular host operating system such as GNU/Linux, Windows, MacOS, + Android, and iOS. + + "Host Application" means software that executes on a device other than a + Cypress hardware product in order to program, control, or communicate + with a Cypress hardware product. + + "inf File" means a hardware setup information file (.inf file) created by + the Software to allow a Microsoft Windows operating system to install + the driver for a Cypress hardware product. + +2. License. Subject to the terms and conditions of this Agreement, Cypress +Semiconductor Corporation ("Cypress") and its suppliers grant to you a +non-exclusive, non-transferable license under their copyright rights: + + a. to use the Development Tools in object code form solely for the purpose + of creating Firmware, Drivers, Host Applications, and inf Files for + Cypress hardware products; and + + b. (i) if provided in Source Code form, to copy, modify, and compile the + Firmware Source Code to create Firmware for execution on a Cypress + hardware product, and + (ii) to distribute Firmware in binary code form only, only when + installed onto a Cypress hardware product; and + + c. (i) if provided in Source Code form, to copy, modify, and compile the + Driver Source Code to create one or more Drivers to enable the use + of a Cypress hardware product on a particular host operating + system, and + (ii) to distribute the Driver, in binary code form only, only when + installed on a device that includes the Cypress hardware product + that the Driver is intended to enable; and + + d. (i) if provided in Source Code form, to copy, modify, and compile the + Host Application Source Code to create one or more Host + Applications to program, control, or communicate with a Cypress + hardware product, and + (ii) to distribute Host Applications, in binary code form only, only + when installed on a device that includes a Cypress hardware product + that the Host Application is intended to program, control, or + communicate with; and + + e. to freely distribute any inf File. + +Any distribution of Software permitted under this Agreement must be made +pursuant to your standard end user license agreement used for your proprietary +(closed source) software products, such end user license agreement to include, +at a minimum, provisions limiting your licensors' liability and prohibiting +reverse engineering of the Software, consistent with such provisions in this +Agreement. + +3. Free and Open Source Software. Portions of the Software may be licensed +under free and/or open source licenses such as the GNU General Public License +or other licenses from third parties ("Third Party Software"). Third Party +Software is subject to the applicable license agreement and not this +Agreement. If you are entitled to receive the source code from Cypress for +any Third Party Software included with the Software, either the source code +will be included with the Software or you may obtain the source code at no +charge from +. +The applicable license terms will accompany each source code package. To +review the license terms applicable to any Third Party Software for which +Cypress is not required to provide you with source code, please see the +Software's installation directory on your computer. + +4. Proprietary Rights; Ownership. The Software, including all intellectual +property rights therein, is and will remain the sole and exclusive property of +Cypress or its suppliers. Cypress retains ownership of the Source Code and +any compiled version thereof. Subject to Cypress' ownership of the underlying +Software (including Source Code), you retain ownership of any modifications +you make to the Source Code. You agree not to remove any Cypress copyright or +other notices from the Source Code and any modifications thereof. You agree +to keep the Source Code confidential. Any reproduction, modification, +translation, compilation, or representation of the Source Code except as +permitted in Section 2 ("License") is prohibited without the express written +permission of Cypress. Except as otherwise expressly provided in this +Agreement, you may not: + (i) modify, adapt, or create derivative works based upon the Software; + (ii) copy the Software; + (iii) except and only to the extent explicitly permitted by applicable + law despite this limitation, decompile, translate, reverse engineer, + disassemble or otherwise reduce the Software to human-readable form; + or + (iv) use the Software or any sample code other than for the Purpose. +You hereby covenant that you will not assert any claim that the Software, or +derivative works thereof created by or for Cypress, infringe any intellectual +property right owned or controlled by you + +5. No Support. Cypress may, but is not required to, provide technical support +for the Software. + +6. Term and Termination. This Agreement is effective until terminated, and +either party may terminate this Agreement at any time with or without cause. +This Agreement and your license rights under this Agreement will terminate +immediately without notice from Cypress if you fail to comply with any +provision of this Agreement. Upon termination, you must destroy all copies of +Software in your possession or control. The following paragraphs shall +survive any termination of this Agreement: "Free and Open Source Software," +"Proprietary Rights; Ownership," "Compliance With Law," "Disclaimer," +"Limitation of Liability," and "General." + +7. Compliance With Law. Each party agrees to comply with all applicable laws, +rules and regulations in connection with its activities under this Agreement. +Without limiting the foregoing, the Software may be subject to export control +laws and regulations of the United States and other countries. You agree to +comply strictly with all such laws and regulations and acknowledge that you +have the responsibility to obtain licenses to export, re-export, or import the +Software. + +8. Disclaimer. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, CYPRESS +MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THE +SOFTWARE, INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress +reserves the right to make changes to the Software without notice. Cypress +does not assume any liability arising out of the application or use of +Software or any product or circuit described in the Software. It is the +responsibility of the user of the Software to properly design, program, and +test the functionality and safety of any application made of the Software and +any resulting product. Cypress does not authorize its Software or products +for use in any products where a malfunction or failure of the Software or +Cypress product may reasonably be expected to result in significant property +damage, injury or death ("High Risk Product"). If you include any Software or +Cypress product in a High Risk Product, you assume all risk of such use and +agree to indemnify Cypress and its suppliers against all liability. No +computing device can be absolutely secure. Therefore, despite security +measures implemented in Cypress hardware or software products, Cypress does +not assume any liability arising out of any security breach, such as +unauthorized access to or use of a Cypress product. + +9. Limitation of Liability. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE +LAW, IN NO EVENT WILL CYPRESS OR ITS SUPPLIERS, RESELLERS, OR DISTRIBUTORS BE +LIABLE FOR ANY LOST REVENUE, PROFIT, OR DATA, OR FOR SPECIAL, INDIRECT, +CONSEQUENTIAL, INCIDENTAL, OR PUNITIVE DAMAGES HOWEVER CAUSED AND REGARDLESS +OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO THE USE OF OR +INABILITY TO USE THE SOFTWARE EVEN IF CYPRESS OR ITS SUPPLIERS, RESELLERS, OR +DISTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN NO +EVENT SHALL CYPRESS' OR ITS SUPPLIERS', RESELLERS', OR DISTRIBUTORS' TOTAL +LIABILITY TO YOU, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), OR +OTHERWISE, EXCEED THE GREATER OF US$500 OR THE PRICE PAID BY YOU FOR THE +SOFTWARE. THE FOREGOING LIMITATIONS SHALL APPLY EVEN IF THE ABOVE-STATED +WARRANTY FAILS OF ITS ESSENTIAL PURPOSE. BECAUSE SOME STATES OR JURISDICTIONS +DO NOT ALLOW LIMITATION OR EXCLUSION OF CONSEQUENTIAL OR INCIDENTAL DAMAGES, +ALL OR PORTIONS OF THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + +10. Restricted Rights. The Software is commercial computer software as that +term is described in 48 C.F.R. 252.227-7014(a)(1). If the Software is being +acquired by or on behalf of the U.S. Government or by a U.S. Government prime +contractor or subcontractor (at any tier), then the Government's rights in +Software shall be only those set forth in this Agreement. + +11. Personal Information. You agree that information you provide through your +registration on Cypress IoT Community Forum or other Cypress websites, +including contact information or other personal information, may be collected +and used by Cypress consistent with its Data Privacy Policy +(https://www.infineon.com/cms/en/about-infineon/privacy-policy/), as updated +or revised from time to time, and may be provided to its third party sales +representatives, distributors and other entities conducting sales activities +for Cypress for sales-related and other business purposes. + +12. General. This Agreement will bind and inure to the benefit of each +party's successors and assigns, provided that you may not assign or transfer +this Agreement, in whole or in part, without Cypress' written consent. This +Agreement shall be governed by and construed in accordance with the laws of +the State of California, United States of America, as if performed wholly +within the state and without giving effect to the principles of conflict of +law. The parties consent to personal and exclusive jurisdiction of and venue +in, the state and federal courts within Santa Clara County, California; +provided however, that nothing in this Agreement will limit Cypress' right to +bring legal action in any venue in order to protect or enforce its +intellectual property rights. No failure of either party to exercise or +enforce any of its rights under this Agreement will act as a waiver of such +rights. If any portion of this Agreement is found to be void or +unenforceable, the remaining provisions of this Agreement shall remain in full +force and effect. This Agreement is the complete and exclusive agreement +between the parties with respect to the subject matter hereof, superseding and +replacing any and all prior agreements, communications, and understandings +(both written and oral) regarding such subject matter. Any notice to Cypress +will be deemed effective when actually received and must be sent to Cypress +Semiconductor Corporation, ATTN: Chief Legal Officer, 198 Champion Court, San +Jose, CA 95134 USA. diff --git a/zephyr/module.yml b/zephyr/module.yml index 8a017fab..6ef924e5 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -37,3 +37,239 @@ blobs: url: https://github.com/Infineon/cat1cm0p/raw/release-v1.0.0/COMPONENT_CAT1A/COMPONENT_CM0P_SLEEP/psoc6_04_cm0p_sleep.bin description: "PSoC 6 Cortex M0+ DeepSleep prebuilt image (CM0P_SLEEP)" doc-url: https://github.com/Infineon/cat1cm0p + +#wifi-host-driver (firmware and clm blobs) + #CYW43012 Device + #firmware + - path: img/whd/resources/firmware/COMPONENT_43012/43012C0.bin + sha256: e2bbc8901bf0ac6cfd1442f15d1fecc1bc176915a88b10fe1399e1ae29c0b642 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/43012C0.bin + description: "Wi-Fi Firmware for CYW43012 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #firmware (mfgtest) + - path: img/whd/resources/firmware/COMPONENT_43012/43012C0-mfgtest.bin + sha256: ec6e23bb1e2a73c9bc6de4ec29900bafa36ba35f4bfc676186275cd333ef1793 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/43012C0-mfgtest.bin + description: "Wi-Fi Firmware (mfgtest) for CYW43012 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm + - path: img/whd/resources/clm/COMPONENT_43012/43012C0.clm_blob + sha256: 2168a39bb68452558c96883be66301655663a41aa328ad92cb9b3795e65d835e + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_43012/43012C0.clm_blob + description: "Wi-Fi CLM for CYW43012 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm (mfgtest) + - path: img/whd/resources/clm/COMPONENT_43012/43012C0-mfgtest.clm_blob + sha256: ffde6dfa33a4af23ac227dfead536f49ef2cd6b147d2778f07cb86bab597d95a + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_43012/43012C0-mfgtest.clm_blob + description: "Wi-Fi CLM (mfgtest) for CYW43012 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + + #CYW4343W Device + #firmware + - path: img/whd/resources/firmware/COMPONENT_4343W/4343WA1.bin + sha256: 672f94b68bc19236c75c395f5d1be7524635c9d812f6f74585996921290bbcd1 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/4343WA1.bin + description: "Wi-Fi Firmware for CYW4343W (mfgtest) Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #firmware (mfgtest) + - path: img/whd/resources/firmware/COMPONENT_4343W/4343WA1-mfgtest.bin + sha256: 00b5e0c87571b7d259c6168fb8e37c312cd011a8465a071776bef35c2a0c3cb1 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/4343WA1-mfgtest.bin + description: "Wi-Fi Firmware for CYW4343W Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm + - path: img/whd/resources/clm/COMPONENT_4343W/4343WA1.clm_blob + sha256: 4a2b14f19bfee84b403ef04e8ca3483e298cb4aaab1013ecc5fb80379901b8d3 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/4343WA1.clm_blob + description: "Wi-Fi CLM for CYW4343W Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm (mfgtest) + - path: img/whd/resources/clm/COMPONENT_4343W/4343WA1-mfgtest.clm_blob + sha256: 51e5ff506775a171d28734c79510d57a05f1cd530294cff31b6ca9e4fdf4fc04 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/4343WA1-mfgtest.clm_blob + description: "Wi-Fi CLM for CYW4343W (mfgtest) Device" + doc-url: https://github.com/Infineon/wifi-host-driver + + #CYW43438 Device + #firmware + - path: img/whd/resources/firmware/COMPONENT_43438/43438A1.bin + sha256: f85e3feed55c429cf2fc88316dba472647da25622bac6c07ab63807fa0ad875e + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/43438A1.bin + description: "Wi-Fi Firmware for CYW43438 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #firmware (mfgtest) + - path: img/whd/resources/firmware/COMPONENT_43438/43438A1-mfgtest.bin + sha256: e54f2246b6b095621fb12d46ac355b854bf637f9bb8829195d622b7dae6a74f8 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/43438A1-mfgtest.bin + description: "Wi-Fi Firmware (mfgtest) for CYW43438 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm + - path: img/whd/resources/clm/COMPONENT_43438/43438A1.clm_blob + sha256: e10611ba6721b8639426d4491a06c53587b56a5ea20f3f4b30ccd8866e26695b + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_43438/43438A1.clm_blob + description: "Wi-Fi CLM for CYW43438 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm (mfgtest) + - path: img/whd/resources/clm/COMPONENT_43438/43438A1-mfgtest.clm_blob + sha256: dea0ff2b093ec5adaafafd394bff39141c7435088da3f1bc32e1b3327eb30e9d + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_43438/43438A1-mfgtest.clm_blob + description: "Wi-Fi CLM for CYW43438(mfgtest) Device" + doc-url: https://github.com/Infineon/wifi-host-driver + + #CYW43439 Device + #firmware + - path: img/whd/resources/firmware/COMPONENT_43439/43439a0.bin + sha256: 651092a60c1a909eab8a90455f6fede608a8b6caca32e3a6156d376a67fafd02 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/43439a0.bin + description: "Wi-Fi Firmware for CYW43439 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #firmware (mfgtest) + - path: img/whd/resources/firmware/COMPONENT_43439/43439a0-mfgtest.bin + sha256: fc8bf8d3054b3ca1b261b20134020652737d55bd453477deda31c5c04bb6fc3e + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/43439a0-mfgtest.bin + description: "Wi-Fi Firmware for CYW43439 (mfgtest) Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm + - path: img/whd/resources/clm/COMPONENT_43439/43439A0.clm_blob + sha256: 60be731f3c147b28e21ea89389e29e34d1c01a09509edf285334ec1bcb1da38a + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_43439/43439A0.clm_blob + description: "Wi-Fi CLM for CYW43439 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm (mfgtest) + - path: img/whd/resources/clm/COMPONENT_43439/43439A0-mfgtest.clm_blob + sha256: ef94fef099ce7c775a63c1009a67f086db63ae933f14f5fbe95b72ae541f7ae7 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_43439/43439A0-mfgtest.clm_blob + description: "Wi-Fi CLM for CYW43439 (mfgtest) Device" + doc-url: https://github.com/Infineon/wifi-host-driver + + #CYW4373 Device + #firmware + - path: img/whd/resources/firmware/COMPONENT_4373/4373A0.bin + sha256: d980497929d62dc81208060766a69bb5bded52748b8e6c484f704cf12867a0bf + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/4373A0.bin + description: "Wi-Fi Firmware for CYW4373 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #firmware (mfgtest) + - path: img/whd/resources/firmware/COMPONENT_4373/4373A0-mfgtest.bin + sha256: e347f14bf028cd8ff73b687ac6d54bbfe9e820dadacb5592cd14c83736e3a842 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/4373A0-mfgtest.bin + description: "Wi-Fi Firmware (mfgtest) for CYW4373 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm + - path: img/whd/resources/clm/COMPONENT_4373/4373A0.clm_blob + sha256: f0f0935b76d9ea9c8e7c05eded4b13caadfc1a35cdaf343f30155c967adf6985 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_4373/4373A0.clm_blob + description: "Wi-Fi CLM for CYW4373 Device" + doc-url: https://github.com/Infineon/wifi-host-driver + #clm (mfgtest) + - path: img/whd/resources/clm/COMPONENT_4373/4373A0-mfgtest.clm_blob + sha256: 56d3a09b077ed91a1063362ad685a72d7fce772291046cb17f8be699ada06796 + type: img + version: '2.5.0' + license-path: zephyr/blobs/license.txt + url: https://github.com/Infineon/wifi-host-driver/raw/release-v2.5.0/WiFi_Host_Driver/resources/clm/COMPONENT_4373/4373A0-mfgtest.clm_blob + description: "Wi-Fi CLM for CYW4373 (mfgtest) Device" + doc-url: https://github.com/Infineon/wifi-host-driver + +# bluetooth-integration (controller firmware blobs for CY43xx connectivity devices) + #CYW43012 Device + #MURATA-1LV module + - path: img/bluetooth/firmware/COMPONENT_43012/COMPONENT_MURATA-1LV/bt_firmware.hcd + sha256: 7866ac13cd06a03dcd7fc748ac82df5d76d034f5204dd277a7c6131594aed162 + type: img + version: '4.1.1' + license-path: zephyr/blobs/license.txt + url: https://raw.githubusercontent.com/Infineon/btstack-integration/release-v4.1.1/COMPONENT_HCI-UART/firmware/COMPONENT_43012/COMPONENT_MURATA-1LV/CYW43012C0_003.001.015.0229.0000_Generic_UART_37_4MHz_wlcsp_ref3_sLNA_CYW943012M2BT1LV.hcd + description: "Bluetooth Controller FW for MURATA-1LV Module" + doc-url: https://github.com/Infineon/btstack-integration + + #CYW4343W Device + #MURATA-1DX module + - path: img/bluetooth/firmware/COMPONENT_4343W/COMPONENT_MURATA-1DX/bt_firmware.hcd + sha256: 485bd176ffe1516f0c07e0c26c580111c8cc4e82b97b5e0b032d0e11af4dabd7 + type: img + version: '4.1.1' + license-path: zephyr/blobs/license.txt + url: https://raw.githubusercontent.com/Infineon/btstack-integration/release-v4.1.1/COMPONENT_HCI-UART/firmware/COMPONENT_4343W/COMPONENT_MURATA-1DX/BCM4343A1_001.002.009.0153.0000_Generic_UART_37_4MHz_wlbga_eLG_lite_AnyCloud.hcd + description: "Bluetooth Controller FW for MURATA-1YN Module" + doc-url: https://github.com/Infineon/btstack-integration + + #CYW43439 Device + #MURATA-1YN module + - path: img/bluetooth/firmware/COMPONENT_43439/COMPONENT_MURATA-1YN/bt_firmware.hcd + sha256: d19812c150b54138141cfcb1ffd1732c0c02694a8a37fc0cc49d8face0972363 + type: img + version: '4.1.1' + license-path: zephyr/blobs/license.txt + url: https://raw.githubusercontent.com/Infineon/btstack-integration/release-v4.1.1/COMPONENT_HCI-UART/firmware/COMPONENT_43439/COMPONENT_MURATA-1YN/CYW4343A2_001.003.016.0031.0000_Generic_UART_37_4MHz_wlbga_BU_dl_signed.hcd + description: "Bluetooth Controller FW for MURATA-1YN Module" + doc-url: https://github.com/Infineon/btstack-integration + + #CYW4373 Device + #STERLING-LWB5plus module + - path: img/bluetooth/firmware/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/bt_firmware.hcd + sha256: 92a4f1fe651ddc454e7a99d99b1422c5dca733078b1d73f509f2002a2430e52b + type: img + version: '4.1.1' + license-path: zephyr/blobs/license.txt + url: https://raw.githubusercontent.com/Infineon/btstack-integration/release-v4.1.1/COMPONENT_HCI-UART/firmware/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/CYW4373A0_001.001.025.0090.0129_UART_M2.hcd + description: "Bluetooth Controller FW for MURATA-1YN Module" + doc-url: https://github.com/Infineon/btstack-integration