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:
Oliver Ruiz Dorantes 2007-11-17 20:48:50 +00:00
parent 4ff174438e
commit 8354ae8795
2 changed files with 296 additions and 0 deletions

View 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);
}

View File

@ -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