1 /***********************************************************************************************//**
2  * \file cy_network_buffer_lwip.c
3  *
4  * \brief
5  * Basic set of APIs for dealing with network packet buffers. This is used by WHD
6  * for relaying data between the network stack and the connectivity chip.
7  *
8  ***************************************************************************************************
9  * \copyright
10  * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
11  * an affiliate of Cypress Semiconductor Corporation
12  *
13  * SPDX-License-Identifier: Apache-2.0
14  *
15  * Licensed under the Apache License, Version 2.0 (the "License");
16  * you may not use this file except in compliance with the License.
17  * You may obtain a copy of the License at
18  *
19  *     http://www.apache.org/licenses/LICENSE-2.0
20  *
21  * Unless required by applicable law or agreed to in writing, software
22  * distributed under the License is distributed on an "AS IS" BASIS,
23  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24  * See the License for the specific language governing permissions and
25  * limitations under the License.
26  **************************************************************************************************/
27 
28 #include <stdlib.h>
29 #include "cy_network_buffer.h"
30 #include "cy_utils.h"
31 #include "cyhal_system.h"
32 #include "lwip/pbuf.h"
33 
34 #define  SDIO_BLOCK_SIZE (64U)
35 
36 //--------------------------------------------------------------------------------------------------
37 // cy_buffer_pool_init
38 //--------------------------------------------------------------------------------------------------
cy_buffer_pool_init(void * tx_packet_pool,void * rx_packet_pool)39 whd_result_t cy_buffer_pool_init(void* tx_packet_pool, void* rx_packet_pool)
40 {
41     CY_UNUSED_PARAMETER(tx_packet_pool);
42     CY_UNUSED_PARAMETER(rx_packet_pool);
43 
44     /*
45      * Not used for LwIP.
46      */
47 
48     return WHD_SUCCESS;
49 }
50 
51 
52 //--------------------------------------------------------------------------------------------------
53 // cy_host_buffer_get
54 //--------------------------------------------------------------------------------------------------
cy_host_buffer_get(whd_buffer_t * buffer,whd_buffer_dir_t direction,uint16_t size,uint32_t timeout_ms)55 whd_result_t cy_host_buffer_get(whd_buffer_t* buffer, whd_buffer_dir_t direction,
56                                 uint16_t size, uint32_t timeout_ms)
57 {
58     struct pbuf* p = NULL;
59     uint32_t counter = 0;
60 
61     do
62     {
63         counter++;
64         if (direction == WHD_NETWORK_TX)
65         {
66             // Allocate from the POOL if possible to avoid dynamic memory allocation
67             pbuf_type type = (size <= PBUF_POOL_BUFSIZE) ? PBUF_POOL : PBUF_RAM;
68             p = pbuf_alloc(PBUF_RAW, size, type);
69         }
70         else
71         {
72             // Increase allocation size to ensure the SDIO can write fully aligned blocks for
73             // best throughput performance
74             p = pbuf_alloc(PBUF_RAW, size + SDIO_BLOCK_SIZE, PBUF_RAM);
75             if (p != NULL)
76             {
77                 p->len      = size;
78                 p->tot_len -= SDIO_BLOCK_SIZE;
79             }
80         }
81 
82         if (NULL == p)
83         {
84             cyhal_system_delay_ms(1);
85         }
86     } while ((NULL == p) && (counter <= timeout_ms));
87 
88     if (p != NULL)
89     {
90         *buffer = p;
91         return WHD_SUCCESS;
92     }
93     else
94     {
95         return WHD_BUFFER_ALLOC_FAIL;
96     }
97 }
98 
99 
100 //--------------------------------------------------------------------------------------------------
101 // cy_buffer_release
102 //--------------------------------------------------------------------------------------------------
cy_buffer_release(whd_buffer_t buffer,whd_buffer_dir_t direction)103 void cy_buffer_release(whd_buffer_t buffer, whd_buffer_dir_t direction)
104 {
105     CY_UNUSED_PARAMETER(direction);
106     (void)pbuf_free((struct pbuf*)buffer);
107 }
108 
109 
110 //--------------------------------------------------------------------------------------------------
111 // cy_buffer_get_current_piece_data_pointer
112 //--------------------------------------------------------------------------------------------------
cy_buffer_get_current_piece_data_pointer(whd_buffer_t buffer)113 uint8_t* cy_buffer_get_current_piece_data_pointer(whd_buffer_t buffer)
114 {
115     CY_ASSERT(buffer != NULL);
116     struct pbuf* pbuffer= (struct pbuf*)buffer;
117     return (uint8_t*)pbuffer->payload;
118 }
119 
120 
121 //--------------------------------------------------------------------------------------------------
122 // cy_buffer_get_current_piece_size
123 //--------------------------------------------------------------------------------------------------
cy_buffer_get_current_piece_size(whd_buffer_t buffer)124 uint16_t cy_buffer_get_current_piece_size(whd_buffer_t buffer)
125 {
126     CY_ASSERT(buffer != NULL);
127     struct pbuf* pbuffer = (struct pbuf*)buffer;
128     return (uint16_t)pbuffer->len;
129 }
130 
131 
132 //--------------------------------------------------------------------------------------------------
133 // cy_buffer_set_size
134 //--------------------------------------------------------------------------------------------------
cy_buffer_set_size(whd_buffer_t buffer,uint16_t size)135 whd_result_t cy_buffer_set_size(whd_buffer_t buffer, uint16_t size)
136 {
137     CY_ASSERT(buffer != NULL);
138     struct pbuf* pbuffer = (struct pbuf*)buffer;
139 
140     if (size > ((uint16_t)WHD_LINK_MTU +
141                 LWIP_MEM_ALIGN_SIZE(LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))) +
142                 LWIP_MEM_ALIGN_SIZE(size)))
143     {
144         return WHD_BUFFER_SIZE_SET_ERROR;
145     }
146 
147     pbuffer->tot_len = size;
148     pbuffer->len     = size;
149 
150     return CY_RSLT_SUCCESS;
151 }
152 
153 
154 //--------------------------------------------------------------------------------------------------
155 // cy_buffer_add_remove_at_front
156 //--------------------------------------------------------------------------------------------------
cy_buffer_add_remove_at_front(whd_buffer_t * buffer,int32_t add_remove_amount)157 whd_result_t cy_buffer_add_remove_at_front(whd_buffer_t* buffer, int32_t add_remove_amount)
158 {
159     CY_ASSERT(buffer != NULL);
160     struct pbuf** pbuffer = (struct pbuf**)buffer;
161 
162     if ((u8_t)0 != pbuf_header(*pbuffer, (s16_t)(-add_remove_amount)))
163     {
164         return WHD_BUFFER_POINTER_MOVE_ERROR;
165     }
166 
167     return WHD_SUCCESS;
168 }
169