![](/media/cache/profiles/5f14615696649541a025d3d0f8e0447f.jpg.50x50_q85.jpg)
うおーるぼっとをWiiリモコンでコントロールする新しいプログラムです。 以前のものより、Wiiリモコンが早く繋がる様になりました。 It is a program which controls A with the Wii remote. ※ A Bluetooth dongle and a Wii remote control are needed.
Dependencies: USBHost mbed FATFileSystem mbed-rtos
USBHostBTstack/USBHostBTstack.cpp@0:fccb789424fc, 2013-06-10 (annotated)
- Committer:
- jksoft
- Date:
- Mon Jun 10 16:01:50 2013 +0000
- Revision:
- 0:fccb789424fc
1.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jksoft | 0:fccb789424fc | 1 | // USBHostBTstack.cpp |
jksoft | 0:fccb789424fc | 2 | #include "USBHostBTstack.h" |
jksoft | 0:fccb789424fc | 3 | #include "dbg.h" |
jksoft | 0:fccb789424fc | 4 | |
jksoft | 0:fccb789424fc | 5 | //#define BTSTACK_DEBUG |
jksoft | 0:fccb789424fc | 6 | |
jksoft | 0:fccb789424fc | 7 | #ifdef BTSTACK_DEBUG |
jksoft | 0:fccb789424fc | 8 | #define BT_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); |
jksoft | 0:fccb789424fc | 9 | #define BT_DBG_BYTES(STR,BUF,LEN) _debug_bytes(__PRETTY_FUNCTION__,__LINE__,STR,BUF,LEN) |
jksoft | 0:fccb789424fc | 10 | #else |
jksoft | 0:fccb789424fc | 11 | #define BT_DBG(...) while(0); |
jksoft | 0:fccb789424fc | 12 | #define BT_DBG_BYTES(S,BUF,LEN) while(0); |
jksoft | 0:fccb789424fc | 13 | #endif |
jksoft | 0:fccb789424fc | 14 | |
jksoft | 0:fccb789424fc | 15 | #define HCI_COMMAND_DATA_PACKET 0x01 |
jksoft | 0:fccb789424fc | 16 | #define HCI_ACL_DATA_PACKET 0x02 |
jksoft | 0:fccb789424fc | 17 | #define HCI_SCO_DATA_PACKET 0x03 |
jksoft | 0:fccb789424fc | 18 | #define HCI_EVENT_PACKET 0x04 |
jksoft | 0:fccb789424fc | 19 | |
jksoft | 0:fccb789424fc | 20 | USBHostBTstack::USBHostBTstack() |
jksoft | 0:fccb789424fc | 21 | { |
jksoft | 0:fccb789424fc | 22 | host = USBHost::getHostInst(); |
jksoft | 0:fccb789424fc | 23 | init(); |
jksoft | 0:fccb789424fc | 24 | m_pCb = NULL; |
jksoft | 0:fccb789424fc | 25 | } |
jksoft | 0:fccb789424fc | 26 | |
jksoft | 0:fccb789424fc | 27 | void USBHostBTstack::init() |
jksoft | 0:fccb789424fc | 28 | { |
jksoft | 0:fccb789424fc | 29 | BT_DBG(""); |
jksoft | 0:fccb789424fc | 30 | dev = NULL; |
jksoft | 0:fccb789424fc | 31 | int_in = NULL; |
jksoft | 0:fccb789424fc | 32 | bulk_in = NULL; |
jksoft | 0:fccb789424fc | 33 | bulk_out = NULL; |
jksoft | 0:fccb789424fc | 34 | btstack_intf = -1; |
jksoft | 0:fccb789424fc | 35 | btstack_device_found = false; |
jksoft | 0:fccb789424fc | 36 | dev_connected = false; |
jksoft | 0:fccb789424fc | 37 | ep_int_in = false; |
jksoft | 0:fccb789424fc | 38 | ep_bulk_in = false; |
jksoft | 0:fccb789424fc | 39 | ep_bulk_out = false; |
jksoft | 0:fccb789424fc | 40 | } |
jksoft | 0:fccb789424fc | 41 | |
jksoft | 0:fccb789424fc | 42 | bool USBHostBTstack::connected() |
jksoft | 0:fccb789424fc | 43 | { |
jksoft | 0:fccb789424fc | 44 | return dev_connected; |
jksoft | 0:fccb789424fc | 45 | } |
jksoft | 0:fccb789424fc | 46 | |
jksoft | 0:fccb789424fc | 47 | bool USBHostBTstack::connect() |
jksoft | 0:fccb789424fc | 48 | { |
jksoft | 0:fccb789424fc | 49 | if (dev_connected) { |
jksoft | 0:fccb789424fc | 50 | return true; |
jksoft | 0:fccb789424fc | 51 | } |
jksoft | 0:fccb789424fc | 52 | |
jksoft | 0:fccb789424fc | 53 | for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { |
jksoft | 0:fccb789424fc | 54 | if ((dev = host->getDevice(i)) != NULL) { |
jksoft | 0:fccb789424fc | 55 | |
jksoft | 0:fccb789424fc | 56 | BT_DBG("Trying to connect BTstack device\r\n"); |
jksoft | 0:fccb789424fc | 57 | |
jksoft | 0:fccb789424fc | 58 | if(host->enumerate(dev, this)) { |
jksoft | 0:fccb789424fc | 59 | break; |
jksoft | 0:fccb789424fc | 60 | } |
jksoft | 0:fccb789424fc | 61 | if (btstack_device_found) { |
jksoft | 0:fccb789424fc | 62 | int_in = dev->getEndpoint(btstack_intf, INTERRUPT_ENDPOINT, IN); |
jksoft | 0:fccb789424fc | 63 | bulk_in = dev->getEndpoint(btstack_intf, BULK_ENDPOINT, IN); |
jksoft | 0:fccb789424fc | 64 | bulk_out = dev->getEndpoint(btstack_intf, BULK_ENDPOINT, OUT); |
jksoft | 0:fccb789424fc | 65 | if (!int_in || !bulk_in || !bulk_out) { |
jksoft | 0:fccb789424fc | 66 | continue; |
jksoft | 0:fccb789424fc | 67 | } |
jksoft | 0:fccb789424fc | 68 | USB_INFO("New BTstack device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, btstack_intf); |
jksoft | 0:fccb789424fc | 69 | dev->setName("BTstack", btstack_intf); |
jksoft | 0:fccb789424fc | 70 | host->registerDriver(dev, btstack_intf, this, &USBHostBTstack::init); |
jksoft | 0:fccb789424fc | 71 | |
jksoft | 0:fccb789424fc | 72 | int_in->attach(this, &USBHostBTstack::int_rxHandler); |
jksoft | 0:fccb789424fc | 73 | host->interruptRead(dev, int_in, int_report, int_in->getSize(), false); |
jksoft | 0:fccb789424fc | 74 | |
jksoft | 0:fccb789424fc | 75 | bulk_in->attach(this, &USBHostBTstack::bulk_rxHandler); |
jksoft | 0:fccb789424fc | 76 | host->bulkRead(dev, bulk_in, bulk_report, bulk_in->getSize(), false); |
jksoft | 0:fccb789424fc | 77 | |
jksoft | 0:fccb789424fc | 78 | dev_connected = true; |
jksoft | 0:fccb789424fc | 79 | return true; |
jksoft | 0:fccb789424fc | 80 | } |
jksoft | 0:fccb789424fc | 81 | } |
jksoft | 0:fccb789424fc | 82 | } |
jksoft | 0:fccb789424fc | 83 | init(); |
jksoft | 0:fccb789424fc | 84 | return false; |
jksoft | 0:fccb789424fc | 85 | } |
jksoft | 0:fccb789424fc | 86 | |
jksoft | 0:fccb789424fc | 87 | void USBHostBTstack::int_rxHandler() |
jksoft | 0:fccb789424fc | 88 | { |
jksoft | 0:fccb789424fc | 89 | int len = int_in->getLengthTransferred(); |
jksoft | 0:fccb789424fc | 90 | BT_DBG_BYTES("HCI_EVT:", int_report, len); |
jksoft | 0:fccb789424fc | 91 | Packet* pkt = mail_box.alloc(); |
jksoft | 0:fccb789424fc | 92 | TEST_ASSERT(pkt); |
jksoft | 0:fccb789424fc | 93 | pkt->type = HCI_EVENT_PACKET; |
jksoft | 0:fccb789424fc | 94 | pkt->buf = int_report; |
jksoft | 0:fccb789424fc | 95 | pkt->len = len; |
jksoft | 0:fccb789424fc | 96 | mail_box.put(pkt); |
jksoft | 0:fccb789424fc | 97 | } |
jksoft | 0:fccb789424fc | 98 | |
jksoft | 0:fccb789424fc | 99 | void USBHostBTstack::bulk_rxHandler() |
jksoft | 0:fccb789424fc | 100 | { |
jksoft | 0:fccb789424fc | 101 | int len = bulk_in->getLengthTransferred(); |
jksoft | 0:fccb789424fc | 102 | BT_DBG_BYTES("ACL_RCV:", bulk_report, len); |
jksoft | 0:fccb789424fc | 103 | Packet* pkt = mail_box.alloc(); |
jksoft | 0:fccb789424fc | 104 | TEST_ASSERT(pkt); |
jksoft | 0:fccb789424fc | 105 | pkt->type = HCI_ACL_DATA_PACKET; |
jksoft | 0:fccb789424fc | 106 | pkt->buf = bulk_report; |
jksoft | 0:fccb789424fc | 107 | pkt->len = len; |
jksoft | 0:fccb789424fc | 108 | mail_box.put(pkt); |
jksoft | 0:fccb789424fc | 109 | } |
jksoft | 0:fccb789424fc | 110 | |
jksoft | 0:fccb789424fc | 111 | /*virtual*/ void USBHostBTstack::setVidPid(uint16_t vid, uint16_t pid) |
jksoft | 0:fccb789424fc | 112 | { |
jksoft | 0:fccb789424fc | 113 | BT_DBG("vid:%04x,pid:%04x", vid, pid); |
jksoft | 0:fccb789424fc | 114 | } |
jksoft | 0:fccb789424fc | 115 | |
jksoft | 0:fccb789424fc | 116 | /*virtual*/ bool USBHostBTstack::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed |
jksoft | 0:fccb789424fc | 117 | { |
jksoft | 0:fccb789424fc | 118 | BT_DBG("intf_nb=%d,intf_class=%02X,intf_subclass=%d,intf_protocol=%d", intf_nb, intf_class, intf_subclass, intf_protocol); |
jksoft | 0:fccb789424fc | 119 | if ((btstack_intf == -1) && intf_class == 0xe0) { |
jksoft | 0:fccb789424fc | 120 | btstack_intf = intf_nb; |
jksoft | 0:fccb789424fc | 121 | return true; |
jksoft | 0:fccb789424fc | 122 | } |
jksoft | 0:fccb789424fc | 123 | return false; |
jksoft | 0:fccb789424fc | 124 | } |
jksoft | 0:fccb789424fc | 125 | |
jksoft | 0:fccb789424fc | 126 | /*virtual*/ bool USBHostBTstack::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used |
jksoft | 0:fccb789424fc | 127 | { |
jksoft | 0:fccb789424fc | 128 | BT_DBG("intf_nb:%d,type:%d,dir:%d",intf_nb, type, dir); |
jksoft | 0:fccb789424fc | 129 | if (intf_nb == btstack_intf) { |
jksoft | 0:fccb789424fc | 130 | if (ep_int_in == false && type == INTERRUPT_ENDPOINT && dir == IN) { |
jksoft | 0:fccb789424fc | 131 | ep_int_in = true; |
jksoft | 0:fccb789424fc | 132 | } else if (ep_bulk_in == false && type == BULK_ENDPOINT && dir == IN) { |
jksoft | 0:fccb789424fc | 133 | ep_bulk_in = true; |
jksoft | 0:fccb789424fc | 134 | } else if (ep_bulk_out == false && type == BULK_ENDPOINT && dir == OUT) { |
jksoft | 0:fccb789424fc | 135 | ep_bulk_out = true; |
jksoft | 0:fccb789424fc | 136 | } else { |
jksoft | 0:fccb789424fc | 137 | return false; |
jksoft | 0:fccb789424fc | 138 | } |
jksoft | 0:fccb789424fc | 139 | if (ep_int_in && ep_bulk_in && ep_bulk_out) { |
jksoft | 0:fccb789424fc | 140 | btstack_device_found = true; |
jksoft | 0:fccb789424fc | 141 | } |
jksoft | 0:fccb789424fc | 142 | return true; |
jksoft | 0:fccb789424fc | 143 | } |
jksoft | 0:fccb789424fc | 144 | return false; |
jksoft | 0:fccb789424fc | 145 | } |
jksoft | 0:fccb789424fc | 146 | |
jksoft | 0:fccb789424fc | 147 | int USBHostBTstack::open() |
jksoft | 0:fccb789424fc | 148 | { |
jksoft | 0:fccb789424fc | 149 | BT_DBG("%p", this); |
jksoft | 0:fccb789424fc | 150 | while(!connected()) { |
jksoft | 0:fccb789424fc | 151 | if (connect()) { |
jksoft | 0:fccb789424fc | 152 | break; |
jksoft | 0:fccb789424fc | 153 | } |
jksoft | 0:fccb789424fc | 154 | Thread::wait(500); |
jksoft | 0:fccb789424fc | 155 | } |
jksoft | 0:fccb789424fc | 156 | return 0; |
jksoft | 0:fccb789424fc | 157 | } |
jksoft | 0:fccb789424fc | 158 | |
jksoft | 0:fccb789424fc | 159 | int USBHostBTstack::send_packet(uint8_t packet_type, uint8_t* packet, int size) |
jksoft | 0:fccb789424fc | 160 | { |
jksoft | 0:fccb789424fc | 161 | USB_TYPE res; |
jksoft | 0:fccb789424fc | 162 | switch(packet_type){ |
jksoft | 0:fccb789424fc | 163 | case HCI_COMMAND_DATA_PACKET: |
jksoft | 0:fccb789424fc | 164 | BT_DBG_BYTES("HCI_CMD:", packet, size); |
jksoft | 0:fccb789424fc | 165 | res = host->controlWrite(dev, |
jksoft | 0:fccb789424fc | 166 | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_DEVICE, |
jksoft | 0:fccb789424fc | 167 | 0, 0, 0, packet, size); |
jksoft | 0:fccb789424fc | 168 | TEST_ASSERT(res == USB_TYPE_OK); |
jksoft | 0:fccb789424fc | 169 | break; |
jksoft | 0:fccb789424fc | 170 | case HCI_ACL_DATA_PACKET: |
jksoft | 0:fccb789424fc | 171 | BT_DBG_BYTES("ACL_SND:", packet, size); |
jksoft | 0:fccb789424fc | 172 | res = host->bulkWrite(dev, bulk_out, packet, size); |
jksoft | 0:fccb789424fc | 173 | TEST_ASSERT(res == USB_TYPE_OK); |
jksoft | 0:fccb789424fc | 174 | break; |
jksoft | 0:fccb789424fc | 175 | default: |
jksoft | 0:fccb789424fc | 176 | TEST_ASSERT(0); |
jksoft | 0:fccb789424fc | 177 | } |
jksoft | 0:fccb789424fc | 178 | return 0; |
jksoft | 0:fccb789424fc | 179 | } |
jksoft | 0:fccb789424fc | 180 | |
jksoft | 0:fccb789424fc | 181 | void USBHostBTstack::register_packet_handler(void (*pMethod)(uint8_t, uint8_t*, uint16_t) ) |
jksoft | 0:fccb789424fc | 182 | { |
jksoft | 0:fccb789424fc | 183 | BT_DBG("pMethod: %p", pMethod); |
jksoft | 0:fccb789424fc | 184 | m_pCb = pMethod; |
jksoft | 0:fccb789424fc | 185 | } |
jksoft | 0:fccb789424fc | 186 | |
jksoft | 0:fccb789424fc | 187 | void USBHostBTstack::poll() |
jksoft | 0:fccb789424fc | 188 | { |
jksoft | 0:fccb789424fc | 189 | osEvent evt = mail_box.get(0); // non-blocking |
jksoft | 0:fccb789424fc | 190 | if (evt.status == osEventMail) { |
jksoft | 0:fccb789424fc | 191 | Packet* pkt = reinterpret_cast<Packet*>(evt.value.p); |
jksoft | 0:fccb789424fc | 192 | TEST_ASSERT(pkt); |
jksoft | 0:fccb789424fc | 193 | //BT_DBG("type: %d, buf: %p, len: %d", pkt->type, pkt->buf, pkt->len); |
jksoft | 0:fccb789424fc | 194 | if (m_pCb) { |
jksoft | 0:fccb789424fc | 195 | m_pCb(pkt->type, pkt->buf, pkt->len); |
jksoft | 0:fccb789424fc | 196 | } |
jksoft | 0:fccb789424fc | 197 | if (dev) { |
jksoft | 0:fccb789424fc | 198 | if (pkt->type == HCI_EVENT_PACKET) { |
jksoft | 0:fccb789424fc | 199 | host->interruptRead(dev, int_in, int_report, int_in->getSize(), false); |
jksoft | 0:fccb789424fc | 200 | } else { // HCI_ACL_DATA_PACKET |
jksoft | 0:fccb789424fc | 201 | host->bulkRead(dev, bulk_in, bulk_report, bulk_in->getSize(), false); |
jksoft | 0:fccb789424fc | 202 | } |
jksoft | 0:fccb789424fc | 203 | } |
jksoft | 0:fccb789424fc | 204 | mail_box.free(pkt); |
jksoft | 0:fccb789424fc | 205 | } |
jksoft | 0:fccb789424fc | 206 | } |
jksoft | 0:fccb789424fc | 207 | |
jksoft | 0:fccb789424fc | 208 | void _debug_bytes(const char* pretty, int line, const char* s, uint8_t* buf, int len) |
jksoft | 0:fccb789424fc | 209 | { |
jksoft | 0:fccb789424fc | 210 | printf("[%s:%d]\n%s", pretty, line, s); |
jksoft | 0:fccb789424fc | 211 | for(int i = 0; i < len; i++) { |
jksoft | 0:fccb789424fc | 212 | printf(" %02x", buf[i]); |
jksoft | 0:fccb789424fc | 213 | } |
jksoft | 0:fccb789424fc | 214 | printf("\n"); |
jksoft | 0:fccb789424fc | 215 | } |