![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Code to control a Traxster robot using a Wimote and Android app
Fork of BlueUSB by
Revision 1:accdaa84fe8d, committed 2014-04-28
- Comitter:
- aswild
- Date:
- Mon Apr 28 16:06:32 2014 +0000
- Parent:
- 0:606b230e5b4a
- Commit message:
- Wiimote controlled Traxster robot using BlueUSB
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,75 @@ +#include "mbed.h" + +extern Serial rob; +extern DigitalOut led1, led2, led3, led4; + +Serial bt(p9, p10); // tx, rx +DigitalIn d11(p11),d12(p12),d15(p15),d16(p16); +DigitalOut out(p18); +extern AnalogIn ir; + +char c; +int dir; +char garbage; +float y; +char stringIn[128]; +int valout; +int maxVel = 50; +int maxVelb = -maxVel; +int i=0; + +extern time_t lastReportTime; + +int RunAndroid() +{ + bt.baud(19200); + while(1) + { + if(bt.readable()) + { + i = 0; + while((c=bt.getc()) != '\0') + stringIn[i++] = c; + + stringIn[i]=0; + if(stringIn[0] == 'X') + sscanf(stringIn,"%s %d %f",&garbage, &dir,&y); + + if (abs(y) >= 500) + valout = -floor((2*(abs(y)-500)/1000)*maxVel); + else + valout = maxVel- floor((2*abs(y)/1000)*maxVel); + + bool wall = ir.read() > (2.0 / 3.3); + led4 = wall; + + if (wall && dir == 1) + rob.printf("stop\r"); + else if(dir == 1) + { + if (y <= 0) + rob.printf("mogo 1:%d 2:%d\r",maxVel, valout); + + else if (y>0) + rob.printf("mogo 1:%d 2:%d\r",valout,maxVel); + + } + else if(dir == -1) + { + valout = -valout; + + if (y <= 0) + rob.printf("mogo 1:%d 2:%d\r",-maxVel, valout); + + else if (y>0) + rob.printf("mogo 1:%d 2:%d\r",valout,-maxVel); + + } + else + rob.printf("stop\r"); + + lastReportTime = time(NULL); + led3 = 0; + } + } +}
--- a/AutoEvents.cpp Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ - -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include "mbed.h" -#include "USBHost.h" -#include "Utils.h" - -#define AUTOEVT(_class,_subclass,_protocol) (((_class) << 16) | ((_subclass) << 8) | _protocol) -#define AUTO_KEYBOARD AUTOEVT(CLASS_HID,1,1) -#define AUTO_MOUSE AUTOEVT(CLASS_HID,1,2) - -u8 auto_mouse[4]; // buttons,dx,dy,scroll -u8 auto_keyboard[8]; // modifiers,reserved,keycode1..keycode6 -u8 auto_joystick[4]; // x,y,buttons,throttle - -void AutoEventCallback(int device, int endpoint, int status, u8* data, int len, void* userData) -{ - int evt = (int)userData; - switch (evt) - { - case AUTO_KEYBOARD: - printf("AUTO_KEYBOARD "); - break; - case AUTO_MOUSE: - printf("AUTO_MOUSE "); - break; - default: - printf("HUH "); - } - printfBytes("data",data,len); - USBInterruptTransfer(device,endpoint,data,len,AutoEventCallback,userData); -} - -// Establish transfers for interrupt events -void AddAutoEvent(int device, InterfaceDescriptor* id, EndpointDescriptor* ed) -{ - if ((ed->bmAttributes & 3) != ENDPOINT_INTERRUPT || !(ed->bEndpointAddress & 0x80)) - return; - - // Make automatic interrupt enpoints for known devices - u32 evt = AUTOEVT(id->bInterfaceClass,id->bInterfaceSubClass,id->bInterfaceProtocol); - u8* dst = 0; - int len; - switch (evt) - { - case AUTO_MOUSE: - dst = auto_mouse; - len = sizeof(auto_mouse); - break; - case AUTO_KEYBOARD: - dst = auto_keyboard; - len = sizeof(auto_keyboard); - break; - default: - printf("Interrupt endpoint %02X %08X\n",ed->bEndpointAddress,evt); - break; - } - if (dst) - { - printf("Auto Event for %02X %08X\n",ed->bEndpointAddress,evt); - USBInterruptTransfer(device,ed->bEndpointAddress,dst,len,AutoEventCallback,(void*)evt); - } -} - -void PrintString(int device, int i) -{ - u8 buffer[256]; - int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,i,buffer,255); - if (le < 0) - return; - char* dst = (char*)buffer; - for (int j = 2; j < le; j += 2) - *dst++ = buffer[j]; - *dst = 0; - printf("%d:%s\n",i,(const char*)buffer); - } - -// Walk descriptors and create endpoints for a given device -int StartAutoEvent(int device, int configuration, int interfaceNumber) -{ - u8 buffer[255]; - int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,255); - if (err < 0) - return err; - - int len = buffer[2] | (buffer[3] << 8); - u8* d = buffer; - u8* end = d + len; - while (d < end) - { - if (d[1] == DESCRIPTOR_TYPE_INTERFACE) - { - InterfaceDescriptor* id = (InterfaceDescriptor*)d; - if (id->bInterfaceNumber == interfaceNumber) - { - d += d[0]; - while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE) - { - if (d[1] == DESCRIPTOR_TYPE_ENDPOINT) - AddAutoEvent(device,id,(EndpointDescriptor*)d); - d += d[0]; - } - } - } - d += d[0]; - } - return 0; -} - -// Implemented in main.cpp -int OnDiskInsert(int device); - -// Implemented in TestShell.cpp -int OnBluetoothInsert(int device); - -void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc) -{ - printf("LoadDevice %d %02X:%02X:%02X\n",device,interfaceDesc->bInterfaceClass,interfaceDesc->bInterfaceSubClass,interfaceDesc->bInterfaceProtocol); - char s[128]; - for (int i = 1; i < 3; i++) - { - if (GetString(device,i,s,sizeof(s)) < 0) - break; - printf("%d: %s\n",i,s); - } - - switch (interfaceDesc->bInterfaceClass) - { - case CLASS_MASS_STORAGE: - if (interfaceDesc->bInterfaceSubClass == 0x06 && interfaceDesc->bInterfaceProtocol == 0x50) - OnDiskInsert(device); // it's SCSI! - break; - case CLASS_WIRELESS_CONTROLLER: - if (interfaceDesc->bInterfaceSubClass == 0x01 && interfaceDesc->bInterfaceProtocol == 0x01) - OnBluetoothInsert(device); // it's bluetooth! - break; - default: - StartAutoEvent(device,1,0); - break; - } -} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/AutoEvents.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,161 @@ + +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "mbed.h" +#include "USBHost.h" +#include "Utils.h" + +#define AUTOEVT(_class,_subclass,_protocol) (((_class) << 16) | ((_subclass) << 8) | _protocol) +#define AUTO_KEYBOARD AUTOEVT(CLASS_HID,1,1) +#define AUTO_MOUSE AUTOEVT(CLASS_HID,1,2) + +u8 auto_mouse[4]; // buttons,dx,dy,scroll +u8 auto_keyboard[8]; // modifiers,reserved,keycode1..keycode6 +u8 auto_joystick[4]; // x,y,buttons,throttle + +void AutoEventCallback(int device, int endpoint, int status, u8* data, int len, void* userData) +{ + int evt = (int)userData; + switch (evt) + { + case AUTO_KEYBOARD: + printf("AUTO_KEYBOARD "); + break; + case AUTO_MOUSE: + printf("AUTO_MOUSE "); + break; + default: + printf("HUH "); + } + printfBytes("data",data,len); + USBInterruptTransfer(device,endpoint,data,len,AutoEventCallback,userData); +} + +// Establish transfers for interrupt events +void AddAutoEvent(int device, InterfaceDescriptor* id, EndpointDescriptor* ed) +{ + if ((ed->bmAttributes & 3) != ENDPOINT_INTERRUPT || !(ed->bEndpointAddress & 0x80)) + return; + + // Make automatic interrupt enpoints for known devices + u32 evt = AUTOEVT(id->bInterfaceClass,id->bInterfaceSubClass,id->bInterfaceProtocol); + u8* dst = 0; + int len; + switch (evt) + { + case AUTO_MOUSE: + dst = auto_mouse; + len = sizeof(auto_mouse); + break; + case AUTO_KEYBOARD: + dst = auto_keyboard; + len = sizeof(auto_keyboard); + break; + default: + printf("Interrupt endpoint %02X %08X\n",ed->bEndpointAddress,evt); + break; + } + if (dst) + { + printf("Auto Event for %02X %08X\n",ed->bEndpointAddress,evt); + USBInterruptTransfer(device,ed->bEndpointAddress,dst,len,AutoEventCallback,(void*)evt); + } +} + +void PrintString(int device, int i) +{ + u8 buffer[256]; + int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,i,buffer,255); + if (le < 0) + return; + char* dst = (char*)buffer; + for (int j = 2; j < le; j += 2) + *dst++ = buffer[j]; + *dst = 0; + printf("%d:%s\n",i,(const char*)buffer); + } + +// Walk descriptors and create endpoints for a given device +int StartAutoEvent(int device, int configuration, int interfaceNumber) +{ + u8 buffer[255]; + int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,255); + if (err < 0) + return err; + + int len = buffer[2] | (buffer[3] << 8); + u8* d = buffer; + u8* end = d + len; + while (d < end) + { + if (d[1] == DESCRIPTOR_TYPE_INTERFACE) + { + InterfaceDescriptor* id = (InterfaceDescriptor*)d; + if (id->bInterfaceNumber == interfaceNumber) + { + d += d[0]; + while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE) + { + if (d[1] == DESCRIPTOR_TYPE_ENDPOINT) + AddAutoEvent(device,id,(EndpointDescriptor*)d); + d += d[0]; + } + } + } + d += d[0]; + } + return 0; +} + +// Implemented in main.cpp +int OnDiskInsert(int device) {return -1;} + +// Implemented in TestShell.cpp +int OnBluetoothInsert(int device); + +void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc) +{ + printf("LoadDevice %d %02X:%02X:%02X\n",device,interfaceDesc->bInterfaceClass,interfaceDesc->bInterfaceSubClass,interfaceDesc->bInterfaceProtocol); + char s[128]; + for (int i = 1; i < 3; i++) + { + if (GetString(device,i,s,sizeof(s)) < 0) + break; + printf("%d: %s\n",i,s); + } + + switch (interfaceDesc->bInterfaceClass) + { + case CLASS_MASS_STORAGE: + if (interfaceDesc->bInterfaceSubClass == 0x06 && interfaceDesc->bInterfaceProtocol == 0x50) + OnDiskInsert(device); // it's SCSI! + break; + case CLASS_WIRELESS_CONTROLLER: + if (interfaceDesc->bInterfaceSubClass == 0x01 && interfaceDesc->bInterfaceProtocol == 0x01) + OnBluetoothInsert(device); // it's bluetooth! + break; + default: + StartAutoEvent(device,1,0); + break; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/L2CAP.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,274 @@ +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "Utils.h" +#include "hci.h" + +#define L2CAP_COMMAND_REJ 0x01 +#define L2CAP_CONN_REQ 0x02 +#define L2CAP_CONN_RSP 0x03 +#define L2CAP_CONF_REQ 0x04 +#define L2CAP_CONF_RSP 0x05 +#define L2CAP_DISCONN_REQ 0x06 +#define L2CAP_DISCONN_RSP 0x07 +#define L2CAP_ECHO_REQ 0x08 +#define L2CAP_ECHO_RSP 0x09 +#define L2CAP_INFO_REQ 0x0a +#define L2CAP_INFO_RSP 0x0b + + + /* L2CAP command codes */ + const char* L2CAP_ComandCodeStr(int c) + { + switch (c) + { + case L2CAP_COMMAND_REJ: return "L2CAP_COMMAND_REJ"; + case L2CAP_CONN_REQ: return "L2CAP_CONN_REQ"; + case L2CAP_CONN_RSP: return "L2CAP_CONN_RSP"; + case L2CAP_CONF_REQ: return "L2CAP_CONF_REQ"; + case L2CAP_CONF_RSP: return "L2CAP_CONF_RSP"; + case L2CAP_DISCONN_REQ: return "L2CAP_DISCONN_REQ"; + case L2CAP_DISCONN_RSP: return "L2CAP_DISCONN_RSP"; + case L2CAP_ECHO_REQ: return "L2CAP_ECHO_REQ"; + case L2CAP_ECHO_RSP: return "L2CAP_ECHO_RSP"; + case L2CAP_INFO_REQ: return "L2CAP_INFO_REQ"; + case L2CAP_INFO_RSP: return "L2CAP_INFO_RSP"; + } + return "unknown"; + } + +typedef struct +{ + u16 handle; + u16 length; // total + u16 l2capLength; // length -4 + u16 cid; // Signaling packet CID = 1 + u8 data[64]; // Largest thing to send!!! todo +} L2CAPData; + +typedef struct +{ + u16 handle; + u16 length; // total + u16 l2capLength; // length -4 + u16 cid; // Signaling packet CID = 1 + + // Payload + u8 cmd; // + u8 id; + u16 cmdLength; // total-8 + u16 params[4]; // Params +} L2CAPCmd; + +// +void BTDevice::Init() +{ + memset(&_info,0,sizeof(inquiry_info)); + _handle = 0; + _name[0] = 0; + _state = 0; +} + +// virtual SocketHandler +int BTDevice::Open(SocketInternal* sock, SocketAddrHdr* addr) +{ + L2CAPSocket* s = (L2CAPSocket*)sock; + L2CAPAddr* a = (L2CAPAddr*)addr; + s->scid = 0x40 + sock->ID-1; // are these reserved? + s->dcid = 0; + Connect(s->scid,a->psm); + return sock->ID; +} + +// virtual SocketHandler +int BTDevice::Send(SocketInternal* sock, const u8* data, int len) +{ + L2CAPData d; + L2CAPSocket* s = (L2CAPSocket*)sock; + + d.handle = _handle | 0x2000; + d.length = 4 + len; + d.l2capLength = len; + d.cid = s->dcid; + + if (len > 64) + return -1; + memcpy(d.data,data,len); + return Send((u8*)&d,len+8); +} + +// virtual SocketHandler +int BTDevice::Close(SocketInternal* sock) +{ + printf("L2CAP close %d\n",sock->ID); + L2CAPSocket* s = (L2CAPSocket*)sock; + return Disconnect(s->scid,s->dcid); +} + +L2CAPSocket* BTDevice::SCIDToSocket(int scid) +{ + return (L2CAPSocket*)GetSocketInternal(scid-0x40+1); +} + +int BTDevice::Send(const u8* data, int len) +{ + _transport->ACLSend(data,len); + return 0; +} + +int BTDevice::Send(u8 c, u8 id, u16* params, int count) +{ + L2CAPCmd cmd; + cmd.handle = _handle | 0x2000; + cmd.length = 8 + count*2; + + cmd.l2capLength = cmd.length-4; + cmd.cid = 1; // Signaling packet + + cmd.cmd = c; + cmd.id = id; + cmd.cmdLength = count*2; + for (int i = 0; i < count; i++) + cmd.params[i] = params[i]; + return Send((u8*)&cmd,cmd.length+4); +} + +int BTDevice::Connect(int scid, int psm) +{ + u16 p[2]; + p[0] = psm; + p[1] = scid; + return Send(L2CAP_CONN_REQ,_txid++,p,2); +} + +int BTDevice::Disconnect(int scid, int dcid) +{ + u16 p[2]; + p[0] = dcid; + p[1] = scid; + return Send(L2CAP_DISCONN_REQ,_txid++,p,2); +} + +int BTDevice::ConfigureRequest(int dcid) +{ + u16 p[4]; + p[0] = dcid; + p[1] = 0; + p[2] = 0x0201; // Options + p[3] = 0x02A0; // 672 + return Send(L2CAP_CONF_REQ,_txid++,p,4); +} + +int BTDevice::ConfigureResponse(u8 rxid, int dcid) +{ + u16 p[3]; + p[0] = dcid; + p[1] = 0; + p[2] = 0; + return Send(L2CAP_CONF_RSP,rxid,p,3); +} + +int BTDevice::DisconnectResponse(u8 rxid, int scid, int dcid) +{ + u16 p[2]; + p[0] = dcid; + p[1] = scid; + return Send(L2CAP_DISCONN_RSP,rxid,p,2); +} + +void BTDevice::Control(const u8* data, int len) +{ + int cc = data[8]; + printf(L2CAP_ComandCodeStr(cc)); + int result = LE16(data+16); + printf(" Result %d\n",result); + switch (cc) + { + case L2CAP_COMMAND_REJ: + break; + case L2CAP_CONN_REQ: + break; + + // Response to our initial connect from Remote + case L2CAP_CONN_RSP: + { + if (result == 0) + { + int dcid = LE16(data+12); + int scid = LE16(data+14); + L2CAPSocket* s = SCIDToSocket(scid); + if (s) + { + s->dcid = dcid; + ConfigureRequest(dcid); + } + } else + printf("Connect failed?\n"); + } + break; + + case L2CAP_CONF_RSP: + { + int scid = LE16(data+12); + SocketInternal* s = (SocketInternal*)SCIDToSocket(scid); + if (s) + s->SetState(SocketState_Open); + } + break; + + case L2CAP_CONF_REQ: + { + int scid = LE16(data+12); + L2CAPSocket* s = SCIDToSocket(scid); + if (s) + ConfigureResponse(data[9],s->dcid); + } + break; + } +} + +void BTDevice::ACLRecv(const u8* data, int len) +{ + // printfBytes("L2CP",data,16); + int handle = LE16(data); + if (handle != (0x2000 | _handle)) + return; + + int cid = LE16(data+6); + if (cid == 1) + { + Control(data,len); + return; + } + + SocketInternal* s = (SocketInternal*)SCIDToSocket(cid); + if (s) + s->Recv(data+8,LE16(data+2)-4); + else + printf("Bad event cid %d\n",cid); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/MassStorage.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,180 @@ + +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "stdlib.h" +#include "stdio.h" +#include "string.h" + +#include "Utils.h" +#include "USBHost.h" + + +int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize); +int MassStorage_ReadBlock(int device, u32 block, u8* dst); +int MassStorage_WriteBlock(int device, u32 block, const u8* dst); + + +#define ERR_BAD_CSW_SIGNATURE -200 + +#define CBW_SIGNATURE 0x43425355 +#define CSW_SIGNATURE 0x53425355 + +// Command Block +typedef struct +{ + u32 Signature; + u32 Tag; + u32 TransferLength; + u8 Flags; + u8 LUN; + u8 CBLength; + u8 CB[16]; // only 6 really +} CBW; + +// Status block +typedef struct +{ + u32 Signature; + u32 Tag; + u32 DataResidue; + u8 Status; +} CSW; + +int SCSIRequestSense(int device); + +int DoSCSI(int device, const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen) +{ + CBW cbw; + cbw.Signature = CBW_SIGNATURE; + cbw.Tag = 0; + cbw.TransferLength = transferLen; + cbw.Flags = flags; + cbw.LUN = 0; + cbw.CBLength = cmdLen; + memset(cbw.CB,0,sizeof(cbw.CB)); + memcpy(cbw.CB,cmd,cmdLen); + + int r; + r = USBBulkTransfer(device,0x01,(u8*)&cbw,31); // Send the command + if (r < 0) + return r; + + if (data) + { + r = USBBulkTransfer(device,flags | 1,data,transferLen); + if (r < 0) + return r; + } + + CSW csw; + csw.Signature = 0; + r = USBBulkTransfer(device,0x81,(u8*)&csw,13); + if (r < 0) + return r; + + if (csw.Signature != CSW_SIGNATURE) + return ERR_BAD_CSW_SIGNATURE; + + // ModeSense? + if (csw.Status == 1 && cmd[0] != 3) + return SCSIRequestSense(device); + + return csw.Status; +} + +int SCSITestUnitReady(int device) +{ + u8 cmd[6]; + memset(cmd,0,6); + return DoSCSI(device,cmd,6,DEVICE_TO_HOST,0,0); +} + +int SCSIRequestSense(int device) +{ + u8 cmd[6] = {0x03,0,0,0,18,0}; + u8 result[18]; + int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,18); + return r; +} + +int SCSIInquiry(int device) +{ + u8 cmd[6] = {0x12,0,0,0,36,0}; + u8 result[36+2]; + result[36] = '\n'; + result[37] = 0; + int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,36); + if (r == 0) + printf((const char*)result + 8); + return r; +} + +int SCSIReadCapacity(int device, u32* blockCount, u32* blockSize) +{ + u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0}; + u8 result[8]; + *blockSize = 0; + *blockCount = 0; + int r = DoSCSI(device,cmd,10,DEVICE_TO_HOST,result,8); + if (r == 0) + { + *blockCount = BE32(result); + *blockSize = BE32(result+4); + } + return r; +} + +int SCSITransfer(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction) +{ + // USB hardware will only do 4k per transfer + while (blockCount*blockSize > 4096) + { + int count = 4096/blockSize; + int r = SCSITransfer(device,blockAddr,count,dst,blockSize,direction); + dst += count*blockSize; + blockAddr += count; + blockCount -= count; + } + + u8 cmd[10]; + memset(cmd,0,10); + cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A; + BE32(blockAddr,cmd+2); + BE16(blockCount,cmd+7); + return DoSCSI(device,cmd,10,direction,dst,blockSize*blockCount); +} + +int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize) +{ + return SCSIReadCapacity(device,blockCount,blockSize); +} + +int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512) +{ + return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,DEVICE_TO_HOST); +} + +int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512) +{ + return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,HOST_TO_DEVICE); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/Socket.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,140 @@ +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "Utils.h" +#include "Socket.h" + +#define MAX_SOCKET_HANDLERS 3 +#define MAX_SOCKETS 16 + +class SocketInternalPad +{ + public: + SocketInternal si; + u8 pad[8]; +}; + +class SocketManager +{ + SocketHandler* _handlers[MAX_SOCKET_HANDLERS]; + SocketInternalPad _sockets[MAX_SOCKETS]; + + public: + SocketManager() + { + memset(_handlers,0,sizeof(_handlers)); + memset(_sockets,0,sizeof(_sockets)); + } + + SocketHandler* GetHandler(int type) + { + if (type < 1 || type > MAX_SOCKET_HANDLERS) + return 0; + return _handlers[type - 1]; + } + + SocketInternal* GetInternal(int s) + { + if (s < 1 || s > MAX_SOCKETS) + return 0; + return &_sockets[s - 1].si; + } + + int RegisterSocketHandler(int type, SocketHandler* handler) + { + if (type < 1 || type > MAX_SOCKET_HANDLERS) + return ERR_SOCKET_TYPE_NOT_FOUND; + _handlers[type - 1] = handler; + return 0; + } + + int Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData) + { + SocketHandler* h = GetHandler(type); + if (!h) + return ERR_SOCKET_TYPE_NOT_FOUND; + + for (int i = 0; i < MAX_SOCKETS; i++) + { + SocketInternal* si = (SocketInternal*)(_sockets+i); + if (si->ID == 0) + { + si->ID = i+1; + si->Type = type; + si->Callback = callback; + si->userData = userData; + return h->Open(si,addr); + } + } + return ERR_SOCKET_NONE_LEFT; + } + + int Send(int socket, const u8* data, int len) + { + SocketInternal* si = GetInternal(socket); + if (!si || si->ID != socket) + return ERR_SOCKET_NOT_FOUND; + return GetHandler(si->Type)->Send(si,data,len); + } + + int Close(int socket) + { + SocketInternal* si = GetInternal(socket); + if (!si || si->ID != socket) + return ERR_SOCKET_NOT_FOUND; + si->ID = 0; + return GetHandler(si->Type)->Close(si); + } +}; + +SocketManager gSocketManager; + +int Socket_Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData) +{ + return gSocketManager.Open(type,addr,callback,userData); +} + +int Socket_Send(int socket, const u8* data, int len) +{ + return gSocketManager.Send(socket,data,len); +} + +int Socket_Close(int socket) +{ + return gSocketManager.Close(socket); +} + +int RegisterSocketHandler(int type, SocketHandler* handler) +{ + return gSocketManager.RegisterSocketHandler(type,handler); +} + +SocketInternal* GetSocketInternal(int socket) +{ + return gSocketManager.GetInternal(socket); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/Socket.h Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,96 @@ +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef SOCKET_H_INCLUDED +#define SOCKET_H_INCLUDED + +#define SOCKET_HCI 1 +#define SOCKET_L2CAP 2 +#define SOCKET_RFCOM 3 + +typedef struct +{ + u8 AddressSpecific[0]; // BDADDR,psm etc +} SocketAddrHdr; + +enum SocketState +{ + SocketState_Unknown, + SocketState_Opening, + SocketState_Open, + SocketState_Closing, + SocketState_Closed +}; + +typedef void (*SocketCallback)(int socket, SocketState state, const u8* data, int len, void* userData); + +int Socket_Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData); // Open a socket +int Socket_Send(int socket, const u8* data, int len); +int Socket_State(int socket); +int Socket_Close(int socket); + +//=========================================================================== +//=========================================================================== +// Don't need to look at or use anything below this line: +// Internal representation of socket + +class SocketHandler; +class SocketInternal +{ + public: + + u8 ID; + u8 State; + u8 Type; + u8 B0; + SocketCallback Callback; + void* userData; + u8 Data[0]; // Extra socket data starts here + + void Recv(const u8* data, int len) + { + Callback(ID,(SocketState)State,data,len,userData); + } + + void SetState(SocketState state) + { + State = state; + Callback(ID,(SocketState)State,0,0,userData); + } +}; + +class SocketHandler +{ + public: + virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) = 0; + virtual int Send(SocketInternal* sock, const u8* data, int len) = 0; + virtual int Close(SocketInternal* sock) = 0; +}; + +int RegisterSocketHandler(int type, SocketHandler* handler); +SocketInternal* GetSocketInternal(int socket); + +#define ERR_SOCKET_TYPE_NOT_FOUND -200 +#define ERR_SOCKET_NOT_FOUND -201 +#define ERR_SOCKET_NONE_LEFT -202 + +#endif // SOCKET_H_INCLUDED
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/TestShell.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,392 @@ + +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "mbed.h" +#include "Utils.h" +#include "USBHost.h" +#include "hci.h" + + + +void ProcessHID(const unsigned char*); + +void printf(const BD_ADDR* addr) +{ + const u8* a = addr->addr; + printf("%02X:%02X:%02X:%02X:%02X:%02X",a[5],a[4],a[3],a[2],a[1],a[0]); +} + +#define MAX_HCL_SIZE 260 +#define MAX_ACL_SIZE 400 + +class HCITransportUSB : public HCITransport +{ + int _device; + u8* _hciBuffer; + u8* _aclBuffer; + + public: + void Open(int device, u8* hciBuffer, u8* aclBuffer) + { + _device = device; + _hciBuffer = hciBuffer; + _aclBuffer = aclBuffer; + USBInterruptTransfer(_device,0x81,_hciBuffer,MAX_HCL_SIZE,HciCallback,this); + USBBulkTransfer(_device,0x82,_aclBuffer,MAX_ACL_SIZE,AclCallback,this); + } + + static void HciCallback(int device, int endpoint, int status, u8* data, int len, void* userData) + { + HCI* t = ((HCITransportUSB*)userData)->_target; + if (t) + t->HCIRecv(data,len); + USBInterruptTransfer(device,0x81,data,MAX_HCL_SIZE,HciCallback,userData); + } + + static void AclCallback(int device, int endpoint, int status, u8* data, int len, void* userData) + { + HCI* t = ((HCITransportUSB*)userData)->_target; + if (t) + t->ACLRecv(data,len); + USBBulkTransfer(device,0x82,data,MAX_ACL_SIZE,AclCallback,userData); + } + + virtual void HCISend(const u8* data, int len) + { + USBControlTransfer(_device,REQUEST_TYPE_CLASS, 0, 0, 0,(u8*)data,len); + } + + virtual void ACLSend(const u8* data, int len) + { + USBBulkTransfer(_device,0x02,(u8*)data,len); + } +}; + + +#define WII_REMOTE 0x042500 + +class HIDBluetooth +{ + int _control; // Sockets for control (out) and interrupt (in) + int _interrupt; + int _devClass; + BD_ADDR _addr; + u8 _pad[2]; // Struct align + +public: + HIDBluetooth() : _control(0),_interrupt(0),_devClass(0) {}; + + bool InUse() + { + return _control != 0; + } + + static void OnHidInterrupt(int socket, SocketState state, const u8* data, int len, void* userData) + { + HIDBluetooth* t = (HIDBluetooth*)userData; + if (data) + { + if (t->_devClass == WII_REMOTE && data[1] == 0x30) + { + printf("================wii====================\n"); + t->Led(); + t->Hid(); // ask for accelerometer + t->_devClass = 0; + } + + const u8* d = data; + switch (d[1]) + { + case 0x02: + { + int x = (signed char)d[3]; + int y = (signed char)d[4]; + printf("Mouse %2X dx:%d dy:%d\n",d[2],x,y); + } + break; + + case 0x37: // Accelerometer http://wiki.wiimoteproject.com/Reports + { + int pad = (d[2] & 0x9F) | ((d[3] & 0x9F) << 8); + int x = (d[2] & 0x60) >> 5 | d[4] << 2; + int y = (d[3] & 0x20) >> 4 | d[5] << 2; + int z = (d[3] & 0x40) >> 5 | d[6] << 2; + printf("WII %04X %d %d %d\n",pad,x,y,z); + } + break; + + // STUFF ACTUALLY HAPPENS HERE + case 0x31: // basic button/accel report + ProcessHID(data); + break; + default: + printHex(data,len); + } + } + } + + void Led(int id = 0x10) + { + u8 led[3] = {0x52, 0x11, id}; + if (_control) + Socket_Send(_control,led,3); + } + + void Hid(int report = 0x31) + { + u8 hid[4] = { 0x52, 0x12, 0x00, report }; + if (_control != -1) + Socket_Send(_control,hid,4); + } + + static void OnHidControl(int socket, SocketState state, const u8* data, int len, void* userData) + { + printf("OnHidControl\n"); + if (data) + printHex(data,len); + } + + void Open(BD_ADDR* bdAddr, inquiry_info* info) + { + printf("L2CAPAddr size %d\n",sizeof(L2CAPAddr)); + _addr = *bdAddr; + L2CAPAddr sockAddr; + sockAddr.bdaddr = _addr; + sockAddr.psm = L2CAP_PSM_HID_INTR; + printf("Socket_Open size %d\n",sizeof(L2CAPAddr)); + _interrupt = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidInterrupt,this); + sockAddr.psm = L2CAP_PSM_HID_CNTL; + _control = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidControl,this); + + printfBytes("OPEN DEVICE CLASS",info->dev_class,3); + _devClass = (info->dev_class[0] << 16) | (info->dev_class[1] << 8) | info->dev_class[2]; + } + + void Close() + { + if (_control) + Socket_Close(_control); + if (_interrupt) + Socket_Close(_interrupt); + _control = _interrupt = 0; + } +}; + + +HCI* gHCI = 0; + +#define MAX_HID_DEVICES 8 + +int GetConsoleChar(); +class ShellApp +{ + char _line[64]; + HIDBluetooth _hids[MAX_HID_DEVICES]; + +public: + void Ready() + { + printf("HIDBluetooth %d\n",sizeof(HIDBluetooth)); + memset(_hids,0,sizeof(_hids)); + Inquiry(); + + } + + // We have connected to a device + void ConnectionComplete(HCI* hci, connection_info* info) + { + printf("ConnectionComplete "); + BD_ADDR* a = &info->bdaddr; + printf(a); + BTDevice* bt = hci->Find(a); + HIDBluetooth* hid = NewHIDBluetooth(); + printf("%08x %08x\n",bt,hid); + if (hid) + hid->Open(a,&bt->_info); + } + + HIDBluetooth* NewHIDBluetooth() + { + for (int i = 0; i < MAX_HID_DEVICES; i++) + if (!_hids[i].InUse()) + return _hids+i; + return 0; + } + + void ConnectDevices() + { + BTDevice* devs[8]; + int count = gHCI->GetDevices(devs,8); + for (int i = 0; i < count; i++) + { + printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3); + if (devs[i]->_handle == 0) + { + BD_ADDR* bd = &devs[i]->_info.bdaddr; + if ((bd->addr)[0] == 0xA8) + { + printf("Connecting to "); + printf(bd); + printf("\n"); + gHCI->CreateConnection(bd); + } + } + } + } + + const char* ReadLine() + { + int i; + for (i = 0; i < 255; ) + { + USBLoop(); + int c = GetConsoleChar(); + if (c == -1) + continue; + if (c == '\n' || c == 13) + break; + _line[i++] = c; + } + _line[i] = 0; + return _line; + } + + void Inquiry() + { + printf("Inquiry..\n"); + gHCI->Inquiry(3); + } + + void List() + { + #if 0 + printf("%d devices\n",_deviceCount); + for (int i = 0; i < _deviceCount; i++) + { + printf(&_devices[i].info.bdaddr); + printf("\n"); + } + #endif + } + + void Connect() + { + ConnectDevices(); + } + + void Disconnect() + { + gHCI->DisconnectAll(); + } + + void CloseMouse() + { + } + + void Quit() + { + CloseMouse(); + } + + void Run() + { + for (;;) + USBLoop(); + } +}; + +// Instance +ShellApp gApp; + +static int HciCallback(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len) +{ + switch (evt) + { + case CALLBACK_READY: + printf("CALLBACK_READY\n"); + gApp.Ready(); + break; + + case CALLBACK_INQUIRY_RESULT: + printf("CALLBACK_INQUIRY_RESULT "); + printf((BD_ADDR*)data); + printf("\n"); + break; + + case CALLBACK_INQUIRY_DONE: + printf("CALLBACK_INQUIRY_DONE\n"); + gApp.ConnectDevices(); + break; + + case CALLBACK_REMOTE_NAME: + { + BD_ADDR* addr = (BD_ADDR*)data; + const char* name = (const char*)(data + 6); + printf(addr); + printf(" % s\n",name); + } + break; + + case CALLBACK_CONNECTION_COMPLETE: + gApp.ConnectionComplete(hci,(connection_info*)data); + break; + }; + return 0; +} + +// these should be placed in the DMA SRAM +typedef struct +{ + u8 _hciBuffer[MAX_HCL_SIZE]; + u8 _aclBuffer[MAX_ACL_SIZE]; +} SRAMPlacement; + +HCITransportUSB _HCITransportUSB; +HCI _HCI; + +u8* USBGetBuffer(u32* len); +int OnBluetoothInsert(int device) +{ + printf("Bluetooth inserted of %d\n",device); + u32 sramLen; + u8* sram = USBGetBuffer(&sramLen); + sram = (u8*)(((u32)sram + 1023) & ~1023); + SRAMPlacement* s = (SRAMPlacement*)sram; + _HCITransportUSB.Open(device,s->_hciBuffer,s->_aclBuffer); + _HCI.Open(&_HCITransportUSB,HciCallback); + RegisterSocketHandler(SOCKET_L2CAP,&_HCI); + gHCI = &_HCI; + gApp.Inquiry(); + return 0; +} + +void RunWiimote() +{ + USBInit(); + gApp.Run(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/USBHost.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,1072 @@ + +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "mbed.h" +#include "USBHost.h" + +// Config (default uses x bytes) +#define MAX_DEVICES 8 // Max number of devices +#define MAX_ENDPOINTS_TOTAL 16 // Max number of endpoints total +#define MAX_ENDPOINTS_PER_DEVICE 8 // Max number of endpoints for any one device + +#define USBLOG 1 +#if USBLOG +#define LOG(...) printf(__VA_ARGS__) +#else +#define LOG(...) do {} while(0) +#endif + +// USB host structures + +#define USB_RAM_SIZE 16*1024 // AHB SRAM block 1 TODO MACHINE DEPENDENT +#define USB_RAM_BASE 0x2007C000 + +#define TOKEN_SETUP 0 +#define TOKEN_IN 1 +#define TOKEN_OUT 2 + +// Status flags from hub +#define PORT_CONNECTION 0 +#define PORT_ENABLE 1 +#define PORT_SUSPEND 2 +#define PORT_OVER_CURRENT 3 +#define PORT_RESET 4 +#define PORT_POWER 8 +#define PORT_LOW_SPEED 9 + +#define C_PORT_CONNECTION 16 +#define C_PORT_ENABLE 17 +#define C_PORT_SUSPEND 18 +#define C_PORT_OVER_CURRENT 19 +#define C_PORT_RESET 20 + +typedef struct { + u8 bm_request_type; + u8 b_request; + u16 w_value; + u16 w_index; + u16 w_length; +} Setup; + + +// Hub stuff is kept private just to keep api simple +int SetPortFeature(int device, int feature, int index); +int ClearPortFeature(int device, int feature, int index); +int SetPortPower(int device, int port); +int SetPortReset(int device, int port); +int GetPortStatus(int device, int port, u32* status); + +//=================================================================== +//=================================================================== +// Hardware defines + +// HcControl +#define PeriodicListEnable 0x00000004 +#define IsochronousEnable 0x00000008 +#define ControlListEnable 0x00000010 +#define BulkListEnable 0x00000020 +#define OperationalMask 0x00000080 +#define HostControllerFunctionalState 0x000000C0 + +// HcCommandStatus +#define HostControllerReset 0x00000001 +#define ControlListFilled 0x00000002 +#define BulkListFilled 0x00000004 + +// HcInterruptStatus Register +#define WritebackDoneHead 0x00000002 +#define StartofFrame 0x00000004 +#define ResumeDetected 0x00000008 +#define UnrecoverableError 0x00000010 +#define FrameNumberOverflow 0x00000020 +#define RootHubStatusChange 0x00000040 +#define OwnershipChange 0x00000080 +#define MasterInterruptEnable 0x80000000 + +// HcRhStatus +#define SetGlobalPower 0x00010000 +#define DeviceRemoteWakeupEnable 0x00008000 + +// HcRhPortStatus (hub 0, port 1) +#define CurrentConnectStatus 0x00000001 +#define PortEnableStatus 0x00000002 +#define PortSuspendStatus 0x00000004 +#define PortOverCurrentIndicator 0x00000008 +#define PortResetStatus 0x00000010 + +#define PortPowerStatus 0x00000100 +#define LowspeedDevice 0x00000200 +#define HighspeedDevice 0x00000400 + +#define ConnectStatusChange (CurrentConnectStatus << 16) +#define PortResetStatusChange (PortResetStatus << 16) + + +#define TD_ROUNDING (u32)0x00040000 +#define TD_SETUP (u32)0x00000000 +#define TD_IN (u32)0x00100000 +#define TD_OUT (u32)0x00080000 +#define TD_DELAY_INT(x) (u32)((x) << 21) +#define TD_TOGGLE_0 (u32)0x02000000 +#define TD_TOGGLE_1 (u32)0x03000000 +#define TD_CC (u32)0xF0000000 + +// HostController EndPoint Descriptor +typedef struct { + volatile u32 Control; + volatile u32 TailTd; + volatile u32 HeadTd; + volatile u32 Next; +} HCED; + +// HostController Transfer Descriptor +typedef struct { + volatile u32 Control; + volatile u32 CurrBufPtr; + volatile u32 Next; + volatile u32 BufEnd; +} HCTD; + +// Host Controller Communication Area +typedef struct { + volatile u32 InterruptTable[32]; + volatile u16 FrameNumber; + volatile u16 FrameNumberPad; + volatile u32 DoneHead; + volatile u8 Reserved[120]; +} HCCA; + +//==================================================================================== +//==================================================================================== + +class HostController; +class Endpoint; +class Device; + +// must be 3*16 bytes long +class Endpoint +{ +public: + HCED EndpointDescriptor; // Pointer to EndpointDescriptor == Pointer to Endpoint + HCTD TDHead; + + enum State + { + Free, + NotQueued, + Idle, + SetupQueued, + DataQueued, + StatusQueued, + CallbackPending + }; + + volatile u8 CurrentState; + u8 Flags; // 0x80 In, 0x03 mask endpoint type + + u16 Length; + u8* Data; + USBCallback Callback; // Must be a multiple of 16 bytes long + void* UserData; + + int Address() + { + int ep = (EndpointDescriptor.Control >> 7) & 0xF; + if (ep) + ep |= Flags & 0x80; + return ep; + } + + int Device() + { + return EndpointDescriptor.Control & 0x7F; + } + + int Status() + { + return (TDHead.Control >> 28) & 0xF; + } + + u32 Enqueue(u32 head) + { + if (CurrentState == NotQueued) + { + EndpointDescriptor.Next = head; + head = (u32)&EndpointDescriptor; + CurrentState = Idle; + } + return head; + } +}; + +class Device +{ +public: + u8 _endpointMap[MAX_ENDPOINTS_PER_DEVICE*2]; + u8 Hub; + u8 Port; + u8 Addr; + u8 Pad; + + // Only if this device is a hub + u8 HubPortCount; // nonzero if this is a hub + u8 HubInterruptData; + u8 HubMap; + u8 HubMask; + + int Flags; // 1 = Disconnected + + Setup SetupBuffer; + + // Allocate endpoint zero + int Init(DeviceDescriptor* d, int hub, int port, int addr, int lowSpeed) + { + Hub = hub; + Port = port; + Addr = addr; + Flags = lowSpeed; + memset(_endpointMap,0xFF,sizeof(_endpointMap)); + return 0; + } + + int SetEndpointIndex(int ep, int endpointIndex) + { + for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2) + { + if (_endpointMap[i] == 0xFF) // Add endpoint to map + { + _endpointMap[i] = ep; + _endpointMap[i+1] = endpointIndex; + return 0; + } + } + return ERR_ENDPOINT_NONE_LEFT; + } + + int GetEndpointIndex(int ep) + { + for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2) + { + if (_endpointMap[i] == ep) + return _endpointMap[i+1]; + if (_endpointMap[i] == 0xFF) + break; + } + return -1; + } +}; + +class HostController +{ +public: + HCCA CommunicationArea; + Endpoint Endpoints[MAX_ENDPOINTS_TOTAL]; // Multiple of 16 + + Endpoint EndpointZero; // For device enumeration + HCTD _commonTail; + Setup _setupZero; + + Device Devices[MAX_DEVICES]; + u32 _frameNumber; // 32 bit ms counter + + u8 _callbacksPending; // Endpoints with callbacks are pending, set from ISR via ProcessDoneQueue + u8 _rootHubStatusChange; // Root hub status has changed, set from ISR + u8 _unused0; + u8 _unused1; + + u8 _connectPending; // Reset has initiated a connect + u8 _connectCountdown; // Number of ms left after reset before we can connect + u8 _connectHub; // Will connect on this hub + u8 _connectPort; // ... and this port + + u8 SRAM[0]; // Start of free SRAM + + void Loop() + { + u16 elapsed = CommunicationArea.FrameNumber - (u16)_frameNumber; // extend to 32 bits + _frameNumber += elapsed; + + // Do callbacks, if any + while (_callbacksPending) + { + for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++) + { + Endpoint* endpoint = Endpoints + i; + if (endpoint->CurrentState == Endpoint::CallbackPending) + { + _callbacksPending--; + endpoint->CurrentState = Endpoint::Idle; + endpoint->Callback(endpoint->Device(),endpoint->Address(),endpoint->Status(),endpoint->Data,endpoint->Length,endpoint->UserData); + } + } + } + + // Deal with changes on the root hub + if (_rootHubStatusChange) + { + u32 status = LPC_USB->HcRhPortStatus1; + _rootHubStatusChange = 0; + if (status >> 16) + { + HubStatusChange(0,1,status); + LPC_USB->HcRhPortStatus1 = status & 0xFFFF0000; // clear status changes + } + } + + // Connect after reset timeout + if (_connectCountdown) + { + if (elapsed >= _connectCountdown) + { + _connectCountdown = 0; + Connect(_connectHub,_connectPort & 0x7F,_connectPort & 0x80); + } else + _connectCountdown -= elapsed; + } + } + + // HubInterrupt - bitmap in dev->HubInterruptData + void HubInterrupt(int device) + { + Device* dev = &Devices[device-1]; + for (int i = 0; i < dev->HubPortCount; i++) + { + int port = i+1; + if (dev->HubInterruptData & (1 << port)) + { + u32 status = 0; + GetPortStatus(device,port,&status); + if (status >> 16) + { + if (_connectPending && (status & ConnectStatusChange)) + continue; // Don't connect again until previous device has been added and addressed + + HubStatusChange(device,port,status); + if (status & ConnectStatusChange) + ClearPortFeature(device,C_PORT_CONNECTION,port); + if (status & PortResetStatusChange) + ClearPortFeature(device,C_PORT_RESET,port); + } + } + } + } + + static void HubInterruptCallback(int device, int endpoint, int status, u8* data, int len, void* userData) + { + HostController* controller = (HostController*)userData; + if (status == 0) + controller->HubInterrupt(device); + USBInterruptTransfer(device,endpoint,data,1,HubInterruptCallback,userData); + } + + int InitHub(int device) + { + u8 buf[16]; + int r= USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_DEVICE,GET_DESCRIPTOR,(DESCRIPTOR_TYPE_HUB << 8),0,buf,sizeof(buf)); + if (r < 0) + return ERR_HUB_INIT_FAILED; + + // turn on power on the hubs ports + Device* dev = &Devices[device-1]; + int ports = buf[2]; + dev->HubPortCount = ports; + for (int i = 0; i < ports; i++) + SetPortPower(device,i+1); + + // Enable hub change interrupts + return USBInterruptTransfer(device,0x81,&dev->HubInterruptData,1,HubInterruptCallback,this); + } + + int AddEndpoint(int device, int ep, int attributes, int maxPacketSize, int interval) + { + LOG("AddEndpoint D:%02X A:%02X T:%02X P:%04X I:%02X\n",device,ep,attributes,maxPacketSize,interval); + Device* dev = &Devices[device-1]; + Endpoint* endpoint = AllocateEndpoint(device,ep,attributes,maxPacketSize); + if (!endpoint) + return ERR_ENDPOINT_NONE_LEFT; + dev->SetEndpointIndex(ep,endpoint - Endpoints); + endpoint->EndpointDescriptor.Control |= dev->Flags; // Map in slow speed + return 0; // TODO ed->bInterval + } + + int AddEndpoint(int device, EndpointDescriptor* ed) + { + return AddEndpoint(device,ed->bEndpointAddress,ed->bmAttributes,ed->wMaxPacketSize,ed->bInterval); + } + + // allocate a endpoint + Endpoint* AllocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize) + { + for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++) + { + Endpoint* ep = &Endpoints[i]; + if (ep->CurrentState == 0) + { + //LOG("Allocated endpoint %d to %02X:%02X\n",i,device,endpointAddress); + ep->Flags = (endpointAddress & 0x80) | (type & 3); + ep->CurrentState = Endpoint::NotQueued; + ep->EndpointDescriptor.Control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device; + return ep; + } + } + return 0; + } + + Endpoint* GetEndpoint(int device, int ep) + { + if (device == 0) + { + //printf("WARNING: USING DEVICE 0\n"); + return &EndpointZero; + } + if (device > MAX_DEVICES) + return 0; + int i = Devices[device-1].GetEndpointIndex(ep); + if (i == -1) + return 0; + return Endpoints + i; + } + + int Transfer(Endpoint* endpoint, int token, u8* data, int len, int state) + { + //LOG("Transfer %02X T:%d Len:%d S:%d\n",endpoint->Address(),token,len,state); + + int toggle = 0; + if (endpoint->Address() == 0) + toggle = (token == TOKEN_SETUP) ? TD_TOGGLE_0 : TD_TOGGLE_1; + + if (token != TOKEN_SETUP) + token = (token == TOKEN_IN ? TD_IN : TD_OUT); + + HCTD* head = &endpoint->TDHead; + HCTD* tail = &_commonTail; + + head->Control = TD_ROUNDING | token | TD_DELAY_INT(0) | toggle | TD_CC; + head->CurrBufPtr = (u32)data; + head->BufEnd = (u32)(data + len - 1); + head->Next = (u32)tail; + + HCED* ed = &endpoint->EndpointDescriptor; + ed->HeadTd = (u32)head | (ed->HeadTd & 0x00000002); // carry toggle + ed->TailTd = (u32)tail; + + //HCTD* td = head; + //LOG("%04X TD %08X %08X %08X Next:%08X\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next); + //LOG("%04X ED %08X %08X %08X\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd); + + switch (endpoint->Flags & 3) + { + case ENDPOINT_CONTROL: + LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED); // May change state NotQueued->Idle + endpoint->CurrentState = state; // Get in before an int + LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | ControlListFilled; + LPC_USB->HcControl = LPC_USB->HcControl | ControlListEnable; + break; + + case ENDPOINT_BULK: + LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED); + endpoint->CurrentState = state; + LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled; + LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable; + break; + + case ENDPOINT_INTERRUPT: + CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]); + endpoint->CurrentState = state; + LPC_USB->HcControl |= PeriodicListEnable; + break; + } + return 0; + } + + // Remove an endpoint from an active queue + bool Remove(HCED* ed, volatile HCED** queue) + { + if (*queue == 0) + return false; + if (*queue == (volatile HCED*)ed) + { + *queue = (volatile HCED*)ed->Next; // At head of queue + return true; + } + + volatile HCED* head = *queue; + while (head) + { + if (head->Next == (u32)ed) + { + head->Next = ed->Next; + return true; + } + head = (volatile HCED*)head->Next; + } + return false; + } + + void Release(Endpoint* endpoint) + { + if (endpoint->CurrentState == Endpoint::NotQueued) + { + // Never event used it, nothing to do + } + else + { + HCED* ed = (HCED*)endpoint; + ed->Control |= 0x4000; // SKIP + switch (endpoint->Flags & 0x03) + { + case ENDPOINT_CONTROL: + Remove(ed,(volatile HCED**)&LPC_USB->HcControlHeadED); + break; + case ENDPOINT_BULK: + Remove(ed,(volatile HCED**)&LPC_USB->HcBulkHeadED); + break; + case ENDPOINT_INTERRUPT: + for (int i = 0; i < 32; i++) + Remove(ed,(volatile HCED**)&CommunicationArea.InterruptTable[i]); + break; + } + + u16 fn = CommunicationArea.FrameNumber; + while (fn == CommunicationArea.FrameNumber) + ; // Wait for next frame + + } + + // In theory, the endpoint is now dead. + // TODO: Will Callbacks ever be pending? BUGBUG + memset(endpoint,0,sizeof(Endpoint)); + } + + // Pop the last TD from the list + HCTD* Reverse(HCTD* current) + { + HCTD *result = NULL,*temp; + while (current) + { + temp = (HCTD*)current->Next; + current->Next = (u32)result; + result = current; + current = temp; + } + return result; + } + + // Called from interrupt... + // Control endpoints use a state machine to progress through the transfers + void ProcessDoneQueue(u32 tdList) + { + HCTD* list = Reverse((HCTD*)tdList); + while (list) + { + Endpoint* endpoint = (Endpoint*)(list-1); + list = (HCTD*)list->Next; + int ep = endpoint->Address(); + bool in = endpoint->Flags & 0x80; + int status = (endpoint->TDHead.Control >> 28) & 0xF; + + //LOG("ProcessDoneQueue %02X %08X\n",ep,endpoint->TDHead.Control); + + if (status != 0) + { + LOG("ProcessDoneQueue status %02X %d\n",ep,status); + endpoint->CurrentState = Endpoint::Idle; + } else { + switch (endpoint->CurrentState) + { + case Endpoint::SetupQueued: + if (endpoint->Length == 0) + Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Skip Data Phase + else + Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued); // Setup is done, now Data + break; + + case Endpoint::DataQueued: + if (endpoint->TDHead.CurrBufPtr) + endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data; + + if (ep == 0) + Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Data is done, now Status, Control only + else + endpoint->CurrentState = Endpoint::Idle; + break; + + case Endpoint::StatusQueued: // Transaction is done + endpoint->CurrentState = Endpoint::Idle; + break; + } + } + + // Complete, flag if we need a callback + if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle) + { + endpoint->CurrentState = Endpoint::CallbackPending; + _callbacksPending++; + } + } + } + + // Hack to reset devices that don't want to connect + int AddDevice(int hub, int port, bool isLowSpeed) + { + int device = AddDeviceCore(hub,port,isLowSpeed); + if (device < 0) + { + LOG("========RETRY ADD DEVICE========\n"); // This will go for ever.. TODO power cycle root? + Disconnect(hub,port); // Could not read descriptor at assigned address, reset this port and try again + ResetPort(hub,port); // Cheap bluetooth dongles often need this on a hotplug + return -1; + } + return device; + } + + int AddDeviceCore(int hub, int port, bool isLowSpeed) + { + int lowSpeed = isLowSpeed ? 0x2000 : 0; + DeviceDescriptor desc; + EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed; // MaxPacketSize == 8 + int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8); + if (r < 0) + { + LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\n"); + return r; + } + + EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed; // Actual MaxPacketSize + r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc)); + if (r < 0) + return r; + + LOG("\nClass %02X found %04X:%04X\n\n",desc.bDeviceClass,desc.idVendor,desc.idProduct); + + // Now assign the device an address, move off EndpointZero + int device = 0; + for (int i = 0; i < MAX_DEVICES; i++) + { + if (Devices[i].Port == 0) + { + device = i+1; + break; + } + } + if (!device) + return ERR_DEVICE_NONE_LEFT; + + r = SetAddress(0,device); + if (r) + return r; + DelayMS(2); + + // Now at a nonzero address, create control endpoint + Device* dev = &Devices[device-1]; + dev->Init(&desc,hub,port,device,lowSpeed); + AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0); + _connectPending = 0; + + // Verify this all works + r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc)); + if (r < 0) + return r; + + // Set to interface 0 by default + // Calls LoadDevice if interface is found + r = SetConfigurationAndInterface(device,1,0,&desc); + + if (desc.bDeviceClass == CLASS_HUB) + InitHub(device); // Handle hubs in this code + + return device; + } + + // Walk descriptors and create endpoints for a given device + // TODO configuration !=1, alternate settings etc. + int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc) + { + u8 buffer[255]; + int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,sizeof(buffer)); + if (err < 0) + return err; + + err = SetConfiguration(device,configuration); + if (err < 0) + return err; + + // Add the endpoints for this interface + int len = buffer[2] | (buffer[3] << 8); + u8* d = buffer; + u8* end = d + len; + InterfaceDescriptor* found = 0; + while (d < end) + { + if (d[1] == DESCRIPTOR_TYPE_INTERFACE) + { + InterfaceDescriptor* id = (InterfaceDescriptor*)d; + if (id->bInterfaceNumber == interfaceNumber) + { + found = id; + d += d[0]; + while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE) + { + switch (d[1]) + { + case DESCRIPTOR_TYPE_ENDPOINT: + AddEndpoint(device,(EndpointDescriptor*)d); + break; + default: + LOG("Skipping descriptor %02X (%d bytes)\n",d[1],d[0]); + } + d += d[0]; + } + } + } + d += d[0]; + } + + if (!found) + return ERR_INTERFACE_NOT_FOUND; + OnLoadDevice(device,desc,found); + return 0; + } + + void Init() + { + LOG("USB INIT (Controller is %d bytes)\n",sizeof(*this)); + memset(this,0,sizeof(HostController)); + EndpointZero.CurrentState = Endpoint::NotQueued; + HWInit(&CommunicationArea); + DelayMS(10); + } + + void ResetPort(int hub, int port) + { + LOG("ResetPort Hub:%d Port:%d\n",hub,port); + _connectPending++; // Only reset/add 1 device at a time + if (hub == 0) + LPC_USB->HcRhPortStatus1 = PortResetStatus; // Reset Root Hub, port 1 + else + SetPortReset(hub,port); // or reset other hub + } + + void Disconnect(int hub, int port) + { + LOG("Disconnect Hub:%d Port:%d\n",hub,port); // Mark a device for destruction + for (int i = 0; i < MAX_DEVICES; i++) + { + Device* dev = Devices + i; + if (dev->Port == port && dev->Hub == hub) + { + // Disconnect everything that is attached to this device if it is a hub + for (int p = 0; p < dev->HubPortCount; p++) + Disconnect(i+1,p+1); + + // Now release endpoints + for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2) + { + u8 endpointIndex = dev->_endpointMap[j]; + if (endpointIndex != 0xFF) + Release(Endpoints + endpointIndex); + } + dev->Port = 0; // Device is now free + dev->Flags = 0; + return; + } + } + } + + // called after reset + void Connect(int hub, int port, bool lowspeed) + { + LOG("Connect Hub:%d Port:%d %s\n",hub,port,lowspeed ? "slow" : "full"); + AddDevice(hub,port,lowspeed); + } + + // Called from interrupt + void HubStatusChange(int hub, int port, u32 status) + { + LOG("HubStatusChange Hub:%d Port:%d %08X\n",hub,port,status); + if (status & ConnectStatusChange) + { + if (status & CurrentConnectStatus) // Connecting + ResetPort(hub,port); // Reset to initiate connect (state machine?) + else + Disconnect(hub,port); + } + + if (status & PortResetStatusChange) + { + if (!(status & PortResetStatus)) + { + _connectCountdown = 200; // Schedule a connection in 200ms + if (status & LowspeedDevice) + port |= 0x80; + _connectHub = hub; + _connectPort = port; + } + } + } + + #define HOST_CLK_EN (1<<0) + #define PORTSEL_CLK_EN (1<<3) + #define AHB_CLK_EN (1<<4) + #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN) + + #define FRAMEINTERVAL (12000-1) // 1ms + #define DEFAULT_FMINTERVAL ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL) + + void DelayMS(int ms) + { + u16 f = ms + CommunicationArea.FrameNumber; + while (f != CommunicationArea.FrameNumber) + ; + } + + static void HWInit(HCCA* cca) + { + NVIC_DisableIRQ(USB_IRQn); + + // turn on power for USB + LPC_SC->PCONP |= (1UL<<31); + // Enable USB host clock, port selection and AHB clock + LPC_USB->USBClkCtrl |= CLOCK_MASK; + // Wait for clocks to become available + while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK) + ; + + // We are a Host + LPC_USB->OTGStCtrl |= 1; + LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN; // we don't need port selection clock until we do OTG + + // configure USB pins + LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28)); + LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // USB D+/D- + + LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22)); // USB_PPWR, USB_OVRCR + LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22)); + + LPC_PINCON->PINSEL4 &= ~(3 << 18); // USB_CONNECT + LPC_PINCON->PINSEL4 |= (1 << 18); + + // Reset OHCI block + LPC_USB->HcControl = 0; + LPC_USB->HcControlHeadED = 0; + LPC_USB->HcBulkHeadED = 0; + + LPC_USB->HcCommandStatus = HostControllerReset; + LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; + LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100; + + LPC_USB->HcControl = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask; + LPC_USB->HcRhStatus = SetGlobalPower; + + LPC_USB->HcHCCA = (u32)cca; + LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; + LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow; + + NVIC_SetPriority(USB_IRQn, 0); + NVIC_EnableIRQ(USB_IRQn); + while (cca->FrameNumber < 10) + ; // 10ms delay before diving in + } +}; + +//==================================================================================== +//==================================================================================== +// Host controller instance and Interrupt handler + +static HostController _controller __attribute__((at(USB_RAM_BASE))); + +extern "C" void USB_IRQHandler(void) __irq; +void USB_IRQHandler (void) __irq +{ + u32 int_status = LPC_USB->HcInterruptStatus; + + if (int_status & RootHubStatusChange) // Root hub status change + _controller._rootHubStatusChange++; // Just flag the controller, will be processed in USBLoop + + u32 head = 0; + if (int_status & WritebackDoneHead) + { + head = _controller.CommunicationArea.DoneHead; // Writeback Done + _controller.CommunicationArea.DoneHead = 0; + } + LPC_USB->HcInterruptStatus = int_status; + + if (head) + _controller.ProcessDoneQueue(head); // TODO - low bit can be set BUGBUG +} + +//==================================================================================== +//==================================================================================== +// API Methods + +void USBInit() +{ + return _controller.Init(); +} + +void USBLoop() +{ + return _controller.Loop(); +} + +u8* USBGetBuffer(u32* len) +{ + *len = USB_RAM_SIZE - sizeof(HostController); + return _controller.SRAM; +} + +static Setup* GetSetup(int device) +{ + if (device == 0) + return &_controller._setupZero; + + if (device < 1 || device > MAX_DEVICES) + return 0; + return &_controller.Devices[device-1].SetupBuffer; +} + +// Loop until IO on endpoint is complete +static int WaitIODone(Endpoint* endpoint) +{ + if (endpoint->CurrentState == Endpoint::NotQueued) + return 0; + while (endpoint->CurrentState != Endpoint::Idle) + USBLoop(); // May generate callbacks, mount or unmount devices etc + int status = endpoint->Status(); + if (status == 0) + return endpoint->Length; + return -status; +} + +int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData) +{ + Endpoint* endpoint = _controller.GetEndpoint(device,ep); + if (!endpoint) + return ERR_ENDPOINT_NOT_FOUND; + + WaitIODone(endpoint); + endpoint->Flags = flags; + endpoint->Data = data; + endpoint->Length = length; + endpoint->Callback = callback; + endpoint->UserData = userData; + if (ep == 0) + _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued); + else + _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued); + if (callback) + return IO_PENDING; + return WaitIODone(endpoint); +} + +int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData) +{ + Setup* setup = GetSetup(device); + if (!setup) + return ERR_DEVICE_NOT_FOUND; + + // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call + WaitIODone(_controller.GetEndpoint(device,0)); + + setup->bm_request_type = request_type; + setup->b_request = request; + setup->w_value = value; + setup->w_index = index; + setup->w_length = length; + return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData); +} + +int USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData) +{ + return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData); +} + +int USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData) +{ + return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData); +} + +int GetDescriptor(int device, int descType,int descIndex, u8* data, int length) +{ + return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0); +} + +int GetString(int device, int index, char* dst, int length) +{ + u8 buffer[255]; + int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer)); + if (le < 0) + return le; + if (length < 1) + return -1; + length <<= 1; + if (le > length) + le = length; + for (int j = 2; j < le; j += 2) + *dst++ = buffer[j]; + *dst = 0; + return (le>>1)-1; +} + +int SetAddress(int device, int new_addr) +{ + return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0); +} + +int SetConfiguration(int device, int configNum) +{ + return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0); +} + +int SetInterface(int device, int ifNum, int altNum) +{ + return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0); +} + +// HUB stuff +int SetPortFeature(int device, int feature, int index) +{ + return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0); +} + +int ClearPortFeature(int device, int feature, int index) +{ + return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0); +} + +int SetPortPower(int device, int port) +{ + int r = SetPortFeature(device,PORT_POWER,port); + _controller.DelayMS(20); // 80ms to turn on a hubs power... DESCRIPTOR? todo + return r; +} + +int SetPortReset(int device, int port) +{ + return SetPortFeature(device,PORT_RESET,port); +} + +int GetPortStatus(int device, int port, u32* status) +{ + return USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,GET_STATUS,0,port,(u8*)status,4); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/USBHost.h Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,200 @@ + +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef USBHOST_H +#define USBHOST_H + +#ifndef u8 +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +typedef char s8; +typedef short s16; +typedef char s32; +#endif + +#define ENDPOINT_CONTROL 0 +#define ENDPOINT_ISOCRONOUS 1 +#define ENDPOINT_BULK 2 +#define ENDPOINT_INTERRUPT 3 + +#define DESCRIPTOR_TYPE_DEVICE 1 +#define DESCRIPTOR_TYPE_CONFIGURATION 2 +#define DESCRIPTOR_TYPE_STRING 3 +#define DESCRIPTOR_TYPE_INTERFACE 4 +#define DESCRIPTOR_TYPE_ENDPOINT 5 + +#define DESCRIPTOR_TYPE_HID 0x21 +#define DESCRIPTOR_TYPE_REPORT 0x22 +#define DESCRIPTOR_TYPE_PHYSICAL 0x23 +#define DESCRIPTOR_TYPE_HUB 0x29 + +enum USB_CLASS_CODE +{ + CLASS_DEVICE, + CLASS_AUDIO, + CLASS_COMM_AND_CDC_CONTROL, + CLASS_HID, + CLASS_PHYSICAL = 0x05, + CLASS_STILL_IMAGING, + CLASS_PRINTER, + CLASS_MASS_STORAGE, + CLASS_HUB, + CLASS_CDC_DATA, + CLASS_SMART_CARD, + CLASS_CONTENT_SECURITY = 0x0D, + CLASS_VIDEO = 0x0E, + CLASS_DIAGNOSTIC_DEVICE = 0xDC, + CLASS_WIRELESS_CONTROLLER = 0xE0, + CLASS_MISCELLANEOUS = 0xEF, + CLASS_APP_SPECIFIC = 0xFE, + CLASS_VENDOR_SPECIFIC = 0xFF +}; + +#define DEVICE_TO_HOST 0x80 +#define HOST_TO_DEVICE 0x00 +#define REQUEST_TYPE_CLASS 0x20 +#define RECIPIENT_DEVICE 0x00 +#define RECIPIENT_INTERFACE 0x01 +#define RECIPIENT_ENDPOINT 0x02 +#define RECIPIENT_OTHER 0x03 + +#define GET_STATUS 0 +#define CLEAR_FEATURE 1 +#define SET_FEATURE 3 +#define SET_ADDRESS 5 +#define GET_DESCRIPTOR 6 +#define SET_DESCRIPTOR 7 +#define GET_CONFIGURATION 8 +#define SET_CONFIGURATION 9 +#define GET_INTERFACE 10 +#define SET_INTERFACE 11 +#define SYNCH_FRAME 11 + +// -5 is nak +/* +0010 ACK Handshake +1010 NAK Handshake +1110 STALL Handshake +0110 NYET (No Response Yet) +*/ + +#define IO_PENDING -100 +#define ERR_ENDPOINT_NONE_LEFT -101 +#define ERR_ENDPOINT_NOT_FOUND -102 +#define ERR_DEVICE_NOT_FOUND -103 +#define ERR_DEVICE_NONE_LEFT -104 +#define ERR_HUB_INIT_FAILED -105 +#define ERR_INTERFACE_NOT_FOUND -106 + +typedef struct +{ + u8 bLength; + u8 bDescriptorType; + u16 bcdUSB; + u8 bDeviceClass; + u8 bDeviceSubClass; + u8 bDeviceProtocol; + u8 bMaxPacketSize; + u16 idVendor; + u16 idProduct; + u16 bcdDevice; // version + u8 iManufacturer; + u8 iProduct; + u8 iSerialNumber; + u8 bNumConfigurations; +} DeviceDescriptor; // 16 bytes + +typedef struct +{ + u8 bLength; + u8 bDescriptorType; + u16 wTotalLength; + u8 bNumInterfaces; + u8 bConfigurationValue; // Value to use as an argument to select this configuration + u8 iConfiguration; // Index of String Descriptor describing this configuration + u8 bmAttributes; // Bitmap D7 Reserved, set to 1. (USB 1.0 Bus Powered),D6 Self Powered,D5 Remote Wakeup,D4..0 = 0 + u8 bMaxPower; // Maximum Power Consumption in 2mA units +} ConfigurationDescriptor; + +typedef struct +{ + u8 bLength; + u8 bDescriptorType; + u8 bInterfaceNumber; + u8 bAlternateSetting; + u8 bNumEndpoints; + u8 bInterfaceClass; + u8 bInterfaceSubClass; + u8 bInterfaceProtocol; + u8 iInterface; // Index of String Descriptor Describing this interface +} InterfaceDescriptor; + +typedef struct +{ + u8 bLength; + u8 bDescriptorType; + u8 bEndpointAddress; // Bits 0:3 endpoint, Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints) + u8 bmAttributes; // Bits 0:1 00 = Control, 01 = Isochronous, 10 = Bulk, 11 = Interrupt + u16 wMaxPacketSize; + u8 bInterval; // Interval for polling endpoint data transfers. +} EndpointDescriptor; + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u16 bcdHID; + u8 bCountryCode; + u8 bNumDescriptors; + u8 bDescriptorType2; + u16 wDescriptorLength; +} HIDDescriptor; + +//============================================================================ +//============================================================================ + + +void USBInit(); +void USBLoop(); +u8* USBGetBuffer(u32* len); + +// Optional callback for transfers, called at interrupt time +typedef void (*USBCallback)(int device, int endpoint, int status, u8* data, int len, void* userData); + +// Transfers +int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback = 0, void* userData = 0); +int USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback = 0, void* userData = 0); +int USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback = 0, void* userData = 0); + +// Standard Device methods +int GetDescriptor(int device, int descType, int descIndex, u8* data, int length); +int GetString(int device, int index, char* dst, int length); +int SetAddress(int device, int new_addr); +int SetConfiguration(int device, int configNum); +int SetInterface(int device, int ifNum, int altNum); + +// Implemented to notify app of the arrival of a device +void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc); + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/Utils.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,48 @@ + + +#include "mbed.h" +#include "Utils.h" + +void printfBytes(const char* s, const u8* data, int len) +{ + printf("%s %d:",s,len); + if (len > 256) + len = 256; + while (len-- > 0) + printf(" %02X",*data++); + printf("\n"); +} + +void printHexLine(const u8* d, int addr, int len) +{ + printf("%04X ",addr); + int i; + for (i = 0; i < len; i++) + printf("%02X ",d[i]); + for (;i < 16; i++) + printf(" "); + char s[16+1]; + memset(s,0,sizeof(s)); + for (i = 0; i < len; i++) + { + int c = d[i]; + if (c < 0x20 || c > 0x7E) + c = '.'; + s[i] = c; + } + printf("%s\n",s); +} + +void printHex(const u8* d, int len) +{ + int addr = 0; + while (len) + { + int count = len; + if (count > 16) + count = 16; + printHexLine(d+addr,addr,count); + addr += 16; + len -= count; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/Utils.h Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,37 @@ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +void DelayMS(int ms); + +void printfBytes(const char* label,const u8* data, int len); +void printHex(const u8* d, int len); + +#ifndef min +#define min(_a,_b) ((_a) < (_b) ? (_a) : (_b)) +#endif + +inline int LE16(const u8* d) +{ + return d[0] | (d[1] << 8); +} + +inline u32 BE32(const u8* d) +{ + return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3]; +} + +inline void BE32(u32 n, u8* d) +{ + d[0] = (u8)(n >> 24); + d[1] = (u8)(n >> 16); + d[2] = (u8)(n >> 8); + d[3] = (u8)n; +} + +inline void BE16(u32 n, u8* d) +{ + d[0] = (u8)(n >> 8); + d[1] = (u8)n; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/hci.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,426 @@ + +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "Utils.h" +#include "hci.h" +#include "hci_private.h" + +enum hci_callback_evt +{ + NONE, + CONNECT, + DISCONECT, + INQUIRYRESULT +}; + +#define MAX_BLUETOOTH_ADAPTERS 1 + +enum StateMask { + MASK_RESET = 1, + MASK_READ_BUFFER_SIZE = 2, + MASK_READ_BD_ADDR = 4, + MASK_INITED = 8, + MASK_INQUIRY = 16, + MASK_REMOTE_NAME = 32, + MASK_CREATE_CONNECTION = 64 +}; + +int HCI::Open(HCITransport* transport, HCICallback callback) +{ + _transport = transport; + _transport->Set(this); + _callback = callback; + _state = 0; + for (int i = 0; i < MAX_BTDEVICES; i++) + { + _devices[i].Init(); + _devices[i]._transport = transport; + } + return SendCmd(HCI_OP_RESET); +} + +void printf(const BD_ADDR* addr); + +BTDevice* HCI::Find(const BD_ADDR* addr) +{ + for (int i = 0; i < MAX_BTDEVICES; i++) + if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0) + return &_devices[i]; + return 0; +} + +BTDevice* HCI::Find(int handle) +{ + for (int i = 0; i < MAX_BTDEVICES; i++) + if (_devices[i]._state != 0 && handle == _devices[i]._handle) + return &_devices[i]; + return 0; +} +// +bool HCI::Busy() +{ + return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0; +} + +int HCI::Inquiry(int duration) +{ + _state |= MASK_INQUIRY; + u8 buf[5]; + buf[0] = 0x33; + buf[1] = 0x8B; + buf[2] = 0x9E; + buf[3] = duration; + buf[4] = 5; // 5 results + SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf)); + return 0; +} + +int HCI::SendCmd(int cmd, const u8* params, int len) +{ + u8 b[32]; + b[0] = cmd; + b[1] = (cmd >> 8); + b[2] = len; + if (params) + memcpy(b+3,params,len); + _transport->HCISend(b,len+3); + return 0; +} + +void HCI::OnCommandComplete(int cmd, const u8* data, int len) +{ + // printf("%04X %s",cmd,CmdStr(cmd)); + if (len < 0) + return; + //printfBytes(" complete",data,min(16,len)); + + switch (cmd) + { + // Init phase 0 + case HCI_OP_RESET: // Reset done, init chain to HCI_OP_READ_LOCAL_NAME + SendCmd(HCI_OP_READ_BUFFER_SIZE); + _state |= MASK_RESET; + break; + + // Init phase 1 + case HCI_OP_READ_BUFFER_SIZE: + _acl_mtu = LE16(data); + _sco_mtu = data[2]; + _acl_max_pkt = LE16(data+3); + _sco_max_pkt = LE16(data+5); + SendCmd(HCI_OP_READ_BD_ADDR); + _state |= MASK_READ_BUFFER_SIZE; + break; + + // Init phase 2 + case HCI_OP_READ_BD_ADDR: + _localAddr = *((BD_ADDR*)data); // Local Address + _state |= MASK_READ_BD_ADDR; + _state |= MASK_INITED; + Callback(CALLBACK_READY,data,6); + break; + + // 0CXX + case HCI_OP_READ_LOCAL_NAME: + break; + + case HCI_OP_READ_LOCAL_VERSION: + // params + //SendCmd(HCI_OP_READ_LOCAL_NAME); + break; + + case HCI_OP_READ_LOCAL_COMMANDS: + break; + + case HCI_OP_READ_LOCAL_FEATURES: + //SendCmd(HCI_OP_READ_LOCAL_VERSION); + break; + + case HCI_OP_READ_LOCAL_EXT_FEATURES: + break; + + case HCI_OP_PIN_CODE_REPLY: + printf("Got pin reply\n"); + break; + + default: + printf("Unrecognized Command %04X\n",cmd); + break; + } +} + +void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len) +{ + _callback(this,c,data,len); +} + +int HCI::RemoteNameRequest(const BD_ADDR* addr) +{ + _state |= MASK_REMOTE_NAME; + u8 buf[6+4]; + memset(buf,0,sizeof(buf)); + memcpy(buf,addr,6); + buf[7] = 1; + return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf)); +} + +int HCI::CreateConnection(const BD_ADDR* remoteAddr) +{ + _state |= MASK_CREATE_CONNECTION; + u8 buf[6+7]; + memset(buf,0,sizeof(buf)); + memcpy(buf,remoteAddr,6); + buf[6] = 0x18; // DM1,DH1 + buf[7] = 0xCC; // DM3, DH3, DM5, DH5 + buf[8] = 1; // Page Repetition R1 + return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf)); +} + +int HCI::Disconnect(const BD_ADDR* bdaddr) +{ + BTDevice* d = Find(bdaddr); + if (!d) + return ERR_HCI_DEVICE_NOT_FOUND; + int handle = d->_handle; + printf("Disconnect from %d\n",handle); + _state |= MASK_CREATE_CONNECTION; + u8 buf[3]; + buf[0] = handle; + buf[1] = (handle >> 8); + buf[2] = 0x13; + return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf)); +} + +void HCI::DisconnectComplete(int handle) +{ + BTDevice* d = Find(handle); + if (!d) + return; + d->_handle = 0; +} + +int HCI::DisconnectAll() +{ + BTDevice* devs[8]; + int count = GetDevices(devs,8); + for (int i = 0; i < count; i++) + Disconnect(&devs[i]->_info.bdaddr); + return 0; +} + +int HCI::PinCodeReply(const u8* data) +{ + u8 b[6+1+16]; + memset(b,0,sizeof(b)); + memcpy(b,data,6); + b[6] = 4; + b[7] = '0'; + b[8] = '0'; + b[9] = '0'; + b[10] = '0'; + return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b)); +} + +void HCI::InquiryResult(const inquiry_info* info) +{ + BTDevice* bt = Find(&info->bdaddr); + if (!bt) // new device + { + for (int i = 0; i < MAX_BTDEVICES; i++) + { + if (_devices[i]._state == 0) + { + bt = _devices + i; + bt->_state = 1; + break; + } + } + if (!bt) + { + printf("HCI::InquiryResult too many devices\n"); + return; // Too many devices! + } + } + + bt->_info = *info; +} + +int HCI::GetDevices(BTDevice** devices, int maxDevices) +{ + int j = 0; + for (int i = 0; i < MAX_BTDEVICES; i++) + { + if (_devices[i]._state != 0) + { + devices[j++] = _devices + i; + if (j == maxDevices) + break; + } + } + return j; +} + +void HCI::RemoteName(const BD_ADDR* addr, const char* name) +{ + BTDevice* d = Find(addr); + if (d) + { + strncpy(d->_name,name,sizeof(d->_name)-1); + d->_name[sizeof(d->_name)-1] = 0; + } +} + +void HCI::ConnectComplete(const connection_info* info) +{ + BTDevice* d = Find(&info->bdaddr); + if (!d) + return; + if (info->status == 0) + { + d->_handle = info->handle; + printf("Connected on %04X\n",info->handle); + } else + printf("Connection failed with %d\n",info->status); +} + +void HCI::HCIRecv(const u8* data, int len) +{ + // printfBytes(EvtStr(data[0]),data,min(len,16)); + switch (data[0]) + { + case HCI_EV_INQUIRY_COMPLETE: + printfBytes("Inquiry Complete",data,data[1]); + _state &= ~MASK_INQUIRY; + Callback(CALLBACK_INQUIRY_DONE,0,0); + break; + + case HCI_EV_INQUIRY_RESULT: + { + const u8* end = data[1] + data + 2; + data += 3; + while (data < end) + { + inquiry_info align; + memcpy(&align,data,sizeof(inquiry_info)); + InquiryResult(&align); + Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info)); + data += 14; + } + } + break; + + case HCI_EV_CONN_COMPLETE: + _state &= ~MASK_CREATE_CONNECTION; + { + connection_info align; + memcpy(&align,data+2,sizeof(connection_info)); + ConnectComplete(&align); + Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info)); + } + break; + + case HCI_EV_CONN_REQUEST: + break; + + case HCI_EV_DISCONN_COMPLETE: + DisconnectComplete(LE16(data+3)); + break; + + case HCI_EV_REMOTE_NAME: + { + BD_ADDR* addr = (BD_ADDR*)(data+3); + const char* name = (const char*)(data + 9); + RemoteName(addr,name); + } + Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1)); // addr is in here too + _state &= ~MASK_REMOTE_NAME; + break; + + case HCI_EV_CMD_STATUS: + { + const char* errs = HCIErrStr(data[2]); + printf("Status %s %s\n",CmdStr(LE16(data+4)),errs); + } + break; + + case HCI_EV_CMD_COMPLETE: + OnCommandComplete(data[3] | (data[4] << 8),data+6,data[1]-4); + break; + + case HCI_EV_PIN_CODE_REQ: + PinCodeReply(data+2); + break; + + case HCI_EV_LINK_KEY_REQ: + SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6); + break; + + default: + ; + // printfBytes(":",data,data[1]+2); + } +} + +int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr) +{ + L2CAPSocket* l2capsock = (L2CAPSocket*)sock; + L2CAPAddr* l2capaddr = (L2CAPAddr*)addr; + BTDevice* bt = Find(&l2capaddr->bdaddr); + if (!bt) + { + printf("Can't open l2cap %d on ",l2capaddr->psm); + printf(&l2capaddr->bdaddr); + printf("\n"); + return ERR_HCI_DEVICE_NOT_FOUND; + } + l2capsock->btdevice = bt; + return bt->Open(sock,addr); +} + +int HCI::Send(SocketInternal* sock, const u8* data, int len) +{ + L2CAPSocket* l2capsock = (L2CAPSocket*)sock; + return l2capsock->btdevice->Send(sock,data,len); // Pointless double dispatch +} + +int HCI::Close(SocketInternal* sock) +{ + L2CAPSocket* l2capsock = (L2CAPSocket*)sock; + return l2capsock->btdevice->Close(sock); // Pointless double dispatch +} + +void HCI::ACLRecv(const u8* data, int len) +{ + int handle = LE16(data); + BTDevice* d = Find(handle & 0x0FFF); + if (d) + d->ACLRecv(data,len); +} + +//=================================================================== +//===================================================================
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/hci.h Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,224 @@ +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef HCI_H_INCLUDED +#define HCI_H_INCLUDED + +#include "Socket.h" + +#pragma pack(1) + +#define ERR_HCI_DEVICE_NOT_FOUND -300 + +class HCI; +class HCITransport; +class BTDevice; + +typedef struct +{ + u8 addr[6]; +} BD_ADDR; + +typedef struct +{ + BD_ADDR bdaddr; + u8 pscan_rep_mode; + u8 pscan_period_mode; + u8 pscan_mode; + u8 dev_class[3]; + u16 clock_offset; +} inquiry_info; + +typedef struct +{ + u8 status; + u16 handle; + BD_ADDR bdaddr; + u8 link_type; + u8 encr_mode; +} connection_info; + +// Address struct for creating L2CAP sockets +typedef struct { + SocketAddrHdr hdr; + BD_ADDR bdaddr; + u16 psm; +} L2CAPAddr; + +#pragma pack(4) + +class BTDevice; +typedef struct +{ + public: + SocketInternal si; + BTDevice* btdevice; + u16 scid; + u16 dcid; +} L2CAPSocket; + +#define MAX_HCL_NAME_LENGTH 20 // TODO - BTDevice wants to be a multiple of 4 + +// BTDevice encapsulates individual device state +// It provides L2CAP layer sockets + +class BTDevice : public SocketHandler +{ + public: + HCITransport* _transport; + inquiry_info _info; + u16 _handle; // acl connection handle + u8 _state; // connection state + u8 _txid; + char _name[MAX_HCL_NAME_LENGTH]; + + void Init(); + + BD_ADDR* GetAddress() { return &_info.bdaddr; } + + // Called from HCI + void ACLRecv(const u8* data, int len); + + // SocketHandler + virtual int Open(SocketInternal* sock, SocketAddrHdr* addr); + virtual int Send(SocketInternal* sock, const u8* data, int len); + virtual int Close(SocketInternal* sock); + +private: + L2CAPSocket* SCIDToSocket(int scid); + int Send(const u8* data, int len); + int Send(u8 c, u8 id, u16* params, int count); + int Connect(int scid, int psm); + int Disconnect(int scid, int dcid); + int ConfigureRequest(int dcid); + int ConfigureResponse(u8 rxid, int dcid); + int DisconnectResponse(u8 rxid, int scid, int dcid); + void Control(const u8* data, int len); +}; + +enum HCI_CALLBACK_EVENT +{ + CALLBACK_NONE, + CALLBACK_READY, + CALLBACK_INQUIRY_RESULT, + CALLBACK_INQUIRY_DONE, + CALLBACK_REMOTE_NAME, + CALLBACK_CONNECTION_COMPLETE, + CALLBACK_CONNECTION_FAILED +}; + +// L2CAP Protocol/Service Multiplexor (PSM) values + +#define L2CAP_PSM_ANY 0x0000 /* Any/Invalid PSM */ +#define L2CAP_PSM_SDP 0x0001 /* Service Discovery Protocol */ +#define L2CAP_PSM_RFCOMM 0x0003 /* RFCOMM protocol */ +#define L2CAP_PSM_TCP 0x0005 /* Telephony Control Protocol */ +#define L2CAP_PSM_TCS 0x0007 /* TCS cordless */ +#define L2CAP_PSM_BNEP 0x000f /* Bluetooth Network Encapsulation Protocol*/ +#define L2CAP_PSM_HID_CNTL 0x0011 /* HID Control */ +#define L2CAP_PSM_HID_INTR 0x0013 /* HID Interrupt */ +#define L2CAP_PSM_ESDP 0x0015 /* Extended Service Discovery Profile */ +#define L2CAP_PSM_AVCTP 0x0017 /* Audio/Visual Control Transport Protocol */ +#define L2CAP_PSM_AVDTP 0x0019 /* Audio/Visual Distribution */ + +// Callback from inquiry +typedef int (*HCICallback)(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len); + +#define MAX_BTDEVICES 8 + +class HCITransport; +class HCI : public SocketHandler +{ + HCITransport* _transport; + HCICallback _callback; + BD_ADDR _localAddr; + + BTDevice _devices[MAX_BTDEVICES]; + int _deviceCount; + + int _acl_mtu; + int _acl_max_pkt; + int _sco_mtu; + int _sco_max_pkt; + + int _state; + + public: + + // Open a local adapter + int Open(HCITransport* transport, HCICallback callback); + + // Return list of discovered addreses + int GetDevices(BTDevice** devices, int maxDevices); + + // Lookup a device by address or handle + BTDevice* Find(const BD_ADDR* addr); + BTDevice* Find(int handle); + + // Disconnect from a remote device + int Disconnect(const BD_ADDR* addr); + int DisconnectAll(); + + // see what devies are in the system + int Inquiry(int duration = 5); + + // get a name, delivered in callback + int RemoteNameRequest(const BD_ADDR* addr); + + // Connect to a remote device + int CreateConnection(const BD_ADDR* remoteAddr); + + bool Busy(); + + // called from transport + void HCIRecv(const u8* data, int len); + + // called from transport + void ACLRecv(const u8* data, int len); + + // SocketHandler methods for maintaining L2CAP sockets + virtual int Open(SocketInternal* sock, SocketAddrHdr* addr); + virtual int Send(SocketInternal* sock, const u8* data, int len); + virtual int Close(SocketInternal* sock); + + private: + void InquiryResult(const inquiry_info* info); + void RemoteName(const BD_ADDR* addr, const char* name); + void ConnectComplete(const connection_info* info); + void DisconnectComplete(int handle); + int SendCmd(int cmd, const u8* params = 0, int len = 0); + void OnCommandComplete(int cmd, const u8* data, int len); + void Callback(HCI_CALLBACK_EVENT c, const u8* data, int len); + int PinCodeReply(const u8* data); +}; + +class HCITransport +{ +protected: + HCI* _target; +public: + void Set(HCI* target) { _target = target; }; + virtual void HCISend(const u8* data, int len) = 0; + virtual void ACLSend(const u8* data, int len) = 0; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BlueUSB/hci_private.h Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,323 @@ +/* +Copyright (c) 2010 Peter Barrett + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef HCI_PRIVATE_H_INCLUDED +#define HCI_PRIVATE_H_INCLUDED + +#define HCI_OP_INQUIRY 0x0401 +#define HCI_OP_INQUIRY_CANCEL 0x0402 +#define HCI_OP_EXIT_PERIODIC_INQ 0x0404 +#define HCI_OP_CREATE_CONN 0x0405 +#define HCI_OP_DISCONNECT 0x0406 +#define HCI_OP_ADD_SCO 0x0407 +#define HCI_OP_CREATE_CONN_CANCEL 0x0408 +#define HCI_OP_ACCEPT_CONN_REQ 0x0409 +#define HCI_OP_REJECT_CONN_REQ 0x040a +#define HCI_OP_LINK_KEY_REPLY 0x040b +#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c +#define HCI_OP_PIN_CODE_REPLY 0x040d +#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e +#define HCI_OP_CHANGE_CONN_PTYPE 0x040f +#define HCI_OP_AUTH_REQUESTED 0x0411 +#define HCI_OP_SET_CONN_ENCRYPT 0x0413 +#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415 +#define HCI_OP_REMOTE_NAME_REQ 0x0419 +#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a +#define HCI_OP_READ_REMOTE_FEATURES 0x041b +#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c +#define HCI_OP_READ_REMOTE_VERSION 0x041d +#define HCI_OP_SETUP_SYNC_CONN 0x0428 +#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429 +#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a + +#define HCI_OP_SNIFF_MODE 0x0803 +#define HCI_OP_EXIT_SNIFF_MODE 0x0804 +#define HCI_OP_ROLE_DISCOVERY 0x0809 +#define HCI_OP_SWITCH_ROLE 0x080b +#define HCI_OP_READ_LINK_POLICY 0x080c +#define HCI_OP_WRITE_LINK_POLICY 0x080d +#define HCI_OP_READ_DEF_LINK_POLICY 0x080e +#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f +#define HCI_OP_SNIFF_SUBRATE 0x0811 + + +#define HCI_OP_SET_EVENT_MASK 0x0c01 +#define HCI_OP_RESET 0x0c03 +#define HCI_OP_SET_EVENT_FLT 0x0c05 +#define HCI_OP_WRITE_LOCAL_NAME 0x0c13 +#define HCI_OP_READ_LOCAL_NAME 0x0c14 +#define HCI_OP_WRITE_CA_TIMEOUT 0x0c16 +#define HCI_OP_WRITE_PG_TIMEOUT 0x0c18 +#define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a +#define HCI_OP_READ_AUTH_ENABLE 0x0c1f +#define HCI_OP_WRITE_AUTH_ENABLE 0x0c20 +#define HCI_OP_READ_ENCRYPT_MODE 0x0c21 +#define HCI_OP_WRITE_ENCRYPT_MODE 0x0c22 + #define ENCRYPT_DISABLED 0x00 + #define ENCRYPT_P2P 0x01 + #define ENCRYPT_BOTH 0x02 +#define HCI_OP_READ_CLASS_OF_DEV 0x0c23 +#define HCI_OP_WRITE_CLASS_OF_DEV 0x0c24 +#define HCI_OP_READ_VOICE_SETTING 0x0c25 +#define HCI_OP_WRITE_VOICE_SETTING 0x0c26 +#define HCI_OP_HOST_BUFFER_SIZE 0x0c33 +#define HCI_OP_READ_SSP_MODE 0x0c55 +#define HCI_OP_WRITE_SSP_MODE 0x0c56 + +#define HCI_OP_READ_LOCAL_VERSION 0x1001 +#define HCI_OP_READ_LOCAL_COMMANDS 0x1002 +#define HCI_OP_READ_LOCAL_FEATURES 0x1003 +#define HCI_OP_READ_LOCAL_EXT_FEATURES 0x1004 +#define HCI_OP_READ_BUFFER_SIZE 0x1005 +#define HCI_OP_READ_BD_ADDR 0x1009 + +// events +#define HCI_EV_INQUIRY_COMPLETE 0x01 +#define HCI_EV_INQUIRY_RESULT 0x02 +#define HCI_EV_CONN_COMPLETE 0x03 +#define HCI_EV_CONN_REQUEST 0x04 +#define HCI_EV_DISCONN_COMPLETE 0x05 +#define HCI_EV_AUTH_COMPLETE 0x06 +#define HCI_EV_REMOTE_NAME 0x07 +#define HCI_EV_ENCRYPT_CHANGE 0x08 +#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09 +#define HCI_EV_REMOTE_FEATURES 0x0b +#define HCI_EV_REMOTE_VERSION 0x0c +#define HCI_EV_QOS_SETUP_COMPLETE 0x0d +#define HCI_EV_CMD_COMPLETE 0x0e +#define HCI_EV_CMD_STATUS 0x0f +#define HCI_EV_ROLE_CHANGE 0x12 +#define HCI_EV_NUM_COMP_PKTS 0x13 +#define HCI_EV_MODE_CHANGE 0x14 +#define HCI_EV_PIN_CODE_REQ 0x16 +#define HCI_EV_LINK_KEY_REQ 0x17 +#define HCI_EV_LINK_KEY_NOTIFY 0x18 +#define HCI_EV_CLOCK_OFFSET 0x1c +#define HCI_EV_PKT_TYPE_CHANGE 0x1d +#define HCI_EV_PSCAN_REP_MODE 0x20 +#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22 +#define HCI_EV_REMOTE_EXT_FEATURES 0x23 +#define HCI_EV_SYNC_CONN_COMPLETE 0x2c +#define HCI_EV_SYNC_CONN_CHANGED 0x2d +#define HCI_EV_SNIFF_SUBRATE 0x2e +#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f +#define HCI_EV_IO_CAPA_REQUEST 0x31 +#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36 +#define HCI_EV_REMOTE_HOST_FEATURES 0x3d + +/* Possible error codes */ +#define HCI_UNKNOWN_HCI_COMMAND 0x01 +#define HCI_NO_CONNECTION 0x02 +#define HCI_HW_FAILURE 0x03 +#define HCI_PAGE_TIMEOUT 0x04 +#define HCI_AUTHENTICATION_FAILURE 0x05 +#define HCI_KEY_MISSING 0x06 +#define HCI_MEMORY_FULL 0x07 +#define HCI_CONN_TIMEOUT 0x08 +#define HCI_MAX_NUMBER_OF_CONNECTIONS 0x09 +#define HCI_MAX_NUMBER_OF_SCO_CONNECTIONS_TO_DEVICE 0x0A +#define HCI_ACL_CONNECTION_EXISTS 0x0B +#define HCI_COMMAND_DISSALLOWED 0x0C +#define HCI_HOST_REJECTED_DUE_TO_LIMITED_RESOURCES 0x0D +#define HCI_HOST_REJECTED_DUE_TO_SECURITY_REASONS 0x0E +#define HCI_HOST_REJECTED_DUE_TO_REMOTE_DEVICE_ONLY_PERSONAL_SERVICE 0x0F +#define HCI_HOST_TIMEOUT 0x10 +#define HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE 0x11 +#define HCI_INVALID_HCI_COMMAND_PARAMETERS 0x12 +#define HCI_OTHER_END_TERMINATED_CONN_USER_ENDED 0x13 +#define HCI_OTHER_END_TERMINATED_CONN_LOW_RESOURCES 0x14 +#define HCI_OTHER_END_TERMINATED_CONN_ABOUT_TO_POWER_OFF 0x15 +#define HCI_CONN_TERMINATED_BY_LOCAL_HOST 0x16 +#define HCI_REPETED_ATTEMPTS 0x17 +#define HCI_PAIRING_NOT_ALLOWED 0x18 +#define HCI_UNKNOWN_LMP_PDU 0x19 +#define HCI_UNSUPPORTED_REMOTE_FEATURE 0x1A +#define HCI_SCO_OFFSET_REJECTED 0x1B +#define HCI_SCO_INTERVAL_REJECTED 0x1C +#define HCI_SCO_AIR_MODE_REJECTED 0x1D +#define HCI_INVALID_LMP_PARAMETERS 0x1E +#define HCI_UNSPECIFIED_ERROR 0x1F +#define HCI_UNSUPPORTED_LMP_PARAMETER_VALUE 0x20 +#define HCI_ROLE_CHANGE_NOT_ALLOWED 0x21 +#define HCI_LMP_RESPONSE_TIMEOUT 0x22 +#define HCI_LMP_ERROR_TRANSACTION_COLLISION 0x23 +#define HCI_LMP_PDU_NOT_ALLOWED 0x24 +#define HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE 0x25 +#define HCI_UNIT_KEY_USED 0x26 +#define HCI_QOS_NOT_SUPPORTED 0x27 +#define HCI_INSTANT_PASSED 0x28 +#define HCI_PAIRING_UNIT_KEY_NOT_SUPPORTED 0x29 + +const char* EvtStr(int evt) +{ + switch (evt) + { + case HCI_EV_INQUIRY_COMPLETE: return "HCI_EV_INQUIRY_COMPLETE"; + case HCI_EV_INQUIRY_RESULT: return "HCI_EV_INQUIRY_RESULT"; + case HCI_EV_CONN_COMPLETE: return "HCI_EV_CONN_COMPLETE"; + case HCI_EV_CONN_REQUEST: return "HCI_EV_CONN_REQUEST"; + case HCI_EV_DISCONN_COMPLETE: return "HCI_EV_DISCONN_COMPLETE"; + case HCI_EV_AUTH_COMPLETE: return "HCI_EV_AUTH_COMPLETE"; + case HCI_EV_REMOTE_NAME: return "HCI_EV_REMOTE_NAME"; + case HCI_EV_ENCRYPT_CHANGE: return "HCI_EV_ENCRYPT_CHANGE"; + case HCI_EV_CHANGE_LINK_KEY_COMPLETE : return "HCI_EV_CHANGE_LINK_KEY_COMPLETE"; + case HCI_EV_REMOTE_FEATURES: return "HCI_EV_REMOTE_FEATURES"; + case HCI_EV_REMOTE_VERSION: return "HCI_EV_REMOTE_VERSION"; + case HCI_EV_QOS_SETUP_COMPLETE : return "HCI_EV_QOS_SETUP_COMPLETE"; + case HCI_EV_CMD_COMPLETE: return "HCI_EV_CMD_COMPLETE"; + case HCI_EV_CMD_STATUS: return "HCI_EV_CMD_STATUS"; + case HCI_EV_ROLE_CHANGE: return "HCI_EV_ROLE_CHANGE"; + case HCI_EV_NUM_COMP_PKTS: return "HCI_EV_NUM_COMP_PKTS"; + case HCI_EV_MODE_CHANGE: return "HCI_EV_MODE_CHANGE"; + case HCI_EV_PIN_CODE_REQ: return "HCI_EV_PIN_CODE_REQ"; + case HCI_EV_LINK_KEY_REQ: return "HCI_EV_LINK_KEY_REQ"; + case HCI_EV_LINK_KEY_NOTIFY: return "HCI_EV_LINK_KEY_NOTIFY"; + case HCI_EV_CLOCK_OFFSET: return "HCI_EV_CLOCK_OFFSET"; + case HCI_EV_PKT_TYPE_CHANGE: return "HCI_EV_PKT_TYPE_CHANGE"; + case HCI_EV_PSCAN_REP_MODE: return "HCI_EV_PSCAN_REP_MODE"; + case HCI_EV_INQUIRY_RESULT_WITH_RSSI : return "HCI_EV_INQUIRY_RESULT_WITH_RSSI"; + case HCI_EV_REMOTE_EXT_FEATURES: return "HCI_EV_REMOTE_EXT_FEATURES"; + case HCI_EV_SYNC_CONN_COMPLETE: return "HCI_EV_SYNC_CONN_COMPLETE"; + case HCI_EV_SYNC_CONN_CHANGED: return "HCI_EV_SYNC_CONN_CHANGED"; + case HCI_EV_SNIFF_SUBRATE: return "HCI_EV_SNIFF_SUBRATE"; + case HCI_EV_EXTENDED_INQUIRY_RESULT: return "HCI_EV_EXTENDED_INQUIRY_RESULT"; + case HCI_EV_IO_CAPA_REQUEST: return "HCI_EV_IO_CAPA_REQUEST"; + case HCI_EV_SIMPLE_PAIR_COMPLETE: return "HCI_EV_SIMPLE_PAIR_COMPLETE"; + case HCI_EV_REMOTE_HOST_FEATURES: return "HCI_EV_REMOTE_HOST_FEATURES"; + } + return "Unknown Event"; +} + +const char* CmdStr(int cmd) +{ + switch (cmd) + { + // 0x04XX + case HCI_OP_INQUIRY: return "HCI_OP_INQUIRY"; + case HCI_OP_INQUIRY_CANCEL: return "HCI_OP_INQUIRY_CANCEL"; + case HCI_OP_EXIT_PERIODIC_INQ: return "HCI_OP_EXIT_PERIODIC_INQ"; + case HCI_OP_CREATE_CONN: return "HCI_OP_CREATE_CONN"; + case HCI_OP_DISCONNECT: return "HCI_OP_DISCONNECT"; + case HCI_OP_ADD_SCO: return "HCI_OP_ADD_SCO"; + case HCI_OP_CREATE_CONN_CANCEL: return "HCI_OP_CREATE_CONN_CANCEL"; + case HCI_OP_ACCEPT_CONN_REQ: return "HCI_OP_ACCEPT_CONN_REQ"; + case HCI_OP_REJECT_CONN_REQ: return "HCI_OP_REJECT_CONN_REQ"; + case HCI_OP_LINK_KEY_REPLY: return "HCI_OP_LINK_KEY_REPLY"; + case HCI_OP_LINK_KEY_NEG_REPLY: return "HCI_OP_LINK_KEY_NEG_REPLY"; + case HCI_OP_PIN_CODE_REPLY: return "HCI_OP_PIN_CODE_REPLY"; + case HCI_OP_PIN_CODE_NEG_REPLY: return "HCI_OP_PIN_CODE_NEG_REPLY"; + case HCI_OP_CHANGE_CONN_PTYPE: return "HCI_OP_CHANGE_CONN_PTYPE"; + case HCI_OP_AUTH_REQUESTED: return "HCI_OP_AUTH_REQUESTED"; + case HCI_OP_SET_CONN_ENCRYPT: return "HCI_OP_SET_CONN_ENCRYPT"; + case HCI_OP_CHANGE_CONN_LINK_KEY: return "HCI_OP_CHANGE_CONN_LINK_KEY"; + case HCI_OP_REMOTE_NAME_REQ: return "HCI_OP_REMOTE_NAME_REQ"; + case HCI_OP_REMOTE_NAME_REQ_CANCEL: return "HCI_OP_REMOTE_NAME_REQ_CANCEL"; + case HCI_OP_READ_REMOTE_FEATURES: return "HCI_OP_READ_REMOTE_FEATURES"; + case HCI_OP_READ_REMOTE_EXT_FEATURES: return "HCI_OP_READ_REMOTE_EXT_FEATURES"; + case HCI_OP_READ_REMOTE_VERSION: return "HCI_OP_READ_REMOTE_VERSION"; + case HCI_OP_SETUP_SYNC_CONN: return "HCI_OP_SETUP_SYNC_CONN"; + case HCI_OP_ACCEPT_SYNC_CONN_REQ: return "HCI_OP_ACCEPT_SYNC_CONN_REQ"; + case HCI_OP_REJECT_SYNC_CONN_REQ: return "HCI_OP_REJECT_SYNC_CONN_REQ"; + // 0x0CXX + case HCI_OP_SET_EVENT_MASK: return "HCI_OP_SET_EVENT_MASK"; + case HCI_OP_RESET: return "HCI_OP_RESET"; + case HCI_OP_SET_EVENT_FLT: return "HCI_OP_SET_EVENT_FLT"; + case HCI_OP_WRITE_LOCAL_NAME: return "HCI_OP_WRITE_LOCAL_NAME"; + case HCI_OP_READ_LOCAL_NAME: return "HCI_OP_READ_LOCAL_NAME"; + case HCI_OP_WRITE_CA_TIMEOUT: return "HCI_OP_WRITE_CA_TIMEOUT"; + case HCI_OP_WRITE_PG_TIMEOUT: return "HCI_OP_WRITE_PG_TIMEOUT"; + case HCI_OP_WRITE_SCAN_ENABLE: return "HCI_OP_WRITE_SCAN_ENABLE"; + case HCI_OP_READ_AUTH_ENABLE: return "HCI_OP_READ_AUTH_ENABLE"; + case HCI_OP_WRITE_AUTH_ENABLE: return "HCI_OP_WRITE_AUTH_ENABLE"; + case HCI_OP_READ_ENCRYPT_MODE: return "HCI_OP_READ_ENCRYPT_MODE"; + case HCI_OP_WRITE_ENCRYPT_MODE: return "HCI_OP_WRITE_ENCRYPT_MODE"; + case HCI_OP_READ_CLASS_OF_DEV: return "HCI_OP_READ_CLASS_OF_DEV"; + case HCI_OP_WRITE_CLASS_OF_DEV: return "HCI_OP_WRITE_CLASS_OF_DEV"; + case HCI_OP_READ_VOICE_SETTING: return "HCI_OP_READ_VOICE_SETTING"; + case HCI_OP_WRITE_VOICE_SETTING: return "HCI_OP_WRITE_VOICE_SETTING"; + case HCI_OP_HOST_BUFFER_SIZE: return "HCI_OP_HOST_BUFFER_SIZE"; + case HCI_OP_READ_SSP_MODE: return "HCI_OP_READ_SSP_MODE"; + case HCI_OP_WRITE_SSP_MODE: return "HCI_OP_WRITE_SSP_MODE"; + + // 10xx + case HCI_OP_READ_LOCAL_VERSION: return "HCI_OP_READ_LOCAL_VERSION"; + case HCI_OP_READ_LOCAL_COMMANDS: return "HCI_OP_READ_LOCAL_COMMANDS"; + case HCI_OP_READ_LOCAL_FEATURES: return "HCI_OP_READ_LOCAL_FEATURES"; + case HCI_OP_READ_LOCAL_EXT_FEATURES: return "HCI_OP_READ_LOCAL_EXT_FEATURES"; + case HCI_OP_READ_BUFFER_SIZE: return "HCI_OP_READ_BUFFER_SIZE"; + case HCI_OP_READ_BD_ADDR: return "HCI_OP_READ_BD_ADDR"; + } + return "Unknown Cmd"; +} + +const char* HCIErrStr(int err) +{ + switch (err) + { + case 0: return "OK"; + case HCI_UNKNOWN_HCI_COMMAND: return "HCI_UNKNOWN_HCI_COMMAND"; + case HCI_NO_CONNECTION: return "HCI_NO_CONNECTION"; + case HCI_HW_FAILURE: return "HCI_HW_FAILURE"; + case HCI_PAGE_TIMEOUT: return "HCI_PAGE_TIMEOUT"; + case HCI_AUTHENTICATION_FAILURE: return "HCI_AUTHENTICATION_FAILURE"; + case HCI_KEY_MISSING: return "HCI_KEY_MISSING"; + case HCI_MEMORY_FULL: return "HCI_MEMORY_FULL"; + case HCI_CONN_TIMEOUT: return "HCI_CONN_TIMEOUT"; + case HCI_MAX_NUMBER_OF_CONNECTIONS: return "HCI_CONN_TIMEOUT"; + case HCI_MAX_NUMBER_OF_SCO_CONNECTIONS_TO_DEVICE: return "HCI_MAX_NUMBER_OF_SCO_CONNECTIONS_TO_DEVICE"; + case HCI_ACL_CONNECTION_EXISTS: return "HCI_ACL_CONNECTION_EXISTS"; + case HCI_COMMAND_DISSALLOWED: return "HCI_COMMAND_DISSALLOWED"; + case HCI_HOST_REJECTED_DUE_TO_LIMITED_RESOURCES: return "HCI_HOST_REJECTED_DUE_TO_LIMITED_RESOURCES"; + case HCI_HOST_REJECTED_DUE_TO_SECURITY_REASONS: return "HCI_HOST_REJECTED_DUE_TO_SECURITY_REASONS"; + case HCI_HOST_REJECTED_DUE_TO_REMOTE_DEVICE_ONLY_PERSONAL_SERVICE: return "HCI_HOST_REJECTED_DUE_TO_REMOTE_DEVICE_ONLY_PERSONAL_SERVICE"; + case HCI_HOST_TIMEOUT: return "HCI_HOST_TIMEOUT"; + case HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE: return "HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE"; + case HCI_INVALID_HCI_COMMAND_PARAMETERS: return "HCI_INVALID_HCI_COMMAND_PARAMETERS"; + case HCI_OTHER_END_TERMINATED_CONN_USER_ENDED: return "HCI_OTHER_END_TERMINATED_CONN_USER_ENDED"; + case HCI_OTHER_END_TERMINATED_CONN_LOW_RESOURCES: return "HCI_OTHER_END_TERMINATED_CONN_LOW_RESOURCES"; + case HCI_OTHER_END_TERMINATED_CONN_ABOUT_TO_POWER_OFF: return "HCI_OTHER_END_TERMINATED_CONN_ABOUT_TO_POWER_OFF"; + case HCI_CONN_TERMINATED_BY_LOCAL_HOST: return "HCI_CONN_TERMINATED_BY_LOCAL_HOST"; + case HCI_REPETED_ATTEMPTS: return "HCI_REPETED_ATTEMPTS"; + case HCI_PAIRING_NOT_ALLOWED: return "HCI_PAIRING_NOT_ALLOWED"; + case HCI_UNKNOWN_LMP_PDU: return "HCI_UNKNOWN_LMP_PDU"; + case HCI_UNSUPPORTED_REMOTE_FEATURE: return "HCI_UNSUPPORTED_REMOTE_FEATURE"; + case HCI_SCO_OFFSET_REJECTED: return "HCI_SCO_OFFSET_REJECTED"; + case HCI_SCO_INTERVAL_REJECTED: return "HCI_SCO_INTERVAL_REJECTED"; + case HCI_SCO_AIR_MODE_REJECTED: return "HCI_SCO_AIR_MODE_REJECTED"; + case HCI_INVALID_LMP_PARAMETERS: return "HCI_INVALID_LMP_PARAMETERS"; + case HCI_UNSPECIFIED_ERROR: return "HCI_UNSPECIFIED_ERROR"; + case HCI_UNSUPPORTED_LMP_PARAMETER_VALUE: return "HCI_UNSUPPORTED_LMP_PARAMETER_VALUE"; + case HCI_ROLE_CHANGE_NOT_ALLOWED: return "HCI_ROLE_CHANGE_NOT_ALLOWED"; + case HCI_LMP_RESPONSE_TIMEOUT: return "HCI_LMP_RESPONSE_TIMEOUT"; + case HCI_LMP_ERROR_TRANSACTION_COLLISION: return "HCI_LMP_ERROR_TRANSACTION_COLLISION"; + case HCI_LMP_PDU_NOT_ALLOWED: return "HCI_LMP_PDU_NOT_ALLOWED"; + case HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE: return "HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE"; + case HCI_UNIT_KEY_USED: return "HCI_UNIT_KEY_USED"; + case HCI_QOS_NOT_SUPPORTED: return "HCI_QOS_NOT_SUPPORTED"; + case HCI_INSTANT_PASSED: return "HCI_INSTANT_PASSED"; + case HCI_PAIRING_UNIT_KEY_NOT_SUPPORTED: return "HCI_PAIRING_UNIT_KEY_NOT_SUPPORTED"; + }; + return "Unknow HCI err"; +}; + + +#endif // HCI_PRIVATE_H_INCLUDED
--- a/FATFileSystem.lib Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/mbed_unsupported/code/fatfilesystem/ \ No newline at end of file
--- a/L2CAP.cpp Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,274 +0,0 @@ -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - - -#include <stdio.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "Utils.h" -#include "hci.h" - -#define L2CAP_COMMAND_REJ 0x01 -#define L2CAP_CONN_REQ 0x02 -#define L2CAP_CONN_RSP 0x03 -#define L2CAP_CONF_REQ 0x04 -#define L2CAP_CONF_RSP 0x05 -#define L2CAP_DISCONN_REQ 0x06 -#define L2CAP_DISCONN_RSP 0x07 -#define L2CAP_ECHO_REQ 0x08 -#define L2CAP_ECHO_RSP 0x09 -#define L2CAP_INFO_REQ 0x0a -#define L2CAP_INFO_RSP 0x0b - - - /* L2CAP command codes */ - const char* L2CAP_ComandCodeStr(int c) - { - switch (c) - { - case L2CAP_COMMAND_REJ: return "L2CAP_COMMAND_REJ"; - case L2CAP_CONN_REQ: return "L2CAP_CONN_REQ"; - case L2CAP_CONN_RSP: return "L2CAP_CONN_RSP"; - case L2CAP_CONF_REQ: return "L2CAP_CONF_REQ"; - case L2CAP_CONF_RSP: return "L2CAP_CONF_RSP"; - case L2CAP_DISCONN_REQ: return "L2CAP_DISCONN_REQ"; - case L2CAP_DISCONN_RSP: return "L2CAP_DISCONN_RSP"; - case L2CAP_ECHO_REQ: return "L2CAP_ECHO_REQ"; - case L2CAP_ECHO_RSP: return "L2CAP_ECHO_RSP"; - case L2CAP_INFO_REQ: return "L2CAP_INFO_REQ"; - case L2CAP_INFO_RSP: return "L2CAP_INFO_RSP"; - } - return "unknown"; - } - -typedef struct -{ - u16 handle; - u16 length; // total - u16 l2capLength; // length -4 - u16 cid; // Signaling packet CID = 1 - u8 data[64]; // Largest thing to send!!! todo -} L2CAPData; - -typedef struct -{ - u16 handle; - u16 length; // total - u16 l2capLength; // length -4 - u16 cid; // Signaling packet CID = 1 - - // Payload - u8 cmd; // - u8 id; - u16 cmdLength; // total-8 - u16 params[4]; // Params -} L2CAPCmd; - -// -void BTDevice::Init() -{ - memset(&_info,0,sizeof(inquiry_info)); - _handle = 0; - _name[0] = 0; - _state = 0; -} - -// virtual SocketHandler -int BTDevice::Open(SocketInternal* sock, SocketAddrHdr* addr) -{ - L2CAPSocket* s = (L2CAPSocket*)sock; - L2CAPAddr* a = (L2CAPAddr*)addr; - s->scid = 0x40 + sock->ID-1; // are these reserved? - s->dcid = 0; - Connect(s->scid,a->psm); - return sock->ID; -} - -// virtual SocketHandler -int BTDevice::Send(SocketInternal* sock, const u8* data, int len) -{ - L2CAPData d; - L2CAPSocket* s = (L2CAPSocket*)sock; - - d.handle = _handle | 0x2000; - d.length = 4 + len; - d.l2capLength = len; - d.cid = s->dcid; - - if (len > 64) - return -1; - memcpy(d.data,data,len); - return Send((u8*)&d,len+8); -} - -// virtual SocketHandler -int BTDevice::Close(SocketInternal* sock) -{ - printf("L2CAP close %d\n",sock->ID); - L2CAPSocket* s = (L2CAPSocket*)sock; - return Disconnect(s->scid,s->dcid); -} - -L2CAPSocket* BTDevice::SCIDToSocket(int scid) -{ - return (L2CAPSocket*)GetSocketInternal(scid-0x40+1); -} - -int BTDevice::Send(const u8* data, int len) -{ - _transport->ACLSend(data,len); - return 0; -} - -int BTDevice::Send(u8 c, u8 id, u16* params, int count) -{ - L2CAPCmd cmd; - cmd.handle = _handle | 0x2000; - cmd.length = 8 + count*2; - - cmd.l2capLength = cmd.length-4; - cmd.cid = 1; // Signaling packet - - cmd.cmd = c; - cmd.id = id; - cmd.cmdLength = count*2; - for (int i = 0; i < count; i++) - cmd.params[i] = params[i]; - return Send((u8*)&cmd,cmd.length+4); -} - -int BTDevice::Connect(int scid, int psm) -{ - u16 p[2]; - p[0] = psm; - p[1] = scid; - return Send(L2CAP_CONN_REQ,_txid++,p,2); -} - -int BTDevice::Disconnect(int scid, int dcid) -{ - u16 p[2]; - p[0] = dcid; - p[1] = scid; - return Send(L2CAP_DISCONN_REQ,_txid++,p,2); -} - -int BTDevice::ConfigureRequest(int dcid) -{ - u16 p[4]; - p[0] = dcid; - p[1] = 0; - p[2] = 0x0201; // Options - p[3] = 0x02A0; // 672 - return Send(L2CAP_CONF_REQ,_txid++,p,4); -} - -int BTDevice::ConfigureResponse(u8 rxid, int dcid) -{ - u16 p[3]; - p[0] = dcid; - p[1] = 0; - p[2] = 0; - return Send(L2CAP_CONF_RSP,rxid,p,3); -} - -int BTDevice::DisconnectResponse(u8 rxid, int scid, int dcid) -{ - u16 p[2]; - p[0] = dcid; - p[1] = scid; - return Send(L2CAP_DISCONN_RSP,rxid,p,2); -} - -void BTDevice::Control(const u8* data, int len) -{ - int cc = data[8]; - printf(L2CAP_ComandCodeStr(cc)); - int result = LE16(data+16); - printf(" Result %d\n",result); - switch (cc) - { - case L2CAP_COMMAND_REJ: - break; - case L2CAP_CONN_REQ: - break; - - // Response to our initial connect from Remote - case L2CAP_CONN_RSP: - { - if (result == 0) - { - int dcid = LE16(data+12); - int scid = LE16(data+14); - L2CAPSocket* s = SCIDToSocket(scid); - if (s) - { - s->dcid = dcid; - ConfigureRequest(dcid); - } - } else - printf("Connect failed?\n"); - } - break; - - case L2CAP_CONF_RSP: - { - int scid = LE16(data+12); - SocketInternal* s = (SocketInternal*)SCIDToSocket(scid); - if (s) - s->SetState(SocketState_Open); - } - break; - - case L2CAP_CONF_REQ: - { - int scid = LE16(data+12); - L2CAPSocket* s = SCIDToSocket(scid); - if (s) - ConfigureResponse(data[9],s->dcid); - } - break; - } -} - -void BTDevice::ACLRecv(const u8* data, int len) -{ - // printfBytes("L2CP",data,16); - int handle = LE16(data); - if (handle != (0x2000 | _handle)) - return; - - int cid = LE16(data+6); - if (cid == 1) - { - Control(data,len); - return; - } - - SocketInternal* s = (SocketInternal*)SCIDToSocket(cid); - if (s) - s->Recv(data+8,LE16(data+2)-4); - else - printf("Bad event cid %d\n",cid); -}
--- a/MassStorage.cpp Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ - -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include "stdlib.h" -#include "stdio.h" -#include "string.h" - -#include "Utils.h" -#include "USBHost.h" - - -int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize); -int MassStorage_ReadBlock(int device, u32 block, u8* dst); -int MassStorage_WriteBlock(int device, u32 block, const u8* dst); - - -#define ERR_BAD_CSW_SIGNATURE -200 - -#define CBW_SIGNATURE 0x43425355 -#define CSW_SIGNATURE 0x53425355 - -// Command Block -typedef struct -{ - u32 Signature; - u32 Tag; - u32 TransferLength; - u8 Flags; - u8 LUN; - u8 CBLength; - u8 CB[16]; // only 6 really -} CBW; - -// Status block -typedef struct -{ - u32 Signature; - u32 Tag; - u32 DataResidue; - u8 Status; -} CSW; - -int SCSIRequestSense(int device); - -int DoSCSI(int device, const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen) -{ - CBW cbw; - cbw.Signature = CBW_SIGNATURE; - cbw.Tag = 0; - cbw.TransferLength = transferLen; - cbw.Flags = flags; - cbw.LUN = 0; - cbw.CBLength = cmdLen; - memset(cbw.CB,0,sizeof(cbw.CB)); - memcpy(cbw.CB,cmd,cmdLen); - - int r; - r = USBBulkTransfer(device,0x01,(u8*)&cbw,31); // Send the command - if (r < 0) - return r; - - if (data) - { - r = USBBulkTransfer(device,flags | 1,data,transferLen); - if (r < 0) - return r; - } - - CSW csw; - csw.Signature = 0; - r = USBBulkTransfer(device,0x81,(u8*)&csw,13); - if (r < 0) - return r; - - if (csw.Signature != CSW_SIGNATURE) - return ERR_BAD_CSW_SIGNATURE; - - // ModeSense? - if (csw.Status == 1 && cmd[0] != 3) - return SCSIRequestSense(device); - - return csw.Status; -} - -int SCSITestUnitReady(int device) -{ - u8 cmd[6]; - memset(cmd,0,6); - return DoSCSI(device,cmd,6,DEVICE_TO_HOST,0,0); -} - -int SCSIRequestSense(int device) -{ - u8 cmd[6] = {0x03,0,0,0,18,0}; - u8 result[18]; - int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,18); - return r; -} - -int SCSIInquiry(int device) -{ - u8 cmd[6] = {0x12,0,0,0,36,0}; - u8 result[36+2]; - result[36] = '\n'; - result[37] = 0; - int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,36); - if (r == 0) - printf((const char*)result + 8); - return r; -} - -int SCSIReadCapacity(int device, u32* blockCount, u32* blockSize) -{ - u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0}; - u8 result[8]; - *blockSize = 0; - *blockCount = 0; - int r = DoSCSI(device,cmd,10,DEVICE_TO_HOST,result,8); - if (r == 0) - { - *blockCount = BE32(result); - *blockSize = BE32(result+4); - } - return r; -} - -int SCSITransfer(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction) -{ - // USB hardware will only do 4k per transfer - while (blockCount*blockSize > 4096) - { - int count = 4096/blockSize; - int r = SCSITransfer(device,blockAddr,count,dst,blockSize,direction); - dst += count*blockSize; - blockAddr += count; - blockCount -= count; - } - - u8 cmd[10]; - memset(cmd,0,10); - cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A; - BE32(blockAddr,cmd+2); - BE16(blockCount,cmd+7); - return DoSCSI(device,cmd,10,direction,dst,blockSize*blockCount); -} - -int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize) -{ - return SCSIReadCapacity(device,blockCount,blockSize); -} - -int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512) -{ - return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,DEVICE_TO_HOST); -} - -int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512) -{ - return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,HOST_TO_DEVICE); -}
--- a/Socket.cpp Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "Utils.h" -#include "Socket.h" - -#define MAX_SOCKET_HANDLERS 3 -#define MAX_SOCKETS 16 - -class SocketInternalPad -{ - public: - SocketInternal si; - u8 pad[8]; -}; - -class SocketManager -{ - SocketHandler* _handlers[MAX_SOCKET_HANDLERS]; - SocketInternalPad _sockets[MAX_SOCKETS]; - - public: - SocketManager() - { - memset(_handlers,0,sizeof(_handlers)); - memset(_sockets,0,sizeof(_sockets)); - } - - SocketHandler* GetHandler(int type) - { - if (type < 1 || type > MAX_SOCKET_HANDLERS) - return 0; - return _handlers[type - 1]; - } - - SocketInternal* GetInternal(int s) - { - if (s < 1 || s > MAX_SOCKETS) - return 0; - return &_sockets[s - 1].si; - } - - int RegisterSocketHandler(int type, SocketHandler* handler) - { - if (type < 1 || type > MAX_SOCKET_HANDLERS) - return ERR_SOCKET_TYPE_NOT_FOUND; - _handlers[type - 1] = handler; - return 0; - } - - int Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData) - { - SocketHandler* h = GetHandler(type); - if (!h) - return ERR_SOCKET_TYPE_NOT_FOUND; - - for (int i = 0; i < MAX_SOCKETS; i++) - { - SocketInternal* si = (SocketInternal*)(_sockets+i); - if (si->ID == 0) - { - si->ID = i+1; - si->Type = type; - si->Callback = callback; - si->userData = userData; - return h->Open(si,addr); - } - } - return ERR_SOCKET_NONE_LEFT; - } - - int Send(int socket, const u8* data, int len) - { - SocketInternal* si = GetInternal(socket); - if (!si || si->ID != socket) - return ERR_SOCKET_NOT_FOUND; - return GetHandler(si->Type)->Send(si,data,len); - } - - int Close(int socket) - { - SocketInternal* si = GetInternal(socket); - if (!si || si->ID != socket) - return ERR_SOCKET_NOT_FOUND; - si->ID = 0; - return GetHandler(si->Type)->Close(si); - } -}; - -SocketManager gSocketManager; - -int Socket_Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData) -{ - return gSocketManager.Open(type,addr,callback,userData); -} - -int Socket_Send(int socket, const u8* data, int len) -{ - return gSocketManager.Send(socket,data,len); -} - -int Socket_Close(int socket) -{ - return gSocketManager.Close(socket); -} - -int RegisterSocketHandler(int type, SocketHandler* handler) -{ - return gSocketManager.RegisterSocketHandler(type,handler); -} - -SocketInternal* GetSocketInternal(int socket) -{ - return gSocketManager.GetInternal(socket); -} -
--- a/Socket.h Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef SOCKET_H_INCLUDED -#define SOCKET_H_INCLUDED - -#define SOCKET_HCI 1 -#define SOCKET_L2CAP 2 -#define SOCKET_RFCOM 3 - -typedef struct -{ - u8 AddressSpecific[0]; // BDADDR,psm etc -} SocketAddrHdr; - -enum SocketState -{ - SocketState_Unknown, - SocketState_Opening, - SocketState_Open, - SocketState_Closing, - SocketState_Closed -}; - -typedef void (*SocketCallback)(int socket, SocketState state, const u8* data, int len, void* userData); - -int Socket_Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData); // Open a socket -int Socket_Send(int socket, const u8* data, int len); -int Socket_State(int socket); -int Socket_Close(int socket); - -//=========================================================================== -//=========================================================================== -// Don't need to look at or use anything below this line: -// Internal representation of socket - -class SocketHandler; -class SocketInternal -{ - public: - - u8 ID; - u8 State; - u8 Type; - u8 B0; - SocketCallback Callback; - void* userData; - u8 Data[0]; // Extra socket data starts here - - void Recv(const u8* data, int len) - { - Callback(ID,(SocketState)State,data,len,userData); - } - - void SetState(SocketState state) - { - State = state; - Callback(ID,(SocketState)State,0,0,userData); - } -}; - -class SocketHandler -{ - public: - virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) = 0; - virtual int Send(SocketInternal* sock, const u8* data, int len) = 0; - virtual int Close(SocketInternal* sock) = 0; -}; - -int RegisterSocketHandler(int type, SocketHandler* handler); -SocketInternal* GetSocketInternal(int socket); - -#define ERR_SOCKET_TYPE_NOT_FOUND -200 -#define ERR_SOCKET_NOT_FOUND -201 -#define ERR_SOCKET_NONE_LEFT -202 - -#endif // SOCKET_H_INCLUDED
--- a/TestShell.cpp Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,396 +0,0 @@ - -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "Utils.h" -#include "USBHost.h" -#include "hci.h" - -void printf(const BD_ADDR* addr) -{ - const u8* a = addr->addr; - printf("%02X:%02X:%02X:%02X:%02X:%02X",a[5],a[4],a[3],a[2],a[1],a[0]); -} - -#define MAX_HCL_SIZE 260 -#define MAX_ACL_SIZE 400 - -class HCITransportUSB : public HCITransport -{ - int _device; - u8* _hciBuffer; - u8* _aclBuffer; - - public: - void Open(int device, u8* hciBuffer, u8* aclBuffer) - { - _device = device; - _hciBuffer = hciBuffer; - _aclBuffer = aclBuffer; - USBInterruptTransfer(_device,0x81,_hciBuffer,MAX_HCL_SIZE,HciCallback,this); - USBBulkTransfer(_device,0x82,_aclBuffer,MAX_ACL_SIZE,AclCallback,this); - } - - static void HciCallback(int device, int endpoint, int status, u8* data, int len, void* userData) - { - HCI* t = ((HCITransportUSB*)userData)->_target; - if (t) - t->HCIRecv(data,len); - USBInterruptTransfer(device,0x81,data,MAX_HCL_SIZE,HciCallback,userData); - } - - static void AclCallback(int device, int endpoint, int status, u8* data, int len, void* userData) - { - HCI* t = ((HCITransportUSB*)userData)->_target; - if (t) - t->ACLRecv(data,len); - USBBulkTransfer(device,0x82,data,MAX_ACL_SIZE,AclCallback,userData); - } - - virtual void HCISend(const u8* data, int len) - { - USBControlTransfer(_device,REQUEST_TYPE_CLASS, 0, 0, 0,(u8*)data,len); - } - - virtual void ACLSend(const u8* data, int len) - { - USBBulkTransfer(_device,0x02,(u8*)data,len); - } -}; - - -#define WII_REMOTE 0x042500 - -class HIDBluetooth -{ - int _control; // Sockets for control (out) and interrupt (in) - int _interrupt; - int _devClass; - BD_ADDR _addr; - u8 _pad[2]; // Struct align - -public: - HIDBluetooth() : _control(0),_interrupt(0),_devClass(0) {}; - - bool InUse() - { - return _control != 0; - } - - static void OnHidInterrupt(int socket, SocketState state, const u8* data, int len, void* userData) - { - HIDBluetooth* t = (HIDBluetooth*)userData; - if (data) - { - if (t->_devClass == WII_REMOTE && data[1] == 0x30) - { - printf("================wii====================\n"); - t->Led(); - t->Hid(); // ask for accelerometer - t->_devClass = 0; - } - - const u8* d = data; - switch (d[1]) - { - case 0x02: - { - int x = (signed char)d[3]; - int y = (signed char)d[4]; - printf("Mouse %2X dx:%d dy:%d\n",d[2],x,y); - } - break; - - case 0x37: // Accelerometer http://wiki.wiimoteproject.com/Reports - { - int pad = (d[2] & 0x9F) | ((d[3] & 0x9F) << 8); - int x = (d[2] & 0x60) >> 5 | d[4] << 2; - int y = (d[3] & 0x20) >> 4 | d[5] << 2; - int z = (d[3] & 0x40) >> 5 | d[6] << 2; - printf("WII %04X %d %d %d\n",pad,x,y,z); - } - break; - default: - printHex(data,len); - } - } - } - - static void OnHidControl(int socket, SocketState state, const u8* data, int len, void* userData) - { - printf("OnHidControl\n"); - if (data) - printHex(data,len); - } - - void Open(BD_ADDR* bdAddr, inquiry_info* info) - { - printf("L2CAPAddr size %d\n",sizeof(L2CAPAddr)); - _addr = *bdAddr; - L2CAPAddr sockAddr; - sockAddr.bdaddr = _addr; - sockAddr.psm = L2CAP_PSM_HID_INTR; - printf("Socket_Open size %d\n",sizeof(L2CAPAddr)); - _interrupt = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidInterrupt,this); - sockAddr.psm = L2CAP_PSM_HID_CNTL; - _control = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidControl,this); - - printfBytes("OPEN DEVICE CLASS",info->dev_class,3); - _devClass = (info->dev_class[0] << 16) | (info->dev_class[1] << 8) | info->dev_class[2]; - } - - void Close() - { - if (_control) - Socket_Close(_control); - if (_interrupt) - Socket_Close(_interrupt); - _control = _interrupt = 0; - } - - void Led(int id = 0x10) - { - u8 led[3] = {0x52, 0x11, id}; - if (_control) - Socket_Send(_control,led,3); - } - - void Hid(int report = 0x37) - { - u8 hid[4] = { 0x52, 0x12, 0x00, report }; - if (_control != -1) - Socket_Send(_control,hid,4); - } -}; - - -HCI* gHCI = 0; - -#define MAX_HID_DEVICES 8 - -int GetConsoleChar(); -class ShellApp -{ - char _line[64]; - HIDBluetooth _hids[MAX_HID_DEVICES]; - -public: - void Ready() - { - printf("HIDBluetooth %d\n",sizeof(HIDBluetooth)); - memset(_hids,0,sizeof(_hids)); - Inquiry(); - - } - - // We have connected to a device - void ConnectionComplete(HCI* hci, connection_info* info) - { - printf("ConnectionComplete "); - BD_ADDR* a = &info->bdaddr; - printf(a); - BTDevice* bt = hci->Find(a); - HIDBluetooth* hid = NewHIDBluetooth(); - printf("%08x %08x\n",bt,hid); - if (hid) - hid->Open(a,&bt->_info); - } - - HIDBluetooth* NewHIDBluetooth() - { - for (int i = 0; i < MAX_HID_DEVICES; i++) - if (!_hids[i].InUse()) - return _hids+i; - return 0; - } - - void ConnectDevices() - { - BTDevice* devs[8]; - int count = gHCI->GetDevices(devs,8); - for (int i = 0; i < count; i++) - { - printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3); - if (devs[i]->_handle == 0) - { - BD_ADDR* bd = &devs[i]->_info.bdaddr; - printf("Connecting to "); - printf(bd); - printf("\n"); - gHCI->CreateConnection(bd); - } - } - } - - const char* ReadLine() - { - int i; - for (i = 0; i < 255; ) - { - USBLoop(); - int c = GetConsoleChar(); - if (c == -1) - continue; - if (c == '\n' || c == 13) - break; - _line[i++] = c; - } - _line[i] = 0; - return _line; - } - - void Inquiry() - { - printf("Inquiry..\n"); - gHCI->Inquiry(); - } - - void List() - { - #if 0 - printf("%d devices\n",_deviceCount); - for (int i = 0; i < _deviceCount; i++) - { - printf(&_devices[i].info.bdaddr); - printf("\n"); - } - #endif - } - - void Connect() - { - ConnectDevices(); - } - - void Disconnect() - { - gHCI->DisconnectAll(); - } - - void CloseMouse() - { - } - - void Quit() - { - CloseMouse(); - } - - void Run() - { - for(;;) - { - const char* cmd = ReadLine(); - if (strcmp(cmd,"scan") == 0 || strcmp(cmd,"inquiry") == 0) - Inquiry(); - else if (strcmp(cmd,"ls") == 0) - List(); - else if (strcmp(cmd,"connect") == 0) - Connect(); - else if (strcmp(cmd,"disconnect") == 0) - Disconnect(); - else if (strcmp(cmd,"q")== 0) - { - Quit(); - break; - } else { - printf("eh? %s\n",cmd); - } - } - } -}; - -// Instance -ShellApp gApp; - -static int HciCallback(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len) -{ - switch (evt) - { - case CALLBACK_READY: - printf("CALLBACK_READY\n"); - gApp.Ready(); - break; - - case CALLBACK_INQUIRY_RESULT: - printf("CALLBACK_INQUIRY_RESULT "); - printf((BD_ADDR*)data); - printf("\n"); - break; - - case CALLBACK_INQUIRY_DONE: - printf("CALLBACK_INQUIRY_DONE\n"); - gApp.ConnectDevices(); - break; - - case CALLBACK_REMOTE_NAME: - { - BD_ADDR* addr = (BD_ADDR*)data; - const char* name = (const char*)(data + 6); - printf(addr); - printf(" % s\n",name); - } - break; - - case CALLBACK_CONNECTION_COMPLETE: - gApp.ConnectionComplete(hci,(connection_info*)data); - break; - }; - return 0; -} - -// these should be placed in the DMA SRAM -typedef struct -{ - u8 _hciBuffer[MAX_HCL_SIZE]; - u8 _aclBuffer[MAX_ACL_SIZE]; -} SRAMPlacement; - -HCITransportUSB _HCITransportUSB; -HCI _HCI; - -u8* USBGetBuffer(u32* len); -int OnBluetoothInsert(int device) -{ - printf("Bluetooth inserted of %d\n",device); - u32 sramLen; - u8* sram = USBGetBuffer(&sramLen); - sram = (u8*)(((u32)sram + 1023) & ~1023); - SRAMPlacement* s = (SRAMPlacement*)sram; - _HCITransportUSB.Open(device,s->_hciBuffer,s->_aclBuffer); - _HCI.Open(&_HCITransportUSB,HciCallback); - RegisterSocketHandler(SOCKET_L2CAP,&_HCI); - gHCI = &_HCI; - gApp.Inquiry(); - return 0; -} - -void TestShell() -{ - USBInit(); - gApp.Run(); -}
--- a/USBHost.cpp Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1072 +0,0 @@ - -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include "mbed.h" -#include "USBHost.h" - -// Config (default uses x bytes) -#define MAX_DEVICES 8 // Max number of devices -#define MAX_ENDPOINTS_TOTAL 16 // Max number of endpoints total -#define MAX_ENDPOINTS_PER_DEVICE 8 // Max number of endpoints for any one device - -#define USBLOG 1 -#if USBLOG -#define LOG(...) printf(__VA_ARGS__) -#else -#define LOG(...) do {} while(0) -#endif - -// USB host structures - -#define USB_RAM_SIZE 16*1024 // AHB SRAM block 1 TODO MACHINE DEPENDENT -#define USB_RAM_BASE 0x2007C000 - -#define TOKEN_SETUP 0 -#define TOKEN_IN 1 -#define TOKEN_OUT 2 - -// Status flags from hub -#define PORT_CONNECTION 0 -#define PORT_ENABLE 1 -#define PORT_SUSPEND 2 -#define PORT_OVER_CURRENT 3 -#define PORT_RESET 4 -#define PORT_POWER 8 -#define PORT_LOW_SPEED 9 - -#define C_PORT_CONNECTION 16 -#define C_PORT_ENABLE 17 -#define C_PORT_SUSPEND 18 -#define C_PORT_OVER_CURRENT 19 -#define C_PORT_RESET 20 - -typedef struct { - u8 bm_request_type; - u8 b_request; - u16 w_value; - u16 w_index; - u16 w_length; -} Setup; - - -// Hub stuff is kept private just to keep api simple -int SetPortFeature(int device, int feature, int index); -int ClearPortFeature(int device, int feature, int index); -int SetPortPower(int device, int port); -int SetPortReset(int device, int port); -int GetPortStatus(int device, int port, u32* status); - -//=================================================================== -//=================================================================== -// Hardware defines - -// HcControl -#define PeriodicListEnable 0x00000004 -#define IsochronousEnable 0x00000008 -#define ControlListEnable 0x00000010 -#define BulkListEnable 0x00000020 -#define OperationalMask 0x00000080 -#define HostControllerFunctionalState 0x000000C0 - -// HcCommandStatus -#define HostControllerReset 0x00000001 -#define ControlListFilled 0x00000002 -#define BulkListFilled 0x00000004 - -// HcInterruptStatus Register -#define WritebackDoneHead 0x00000002 -#define StartofFrame 0x00000004 -#define ResumeDetected 0x00000008 -#define UnrecoverableError 0x00000010 -#define FrameNumberOverflow 0x00000020 -#define RootHubStatusChange 0x00000040 -#define OwnershipChange 0x00000080 -#define MasterInterruptEnable 0x80000000 - -// HcRhStatus -#define SetGlobalPower 0x00010000 -#define DeviceRemoteWakeupEnable 0x00008000 - -// HcRhPortStatus (hub 0, port 1) -#define CurrentConnectStatus 0x00000001 -#define PortEnableStatus 0x00000002 -#define PortSuspendStatus 0x00000004 -#define PortOverCurrentIndicator 0x00000008 -#define PortResetStatus 0x00000010 - -#define PortPowerStatus 0x00000100 -#define LowspeedDevice 0x00000200 -#define HighspeedDevice 0x00000400 - -#define ConnectStatusChange (CurrentConnectStatus << 16) -#define PortResetStatusChange (PortResetStatus << 16) - - -#define TD_ROUNDING (u32)0x00040000 -#define TD_SETUP (u32)0x00000000 -#define TD_IN (u32)0x00100000 -#define TD_OUT (u32)0x00080000 -#define TD_DELAY_INT(x) (u32)((x) << 21) -#define TD_TOGGLE_0 (u32)0x02000000 -#define TD_TOGGLE_1 (u32)0x03000000 -#define TD_CC (u32)0xF0000000 - -// HostController EndPoint Descriptor -typedef struct { - volatile u32 Control; - volatile u32 TailTd; - volatile u32 HeadTd; - volatile u32 Next; -} HCED; - -// HostController Transfer Descriptor -typedef struct { - volatile u32 Control; - volatile u32 CurrBufPtr; - volatile u32 Next; - volatile u32 BufEnd; -} HCTD; - -// Host Controller Communication Area -typedef struct { - volatile u32 InterruptTable[32]; - volatile u16 FrameNumber; - volatile u16 FrameNumberPad; - volatile u32 DoneHead; - volatile u8 Reserved[120]; -} HCCA; - -//==================================================================================== -//==================================================================================== - -class HostController; -class Endpoint; -class Device; - -// must be 3*16 bytes long -class Endpoint -{ -public: - HCED EndpointDescriptor; // Pointer to EndpointDescriptor == Pointer to Endpoint - HCTD TDHead; - - enum State - { - Free, - NotQueued, - Idle, - SetupQueued, - DataQueued, - StatusQueued, - CallbackPending - }; - - volatile u8 CurrentState; - u8 Flags; // 0x80 In, 0x03 mask endpoint type - - u16 Length; - u8* Data; - USBCallback Callback; // Must be a multiple of 16 bytes long - void* UserData; - - int Address() - { - int ep = (EndpointDescriptor.Control >> 7) & 0xF; - if (ep) - ep |= Flags & 0x80; - return ep; - } - - int Device() - { - return EndpointDescriptor.Control & 0x7F; - } - - int Status() - { - return (TDHead.Control >> 28) & 0xF; - } - - u32 Enqueue(u32 head) - { - if (CurrentState == NotQueued) - { - EndpointDescriptor.Next = head; - head = (u32)&EndpointDescriptor; - CurrentState = Idle; - } - return head; - } -}; - -class Device -{ -public: - u8 _endpointMap[MAX_ENDPOINTS_PER_DEVICE*2]; - u8 Hub; - u8 Port; - u8 Addr; - u8 Pad; - - // Only if this device is a hub - u8 HubPortCount; // nonzero if this is a hub - u8 HubInterruptData; - u8 HubMap; - u8 HubMask; - - int Flags; // 1 = Disconnected - - Setup SetupBuffer; - - // Allocate endpoint zero - int Init(DeviceDescriptor* d, int hub, int port, int addr, int lowSpeed) - { - Hub = hub; - Port = port; - Addr = addr; - Flags = lowSpeed; - memset(_endpointMap,0xFF,sizeof(_endpointMap)); - return 0; - } - - int SetEndpointIndex(int ep, int endpointIndex) - { - for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2) - { - if (_endpointMap[i] == 0xFF) // Add endpoint to map - { - _endpointMap[i] = ep; - _endpointMap[i+1] = endpointIndex; - return 0; - } - } - return ERR_ENDPOINT_NONE_LEFT; - } - - int GetEndpointIndex(int ep) - { - for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2) - { - if (_endpointMap[i] == ep) - return _endpointMap[i+1]; - if (_endpointMap[i] == 0xFF) - break; - } - return -1; - } -}; - -class HostController -{ -public: - HCCA CommunicationArea; - Endpoint Endpoints[MAX_ENDPOINTS_TOTAL]; // Multiple of 16 - - Endpoint EndpointZero; // For device enumeration - HCTD _commonTail; - Setup _setupZero; - - Device Devices[MAX_DEVICES]; - u32 _frameNumber; // 32 bit ms counter - - u8 _callbacksPending; // Endpoints with callbacks are pending, set from ISR via ProcessDoneQueue - u8 _rootHubStatusChange; // Root hub status has changed, set from ISR - u8 _unused0; - u8 _unused1; - - u8 _connectPending; // Reset has initiated a connect - u8 _connectCountdown; // Number of ms left after reset before we can connect - u8 _connectHub; // Will connect on this hub - u8 _connectPort; // ... and this port - - u8 SRAM[0]; // Start of free SRAM - - void Loop() - { - u16 elapsed = CommunicationArea.FrameNumber - (u16)_frameNumber; // extend to 32 bits - _frameNumber += elapsed; - - // Do callbacks, if any - while (_callbacksPending) - { - for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++) - { - Endpoint* endpoint = Endpoints + i; - if (endpoint->CurrentState == Endpoint::CallbackPending) - { - _callbacksPending--; - endpoint->CurrentState = Endpoint::Idle; - endpoint->Callback(endpoint->Device(),endpoint->Address(),endpoint->Status(),endpoint->Data,endpoint->Length,endpoint->UserData); - } - } - } - - // Deal with changes on the root hub - if (_rootHubStatusChange) - { - u32 status = LPC_USB->HcRhPortStatus1; - _rootHubStatusChange = 0; - if (status >> 16) - { - HubStatusChange(0,1,status); - LPC_USB->HcRhPortStatus1 = status & 0xFFFF0000; // clear status changes - } - } - - // Connect after reset timeout - if (_connectCountdown) - { - if (elapsed >= _connectCountdown) - { - _connectCountdown = 0; - Connect(_connectHub,_connectPort & 0x7F,_connectPort & 0x80); - } else - _connectCountdown -= elapsed; - } - } - - // HubInterrupt - bitmap in dev->HubInterruptData - void HubInterrupt(int device) - { - Device* dev = &Devices[device-1]; - for (int i = 0; i < dev->HubPortCount; i++) - { - int port = i+1; - if (dev->HubInterruptData & (1 << port)) - { - u32 status = 0; - GetPortStatus(device,port,&status); - if (status >> 16) - { - if (_connectPending && (status & ConnectStatusChange)) - continue; // Don't connect again until previous device has been added and addressed - - HubStatusChange(device,port,status); - if (status & ConnectStatusChange) - ClearPortFeature(device,C_PORT_CONNECTION,port); - if (status & PortResetStatusChange) - ClearPortFeature(device,C_PORT_RESET,port); - } - } - } - } - - static void HubInterruptCallback(int device, int endpoint, int status, u8* data, int len, void* userData) - { - HostController* controller = (HostController*)userData; - if (status == 0) - controller->HubInterrupt(device); - USBInterruptTransfer(device,endpoint,data,1,HubInterruptCallback,userData); - } - - int InitHub(int device) - { - u8 buf[16]; - int r= USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_DEVICE,GET_DESCRIPTOR,(DESCRIPTOR_TYPE_HUB << 8),0,buf,sizeof(buf)); - if (r < 0) - return ERR_HUB_INIT_FAILED; - - // turn on power on the hubs ports - Device* dev = &Devices[device-1]; - int ports = buf[2]; - dev->HubPortCount = ports; - for (int i = 0; i < ports; i++) - SetPortPower(device,i+1); - - // Enable hub change interrupts - return USBInterruptTransfer(device,0x81,&dev->HubInterruptData,1,HubInterruptCallback,this); - } - - int AddEndpoint(int device, int ep, int attributes, int maxPacketSize, int interval) - { - LOG("AddEndpoint D:%02X A:%02X T:%02X P:%04X I:%02X\n",device,ep,attributes,maxPacketSize,interval); - Device* dev = &Devices[device-1]; - Endpoint* endpoint = AllocateEndpoint(device,ep,attributes,maxPacketSize); - if (!endpoint) - return ERR_ENDPOINT_NONE_LEFT; - dev->SetEndpointIndex(ep,endpoint - Endpoints); - endpoint->EndpointDescriptor.Control |= dev->Flags; // Map in slow speed - return 0; // TODO ed->bInterval - } - - int AddEndpoint(int device, EndpointDescriptor* ed) - { - return AddEndpoint(device,ed->bEndpointAddress,ed->bmAttributes,ed->wMaxPacketSize,ed->bInterval); - } - - // allocate a endpoint - Endpoint* AllocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize) - { - for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++) - { - Endpoint* ep = &Endpoints[i]; - if (ep->CurrentState == 0) - { - //LOG("Allocated endpoint %d to %02X:%02X\n",i,device,endpointAddress); - ep->Flags = (endpointAddress & 0x80) | (type & 3); - ep->CurrentState = Endpoint::NotQueued; - ep->EndpointDescriptor.Control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device; - return ep; - } - } - return 0; - } - - Endpoint* GetEndpoint(int device, int ep) - { - if (device == 0) - { - //printf("WARNING: USING DEVICE 0\n"); - return &EndpointZero; - } - if (device > MAX_DEVICES) - return 0; - int i = Devices[device-1].GetEndpointIndex(ep); - if (i == -1) - return 0; - return Endpoints + i; - } - - int Transfer(Endpoint* endpoint, int token, u8* data, int len, int state) - { - //LOG("Transfer %02X T:%d Len:%d S:%d\n",endpoint->Address(),token,len,state); - - int toggle = 0; - if (endpoint->Address() == 0) - toggle = (token == TOKEN_SETUP) ? TD_TOGGLE_0 : TD_TOGGLE_1; - - if (token != TOKEN_SETUP) - token = (token == TOKEN_IN ? TD_IN : TD_OUT); - - HCTD* head = &endpoint->TDHead; - HCTD* tail = &_commonTail; - - head->Control = TD_ROUNDING | token | TD_DELAY_INT(0) | toggle | TD_CC; - head->CurrBufPtr = (u32)data; - head->BufEnd = (u32)(data + len - 1); - head->Next = (u32)tail; - - HCED* ed = &endpoint->EndpointDescriptor; - ed->HeadTd = (u32)head | (ed->HeadTd & 0x00000002); // carry toggle - ed->TailTd = (u32)tail; - - //HCTD* td = head; - //LOG("%04X TD %08X %08X %08X Next:%08X\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next); - //LOG("%04X ED %08X %08X %08X\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd); - - switch (endpoint->Flags & 3) - { - case ENDPOINT_CONTROL: - LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED); // May change state NotQueued->Idle - endpoint->CurrentState = state; // Get in before an int - LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | ControlListFilled; - LPC_USB->HcControl = LPC_USB->HcControl | ControlListEnable; - break; - - case ENDPOINT_BULK: - LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED); - endpoint->CurrentState = state; - LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled; - LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable; - break; - - case ENDPOINT_INTERRUPT: - CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]); - endpoint->CurrentState = state; - LPC_USB->HcControl |= PeriodicListEnable; - break; - } - return 0; - } - - // Remove an endpoint from an active queue - bool Remove(HCED* ed, volatile HCED** queue) - { - if (*queue == 0) - return false; - if (*queue == (volatile HCED*)ed) - { - *queue = (volatile HCED*)ed->Next; // At head of queue - return true; - } - - volatile HCED* head = *queue; - while (head) - { - if (head->Next == (u32)ed) - { - head->Next = ed->Next; - return true; - } - head = (volatile HCED*)head->Next; - } - return false; - } - - void Release(Endpoint* endpoint) - { - if (endpoint->CurrentState == Endpoint::NotQueued) - { - // Never event used it, nothing to do - } - else - { - HCED* ed = (HCED*)endpoint; - ed->Control |= 0x4000; // SKIP - switch (endpoint->Flags & 0x03) - { - case ENDPOINT_CONTROL: - Remove(ed,(volatile HCED**)&LPC_USB->HcControlHeadED); - break; - case ENDPOINT_BULK: - Remove(ed,(volatile HCED**)&LPC_USB->HcBulkHeadED); - break; - case ENDPOINT_INTERRUPT: - for (int i = 0; i < 32; i++) - Remove(ed,(volatile HCED**)&CommunicationArea.InterruptTable[i]); - break; - } - - u16 fn = CommunicationArea.FrameNumber; - while (fn == CommunicationArea.FrameNumber) - ; // Wait for next frame - - } - - // In theory, the endpoint is now dead. - // TODO: Will Callbacks ever be pending? BUGBUG - memset(endpoint,0,sizeof(Endpoint)); - } - - // Pop the last TD from the list - HCTD* Reverse(HCTD* current) - { - HCTD *result = NULL,*temp; - while (current) - { - temp = (HCTD*)current->Next; - current->Next = (u32)result; - result = current; - current = temp; - } - return result; - } - - // Called from interrupt... - // Control endpoints use a state machine to progress through the transfers - void ProcessDoneQueue(u32 tdList) - { - HCTD* list = Reverse((HCTD*)tdList); - while (list) - { - Endpoint* endpoint = (Endpoint*)(list-1); - list = (HCTD*)list->Next; - int ep = endpoint->Address(); - bool in = endpoint->Flags & 0x80; - int status = (endpoint->TDHead.Control >> 28) & 0xF; - - //LOG("ProcessDoneQueue %02X %08X\n",ep,endpoint->TDHead.Control); - - if (status != 0) - { - LOG("ProcessDoneQueue status %02X %d\n",ep,status); - endpoint->CurrentState = Endpoint::Idle; - } else { - switch (endpoint->CurrentState) - { - case Endpoint::SetupQueued: - if (endpoint->Length == 0) - Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Skip Data Phase - else - Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued); // Setup is done, now Data - break; - - case Endpoint::DataQueued: - if (endpoint->TDHead.CurrBufPtr) - endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data; - - if (ep == 0) - Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Data is done, now Status, Control only - else - endpoint->CurrentState = Endpoint::Idle; - break; - - case Endpoint::StatusQueued: // Transaction is done - endpoint->CurrentState = Endpoint::Idle; - break; - } - } - - // Complete, flag if we need a callback - if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle) - { - endpoint->CurrentState = Endpoint::CallbackPending; - _callbacksPending++; - } - } - } - - // Hack to reset devices that don't want to connect - int AddDevice(int hub, int port, bool isLowSpeed) - { - int device = AddDeviceCore(hub,port,isLowSpeed); - if (device < 0) - { - LOG("========RETRY ADD DEVICE========\n"); // This will go for ever.. TODO power cycle root? - Disconnect(hub,port); // Could not read descriptor at assigned address, reset this port and try again - ResetPort(hub,port); // Cheap bluetooth dongles often need this on a hotplug - return -1; - } - return device; - } - - int AddDeviceCore(int hub, int port, bool isLowSpeed) - { - int lowSpeed = isLowSpeed ? 0x2000 : 0; - DeviceDescriptor desc; - EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed; // MaxPacketSize == 8 - int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8); - if (r < 0) - { - LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\n"); - return r; - } - - EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed; // Actual MaxPacketSize - r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc)); - if (r < 0) - return r; - - LOG("\nClass %02X found %04X:%04X\n\n",desc.bDeviceClass,desc.idVendor,desc.idProduct); - - // Now assign the device an address, move off EndpointZero - int device = 0; - for (int i = 0; i < MAX_DEVICES; i++) - { - if (Devices[i].Port == 0) - { - device = i+1; - break; - } - } - if (!device) - return ERR_DEVICE_NONE_LEFT; - - r = SetAddress(0,device); - if (r) - return r; - DelayMS(2); - - // Now at a nonzero address, create control endpoint - Device* dev = &Devices[device-1]; - dev->Init(&desc,hub,port,device,lowSpeed); - AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0); - _connectPending = 0; - - // Verify this all works - r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc)); - if (r < 0) - return r; - - // Set to interface 0 by default - // Calls LoadDevice if interface is found - r = SetConfigurationAndInterface(device,1,0,&desc); - - if (desc.bDeviceClass == CLASS_HUB) - InitHub(device); // Handle hubs in this code - - return device; - } - - // Walk descriptors and create endpoints for a given device - // TODO configuration !=1, alternate settings etc. - int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc) - { - u8 buffer[255]; - int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,sizeof(buffer)); - if (err < 0) - return err; - - err = SetConfiguration(device,configuration); - if (err < 0) - return err; - - // Add the endpoints for this interface - int len = buffer[2] | (buffer[3] << 8); - u8* d = buffer; - u8* end = d + len; - InterfaceDescriptor* found = 0; - while (d < end) - { - if (d[1] == DESCRIPTOR_TYPE_INTERFACE) - { - InterfaceDescriptor* id = (InterfaceDescriptor*)d; - if (id->bInterfaceNumber == interfaceNumber) - { - found = id; - d += d[0]; - while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE) - { - switch (d[1]) - { - case DESCRIPTOR_TYPE_ENDPOINT: - AddEndpoint(device,(EndpointDescriptor*)d); - break; - default: - LOG("Skipping descriptor %02X (%d bytes)\n",d[1],d[0]); - } - d += d[0]; - } - } - } - d += d[0]; - } - - if (!found) - return ERR_INTERFACE_NOT_FOUND; - OnLoadDevice(device,desc,found); - return 0; - } - - void Init() - { - LOG("USB INIT (Controller is %d bytes)\n",sizeof(*this)); - memset(this,0,sizeof(HostController)); - EndpointZero.CurrentState = Endpoint::NotQueued; - HWInit(&CommunicationArea); - DelayMS(10); - } - - void ResetPort(int hub, int port) - { - LOG("ResetPort Hub:%d Port:%d\n",hub,port); - _connectPending++; // Only reset/add 1 device at a time - if (hub == 0) - LPC_USB->HcRhPortStatus1 = PortResetStatus; // Reset Root Hub, port 1 - else - SetPortReset(hub,port); // or reset other hub - } - - void Disconnect(int hub, int port) - { - LOG("Disconnect Hub:%d Port:%d\n",hub,port); // Mark a device for destruction - for (int i = 0; i < MAX_DEVICES; i++) - { - Device* dev = Devices + i; - if (dev->Port == port && dev->Hub == hub) - { - // Disconnect everything that is attached to this device if it is a hub - for (int p = 0; p < dev->HubPortCount; p++) - Disconnect(i+1,p+1); - - // Now release endpoints - for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2) - { - u8 endpointIndex = dev->_endpointMap[j]; - if (endpointIndex != 0xFF) - Release(Endpoints + endpointIndex); - } - dev->Port = 0; // Device is now free - dev->Flags = 0; - return; - } - } - } - - // called after reset - void Connect(int hub, int port, bool lowspeed) - { - LOG("Connect Hub:%d Port:%d %s\n",hub,port,lowspeed ? "slow" : "full"); - AddDevice(hub,port,lowspeed); - } - - // Called from interrupt - void HubStatusChange(int hub, int port, u32 status) - { - LOG("HubStatusChange Hub:%d Port:%d %08X\n",hub,port,status); - if (status & ConnectStatusChange) - { - if (status & CurrentConnectStatus) // Connecting - ResetPort(hub,port); // Reset to initiate connect (state machine?) - else - Disconnect(hub,port); - } - - if (status & PortResetStatusChange) - { - if (!(status & PortResetStatus)) - { - _connectCountdown = 200; // Schedule a connection in 200ms - if (status & LowspeedDevice) - port |= 0x80; - _connectHub = hub; - _connectPort = port; - } - } - } - - #define HOST_CLK_EN (1<<0) - #define PORTSEL_CLK_EN (1<<3) - #define AHB_CLK_EN (1<<4) - #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN) - - #define FRAMEINTERVAL (12000-1) // 1ms - #define DEFAULT_FMINTERVAL ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL) - - void DelayMS(int ms) - { - u16 f = ms + CommunicationArea.FrameNumber; - while (f != CommunicationArea.FrameNumber) - ; - } - - static void HWInit(HCCA* cca) - { - NVIC_DisableIRQ(USB_IRQn); - - // turn on power for USB - LPC_SC->PCONP |= (1UL<<31); - // Enable USB host clock, port selection and AHB clock - LPC_USB->USBClkCtrl |= CLOCK_MASK; - // Wait for clocks to become available - while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK) - ; - - // We are a Host - LPC_USB->OTGStCtrl |= 1; - LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN; // we don't need port selection clock until we do OTG - - // configure USB pins - LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28)); - LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // USB D+/D- - - LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22)); // USB_PPWR, USB_OVRCR - LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22)); - - LPC_PINCON->PINSEL4 &= ~(3 << 18); // USB_CONNECT - LPC_PINCON->PINSEL4 |= (1 << 18); - - // Reset OHCI block - LPC_USB->HcControl = 0; - LPC_USB->HcControlHeadED = 0; - LPC_USB->HcBulkHeadED = 0; - - LPC_USB->HcCommandStatus = HostControllerReset; - LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; - LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100; - - LPC_USB->HcControl = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask; - LPC_USB->HcRhStatus = SetGlobalPower; - - LPC_USB->HcHCCA = (u32)cca; - LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; - LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow; - - NVIC_SetPriority(USB_IRQn, 0); - NVIC_EnableIRQ(USB_IRQn); - while (cca->FrameNumber < 10) - ; // 10ms delay before diving in - } -}; - -//==================================================================================== -//==================================================================================== -// Host controller instance and Interrupt handler - -static HostController _controller __attribute__((at(USB_RAM_BASE))); - -extern "C" void USB_IRQHandler(void) __irq; -void USB_IRQHandler (void) __irq -{ - u32 int_status = LPC_USB->HcInterruptStatus; - - if (int_status & RootHubStatusChange) // Root hub status change - _controller._rootHubStatusChange++; // Just flag the controller, will be processed in USBLoop - - u32 head = 0; - if (int_status & WritebackDoneHead) - { - head = _controller.CommunicationArea.DoneHead; // Writeback Done - _controller.CommunicationArea.DoneHead = 0; - } - LPC_USB->HcInterruptStatus = int_status; - - if (head) - _controller.ProcessDoneQueue(head); // TODO - low bit can be set BUGBUG -} - -//==================================================================================== -//==================================================================================== -// API Methods - -void USBInit() -{ - return _controller.Init(); -} - -void USBLoop() -{ - return _controller.Loop(); -} - -u8* USBGetBuffer(u32* len) -{ - *len = USB_RAM_SIZE - sizeof(HostController); - return _controller.SRAM; -} - -static Setup* GetSetup(int device) -{ - if (device == 0) - return &_controller._setupZero; - - if (device < 1 || device > MAX_DEVICES) - return 0; - return &_controller.Devices[device-1].SetupBuffer; -} - -// Loop until IO on endpoint is complete -static int WaitIODone(Endpoint* endpoint) -{ - if (endpoint->CurrentState == Endpoint::NotQueued) - return 0; - while (endpoint->CurrentState != Endpoint::Idle) - USBLoop(); // May generate callbacks, mount or unmount devices etc - int status = endpoint->Status(); - if (status == 0) - return endpoint->Length; - return -status; -} - -int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData) -{ - Endpoint* endpoint = _controller.GetEndpoint(device,ep); - if (!endpoint) - return ERR_ENDPOINT_NOT_FOUND; - - WaitIODone(endpoint); - endpoint->Flags = flags; - endpoint->Data = data; - endpoint->Length = length; - endpoint->Callback = callback; - endpoint->UserData = userData; - if (ep == 0) - _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued); - else - _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued); - if (callback) - return IO_PENDING; - return WaitIODone(endpoint); -} - -int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData) -{ - Setup* setup = GetSetup(device); - if (!setup) - return ERR_DEVICE_NOT_FOUND; - - // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call - WaitIODone(_controller.GetEndpoint(device,0)); - - setup->bm_request_type = request_type; - setup->b_request = request; - setup->w_value = value; - setup->w_index = index; - setup->w_length = length; - return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData); -} - -int USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData) -{ - return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData); -} - -int USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData) -{ - return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData); -} - -int GetDescriptor(int device, int descType,int descIndex, u8* data, int length) -{ - return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0); -} - -int GetString(int device, int index, char* dst, int length) -{ - u8 buffer[255]; - int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer)); - if (le < 0) - return le; - if (length < 1) - return -1; - length <<= 1; - if (le > length) - le = length; - for (int j = 2; j < le; j += 2) - *dst++ = buffer[j]; - *dst = 0; - return (le>>1)-1; -} - -int SetAddress(int device, int new_addr) -{ - return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0); -} - -int SetConfiguration(int device, int configNum) -{ - return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0); -} - -int SetInterface(int device, int ifNum, int altNum) -{ - return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0); -} - -// HUB stuff -int SetPortFeature(int device, int feature, int index) -{ - return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0); -} - -int ClearPortFeature(int device, int feature, int index) -{ - return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0); -} - -int SetPortPower(int device, int port) -{ - int r = SetPortFeature(device,PORT_POWER,port); - _controller.DelayMS(20); // 80ms to turn on a hubs power... DESCRIPTOR? todo - return r; -} - -int SetPortReset(int device, int port) -{ - return SetPortFeature(device,PORT_RESET,port); -} - -int GetPortStatus(int device, int port, u32* status) -{ - return USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,GET_STATUS,0,port,(u8*)status,4); -} \ No newline at end of file
--- a/USBHost.h Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ - -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef USBHOST_H -#define USBHOST_H - -#ifndef u8 -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; - -typedef char s8; -typedef short s16; -typedef char s32; -#endif - -#define ENDPOINT_CONTROL 0 -#define ENDPOINT_ISOCRONOUS 1 -#define ENDPOINT_BULK 2 -#define ENDPOINT_INTERRUPT 3 - -#define DESCRIPTOR_TYPE_DEVICE 1 -#define DESCRIPTOR_TYPE_CONFIGURATION 2 -#define DESCRIPTOR_TYPE_STRING 3 -#define DESCRIPTOR_TYPE_INTERFACE 4 -#define DESCRIPTOR_TYPE_ENDPOINT 5 - -#define DESCRIPTOR_TYPE_HID 0x21 -#define DESCRIPTOR_TYPE_REPORT 0x22 -#define DESCRIPTOR_TYPE_PHYSICAL 0x23 -#define DESCRIPTOR_TYPE_HUB 0x29 - -enum USB_CLASS_CODE -{ - CLASS_DEVICE, - CLASS_AUDIO, - CLASS_COMM_AND_CDC_CONTROL, - CLASS_HID, - CLASS_PHYSICAL = 0x05, - CLASS_STILL_IMAGING, - CLASS_PRINTER, - CLASS_MASS_STORAGE, - CLASS_HUB, - CLASS_CDC_DATA, - CLASS_SMART_CARD, - CLASS_CONTENT_SECURITY = 0x0D, - CLASS_VIDEO = 0x0E, - CLASS_DIAGNOSTIC_DEVICE = 0xDC, - CLASS_WIRELESS_CONTROLLER = 0xE0, - CLASS_MISCELLANEOUS = 0xEF, - CLASS_APP_SPECIFIC = 0xFE, - CLASS_VENDOR_SPECIFIC = 0xFF -}; - -#define DEVICE_TO_HOST 0x80 -#define HOST_TO_DEVICE 0x00 -#define REQUEST_TYPE_CLASS 0x20 -#define RECIPIENT_DEVICE 0x00 -#define RECIPIENT_INTERFACE 0x01 -#define RECIPIENT_ENDPOINT 0x02 -#define RECIPIENT_OTHER 0x03 - -#define GET_STATUS 0 -#define CLEAR_FEATURE 1 -#define SET_FEATURE 3 -#define SET_ADDRESS 5 -#define GET_DESCRIPTOR 6 -#define SET_DESCRIPTOR 7 -#define GET_CONFIGURATION 8 -#define SET_CONFIGURATION 9 -#define GET_INTERFACE 10 -#define SET_INTERFACE 11 -#define SYNCH_FRAME 11 - -// -5 is nak -/* -0010 ACK Handshake -1010 NAK Handshake -1110 STALL Handshake -0110 NYET (No Response Yet) -*/ - -#define IO_PENDING -100 -#define ERR_ENDPOINT_NONE_LEFT -101 -#define ERR_ENDPOINT_NOT_FOUND -102 -#define ERR_DEVICE_NOT_FOUND -103 -#define ERR_DEVICE_NONE_LEFT -104 -#define ERR_HUB_INIT_FAILED -105 -#define ERR_INTERFACE_NOT_FOUND -106 - -typedef struct -{ - u8 bLength; - u8 bDescriptorType; - u16 bcdUSB; - u8 bDeviceClass; - u8 bDeviceSubClass; - u8 bDeviceProtocol; - u8 bMaxPacketSize; - u16 idVendor; - u16 idProduct; - u16 bcdDevice; // version - u8 iManufacturer; - u8 iProduct; - u8 iSerialNumber; - u8 bNumConfigurations; -} DeviceDescriptor; // 16 bytes - -typedef struct -{ - u8 bLength; - u8 bDescriptorType; - u16 wTotalLength; - u8 bNumInterfaces; - u8 bConfigurationValue; // Value to use as an argument to select this configuration - u8 iConfiguration; // Index of String Descriptor describing this configuration - u8 bmAttributes; // Bitmap D7 Reserved, set to 1. (USB 1.0 Bus Powered),D6 Self Powered,D5 Remote Wakeup,D4..0 = 0 - u8 bMaxPower; // Maximum Power Consumption in 2mA units -} ConfigurationDescriptor; - -typedef struct -{ - u8 bLength; - u8 bDescriptorType; - u8 bInterfaceNumber; - u8 bAlternateSetting; - u8 bNumEndpoints; - u8 bInterfaceClass; - u8 bInterfaceSubClass; - u8 bInterfaceProtocol; - u8 iInterface; // Index of String Descriptor Describing this interface -} InterfaceDescriptor; - -typedef struct -{ - u8 bLength; - u8 bDescriptorType; - u8 bEndpointAddress; // Bits 0:3 endpoint, Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints) - u8 bmAttributes; // Bits 0:1 00 = Control, 01 = Isochronous, 10 = Bulk, 11 = Interrupt - u16 wMaxPacketSize; - u8 bInterval; // Interval for polling endpoint data transfers. -} EndpointDescriptor; - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 bcdHID; - u8 bCountryCode; - u8 bNumDescriptors; - u8 bDescriptorType2; - u16 wDescriptorLength; -} HIDDescriptor; - -//============================================================================ -//============================================================================ - - -void USBInit(); -void USBLoop(); -u8* USBGetBuffer(u32* len); - -// Optional callback for transfers, called at interrupt time -typedef void (*USBCallback)(int device, int endpoint, int status, u8* data, int len, void* userData); - -// Transfers -int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback = 0, void* userData = 0); -int USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback = 0, void* userData = 0); -int USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback = 0, void* userData = 0); - -// Standard Device methods -int GetDescriptor(int device, int descType, int descIndex, u8* data, int length); -int GetString(int device, int index, char* dst, int length); -int SetAddress(int device, int new_addr); -int SetConfiguration(int device, int configNum); -int SetInterface(int device, int ifNum, int altNum); - -// Implemented to notify app of the arrival of a device -void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc); - -#endif \ No newline at end of file
--- a/Utils.cpp Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ - - -#include "mbed.h" -#include "Utils.h" - -void printfBytes(const char* s, const u8* data, int len) -{ - printf("%s %d:",s,len); - if (len > 256) - len = 256; - while (len-- > 0) - printf(" %02X",*data++); - printf("\n"); -} - -void printHexLine(const u8* d, int addr, int len) -{ - printf("%04X ",addr); - int i; - for (i = 0; i < len; i++) - printf("%02X ",d[i]); - for (;i < 16; i++) - printf(" "); - char s[16+1]; - memset(s,0,sizeof(s)); - for (i = 0; i < len; i++) - { - int c = d[i]; - if (c < 0x20 || c > 0x7E) - c = '.'; - s[i] = c; - } - printf("%s\n",s); -} - -void printHex(const u8* d, int len) -{ - int addr = 0; - while (len) - { - int count = len; - if (count > 16) - count = 16; - printHexLine(d+addr,addr,count); - addr += 16; - len -= count; - } -}
--- a/Utils.h Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; - -void DelayMS(int ms); - -void printfBytes(const char* label,const u8* data, int len); -void printHex(const u8* d, int len); - -#ifndef min -#define min(_a,_b) ((_a) < (_b) ? (_a) : (_b)) -#endif - -inline int LE16(const u8* d) -{ - return d[0] | (d[1] << 8); -} - -inline u32 BE32(const u8* d) -{ - return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3]; -} - -inline void BE32(u32 n, u8* d) -{ - d[0] = (u8)(n >> 24); - d[1] = (u8)(n >> 16); - d[2] = (u8)(n >> 8); - d[3] = (u8)n; -} - -inline void BE16(u32 n, u8* d) -{ - d[0] = (u8)(n >> 8); - d[1] = (u8)n; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WiiControl.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -0,0 +1,154 @@ +#include "mbed.h" + +#define ACC_LEFT 600 +#define ACC_RIGHT 430 +#define ACC_CENTERL 490 +#define ACC_CENTERH 530 +#define ACC_C_U_L 560 +#define ACC_C_U_R 470 +#define BASE_SPEED 30 + +#define X_MAX 610 +#define X_MIN 410 +#define X_UPPER_MID 530 +#define X_LOWER_MID 490 + +#define SPEED_BASE 30 +#define SPEED_BOOST 20 +#define SPEED_TURBO 100 + +extern Serial rob, pc; +extern time_t lastReportTime; + +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); + +AnalogIn ir(p20); + +void MoveRobot(); +void ControlRobot(int, int); +int GetMotorSpeeds(int y, int x, bool turbo); + +typedef struct +{ + bool a, b, up, down, left, right, one, two; + int x, y, z; +} WiimoteState; + +WiimoteState state; + +void ProcessHID(const unsigned char *data) +{ + lastReportTime = time(NULL); + led3 = 0; + + char b1 = data[2]; + char b2 = data[3]; + + state.a = (bool)(b2 & 8); + state.b = (bool)(b2 & 4); + state.up = (bool)(b1 & 8); + state.down = (bool)(b1 & 4); + state.left = (bool)(b1 & 1); + state.right = (bool)(b1 & 2); + state.one = (bool)(b2 & 2); + state.two = (bool)(b2 & 1); + + state.x = (data[4] << 2) | ((b1 & 0x60) >> 5); + state.y = (data[5] << 2) | ((b2 & 0x20) >> 4); + state.z = (data[6] << 2) | ((b2 & 0x40) >> 5); + + MoveRobot(); +} + +int GetMotorSpeeds(int y, int x, bool turbo) +{ + int speed = turbo ? SPEED_TURBO : SPEED_BASE; + int m1, m2; + float yscale, xscale; + + if (x > X_UPPER_MID) + { + if (x > X_MAX) + x = X_MAX; + xscale = (1.0*x - X_UPPER_MID) / (X_MAX - X_UPPER_MID); + speed += (int)(xscale * SPEED_BOOST); + } + else if (x < X_LOWER_MID) + { + if (x < X_MIN) + x = X_MIN; + xscale = (1.0*x - X_LOWER_MID) / (X_MIN - X_LOWER_MID); + speed -= (int)(xscale * SPEED_BOOST); + } + + if (y >= ACC_CENTERL && y <= ACC_CENTERH) + { + m1 = m2 = speed; + } + else if (y > ACC_CENTERH) // turning left + { + if (y > ACC_LEFT) + y = ACC_LEFT; + yscale = (1.0*y - ACC_CENTERH) / (ACC_LEFT - ACC_CENTERH); + yscale *= speed; + m1 = speed; + m2 = (int)(speed - yscale); + } + else // turning right + { + if (y < ACC_RIGHT) + y = ACC_RIGHT; + yscale = (1.0*y - ACC_CENTERL) / (ACC_RIGHT - ACC_CENTERL); + yscale *= speed; + m1 = (int)(speed - yscale); + m2 = speed; + } + + return ((m1&0xFF)<<8) | (m2 & 0xFF); +} + +void MoveRobot() +{ + int turnspeed = state.b ? SPEED_TURBO : SPEED_BASE; + + bool wall = ir.read() > (2.2 / 3.3); + led4 = wall; + + if (state.up) + ControlRobot(turnspeed, -1*turnspeed); + else if (state.down) + ControlRobot(-1*turnspeed, turnspeed); + else if (state.one || state.two) + { + int dir = state.two ? 1 : -1; + int speeds = GetMotorSpeeds(state.y, state.x, state.b); + int m1 = speeds >> 8; + int m2 = speeds & 0xFF; + + if (wall && dir == 1) + ControlRobot(0,0); + else + ControlRobot(m1*dir, m2*dir); + } + else + ControlRobot(0,0); +} + +void ControlRobot(int m1, int m2) +{ + if (m1 == 0 && m2 == 0) + { + led1 = 0; + rob.puts("stop\r"); + } + else + { + led1 = 1; + rob.printf("mogo 1:%d 2:%d\r", m1, m2); + } + while (rob.readable()) + rob.getc(); +}
--- a/hci.cpp Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,426 +0,0 @@ - -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "Utils.h" -#include "hci.h" -#include "hci_private.h" - -enum hci_callback_evt -{ - NONE, - CONNECT, - DISCONECT, - INQUIRYRESULT -}; - -#define MAX_BLUETOOTH_ADAPTERS 1 - -enum StateMask { - MASK_RESET = 1, - MASK_READ_BUFFER_SIZE = 2, - MASK_READ_BD_ADDR = 4, - MASK_INITED = 8, - MASK_INQUIRY = 16, - MASK_REMOTE_NAME = 32, - MASK_CREATE_CONNECTION = 64 -}; - -int HCI::Open(HCITransport* transport, HCICallback callback) -{ - _transport = transport; - _transport->Set(this); - _callback = callback; - _state = 0; - for (int i = 0; i < MAX_BTDEVICES; i++) - { - _devices[i].Init(); - _devices[i]._transport = transport; - } - return SendCmd(HCI_OP_RESET); -} - -void printf(const BD_ADDR* addr); - -BTDevice* HCI::Find(const BD_ADDR* addr) -{ - for (int i = 0; i < MAX_BTDEVICES; i++) - if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0) - return &_devices[i]; - return 0; -} - -BTDevice* HCI::Find(int handle) -{ - for (int i = 0; i < MAX_BTDEVICES; i++) - if (_devices[i]._state != 0 && handle == _devices[i]._handle) - return &_devices[i]; - return 0; -} -// -bool HCI::Busy() -{ - return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0; -} - -int HCI::Inquiry(int duration) -{ - _state |= MASK_INQUIRY; - u8 buf[5]; - buf[0] = 0x33; - buf[1] = 0x8B; - buf[2] = 0x9E; - buf[3] = duration; - buf[4] = 5; // 5 results - SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf)); - return 0; -} - -int HCI::SendCmd(int cmd, const u8* params, int len) -{ - u8 b[32]; - b[0] = cmd; - b[1] = (cmd >> 8); - b[2] = len; - if (params) - memcpy(b+3,params,len); - _transport->HCISend(b,len+3); - return 0; -} - -void HCI::OnCommandComplete(int cmd, const u8* data, int len) -{ - // printf("%04X %s",cmd,CmdStr(cmd)); - if (len < 0) - return; - //printfBytes(" complete",data,min(16,len)); - - switch (cmd) - { - // Init phase 0 - case HCI_OP_RESET: // Reset done, init chain to HCI_OP_READ_LOCAL_NAME - SendCmd(HCI_OP_READ_BUFFER_SIZE); - _state |= MASK_RESET; - break; - - // Init phase 1 - case HCI_OP_READ_BUFFER_SIZE: - _acl_mtu = LE16(data); - _sco_mtu = data[2]; - _acl_max_pkt = LE16(data+3); - _sco_max_pkt = LE16(data+5); - SendCmd(HCI_OP_READ_BD_ADDR); - _state |= MASK_READ_BUFFER_SIZE; - break; - - // Init phase 2 - case HCI_OP_READ_BD_ADDR: - _localAddr = *((BD_ADDR*)data); // Local Address - _state |= MASK_READ_BD_ADDR; - _state |= MASK_INITED; - Callback(CALLBACK_READY,data,6); - break; - - // 0CXX - case HCI_OP_READ_LOCAL_NAME: - break; - - case HCI_OP_READ_LOCAL_VERSION: - // params - //SendCmd(HCI_OP_READ_LOCAL_NAME); - break; - - case HCI_OP_READ_LOCAL_COMMANDS: - break; - - case HCI_OP_READ_LOCAL_FEATURES: - //SendCmd(HCI_OP_READ_LOCAL_VERSION); - break; - - case HCI_OP_READ_LOCAL_EXT_FEATURES: - break; - - case HCI_OP_PIN_CODE_REPLY: - printf("Got pin reply\n"); - break; - - default: - printf("Unrecognized Command %04X\n",cmd); - break; - } -} - -void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len) -{ - _callback(this,c,data,len); -} - -int HCI::RemoteNameRequest(const BD_ADDR* addr) -{ - _state |= MASK_REMOTE_NAME; - u8 buf[6+4]; - memset(buf,0,sizeof(buf)); - memcpy(buf,addr,6); - buf[7] = 1; - return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf)); -} - -int HCI::CreateConnection(const BD_ADDR* remoteAddr) -{ - _state |= MASK_CREATE_CONNECTION; - u8 buf[6+7]; - memset(buf,0,sizeof(buf)); - memcpy(buf,remoteAddr,6); - buf[6] = 0x18; // DM1,DH1 - buf[7] = 0xCC; // DM3, DH3, DM5, DH5 - buf[8] = 1; // Page Repetition R1 - return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf)); -} - -int HCI::Disconnect(const BD_ADDR* bdaddr) -{ - BTDevice* d = Find(bdaddr); - if (!d) - return ERR_HCI_DEVICE_NOT_FOUND; - int handle = d->_handle; - printf("Disconnect from %d\n",handle); - _state |= MASK_CREATE_CONNECTION; - u8 buf[3]; - buf[0] = handle; - buf[1] = (handle >> 8); - buf[2] = 0x13; - return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf)); -} - -void HCI::DisconnectComplete(int handle) -{ - BTDevice* d = Find(handle); - if (!d) - return; - d->_handle = 0; -} - -int HCI::DisconnectAll() -{ - BTDevice* devs[8]; - int count = GetDevices(devs,8); - for (int i = 0; i < count; i++) - Disconnect(&devs[i]->_info.bdaddr); - return 0; -} - -int HCI::PinCodeReply(const u8* data) -{ - u8 b[6+1+16]; - memset(b,0,sizeof(b)); - memcpy(b,data,6); - b[6] = 4; - b[7] = '0'; - b[8] = '0'; - b[9] = '0'; - b[10] = '0'; - return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b)); -} - -void HCI::InquiryResult(const inquiry_info* info) -{ - BTDevice* bt = Find(&info->bdaddr); - if (!bt) // new device - { - for (int i = 0; i < MAX_BTDEVICES; i++) - { - if (_devices[i]._state == 0) - { - bt = _devices + i; - bt->_state = 1; - break; - } - } - if (!bt) - { - printf("HCI::InquiryResult too many devices\n"); - return; // Too many devices! - } - } - - bt->_info = *info; -} - -int HCI::GetDevices(BTDevice** devices, int maxDevices) -{ - int j = 0; - for (int i = 0; i < MAX_BTDEVICES; i++) - { - if (_devices[i]._state != 0) - { - devices[j++] = _devices + i; - if (j == maxDevices) - break; - } - } - return j; -} - -void HCI::RemoteName(const BD_ADDR* addr, const char* name) -{ - BTDevice* d = Find(addr); - if (d) - { - strncpy(d->_name,name,sizeof(d->_name)-1); - d->_name[sizeof(d->_name)-1] = 0; - } -} - -void HCI::ConnectComplete(const connection_info* info) -{ - BTDevice* d = Find(&info->bdaddr); - if (!d) - return; - if (info->status == 0) - { - d->_handle = info->handle; - printf("Connected on %04X\n",info->handle); - } else - printf("Connection failed with %d\n",info->status); -} - -void HCI::HCIRecv(const u8* data, int len) -{ - // printfBytes(EvtStr(data[0]),data,min(len,16)); - switch (data[0]) - { - case HCI_EV_INQUIRY_COMPLETE: - printfBytes("Inquiry Complete",data,data[1]); - _state &= ~MASK_INQUIRY; - Callback(CALLBACK_INQUIRY_DONE,0,0); - break; - - case HCI_EV_INQUIRY_RESULT: - { - const u8* end = data[1] + data + 2; - data += 3; - while (data < end) - { - inquiry_info align; - memcpy(&align,data,sizeof(inquiry_info)); - InquiryResult(&align); - Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info)); - data += 14; - } - } - break; - - case HCI_EV_CONN_COMPLETE: - _state &= ~MASK_CREATE_CONNECTION; - { - connection_info align; - memcpy(&align,data+2,sizeof(connection_info)); - ConnectComplete(&align); - Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info)); - } - break; - - case HCI_EV_CONN_REQUEST: - break; - - case HCI_EV_DISCONN_COMPLETE: - DisconnectComplete(LE16(data+3)); - break; - - case HCI_EV_REMOTE_NAME: - { - BD_ADDR* addr = (BD_ADDR*)(data+3); - const char* name = (const char*)(data + 9); - RemoteName(addr,name); - } - Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1)); // addr is in here too - _state &= ~MASK_REMOTE_NAME; - break; - - case HCI_EV_CMD_STATUS: - { - const char* errs = HCIErrStr(data[2]); - printf("Status %s %s\n",CmdStr(LE16(data+4)),errs); - } - break; - - case HCI_EV_CMD_COMPLETE: - OnCommandComplete(data[3] | (data[4] << 8),data+6,data[1]-4); - break; - - case HCI_EV_PIN_CODE_REQ: - PinCodeReply(data+2); - break; - - case HCI_EV_LINK_KEY_REQ: - SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6); - break; - - default: - ; - // printfBytes(":",data,data[1]+2); - } -} - -int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr) -{ - L2CAPSocket* l2capsock = (L2CAPSocket*)sock; - L2CAPAddr* l2capaddr = (L2CAPAddr*)addr; - BTDevice* bt = Find(&l2capaddr->bdaddr); - if (!bt) - { - printf("Can't open l2cap %d on ",l2capaddr->psm); - printf(&l2capaddr->bdaddr); - printf("\n"); - return ERR_HCI_DEVICE_NOT_FOUND; - } - l2capsock->btdevice = bt; - return bt->Open(sock,addr); -} - -int HCI::Send(SocketInternal* sock, const u8* data, int len) -{ - L2CAPSocket* l2capsock = (L2CAPSocket*)sock; - return l2capsock->btdevice->Send(sock,data,len); // Pointless double dispatch -} - -int HCI::Close(SocketInternal* sock) -{ - L2CAPSocket* l2capsock = (L2CAPSocket*)sock; - return l2capsock->btdevice->Close(sock); // Pointless double dispatch -} - -void HCI::ACLRecv(const u8* data, int len) -{ - int handle = LE16(data); - BTDevice* d = Find(handle & 0x0FFF); - if (d) - d->ACLRecv(data,len); -} - -//=================================================================== -//===================================================================
--- a/hci.h Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,224 +0,0 @@ -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef HCI_H_INCLUDED -#define HCI_H_INCLUDED - -#include "Socket.h" - -#pragma pack(1) - -#define ERR_HCI_DEVICE_NOT_FOUND -300 - -class HCI; -class HCITransport; -class BTDevice; - -typedef struct -{ - u8 addr[6]; -} BD_ADDR; - -typedef struct -{ - BD_ADDR bdaddr; - u8 pscan_rep_mode; - u8 pscan_period_mode; - u8 pscan_mode; - u8 dev_class[3]; - u16 clock_offset; -} inquiry_info; - -typedef struct -{ - u8 status; - u16 handle; - BD_ADDR bdaddr; - u8 link_type; - u8 encr_mode; -} connection_info; - -// Address struct for creating L2CAP sockets -typedef struct { - SocketAddrHdr hdr; - BD_ADDR bdaddr; - u16 psm; -} L2CAPAddr; - -#pragma pack(4) - -class BTDevice; -typedef struct -{ - public: - SocketInternal si; - BTDevice* btdevice; - u16 scid; - u16 dcid; -} L2CAPSocket; - -#define MAX_HCL_NAME_LENGTH 20 // TODO - BTDevice wants to be a multiple of 4 - -// BTDevice encapsulates individual device state -// It provides L2CAP layer sockets - -class BTDevice : public SocketHandler -{ - public: - HCITransport* _transport; - inquiry_info _info; - u16 _handle; // acl connection handle - u8 _state; // connection state - u8 _txid; - char _name[MAX_HCL_NAME_LENGTH]; - - void Init(); - - BD_ADDR* GetAddress() { return &_info.bdaddr; } - - // Called from HCI - void ACLRecv(const u8* data, int len); - - // SocketHandler - virtual int Open(SocketInternal* sock, SocketAddrHdr* addr); - virtual int Send(SocketInternal* sock, const u8* data, int len); - virtual int Close(SocketInternal* sock); - -private: - L2CAPSocket* SCIDToSocket(int scid); - int Send(const u8* data, int len); - int Send(u8 c, u8 id, u16* params, int count); - int Connect(int scid, int psm); - int Disconnect(int scid, int dcid); - int ConfigureRequest(int dcid); - int ConfigureResponse(u8 rxid, int dcid); - int DisconnectResponse(u8 rxid, int scid, int dcid); - void Control(const u8* data, int len); -}; - -enum HCI_CALLBACK_EVENT -{ - CALLBACK_NONE, - CALLBACK_READY, - CALLBACK_INQUIRY_RESULT, - CALLBACK_INQUIRY_DONE, - CALLBACK_REMOTE_NAME, - CALLBACK_CONNECTION_COMPLETE, - CALLBACK_CONNECTION_FAILED -}; - -// L2CAP Protocol/Service Multiplexor (PSM) values - -#define L2CAP_PSM_ANY 0x0000 /* Any/Invalid PSM */ -#define L2CAP_PSM_SDP 0x0001 /* Service Discovery Protocol */ -#define L2CAP_PSM_RFCOMM 0x0003 /* RFCOMM protocol */ -#define L2CAP_PSM_TCP 0x0005 /* Telephony Control Protocol */ -#define L2CAP_PSM_TCS 0x0007 /* TCS cordless */ -#define L2CAP_PSM_BNEP 0x000f /* Bluetooth Network Encapsulation Protocol*/ -#define L2CAP_PSM_HID_CNTL 0x0011 /* HID Control */ -#define L2CAP_PSM_HID_INTR 0x0013 /* HID Interrupt */ -#define L2CAP_PSM_ESDP 0x0015 /* Extended Service Discovery Profile */ -#define L2CAP_PSM_AVCTP 0x0017 /* Audio/Visual Control Transport Protocol */ -#define L2CAP_PSM_AVDTP 0x0019 /* Audio/Visual Distribution */ - -// Callback from inquiry -typedef int (*HCICallback)(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len); - -#define MAX_BTDEVICES 8 - -class HCITransport; -class HCI : public SocketHandler -{ - HCITransport* _transport; - HCICallback _callback; - BD_ADDR _localAddr; - - BTDevice _devices[MAX_BTDEVICES]; - int _deviceCount; - - int _acl_mtu; - int _acl_max_pkt; - int _sco_mtu; - int _sco_max_pkt; - - int _state; - - public: - - // Open a local adapter - int Open(HCITransport* transport, HCICallback callback); - - // Return list of discovered addreses - int GetDevices(BTDevice** devices, int maxDevices); - - // Lookup a device by address or handle - BTDevice* Find(const BD_ADDR* addr); - BTDevice* Find(int handle); - - // Disconnect from a remote device - int Disconnect(const BD_ADDR* addr); - int DisconnectAll(); - - // see what devies are in the system - int Inquiry(int duration = 10); - - // get a name, delivered in callback - int RemoteNameRequest(const BD_ADDR* addr); - - // Connect to a remote device - int CreateConnection(const BD_ADDR* remoteAddr); - - bool Busy(); - - // called from transport - void HCIRecv(const u8* data, int len); - - // called from transport - void ACLRecv(const u8* data, int len); - - // SocketHandler methods for maintaining L2CAP sockets - virtual int Open(SocketInternal* sock, SocketAddrHdr* addr); - virtual int Send(SocketInternal* sock, const u8* data, int len); - virtual int Close(SocketInternal* sock); - - private: - void InquiryResult(const inquiry_info* info); - void RemoteName(const BD_ADDR* addr, const char* name); - void ConnectComplete(const connection_info* info); - void DisconnectComplete(int handle); - int SendCmd(int cmd, const u8* params = 0, int len = 0); - void OnCommandComplete(int cmd, const u8* data, int len); - void Callback(HCI_CALLBACK_EVENT c, const u8* data, int len); - int PinCodeReply(const u8* data); -}; - -class HCITransport -{ -protected: - HCI* _target; -public: - void Set(HCI* target) { _target = target; }; - virtual void HCISend(const u8* data, int len) = 0; - virtual void ACLSend(const u8* data, int len) = 0; -}; - -#endif
--- a/hci_private.h Sat Apr 10 00:30:24 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,323 +0,0 @@ -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef HCI_PRIVATE_H_INCLUDED -#define HCI_PRIVATE_H_INCLUDED - -#define HCI_OP_INQUIRY 0x0401 -#define HCI_OP_INQUIRY_CANCEL 0x0402 -#define HCI_OP_EXIT_PERIODIC_INQ 0x0404 -#define HCI_OP_CREATE_CONN 0x0405 -#define HCI_OP_DISCONNECT 0x0406 -#define HCI_OP_ADD_SCO 0x0407 -#define HCI_OP_CREATE_CONN_CANCEL 0x0408 -#define HCI_OP_ACCEPT_CONN_REQ 0x0409 -#define HCI_OP_REJECT_CONN_REQ 0x040a -#define HCI_OP_LINK_KEY_REPLY 0x040b -#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c -#define HCI_OP_PIN_CODE_REPLY 0x040d -#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e -#define HCI_OP_CHANGE_CONN_PTYPE 0x040f -#define HCI_OP_AUTH_REQUESTED 0x0411 -#define HCI_OP_SET_CONN_ENCRYPT 0x0413 -#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415 -#define HCI_OP_REMOTE_NAME_REQ 0x0419 -#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a -#define HCI_OP_READ_REMOTE_FEATURES 0x041b -#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c -#define HCI_OP_READ_REMOTE_VERSION 0x041d -#define HCI_OP_SETUP_SYNC_CONN 0x0428 -#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429 -#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a - -#define HCI_OP_SNIFF_MODE 0x0803 -#define HCI_OP_EXIT_SNIFF_MODE 0x0804 -#define HCI_OP_ROLE_DISCOVERY 0x0809 -#define HCI_OP_SWITCH_ROLE 0x080b -#define HCI_OP_READ_LINK_POLICY 0x080c -#define HCI_OP_WRITE_LINK_POLICY 0x080d -#define HCI_OP_READ_DEF_LINK_POLICY 0x080e -#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f -#define HCI_OP_SNIFF_SUBRATE 0x0811 - - -#define HCI_OP_SET_EVENT_MASK 0x0c01 -#define HCI_OP_RESET 0x0c03 -#define HCI_OP_SET_EVENT_FLT 0x0c05 -#define HCI_OP_WRITE_LOCAL_NAME 0x0c13 -#define HCI_OP_READ_LOCAL_NAME 0x0c14 -#define HCI_OP_WRITE_CA_TIMEOUT 0x0c16 -#define HCI_OP_WRITE_PG_TIMEOUT 0x0c18 -#define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a -#define HCI_OP_READ_AUTH_ENABLE 0x0c1f -#define HCI_OP_WRITE_AUTH_ENABLE 0x0c20 -#define HCI_OP_READ_ENCRYPT_MODE 0x0c21 -#define HCI_OP_WRITE_ENCRYPT_MODE 0x0c22 - #define ENCRYPT_DISABLED 0x00 - #define ENCRYPT_P2P 0x01 - #define ENCRYPT_BOTH 0x02 -#define HCI_OP_READ_CLASS_OF_DEV 0x0c23 -#define HCI_OP_WRITE_CLASS_OF_DEV 0x0c24 -#define HCI_OP_READ_VOICE_SETTING 0x0c25 -#define HCI_OP_WRITE_VOICE_SETTING 0x0c26 -#define HCI_OP_HOST_BUFFER_SIZE 0x0c33 -#define HCI_OP_READ_SSP_MODE 0x0c55 -#define HCI_OP_WRITE_SSP_MODE 0x0c56 - -#define HCI_OP_READ_LOCAL_VERSION 0x1001 -#define HCI_OP_READ_LOCAL_COMMANDS 0x1002 -#define HCI_OP_READ_LOCAL_FEATURES 0x1003 -#define HCI_OP_READ_LOCAL_EXT_FEATURES 0x1004 -#define HCI_OP_READ_BUFFER_SIZE 0x1005 -#define HCI_OP_READ_BD_ADDR 0x1009 - -// events -#define HCI_EV_INQUIRY_COMPLETE 0x01 -#define HCI_EV_INQUIRY_RESULT 0x02 -#define HCI_EV_CONN_COMPLETE 0x03 -#define HCI_EV_CONN_REQUEST 0x04 -#define HCI_EV_DISCONN_COMPLETE 0x05 -#define HCI_EV_AUTH_COMPLETE 0x06 -#define HCI_EV_REMOTE_NAME 0x07 -#define HCI_EV_ENCRYPT_CHANGE 0x08 -#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09 -#define HCI_EV_REMOTE_FEATURES 0x0b -#define HCI_EV_REMOTE_VERSION 0x0c -#define HCI_EV_QOS_SETUP_COMPLETE 0x0d -#define HCI_EV_CMD_COMPLETE 0x0e -#define HCI_EV_CMD_STATUS 0x0f -#define HCI_EV_ROLE_CHANGE 0x12 -#define HCI_EV_NUM_COMP_PKTS 0x13 -#define HCI_EV_MODE_CHANGE 0x14 -#define HCI_EV_PIN_CODE_REQ 0x16 -#define HCI_EV_LINK_KEY_REQ 0x17 -#define HCI_EV_LINK_KEY_NOTIFY 0x18 -#define HCI_EV_CLOCK_OFFSET 0x1c -#define HCI_EV_PKT_TYPE_CHANGE 0x1d -#define HCI_EV_PSCAN_REP_MODE 0x20 -#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22 -#define HCI_EV_REMOTE_EXT_FEATURES 0x23 -#define HCI_EV_SYNC_CONN_COMPLETE 0x2c -#define HCI_EV_SYNC_CONN_CHANGED 0x2d -#define HCI_EV_SNIFF_SUBRATE 0x2e -#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f -#define HCI_EV_IO_CAPA_REQUEST 0x31 -#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36 -#define HCI_EV_REMOTE_HOST_FEATURES 0x3d - -/* Possible error codes */ -#define HCI_UNKNOWN_HCI_COMMAND 0x01 -#define HCI_NO_CONNECTION 0x02 -#define HCI_HW_FAILURE 0x03 -#define HCI_PAGE_TIMEOUT 0x04 -#define HCI_AUTHENTICATION_FAILURE 0x05 -#define HCI_KEY_MISSING 0x06 -#define HCI_MEMORY_FULL 0x07 -#define HCI_CONN_TIMEOUT 0x08 -#define HCI_MAX_NUMBER_OF_CONNECTIONS 0x09 -#define HCI_MAX_NUMBER_OF_SCO_CONNECTIONS_TO_DEVICE 0x0A -#define HCI_ACL_CONNECTION_EXISTS 0x0B -#define HCI_COMMAND_DISSALLOWED 0x0C -#define HCI_HOST_REJECTED_DUE_TO_LIMITED_RESOURCES 0x0D -#define HCI_HOST_REJECTED_DUE_TO_SECURITY_REASONS 0x0E -#define HCI_HOST_REJECTED_DUE_TO_REMOTE_DEVICE_ONLY_PERSONAL_SERVICE 0x0F -#define HCI_HOST_TIMEOUT 0x10 -#define HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE 0x11 -#define HCI_INVALID_HCI_COMMAND_PARAMETERS 0x12 -#define HCI_OTHER_END_TERMINATED_CONN_USER_ENDED 0x13 -#define HCI_OTHER_END_TERMINATED_CONN_LOW_RESOURCES 0x14 -#define HCI_OTHER_END_TERMINATED_CONN_ABOUT_TO_POWER_OFF 0x15 -#define HCI_CONN_TERMINATED_BY_LOCAL_HOST 0x16 -#define HCI_REPETED_ATTEMPTS 0x17 -#define HCI_PAIRING_NOT_ALLOWED 0x18 -#define HCI_UNKNOWN_LMP_PDU 0x19 -#define HCI_UNSUPPORTED_REMOTE_FEATURE 0x1A -#define HCI_SCO_OFFSET_REJECTED 0x1B -#define HCI_SCO_INTERVAL_REJECTED 0x1C -#define HCI_SCO_AIR_MODE_REJECTED 0x1D -#define HCI_INVALID_LMP_PARAMETERS 0x1E -#define HCI_UNSPECIFIED_ERROR 0x1F -#define HCI_UNSUPPORTED_LMP_PARAMETER_VALUE 0x20 -#define HCI_ROLE_CHANGE_NOT_ALLOWED 0x21 -#define HCI_LMP_RESPONSE_TIMEOUT 0x22 -#define HCI_LMP_ERROR_TRANSACTION_COLLISION 0x23 -#define HCI_LMP_PDU_NOT_ALLOWED 0x24 -#define HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE 0x25 -#define HCI_UNIT_KEY_USED 0x26 -#define HCI_QOS_NOT_SUPPORTED 0x27 -#define HCI_INSTANT_PASSED 0x28 -#define HCI_PAIRING_UNIT_KEY_NOT_SUPPORTED 0x29 - -const char* EvtStr(int evt) -{ - switch (evt) - { - case HCI_EV_INQUIRY_COMPLETE: return "HCI_EV_INQUIRY_COMPLETE"; - case HCI_EV_INQUIRY_RESULT: return "HCI_EV_INQUIRY_RESULT"; - case HCI_EV_CONN_COMPLETE: return "HCI_EV_CONN_COMPLETE"; - case HCI_EV_CONN_REQUEST: return "HCI_EV_CONN_REQUEST"; - case HCI_EV_DISCONN_COMPLETE: return "HCI_EV_DISCONN_COMPLETE"; - case HCI_EV_AUTH_COMPLETE: return "HCI_EV_AUTH_COMPLETE"; - case HCI_EV_REMOTE_NAME: return "HCI_EV_REMOTE_NAME"; - case HCI_EV_ENCRYPT_CHANGE: return "HCI_EV_ENCRYPT_CHANGE"; - case HCI_EV_CHANGE_LINK_KEY_COMPLETE : return "HCI_EV_CHANGE_LINK_KEY_COMPLETE"; - case HCI_EV_REMOTE_FEATURES: return "HCI_EV_REMOTE_FEATURES"; - case HCI_EV_REMOTE_VERSION: return "HCI_EV_REMOTE_VERSION"; - case HCI_EV_QOS_SETUP_COMPLETE : return "HCI_EV_QOS_SETUP_COMPLETE"; - case HCI_EV_CMD_COMPLETE: return "HCI_EV_CMD_COMPLETE"; - case HCI_EV_CMD_STATUS: return "HCI_EV_CMD_STATUS"; - case HCI_EV_ROLE_CHANGE: return "HCI_EV_ROLE_CHANGE"; - case HCI_EV_NUM_COMP_PKTS: return "HCI_EV_NUM_COMP_PKTS"; - case HCI_EV_MODE_CHANGE: return "HCI_EV_MODE_CHANGE"; - case HCI_EV_PIN_CODE_REQ: return "HCI_EV_PIN_CODE_REQ"; - case HCI_EV_LINK_KEY_REQ: return "HCI_EV_LINK_KEY_REQ"; - case HCI_EV_LINK_KEY_NOTIFY: return "HCI_EV_LINK_KEY_NOTIFY"; - case HCI_EV_CLOCK_OFFSET: return "HCI_EV_CLOCK_OFFSET"; - case HCI_EV_PKT_TYPE_CHANGE: return "HCI_EV_PKT_TYPE_CHANGE"; - case HCI_EV_PSCAN_REP_MODE: return "HCI_EV_PSCAN_REP_MODE"; - case HCI_EV_INQUIRY_RESULT_WITH_RSSI : return "HCI_EV_INQUIRY_RESULT_WITH_RSSI"; - case HCI_EV_REMOTE_EXT_FEATURES: return "HCI_EV_REMOTE_EXT_FEATURES"; - case HCI_EV_SYNC_CONN_COMPLETE: return "HCI_EV_SYNC_CONN_COMPLETE"; - case HCI_EV_SYNC_CONN_CHANGED: return "HCI_EV_SYNC_CONN_CHANGED"; - case HCI_EV_SNIFF_SUBRATE: return "HCI_EV_SNIFF_SUBRATE"; - case HCI_EV_EXTENDED_INQUIRY_RESULT: return "HCI_EV_EXTENDED_INQUIRY_RESULT"; - case HCI_EV_IO_CAPA_REQUEST: return "HCI_EV_IO_CAPA_REQUEST"; - case HCI_EV_SIMPLE_PAIR_COMPLETE: return "HCI_EV_SIMPLE_PAIR_COMPLETE"; - case HCI_EV_REMOTE_HOST_FEATURES: return "HCI_EV_REMOTE_HOST_FEATURES"; - } - return "Unknown Event"; -} - -const char* CmdStr(int cmd) -{ - switch (cmd) - { - // 0x04XX - case HCI_OP_INQUIRY: return "HCI_OP_INQUIRY"; - case HCI_OP_INQUIRY_CANCEL: return "HCI_OP_INQUIRY_CANCEL"; - case HCI_OP_EXIT_PERIODIC_INQ: return "HCI_OP_EXIT_PERIODIC_INQ"; - case HCI_OP_CREATE_CONN: return "HCI_OP_CREATE_CONN"; - case HCI_OP_DISCONNECT: return "HCI_OP_DISCONNECT"; - case HCI_OP_ADD_SCO: return "HCI_OP_ADD_SCO"; - case HCI_OP_CREATE_CONN_CANCEL: return "HCI_OP_CREATE_CONN_CANCEL"; - case HCI_OP_ACCEPT_CONN_REQ: return "HCI_OP_ACCEPT_CONN_REQ"; - case HCI_OP_REJECT_CONN_REQ: return "HCI_OP_REJECT_CONN_REQ"; - case HCI_OP_LINK_KEY_REPLY: return "HCI_OP_LINK_KEY_REPLY"; - case HCI_OP_LINK_KEY_NEG_REPLY: return "HCI_OP_LINK_KEY_NEG_REPLY"; - case HCI_OP_PIN_CODE_REPLY: return "HCI_OP_PIN_CODE_REPLY"; - case HCI_OP_PIN_CODE_NEG_REPLY: return "HCI_OP_PIN_CODE_NEG_REPLY"; - case HCI_OP_CHANGE_CONN_PTYPE: return "HCI_OP_CHANGE_CONN_PTYPE"; - case HCI_OP_AUTH_REQUESTED: return "HCI_OP_AUTH_REQUESTED"; - case HCI_OP_SET_CONN_ENCRYPT: return "HCI_OP_SET_CONN_ENCRYPT"; - case HCI_OP_CHANGE_CONN_LINK_KEY: return "HCI_OP_CHANGE_CONN_LINK_KEY"; - case HCI_OP_REMOTE_NAME_REQ: return "HCI_OP_REMOTE_NAME_REQ"; - case HCI_OP_REMOTE_NAME_REQ_CANCEL: return "HCI_OP_REMOTE_NAME_REQ_CANCEL"; - case HCI_OP_READ_REMOTE_FEATURES: return "HCI_OP_READ_REMOTE_FEATURES"; - case HCI_OP_READ_REMOTE_EXT_FEATURES: return "HCI_OP_READ_REMOTE_EXT_FEATURES"; - case HCI_OP_READ_REMOTE_VERSION: return "HCI_OP_READ_REMOTE_VERSION"; - case HCI_OP_SETUP_SYNC_CONN: return "HCI_OP_SETUP_SYNC_CONN"; - case HCI_OP_ACCEPT_SYNC_CONN_REQ: return "HCI_OP_ACCEPT_SYNC_CONN_REQ"; - case HCI_OP_REJECT_SYNC_CONN_REQ: return "HCI_OP_REJECT_SYNC_CONN_REQ"; - // 0x0CXX - case HCI_OP_SET_EVENT_MASK: return "HCI_OP_SET_EVENT_MASK"; - case HCI_OP_RESET: return "HCI_OP_RESET"; - case HCI_OP_SET_EVENT_FLT: return "HCI_OP_SET_EVENT_FLT"; - case HCI_OP_WRITE_LOCAL_NAME: return "HCI_OP_WRITE_LOCAL_NAME"; - case HCI_OP_READ_LOCAL_NAME: return "HCI_OP_READ_LOCAL_NAME"; - case HCI_OP_WRITE_CA_TIMEOUT: return "HCI_OP_WRITE_CA_TIMEOUT"; - case HCI_OP_WRITE_PG_TIMEOUT: return "HCI_OP_WRITE_PG_TIMEOUT"; - case HCI_OP_WRITE_SCAN_ENABLE: return "HCI_OP_WRITE_SCAN_ENABLE"; - case HCI_OP_READ_AUTH_ENABLE: return "HCI_OP_READ_AUTH_ENABLE"; - case HCI_OP_WRITE_AUTH_ENABLE: return "HCI_OP_WRITE_AUTH_ENABLE"; - case HCI_OP_READ_ENCRYPT_MODE: return "HCI_OP_READ_ENCRYPT_MODE"; - case HCI_OP_WRITE_ENCRYPT_MODE: return "HCI_OP_WRITE_ENCRYPT_MODE"; - case HCI_OP_READ_CLASS_OF_DEV: return "HCI_OP_READ_CLASS_OF_DEV"; - case HCI_OP_WRITE_CLASS_OF_DEV: return "HCI_OP_WRITE_CLASS_OF_DEV"; - case HCI_OP_READ_VOICE_SETTING: return "HCI_OP_READ_VOICE_SETTING"; - case HCI_OP_WRITE_VOICE_SETTING: return "HCI_OP_WRITE_VOICE_SETTING"; - case HCI_OP_HOST_BUFFER_SIZE: return "HCI_OP_HOST_BUFFER_SIZE"; - case HCI_OP_READ_SSP_MODE: return "HCI_OP_READ_SSP_MODE"; - case HCI_OP_WRITE_SSP_MODE: return "HCI_OP_WRITE_SSP_MODE"; - - // 10xx - case HCI_OP_READ_LOCAL_VERSION: return "HCI_OP_READ_LOCAL_VERSION"; - case HCI_OP_READ_LOCAL_COMMANDS: return "HCI_OP_READ_LOCAL_COMMANDS"; - case HCI_OP_READ_LOCAL_FEATURES: return "HCI_OP_READ_LOCAL_FEATURES"; - case HCI_OP_READ_LOCAL_EXT_FEATURES: return "HCI_OP_READ_LOCAL_EXT_FEATURES"; - case HCI_OP_READ_BUFFER_SIZE: return "HCI_OP_READ_BUFFER_SIZE"; - case HCI_OP_READ_BD_ADDR: return "HCI_OP_READ_BD_ADDR"; - } - return "Unknown Cmd"; -} - -const char* HCIErrStr(int err) -{ - switch (err) - { - case 0: return "OK"; - case HCI_UNKNOWN_HCI_COMMAND: return "HCI_UNKNOWN_HCI_COMMAND"; - case HCI_NO_CONNECTION: return "HCI_NO_CONNECTION"; - case HCI_HW_FAILURE: return "HCI_HW_FAILURE"; - case HCI_PAGE_TIMEOUT: return "HCI_PAGE_TIMEOUT"; - case HCI_AUTHENTICATION_FAILURE: return "HCI_AUTHENTICATION_FAILURE"; - case HCI_KEY_MISSING: return "HCI_KEY_MISSING"; - case HCI_MEMORY_FULL: return "HCI_MEMORY_FULL"; - case HCI_CONN_TIMEOUT: return "HCI_CONN_TIMEOUT"; - case HCI_MAX_NUMBER_OF_CONNECTIONS: return "HCI_CONN_TIMEOUT"; - case HCI_MAX_NUMBER_OF_SCO_CONNECTIONS_TO_DEVICE: return "HCI_MAX_NUMBER_OF_SCO_CONNECTIONS_TO_DEVICE"; - case HCI_ACL_CONNECTION_EXISTS: return "HCI_ACL_CONNECTION_EXISTS"; - case HCI_COMMAND_DISSALLOWED: return "HCI_COMMAND_DISSALLOWED"; - case HCI_HOST_REJECTED_DUE_TO_LIMITED_RESOURCES: return "HCI_HOST_REJECTED_DUE_TO_LIMITED_RESOURCES"; - case HCI_HOST_REJECTED_DUE_TO_SECURITY_REASONS: return "HCI_HOST_REJECTED_DUE_TO_SECURITY_REASONS"; - case HCI_HOST_REJECTED_DUE_TO_REMOTE_DEVICE_ONLY_PERSONAL_SERVICE: return "HCI_HOST_REJECTED_DUE_TO_REMOTE_DEVICE_ONLY_PERSONAL_SERVICE"; - case HCI_HOST_TIMEOUT: return "HCI_HOST_TIMEOUT"; - case HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE: return "HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE"; - case HCI_INVALID_HCI_COMMAND_PARAMETERS: return "HCI_INVALID_HCI_COMMAND_PARAMETERS"; - case HCI_OTHER_END_TERMINATED_CONN_USER_ENDED: return "HCI_OTHER_END_TERMINATED_CONN_USER_ENDED"; - case HCI_OTHER_END_TERMINATED_CONN_LOW_RESOURCES: return "HCI_OTHER_END_TERMINATED_CONN_LOW_RESOURCES"; - case HCI_OTHER_END_TERMINATED_CONN_ABOUT_TO_POWER_OFF: return "HCI_OTHER_END_TERMINATED_CONN_ABOUT_TO_POWER_OFF"; - case HCI_CONN_TERMINATED_BY_LOCAL_HOST: return "HCI_CONN_TERMINATED_BY_LOCAL_HOST"; - case HCI_REPETED_ATTEMPTS: return "HCI_REPETED_ATTEMPTS"; - case HCI_PAIRING_NOT_ALLOWED: return "HCI_PAIRING_NOT_ALLOWED"; - case HCI_UNKNOWN_LMP_PDU: return "HCI_UNKNOWN_LMP_PDU"; - case HCI_UNSUPPORTED_REMOTE_FEATURE: return "HCI_UNSUPPORTED_REMOTE_FEATURE"; - case HCI_SCO_OFFSET_REJECTED: return "HCI_SCO_OFFSET_REJECTED"; - case HCI_SCO_INTERVAL_REJECTED: return "HCI_SCO_INTERVAL_REJECTED"; - case HCI_SCO_AIR_MODE_REJECTED: return "HCI_SCO_AIR_MODE_REJECTED"; - case HCI_INVALID_LMP_PARAMETERS: return "HCI_INVALID_LMP_PARAMETERS"; - case HCI_UNSPECIFIED_ERROR: return "HCI_UNSPECIFIED_ERROR"; - case HCI_UNSUPPORTED_LMP_PARAMETER_VALUE: return "HCI_UNSUPPORTED_LMP_PARAMETER_VALUE"; - case HCI_ROLE_CHANGE_NOT_ALLOWED: return "HCI_ROLE_CHANGE_NOT_ALLOWED"; - case HCI_LMP_RESPONSE_TIMEOUT: return "HCI_LMP_RESPONSE_TIMEOUT"; - case HCI_LMP_ERROR_TRANSACTION_COLLISION: return "HCI_LMP_ERROR_TRANSACTION_COLLISION"; - case HCI_LMP_PDU_NOT_ALLOWED: return "HCI_LMP_PDU_NOT_ALLOWED"; - case HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE: return "HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE"; - case HCI_UNIT_KEY_USED: return "HCI_UNIT_KEY_USED"; - case HCI_QOS_NOT_SUPPORTED: return "HCI_QOS_NOT_SUPPORTED"; - case HCI_INSTANT_PASSED: return "HCI_INSTANT_PASSED"; - case HCI_PAIRING_UNIT_KEY_NOT_SUPPORTED: return "HCI_PAIRING_UNIT_KEY_NOT_SUPPORTED"; - }; - return "Unknow HCI err"; -}; - - -#endif // HCI_PRIVATE_H_INCLUDED
--- a/main.cpp Sat Apr 10 00:30:24 2010 +0000 +++ b/main.cpp Mon Apr 28 16:06:32 2014 +0000 @@ -1,121 +1,47 @@ -/* -Copyright (c) 2010 Peter Barrett - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - #include "mbed.h" #include "USBHost.h" #include "Utils.h" -#include "FATFileSystem.h" -int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize); -int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize); -int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize); +Serial pc(USBTX, USBRX); +Serial rob(p13, p14); +DigitalIn modeSw(p19); -class USBFileSystem : public FATFileSystem +// because of wiring on the breadboard, these pins are connected to 5V or +// ground (for the robot and BlueSMiRF connections) so configure them as inputs +// to avoid shorting anything out +DigitalIn di11(p11); +DigitalIn di12(p12); +DigitalIn di15(p15); +DigitalIn di16(p16); + +extern DigitalOut led1, led2, led3, led4; + +Ticker failsafeTick; +time_t lastReportTime; + +void failsafe() { - int _device; - u32 _blockSize; - u32 _blockCount; - -public: - USBFileSystem() : FATFileSystem("usb"),_device(0),_blockSize(0),_blockCount(0) + time_t t = time(NULL); + if (t > lastReportTime+1) { - } - - void SetDevice(int device) - { - _device = device; - } - - virtual int disk_initialize() - { - return MassStorage_ReadCapacity(_device,&_blockCount,&_blockSize); - } - - virtual int disk_write(const char *buffer, int block_number) - { - return MassStorage_Write(_device,block_number,1,(u8*)buffer,_blockSize); + rob.puts("stop\r"); + led3 = 1; } - - virtual int disk_read(char *buffer, int block_number) - { - return MassStorage_Read(_device,block_number,1,(u8*)buffer,_blockSize); - } - - virtual int disk_sectors() - { - return _blockCount; - } -}; - -void DumpFS(int depth, int count) -{ - DIR *d = opendir("/usb"); - if (!d) - { - printf("USB file system borked\n"); - return; - } - - printf("\nDumping root dir\n"); - struct dirent *p; - for(;;) - { - p = readdir(d); - if (!p) - break; - int len = sizeof( dirent); - printf("%s %d\n", p->d_name, len); - } - closedir(d); } -int OnDiskInsert(int device) -{ - USBFileSystem fs; - fs.SetDevice(device); - DumpFS(0,0); - return 0; -} - -/* - Simple test shell to exercise mouse,keyboard,mass storage and hubs. - Add 2 15k pulldown resistors between D+/D- and ground, attach a usb socket and have at it. -*/ - -Serial pc(USBTX, USBRX); -int GetConsoleChar() -{ - if (!pc.readable()) - return -1; - char c = pc.getc(); - pc.putc(c); // echo - return c; -} - -void TestShell(); +void RunWiimote(); +void RunAndroid(); int main() { - pc.baud(460800); - printf("BlueUSB\nNow get a bunch of usb or bluetooth things and plug them in\n"); - TestShell(); + modeSw.mode(PullDown); + rob.baud(19200); + set_time(9001); + failsafeTick.attach(&failsafe, 0.1); + + printf("Vroom Vroom!\n"); + if (modeSw) + RunWiimote(); + else + RunAndroid(); }