Auxiliary structure to handle with BT commands and events. To consider later moving to a module. This is part of the USB-BT driver
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22939 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4ff174438e
commit
8354ae8795
215
src/add-ons/kernel/drivers/bluetooth/h2/h2generic/snet_buffer.c
Normal file
215
src/add-ons/kernel/drivers/bluetooth/h2/h2generic/snet_buffer.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||
*
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "snet_buffer.h"
|
||||
|
||||
|
||||
struct snet_buffer {
|
||||
struct list_link link;
|
||||
|
||||
uint8* buffer;
|
||||
|
||||
uint16 allocatedSize;
|
||||
uint16 expectedSize;
|
||||
uint16 puttingSize;
|
||||
uint16 pullingSize;
|
||||
|
||||
void* cookie;
|
||||
|
||||
};
|
||||
|
||||
|
||||
snet_buffer*
|
||||
snb_create(uint16 size)
|
||||
{
|
||||
/* TODO: pointer checking */
|
||||
|
||||
#ifdef SNB_BUFFER_ATTACHED
|
||||
/* Allocating these 2 buffers together might prevent memory fragmentation? */
|
||||
snet_buffer* snb = (snet_buffer*) malloc(sizeof(snet_buffer) + size);
|
||||
snb->buffer = ((uint8*)snb) + sizeof(snet_buffer);
|
||||
#else
|
||||
snet_buffer* snb = malloc(sizeof (snet_buffer));
|
||||
snb->buffer = malloc(size);
|
||||
#endif
|
||||
|
||||
snb->pullingSize = snb->puttingSize = 0;
|
||||
snb->expectedSize = snb->allocatedSize = size;
|
||||
|
||||
return snb;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
snb_put(snet_buffer* snb, void* data, uint16 size)
|
||||
{
|
||||
/* TODO: check overflow */
|
||||
memcpy( &snb->buffer[snb->puttingSize], data, size);
|
||||
snb->puttingSize+=size;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
snb_pull(snet_buffer* snb, uint16 size)
|
||||
{
|
||||
/* TODO: check overflow */
|
||||
snb->pullingSize+=size;
|
||||
return &snb->buffer[snb->pullingSize-size];
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
snb_reset(snet_buffer* snb)
|
||||
{
|
||||
snb->puttingSize = snb->pullingSize = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
snb_free(snet_buffer* snb)
|
||||
{
|
||||
if (snb == NULL)
|
||||
return;
|
||||
|
||||
#ifdef SNB_BUFFER_ATTACHED
|
||||
free(snb);
|
||||
#else
|
||||
free(snb->buffer);
|
||||
free(snb);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline void*
|
||||
snb_get(snet_buffer* snb)
|
||||
{
|
||||
/* TODO: pointer checking */
|
||||
return snb->buffer;
|
||||
}
|
||||
|
||||
|
||||
inline uint16
|
||||
snb_size(snet_buffer* snb)
|
||||
{
|
||||
/* TODO: pointer checking */
|
||||
return snb->expectedSize;
|
||||
}
|
||||
|
||||
|
||||
inline void*
|
||||
snb_cookie(snet_buffer* snb)
|
||||
{
|
||||
/* TODO: pointer checking */
|
||||
return snb->cookie;
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
snb_set_cookie(snet_buffer* snb, void* cookie)
|
||||
{
|
||||
/* TODO: pointer checking */
|
||||
snb->cookie = cookie;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if we canot "put" more data in the buffer */
|
||||
inline bool snb_completed(snet_buffer* snb)
|
||||
{
|
||||
return (snb != NULL && (snb->expectedSize == snb->puttingSize));
|
||||
}
|
||||
|
||||
|
||||
/* Return true if we cannot pull more more data from the buffer */
|
||||
inline bool snb_finished(snet_buffer* snb)
|
||||
{
|
||||
return (snb != NULL && (snb->expectedSize == snb->pullingSize));
|
||||
}
|
||||
|
||||
|
||||
inline bool snb_remaining_to_put(snet_buffer* snb)
|
||||
{
|
||||
return (snb != NULL && (snb->expectedSize - snb->puttingSize));
|
||||
}
|
||||
|
||||
|
||||
inline bool snb_remaining_to_pull(snet_buffer* snb)
|
||||
{
|
||||
return (snb != NULL && (snb->expectedSize - snb->pullingSize));
|
||||
}
|
||||
|
||||
|
||||
/* ISSUE1: Number of packets in the worst case(we always need a bigger
|
||||
buffer than before) increases, never decreases:
|
||||
|
||||
SOL1: Delete the smallest when the queue is bigger than X elements
|
||||
SOL2: ?
|
||||
|
||||
ISSUE2: If the queue is not gonna be used for long time, Memory c
|
||||
ould be freed
|
||||
|
||||
SOL1: Provide purge func.
|
||||
SOL2: ?
|
||||
|
||||
*/
|
||||
static snet_buffer*
|
||||
snb_attempt_reuse(snet_buffer* snb, uint16 size)
|
||||
{
|
||||
if ( snb == NULL ||
|
||||
((int16)snb->allocatedSize - (int16)size) < 0 ) {
|
||||
|
||||
/* Impossible or not worth, Creating a new one */
|
||||
snb_free(snb);
|
||||
return snb_create(size);
|
||||
|
||||
}
|
||||
else {
|
||||
snb_reset(snb);
|
||||
snb->expectedSize = size;
|
||||
return snb;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
snb_park(struct list* l, snet_buffer* snb)
|
||||
{
|
||||
snet_buffer* item = NULL;
|
||||
/* insert it by order */
|
||||
while ((item = list_get_next_item(l, item)) != NULL) {
|
||||
if (item->allocatedSize > snb->allocatedSize)
|
||||
list_insert_item_before(l, item, snb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
snet_buffer*
|
||||
snb_fetch(struct list* l, uint16 size)
|
||||
{
|
||||
|
||||
snet_buffer* item = NULL;
|
||||
snet_buffer* previous = NULL;
|
||||
|
||||
if (!list_is_empty(l))
|
||||
while ((item = list_get_next_item(l, item)) != NULL) {
|
||||
if (item->allocatedSize == size) {
|
||||
/* This one is for us*/
|
||||
break;
|
||||
}
|
||||
else if (item->allocatedSize > size) {
|
||||
/* get the previous*/
|
||||
item = previous;
|
||||
break;
|
||||
}
|
||||
previous = item;
|
||||
}
|
||||
|
||||
return snb_attempt_reuse(item, size);
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||
*
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SNET_BUFFER_H_
|
||||
#define _SNET_BUFFER_H_
|
||||
|
||||
#include <util/list.h>
|
||||
|
||||
/*
|
||||
* This is a simple data structure to hold network buffers.
|
||||
* It drops many functionality that the Haiku net_buffer provides.
|
||||
*
|
||||
* - Inspired by linux sk_buff/bsd mbuf (put/pull)
|
||||
* - Contiguoussafe (no push operation)
|
||||
*
|
||||
* So snet_buffers are ONLY meant to be used when:
|
||||
* 1) You know exactily the maximun/final size of the frame
|
||||
* before allocating it, and you will never exceed it.
|
||||
* 2) You are not supposed to prepend data, only append.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Configuration parameters */
|
||||
#define SNB_BUFFER_ATTACHED
|
||||
//#define SNB_PERFORMS_OVERFLOW_CHECKS
|
||||
//#define SNB_PERFORMS_POINTER_CHECKS
|
||||
|
||||
struct snet_buffer;
|
||||
|
||||
typedef struct snet_buffer snet_buffer;
|
||||
|
||||
/* Creates a snb_buffer allocating size space for its full content */
|
||||
snet_buffer* snb_create(uint16 size);
|
||||
/* Free the snb_buffer*/
|
||||
void snb_free(snet_buffer* snb);
|
||||
/* Free the snb_buffer*/
|
||||
void* snb_get(snet_buffer* snb);
|
||||
/* Size of the snb_buffer*/
|
||||
uint16 snb_size(snet_buffer* snb);
|
||||
|
||||
/* Cookie of the snb_buffer*/
|
||||
void* snb_cookie(snet_buffer* snb);
|
||||
/* Get Cookie of the snb_buffer*/
|
||||
void snb_set_cookie(snet_buffer* snb, void* cookie);
|
||||
|
||||
/* Place the memory given by data to the "tail" of the snb */
|
||||
void snb_put(snet_buffer* snb, void* data, uint16 size);
|
||||
/* Returns a header chunk of size data */
|
||||
void* snb_pull(snet_buffer* snb, uint16 size);
|
||||
/* Discards all data put or pulled from the buffer */
|
||||
void snb_reset(snet_buffer* snb);
|
||||
|
||||
/* Return true if we canot "put" more data in the buffer */
|
||||
bool snb_completed(snet_buffer* snb);
|
||||
/* Return true if we cannot pull more more data from the buffer */
|
||||
bool snb_finished(snet_buffer* snb);
|
||||
/* Return the amount of data we can still put in the buffer */
|
||||
bool snb_remaining_to_put(snet_buffer* snb);
|
||||
/* Return the amount of data we can still pull in the buffer */
|
||||
bool snb_remaining_to_pull(snet_buffer* snb);
|
||||
|
||||
/* These to functions are provided to avoid memory fragmentation
|
||||
* allocating and freeing many snb_buffers and its possible overhead.
|
||||
* Thypical scenario would be
|
||||
* that you create a snb_buffer to send data, once you send you free it,
|
||||
* and need another one to hold the response. The idea would be once you send
|
||||
* that buffer, to snb_park the buffer, and whenever you need to allocate another
|
||||
* one snb_fetch it. That funcion will reuse most appropiated previous used one
|
||||
* snb_buff by its memory use.
|
||||
*/
|
||||
void snb_park(struct list* l, snet_buffer* snb);
|
||||
snet_buffer* snb_fetch(struct list* l, uint16 size);
|
||||
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user