2009-10-29 20:25:42 +00:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2009 by Matthias Ringwald
|
|
|
|
|
*
|
|
|
|
|
* 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 copyright holders nor the names of
|
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD 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 MATTHIAS
|
|
|
|
|
* RINGWALD 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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2009-07-05 21:06:38 +00:00
|
|
|
|
/*
|
|
|
|
|
* hci_transport_usb.c
|
|
|
|
|
*
|
2009-07-08 22:21:02 +00:00
|
|
|
|
* HCI Transport API implementation for USB
|
|
|
|
|
*
|
2009-07-05 21:06:38 +00:00
|
|
|
|
* Created by Matthias Ringwald on 7/5/09.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// this is not even alpha... :)
|
|
|
|
|
|
|
|
|
|
// delock bt class 2 - csr
|
|
|
|
|
// 0a12:0001 (bus 27, device 2)
|
|
|
|
|
|
|
|
|
|
// Interface Number - Alternate Setting - suggested Endpoint Address - Endpoint Type - Suggested Max Packet Size
|
|
|
|
|
// HCI Commands 0 0 0x00 Control 8/16/32/64
|
|
|
|
|
// HCI Events 0 0 0x81 Interrupt (IN) 16
|
|
|
|
|
// ACL Data 0 0 0x82 Bulk (IN) 32/64
|
|
|
|
|
// ACL Data 0 0 0x02 Bulk (OUT) 32/64
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2009-07-08 22:21:02 +00:00
|
|
|
|
#include <strings.h>
|
|
|
|
|
#include <unistd.h> /* UNIX standard function definitions */
|
2009-07-05 21:06:38 +00:00
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
|
|
#include <libusb-1.0/libusb.h>
|
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
#include "hci.h"
|
2010-06-04 18:10:12 +00:00
|
|
|
|
#include "hci_transport.h"
|
2009-07-08 22:21:02 +00:00
|
|
|
|
#include "hci_dump.h"
|
|
|
|
|
|
|
|
|
|
// prototypes
|
|
|
|
|
static void dummy_handler(uint8_t *packet, int size);
|
|
|
|
|
static int usb_close();
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
LIB_USB_CLOSED,
|
|
|
|
|
LIB_USB_OPENED,
|
|
|
|
|
LIB_USB_DEVICE_OPENDED,
|
|
|
|
|
LIB_USB_KERNEL_DETACHED,
|
|
|
|
|
LIB_USB_INTERFACE_CLAIMED,
|
|
|
|
|
LIB_USB_TRANSFERS_ALLOCATED
|
|
|
|
|
} libusb_state = LIB_USB_CLOSED;
|
|
|
|
|
|
|
|
|
|
// single instance
|
|
|
|
|
static hci_transport_t * hci_transport_usb = NULL;
|
|
|
|
|
|
2010-07-18 16:14:55 +00:00
|
|
|
|
static void (*packet_handler)(uint8_t *packet, int size) = dummy_handler;
|
2009-07-08 22:21:02 +00:00
|
|
|
|
|
2010-07-25 12:28:23 +00:00
|
|
|
|
static uint8_t hci_cmd_out[HCI_ACL_3DH5_SIZE]; // bigger than largest packet
|
|
|
|
|
static uint8_t hci_event_buffer[HCI_ACL_3DH5_SIZE]; // bigger than largest packet
|
|
|
|
|
static uint8_t hci_acl_in[HCI_ACL_3DH5_SIZE]; // bigger than largest packet
|
2009-07-08 22:21:02 +00:00
|
|
|
|
|
|
|
|
|
// libusb
|
|
|
|
|
static struct libusb_device_descriptor desc;
|
|
|
|
|
static libusb_device * dev;
|
|
|
|
|
static libusb_device_handle * handle;
|
|
|
|
|
static struct libusb_transfer *interrupt_transfer;
|
|
|
|
|
static struct libusb_transfer *control_transfer;
|
2009-10-18 20:49:27 +00:00
|
|
|
|
static struct libusb_transfer *bulk_in_transfer;
|
|
|
|
|
static struct libusb_transfer *bulk_out_transfer;
|
|
|
|
|
|
2009-07-05 21:06:38 +00:00
|
|
|
|
|
|
|
|
|
int find_bt(libusb_device **devs)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
while ((dev = devs[i++]) != NULL) {
|
|
|
|
|
int r = libusb_get_device_descriptor(dev, &desc);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
fprintf(stderr, "failed to get device descriptor");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("%04x:%04x (bus %d, device %d) - class %x subclass %x protocol %x \n",
|
|
|
|
|
desc.idVendor, desc.idProduct,
|
|
|
|
|
libusb_get_bus_number(dev), libusb_get_device_address(dev),
|
|
|
|
|
desc.bDeviceClass, desc.bDeviceSubClass, desc.bDeviceProtocol);
|
|
|
|
|
|
2009-07-31 21:41:15 +00:00
|
|
|
|
// @TODO: detect BT USB Dongle based on character and not by id
|
2009-07-06 21:40:30 +00:00
|
|
|
|
// The class code (bDeviceClass) is 0xE0 – Wireless Controller.
|
|
|
|
|
// The SubClass code (bDeviceSubClass) is 0x01 – RF Controller.
|
|
|
|
|
// The Protocol code (bDeviceProtocol) is 0x01 – Bluetooth programming.
|
|
|
|
|
if (desc.bDeviceClass == 0xe0 && desc.bDeviceSubClass == 0x01 && desc.bDeviceProtocol == 0x01){
|
|
|
|
|
// if (desc.idVendor == 0x0a12 && desc.idProduct == 0x0001){
|
2009-07-05 21:06:38 +00:00
|
|
|
|
printf("BT Dongle found.\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-06 21:40:30 +00:00
|
|
|
|
static void control_callback(struct libusb_transfer *transfer){
|
|
|
|
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
|
|
|
|
fprintf(stderr, "control_callback not completed!\n");
|
2009-07-08 22:21:02 +00:00
|
|
|
|
return;
|
2009-07-06 21:40:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
printf("control_callback length=%d actual_length=%d\n",
|
2009-07-06 21:40:30 +00:00
|
|
|
|
transfer->length, transfer->actual_length);
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-18 20:49:27 +00:00
|
|
|
|
static void bulk_out_callback(struct libusb_transfer *transfer){
|
|
|
|
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
|
|
|
|
fprintf(stderr, "bulk_out_callback not completed!\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("bulk_out_callback length=%d actual_length=%d\n",
|
|
|
|
|
transfer->length, transfer->actual_length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-07-06 21:40:30 +00:00
|
|
|
|
static void event_callback(struct libusb_transfer *transfer)
|
|
|
|
|
{
|
2009-10-18 20:49:27 +00:00
|
|
|
|
printf("event_callback length=%d actual_length=%d: ",
|
|
|
|
|
transfer->length, transfer->actual_length);
|
|
|
|
|
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
|
2009-07-08 22:21:02 +00:00
|
|
|
|
int i;
|
|
|
|
|
for (i=0;i<transfer->actual_length; i++) printf("0x%02x ", transfer->buffer[i]);
|
|
|
|
|
printf("\n");
|
2009-07-06 21:40:30 +00:00
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
hci_dump_packet( HCI_EVENT_PACKET, 1, transfer->buffer, transfer->actual_length);
|
|
|
|
|
event_packet_handler(transfer->buffer, transfer->actual_length);
|
|
|
|
|
}
|
2009-10-18 21:06:57 +00:00
|
|
|
|
int r = libusb_submit_transfer(transfer);
|
2009-07-06 21:40:30 +00:00
|
|
|
|
if (r) {
|
|
|
|
|
printf("Error submitting interrupt transfer %d\n", r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-18 20:49:27 +00:00
|
|
|
|
static void bulk_in_callback(struct libusb_transfer *transfer)
|
|
|
|
|
{
|
2009-10-18 21:06:57 +00:00
|
|
|
|
printf("bulk_in_callback length=%d actual_length=%d: \n",
|
2009-10-18 20:49:27 +00:00
|
|
|
|
transfer->length, transfer->actual_length);
|
|
|
|
|
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
|
|
|
|
|
int i;
|
|
|
|
|
for (i=0;i<transfer->actual_length; i++) printf("0x%02x ", transfer->buffer[i]);
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
hci_dump_packet( HCI_EVENT_PACKET, 1, transfer->buffer, transfer->actual_length);
|
|
|
|
|
acl_packet_handler(transfer->buffer, transfer->actual_length);
|
|
|
|
|
}
|
2009-10-18 21:06:57 +00:00
|
|
|
|
int r = libusb_submit_transfer(transfer);
|
2009-10-18 20:49:27 +00:00
|
|
|
|
if (r) {
|
|
|
|
|
printf("Error submitting bulk in transfer %d\n", r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-17 22:38:48 +00:00
|
|
|
|
static int usb_process(struct data_source *ds) {
|
2009-07-08 22:21:02 +00:00
|
|
|
|
if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1;
|
|
|
|
|
struct timeval tv;
|
|
|
|
|
bzero(&tv, sizeof(struct timeval));
|
|
|
|
|
libusb_handle_events_timeout(NULL, &tv);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_open(void *transport_config){
|
|
|
|
|
|
|
|
|
|
libusb_device **devs;
|
2009-07-05 21:06:38 +00:00
|
|
|
|
int r;
|
|
|
|
|
ssize_t cnt;
|
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
// USB init
|
|
|
|
|
r = libusb_init(NULL);
|
|
|
|
|
if (r < 0) {
|
2009-07-05 21:06:38 +00:00
|
|
|
|
return r;
|
2009-07-08 22:21:02 +00:00
|
|
|
|
}
|
|
|
|
|
libusb_state = LIB_USB_OPENED;
|
|
|
|
|
|
|
|
|
|
// Get Devices
|
|
|
|
|
cnt = libusb_get_device_list(NULL, &devs);
|
|
|
|
|
if (cnt < 0) {
|
|
|
|
|
usb_close();
|
|
|
|
|
return (int) cnt;
|
|
|
|
|
}
|
|
|
|
|
// Find BT modul
|
|
|
|
|
r = find_bt(devs);
|
2009-07-05 21:06:38 +00:00
|
|
|
|
if (r) {
|
|
|
|
|
r = libusb_open(dev, &handle);
|
|
|
|
|
printf("libusb open %d, handle %xu\n", r, (int) handle);
|
2009-07-08 22:21:02 +00:00
|
|
|
|
libusb_state = LIB_USB_OPENED;
|
2009-07-05 21:06:38 +00:00
|
|
|
|
}
|
|
|
|
|
libusb_free_device_list(devs, 1);
|
|
|
|
|
if (r < 0) {
|
2009-07-08 22:21:02 +00:00
|
|
|
|
usb_close();
|
|
|
|
|
return r;
|
2009-07-05 21:06:38 +00:00
|
|
|
|
}
|
2009-07-06 21:40:30 +00:00
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
// libusb_set_debug(0,3);
|
|
|
|
|
|
|
|
|
|
// Detach OS driver (not possible for OS X)
|
2009-07-06 21:40:30 +00:00
|
|
|
|
#ifndef __APPLE__
|
2009-07-05 21:06:38 +00:00
|
|
|
|
r = libusb_detach_kernel_driver (handle, 0);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
fprintf(stderr, "libusb_detach_kernel_driver error %d\n", r);
|
2009-07-08 22:21:02 +00:00
|
|
|
|
usb_close();
|
|
|
|
|
return r;
|
2009-07-05 21:06:38 +00:00
|
|
|
|
}
|
|
|
|
|
printf("libusb_detach_kernel_driver\n");
|
2009-07-06 16:37:53 +00:00
|
|
|
|
#endif
|
2009-07-08 22:21:02 +00:00
|
|
|
|
libusb_state = LIB_USB_KERNEL_DETACHED;
|
2009-07-06 16:37:53 +00:00
|
|
|
|
|
2009-10-18 20:49:27 +00:00
|
|
|
|
// libusb_set_debug(0,3);
|
2009-10-18 09:06:29 +00:00
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
// reserve access to device
|
2009-10-17 22:38:48 +00:00
|
|
|
|
printf("claiming interface 0...\n");
|
2009-10-18 09:06:29 +00:00
|
|
|
|
r = libusb_claim_interface(handle, 0);
|
2009-07-05 21:06:38 +00:00
|
|
|
|
if (r < 0) {
|
|
|
|
|
fprintf(stderr, "usb_claim_interface error %d\n", r);
|
2009-07-08 22:21:02 +00:00
|
|
|
|
usb_close();
|
|
|
|
|
return r;
|
2009-07-05 21:06:38 +00:00
|
|
|
|
}
|
2009-07-08 22:21:02 +00:00
|
|
|
|
libusb_state = LIB_USB_INTERFACE_CLAIMED;
|
2009-07-05 21:06:38 +00:00
|
|
|
|
printf("claimed interface 0\n");
|
|
|
|
|
|
2009-10-18 20:49:27 +00:00
|
|
|
|
/*
|
2009-10-18 09:06:29 +00:00
|
|
|
|
// get endpoints - broken on OS X until libusb 1.0.3
|
2009-07-05 21:06:38 +00:00
|
|
|
|
struct libusb_config_descriptor *config_descriptor;
|
|
|
|
|
r = libusb_get_active_config_descriptor(dev, &config_descriptor);
|
2009-10-18 09:06:29 +00:00
|
|
|
|
printf("configuration: %u interfaces\n", config_descriptor->bNumInterfaces);
|
2009-07-05 21:06:38 +00:00
|
|
|
|
const struct libusb_interface *interface = config_descriptor->interface;
|
|
|
|
|
const struct libusb_interface_descriptor * interface0descriptor = interface->altsetting;
|
|
|
|
|
printf("interface 0: %u endpoints\n", interface0descriptor->bNumEndpoints);
|
|
|
|
|
const struct libusb_endpoint_descriptor *endpoint = interface0descriptor->endpoint;
|
|
|
|
|
for (r=0;r<interface0descriptor->bNumEndpoints;r++,endpoint++){
|
|
|
|
|
printf("endpoint %x, attributes %x\n", endpoint->bEndpointAddress, endpoint->bmAttributes);
|
|
|
|
|
}
|
2009-10-18 20:49:27 +00:00
|
|
|
|
*/
|
2009-07-06 21:40:30 +00:00
|
|
|
|
// allocation
|
2009-07-08 22:21:02 +00:00
|
|
|
|
control_transfer = libusb_alloc_transfer(0); // 0 isochronous transfers CMDs
|
2009-07-06 21:40:30 +00:00
|
|
|
|
interrupt_transfer = libusb_alloc_transfer(0); // 0 isochronous transfers Events
|
2009-10-18 20:49:27 +00:00
|
|
|
|
bulk_in_transfer = libusb_alloc_transfer(0); // 0 isochronous transfers ACL in
|
|
|
|
|
bulk_out_transfer = libusb_alloc_transfer(0); // 0 isochronous transfers ACL in
|
|
|
|
|
if (!control_transfer || !interrupt_transfer || !bulk_in_transfer || !bulk_out_transfer){
|
2009-07-08 22:21:02 +00:00
|
|
|
|
usb_close();
|
|
|
|
|
return LIBUSB_ERROR_NO_MEM;
|
|
|
|
|
}
|
|
|
|
|
libusb_state = LIB_USB_TRANSFERS_ALLOCATED;
|
|
|
|
|
|
|
|
|
|
// interrupt (= HCI event) handler
|
|
|
|
|
libusb_fill_interrupt_transfer(interrupt_transfer, handle, 0x81, hci_event_buffer, 260, event_callback, NULL, 3000) ;
|
2009-07-09 18:49:43 +00:00
|
|
|
|
// interrupt_transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK;
|
2009-07-06 21:40:30 +00:00
|
|
|
|
r = libusb_submit_transfer(interrupt_transfer);
|
|
|
|
|
if (r) {
|
|
|
|
|
printf("Error submitting interrupt transfer %d\n", r);
|
|
|
|
|
}
|
|
|
|
|
printf("interrupt started\n");
|
|
|
|
|
|
2009-10-18 20:49:27 +00:00
|
|
|
|
|
|
|
|
|
// bulk in (= ACL packets) handler
|
2010-07-25 12:28:23 +00:00
|
|
|
|
libusb_fill_bulk_transfer(bulk_in_transfer, handle, 0x82, hci_acl_in, HCI_ACL_3DH5_SIZE, bulk_in_callback, NULL, 3000) ;
|
2009-10-18 21:06:57 +00:00
|
|
|
|
// bulk_in_transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK;
|
2009-10-18 20:49:27 +00:00
|
|
|
|
r = libusb_submit_transfer(bulk_in_transfer);
|
|
|
|
|
if (r) {
|
|
|
|
|
printf("Error submitting bulk in transfer %d\n", r);
|
|
|
|
|
}
|
|
|
|
|
printf("bulk in started\n");
|
|
|
|
|
|
2009-07-09 18:49:43 +00:00
|
|
|
|
// set up data_sources
|
2009-07-08 22:21:02 +00:00
|
|
|
|
const struct libusb_pollfd ** pollfd = libusb_get_pollfds(NULL);
|
|
|
|
|
for (r = 0 ; pollfd[r] ; r++) {
|
2009-07-09 18:49:43 +00:00
|
|
|
|
data_source_t *ds = malloc(sizeof(data_source_t));
|
|
|
|
|
ds->fd = pollfd[r]->fd;
|
|
|
|
|
ds->process = usb_process;
|
2009-10-17 22:38:48 +00:00
|
|
|
|
run_loop_add_data_source(ds);
|
|
|
|
|
printf("%u: %x fd: %u, events %x\n", r, (unsigned int) pollfd[r], pollfd[r]->fd, pollfd[r]->events);
|
2009-07-08 22:21:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// init state machine
|
|
|
|
|
// bytes_to_read = 1;
|
|
|
|
|
// usb_state = USB_W4_PACKET_TYPE;
|
|
|
|
|
// read_pos = 0;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
static int usb_close(){
|
2009-07-31 21:41:15 +00:00
|
|
|
|
// @TODO: remove all run loops!
|
2009-07-08 22:21:02 +00:00
|
|
|
|
|
|
|
|
|
switch (libusb_state){
|
|
|
|
|
case LIB_USB_TRANSFERS_ALLOCATED:
|
2009-10-18 21:06:57 +00:00
|
|
|
|
libusb_free_transfer(bulk_in_transfer);
|
|
|
|
|
libusb_free_transfer(bulk_out_transfer);
|
2009-07-08 22:21:02 +00:00
|
|
|
|
libusb_free_transfer(control_transfer);
|
|
|
|
|
libusb_free_transfer(interrupt_transfer);
|
|
|
|
|
case LIB_USB_INTERFACE_CLAIMED:
|
|
|
|
|
libusb_release_interface(handle, 0);
|
|
|
|
|
case LIB_USB_KERNEL_DETACHED:
|
|
|
|
|
#ifndef __APPLE__
|
|
|
|
|
libusb_attach_kernel_driver (handle, 0);
|
|
|
|
|
#endif
|
|
|
|
|
case LIB_USB_DEVICE_OPENDED:
|
|
|
|
|
libusb_close(handle);
|
|
|
|
|
case LIB_USB_OPENED:
|
|
|
|
|
libusb_exit(NULL);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_send_cmd_packet(uint8_t *packet, int size){
|
2009-07-06 21:40:30 +00:00
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1;
|
|
|
|
|
|
|
|
|
|
hci_dump_packet( HCI_COMMAND_DATA_PACKET, 0, packet, size);
|
|
|
|
|
printf("send HCI packet, len %u\n", size);
|
|
|
|
|
|
|
|
|
|
// send packet over USB
|
2009-10-18 20:49:27 +00:00
|
|
|
|
libusb_fill_control_setup(hci_cmd_out, LIBUSB_REQUEST_TYPE_CLASS, 0, 0, 0, size);
|
|
|
|
|
memcpy(&hci_cmd_out[LIBUSB_CONTROL_SETUP_SIZE], packet, size);
|
|
|
|
|
libusb_fill_control_transfer(control_transfer, handle, hci_cmd_out, control_callback, NULL, 1000);
|
2009-07-08 22:21:02 +00:00
|
|
|
|
control_transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK;
|
|
|
|
|
int r = libusb_submit_transfer(control_transfer);
|
2009-07-06 21:40:30 +00:00
|
|
|
|
if (r) {
|
|
|
|
|
printf("Error submitting control transfer %d\n", r);
|
2009-07-08 22:21:02 +00:00
|
|
|
|
return r;
|
2009-07-05 21:06:38 +00:00
|
|
|
|
}
|
2009-07-08 22:21:02 +00:00
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2009-07-06 21:40:30 +00:00
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
static int usb_send_acl_packet(uint8_t *packet, int size){
|
|
|
|
|
|
|
|
|
|
if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1;
|
2009-07-05 21:06:38 +00:00
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
hci_dump_packet( HCI_ACL_DATA_PACKET, 0, packet, size);
|
|
|
|
|
|
2009-10-18 21:06:57 +00:00
|
|
|
|
#if 1 // send packet over USB
|
2009-10-18 20:49:27 +00:00
|
|
|
|
libusb_fill_bulk_transfer(bulk_out_transfer, handle, 0x02, packet, size, bulk_out_callback, NULL, 1000);
|
|
|
|
|
bulk_out_transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK;
|
|
|
|
|
int r = libusb_submit_transfer(bulk_out_transfer);
|
|
|
|
|
if (r) {
|
|
|
|
|
printf("Error submitting control transfer %d\n", r);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
2009-10-18 21:06:57 +00:00
|
|
|
|
#else
|
|
|
|
|
int transferred;
|
|
|
|
|
int ret = libusb_bulk_transfer (handle, 0x02, packet, size, &transferred, 5000);
|
|
|
|
|
if(ret>=0){
|
|
|
|
|
printf("acl data transfer succeeded");
|
|
|
|
|
}else{
|
|
|
|
|
printf("acl data transfer failed");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2009-07-08 22:21:02 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2009-07-06 21:40:30 +00:00
|
|
|
|
|
2010-08-16 17:23:22 +00:00
|
|
|
|
static int usb_send_packet(uint8_t packet_type, uint8_8 * packet, int size){
|
|
|
|
|
switch (packet_type){
|
|
|
|
|
case HCI_COMMAND_DATA_PACKET:
|
|
|
|
|
return usb_send_cmd_packet(packet, size);
|
|
|
|
|
case HCI_ACL_DATA_PACKET:
|
|
|
|
|
return usb_send_acl_packet(packet, size);
|
|
|
|
|
default:
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-18 16:14:55 +00:00
|
|
|
|
static void usb_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, int size)){
|
2009-07-08 22:21:02 +00:00
|
|
|
|
event_packet_handler = handler;
|
2009-07-05 21:06:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-07-08 22:21:02 +00:00
|
|
|
|
static const char * usb_get_transport_name(){
|
|
|
|
|
return "USB";
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-18 16:14:55 +00:00
|
|
|
|
static void dummy_handler(uint8_t packet_type, uint8_t *packet, int size){
|
2009-07-08 22:21:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get usb singleton
|
|
|
|
|
hci_transport_t * hci_transport_usb_instance() {
|
|
|
|
|
if (!hci_transport_usb) {
|
|
|
|
|
hci_transport_usb = malloc( sizeof(hci_transport_t));
|
|
|
|
|
hci_transport_usb->open = usb_open;
|
|
|
|
|
hci_transport_usb->close = usb_close;
|
|
|
|
|
hci_transport_usb->send_cmd_packet = usb_send_cmd_packet;
|
|
|
|
|
hci_transport_usb->send_acl_packet = usb_send_acl_packet;
|
2010-07-18 16:14:55 +00:00
|
|
|
|
hci_transport_usb->register_packet_handler = usb_register_packet_handler;
|
2009-07-08 22:21:02 +00:00
|
|
|
|
hci_transport_usb->get_transport_name = usb_get_transport_name;
|
|
|
|
|
}
|
|
|
|
|
return hci_transport_usb;
|
|
|
|
|
}
|