/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
* Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "h2upper.h"
#include <string.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include <kernel.h>
#include "h2debug.h"
#include "h2generic.h"
#include "h2transactions.h"
#include "snet_buffer.h"
// TODO: split for commands and comunication (ACL & SCO)
void
sched_tx_processing(bt_usb_dev* bdev)
{
net_buffer* nbuf;
snet_buffer* snbuf;
status_t err;
TRACE("%s: (%p)\n", __func__, bdev);
if (!TEST_AND_SET(&bdev->state, PROCESSING)) {
// We are not processing in another thread so... START!!
do {
/* Do while this bit is on... so someone should set it before we
* stop the iterations
*/
bdev->state = CLEAR_BIT(bdev->state, SENDING);
// check Commands
#ifdef EMPTY_COMMAND_QUEUE
while (!list_is_empty(&bdev->nbuffersTx[BT_COMMAND])) {
#else
if (!list_is_empty(&bdev->nbuffersTx[BT_COMMAND])) {
#endif
snbuf = (snet_buffer*)
list_remove_head_item(&bdev->nbuffersTx[BT_COMMAND]);
err = submit_tx_command(bdev, snbuf);
if (err != B_OK) {
// re-head it
list_insert_item_before(&bdev->nbuffersTx[BT_COMMAND],
list_get_first_item(&bdev->nbuffersTx[BT_COMMAND]),
snbuf);
}
}
// check ACl
#define EMPTY_ACL_QUEUE
#ifdef EMPTY_ACL_QUEUE
while (!list_is_empty(&bdev->nbuffersTx[BT_ACL])) {
#else
if (!list_is_empty(&bdev->nbuffersTx[BT_ACL])) {
#endif
nbuf = (net_buffer*)
list_remove_head_item(&bdev->nbuffersTx[BT_ACL]);
err = submit_tx_acl(bdev, nbuf);
if (err != B_OK) {
// re-head it
list_insert_item_before(&bdev->nbuffersTx[BT_ACL],
list_get_first_item(&bdev->nbuffersTx[BT_ACL]),
nbuf);
}
}
if (!list_is_empty(&bdev->nbuffersTx[BT_SCO])) {
// TODO to be implemented
}
} while (GET_BIT(bdev->state, SENDING));
bdev->state = CLEAR_BIT(bdev->state, PROCESSING);
} else {
// We are processing so MARK that we need to still go on with that
bdev->state = SET_BIT(bdev->state, SENDING);
}
}
#if 0
// DEPRECATED
status_t
post_packet_up(bt_usb_dev* bdev, bt_packet_t type, void* buf)
{
status_t err = B_ERROR;
debugf("Frame up type=%d\n", type);
if (type == BT_EVENT) {
snet_buffer* snbuf = (snet_buffer*)buf;
btCoreData->PostEvent(bdev->ndev, snb_get(snbuf),
(size_t)snb_size(snbuf));
snb_park(&bdev->snetBufferRecycleTrash, snbuf);
debugf("to btDataCore len=%d\n", snb_size(snbuf));
} else {
net_buffer* nbuf = (net_buffer*) buf;
// No need to free the buffer at allocation is gonna be reused
btDevices->receive_data(bdev->ndev, &nbuf);
TRACE("to net_device\n");
}
return err;
}
#endif
status_t
send_packet(hci_id hid, bt_packet_t type, net_buffer* nbuf)
{
bt_usb_dev* bdev = fetch_device(NULL, hid);
status_t err = B_OK;
if (bdev == NULL)
return B_ERROR;
// TODO: check if device is actually ready for this
// TODO: Lock Device
if (nbuf != NULL) {
if (type != nbuf->protocol) // a bit strict maybe
panic("Upper layer has not filled correctly a packet");
switch (type) {
case BT_COMMAND:
case BT_ACL:
case BT_SCO:
list_add_item(&bdev->nbuffersTx[type], nbuf);
bdev->nbuffersPendingTx[type]++;
break;
default:
ERROR("%s: Unknown packet type for sending %d\n", __func__,
type);
// TODO: free the net_buffer -> no, allow upper layer
// handle it with the given error
err = B_BAD_VALUE;
break;
}
} else {
TRACE("%s: tx sched provoked", __func__);
}
// TODO: check if device is actually ready for this
// TODO: unlock device
// sched in any case even if nbuf is null (provoke re-scheduling)
sched_tx_processing(bdev);
return err;
}
status_t
send_command(hci_id hid, snet_buffer* snbuf)
{
bt_usb_dev* bdev = fetch_device(NULL, hid);
status_t err = B_OK;
if (bdev == NULL)
return B_ERROR;
// TODO: check if device is actually ready for this
// TODO: mutex
if (snbuf != NULL) {
list_add_item(&bdev->nbuffersTx[BT_COMMAND], snbuf);
bdev->nbuffersPendingTx[BT_COMMAND]++;
} else {
err = B_BAD_VALUE;
TRACE("%s: tx sched provoked", __func__);
}
// TODO: check if device is actually ready for this
// TODO: mutex
/* sched in All cases even if nbuf is null (hidden way to provoke
* re-scheduling)
*/
sched_tx_processing(bdev);
return err;
}
↑ V557 Array overrun is possible. The 'BT_SCO' index is pointing beyond array bound.