12 #endif /* STATISTICS == 1 */
14 MEMB(pool_pbufs
,sizeof(struct pbuf
)+PBUF_POOL_BUFSIZE
,PBUF_POOL_NUM
);
15 MEMB(rom_pbufs
,sizeof(struct pbuf
),PBUF_ROM_NUM
);
19 btmemb_init(&pool_pbufs
);
20 btmemb_init(&rom_pbufs
);
23 struct pbuf
* btpbuf_alloc(pbuf_layer layer
,u16_t len
,pbuf_flag flag
)
32 offset
+= TRANSPORT_HLEN
;
39 ERROR("btpbuf_alloc: bad pbuf layer.\n");
45 p
= btmemb_alloc(&pool_pbufs
);
47 ERROR("btbtpbuf_alloc: couldn't allocate pbuf(p) from pool\n");
52 p
->payload
= MEM_ALIGN((void*)((u8_t
*)p
+(sizeof(struct pbuf
)+offset
)));
54 p
->len
= (len
>(PBUF_POOL_BUFSIZE
-offset
)?(PBUF_POOL_BUFSIZE
-offset
):len
);
55 p
->flags
= PBUF_FLAG_POOL
;
59 rem_len
= len
- p
->len
;
61 q
= btmemb_alloc(&pool_pbufs
);
63 ERROR("btpbuf_alloc: couldn't allocate pbuf(q) from pool\n");
71 q
->len
= (rem_len
>PBUF_POOL_BUFSIZE
?PBUF_POOL_BUFSIZE
:rem_len
);
72 q
->payload
= (void*)((u8_t
*)q
+sizeof(struct pbuf
));
73 q
->flags
= PBUF_FLAG_POOL
;
81 p
= btmemr_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf
)+offset
)+MEM_ALIGN_SIZE(len
));
83 ERROR("btpbuf_alloc: couldn't allocate pbuf from ram\n");
86 p
->payload
= MEM_ALIGN((u8_t
*)p
+sizeof(struct pbuf
)+offset
);
87 p
->len
= p
->tot_len
= len
;
89 p
->flags
= PBUF_FLAG_RAM
;
93 p
= btmemb_alloc(&rom_pbufs
);
95 ERROR("btpbuf_alloc: couldn't allocate pbuf from rom/ref\n");
100 p
->len
= p
->tot_len
= len
;
101 p
->flags
= (flag
==PBUF_ROM
?PBUF_FLAG_ROM
:PBUF_FLAG_REF
);
104 ERROR("btpbuf_alloc: bad flag value.\n");
112 u8_t
btpbuf_free(struct pbuf
*p
)
118 if(p
==NULL
) return 0;
122 _CPU_ISR_Disable(level
);
127 if(p
->flags
==PBUF_FLAG_POOL
) {
128 btmemb_free(&pool_pbufs
,p
);
129 } else if(p
->flags
==PBUF_FLAG_ROM
|| p
->flags
==PBUF_FLAG_REF
) {
130 btmemb_free(&rom_pbufs
,p
);
139 _CPU_ISR_Restore(level
);
144 void btpbuf_realloc(struct pbuf
*p
,u16_t new_len
)
150 if(new_len
>=p
->tot_len
) return;
152 grow
= new_len
- p
->tot_len
;
155 while(rem_len
>q
->len
) {
161 if(q
->flags
==PBUF_FLAG_RAM
&& rem_len
!=q
->len
)
162 btmemr_realloc(q
,(u8_t
*)q
->payload
-(u8_t
*)q
+rem_len
);
167 if(q
->next
!=NULL
) btpbuf_free(q
->next
);
171 u8_t
btpbuf_header(struct pbuf
*p
,s16_t hdr_size_inc
)
175 if(hdr_size_inc
==0 || p
==NULL
) return 0;
178 payload
= p
->payload
;
179 if(p
->flags
==PBUF_FLAG_POOL
|| p
->flags
==PBUF_FLAG_RAM
) {
180 p
->payload
= (u8_t
*)p
->payload
-hdr_size_inc
;
181 if((u8_t
*)p
->payload
<(u8_t
*)p
+sizeof(struct pbuf
)) {
182 p
->payload
= payload
;
185 } else if(p
->flags
==PBUF_FLAG_ROM
|| p
->flags
==PBUF_FLAG_REF
) {
186 if(hdr_size_inc
<0 && hdr_size_inc
-p
->len
<=0) p
->payload
= (u8_t
*)p
->payload
-hdr_size_inc
;
189 p
->tot_len
+= hdr_size_inc
;
190 p
->len
+= hdr_size_inc
;
195 u8_t
btpbuf_clen(struct pbuf
*p
)
207 void btpbuf_ref(struct pbuf
*p
)
212 _CPU_ISR_Disable(level
);
214 _CPU_ISR_Restore(level
);
218 void btpbuf_cat(struct pbuf
*h
,struct pbuf
*t
)
222 if(h
==NULL
|| t
==NULL
) return;
224 for(p
=h
;p
->next
!=NULL
;p
=p
->next
) {
225 p
->tot_len
+= t
->tot_len
;
227 p
->tot_len
+= t
->tot_len
;
231 void btpbuf_queue(struct pbuf
*p
,struct pbuf
*n
)
233 if(p
==NULL
|| n
==NULL
|| p
==n
) return;
235 while(p
->next
!=NULL
) p
= p
->next
;
241 struct pbuf
* btpbuf_dequeue(struct pbuf
*p
)
245 if(p
==NULL
) return NULL
;
247 while(p
->tot_len
!=p
->len
) p
= p
->next
;
255 void btpbuf_chain(struct pbuf
*h
,struct pbuf
*t
)
261 struct pbuf
* btpbuf_dechain(struct pbuf
*p
)
268 q
->tot_len
= p
->tot_len
- p
->len
;
272 tail_gone
= btpbuf_free(q
);
275 return (tail_gone
>0?NULL
:q
);
278 struct pbuf
* btpbuf_take(struct pbuf
*p
)
280 struct pbuf
*q
, *prev
, *head
;
284 /* iterate through pbuf chain */
287 /* pbuf is of type PBUF_REF? */
288 if (p
->flags
== PBUF_FLAG_REF
) {
289 LOG("pbuf_take: encountered PBUF_REF %p\n", (void *)p
);
290 /* allocate a pbuf (w/ payload) fully in RAM */
291 /* PBUF_POOL buffers are faster if we can use them */
292 if (p
->len
<= PBUF_POOL_BUFSIZE
) {
293 q
= btpbuf_alloc(PBUF_RAW
, p
->len
, PBUF_POOL
);
295 LOG("pbuf_take: Could not allocate PBUF_POOL\n");
298 /* no replacement pbuf yet */
300 LOG("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n");
302 /* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
304 q
= btpbuf_alloc(PBUF_RAW
, p
->len
, PBUF_RAM
);
306 LOG("pbuf_take: Could not allocate PBUF_RAM\n");
309 /* replacement pbuf could be allocated? */
315 /* remove linkage from original pbuf */
317 /* remove linkage to original pbuf */
319 /* break chain and insert new pbuf instead */
321 /* prev == NULL, so we replaced the head pbuf of the chain */
325 /* copy pbuf payload */
326 memcpy(q
->payload
, p
->payload
, p
->len
);
327 q
->tot_len
= p
->tot_len
;
329 /* in case p was the first pbuf, it is no longer refered to by
330 * our caller, as the caller MUST do p = pbuf_take(p);
331 * in case p was not the first pbuf, it is no longer refered to
332 * by prev. we can safely free the pbuf here.
333 * (note that we have set p->next to NULL already so that
334 * we will not free the rest of the chain by accident.)
337 /* do not copy ref, since someone else might be using the old buffer */
338 LOG("pbuf_take: replaced PBUF_REF %p with %p\n", (void *)p
, (void *)q
);
341 /* deallocate chain */
343 LOG("pbuf_take: failed to allocate replacement pbuf for %p\n", (void *)p
);
346 /* p->flags != PBUF_FLAG_REF */
348 LOG("pbuf_take: skipping pbuf not of type PBUF_REF\n");
350 /* remember this pbuf */
352 /* proceed to next pbuf in original chain */
355 LOG("pbuf_take: end of chain reached.\n");