summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominic Spill <dominicgs@gmail.com>2013-05-24 09:56:34 +1000
committerDominic Spill <dominicgs@gmail.com>2013-05-24 09:56:34 +1000
commit3342bb36566249fa80891f2b394445dcb30f60c2 (patch)
tree68d0c4f8a29ce318a2eba7b2eed7a8a03a1a6efc
parent76eae1b582f71813371cbd7e901a4f8e1b07c7e6 (diff)
Reorganise bluetooth_rxtx firmware
- split out USB handling - remove unused functions - merge duplicate code
-rw-r--r--firmware/bluetooth_rxtx/Makefile1
-rw-r--r--firmware/bluetooth_rxtx/bluetooth_rxtx.c745
-rw-r--r--firmware/bluetooth_rxtx/ubertooth_usb.c293
-rw-r--r--firmware/bluetooth_rxtx/ubertooth_usb.h64
4 files changed, 594 insertions, 509 deletions
diff --git a/firmware/bluetooth_rxtx/Makefile b/firmware/bluetooth_rxtx/Makefile
index fc86889..278b43e 100644
--- a/firmware/bluetooth_rxtx/Makefile
+++ b/firmware/bluetooth_rxtx/Makefile
@@ -7,6 +7,7 @@ TARGET = bluetooth_rxtx
SRC = $(TARGET).c \
bluetooth.c \
bluetooth_le.c \
+ ubertooth_usb.c \
$(LIBS_PATH)/usb_serial.c \
$(LIBS_PATH)/serial_fifo.c \
$(LIBS_PATH)/LPC17xx_Startup.c \
diff --git a/firmware/bluetooth_rxtx/bluetooth_rxtx.c b/firmware/bluetooth_rxtx/bluetooth_rxtx.c
index 545aadc..16935bb 100644
--- a/firmware/bluetooth_rxtx/bluetooth_rxtx.c
+++ b/firmware/bluetooth_rxtx/bluetooth_rxtx.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2010 Michael Ossmann
+ * Copyright 2010-2013 Michael Ossmann
+ * Copyright 2011-2013 Dominic Spill
*
* This file is part of Project Ubertooth.
*
@@ -19,38 +20,10 @@
* Boston, MA 02110-1301, USA.
*/
-/*
- LPCUSB, an USB device driver for LPC microcontrollers
- Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
-
- 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. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-*/
-
#include <string.h>
#include "ubertooth.h"
-#include "usbapi.h"
-#include "usbhw_lpc.h"
+#include "ubertooth_usb.h"
#include "ubertooth_interface.h"
#include "bluetooth.h"
#include "bluetooth_le.h"
@@ -59,6 +32,9 @@
typedef void (*IAP)(u32[], u32[]);
IAP iap_entry = (IAP)IAP_LOCATION;
+#define MIN(x,y) ((x)<(y)?(x):(y))
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
/*
* CLK100NS is a free-running clock with a period of 100 ns. It resets every
* 2^15 * 10^5 cycles (about 5.5 minutes) - computed from clkn and timer0 (T0TC)
@@ -90,7 +66,6 @@ volatile u8 cs_trigger; // set by intr on P2.2 falling (CS)
volatile u8 keepalive_trigger; // set by timer 1/s
volatile u32 cs_timestamp; // CLK100NS at time of cs_trigger
u16 hop_direct_channel = 0; // for hopping directly to a channel
-u32 last_usb_pkt = 0; // for keep alive packets
int clock_trim = 0; // to counteract clock drift
u32 idle_buf_clkn_high;
u32 active_buf_clkn_high;
@@ -100,6 +75,17 @@ u32 idle_buf_channel = 0;
u32 active_buf_channel = 0;
u8 slave_mac_address[6] = { 0, };
+/* DMA buffers */
+u8 rxbuf1[DMA_SIZE];
+u8 rxbuf2[DMA_SIZE];
+
+/*
+ * The active buffer is the one with an active DMA transfer.
+ * The idle buffer is the one we can read/write between transfers.
+ */
+u8 *active_rxbuf = &rxbuf1[0];
+u8 *idle_rxbuf = &rxbuf2[0];
+
le_state_t le = {
.access_address = 0x8e89bed6, // advertising channel access address
.crc_init = 0x555555, // advertising channel CRCInit
@@ -125,24 +111,6 @@ int16_t rssi_iir[79] = {0};
*/
#define CLK_TUNE_TIME 2250
-#define BULK_IN_EP 0x82
-#define BULK_OUT_EP 0x05
-
-#define MAX_PACKET_SIZE 64
-
-#define LE_WORD(x) ((x)&0xFF),((x)>>8)
-
-/* DMA buffers */
-u8 rxbuf1[DMA_SIZE];
-u8 rxbuf2[DMA_SIZE];
-
-/*
- * The active buffer is the one with an active DMA transfer.
- * The idle buffer is the one we can read/write between transfers.
- */
-u8 *active_rxbuf = &rxbuf1[0];
-u8 *idle_rxbuf = &rxbuf2[0];
-
/* Unpacked symbol buffers (two rxbufs) */
char unpacked[DMA_SIZE*8*2];
@@ -248,71 +216,12 @@ static void cs_threshold_set(int8_t level, u8 samples)
cs_no_squelch = (level <= -120);
}
-static void cs_threshold_calc_and_set(void)
-{
- int8_t level;
-
- /* If threshold is max/avg based (>0), reset here while rx is
- * off. TODO - max-to-iir only works in SWEEP mode, where the
- * channel is known to be in the BT band, i.e., rssi_iir has a
- * value for it. */
- if ((hop_mode > 0) && (cs_threshold_req > 0)) {
- int8_t rssi = (int8_t)((rssi_iir[channel-2402] + 128)/256);
- level = rssi - 54 + cs_threshold_req;
- }
- else {
- level = cs_threshold_req;
- }
- cs_threshold_set(level, CS_SAMPLES_4);
-}
-
-/* CS comes from CC2400 GIO6, which is LPC P2.2, active low. GPIO
- * triggers EINT3, which could be used for other things (but is not
- * currently). TODO - EINT3 should be managed globally, not turned on
- * and off here. */
-static void cs_trigger_enable(void)
-{
- cs_trigger = 0;
- ISER0 = ISER0_ISE_EINT3;
- IO2IntClr = PIN_GIO6; // Clear pending
- IO2IntEnF |= PIN_GIO6; // Enable port 2.2 falling (CS active low)
-}
-
-static void cs_trigger_disable(void)
-{
- IO2IntEnF &= ~PIN_GIO6; // Disable port 2.2 falling (CS active low)
- IO2IntClr = PIN_GIO6; // Clear pending
- ICER0 = ICER0_ICE_EINT3;
- cs_trigger = 0;
-}
-
-/*
- * This is supposed to be a lock-free ring buffer, but I haven't verified
- * atomicity of the operations on head and tail.
- */
-
-usb_pkt_rx fifo[128];
-
-volatile u32 head = 0;
-volatile u32 tail = 0;
-
-void queue_init()
-{
- head = 0;
- tail = 0;
-}
-
static int enqueue(u8 *buf)
{
- int i;
- u8 h = head & 0x7F;
- u8 t = tail & 0x7F;
- u8 n = (t + 1) & 0x7F;
-
- usb_pkt_rx *f = &fifo[t];
+ usb_pkt_rx *f = usb_enqueue();
/* fail if queue is full */
- if (h == n) {
+ if (f == NULL) {
status |= FIFO_OVERFLOW;
return 0;
}
@@ -332,7 +241,7 @@ static int enqueue(u8 *buf)
USRLED_SET;
// Unrolled copy of 50 bytes from buf to fifo
- u32 *p1 = (u32 *)fifo[t].data;
+ u32 *p1 = (u32 *)f->data;
u32 *p2 = (u32 *)buf;
p1[0] = p2[0];
p1[1] = p2[1];
@@ -346,164 +255,54 @@ static int enqueue(u8 *buf)
p1[9] = p2[9];
p1[10] = p2[10];
p1[11] = p2[11];
- *(u16 *)&(fifo[t].data[48]) = *(u16 *)&(buf[48]);
+ *(u16 *)&(f->data[48]) = *(u16 *)&(buf[48]);
- fifo[t].status = status;
+ f->status = status;
status = 0;
- ++tail;
return 1;
}
-static usb_pkt_rx *dequeue()
+static void cs_threshold_calc_and_set(void)
{
- u8 h = head & 0x7F;
- u8 t = tail & 0x7F;
+ int8_t level;
- /* fail if queue is empty */
- if (h == t) {
- USRLED_CLR;
- return NULL;
+ /* If threshold is max/avg based (>0), reset here while rx is
+ * off. TODO - max-to-iir only works in SWEEP mode, where the
+ * channel is known to be in the BT band, i.e., rssi_iir has a
+ * value for it. */
+ if ((hop_mode > 0) && (cs_threshold_req > 0)) {
+ int8_t rssi = (int8_t)((rssi_iir[channel-2402] + 128)/256);
+ level = rssi - 54 + cs_threshold_req;
}
-
- ++head;
-
- return &fifo[h];
-}
-
-#define USB_KEEP_ALIVE 400000
-static int dequeue_send()
-{
- usb_pkt_rx *pkt = dequeue(&pkt);
- if (pkt != NULL) {
- last_usb_pkt = clkn;
- USBHwEPWrite(BULK_IN_EP, (u8 *)pkt, sizeof(usb_pkt_rx));
- return 1;
- } else {
- if (clkn - last_usb_pkt > USB_KEEP_ALIVE) {
- u8 pkt_type = KEEP_ALIVE;
- last_usb_pkt = clkn;
- USBHwEPWrite(BULK_IN_EP, &pkt_type, 1);
- }
- return 0;
+ else {
+ level = cs_threshold_req;
}
+ cs_threshold_set(level, CS_SAMPLES_4);
}
-
-#ifdef UBERTOOTH_ZERO
-#define ID_VENDOR 0x1D50
-#define ID_PRODUCT 0x6000
-#elif defined UBERTOOTH_ONE
-#define ID_VENDOR 0x1D50
-#define ID_PRODUCT 0x6002
-#elif defined TC13BADGE
-#define ID_VENDOR 0xFFFF
-#define ID_PRODUCT 0x0004
-#else
-#define ID_VENDOR 0xFFFF
-#define ID_PRODUCT 0x0004
-#endif
-
-
-static const u8 abDescriptors[] = {
-
-/* Device descriptor */
- 0x12,
- DESC_DEVICE,
- LE_WORD(0x0200), // bcdUSB
- 0xFF, // bDeviceClass
- 0x00, // bDeviceSubClass
- 0x00, // bDeviceProtocol
- MAX_PACKET_SIZE0, // bMaxPacketSize
- LE_WORD(ID_VENDOR), // idVendor
- LE_WORD(ID_PRODUCT), // idProduct
- LE_WORD(0x0100), // bcdDevice
- 0x01, // iManufacturer
- 0x02, // iProduct
- 0x03, // iSerialNumber
- 0x01, // bNumConfigurations
-
-// configuration
- 0x09,
- DESC_CONFIGURATION,
- LE_WORD(0x20), // wTotalLength
- 0x01, // bNumInterfaces
- 0x01, // bConfigurationValue
- 0x00, // iConfiguration
- 0x80, // bmAttributes
- 0x32, // bMaxPower
-
-// interface
- 0x09,
- DESC_INTERFACE,
- 0x00, // bInterfaceNumber
- 0x00, // bAlternateSetting
- 0x02, // bNumEndPoints
- 0xFF, // bInterfaceClass
- 0x00, // bInterfaceSubClass
- 0x00, // bInterfaceProtocol
- 0x00, // iInterface
-
-// bulk in
- 0x07,
- DESC_ENDPOINT,
- BULK_IN_EP, // bEndpointAddress
- 0x02, // bmAttributes = BULK
- LE_WORD(MAX_PACKET_SIZE),// wMaxPacketSize
- 0, // bInterval
-
-// bulk out
- 0x07,
- DESC_ENDPOINT,
- BULK_OUT_EP, // bEndpointAddress
- 0x02, // bmAttributes = BULK
- LE_WORD(MAX_PACKET_SIZE),// wMaxPacketSize
- 0, // bInterval
-
-// string descriptors
- 0x04,
- DESC_STRING,
- LE_WORD(0x0409),
-
- // manufacturer string
- 0x44,
- DESC_STRING,
- 'h', 0, 't', 0, 't', 0, 'p', 0, ':', 0, '/', 0, '/', 0, 'u', 0,
- 'b', 0, 'e', 0, 'r', 0, 't', 0, 'o', 0, 'o', 0, 't', 0, 'h', 0,
- '.', 0, 's', 0, 'o', 0, 'u', 0, 'r', 0, 'c', 0, 'e', 0, 'f', 0,
- 'o', 0, 'r', 0, 'g', 0, 'e', 0, '.', 0, 'n', 0, 'e', 0, 't', 0,
- '/', 0,
-
- // product string
- 0x1E,
- DESC_STRING,
- 'b', 0, 'l', 0, 'u', 0, 'e', 0, 't', 0, 'o', 0, 'o', 0, 't', 0, 'h', 0, '_', 0,
- 'r', 0, 'x', 0, 't', 0, 'x', 0,
-
- // serial number string
- 0x12,
- DESC_STRING,
- '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '1', 0,
-
- // terminator
- 0
-};
-
-static u8 abVendorReqData[258];
-
-static void usb_bulk_in_handler(u8 bEP, u8 bEPStatus)
+/* CS comes from CC2400 GIO6, which is LPC P2.2, active low. GPIO
+ * triggers EINT3, which could be used for other things (but is not
+ * currently). TODO - EINT3 should be managed globally, not turned on
+ * and off here. */
+static void cs_trigger_enable(void)
{
- if (!(bEPStatus & EP_STATUS_DATA))
- dequeue_send();
+ cs_trigger = 0;
+ ISER0 = ISER0_ISE_EINT3;
+ IO2IntClr = PIN_GIO6; // Clear pending
+ IO2IntEnF |= PIN_GIO6; // Enable port 2.2 falling (CS active low)
}
-static void usb_bulk_out_handler(u8 bEP, u8 bEPStatus)
+static void cs_trigger_disable(void)
{
+ IO2IntEnF &= ~PIN_GIO6; // Disable port 2.2 falling (CS active low)
+ IO2IntClr = PIN_GIO6; // Clear pending
+ ICER0 = ICER0_ICE_EINT3;
+ cs_trigger = 0;
}
-static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **ppbData)
+static int vendor_request_handler(u8 request, u16 *request_params, u8 *data, int *data_len)
{
- u8 *pbData = *ppbData;
u32 command[5];
u32 result[5];
u64 ac_copy;
@@ -514,63 +313,63 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
usb_pkt_rx *p = NULL;
u16 reg_val;
- switch (pSetup->bRequest) {
+ switch (request) {
case UBERTOOTH_PING:
- *piLen = 0;
+ *data_len = 0;
break;
case UBERTOOTH_RX_SYMBOLS:
requested_mode = MODE_RX_SYMBOLS;
- rx_pkts += pSetup->wValue;
+ rx_pkts += request_params[0];
if (rx_pkts == 0)
rx_pkts = 0xFFFFFFFF;
- *piLen = 0;
+ *data_len = 0;
break;
case UBERTOOTH_GET_USRLED:
- pbData[0] = (USRLED) ? 1 : 0;
- *piLen = 1;
+ data[0] = (USRLED) ? 1 : 0;
+ *data_len = 1;
break;
case UBERTOOTH_SET_USRLED:
- if (pSetup->wValue)
+ if (request_params[0])
USRLED_SET;
else
USRLED_CLR;
break;
case UBERTOOTH_GET_RXLED:
- pbData[0] = (RXLED) ? 1 : 0;
- *piLen = 1;
+ data[0] = (RXLED) ? 1 : 0;
+ *data_len = 1;
break;
case UBERTOOTH_SET_RXLED:
- if (pSetup->wValue)
+ if (request_params[0])
RXLED_SET;
else
RXLED_CLR;
break;
case UBERTOOTH_GET_TXLED:
- pbData[0] = (TXLED) ? 1 : 0;
- *piLen = 1;
+ data[0] = (TXLED) ? 1 : 0;
+ *data_len = 1;
break;
case UBERTOOTH_SET_TXLED:
- if (pSetup->wValue)
+ if (request_params[0])
TXLED_SET;
else
TXLED_CLR;
break;
case UBERTOOTH_GET_1V8:
- pbData[0] = (CC1V8) ? 1 : 0;
- *piLen = 1;
+ data[0] = (CC1V8) ? 1 : 0;
+ *data_len = 1;
break;
case UBERTOOTH_SET_1V8:
- if (pSetup->wValue)
+ if (request_params[0])
CC1V8_SET;
else
CC1V8_CLR;
@@ -579,12 +378,12 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
case UBERTOOTH_GET_PARTNUM:
command[0] = 54; /* read part number */
iap_entry(command, result);
- pbData[0] = result[0] & 0xFF; /* status */
- pbData[1] = result[1] & 0xFF;
- pbData[2] = (result[1] >> 8) & 0xFF;
- pbData[3] = (result[1] >> 16) & 0xFF;
- pbData[4] = (result[1] >> 24) & 0xFF;
- *piLen = 5;
+ data[0] = result[0] & 0xFF; /* status */
+ data[1] = result[1] & 0xFF;
+ data[2] = (result[1] >> 8) & 0xFF;
+ data[3] = (result[1] >> 16) & 0xFF;
+ data[4] = (result[1] >> 24) & 0xFF;
+ *data_len = 5;
break;
case UBERTOOTH_RESET:
@@ -594,46 +393,46 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
case UBERTOOTH_GET_SERIAL:
command[0] = 58; /* read device serial number */
iap_entry(command, result);
- pbData[0] = result[0] & 0xFF; /* status */
- pbData[1] = result[1] & 0xFF;
- pbData[2] = (result[1] >> 8) & 0xFF;
- pbData[3] = (result[1] >> 16) & 0xFF;
- pbData[4] = (result[1] >> 24) & 0xFF;
- pbData[5] = result[2] & 0xFF;
- pbData[6] = (result[2] >> 8) & 0xFF;
- pbData[7] = (result[2] >> 16) & 0xFF;
- pbData[8] = (result[2] >> 24) & 0xFF;
- pbData[9] = result[3] & 0xFF;
- pbData[10] = (result[3] >> 8) & 0xFF;
- pbData[11] = (result[3] >> 16) & 0xFF;
- pbData[12] = (result[3] >> 24) & 0xFF;
- pbData[13] = result[4] & 0xFF;
- pbData[14] = (result[4] >> 8) & 0xFF;
- pbData[15] = (result[4] >> 16) & 0xFF;
- pbData[16] = (result[4] >> 24) & 0xFF;
- *piLen = 17;
+ data[0] = result[0] & 0xFF; /* status */
+ data[1] = result[1] & 0xFF;
+ data[2] = (result[1] >> 8) & 0xFF;
+ data[3] = (result[1] >> 16) & 0xFF;
+ data[4] = (result[1] >> 24) & 0xFF;
+ data[5] = result[2] & 0xFF;
+ data[6] = (result[2] >> 8) & 0xFF;
+ data[7] = (result[2] >> 16) & 0xFF;
+ data[8] = (result[2] >> 24) & 0xFF;
+ data[9] = result[3] & 0xFF;
+ data[10] = (result[3] >> 8) & 0xFF;
+ data[11] = (result[3] >> 16) & 0xFF;
+ data[12] = (result[3] >> 24) & 0xFF;
+ data[13] = result[4] & 0xFF;
+ data[14] = (result[4] >> 8) & 0xFF;
+ data[15] = (result[4] >> 16) & 0xFF;
+ data[16] = (result[4] >> 24) & 0xFF;
+ *data_len = 17;
break;
#ifdef UBERTOOTH_ONE
case UBERTOOTH_GET_PAEN:
- pbData[0] = (PAEN) ? 1 : 0;
- *piLen = 1;
+ data[0] = (PAEN) ? 1 : 0;
+ *data_len = 1;
break;
case UBERTOOTH_SET_PAEN:
- if (pSetup->wValue)
+ if (request_params[0])
PAEN_SET;
else
PAEN_CLR;
break;
case UBERTOOTH_GET_HGM:
- pbData[0] = (HGM) ? 1 : 0;
- *piLen = 1;
+ data[0] = (HGM) ? 1 : 0;
+ *data_len = 1;
break;
case UBERTOOTH_SET_HGM:
- if (pSetup->wValue)
+ if (request_params[0])
HGM_SET;
else
HGM_CLR;
@@ -646,15 +445,15 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
break;
case UBERTOOTH_GET_PALEVEL:
- pbData[0] = cc2400_get(FREND) & 0x7;
- *piLen = 1;
+ data[0] = cc2400_get(FREND) & 0x7;
+ *data_len = 1;
break;
case UBERTOOTH_SET_PALEVEL:
- if( pSetup->wValue < 8 ) {
- cc2400_set(FREND, 8 | pSetup->wValue);
+ if( request_params[0] < 8 ) {
+ cc2400_set(FREND, 8 | request_params[0]);
} else {
- return FALSE;
+ return 0;
}
break;
@@ -668,12 +467,12 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
#endif
case UBERTOOTH_RANGE_CHECK:
- pbData[0] = rr.valid;
- pbData[1] = rr.request_pa;
- pbData[2] = rr.request_num;
- pbData[3] = rr.reply_pa;
- pbData[4] = rr.reply_num;
- *piLen = 5;
+ data[0] = rr.valid;
+ data[1] = rr.request_pa;
+ data[2] = rr.request_num;
+ data[3] = rr.reply_pa;
+ data[4] = rr.reply_num;
+ *data_len = 5;
break;
case UBERTOOTH_STOP:
@@ -681,22 +480,22 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
break;
case UBERTOOTH_GET_MOD:
- pbData[0] = modulation;
- *piLen = 1;
+ data[0] = modulation;
+ *data_len = 1;
break;
case UBERTOOTH_SET_MOD:
- modulation = pSetup->wValue;
+ modulation = request_params[0];
break;
case UBERTOOTH_GET_CHANNEL:
- pbData[0] = channel & 0xFF;
- pbData[1] = (channel >> 8) & 0xFF;
- *piLen = 2;
+ data[0] = channel & 0xFF;
+ data[1] = (channel >> 8) & 0xFF;
+ *data_len = 2;
break;
case UBERTOOTH_SET_CHANNEL:
- requested_channel = pSetup->wValue;
+ requested_channel = request_params[0];
/* bluetooth band sweep mode, start at channel 2402 */
if (requested_channel > MAX_FREQ) {
hop_mode = HOP_SWEEP;
@@ -722,7 +521,7 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
case UBERTOOTH_SET_ISP:
command[0] = 57;
iap_entry(command, result);
- *piLen = 0; /* should never return */
+ *data_len = 0; /* should never return */
break;
case UBERTOOTH_FLASH:
@@ -731,62 +530,60 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
break;
case UBERTOOTH_SPECAN:
- if (pSetup->wValue < 2049 || pSetup->wValue > 3072 ||
- pSetup->wIndex < 2049 || pSetup->wIndex > 3072 ||
- pSetup->wIndex < pSetup->wValue)
- return FALSE;
- low_freq = pSetup->wValue;
- high_freq = pSetup->wIndex;
+ if (request_params[0] < 2049 || request_params[0] > 3072 ||
+ request_params[1] < 2049 || request_params[1] > 3072 ||
+ request_params[1] < request_params[0])
+ return 0;
+ low_freq = request_params[0];
+ high_freq = request_params[1];
requested_mode = MODE_SPECAN;
- *piLen = 0;
+ *data_len = 0;
break;
case UBERTOOTH_LED_SPECAN:
- if (pSetup->wValue > 256)
- return FALSE;
- rssi_threshold = (int8_t)pSetup->wValue;
+ if (request_params[0] > 256)
+ return 0;
+ rssi_threshold = (int8_t)request_params[0];
requested_mode = MODE_LED_SPECAN;
- *piLen = 0;
+ *data_len = 0;
break;
case UBERTOOTH_GET_REV_NUM:
- pbData[0] = 0x00;
- pbData[1] = 0x00;
+ data[0] = 0x00;
+ data[1] = 0x00;
length = (u8)strlen(GIT_DESCRIBE);
- pbData[2] = length;
+ data[2] = length;
- memcpy(&pbData[3], GIT_DESCRIBE, length);
+ memcpy(&data[3], GIT_DESCRIBE, length);
- *piLen = 2 + 1 + length;
+ *data_len = 2 + 1 + length;
break;
case UBERTOOTH_GET_BOARD_ID:
- pbData[0] = BOARD_ID;
- *piLen = 1;
+ data[0] = BOARD_ID;
+ *data_len = 1;
break;
case UBERTOOTH_SET_SQUELCH:
- cs_threshold_req = (int8_t)pSetup->wValue;
+ cs_threshold_req = (int8_t)request_params[0];
cs_threshold_calc_and_set();
break;
case UBERTOOTH_GET_SQUELCH:
- pbData[0] = cs_threshold_req;
- *piLen = 1;
+ data[0] = cs_threshold_req;
+ *data_len = 1;
break;
case UBERTOOTH_SET_BDADDR:
target.address = 0;
target.access_code = 0;
for(i=0; i < 8; i++) {
- target.address |= pbData[i] << 8*i;
+ target.address |= data[i] << 8*i;
}
- for(0; i < 8; i++) {
- target.access_code |= pbData[i+8] << 8*i;
+ for(i=0; i < 8; i++) {
+ target.access_code |= data[i+8] << 8*i;
}
- if(afh_enabled == NULL)
- afh_enabled = 0;
precalc();
break;
@@ -794,7 +591,7 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
clock_offset = 0;
for(i=0; i < 4; i++) {
clock_offset <<= 8;
- clock_offset |= pbData[i];
+ clock_offset |= data[i];
}
clkn += clock_offset;
hop_mode = HOP_BLUETOOTH;
@@ -802,17 +599,17 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
break;
case UBERTOOTH_SET_CLOCK:
- clock = pbData[0] | pbData[1] << 8 | pbData[2] << 16 | pbData[3] << 24;
+ clock = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24;
clkn = clock;
cs_threshold_calc_and_set();
break;
case UBERTOOTH_SET_AFHMAP:
for(i=0; i < 10; i++) {
- afh_map[i] = pbData[i];
+ afh_map[i] = data[i];
}
afh_enabled = 1;
- *piLen = 10;
+ *data_len = 10;
precalc();
break;
@@ -821,23 +618,23 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
afh_map[i] = 0;
}
afh_enabled = 0;
- *piLen = 10;
+ *data_len = 10;
precalc();
break;
case UBERTOOTH_GET_CLOCK:
clock = clkn;
for(i=0; i < 4; i++) {
- pbData[i] = (clock >> (8*i)) & 0xff;
+ data[i] = (clock >> (8*i)) & 0xff;
}
- *piLen = 4;
+ *data_len = 4;
break;
case UBERTOOTH_BTLE_SNIFFING:
- rx_pkts += pSetup->wValue;
+ rx_pkts += request_params[0];
if (rx_pkts == 0)
rx_pkts = 0xFFFFFFFF;
- *piLen = 0;
+ *data_len = 0;
do_hop = 0;
hop_mode = HOP_BTLE;
@@ -849,13 +646,13 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
case UBERTOOTH_GET_ACCESS_ADDRESS:
for(i=0; i < 4; i++) {
- pbData[i] = (le.access_address >> (8*i)) & 0xff;
+ data[i] = (le.access_address >> (8*i)) & 0xff;
}
- *piLen = 4;
+ *data_len = 4;
break;
case UBERTOOTH_SET_ACCESS_ADDRESS:
- le.access_address = pbData[0] | pbData[1] << 8 | pbData[2] << 16 | pbData[3] << 24;
+ le.access_address = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24;
break;
case UBERTOOTH_DO_SOMETHING:
@@ -865,33 +662,33 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
case UBERTOOTH_DO_SOMETHING_REPLY:
// after you do something, tell me what you did!
// don't commit here please
- pbData[0] = 0x13;
- pbData[1] = 0x37;
- *piLen = 2;
+ data[0] = 0x13;
+ data[1] = 0x37;
+ *data_len = 2;
break;
case UBERTOOTH_GET_CRC_VERIFY:
- pbData[0] = le.crc_verify ? 1 : 0;
- *piLen = 1;
+ data[0] = le.crc_verify ? 1 : 0;
+ *data_len = 1;
break;
case UBERTOOTH_SET_CRC_VERIFY:
- le.crc_verify = pSetup->wValue ? 1 : 0;
+ le.crc_verify = request_params[0] ? 1 : 0;
break;
case UBERTOOTH_POLL:
p = dequeue();
if (p != NULL) {
- memcpy(pbData, (void *)p, sizeof(usb_pkt_rx));
- *piLen = sizeof(usb_pkt_rx);
+ memcpy(data, (void *)p, sizeof(usb_pkt_rx));
+ *data_len = sizeof(usb_pkt_rx);
} else {
- pbData[0] = 0;
- *piLen = 1;
+ data[0] = 0;
+ *data_len = 1;
}
break;
case UBERTOOTH_BTLE_PROMISC:
- *piLen = 0;
+ *data_len = 0;
hop_mode = HOP_NONE;
requested_mode = MODE_BT_PROMISC_LE;
@@ -901,45 +698,21 @@ static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **pp
break;
case UBERTOOTH_READ_REGISTER:
- reg_val = cc2400_get(pSetup->wValue);
- pbData[0] = (reg_val >> 8) & 0xff;
- pbData[1] = reg_val & 0xff;
- *piLen = 2;
+ reg_val = cc2400_get(request_params[0]);
+ data[0] = (reg_val >> 8) & 0xff;
+ data[1] = reg_val & 0xff;
+ *data_len = 2;
break;
case UBERTOOTH_BTLE_SLAVE:
- memcpy(slave_mac_address, pbData, 6);
+ memcpy(slave_mac_address, data, 6);
requested_mode = MODE_BT_SLAVE_LE;
break;
default:
- return FALSE;
+ return 0;
}
- return TRUE;
-}
-
-static int ubertooth_usb_init()
-{
- // initialise stack
- USBInit();
-
- // register device descriptors
- USBRegisterDescriptors(abDescriptors);
-
- // override standard request handler
- USBRegisterRequestHandler(REQTYPE_TYPE_VENDOR, usb_vendor_request_handler, abVendorReqData);
-
- // register endpoints
- //USBHwRegisterEPIntHandler(BULK_IN_EP, usb_bulk_in_handler);
- //USBHwRegisterEPIntHandler(BULK_OUT_EP, usb_bulk_out_handler);
-
- // enable USB interrupts
- //ISER0 = ISER0_ISE_USB;
-
- // connect to bus
- USBHwConnect(TRUE);
-
- return 0;
+ return 1;
}
static void clkn_init()
@@ -1158,48 +931,6 @@ static void dma_init_le()
rx_err = 0;
}
-/*
- * Flush whatever's in the CC2400's output buffer before going on to
- * receive the next packet.
- */
-static void dma_flush_le()
-{
- /* power up GPDMA controller */
- PCONP |= PCONP_PCGPDMA;
-
- /* zero out channel configs and clear interrupts */
- DMACC0Config = 0;
- DMACC1Config = 0;
- DMACC2Config = 0;
- DMACC3Config = 0;
- DMACC4Config = 0;
- DMACC5Config = 0;
- DMACC6Config = 0;
- DMACC7Config = 0;
- DMACIntTCClear = 0xFF;
- DMACIntErrClr = 0xFF;
-
- /* enable DMA globally */
- DMACConfig = DMACConfig_E;
- while (!(DMACConfig & DMACConfig_E));
-
-
- /* configure DMA channel 0 */
- DMACC0SrcAddr = (u32)&(DIO_SSP_DR);
- DMACC0DestAddr = (u32)&rxbuf1[0];
- DMACC0LLI = (u32)0;
- DMACC0Control = (DMA_SIZE) |
- (1 << 12) | /* source burst size = 4 */
- (1 << 15) | /* destination burst size = 4 */
- (0 << 18) | /* source width 8 bits */
- (0 << 21) ; /* destination width 8 bits */
-
- DMACC0Config =
- DIO_SSP_SRC |
- (0x2 << 11); /* peripheral to memory */
- // XXX no interrupts: we don't care about the data
-}
-
void DMA_IRQHandler()
{
idle_buf_clkn_high = active_buf_clkn_high;
@@ -1265,32 +996,28 @@ static void cc2400_idle()
/* start un-buffered rx */
static void cc2400_rx()
{
+ u16 mdmctrl;
if (modulation == MOD_BT_BASIC_RATE) {
- cc2400_set(LMTST, 0x2b22);
- cc2400_set(MDMTST0, 0x134b); // without PRNG
- cc2400_set(GRMDM, 0x0101); // un-buffered mode, GFSK
- cc2400_set(FSDIV, channel - 1); // 1 MHz IF
- cc2400_set(MDMCTRL, 0x0029); // 160 kHz frequency deviation
+ mdmctrl = 0x0029; // 160 kHz frequency deviation
} else if (modulation == MOD_BT_LOW_ENERGY) {
- cc2400_set(LMTST, 0x2b22);
- cc2400_set(MDMTST0, 0x134b); // without PRNG
-
- cc2400_set(GRMDM, 0x0101); // un-buffered mode, GFSK
- // 0 00 00 0 010 00 0 00 0 1
- // | | | | +--------> CRC off
- // | | | +-----------> sync word: 8 MSB bits of SYNC_WORD
- // | | +---------------> 2 preamble bytes of 01010101
- // | +-----------------> not packet mode
- // +--------------------> un-buffered mode
- //
-
- cc2400_set(FSDIV, channel - 1); // 1 MHz IF
- cc2400_set(MDMCTRL, 0x0040); // 250 kHz frequency deviation
+ mdmctrl = 0x0040; // 250 kHz frequency deviation
} else {
/* oops */
return;
}
+ cc2400_set(LMTST, 0x2b22);
+ cc2400_set(MDMTST0, 0x134b); // without PRNG
+ cc2400_set(GRMDM, 0x0101); // un-buffered mode, GFSK
+ // 0 00 00 0 010 00 0 00 0 1
+ // | | | | +--------> CRC off
+ // | | | +-----------> sync word: 8 MSB bits of SYNC_WORD
+ // | | +---------------> 2 preamble bytes of 01010101
+ // | +-----------------> not packet mode
+ // +--------------------> un-buffered mode
+ cc2400_set(FSDIV, channel - 1); // 1 MHz IF
+ cc2400_set(MDMCTRL, mdmctrl);
+
// Set up CS register
cs_threshold_calc_and_set();
@@ -1304,28 +1031,48 @@ static void cc2400_rx()
#endif
}
-static void cc2400_rx_le_sync()
+/* start un-buffered rx */
+static void cc2400_rx_sync(u32 sync)
{
+ u16 grmdm, mdmctrl;
+
+ if (modulation == MOD_BT_BASIC_RATE) {
+ mdmctrl = 0x0029; // 160 kHz frequency deviation
+ grmdm = 0x0461; // un-buffered mode, packet w/ sync word detection
+ // 0 00 00 1 000 11 0 00 0 1
+ // | | | | | +--------> CRC off
+ // | | | | +-----------> sync word: 32 MSB bits of SYNC_WORD
+ // | | | +---------------> 0 preamble bytes of 01010101
+ // | | +-----------------> packet mode
+ // | +--------------------> un-buffered mode
+ // +-----------------------> sync error bits: 0
+
+ } else if (modulation == MOD_BT_LOW_ENERGY) {
+ mdmctrl = 0x0040; // 250 kHz frequency deviation
+ grmdm = 0x0561; // un-buffered mode, packet w/ sync word detection
+ // 0 00 00 1 010 11 0 00 0 1
+ // | | | | | +--------> CRC off
+ // | | | | +-----------> sync word: 32 MSB bits of SYNC_WORD
+ // | | | +---------------> 2 preamble bytes of 01010101
+ // | | +-----------------> packet mode
+ // | +--------------------> un-buffered mode
+ // +-----------------------> sync error bits: 0
+
+ } else {
+ /* oops */
+ return;
+ }
+
cc2400_set(MANAND, 0x7fff);
cc2400_set(LMTST, 0x2b22);
cc2400_set(MDMTST0, 0x134b); // without PRNG
+ cc2400_set(GRMDM, grmdm);
- cc2400_set(GRMDM, 0x0561); // un-buffered mode, packet w/ sync word detection
- // 0 00 00 1 010 11 0 00 0 1
- // | | | | | +--------> CRC off
- // | | | | +-----------> sync word: 32 MSB bits of SYNC_WORD
- // | | | +---------------> 2 preamble bytes of 01010101
- // | | +-----------------> packet mode
- // | +--------------------> un-buffered mode
- // +-----------------------> sync error bits: 0
-
- // cc2400_set(SYNCH, 0x8e89);
- // cc2400_set(SYNCL, 0xbed6);
- cc2400_set(SYNCH, 0x6b7d); // bit-reversed access address
- cc2400_set(SYNCL, 0x9171);
-
+ cc2400_set(SYNCL, sync & 0xffff);
+ cc2400_set(SYNCH, (sync >> 16) & 0xffff);
+
cc2400_set(FSDIV, channel - 1); // 1 MHz IF
- cc2400_set(MDMCTRL, 0x0040); // 250 kHz frequency deviation
+ cc2400_set(MDMCTRL, mdmctrl);
// Set up CS register
cs_threshold_calc_and_set();
@@ -1340,26 +1087,24 @@ static void cc2400_rx_le_sync()
#endif
}
-
void cc2400_txtest()
{
#ifdef TX_ENABLE
+ u16 mdmctrl;
if (modulation == MOD_BT_BASIC_RATE) {
- cc2400_set(LMTST, 0x2b22);
- cc2400_set(MDMTST0, 0x334b); // with PRNG
- cc2400_set(GRMDM, 0x0df1); // default value
- cc2400_set(FSDIV, channel);
- cc2400_set(MDMCTRL, 0x0029); // 160 kHz frequency deviation
+ mdmctrl = 0x0029; // 160 kHz frequency deviation
} else if (modulation == MOD_BT_LOW_ENERGY) {
- cc2400_set(LMTST, 0x2b22);
- cc2400_set(MDMTST0, 0x334b); // with PRNG
- cc2400_set(GRMDM, 0x0df1); // default value
- cc2400_set(FSDIV, channel);
- cc2400_set(MDMCTRL, 0x0040); // 250 kHz frequency deviation
+ mdmctrl = 0x0040; // 250 kHz frequency deviation
} else {
/* oops */
return;
}
+ cc2400_set(LMTST, 0x2b22);
+ cc2400_set(MDMTST0, 0x334b); // with PRNG
+ cc2400_set(GRMDM, 0x0df1); // default value
+ cc2400_set(FSDIV, channel);
+ cc2400_set(MDMCTRL, mdmctrl);
+
while (!(cc2400_status() & XOSC16M_STABLE));
cc2400_strobe(SFSON);
while (!(cc2400_status() & FS_LOCK));
@@ -1750,24 +1495,6 @@ void hop(void)
}
-static void handle_usb(void)
-{
- u8 epstat;
-
- /* write queued packets to USB if possible */
- epstat = USBHwEPGetStatus(BULK_IN_EP);
- if (!(epstat & EPSTAT_B1FULL)) {
- dequeue_send();
- }
- if (!(epstat & EPSTAT_B2FULL)) {
- dequeue_send();
- }
-
- /* polled "interrupt" */
- USBHwISR();
-}
-
-
/* Bluetooth packet monitoring */
void bt_stream_rx()
{
@@ -1899,7 +1626,7 @@ void bt_stream_rx()
}
rx_continue:
- handle_usb();
+ handle_usb(clkn);
rx_tc = 0;
rx_err = 0;
}
@@ -1932,7 +1659,7 @@ void bt_follow()
dio_ssp_init();
dma_init();
dio_ssp_start();
- cc2400_rx();
+ cc2400_rx_sync(syncword & 0xffffffff);
cs_trigger_enable();
@@ -2031,7 +1758,7 @@ void bt_follow()
//}
rx_continue:
- handle_usb();
+ handle_usb(clkn);
rx_tc = 0;
rx_err = 0;
}
@@ -2207,7 +1934,7 @@ void bt_le_sync(u8 active_mode)
dio_ssp_init();
dma_init_le();
dio_ssp_start();
- cc2400_rx_le_sync();
+ cc2400_rx_sync(0x6b7d9171); // bit-reversed access address
cs_trigger_enable();
@@ -2765,7 +2492,7 @@ void specan()
enqueue(buf);
i = 0;
- handle_usb();
+ handle_usb(clkn);
}
cc2400_strobe(SRFOFF);
@@ -2836,7 +2563,7 @@ void led_specan()
i = (i+1) % 3;
- USBHwISR();
+ handle_usb(clkn);
//wait(1);
cc2400_strobe(SRFOFF);
while ((cc2400_status() & FS_LOCK));
@@ -2848,10 +2575,10 @@ int main()
{
ubertooth_init();
clkn_init();
- ubertooth_usb_init();
+ ubertooth_usb_init(vendor_request_handler);
while (1) {
- USBHwISR();
+ handle_usb(clkn);
if (requested_mode == MODE_RESET) {
/* Allow time for the USB command to return correctly */
wait(1);
diff --git a/firmware/bluetooth_rxtx/ubertooth_usb.c b/firmware/bluetooth_rxtx/ubertooth_usb.c
new file mode 100644
index 0000000..1992b5f
--- /dev/null
+++ b/firmware/bluetooth_rxtx/ubertooth_usb.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2010 Michael Ossmann
+ * Copyright 2013 Dominic Spill
+ *
+ * This file is part of Project Ubertooth.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ LPCUSB, an USB device driver for LPC microcontrollers
+ Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+ 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. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+*/
+
+#include "usbapi.h"
+#include "usbhw_lpc.h"
+#include "ubertooth_usb.h"
+
+#ifdef UBERTOOTH_ZERO
+#define ID_VENDOR 0x1D50
+#define ID_PRODUCT 0x6000
+#elif defined UBERTOOTH_ONE
+#define ID_VENDOR 0x1D50
+#define ID_PRODUCT 0x6002
+#elif defined TC13BADGE
+#define ID_VENDOR 0xFFFF
+#define ID_PRODUCT 0x0004
+#else
+#define ID_VENDOR 0xFFFF
+#define ID_PRODUCT 0x0004
+#endif
+
+#define BULK_IN_EP 0x82
+#define BULK_OUT_EP 0x05
+
+#define MAX_PACKET_SIZE 64
+
+#define LE_WORD(x) ((x)&0xFF),((x)>>8)
+
+/*
+ * This is supposed to be a lock-free ring buffer, but I haven't verified
+ * atomicity of the operations on head and tail.
+ */
+
+const u8 abDescriptors[] = {
+
+/* Device descriptor */
+ 0x12,
+ DESC_DEVICE,
+ LE_WORD(0x0200), // bcdUSB
+ 0xFF, // bDeviceClass
+ 0x00, // bDeviceSubClass
+ 0x00, // bDeviceProtocol
+ MAX_PACKET_SIZE0, // bMaxPacketSize
+ LE_WORD(ID_VENDOR), // idVendor
+ LE_WORD(ID_PRODUCT), // idProduct
+ LE_WORD(0x0100), // bcdDevice
+ 0x01, // iManufacturer
+ 0x02, // iProduct
+ 0x03, // iSerialNumber
+ 0x01, // bNumConfigurations
+
+// configuration
+ 0x09,
+ DESC_CONFIGURATION,
+ LE_WORD(0x20), // wTotalLength
+ 0x01, // bNumInterfaces
+ 0x01, // bConfigurationValue
+ 0x00, // iConfiguration
+ 0x80, // bmAttributes
+ 0x32, // bMaxPower
+
+// interface
+ 0x09,
+ DESC_INTERFACE,
+ 0x00, // bInterfaceNumber
+ 0x00, // bAlternateSetting
+ 0x02, // bNumEndPoints
+ 0xFF, // bInterfaceClass
+ 0x00, // bInterfaceSubClass
+ 0x00, // bInterfaceProtocol
+ 0x00, // iInterface
+
+// bulk in
+ 0x07,
+ DESC_ENDPOINT,
+ BULK_IN_EP, // bEndpointAddress
+ 0x02, // bmAttributes = BULK
+ LE_WORD(MAX_PACKET_SIZE),// wMaxPacketSize
+ 0, // bInterval
+
+// bulk out
+ 0x07,
+ DESC_ENDPOINT,
+ BULK_OUT_EP, // bEndpointAddress
+ 0x02, // bmAttributes = BULK
+ LE_WORD(MAX_PACKET_SIZE),// wMaxPacketSize
+ 0, // bInterval
+
+// string descriptors
+ 0x04,
+ DESC_STRING,
+ LE_WORD(0x0409),
+
+ // manufacturer string
+ 0x44,
+ DESC_STRING,
+ 'h', 0, 't', 0, 't', 0, 'p', 0, ':', 0, '/', 0, '/', 0, 'u', 0,
+ 'b', 0, 'e', 0, 'r', 0, 't', 0, 'o', 0, 'o', 0, 't', 0, 'h', 0,
+ '.', 0, 's', 0, 'o', 0, 'u', 0, 'r', 0, 'c', 0, 'e', 0, 'f', 0,
+ 'o', 0, 'r', 0, 'g', 0, 'e', 0, '.', 0, 'n', 0, 'e', 0, 't', 0,
+ '/', 0,
+
+ // product string
+ 0x1E,
+ DESC_STRING,
+ 'b', 0, 'l', 0, 'u', 0, 'e', 0, 't', 0, 'o', 0, 'o', 0, 't', 0, 'h', 0, '_', 0,
+ 'r', 0, 'x', 0, 't', 0, 'x', 0,
+
+ // serial number string
+ 0x12,
+ DESC_STRING,
+ '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '1', 0,
+
+ // terminator
+ 0
+};
+
+
+u8 abVendorReqData[258];
+
+/* Unused functions
+void usb_bulk_in_handler(u8 bEP, u8 bEPStatus)
+{
+ if (!(bEPStatus & EP_STATUS_DATA))
+ dequeue_send();
+}
+
+void usb_bulk_out_handler(u8 bEP, u8 bEPStatus)
+{
+}
+*/
+
+VendorRequestHandler *v_req_handler;
+
+BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **ppbData)
+{
+ int rv;
+ u16 params[2] = {pSetup->wValue, pSetup->wIndex};
+ rv = v_req_handler(pSetup->bRequest, params, *ppbData, piLen);
+ return (BOOL) (rv==1);
+}
+
+int ubertooth_usb_init(VendorRequestHandler *vendor_req_handler)
+{
+ // initialise stack
+ USBInit();
+
+ // register device descriptors
+ USBRegisterDescriptors(abDescriptors);
+
+ // Request handler
+ v_req_handler = vendor_req_handler;
+
+ // override standard request handler
+ USBRegisterRequestHandler(REQTYPE_TYPE_VENDOR, usb_vendor_request_handler, abVendorReqData);
+
+ // register endpoints
+ //USBHwRegisterEPIntHandler(BULK_IN_EP, usb_bulk_in_handler);
+ //USBHwRegisterEPIntHandler(BULK_OUT_EP, usb_bulk_out_handler);
+
+ // enable USB interrupts
+ //ISER0 = ISER0_ISE_USB;
+
+ // connect to bus
+ USBHwConnect(TRUE);
+
+ return 0;
+}
+
+usb_pkt_rx fifo[128];
+
+volatile u32 head = 0;
+volatile u32 tail = 0;
+
+void queue_init()
+{
+ head = 0;
+ tail = 0;
+}
+
+usb_pkt_rx *usb_enqueue()
+{
+ u8 h = head & 0x7F;
+ u8 t = tail & 0x7F;
+ u8 n = (t + 1) & 0x7F;
+
+ /* fail if queue is full */
+ if (h == n) {
+ return NULL;
+ }
+
+ ++tail;
+ return &fifo[t];
+
+}
+
+usb_pkt_rx *dequeue()
+{
+ u8 h = head & 0x7F;
+ u8 t = tail & 0x7F;
+
+ /* fail if queue is empty */
+ if (h == t) {
+ USRLED_CLR;
+ return NULL;
+ }
+
+ ++head;
+ return &fifo[h];
+}
+
+#define USB_KEEP_ALIVE 400000
+u32 last_usb_pkt = 0; // for keep alive packets
+
+int dequeue_send(u32 clkn)
+{
+ usb_pkt_rx *pkt = dequeue(&pkt);
+ if (pkt != NULL) {
+ last_usb_pkt = clkn;
+ USBHwEPWrite(BULK_IN_EP, (u8 *)pkt, sizeof(usb_pkt_rx));
+ return 1;
+ } else {
+ if (clkn - last_usb_pkt > USB_KEEP_ALIVE) {
+ u8 pkt_type = KEEP_ALIVE;
+ last_usb_pkt = clkn;
+ USBHwEPWrite(BULK_IN_EP, &pkt_type, 1);
+ }
+ return 0;
+ }
+}
+
+void handle_usb(u32 clkn)
+{
+ u8 epstat;
+
+ /* write queued packets to USB if possible */
+ epstat = USBHwEPGetStatus(BULK_IN_EP);
+ if (!(epstat & EPSTAT_B1FULL)) {
+ dequeue_send(clkn);
+ }
+ if (!(epstat & EPSTAT_B2FULL)) {
+ dequeue_send(clkn);
+ }
+
+ /* polled "interrupt" */
+ USBHwISR();
+}
diff --git a/firmware/bluetooth_rxtx/ubertooth_usb.h b/firmware/bluetooth_rxtx/ubertooth_usb.h
new file mode 100644
index 0000000..47490f3
--- /dev/null
+++ b/firmware/bluetooth_rxtx/ubertooth_usb.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010 Michael Ossmann
+ *
+ * This file is part of Project Ubertooth.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ LPCUSB, an USB device driver for LPC microcontrollers
+ Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+ 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. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+*/
+
+
+#ifndef __UBERTOOTH_USB_H
+#define __UBERTOOTH_USB_H
+
+#include "ubertooth.h"
+#include "ubertooth_interface.h"
+
+typedef int (VendorRequestHandler)(u8 request, u16 *request_params, u8 *data, int *data_len);
+
+int ubertooth_usb_init(VendorRequestHandler *vendor_req_handler);
+void queue_init();
+usb_pkt_rx *usb_enqueue();
+usb_pkt_rx *dequeue();
+void handle_usb(u32 clkn);
+
+#endif /* __UBERTOOTH_USB_H */