mirror of
https://github.com/itomato/macusbdb.git
synced 2024-12-28 07:31:05 +00:00
203 lines
6.4 KiB
C
203 lines
6.4 KiB
C
/*******************************************************************
|
|
Copyright (C) 2009 FreakLabs
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
3. Neither the name of the the copyright holder nor the names of its contributors
|
|
may be used to endorse or promote products derived from this software
|
|
without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
SUCH DAMAGE.
|
|
|
|
Originally written by Christopher Wang aka Akiba.
|
|
Please post support questions to the FreakLabs forum.
|
|
|
|
*******************************************************************/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "chb.h"
|
|
#include "chb_drvr.h"
|
|
#include "chb_buf.h"
|
|
|
|
static chb_pcb_t pcb;
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
|
|
*/
|
|
/**************************************************************************/
|
|
void chb_init()
|
|
{
|
|
memset(&pcb, 0, sizeof(chb_pcb_t));
|
|
pcb.src_addr = chb_get_short_addr();
|
|
chb_drvr_init();
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
|
|
*/
|
|
/**************************************************************************/
|
|
chb_pcb_t *chb_get_pcb()
|
|
{
|
|
return &pcb;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
Requires the dest addr, location to store data, and len of payload.
|
|
Returns the length of the hdr.
|
|
*/
|
|
/**************************************************************************/
|
|
static U8 chb_gen_hdr(U8 *hdr, U16 addr, U8 len)
|
|
{
|
|
U8 *hdr_ptr = hdr;
|
|
|
|
// calc frame size and put in 0 position of array
|
|
// frame size = hdr sz + payload len + fcs len
|
|
*hdr_ptr++ = CHB_HDR_SZ + len + CHB_FCS_LEN;
|
|
|
|
// use default fcf byte 0 val but test for ack request. we won't request
|
|
// ack if broadcast. all other cases we will.
|
|
*hdr_ptr++ = CHB_FCF_BYTE_0 | ((addr != 0xFFFF) << CHB_ACK_REQ_POS);
|
|
*hdr_ptr++ = CHB_FCF_BYTE_1;
|
|
|
|
*hdr_ptr++ = pcb.seq++;
|
|
|
|
// fill out dest pan ID, dest addr, src addr
|
|
*(U16 *)hdr_ptr = CHB_PAN_ID;
|
|
hdr_ptr += sizeof(U16);
|
|
*(U16 *)hdr_ptr = addr;
|
|
hdr_ptr += sizeof(U16);
|
|
*(U16 *)hdr_ptr = pcb.src_addr;
|
|
hdr_ptr += sizeof(U16);
|
|
|
|
// return the len of the header
|
|
return hdr_ptr - hdr;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
|
|
*/
|
|
/**************************************************************************/
|
|
U8 chb_write(U16 addr, U8 *data, U8 len)
|
|
{
|
|
U8 status, frm_len, hdr_len, hdr[CHB_HDR_SZ + 1];
|
|
|
|
while (len > 0)
|
|
{
|
|
// calculate which frame len to use. if greater than max payload, split
|
|
// up operation.
|
|
frm_len = (len > CHB_MAX_PAYLOAD) ? CHB_MAX_PAYLOAD : len;
|
|
|
|
// gen frame header
|
|
hdr_len = chb_gen_hdr(hdr, addr, len);
|
|
|
|
// send data to chip
|
|
status = chb_tx(hdr, data, len);
|
|
|
|
if (status != CHB_SUCCESS)
|
|
{
|
|
switch (status)
|
|
{
|
|
case RADIO_SUCCESS:
|
|
// fall through
|
|
case CHB_SUCCESS_DATA_PENDING:
|
|
pcb.txd_success++;
|
|
break;
|
|
|
|
case CHB_NO_ACK:
|
|
pcb.txd_noack++;
|
|
break;
|
|
|
|
case CHB_CHANNEL_ACCESS_FAILURE:
|
|
pcb.txd_channel_fail++;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
// adjust len and restart
|
|
len = len - frm_len;
|
|
}
|
|
return CHB_SUCCESS;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
Read data from the buffer. Need to pass in a buffer of at leasts max frame
|
|
size and two 16-bit containers for the src and dest addresses.
|
|
|
|
The read function will automatically populate the addresses and the data with
|
|
the frm payload. It will then return the len of the payload.
|
|
*/
|
|
/**************************************************************************/
|
|
U8 chb_read(chb_rx_data_t *rx)
|
|
{
|
|
U8 i, len, *data_ptr;
|
|
|
|
data_ptr = rx->data;
|
|
|
|
// first byte is always len. check it to make sure
|
|
// we have a valid len byte.
|
|
if ((len = chb_buf_read()) > CHB_MAX_FRAME_LENGTH)
|
|
{
|
|
return 0;
|
|
}
|
|
*data_ptr++ = len;
|
|
|
|
// load the rest of the data into buffer
|
|
for (i=0; i<len; i++)
|
|
{
|
|
*data_ptr++ = chb_buf_read();
|
|
}
|
|
|
|
// we're using the buffer that's fed in as an argument as a temp
|
|
// buffer as well to save resources.
|
|
// we'll use it as temp storage to parse the frame. then move the frame
|
|
// down so that only the payload will be in the buffer.
|
|
|
|
// parse the buffer and extract the dest and src addresses
|
|
data_ptr = rx->data + 6; // location of dest addr
|
|
rx->dest_addr = *(U16 *)data_ptr;
|
|
data_ptr += sizeof(U16);
|
|
rx->src_addr = *(U16 *)data_ptr;
|
|
data_ptr += sizeof(U16);
|
|
|
|
// move the payload down to the beginning of the data buffer
|
|
memmove(rx->data, data_ptr, len - CHB_HDR_SZ);
|
|
|
|
// if the data in the rx buf is 0, then clear the rx_flag. otherwise, keep it raised
|
|
if (!chb_buf_get_len())
|
|
{
|
|
pcb.data_rcv = false;
|
|
}
|
|
|
|
// finally, return the len of the payload
|
|
return len - CHB_HDR_SZ - CHB_FCS_LEN;
|
|
}
|
|
|