📄 btmem.c
字号:
return tx;}/* Returns number of buffers */s32 buf_count(void){ return bt_buf.nbr_bufs;}/* Returns total number of bytes in buffer (fragmented) */s32 buf_byte_count(s32 line){ u8 *pos = bt_buf.head; bt_tx_buf *tx; u32 sum = 0; if (line < 0) { //printk(__FUNCTION__": Total bytes in buffer %d\n", bt_buf.count); return bt_buf.count; } else { if (bt_buf.free > bt_buf.send) { /* read from send -> free */ pos = bt_buf.send; while (pos < bt_buf.free) { tx = (bt_tx_buf *)(pos); if (tx->line == line) { sum += tx->subscr_len; } pos += BT_TX_HDRSIZE + tx->subscr_len; } } else if (bt_buf.free < bt_buf.send) { /* read send -> toss_tail + read from head -> free */ pos = bt_buf.send; while (pos < bt_buf.toss_tail) { tx = (bt_tx_buf *)(pos); if (tx->line == line) { sum += tx->subscr_len; } pos += BT_TX_HDRSIZE + tx->subscr_len; } pos = bt_buf.head; while (pos < bt_buf.free) { tx = (bt_tx_buf*)(pos); if (tx->line == line) { sum += tx->subscr_len; } pos += BT_TX_HDRSIZE + tx->subscr_len; } } else { /* Buffer empty */ sum = 0; } //printk(__FUNCTION__": %d chars in buf for line:%d, total:%d\n", sum, line, bt_buf.count); return sum; }}/* Returns unfragmented buffer space */ #define BTMEM_EXTRASPACE BT_BUF_SIZE/10 /* always an extra 10 % marginal in case the subscriber doesn't check available space before doing the subscribe (only in connect/disconnect phase ) */s32 buf_write_room(){ s32 space_left; cli(); if (bt_buf.free > bt_buf.send) space_left = MAX((bt_buf.tail - bt_buf.free), (bt_buf.send - bt_buf.head)); else if (bt_buf.free < bt_buf.send) space_left = (bt_buf.send - bt_buf.free); else { /* subscribe_bt_buf will reset buffer if buffer is empty don't count a tossed tail ! */ space_left = (BT_BUF_SIZE - (bt_buf.tail - bt_buf.toss_tail) - bt_buf.count); } space_left -= (BT_TX_HDRSIZE+BTMEM_EXTRASPACE); if (space_left < 0) space_left = 0;// btmem_show_size(space_left); sti(); return space_left;}/* Fetch pointer to next transmission chunk */bt_tx_buf* get_bt_buf(void){ bt_tx_buf *tx; if (bt_buf.count == 0) { D_MEM("get_bt_buf : no data in buffer\n"); return NULL; } /* Find the next send buf, first check toss_tail */ if (bt_buf.send == bt_buf.toss_tail) { D_MEM("get_bt_buf : toss tail !\n"); bt_buf.send = bt_buf.head; bt_buf.toss_tail = bt_buf.tail; } /* add check that cur_len < subscr_len ? */ tx = (bt_tx_buf *)(bt_buf.send); if (tx->magic != 0x4321) { D_ERR("get_bt_buf : wrong magic!\n");#if PANIC_AT_ERROR panic("lets stop here...\n");#endif return NULL; } /* Check if chunk is valid */ if (tx->flushed) { /* This buffer is flushed */ DSYS("get_bt_buf : Flushing this buffer [handle %d]\n", tx->hci_hdl);#if BTMEM_FLUSH_ENABLED unsubscribe_bt_buf(tx); return get_bt_buf(); /* Yeehaa, more recursion :) */#else return NULL;#endif } D_MEM("get_bt_buf : returning %d\n", (bt_buf.send - bt_buf.head) ); return tx;}/* Unsubscribes memory area so other functions can reuse that memory. */void unsubscribe_bt_buf(bt_tx_buf *tx){ s32 tail_free; /* for debug */ s32 head_free; if (!tx) return; D_MEM(__FUNCTION__ ": %d bytes (not incl hdrs) at pos %d\n", tx->subscr_len, (u8 *)tx - bt_buf.head); /* Check that tx is valid for unssubscribe. We must process the buffers in fifo order ! */ cli(); if (bt_buf.send == (u8*)tx) { if ((u8*)(tx->data + tx->subscr_len) <= bt_buf.tail) { /* don't touch free, only subscribe_bt_buf change free */ bt_buf.send += (tx->subscr_len + BT_TX_HDRSIZE); bt_buf.count -= (tx->subscr_len + BT_TX_HDRSIZE); bt_buf.nbr_bufs--; } else { D_ERR(__FUNCTION__ ": failed, out of boundary\n"); } } else if (bt_buf.count == 0) D_MEM(__FUNCTION__ ": no data in buffer\n"); else { D_ERR(__FUNCTION__ ": invalid data segment!\n");#ifdef __KERNEL__ D_ERR("pid : %d (tx:0x%x - send:0x%x=%d) send:%ld free:%ld\n", current->pid, (uint)tx, (uint)bt_buf.send, (int)tx - (int)bt_buf.send, (long int)(bt_buf.send - bt_buf.head), (long int)(bt_buf.free - bt_buf.head)); D_ERR("count:%d nbr_bufs:%d count:%d\n" , bt_buf.count, bt_buf.nbr_bufs, bt_buf.count);#if PANIC_AT_ERROR panic("Lets stop here...\n");#endif#endif } /* If this buffer has flushed flag set it is simply unsubscribed just as any other buffer, get_bt_buf is responsible for calling this function. However, it is unsubscribe_bt_buf:s responsibility to toss the tail */ /* Check if next buffer is to be tossed or not */ /* Is also checked done in get_bt_buf */ if (bt_buf.send == bt_buf.toss_tail) { D_MEM(__FUNCTION__ ": toss_tail, now send pos is 0\n"); bt_buf.send = bt_buf.head; bt_buf.toss_tail = bt_buf.tail; if (bt_buf.count == 0) bt_buf.free = bt_buf.head; } tail_free = (bt_buf.tail - bt_buf.free); head_free = (bt_buf.send - bt_buf.head);#if BTMEM_SHOW_GRAPH btmem_show_size(BT_BUF_SIZE - buf_write_room());#endif sti();}/*===================================================================*//* Debug tools *//* Displays unfragmented buffer usage */#define BUFFERMETERRESOLUTION 40u8 buffermeter[BUFFERMETERRESOLUTION + 1];/* Graphical view of buffer size */void btmem_show_size(s32 count){ u32 i; i = ((count*BUFFERMETERRESOLUTION)/BT_BUF_SIZE); memset(buffermeter, '|', i); buffermeter[i+1] = 0; /* null terminate */ printk("%s [%s - %d bytes]\n", buffermeter, print_time(0), count);}void show_bt_buf(bt_tx_buf *tx, s32 no_data){ printk("buf (%ld) - magic 0x%x, hci_hdl 0x%x\n", (long)((u8*)tx - bt_buf.head), tx->magic, tx->hci_hdl); printk(" pb flag : %d bc flag : %d\n", tx->pb_flag, tx->bc_flag); printk(" cur_len %d, subscr_len %d, flushed %d\n\n", tx->cur_len, tx->subscr_len, tx->flushed); if (!no_data) print_data("data :", tx->data, tx->subscr_len); }void btmem_get_status(bt_tx_buf *current_buf){ u8 *pos = bt_buf.head; bt_tx_buf *tx; printk("*** buffer info ***\n"); printk("current buffer at : 0x%x\n", (int)current_buf); printk("head : 0x%x, tail : 0x%x\n", (int)bt_buf.head, (int)bt_buf.tail); printk("size : %d count : %d nbr_bufs : %d\n", bt_buf.size, bt_buf.count, bt_buf.nbr_bufs); printk("free : %ld, send : %ld, toss_tail : %ld\n", (long)(bt_buf.free - bt_buf.head), (long)(bt_buf.send - bt_buf.head), (long)(bt_buf.toss_tail - bt_buf.head)); printk("------------------------------------------\n"); if (bt_buf.free > bt_buf.send) { /* read from send -> free */ pos = bt_buf.send; printk("SEND <-> FREE\n"); while (pos < bt_buf.free) { tx = (bt_tx_buf *)(pos); show_bt_buf(tx, 1); pos += BT_TX_HDRSIZE + tx->subscr_len; } } else { /* read send -> toss_tail + read from head -> free */ pos = bt_buf.send; printk("SEND <-> TOSS_TAIL\n"); while (pos < bt_buf.toss_tail) { tx = (bt_tx_buf *)(pos); show_bt_buf(tx, 1); pos += BT_TX_HDRSIZE + tx->subscr_len; } printk("HEAD <-> FREE\n"); pos = bt_buf.head; while (pos < bt_buf.free) { tx = (bt_tx_buf*)(pos); show_bt_buf(tx, 1); pos += BT_TX_HDRSIZE + tx->subscr_len; } } printk("------------------------------------------\n");}#if BTMEM_TESTvoid btmem_test(void){ s32 i; s32 count = 10000; u32 cursize = 1; bt_tx_buf *tx; for (i = 0; i < count; i++) { if (cursize > buf_write_room()) return; printk("storing %d bytes packets\n", cursize); while (buf_write_room() >= cursize) { if (!(tx = subscribe_bt_buf(cursize))) { return ; } } printk("emptying %d bytes packets\n", cursize); while (tx = get_bt_buf()) { unsubscribe_bt_buf(get_bt_buf()); } cursize++; } return;}#endif/****************** END OF FILE btmem.c *************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -