Janitorial, whitespace fixes. No new code.

This commit is contained in:
Andrew J. Kroll 2013-12-25 05:09:57 -05:00
parent b8fb19fb90
commit f1af9b08ec
54 changed files with 1370 additions and 1310 deletions

250
BTD.cpp
View file

@ -36,12 +36,12 @@ qNextPollTime(0), // Reset NextPollTime
pollInterval(0), pollInterval(0),
bPollEnable(false) // Don't start polling before dongle is connected bPollEnable(false) // Don't start polling before dongle is connected
{ {
for (uint8_t i = 0; i < BTD_NUMSERVICES; i++) for(uint8_t i = 0; i < BTD_NUMSERVICES; i++)
btService[i] = NULL; btService[i] = NULL;
Initialize(); // Set all variables, endpoint structs etc. to default values Initialize(); // Set all variables, endpoint structs etc. to default values
if (pUsb) // Register in USB subsystem if(pUsb) // Register in USB subsystem
pUsb->RegisterDeviceClass(this); // Set devConfig[] entry pUsb->RegisterDeviceClass(this); // Set devConfig[] entry
} }
@ -60,7 +60,7 @@ uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
Notify(PSTR("\r\nBTD ConfigureDevice"), 0x80); Notify(PSTR("\r\nBTD ConfigureDevice"), 0x80);
#endif #endif
if (bAddress) { // Check if address has already been assigned to an instance if(bAddress) { // Check if address has already been assigned to an instance
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress in use"), 0x80); Notify(PSTR("\r\nAddress in use"), 0x80);
#endif #endif
@ -68,14 +68,14 @@ uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
} }
p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned
if (!p) { if(!p) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
if (!p->epinfo) { if(!p->epinfo) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nepinfo is null"), 0x80); Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif #endif
@ -89,12 +89,12 @@ uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
p->epinfo = oldep_ptr; // Restore p->epinfo p->epinfo = oldep_ptr; // Restore p->epinfo
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class
if (!bAddress) { if(!bAddress) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nOut of address space"), 0x80); Notify(PSTR("\r\nOut of address space"), 0x80);
#endif #endif
@ -113,7 +113,7 @@ FailGetDevDescr:
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
NotifyFailGetDevDescr(rcode); NotifyFailGetDevDescr(rcode);
#endif #endif
if (rcode != hrJERR) if(rcode != hrJERR)
rcode = USB_ERROR_FailGetDevDescr; rcode = USB_ERROR_FailGetDevDescr;
Release(); Release();
return rcode; return rcode;
@ -130,7 +130,7 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
#endif #endif
UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
if (!p) { if(!p) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
@ -140,7 +140,7 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
delay(300); // Assign new address to the device delay(300); // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device
if (rcode) { if(rcode) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nsetAddr: "), 0x80); Notify(PSTR("\r\nsetAddr: "), 0x80);
D_PrintHex<uint8_t > (rcode, 0x80); D_PrintHex<uint8_t > (rcode, 0x80);
@ -156,7 +156,7 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = false; p->lowspeed = false;
p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
if (!p) { if(!p) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
@ -166,18 +166,18 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
if (VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) { if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) {
delay(100); delay(100);
rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); // We only need the Control endpoint, so we don't have to initialize the other endpoints of device rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); // We only need the Control endpoint, so we don't have to initialize the other endpoints of device
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (PID == PS3_PID || PID == PS3NAVIGATION_PID) { if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {
if (PID == PS3_PID) if(PID == PS3_PID)
Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
else // It must be a navigation controller else // It must be a navigation controller
Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
@ -185,18 +185,18 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
Notify(PSTR("\r\nMotion Controller Connected"), 0x80); Notify(PSTR("\r\nMotion Controller Connected"), 0x80);
#endif #endif
if (my_bdaddr[0] == 0x00 && my_bdaddr[1] == 0x00 && my_bdaddr[2] == 0x00 && my_bdaddr[3] == 0x00 && my_bdaddr[4] == 0x00 && my_bdaddr[5] == 0x00) { if(my_bdaddr[0] == 0x00 && my_bdaddr[1] == 0x00 && my_bdaddr[2] == 0x00 && my_bdaddr[3] == 0x00 && my_bdaddr[4] == 0x00 && my_bdaddr[5] == 0x00) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPlease plug in the dongle before trying to pair with the PS3 Controller\r\nor set the Bluetooth address in the constructor of the PS3BT class"), 0x80); Notify(PSTR("\r\nPlease plug in the dongle before trying to pair with the PS3 Controller\r\nor set the Bluetooth address in the constructor of the PS3BT class"), 0x80);
#endif #endif
} else { } else {
if (PID == PS3_PID || PID == PS3NAVIGATION_PID) if(PID == PS3_PID || PID == PS3NAVIGATION_PID)
setBdaddr(my_bdaddr); // Set internal Bluetooth address setBdaddr(my_bdaddr); // Set internal Bluetooth address
else else
setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
for (int8_t i = 5; i > 0; i--) { for(int8_t i = 5; i > 0; i--) {
D_PrintHex<uint8_t > (my_bdaddr[i], 0x80); D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
Notify(PSTR(":"), 0x80); Notify(PSTR(":"), 0x80);
} }
@ -212,31 +212,31 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Check if attached device is a Bluetooth dongle and fill endpoint data structure // Check if attached device is a Bluetooth dongle and fill endpoint data structure
// First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol // First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol
// And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order // And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order
for (uint8_t i = 0; i < num_of_conf; i++) { for(uint8_t i = 0; i < num_of_conf; i++) {
if (VID == IOGEAR_GBU521_VID && PID == IOGEAR_GBU521_PID) { if(VID == IOGEAR_GBU521_VID && PID == IOGEAR_GBU521_PID) {
ConfigDescParser<USB_CLASS_VENDOR_SPECIFIC, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Needed for the IOGEAR GBU521 ConfigDescParser<USB_CLASS_VENDOR_SPECIFIC, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Needed for the IOGEAR GBU521
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
} else { } else {
ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
} }
if (rcode) // Check error code if(rcode) // Check error code
goto FailGetConfDescr; goto FailGetConfDescr;
if (bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted if(bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted
break; break;
} }
if (bNumEP < BTD_MAX_ENDPOINTS) if(bNumEP < BTD_MAX_ENDPOINTS)
goto FailUnknownDevice; goto FailUnknownDevice;
// Assign epInfo to epinfo pointer - this time all 3 endpoins // Assign epInfo to epinfo pointer - this time all 3 endpoins
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum); rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command
@ -287,14 +287,14 @@ Fail:
void BTD::Initialize() { void BTD::Initialize() {
uint8_t i; uint8_t i;
for (i = 0; i < BTD_MAX_ENDPOINTS; i++) { for(i = 0; i < BTD_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
} }
for (i = 0; i < BTD_NUMSERVICES; i++) { for(i = 0; i < BTD_NUMSERVICES; i++) {
if (btService[i]) if(btService[i])
btService[i]->Reset(); // Reset all Bluetooth services btService[i]->Reset(); // Reset all Bluetooth services
} }
@ -315,17 +315,17 @@ void BTD::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
//ErrorMessage<uint8_t>(PSTR("Iface Num"),iface); //ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
//ErrorMessage<uint8_t>(PSTR("Alt.Set"),alt); //ErrorMessage<uint8_t>(PSTR("Alt.Set"),alt);
if (alt) // Wrong interface - by BT spec, no alt setting if(alt) // Wrong interface - by BT spec, no alt setting
return; return;
bConfNum = conf; bConfNum = conf;
uint8_t index; uint8_t index;
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { // Interrupt In endpoint found if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { // Interrupt In endpoint found
index = BTD_EVENT_PIPE; index = BTD_EVENT_PIPE;
epInfo[index].bmNakPower = USB_NAK_NOWAIT; epInfo[index].bmNakPower = USB_NAK_NOWAIT;
} else { } else {
if ((pep->bmAttributes & 0x02) == 2) // Bulk endpoint found if((pep->bmAttributes & 0x02) == 2) // Bulk endpoint found
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE; index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE;
else else
return; return;
@ -337,7 +337,7 @@ void BTD::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
PrintEndpointDescriptor(pep); PrintEndpointDescriptor(pep);
#endif #endif
if (pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
pollInterval = pep->bInterval; pollInterval = pep->bInterval;
bNumEP++; bNumEP++;
} }
@ -368,9 +368,9 @@ uint8_t BTD::Release() {
} }
uint8_t BTD::Poll() { uint8_t BTD::Poll() {
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
if (qNextPollTime <= millis()) { // Don't poll if shorter than polling interval if(qNextPollTime <= millis()) { // Don't poll if shorter than polling interval
qNextPollTime = millis() + pollInterval; // Set new poll time qNextPollTime = millis() + pollInterval; // Set new poll time
HCI_event_task(); // Poll the HCI event pipe HCI_event_task(); // Poll the HCI event pipe
HCI_task(); // HCI state machine HCI_task(); // HCI state machine
@ -383,16 +383,16 @@ void BTD::HCI_event_task() {
uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf); // Input on endpoint 1 uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf); // Input on endpoint 1
if (!rcode || rcode == hrNAK) { // Check for errors if(!rcode || rcode == hrNAK) { // Check for errors
switch (hcibuf[0]) { // Switch on event type switch(hcibuf[0]) { // Switch on event type
case EV_COMMAND_COMPLETE: case EV_COMMAND_COMPLETE:
if (!hcibuf[5]) { // Check if command succeeded if(!hcibuf[5]) { // Check if command succeeded
hci_set_flag(HCI_FLAG_CMD_COMPLETE); // Set command complete flag hci_set_flag(HCI_FLAG_CMD_COMPLETE); // Set command complete flag
if ((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // Parameters from read local version information if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // Parameters from read local version information
hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm
hci_set_flag(HCI_FLAG_READ_VERSION); hci_set_flag(HCI_FLAG_READ_VERSION);
} else if ((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // Parameters from read local bluetooth address } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // Parameters from read local bluetooth address
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
my_bdaddr[i] = hcibuf[6 + i]; my_bdaddr[i] = hcibuf[6 + i];
hci_set_flag(HCI_FLAG_READ_BDADDR); hci_set_flag(HCI_FLAG_READ_BDADDR);
} }
@ -400,7 +400,7 @@ void BTD::HCI_event_task() {
break; break;
case EV_COMMAND_STATUS: case EV_COMMAND_STATUS:
if (hcibuf[2]) { // Show status on serial if not OK if(hcibuf[2]) { // Show status on serial if not OK
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHCI Command Failed: "), 0x80); Notify(PSTR("\r\nHCI Command Failed: "), 0x80);
D_PrintHex<uint8_t > (hcibuf[2], 0x80); D_PrintHex<uint8_t > (hcibuf[2], 0x80);
@ -409,10 +409,10 @@ void BTD::HCI_event_task() {
break; break;
case EV_INQUIRY_COMPLETE: case EV_INQUIRY_COMPLETE:
if (inquiry_counter >= 5 && (pairWithWii || pairWithHIDDevice)) { if(inquiry_counter >= 5 && (pairWithWii || pairWithHIDDevice)) {
inquiry_counter = 0; inquiry_counter = 0;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (pairWithWii) if(pairWithWii)
Notify(PSTR("\r\nCouldn't find Wiimote"), 0x80); Notify(PSTR("\r\nCouldn't find Wiimote"), 0x80);
else else
Notify(PSTR("\r\nCouldn't find HID device"), 0x80); Notify(PSTR("\r\nCouldn't find HID device"), 0x80);
@ -427,38 +427,38 @@ void BTD::HCI_event_task() {
break; break;
case EV_INQUIRY_RESULT: case EV_INQUIRY_RESULT:
if (hcibuf[2]) { // Check that there is more than zero responses if(hcibuf[2]) { // Check that there is more than zero responses
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nNumber of responses: "), 0x80); Notify(PSTR("\r\nNumber of responses: "), 0x80);
Notify(hcibuf[2], 0x80); Notify(hcibuf[2], 0x80);
#endif #endif
for (uint8_t i = 0; i < hcibuf[2]; i++) { for(uint8_t i = 0; i < hcibuf[2]; i++) {
uint8_t offset = 8 * hcibuf[2] + 3 * i; uint8_t offset = 8 * hcibuf[2] + 3 * i;
uint8_t classOfDevice[3]; uint8_t classOfDevice[3];
for (uint8_t j = 0; j < 3; j++) for(uint8_t j = 0; j < 3; j++)
classOfDevice[j] = hcibuf[j + 4 + offset]; classOfDevice[j] = hcibuf[j + 4 + offset];
if (pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information
if (classOfDevice[0] & 0x08) // Check if it's the new Wiimote with motion plus inside that was detected if(classOfDevice[0] & 0x08) // Check if it's the new Wiimote with motion plus inside that was detected
motionPlusInside = true; motionPlusInside = true;
else else
motionPlusInside = false; motionPlusInside = false;
for (uint8_t j = 0; j < 6; j++) for(uint8_t j = 0; j < 6; j++)
disc_bdaddr[j] = hcibuf[j + 3 + 6 * i]; disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];
hci_set_flag(HCI_FLAG_DEVICE_FOUND); hci_set_flag(HCI_FLAG_DEVICE_FOUND);
break; break;
} else if (pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC0)) { // Check if it is a mouse or keyboard - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html } else if(pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC0)) { // Check if it is a mouse or keyboard - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (classOfDevice[0] & 0x80) if(classOfDevice[0] & 0x80)
Notify(PSTR("\r\nMouse found"), 0x80); Notify(PSTR("\r\nMouse found"), 0x80);
if (classOfDevice[0] & 0x40) if(classOfDevice[0] & 0x40)
Notify(PSTR("\r\nKeyboard found"), 0x80); Notify(PSTR("\r\nKeyboard found"), 0x80);
#endif #endif
for (uint8_t j = 0; j < 6; j++) for(uint8_t j = 0; j < 6; j++)
disc_bdaddr[j] = hcibuf[j + 3 + 6 * i]; disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];
hci_set_flag(HCI_FLAG_DEVICE_FOUND); hci_set_flag(HCI_FLAG_DEVICE_FOUND);
@ -479,7 +479,7 @@ void BTD::HCI_event_task() {
case EV_CONNECT_COMPLETE: case EV_CONNECT_COMPLETE:
hci_set_flag(HCI_FLAG_CONNECT_EVENT); hci_set_flag(HCI_FLAG_CONNECT_EVENT);
if (!hcibuf[2]) { // Check if connected OK if(!hcibuf[2]) { // Check if connected OK
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nConnection established"), 0x80); Notify(PSTR("\r\nConnection established"), 0x80);
#endif #endif
@ -495,17 +495,17 @@ void BTD::HCI_event_task() {
break; break;
case EV_DISCONNECT_COMPLETE: case EV_DISCONNECT_COMPLETE:
if (!hcibuf[2]) { // Check if disconnected OK if(!hcibuf[2]) { // Check if disconnected OK
hci_set_flag(HCI_FLAG_DISCONNECT_COMPLETE); // Set disconnect command complete flag hci_set_flag(HCI_FLAG_DISCONNECT_COMPLETE); // Set disconnect command complete flag
hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); // Clear connection complete flag hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); // Clear connection complete flag
} }
break; break;
case EV_REMOTE_NAME_COMPLETE: case EV_REMOTE_NAME_COMPLETE:
if (!hcibuf[2]) { // Check if reading is OK if(!hcibuf[2]) { // Check if reading is OK
for (uint8_t i = 0; i < min(sizeof (remote_name), sizeof (hcibuf) - 9); i++) { for(uint8_t i = 0; i < min(sizeof (remote_name), sizeof (hcibuf) - 9); i++) {
remote_name[i] = hcibuf[9 + i]; remote_name[i] = hcibuf[9 + i];
if (remote_name[i] == '\0') // End of string if(remote_name[i] == '\0') // End of string
break; break;
} }
hci_set_flag(HCI_FLAG_REMOTE_NAME_COMPLETE); hci_set_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);
@ -513,14 +513,14 @@ void BTD::HCI_event_task() {
break; break;
case EV_INCOMING_CONNECT: case EV_INCOMING_CONNECT:
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
disc_bdaddr[i] = hcibuf[i + 2]; disc_bdaddr[i] = hcibuf[i + 2];
if ((hcibuf[9] & 0x05) && (hcibuf[8] & 0xC0)) { // Check if it is a mouse or keyboard if((hcibuf[9] & 0x05) && (hcibuf[8] & 0xC0)) { // Check if it is a mouse or keyboard
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (hcibuf[8] & 0x80) if(hcibuf[8] & 0x80)
Notify(PSTR("\r\nMouse is connecting"), 0x80); Notify(PSTR("\r\nMouse is connecting"), 0x80);
if (hcibuf[8] & 0x40) if(hcibuf[8] & 0x40)
Notify(PSTR("\r\nKeyboard is connecting"), 0x80); Notify(PSTR("\r\nKeyboard is connecting"), 0x80);
#endif #endif
incomingHIDDevice = true; incomingHIDDevice = true;
@ -538,12 +538,12 @@ void BTD::HCI_event_task() {
break; break;
case EV_PIN_CODE_REQUEST: case EV_PIN_CODE_REQUEST:
if (pairWithWii) { if(pairWithWii) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPairing with wiimote"), 0x80); Notify(PSTR("\r\nPairing with wiimote"), 0x80);
#endif #endif
hci_pin_code_request_reply(); hci_pin_code_request_reply();
} else if (btdPin != NULL) { } else if(btdPin != NULL) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80); Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80);
NotifyStr(btdPin, 0x80); NotifyStr(btdPin, 0x80);
@ -565,12 +565,12 @@ void BTD::HCI_event_task() {
break; break;
case EV_AUTHENTICATION_COMPLETE: case EV_AUTHENTICATION_COMPLETE:
if (pairWithWii && !connectToWii) { if(pairWithWii && !connectToWii) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80); Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80);
#endif #endif
connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device
} else if (pairWithHIDDevice && !connectToHIDDevice) { } else if(pairWithHIDDevice && !connectToHIDDevice) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPairing successful with HID device"), 0x80); Notify(PSTR("\r\nPairing successful with HID device"), 0x80);
#endif #endif
@ -592,7 +592,7 @@ void BTD::HCI_event_task() {
break; break;
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
default: default:
if (hcibuf[0] != 0x00) { if(hcibuf[0] != 0x00) {
Notify(PSTR("\r\nUnmanaged HCI Event: "), 0x80); Notify(PSTR("\r\nUnmanaged HCI Event: "), 0x80);
D_PrintHex<uint8_t > (hcibuf[0], 0x80); D_PrintHex<uint8_t > (hcibuf[0], 0x80);
} }
@ -610,10 +610,10 @@ void BTD::HCI_event_task() {
/* Poll Bluetooth and print result */ /* Poll Bluetooth and print result */
void BTD::HCI_task() { void BTD::HCI_task() {
switch (hci_state) { switch(hci_state) {
case HCI_INIT_STATE: case HCI_INIT_STATE:
hci_counter++; hci_counter++;
if (hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events if(hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events
hci_reset(); hci_reset();
hci_state = HCI_RESET_STATE; hci_state = HCI_RESET_STATE;
hci_counter = 0; hci_counter = 0;
@ -622,16 +622,16 @@ void BTD::HCI_task() {
case HCI_RESET_STATE: case HCI_RESET_STATE:
hci_counter++; hci_counter++;
if (hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
hci_counter = 0; hci_counter = 0;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHCI Reset complete"), 0x80); Notify(PSTR("\r\nHCI Reset complete"), 0x80);
#endif #endif
hci_state = HCI_CLASS_STATE; hci_state = HCI_CLASS_STATE;
hci_write_class_of_device(); hci_write_class_of_device();
} else if (hci_counter > hci_num_reset_loops) { } else if(hci_counter > hci_num_reset_loops) {
hci_num_reset_loops *= 10; hci_num_reset_loops *= 10;
if (hci_num_reset_loops > 2000) if(hci_num_reset_loops > 2000)
hci_num_reset_loops = 2000; hci_num_reset_loops = 2000;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nNo response to HCI Reset"), 0x80); Notify(PSTR("\r\nNo response to HCI Reset"), 0x80);
@ -642,7 +642,7 @@ void BTD::HCI_task() {
break; break;
case HCI_CLASS_STATE: case HCI_CLASS_STATE:
if (hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nWrite class of device"), 0x80); Notify(PSTR("\r\nWrite class of device"), 0x80);
#endif #endif
@ -652,10 +652,10 @@ void BTD::HCI_task() {
break; break;
case HCI_BDADDR_STATE: case HCI_BDADDR_STATE:
if (hci_check_flag(HCI_FLAG_READ_BDADDR)) { if(hci_check_flag(HCI_FLAG_READ_BDADDR)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nLocal Bluetooth Address: "), 0x80); Notify(PSTR("\r\nLocal Bluetooth Address: "), 0x80);
for (int8_t i = 5; i > 0; i--) { for(int8_t i = 5; i > 0; i--) {
D_PrintHex<uint8_t > (my_bdaddr[i], 0x80); D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
Notify(PSTR(":"), 0x80); Notify(PSTR(":"), 0x80);
} }
@ -667,8 +667,8 @@ void BTD::HCI_task() {
break; break;
case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class
if (hci_check_flag(HCI_FLAG_READ_VERSION)) { if(hci_check_flag(HCI_FLAG_READ_VERSION)) {
if (btdName != NULL) { if(btdName != NULL) {
hci_set_local_name(btdName); hci_set_local_name(btdName);
hci_state = HCI_SET_NAME_STATE; hci_state = HCI_SET_NAME_STATE;
} else } else
@ -677,7 +677,7 @@ void BTD::HCI_task() {
break; break;
case HCI_SET_NAME_STATE: case HCI_SET_NAME_STATE:
if (hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nThe name is set to: "), 0x80); Notify(PSTR("\r\nThe name is set to: "), 0x80);
NotifyStr(btdName, 0x80); NotifyStr(btdName, 0x80);
@ -687,9 +687,9 @@ void BTD::HCI_task() {
break; break;
case HCI_CHECK_DEVICE_SERVICE: case HCI_CHECK_DEVICE_SERVICE:
if (pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (pairWithWii) if(pairWithWii)
Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press sync if you are using a Wii U Pro Controller"), 0x80); Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press sync if you are using a Wii U Pro Controller"), 0x80);
else else
Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80); Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80);
@ -701,27 +701,27 @@ void BTD::HCI_task() {
break; break;
case HCI_INQUIRY_STATE: case HCI_INQUIRY_STATE:
if (hci_check_flag(HCI_FLAG_DEVICE_FOUND)) { if(hci_check_flag(HCI_FLAG_DEVICE_FOUND)) {
hci_inquiry_cancel(); // Stop inquiry hci_inquiry_cancel(); // Stop inquiry
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (pairWithWii) if(pairWithWii)
Notify(PSTR("\r\nWiimote found"), 0x80); Notify(PSTR("\r\nWiimote found"), 0x80);
else else
Notify(PSTR("\r\nHID device found"), 0x80); Notify(PSTR("\r\nHID device found"), 0x80);
Notify(PSTR("\r\nNow just create the instance like so:"), 0x80); Notify(PSTR("\r\nNow just create the instance like so:"), 0x80);
if (pairWithWii) if(pairWithWii)
Notify(PSTR("\r\nWII Wii(&Btd);"), 0x80); Notify(PSTR("\r\nWII Wii(&Btd);"), 0x80);
else else
Notify(PSTR("\r\nBTHID hid(&Btd);"), 0x80); Notify(PSTR("\r\nBTHID hid(&Btd);"), 0x80);
Notify(PSTR("\r\nAnd then press any button on the "), 0x80); Notify(PSTR("\r\nAnd then press any button on the "), 0x80);
if (pairWithWii) if(pairWithWii)
Notify(PSTR("Wiimote"), 0x80); Notify(PSTR("Wiimote"), 0x80);
else else
Notify(PSTR("device"), 0x80); Notify(PSTR("device"), 0x80);
#endif #endif
if (motionPlusInside) { if(motionPlusInside) {
hci_remote_name(); // We need to know the name to distinguish between a Wiimote and a Wii U Pro Controller hci_remote_name(); // We need to know the name to distinguish between a Wiimote and a Wii U Pro Controller
hci_state = HCI_REMOTE_NAME_STATE; hci_state = HCI_REMOTE_NAME_STATE;
} else } else
@ -730,9 +730,9 @@ void BTD::HCI_task() {
break; break;
case HCI_CONNECT_DEVICE_STATE: case HCI_CONNECT_DEVICE_STATE:
if (hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (pairWithWii) if(pairWithWii)
Notify(PSTR("\r\nConnecting to Wiimote"), 0x80); Notify(PSTR("\r\nConnecting to Wiimote"), 0x80);
else else
Notify(PSTR("\r\nConnecting to HID device"), 0x80); Notify(PSTR("\r\nConnecting to HID device"), 0x80);
@ -743,10 +743,10 @@ void BTD::HCI_task() {
break; break;
case HCI_CONNECTED_DEVICE_STATE: case HCI_CONNECTED_DEVICE_STATE:
if (hci_check_flag(HCI_FLAG_CONNECT_EVENT)) { if(hci_check_flag(HCI_FLAG_CONNECT_EVENT)) {
if (hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) { if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (pairWithWii) if(pairWithWii)
Notify(PSTR("\r\nConnected to Wiimote"), 0x80); Notify(PSTR("\r\nConnected to Wiimote"), 0x80);
else else
Notify(PSTR("\r\nConnected to HID device"), 0x80); Notify(PSTR("\r\nConnected to HID device"), 0x80);
@ -763,7 +763,7 @@ void BTD::HCI_task() {
break; break;
case HCI_SCANNING_STATE: case HCI_SCANNING_STATE:
if (!connectToWii && !pairWithWii && !connectToHIDDevice && !pairWithHIDDevice) { if(!connectToWii && !pairWithWii && !connectToHIDDevice && !pairWithHIDDevice) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80); Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80);
#endif #endif
@ -774,38 +774,38 @@ void BTD::HCI_task() {
break; break;
case HCI_CONNECT_IN_STATE: case HCI_CONNECT_IN_STATE:
if (hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) { if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) {
watingForConnection = false; watingForConnection = false;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nIncoming Connection Request"), 0x80); Notify(PSTR("\r\nIncoming Connection Request"), 0x80);
#endif #endif
hci_remote_name(); hci_remote_name();
hci_state = HCI_REMOTE_NAME_STATE; hci_state = HCI_REMOTE_NAME_STATE;
} else if (hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) } else if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE))
hci_state = HCI_DISCONNECT_STATE; hci_state = HCI_DISCONNECT_STATE;
break; break;
case HCI_REMOTE_NAME_STATE: case HCI_REMOTE_NAME_STATE:
if (hci_check_flag(HCI_FLAG_REMOTE_NAME_COMPLETE)) { if(hci_check_flag(HCI_FLAG_REMOTE_NAME_COMPLETE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nRemote Name: "), 0x80); Notify(PSTR("\r\nRemote Name: "), 0x80);
for (uint8_t i = 0; i < 30; i++) { for(uint8_t i = 0; i < 30; i++) {
if (remote_name[i] == '\0') // End of string if(remote_name[i] == '\0') // End of string
break; break;
Notifyc(remote_name[i], 0x80); Notifyc(remote_name[i], 0x80);
} }
#endif #endif
if (strncmp((const char*)remote_name, "Nintendo", 8) == 0) { if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) {
incomingWii = true; incomingWii = true;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nWiimote is connecting"), 0x80); Notify(PSTR("\r\nWiimote is connecting"), 0x80);
#endif #endif
if (strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) { if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR(" with Motion Plus Inside"), 0x80); Notify(PSTR(" with Motion Plus Inside"), 0x80);
#endif #endif
motionPlusInside = true; motionPlusInside = true;
} else if (strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) { } else if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR(" - Wii U Pro Controller"), 0x80); Notify(PSTR(" - Wii U Pro Controller"), 0x80);
#endif #endif
@ -816,7 +816,7 @@ void BTD::HCI_task() {
wiiUProController = false; wiiUProController = false;
} }
} }
if (pairWithWii && motionPlusInside) if(pairWithWii && motionPlusInside)
hci_state = HCI_CONNECT_DEVICE_STATE; hci_state = HCI_CONNECT_DEVICE_STATE;
else { else {
hci_accept_connection(); hci_accept_connection();
@ -826,10 +826,10 @@ void BTD::HCI_task() {
break; break;
case HCI_CONNECTED_STATE: case HCI_CONNECTED_STATE:
if (hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) { if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nConnected to Device: "), 0x80); Notify(PSTR("\r\nConnected to Device: "), 0x80);
for (int8_t i = 5; i > 0; i--) { for(int8_t i = 5; i > 0; i--) {
D_PrintHex<uint8_t > (disc_bdaddr[i], 0x80); D_PrintHex<uint8_t > (disc_bdaddr[i], 0x80);
Notify(PSTR(":"), 0x80); Notify(PSTR(":"), 0x80);
} }
@ -847,14 +847,14 @@ void BTD::HCI_task() {
case HCI_DONE_STATE: case HCI_DONE_STATE:
hci_counter++; hci_counter++;
if (hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started if(hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started
hci_counter = 0; hci_counter = 0;
hci_state = HCI_SCANNING_STATE; hci_state = HCI_SCANNING_STATE;
} }
break; break;
case HCI_DISCONNECT_STATE: case HCI_DISCONNECT_STATE:
if (hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) { if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80); Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80);
#endif #endif
@ -879,22 +879,22 @@ void BTD::ACL_event_task() {
uint16_t length = BULK_MAXPKTSIZE; uint16_t length = BULK_MAXPKTSIZE;
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf); // Input on endpoint 2 uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf); // Input on endpoint 2
if (!rcode) { // Check for errors if(!rcode) { // Check for errors
if (length > 0) { // Check if any data was read if(length > 0) { // Check if any data was read
for (uint8_t i = 0; i < BTD_NUMSERVICES; i++) { for(uint8_t i = 0; i < BTD_NUMSERVICES; i++) {
if (btService[i]) if(btService[i])
btService[i]->ACLData(l2capinbuf); btService[i]->ACLData(l2capinbuf);
} }
} }
} }
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
else if (rcode != hrNAK) { else if(rcode != hrNAK) {
Notify(PSTR("\r\nACL data in error: "), 0x80); Notify(PSTR("\r\nACL data in error: "), 0x80);
D_PrintHex<uint8_t > (rcode, 0x80); D_PrintHex<uint8_t > (rcode, 0x80);
} }
#endif #endif
for (uint8_t i = 0; i < BTD_NUMSERVICES; i++) for(uint8_t i = 0; i < BTD_NUMSERVICES; i++)
if (btService[i]) if(btService[i])
btService[i]->Run(); btService[i]->Run();
} }
@ -921,7 +921,7 @@ void BTD::hci_write_scan_enable() {
hcibuf[0] = 0x1A; // HCI OCF = 1A hcibuf[0] = 0x1A; // HCI OCF = 1A
hcibuf[1] = 0x03 << 2; // HCI OGF = 3 hcibuf[1] = 0x03 << 2; // HCI OGF = 3
hcibuf[2] = 0x01; // parameter length = 1 hcibuf[2] = 0x01; // parameter length = 1
if (btdName != NULL) if(btdName != NULL)
hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled. hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled.
else else
hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled. hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled.
@ -996,7 +996,7 @@ void BTD::hci_set_local_name(const char* name) {
hcibuf[1] = 0x03 << 2; // HCI OGF = 3 hcibuf[1] = 0x03 << 2; // HCI OGF = 3
hcibuf[2] = strlen(name) + 1; // parameter length = the length of the string + end byte hcibuf[2] = strlen(name) + 1; // parameter length = the length of the string + end byte
uint8_t i; uint8_t i;
for (i = 0; i < strlen(name); i++) for(i = 0; i < strlen(name); i++)
hcibuf[i + 3] = name[i]; hcibuf[i + 3] = name[i];
hcibuf[i + 3] = 0x00; // End of string hcibuf[i + 3] = 0x00; // End of string
@ -1061,26 +1061,26 @@ void BTD::hci_pin_code_request_reply() {
hcibuf[6] = disc_bdaddr[3]; hcibuf[6] = disc_bdaddr[3];
hcibuf[7] = disc_bdaddr[4]; hcibuf[7] = disc_bdaddr[4];
hcibuf[8] = disc_bdaddr[5]; hcibuf[8] = disc_bdaddr[5];
if (pairWithWii) { if(pairWithWii) {
hcibuf[9] = 6; // Pin length is the length of the Bluetooth address hcibuf[9] = 6; // Pin length is the length of the Bluetooth address
if (wiiUProController) { if(wiiUProController) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nParing with Wii U Pro Controller"), 0x80); Notify(PSTR("\r\nParing with Wii U Pro Controller"), 0x80);
#endif #endif
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards
} else { } else {
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
hcibuf[10 + i] = disc_bdaddr[i]; // The pin is the Wiimote's Bluetooth address backwards hcibuf[10 + i] = disc_bdaddr[i]; // The pin is the Wiimote's Bluetooth address backwards
} }
for (uint8_t i = 16; i < 26; i++) for(uint8_t i = 16; i < 26; i++)
hcibuf[i] = 0x00; // The rest should be 0 hcibuf[i] = 0x00; // The rest should be 0
} else { } else {
hcibuf[9] = strlen(btdPin); // Length of pin hcibuf[9] = strlen(btdPin); // Length of pin
uint8_t i; uint8_t i;
for (i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16 for(i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16
hcibuf[i + 10] = btdPin[i]; hcibuf[i + 10] = btdPin[i];
for (; i < 16; i++) for(; i < 16; i++)
hcibuf[i + 10] = 0x00; // The rest should be 0 hcibuf[i + 10] = 0x00; // The rest should be 0
} }
@ -1184,11 +1184,11 @@ void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t
buf[6] = channelLow; buf[6] = channelLow;
buf[7] = channelHigh; buf[7] = channelHigh;
for (uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame for(uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame
buf[8 + i] = data[i]; buf[8 + i] = data[i];
uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf); uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf);
if (rcode) { if(rcode) {
delay(100); // This small delay prevents it from overflowing if it fails delay(100); // This small delay prevents it from overflowing if it fails
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80); Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80);
@ -1317,7 +1317,7 @@ void BTD::setBdaddr(uint8_t* bdaddr) {
buf[0] = 0x01; buf[0] = 0x01;
buf[1] = 0x00; buf[1] = 0x00;
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
@ -1333,7 +1333,7 @@ void BTD::setMoveBdaddr(uint8_t* bdaddr) {
buf[9] = 0x02; buf[9] = 0x02;
buf[10] = 0x12; buf[10] = 0x12;
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
buf[i + 1] = bdaddr[i]; buf[i + 1] = bdaddr[i];
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data

11
BTD.h
View file

@ -262,12 +262,15 @@ public:
virtual bool isReady() { virtual bool isReady() {
return bPollEnable; return bPollEnable;
}; };
/** /**
* Used by the USB core to check what this driver support. * Used by the USB core to check what this driver support.
* @param klass The device's USB class. * @param klass The device's USB class.
* @return Returns true if the device's USB class matches this driver. * @return Returns true if the device's USB class matches this driver.
*/ */
virtual boolean DEVCLASSOK(uint8_t klass) { return (klass == USB_CLASS_WIRELESS_CTRL); } virtual boolean DEVCLASSOK(uint8_t klass) {
return (klass == USB_CLASS_WIRELESS_CTRL);
}
/** /**
* Used by the USB core to check what this driver support. * Used by the USB core to check what this driver support.
@ -277,10 +280,10 @@ public:
* @return Returns true if the device's VID and PID matches this driver. * @return Returns true if the device's VID and PID matches this driver.
*/ */
virtual boolean VIDPIDOK(uint16_t vid, uint16_t pid) { virtual boolean VIDPIDOK(uint16_t vid, uint16_t pid) {
if (vid == IOGEAR_GBU521_VID && pid == IOGEAR_GBU521_PID) if(vid == IOGEAR_GBU521_VID && pid == IOGEAR_GBU521_PID)
return true; return true;
if (my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { // Check if Bluetooth address is set if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { // Check if Bluetooth address is set
if (vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID)) if(vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID))
return true; return true;
} }
return false; return false;

112
BTHID.cpp
View file

@ -22,16 +22,15 @@
BTHID::BTHID(BTD *p, bool pair, const char *pin) : BTHID::BTHID(BTD *p, bool pair, const char *pin) :
pBtd(p), // pointer to USB class instance - mandatory pBtd(p), // pointer to USB class instance - mandatory
protocolMode(HID_BOOT_PROTOCOL) protocolMode(HID_BOOT_PROTOCOL) {
{ for(uint8_t i = 0; i < NUM_PARSERS; i++)
for (uint8_t i = 0; i < NUM_PARSERS; i++)
pRptParser[i] = NULL; pRptParser[i] = NULL;
if (pBtd) if(pBtd)
pBtd->registerServiceClass(this); // Register it as a Bluetooth service pBtd->registerServiceClass(this); // Register it as a Bluetooth service
pBtd->pairWithHIDDevice = pair; pBtd->pairWithHIDDevice = pair;
pBtd->btdPin= pin; pBtd->btdPin = pin;
/* Set device cid for the control and intterrupt channelse - LSB */ /* Set device cid for the control and intterrupt channelse - LSB */
control_dcid[0] = 0x70; // 0x0070 control_dcid[0] = 0x70; // 0x0070
@ -57,9 +56,9 @@ void BTHID::disconnect() { // Use this void to disconnect any of the controllers
} }
void BTHID::ACLData(uint8_t* l2capinbuf) { void BTHID::ACLData(uint8_t* l2capinbuf) {
if (!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) { if(!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) {
if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
pBtd->incomingHIDDevice = false; pBtd->incomingHIDDevice = false;
pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
activeConnection = true; activeConnection = true;
@ -68,9 +67,9 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
} }
} }
} }
if ((l2capinbuf[0] | (uint16_t)l2capinbuf[1] << 8) == (hci_handle | 0x2000U)) { // acl_handle_ok or it's a new connection if((l2capinbuf[0] | (uint16_t)l2capinbuf[1] << 8) == (hci_handle | 0x2000U)) { // acl_handle_ok or it's a new connection
if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
@ -85,15 +84,15 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
#endif #endif
} else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {
if (((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success
if (l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) {
//Notify(PSTR("\r\nHID Control Connection Complete"), 0x80); //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
control_scid[0] = l2capinbuf[12]; control_scid[0] = l2capinbuf[12];
control_scid[1] = l2capinbuf[13]; control_scid[1] = l2capinbuf[13];
l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED); l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED);
} else if (l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {
//Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80); //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
interrupt_scid[0] = l2capinbuf[12]; interrupt_scid[0] = l2capinbuf[12];
@ -101,7 +100,7 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED); l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED);
} }
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
@ -114,46 +113,46 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR(" Identifier: "), 0x80); Notify(PSTR(" Identifier: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
#endif #endif
if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
control_scid[0] = l2capinbuf[14]; control_scid[0] = l2capinbuf[14];
control_scid[1] = l2capinbuf[15]; control_scid[1] = l2capinbuf[15];
l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);
} else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
interrupt_scid[0] = l2capinbuf[14]; interrupt_scid[0] = l2capinbuf[14];
interrupt_scid[1] = l2capinbuf[15]; interrupt_scid[1] = l2capinbuf[15];
l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);
} }
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
#endif #endif
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
Reset(); Reset();
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
#endif #endif
@ -161,12 +160,12 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
Reset(); Reset();
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
//Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);
} else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
//Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);
@ -179,27 +178,27 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
D_PrintHex<uint8_t > (l2capinbuf[8], 0x80); D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
} }
#endif #endif
} else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
#ifdef PRINTREPORT #ifdef PRINTREPORT
Notify(PSTR("\r\nL2CAP Interrupt: "), 0x80); Notify(PSTR("\r\nL2CAP Interrupt: "), 0x80);
for (uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
#endif #endif
if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
switch (l2capinbuf[9]) { switch(l2capinbuf[9]) {
case 0x01: // Keyboard events case 0x01: // Keyboard events
if (pRptParser[KEYBOARD_PARSER_ID]) { if(pRptParser[KEYBOARD_PARSER_ID]) {
uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<HID *> (this), 0, (uint8_t) length, &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)length, &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
} }
break; break;
case 0x02: // Mouse events case 0x02: // Mouse events
if (pRptParser[MOUSE_PARSER_ID]) { if(pRptParser[MOUSE_PARSER_ID]) {
uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<HID *> (this), 0, (uint8_t) length, &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)length, &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
} }
break; break;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -210,10 +209,10 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
#endif #endif
} }
} }
} else if (l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control
#ifdef PRINTREPORT #ifdef PRINTREPORT
Notify(PSTR("\r\nL2CAP Control: "), 0x80); Notify(PSTR("\r\nL2CAP Control: "), 0x80);
for (uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -228,7 +227,7 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR("\r\nData: "), 0x80); Notify(PSTR("\r\nData: "), 0x80);
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
for (uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -239,10 +238,10 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
} }
void BTHID::L2CAP_task() { void BTHID::L2CAP_task() {
switch (l2cap_state) { switch(l2cap_state) {
/* These states are used if the HID device is the host */ /* These states are used if the HID device is the host */
case L2CAP_CONTROL_SUCCESS: case L2CAP_CONTROL_SUCCESS:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
#endif #endif
@ -252,7 +251,7 @@ void BTHID::L2CAP_task() {
break; break;
case L2CAP_INTERRUPT_SETUP: case L2CAP_INTERRUPT_SETUP:
if (l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
#endif #endif
@ -269,7 +268,7 @@ void BTHID::L2CAP_task() {
/* These states are used if the Arduino is the host */ /* These states are used if the Arduino is the host */
case L2CAP_CONTROL_CONNECT_REQUEST: case L2CAP_CONTROL_CONNECT_REQUEST:
if (l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) { if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); Notify(PSTR("\r\nSend HID Control Config Request"), 0x80);
#endif #endif
@ -280,7 +279,7 @@ void BTHID::L2CAP_task() {
break; break;
case L2CAP_CONTROL_CONFIG_REQUEST: case L2CAP_CONTROL_CONFIG_REQUEST:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
setProtocol(); // Set protocol before establishing HID interrupt channel setProtocol(); // Set protocol before establishing HID interrupt channel
delay(1); // Short delay between commands - just to be sure delay(1); // Short delay between commands - just to be sure
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -293,7 +292,7 @@ void BTHID::L2CAP_task() {
break; break;
case L2CAP_INTERRUPT_CONNECT_REQUEST: case L2CAP_INTERRUPT_CONNECT_REQUEST:
if (l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) { if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80);
#endif #endif
@ -304,7 +303,7 @@ void BTHID::L2CAP_task() {
break; break;
case L2CAP_INTERRUPT_CONFIG_REQUEST: case L2CAP_INTERRUPT_CONFIG_REQUEST:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Channels Established"), 0x80); Notify(PSTR("\r\nHID Channels Established"), 0x80);
#endif #endif
@ -320,7 +319,7 @@ void BTHID::L2CAP_task() {
break; break;
case L2CAP_INTERRUPT_DISCONNECT: case L2CAP_INTERRUPT_DISCONNECT:
if (l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) { if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
#endif #endif
@ -331,7 +330,7 @@ void BTHID::L2CAP_task() {
break; break;
case L2CAP_CONTROL_DISCONNECT: case L2CAP_CONTROL_DISCONNECT:
if (l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
#endif #endif
@ -345,9 +344,9 @@ void BTHID::L2CAP_task() {
} }
void BTHID::Run() { void BTHID::Run() {
switch (l2cap_state) { switch(l2cap_state) {
case L2CAP_WAIT: case L2CAP_WAIT:
if (pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) { if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) {
pBtd->l2capConnectionClaimed = true; pBtd->l2capConnectionClaimed = true;
activeConnection = true; activeConnection = true;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -358,7 +357,7 @@ void BTHID::Run() {
identifier = 0; identifier = 0;
pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM); pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM);
l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;
} else if (l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
#endif #endif
@ -376,6 +375,7 @@ void BTHID::Run() {
/************************************************************/ /************************************************************/
/* HID Commands */ /* HID Commands */
/************************************************************/ /************************************************************/
void BTHID::setProtocol() { void BTHID::setProtocol() {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST

View file

@ -48,6 +48,7 @@ public:
virtual void Reset(); virtual void Reset();
/** Used this to disconnect any of the controllers. */ /** Used this to disconnect any of the controllers. */
virtual void disconnect(); virtual void disconnect();
/**@}*/ /**@}*/
HIDReportParser *GetReportParser(uint8_t id) { HIDReportParser *GetReportParser(uint8_t id) {
@ -71,7 +72,7 @@ public:
/** Call this to start the paring sequence with a controller */ /** Call this to start the paring sequence with a controller */
void pair(void) { void pair(void) {
if (pBtd) if(pBtd)
pBtd->pairWithHID(); pBtd->pairWithHID();
}; };
@ -98,7 +99,7 @@ private:
* This is useful for instance if you want to set the LEDs in a specific way. * This is useful for instance if you want to set the LEDs in a specific way.
*/ */
void onInit() { void onInit() {
if (pFuncOnInit) if(pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
} }
void (*pFuncOnInit)(void); // Pointer to function called in onInit() void (*pFuncOnInit)(void); // Pointer to function called in onInit()

196
PS3BT.cpp
View file

@ -23,7 +23,7 @@
PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) :
pBtd(p) // pointer to USB class instance - mandatory pBtd(p) // pointer to USB class instance - mandatory
{ {
if (pBtd) if(pBtd)
pBtd->registerServiceClass(this); // Register it as a Bluetooth service pBtd->registerServiceClass(this); // Register it as a Bluetooth service
pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead
@ -69,15 +69,15 @@ uint8_t PS3BT::getAnalogHat(AnalogHat a) {
} }
int16_t PS3BT::getSensor(Sensor a) { int16_t PS3BT::getSensor(Sensor a) {
if (PS3Connected) { if(PS3Connected) {
if (a == aX || a == aY || a == aZ || a == gZ) if(a == aX || a == aY || a == aZ || a == gZ)
return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]); return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]);
else else
return 0; return 0;
} else if (PS3MoveConnected) { } else if(PS3MoveConnected) {
if (a == mXmove || a == mYmove) // These are all 12-bits long if(a == mXmove || a == mYmove) // These are all 12-bits long
return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1])); return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1]));
else if (a == mZmove || a == tempMove) // The tempearature is also 12 bits long else if(a == mZmove || a == tempMove) // The tempearature is also 12 bits long
return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4)); return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4));
else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove
return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8)); return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8));
@ -88,13 +88,13 @@ int16_t PS3BT::getSensor(Sensor a) {
double PS3BT::getAngle(Angle a) { double PS3BT::getAngle(Angle a) {
double accXval, accYval, accZval; double accXval, accYval, accZval;
if (PS3Connected) { if(PS3Connected) {
// Data for the Kionix KXPC4 used in the DualShock 3 // Data for the Kionix KXPC4 used in the DualShock 3
const double zeroG = 511.5; // 1.65/3.3*1023 (1.65V) const double zeroG = 511.5; // 1.65/3.3*1023 (1.65V)
accXval = -((double)getSensor(aX) - zeroG); accXval = -((double)getSensor(aX) - zeroG);
accYval = -((double)getSensor(aY) - zeroG); accYval = -((double)getSensor(aY) - zeroG);
accZval = -((double)getSensor(aZ) - zeroG); accZval = -((double)getSensor(aZ) - zeroG);
} else if (PS3MoveConnected) { } else if(PS3MoveConnected) {
// It's a Kionix KXSC4 inside the Motion controller // It's a Kionix KXSC4 inside the Motion controller
const uint16_t zeroG = 0x8000; const uint16_t zeroG = 0x8000;
accXval = -(int16_t)(getSensor(aXmove) - zeroG); accXval = -(int16_t)(getSensor(aXmove) - zeroG);
@ -106,34 +106,34 @@ double PS3BT::getAngle(Angle a) {
// Convert to 360 degrees resolution // Convert to 360 degrees resolution
// atan2 outputs the value of -π to π (radians) // atan2 outputs the value of -π to π (radians)
// We are then converting it to 0 to 2π and then to degrees // We are then converting it to 0 to 2π and then to degrees
if (a == Pitch) if(a == Pitch)
return (atan2(accYval, accZval) + PI) * RAD_TO_DEG; return (atan2(accYval, accZval) + PI) * RAD_TO_DEG;
else else
return (atan2(accXval, accZval) + PI) * RAD_TO_DEG; return (atan2(accXval, accZval) + PI) * RAD_TO_DEG;
} }
double PS3BT::get9DOFValues(Sensor a) { // Thanks to Manfred Piendl double PS3BT::get9DOFValues(Sensor a) { // Thanks to Manfred Piendl
if (!PS3MoveConnected) if(!PS3MoveConnected)
return 0; return 0;
int16_t value = getSensor(a); int16_t value = getSensor(a);
if (a == mXmove || a == mYmove || a == mZmove) { if(a == mXmove || a == mYmove || a == mZmove) {
if (value > 2047) if(value > 2047)
value -= 0x1000; value -= 0x1000;
return (double)value / 3.2; // unit: muT = 10^(-6) Tesla return (double)value / 3.2; // unit: muT = 10^(-6) Tesla
} else if (a == aXmove || a == aYmove || a == aZmove) { } else if(a == aXmove || a == aYmove || a == aZmove) {
if (value < 0) if(value < 0)
value += 0x8000; value += 0x8000;
else else
value -= 0x8000; value -= 0x8000;
return (double)value / 442.0; // unit: m/(s^2) return (double)value / 442.0; // unit: m/(s^2)
} else if (a == gXmove || a == gYmove || a == gZmove) { } else if(a == gXmove || a == gYmove || a == gZmove) {
if (value < 0) if(value < 0)
value += 0x8000; value += 0x8000;
else else
value -= 0x8000; value -= 0x8000;
if (a == gXmove) if(a == gXmove)
return (double)value / 11.6; // unit: deg/s return (double)value / 11.6; // unit: deg/s
else if (a == gYmove) else if(a == gYmove)
return (double)value / 11.2; // unit: deg/s return (double)value / 11.2; // unit: deg/s
else // gZmove else // gZmove
return (double)value / 9.6; // unit: deg/s return (double)value / 9.6; // unit: deg/s
@ -142,12 +142,12 @@ double PS3BT::get9DOFValues(Sensor a) { // Thanks to Manfred Piendl
} }
String PS3BT::getTemperature() { String PS3BT::getTemperature() {
if (PS3MoveConnected) { if(PS3MoveConnected) {
int16_t input = getSensor(tempMove); int16_t input = getSensor(tempMove);
String output = String(input / 100); String output = String(input / 100);
output += "."; output += ".";
if (input % 100 < 10) if(input % 100 < 10)
output += "0"; output += "0";
output += String(input % 100); output += String(input % 100);
@ -161,48 +161,48 @@ bool PS3BT::getStatus(Status c) {
} }
String PS3BT::getStatusString() { String PS3BT::getStatusString() {
if (PS3Connected || PS3NavigationConnected) { if(PS3Connected || PS3NavigationConnected) {
char statusOutput[100]; // Max string length plus null character char statusOutput[100]; // Max string length plus null character
strcpy_P(statusOutput, PSTR("ConnectionStatus: ")); strcpy_P(statusOutput, PSTR("ConnectionStatus: "));
if (getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged")); if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged"));
else if (getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged")); else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged"));
else strcat_P(statusOutput, PSTR("Error")); else strcat_P(statusOutput, PSTR("Error"));
strcat_P(statusOutput, PSTR(" - PowerRating: ")); strcat_P(statusOutput, PSTR(" - PowerRating: "));
if (getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging")); if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging"));
else if (getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging"));
else if (getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown")); else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown"));
else if (getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying")); else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying"));
else if (getStatus(Low)) strcat_P(statusOutput, PSTR("Low")); else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low"));
else if (getStatus(High)) strcat_P(statusOutput, PSTR("High")); else if(getStatus(High)) strcat_P(statusOutput, PSTR("High"));
else if (getStatus(Full)) strcat_P(statusOutput, PSTR("Full")); else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full"));
else strcat_P(statusOutput, PSTR("Error")); else strcat_P(statusOutput, PSTR("Error"));
strcat_P(statusOutput, PSTR(" - WirelessStatus: ")); strcat_P(statusOutput, PSTR(" - WirelessStatus: "));
if (getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on")); if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on"));
else if (getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off")); else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off"));
else if (getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on")); else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on"));
else if (getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off")); else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off"));
else strcat_P(statusOutput, PSTR("Error")); else strcat_P(statusOutput, PSTR("Error"));
return statusOutput; return statusOutput;
} else if (PS3MoveConnected) { } else if(PS3MoveConnected) {
char statusOutput[26]; // Max string length plus null character char statusOutput[26]; // Max string length plus null character
strcpy_P(statusOutput, PSTR("PowerRating: ")); strcpy_P(statusOutput, PSTR("PowerRating: "));
if (getStatus(MoveCharging)) strcat_P(statusOutput, PSTR("Charging")); if(getStatus(MoveCharging)) strcat_P(statusOutput, PSTR("Charging"));
else if (getStatus(MoveNotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); else if(getStatus(MoveNotCharging)) strcat_P(statusOutput, PSTR("Not Charging"));
else if (getStatus(MoveShutdown)) strcat_P(statusOutput, PSTR("Shutdown")); else if(getStatus(MoveShutdown)) strcat_P(statusOutput, PSTR("Shutdown"));
else if (getStatus(MoveDying)) strcat_P(statusOutput, PSTR("Dying")); else if(getStatus(MoveDying)) strcat_P(statusOutput, PSTR("Dying"));
else if (getStatus(MoveLow)) strcat_P(statusOutput, PSTR("Low")); else if(getStatus(MoveLow)) strcat_P(statusOutput, PSTR("Low"));
else if (getStatus(MoveHigh)) strcat_P(statusOutput, PSTR("High")); else if(getStatus(MoveHigh)) strcat_P(statusOutput, PSTR("High"));
else if (getStatus(MoveFull)) strcat_P(statusOutput, PSTR("Full")); else if(getStatus(MoveFull)) strcat_P(statusOutput, PSTR("Full"));
else strcat_P(statusOutput, PSTR("Error")); else strcat_P(statusOutput, PSTR("Error"));
return statusOutput; return statusOutput;
@ -219,7 +219,7 @@ void PS3BT::Reset() {
l2cap_state = L2CAP_WAIT; l2cap_state = L2CAP_WAIT;
// Needed for PS3 Dualshock Controller commands to work via Bluetooth // Needed for PS3 Dualshock Controller commands to work via Bluetooth
for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID
} }
@ -231,17 +231,17 @@ void PS3BT::disconnect() { // Use this void to disconnect any of the controllers
} }
void PS3BT::ACLData(uint8_t* ACLData) { void PS3BT::ACLData(uint8_t* ACLData) {
if (!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) { if(!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) {
if (ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) { if(ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) {
if ((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) { if((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) {
pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
activeConnection = true; activeConnection = true;
hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
l2cap_state = L2CAP_WAIT; l2cap_state = L2CAP_WAIT;
for (uint8_t i = 0; i < 30; i++) for(uint8_t i = 0; i < 30; i++)
remote_name[i] = pBtd->remote_name[i]; // Store the remote name for the connection remote_name[i] = pBtd->remote_name[i]; // Store the remote name for the connection
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle if(pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle
Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80); Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80);
Notify(pBtd->hci_version, 0x80); Notify(pBtd->hci_version, 0x80);
Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80); Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80);
@ -250,10 +250,10 @@ void PS3BT::ACLData(uint8_t* ACLData) {
} }
} }
} }
if ((ACLData[0] | (uint16_t)ACLData[1] << 8) == (hci_handle | 0x2000U)) { //acl_handle_ok if((ACLData[0] | (uint16_t)ACLData[1] << 8) == (hci_handle | 0x2000U)) { //acl_handle_ok
memcpy(l2capinbuf, ACLData, BULK_MAXPKTSIZE); memcpy(l2capinbuf, ACLData, BULK_MAXPKTSIZE);
if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { //l2cap_control - Channel ID for ACL-U if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { //l2cap_control - Channel ID for ACL-U
if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
@ -268,7 +268,7 @@ void PS3BT::ACLData(uint8_t* ACLData) {
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
#endif #endif
} else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
@ -281,44 +281,44 @@ void PS3BT::ACLData(uint8_t* ACLData) {
Notify(PSTR(" Identifier: "), 0x80); Notify(PSTR(" Identifier: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
#endif #endif
if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
control_scid[0] = l2capinbuf[14]; control_scid[0] = l2capinbuf[14];
control_scid[1] = l2capinbuf[15]; control_scid[1] = l2capinbuf[15];
l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);
} else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
interrupt_scid[0] = l2capinbuf[14]; interrupt_scid[0] = l2capinbuf[14];
interrupt_scid[1] = l2capinbuf[15]; interrupt_scid[1] = l2capinbuf[15];
l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);
} }
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
#endif #endif
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
Reset(); Reset();
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
#endif #endif
@ -326,12 +326,12 @@ void PS3BT::ACLData(uint8_t* ACLData) {
pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
Reset(); Reset();
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
//Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);
} else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
//Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);
@ -343,26 +343,26 @@ void PS3BT::ACLData(uint8_t* ACLData) {
D_PrintHex<uint8_t > (l2capinbuf[8], 0x80); D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
} }
#endif #endif
} else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
//Notify(PSTR("\r\nL2CAP Interrupt"), 0x80); //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
if (PS3Connected || PS3MoveConnected || PS3NavigationConnected) { if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) {
/* Read Report */ /* Read Report */
if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
if (PS3Connected || PS3NavigationConnected) if(PS3Connected || PS3NavigationConnected)
ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16)); ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16));
else if (PS3MoveConnected) else if(PS3MoveConnected)
ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16)); ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16));
//Notify(PSTR("\r\nButtonState", 0x80); //Notify(PSTR("\r\nButtonState", 0x80);
//PrintHex<uint32_t>(ButtonState, 0x80); //PrintHex<uint32_t>(ButtonState, 0x80);
if (ButtonState != OldButtonState) { if(ButtonState != OldButtonState) {
ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
OldButtonState = ButtonState; OldButtonState = ButtonState;
} }
#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
for (uint8_t i = 10; i < 58; i++) { for(uint8_t i = 10; i < 58; i++) {
D_PrintHex<uint8_t > (l2capinbuf[i], 0x80); D_PrintHex<uint8_t > (l2capinbuf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -376,9 +376,9 @@ void PS3BT::ACLData(uint8_t* ACLData) {
} }
void PS3BT::L2CAP_task() { void PS3BT::L2CAP_task() {
switch (l2cap_state) { switch(l2cap_state) {
case L2CAP_WAIT: case L2CAP_WAIT:
if (l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
#endif #endif
@ -393,7 +393,7 @@ void PS3BT::L2CAP_task() {
break; break;
case L2CAP_CONTROL_SUCCESS: case L2CAP_CONTROL_SUCCESS:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
#endif #endif
@ -402,7 +402,7 @@ void PS3BT::L2CAP_task() {
break; break;
case L2CAP_INTERRUPT_SETUP: case L2CAP_INTERRUPT_SETUP:
if (l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
#endif #endif
@ -418,11 +418,11 @@ void PS3BT::L2CAP_task() {
break; break;
case L2CAP_INTERRUPT_CONFIG_REQUEST: case L2CAP_INTERRUPT_CONFIG_REQUEST:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80); Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80);
#endif #endif
if (remote_name[0] == 'M') { // First letter in Motion Controller ('M') if(remote_name[0] == 'M') { // First letter in Motion Controller ('M')
memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed
l2cap_state = TURN_ON_LED; l2cap_state = TURN_ON_LED;
} else } else
@ -434,7 +434,7 @@ void PS3BT::L2CAP_task() {
/* These states are handled in Run() */ /* These states are handled in Run() */
case L2CAP_INTERRUPT_DISCONNECT: case L2CAP_INTERRUPT_DISCONNECT:
if (l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) { if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
#endif #endif
@ -445,7 +445,7 @@ void PS3BT::L2CAP_task() {
break; break;
case L2CAP_CONTROL_DISCONNECT: case L2CAP_CONTROL_DISCONNECT:
if (l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
#endif #endif
@ -459,11 +459,11 @@ void PS3BT::L2CAP_task() {
} }
void PS3BT::Run() { void PS3BT::Run() {
switch (l2cap_state) { switch(l2cap_state) {
case PS3_ENABLE_SIXAXIS: case PS3_ENABLE_SIXAXIS:
if (millis() - timer > 1000) { // loop 1 second before sending the command if(millis() - timer > 1000) { // loop 1 second before sending the command
memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed
for (uint8_t i = 15; i < 19; i++) for(uint8_t i = 15; i < 19; i++)
l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position
enable_sixaxis(); enable_sixaxis();
l2cap_state = TURN_ON_LED; l2cap_state = TURN_ON_LED;
@ -472,18 +472,18 @@ void PS3BT::Run() {
break; break;
case TURN_ON_LED: case TURN_ON_LED:
if (millis() - timer > 1000) { // loop 1 second before sending the command if(millis() - timer > 1000) { // loop 1 second before sending the command
if (remote_name[0] == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P') if(remote_name[0] == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P')
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80); Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80);
#endif #endif
PS3Connected = true; PS3Connected = true;
} else if (remote_name[0] == 'N') { // First letter in Navigation Controller ('N') } else if(remote_name[0] == 'N') { // First letter in Navigation Controller ('N')
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80); Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80);
#endif #endif
PS3NavigationConnected = true; PS3NavigationConnected = true;
} else if (remote_name[0] == 'M') { // First letter in Motion Controller ('M') } else if(remote_name[0] == 'M') { // First letter in Motion Controller ('M')
timerBulbRumble = millis(); timerBulbRumble = millis();
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80); Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80);
@ -500,8 +500,8 @@ void PS3BT::Run() {
break; break;
case L2CAP_DONE: case L2CAP_DONE:
if (PS3MoveConnected) { // The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on if(PS3MoveConnected) { // The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on
if (millis() - timerBulbRumble > 4000) { // Send at least every 4th second if(millis() - timerBulbRumble > 4000) { // Send at least every 4th second
HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
timerBulbRumble = millis(); timerBulbRumble = millis();
} }
@ -517,7 +517,7 @@ void PS3BT::Run() {
// Playstation Sixaxis Dualshock and Navigation Controller commands // Playstation Sixaxis Dualshock and Navigation Controller commands
void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) { void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) {
if (millis() - timerHID <= 150) // Check if is has been more than 150ms since last command if(millis() - timerHID <= 150) // Check if is has been more than 150ms since last command
delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands
pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel
timerHID = millis(); timerHID = millis();
@ -544,8 +544,8 @@ void PS3BT::setRumbleOff() {
} }
void PS3BT::setRumbleOn(Rumble mode) { void PS3BT::setRumbleOn(Rumble mode) {
uint8_t power[2] = { 0xff, 0x00 }; // Defaults to RumbleLow uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow
if (mode == RumbleHigh) { if(mode == RumbleHigh) {
power[0] = 0x00; power[0] = 0x00;
power[1] = 0xff; power[1] = 0xff;
} }
@ -595,7 +595,7 @@ void PS3BT::enable_sixaxis() { // Command used to enable the Dualshock 3 and Nav
// Playstation Move Controller commands // Playstation Move Controller commands
void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) { void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) {
if (millis() - timerHID <= 150)// Check if is has been less than 150ms since last command if(millis() - timerHID <= 150)// Check if is has been less than 150ms since last command
delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands
pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel
timerHID = millis(); timerHID = millis();
@ -616,7 +616,7 @@ void PS3BT::moveSetBulb(Colors color) { //Use this to set the Color using the pr
void PS3BT::moveSetRumble(uint8_t rumble) { void PS3BT::moveSetRumble(uint8_t rumble) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)
Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80);
#endif #endif
// Set the rumble value into the write buffer // Set the rumble value into the write buffer
@ -626,10 +626,10 @@ void PS3BT::moveSetRumble(uint8_t rumble) {
} }
void PS3BT::onInit() { void PS3BT::onInit() {
if (pFuncOnInit) if(pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
else { else {
if (PS3MoveConnected) if(PS3MoveConnected)
moveSetBulb(Red); moveSetBulb(Red);
else // Dualshock 3 or Navigation controller else // Dualshock 3 or Navigation controller
setLedOn(LED1); setLedOn(LED1);

View file

@ -143,6 +143,7 @@ public:
* @param value See: ::LED enum. * @param value See: ::LED enum.
*/ */
void setLedRaw(uint8_t value); void setLedRaw(uint8_t value);
/** Turn all LEDs off. */ /** Turn all LEDs off. */
void setLedOff() { void setLedOff() {
setLedRaw(0); setLedRaw(0);

View file

@ -25,14 +25,14 @@ pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory bAddress(0), // device address - mandatory
bPollEnable(false) // don't start polling before dongle is connected bPollEnable(false) // don't start polling before dongle is connected
{ {
for (uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) { for(uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
} }
if (pUsb) // register in USB subsystem if(pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry pUsb->RegisterDeviceClass(this); //set devConfig[] entry
my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead
@ -58,7 +58,7 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
Notify(PSTR("\r\nPS3USB Init"), 0x80); Notify(PSTR("\r\nPS3USB Init"), 0x80);
#endif #endif
// check if address has already been assigned to an instance // check if address has already been assigned to an instance
if (bAddress) { if(bAddress) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress in use"), 0x80); Notify(PSTR("\r\nAddress in use"), 0x80);
#endif #endif
@ -68,14 +68,14 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) { if(!p) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
if (!p->epinfo) { if(!p->epinfo) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nepinfo is null"), 0x80); Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif #endif
@ -95,19 +95,19 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
VID = udd->idVendor; VID = udd->idVendor;
PID = udd->idProduct; PID = udd->idProduct;
if (VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID)) if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID))
goto FailUnknownDevice; goto FailUnknownDevice;
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from device descriptor // Extract Max Packet Size from device descriptor
@ -115,7 +115,7 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -135,14 +135,14 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
//get pointer to assigned address record //get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known // Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
@ -165,17 +165,17 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = 0; epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = 0;
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
delay(200); //Give time for address change delay(200); //Give time for address change
rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1); rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
if (PID == PS3_PID || PID == PS3NAVIGATION_PID) { if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {
if (PID == PS3_PID) { if(PID == PS3_PID) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
#endif #endif
@ -189,10 +189,10 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
enable_sixaxis(); // The PS3 controller needs a special command before it starts sending data enable_sixaxis(); // The PS3 controller needs a special command before it starts sending data
// Needed for PS3 Dualshock and Navigation commands to work // Needed for PS3 Dualshock and Navigation commands to work
for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]);
for (uint8_t i = 6; i < 10; i++) for(uint8_t i = 6; i < 10; i++)
readBuf[i] = 0x7F; // Set the analog joystick values to center position readBuf[i] = 0x7F; // Set the analog joystick values to center position
} else { // must be a Motion controller } else { // must be a Motion controller
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -201,15 +201,15 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
PS3MoveConnected = true; PS3MoveConnected = true;
writeBuf[0] = 0x02; // Set report ID, this is needed for Move commands to work writeBuf[0] = 0x02; // Set report ID, this is needed for Move commands to work
} }
if (my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) {
if (PS3MoveConnected) if(PS3MoveConnected)
setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address
else else
setBdaddr(my_bdaddr); // Set internal Bluetooth address setBdaddr(my_bdaddr); // Set internal Bluetooth address
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
for (int8_t i = 5; i > 0; i--) { for(int8_t i = 5; i > 0; i--) {
D_PrintHex<uint8_t > (my_bdaddr[i], 0x80); D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
Notify(PSTR(":"), 0x80); Notify(PSTR(":"), 0x80);
} }
@ -269,20 +269,20 @@ uint8_t PS3USB::Release() {
} }
uint8_t PS3USB::Poll() { uint8_t PS3USB::Poll() {
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
if (PS3Connected || PS3NavigationConnected) { if(PS3Connected || PS3NavigationConnected) {
uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1
if (millis() - timer > 100) { // Loop 100ms before processing data if(millis() - timer > 100) { // Loop 100ms before processing data
readReport(); readReport();
#ifdef PRINTREPORT #ifdef PRINTREPORT
printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
#endif #endif
} }
} else if (PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB } else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB
if (millis() - timer > 4000) { // Send at least every 4th second if(millis() - timer > 4000) { // Send at least every 4th second
Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
timer = millis(); timer = millis();
} }
@ -296,7 +296,7 @@ void PS3USB::readReport() {
//Notify(PSTR("\r\nButtonState", 0x80); //Notify(PSTR("\r\nButtonState", 0x80);
//PrintHex<uint32_t>(ButtonState, 0x80); //PrintHex<uint32_t>(ButtonState, 0x80);
if (ButtonState != OldButtonState) { if(ButtonState != OldButtonState) {
ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
OldButtonState = ButtonState; OldButtonState = ButtonState;
} }
@ -304,7 +304,7 @@ void PS3USB::readReport() {
void PS3USB::printReport() { // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers void PS3USB::printReport() { // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
#ifdef PRINTREPORT #ifdef PRINTREPORT
for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) { for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) {
D_PrintHex<uint8_t > (readBuf[i], 0x80); D_PrintHex<uint8_t > (readBuf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -336,7 +336,7 @@ uint16_t PS3USB::getSensor(Sensor a) {
} }
double PS3USB::getAngle(Angle a) { double PS3USB::getAngle(Angle a) {
if (PS3Connected) { if(PS3Connected) {
double accXval; double accXval;
double accYval; double accYval;
double accZval; double accZval;
@ -350,7 +350,7 @@ double PS3USB::getAngle(Angle a) {
// Convert to 360 degrees resolution // Convert to 360 degrees resolution
// atan2 outputs the value of -π to π (radians) // atan2 outputs the value of -π to π (radians)
// We are then converting it to 0 to 2π and then to degrees // We are then converting it to 0 to 2π and then to degrees
if (a == Pitch) if(a == Pitch)
return (atan2(accYval, accZval) + PI) * RAD_TO_DEG; return (atan2(accYval, accZval) + PI) * RAD_TO_DEG;
else else
return (atan2(accXval, accZval) + PI) * RAD_TO_DEG; return (atan2(accXval, accZval) + PI) * RAD_TO_DEG;
@ -363,33 +363,33 @@ bool PS3USB::getStatus(Status c) {
} }
String PS3USB::getStatusString() { String PS3USB::getStatusString() {
if (PS3Connected || PS3NavigationConnected) { if(PS3Connected || PS3NavigationConnected) {
char statusOutput[100]; char statusOutput[100];
strcpy(statusOutput, "ConnectionStatus: "); strcpy(statusOutput, "ConnectionStatus: ");
if (getStatus(Plugged)) strcat(statusOutput, "Plugged"); if(getStatus(Plugged)) strcat(statusOutput, "Plugged");
else if (getStatus(Unplugged)) strcat(statusOutput, "Unplugged"); else if(getStatus(Unplugged)) strcat(statusOutput, "Unplugged");
else strcat(statusOutput, "Error"); else strcat(statusOutput, "Error");
strcat(statusOutput, " - PowerRating: "); strcat(statusOutput, " - PowerRating: ");
if (getStatus(Charging)) strcat(statusOutput, "Charging"); if(getStatus(Charging)) strcat(statusOutput, "Charging");
else if (getStatus(NotCharging)) strcat(statusOutput, "Not Charging"); else if(getStatus(NotCharging)) strcat(statusOutput, "Not Charging");
else if (getStatus(Shutdown)) strcat(statusOutput, "Shutdown"); else if(getStatus(Shutdown)) strcat(statusOutput, "Shutdown");
else if (getStatus(Dying)) strcat(statusOutput, "Dying"); else if(getStatus(Dying)) strcat(statusOutput, "Dying");
else if (getStatus(Low)) strcat(statusOutput, "Low"); else if(getStatus(Low)) strcat(statusOutput, "Low");
else if (getStatus(High)) strcat(statusOutput, "High"); else if(getStatus(High)) strcat(statusOutput, "High");
else if (getStatus(Full)) strcat(statusOutput, "Full"); else if(getStatus(Full)) strcat(statusOutput, "Full");
else strcat(statusOutput, "Error"); else strcat(statusOutput, "Error");
strcat(statusOutput, " - WirelessStatus: "); strcat(statusOutput, " - WirelessStatus: ");
if (getStatus(CableRumble)) strcat(statusOutput, "Cable - Rumble is on"); if(getStatus(CableRumble)) strcat(statusOutput, "Cable - Rumble is on");
else if (getStatus(Cable)) strcat(statusOutput, "Cable - Rumble is off"); else if(getStatus(Cable)) strcat(statusOutput, "Cable - Rumble is off");
else if (getStatus(BluetoothRumble)) strcat(statusOutput, "Bluetooth - Rumble is on"); else if(getStatus(BluetoothRumble)) strcat(statusOutput, "Bluetooth - Rumble is on");
else if (getStatus(Bluetooth)) strcat(statusOutput, "Bluetooth - Rumble is off"); else if(getStatus(Bluetooth)) strcat(statusOutput, "Bluetooth - Rumble is off");
else strcat(statusOutput, "Error"); else strcat(statusOutput, "Error");
return statusOutput; return statusOutput;
@ -404,7 +404,7 @@ void PS3USB::PS3_Command(uint8_t *data, uint16_t nbytes) {
} }
void PS3USB::setAllOff() { void PS3USB::setAllOff() {
for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
@ -420,9 +420,9 @@ void PS3USB::setRumbleOff() {
} }
void PS3USB::setRumbleOn(Rumble mode) { void PS3USB::setRumbleOn(Rumble mode) {
if ((mode & 0x30) > 0x00) { if((mode & 0x30) > 0x00) {
uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow
if (mode == RumbleHigh) { if(mode == RumbleHigh) {
power[0] = 0x00; power[0] = 0x00;
power[1] = 0xff; power[1] = 0xff;
} }
@ -464,7 +464,7 @@ void PS3USB::setBdaddr(uint8_t *bdaddr) {
buf[0] = 0x01; buf[0] = 0x01;
buf[1] = 0x00; buf[1] = 0x00;
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
@ -477,7 +477,7 @@ void PS3USB::getBdaddr(uint8_t *bdaddr) {
// bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first
} }
@ -512,7 +512,7 @@ void PS3USB::moveSetBulb(Colors color) { // Use this to set the Color using the
void PS3USB::moveSetRumble(uint8_t rumble) { void PS3USB::moveSetRumble(uint8_t rumble) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)
Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80);
#endif #endif
writeBuf[6] = rumble; // Set the rumble value into the write buffer writeBuf[6] = rumble; // Set the rumble value into the write buffer
@ -529,7 +529,7 @@ void PS3USB::setMoveBdaddr(uint8_t *bdaddr) {
buf[9] = 0x02; buf[9] = 0x02;
buf[10] = 0x12; buf[10] = 0x12;
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
buf[i + 1] = bdaddr[i]; buf[i + 1] = bdaddr[i];
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
@ -542,27 +542,27 @@ void PS3USB::getMoveBdaddr(uint8_t *bdaddr) {
// bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x04), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x04), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL); pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL);
for (uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
bdaddr[i] = buf[10 + i]; bdaddr[i] = buf[10 + i];
} }
void PS3USB::getMoveCalibration(uint8_t *data) { void PS3USB::getMoveCalibration(uint8_t *data) {
uint8_t buf[49]; uint8_t buf[49];
for (uint8_t i = 0; i < 3; i++) { for(uint8_t i = 0; i < 3; i++) {
// bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x10), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x10), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL); pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL);
for (byte j = 0; j < 49; j++) for(byte j = 0; j < 49; j++)
data[49 * i + j] = buf[j]; data[49 * i + j] = buf[j];
} }
} }
void PS3USB::onInit() { void PS3USB::onInit() {
if (pFuncOnInit) if(pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
else { else {
if (PS3MoveConnected) if(PS3MoveConnected)
moveSetBulb(Red); moveSetBulb(Red);
else // Dualshock 3 or Navigation controller else // Dualshock 3 or Navigation controller
setLedOn(LED1); setLedOn(LED1);

View file

@ -220,6 +220,7 @@ public:
* @param value See: ::LED enum. * @param value See: ::LED enum.
*/ */
void setLedRaw(uint8_t value); void setLedRaw(uint8_t value);
/** Turn all LEDs off. */ /** Turn all LEDs off. */
void setLedOff() { void setLedOff() {
setLedRaw(0); setLedRaw(0);

168
SPP.cpp
View file

@ -45,7 +45,7 @@ const uint8_t rfcomm_crc_table[256] PROGMEM = {/* reversed, 8-bit, poly=0x07 */
SPP::SPP(BTD *p, const char* name, const char* pin) : SPP::SPP(BTD *p, const char* name, const char* pin) :
pBtd(p) // Pointer to BTD class instance - mandatory pBtd(p) // Pointer to BTD class instance - mandatory
{ {
if (pBtd) if(pBtd)
pBtd->registerServiceClass(this); // Register it as a Bluetooth service pBtd->registerServiceClass(this); // Register it as a Bluetooth service
pBtd->btdName = name; pBtd->btdName = name;
@ -74,32 +74,32 @@ void SPP::Reset() {
void SPP::disconnect() { void SPP::disconnect() {
connected = false; connected = false;
// First the two L2CAP channels has to be disconnected and then the HCI connection // First the two L2CAP channels has to be disconnected and then the HCI connection
if (RFCOMMConnected) if(RFCOMMConnected)
pBtd->l2cap_disconnection_request(hci_handle, ++identifier, rfcomm_scid, rfcomm_dcid); pBtd->l2cap_disconnection_request(hci_handle, ++identifier, rfcomm_scid, rfcomm_dcid);
if (RFCOMMConnected && SDPConnected) if(RFCOMMConnected && SDPConnected)
delay(1); // Add delay between commands delay(1); // Add delay between commands
if (SDPConnected) if(SDPConnected)
pBtd->l2cap_disconnection_request(hci_handle, ++identifier, sdp_scid, sdp_dcid); pBtd->l2cap_disconnection_request(hci_handle, ++identifier, sdp_scid, sdp_dcid);
l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE; l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE;
} }
void SPP::ACLData(uint8_t* l2capinbuf) { void SPP::ACLData(uint8_t* l2capinbuf) {
if (!connected) { if(!connected) {
if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) { if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) {
pBtd->sdpConnectionClaimed = true; pBtd->sdpConnectionClaimed = true;
hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state
} else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) { } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) {
pBtd->rfcommConnectionClaimed = true; pBtd->rfcommConnectionClaimed = true;
hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state
} }
} }
} }
if ((l2capinbuf[0] | (uint16_t)l2capinbuf[1] << 8) == (hci_handle | 0x2000U)) { // acl_handle_ok if((l2capinbuf[0] | (uint16_t)l2capinbuf[1] << 8) == (hci_handle | 0x2000U)) { // acl_handle_ok
if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { //l2cap_control - Channel ID for ACL-U if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { //l2cap_control - Channel ID for ACL-U
if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
@ -114,7 +114,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
#endif #endif
} else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
@ -127,56 +127,56 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR(" Identifier: "), 0x80); Notify(PSTR(" Identifier: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
#endif #endif
if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
sdp_scid[0] = l2capinbuf[14]; sdp_scid[0] = l2capinbuf[14];
sdp_scid[1] = l2capinbuf[15]; sdp_scid[1] = l2capinbuf[15];
l2cap_set_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); l2cap_set_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST);
} else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || ----- } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || -----
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
rfcomm_scid[0] = l2capinbuf[14]; rfcomm_scid[0] = l2capinbuf[14];
rfcomm_scid[1] = l2capinbuf[15]; rfcomm_scid[1] = l2capinbuf[15];
l2cap_set_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); l2cap_set_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
//Notify(PSTR("\r\nSDP Configuration Complete"), 0x80); //Notify(PSTR("\r\nSDP Configuration Complete"), 0x80);
l2cap_set_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); l2cap_set_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS);
} else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
//Notify(PSTR("\r\nRFCOMM Configuration Complete"), 0x80); //Notify(PSTR("\r\nRFCOMM Configuration Complete"), 0x80);
l2cap_set_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); l2cap_set_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS);
} }
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
//Notify(PSTR("\r\nSDP Configuration Request"), 0x80); //Notify(PSTR("\r\nSDP Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], sdp_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], sdp_scid);
} else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
//Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80); //Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], rfcomm_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], rfcomm_scid);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
//Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST);
} else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
//Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
if (l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) { if(l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) {
//Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE);
} else if (l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) { } else if(l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) {
//Notify(PSTR("\r\nDisconnect Response: RFCOMM Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Response: RFCOMM Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nInformation request"), 0x80); Notify(PSTR("\r\nInformation request"), 0x80);
#endif #endif
@ -189,18 +189,18 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
D_PrintHex<uint8_t > (l2capinbuf[8], 0x80); D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
} }
#endif #endif
} else if (l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP } else if(l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP
if (l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) { if(l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) {
if (((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == SERIALPORT_UUID)) { // Check if it's sending the full UUID, see: https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm, we will just check the first four bytes if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == SERIALPORT_UUID)) { // Check if it's sending the full UUID, see: https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm, we will just check the first four bytes
if (firstMessage) { if(firstMessage) {
serialPortResponse1(l2capinbuf[9], l2capinbuf[10]); serialPortResponse1(l2capinbuf[9], l2capinbuf[10]);
firstMessage = false; firstMessage = false;
} else { } else {
serialPortResponse2(l2capinbuf[9], l2capinbuf[10]); // Serialport continuation state serialPortResponse2(l2capinbuf[9], l2capinbuf[10]); // Serialport continuation state
firstMessage = true; firstMessage = true;
} }
} else if (((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == L2CAP_UUID)) { } else if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == L2CAP_UUID)) {
if (firstMessage) { if(firstMessage) {
l2capResponse1(l2capinbuf[9], l2capinbuf[10]); l2capResponse1(l2capinbuf[9], l2capinbuf[10]);
firstMessage = false; firstMessage = false;
} else { } else {
@ -216,14 +216,14 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
uuid = (l2capinbuf[18] << 8 | l2capinbuf[19]); uuid = (l2capinbuf[18] << 8 | l2capinbuf[19]);
else // Short UUID else // Short UUID
uuid = (l2capinbuf[16] << 8 | l2capinbuf[17]); uuid = (l2capinbuf[16] << 8 | l2capinbuf[17]);
D_PrintHex<uint16_t> (uuid, 0x80); D_PrintHex<uint16_t > (uuid, 0x80);
Notify(PSTR("\r\nLength: "), 0x80); Notify(PSTR("\r\nLength: "), 0x80);
uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12]; uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12];
D_PrintHex<uint16_t> (length, 0x80); D_PrintHex<uint16_t > (length, 0x80);
Notify(PSTR("\r\nData: "), 0x80); Notify(PSTR("\r\nData: "), 0x80);
for (uint8_t i = 0; i < length; i++) { for(uint8_t i = 0; i < length; i++) {
D_PrintHex<uint8_t> (l2capinbuf[13+i], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13 + i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
#endif #endif
@ -234,14 +234,14 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
D_PrintHex<uint8_t > (l2capinbuf[8], 0x80); D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
} }
#endif #endif
} else if (l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM } else if(l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM
rfcommChannel = l2capinbuf[8] & 0xF8; rfcommChannel = l2capinbuf[8] & 0xF8;
rfcommDirection = l2capinbuf[8] & 0x04; rfcommDirection = l2capinbuf[8] & 0x04;
rfcommCommandResponse = l2capinbuf[8] & 0x02; rfcommCommandResponse = l2capinbuf[8] & 0x02;
rfcommChannelType = l2capinbuf[9] & 0xEF; rfcommChannelType = l2capinbuf[9] & 0xEF;
rfcommPfBit = l2capinbuf[9] & 0x10; rfcommPfBit = l2capinbuf[9] & 0x10;
if (rfcommChannel >> 3 != 0x00) if(rfcommChannel >> 3 != 0x00)
rfcommChannelConnection = rfcommChannel; rfcommChannelConnection = rfcommChannel;
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
@ -256,7 +256,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR(" PF_BIT: "), 0x80); Notify(PSTR(" PF_BIT: "), 0x80);
D_PrintHex<uint8_t > (rfcommPfBit, 0x80); D_PrintHex<uint8_t > (rfcommPfBit, 0x80);
#endif #endif
if (rfcommChannelType == RFCOMM_DISC) { if(rfcommChannelType == RFCOMM_DISC) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80); Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80);
D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80); D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);
@ -264,15 +264,15 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
connected = false; connected = false;
sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command
} }
if (connected) { if(connected) {
/* Read the incoming message */ /* Read the incoming message */
if (rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) { if(rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) {
uint8_t length = l2capinbuf[10] >> 1; // Get length uint8_t length = l2capinbuf[10] >> 1; // Get length
uint8_t offset = l2capinbuf[4] - length - 4; // Check if there is credit uint8_t offset = l2capinbuf[4] - length - 4; // Check if there is credit
if (checkFcs(&l2capinbuf[8], l2capinbuf[11 + length + offset])) { if(checkFcs(&l2capinbuf[8], l2capinbuf[11 + length + offset])) {
uint8_t i = 0; uint8_t i = 0;
for (; i < length; i++) { for(; i < length; i++) {
if (rfcommAvailable + i >= sizeof (rfcommDataBuffer)) { if(rfcommAvailable + i >= sizeof (rfcommDataBuffer)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nWarning: Buffer is full!"), 0x80); Notify(PSTR("\r\nWarning: Buffer is full!"), 0x80);
#endif #endif
@ -284,7 +284,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80); Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80);
Notify(rfcommAvailable, 0x80); Notify(rfcommAvailable, 0x80);
if (offset) { if(offset) {
Notify(PSTR(" - Credit: 0x"), 0x80); Notify(PSTR(" - Credit: 0x"), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[11], 0x80); D_PrintHex<uint8_t > (l2capinbuf[11], 0x80);
} }
@ -295,10 +295,10 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR("\r\nError in FCS checksum!"), 0x80); Notify(PSTR("\r\nError in FCS checksum!"), 0x80);
#endif #endif
#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth
for (uint8_t i = 0; i < length; i++) for(uint8_t i = 0; i < length; i++)
Notifyc(l2capinbuf[i + 11 + offset], 0x80); Notifyc(l2capinbuf[i + 11 + offset], 0x80);
#endif #endif
} else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80);
#endif #endif
@ -313,7 +313,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm. rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.
rfcommbuf[9] = l2capinbuf[20]; // Number of Frames rfcommbuf[9] = l2capinbuf[20]; // Number of Frames
sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response
} else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80);
#endif #endif
@ -324,12 +324,12 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
} }
} else { } else {
if (rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish if(rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nReceived SABM Command"), 0x80); Notify(PSTR("\r\nReceived SABM Command"), 0x80);
#endif #endif
sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command
} else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80); Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80);
#endif #endif
@ -344,7 +344,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
rfcommbuf[8] = 0x00; // MaxRatransm. rfcommbuf[8] = 0x00; // MaxRatransm.
rfcommbuf[9] = 0x00; // Number of Frames rfcommbuf[9] = 0x00; // Number of Frames
sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A);
} else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80);
#endif #endif
@ -364,8 +364,8 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES) rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES)
sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
} else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response
if (!creditSent) { if(!creditSent) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSend UIH Command with credit"), 0x80); Notify(PSTR("\r\nSend UIH Command with credit"), 0x80);
#endif #endif
@ -374,11 +374,11 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
timer = millis(); timer = millis();
waitForLastCommand = true; waitForLastCommand = true;
} }
} else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80); Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80);
#endif #endif
} else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80);
#endif #endif
@ -402,7 +402,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
sppIndex = 0; sppIndex = 0;
} }
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
else if (rfcommChannelType != RFCOMM_DISC) { else if(rfcommChannelType != RFCOMM_DISC) {
Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80); Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80);
D_PrintHex<uint8_t > (rfcommChannelType, 0x80); D_PrintHex<uint8_t > (rfcommChannelType, 0x80);
Notify(PSTR(" Command: "), 0x80); Notify(PSTR(" Command: "), 0x80);
@ -425,7 +425,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
} }
void SPP::Run() { void SPP::Run() {
if (waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it if(waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80); Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80);
#endif #endif
@ -438,9 +438,9 @@ void SPP::Run() {
} }
void SPP::SDP_task() { void SPP::SDP_task() {
switch (l2cap_sdp_state) { switch(l2cap_sdp_state) {
case L2CAP_SDP_WAIT: case L2CAP_SDP_WAIT:
if (l2cap_check_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST)) { if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST)) {
l2cap_clear_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); // Clear flag l2cap_clear_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); // Clear flag
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80); Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80);
@ -452,7 +452,7 @@ void SPP::SDP_task() {
delay(1); delay(1);
pBtd->l2cap_config_request(hci_handle, identifier, sdp_scid); pBtd->l2cap_config_request(hci_handle, identifier, sdp_scid);
l2cap_sdp_state = L2CAP_SDP_SUCCESS; l2cap_sdp_state = L2CAP_SDP_SUCCESS;
} else if (l2cap_check_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST)) { } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST)) {
l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); // Clear flag l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); // Clear flag
SDPConnected = false; SDPConnected = false;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -462,7 +462,7 @@ void SPP::SDP_task() {
} }
break; break;
case L2CAP_SDP_SUCCESS: case L2CAP_SDP_SUCCESS:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS)) { if(l2cap_check_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS)) {
l2cap_clear_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); // Clear flag l2cap_clear_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); // Clear flag
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSDP Successfully Configured"), 0x80); Notify(PSTR("\r\nSDP Successfully Configured"), 0x80);
@ -474,7 +474,7 @@ void SPP::SDP_task() {
break; break;
case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected
if (l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RESPONSE)) { if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RESPONSE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80); Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80);
#endif #endif
@ -487,9 +487,9 @@ void SPP::SDP_task() {
} }
void SPP::RFCOMM_task() { void SPP::RFCOMM_task() {
switch (l2cap_rfcomm_state) { switch(l2cap_rfcomm_state) {
case L2CAP_RFCOMM_WAIT: case L2CAP_RFCOMM_WAIT:
if (l2cap_check_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST)) { if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST)) {
l2cap_clear_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); // Clear flag l2cap_clear_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); // Clear flag
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80); Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80);
@ -501,7 +501,7 @@ void SPP::RFCOMM_task() {
delay(1); delay(1);
pBtd->l2cap_config_request(hci_handle, identifier, rfcomm_scid); pBtd->l2cap_config_request(hci_handle, identifier, rfcomm_scid);
l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS; l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS;
} else if (l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST)) { } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST)) {
l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); // Clear flag l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); // Clear flag
RFCOMMConnected = false; RFCOMMConnected = false;
connected = false; connected = false;
@ -512,7 +512,7 @@ void SPP::RFCOMM_task() {
} }
break; break;
case L2CAP_RFCOMM_SUCCESS: case L2CAP_RFCOMM_SUCCESS:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS)) { if(l2cap_check_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS)) {
l2cap_clear_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); // Clear flag l2cap_clear_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); // Clear flag
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80); Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80);
@ -670,12 +670,12 @@ void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t cha
l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
l2capoutbuf[2] = length << 1 | 0x01; // Length and format (always 0x01 bytes format) l2capoutbuf[2] = length << 1 | 0x01; // Length and format (always 0x01 bytes format)
uint8_t i = 0; uint8_t i = 0;
for (; i < length; i++) for(; i < length; i++)
l2capoutbuf[i + 3] = data[i]; l2capoutbuf[i + 3] = data[i];
l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); l2capoutbuf[i + 3] = calcFcs(l2capoutbuf);
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR(" - RFCOMM Data: "), 0x80); Notify(PSTR(" - RFCOMM Data: "), 0x80);
for (i = 0; i < length + 4; i++) { for(i = 0; i < length + 4; i++) {
D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80); D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -691,7 +691,7 @@ void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8
l2capoutbuf[4] = calcFcs(l2capoutbuf); l2capoutbuf[4] = calcFcs(l2capoutbuf);
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR(" - RFCOMM Credit Data: "), 0x80); Notify(PSTR(" - RFCOMM Credit Data: "), 0x80);
for (uint8_t i = 0; i < 5; i++) { for(uint8_t i = 0; i < 5; i++) {
D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80); D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -707,7 +707,7 @@ uint8_t SPP::crc(uint8_t *data) {
/* Calculate FCS */ /* Calculate FCS */
uint8_t SPP::calcFcs(uint8_t *data) { uint8_t SPP::calcFcs(uint8_t *data) {
uint8_t temp = crc(data); uint8_t temp = crc(data);
if ((data[1] & 0xEF) == RFCOMM_UIH) if((data[1] & 0xEF) == RFCOMM_UIH)
return (0xFF - temp); // FCS on 2 bytes return (0xFF - temp); // FCS on 2 bytes
else else
return (0xFF - pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]])); // FCS on 3 bytes return (0xFF - pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]])); // FCS on 3 bytes
@ -716,29 +716,33 @@ uint8_t SPP::calcFcs(uint8_t *data) {
/* Check FCS */ /* Check FCS */
bool SPP::checkFcs(uint8_t *data, uint8_t fcs) { bool SPP::checkFcs(uint8_t *data, uint8_t fcs) {
uint8_t temp = crc(data); uint8_t temp = crc(data);
if ((data[1] & 0xEF) != RFCOMM_UIH) if((data[1] & 0xEF) != RFCOMM_UIH)
temp = pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]]); // FCS on 3 bytes temp = pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]]); // FCS on 3 bytes
return (pgm_read_byte(&rfcomm_crc_table[temp ^ fcs]) == 0xCF); return (pgm_read_byte(&rfcomm_crc_table[temp ^ fcs]) == 0xCF);
} }
/* Serial commands */ /* Serial commands */
#if defined(ARDUINO) && ARDUINO >=100 #if defined(ARDUINO) && ARDUINO >=100
size_t SPP::write(uint8_t data) { size_t SPP::write(uint8_t data) {
return write(&data, 1); return write(&data, 1);
} }
#else #else
void SPP::write(uint8_t data) { void SPP::write(uint8_t data) {
write(&data, 1); write(&data, 1);
} }
#endif #endif
#if defined(ARDUINO) && ARDUINO >=100 #if defined(ARDUINO) && ARDUINO >=100
size_t SPP::write(const uint8_t *data, size_t size) { size_t SPP::write(const uint8_t *data, size_t size) {
#else #else
void SPP::write(const uint8_t *data, size_t size) { void SPP::write(const uint8_t *data, size_t size) {
#endif #endif
for(uint8_t i = 0; i < size; i++) { for(uint8_t i = 0; i < size; i++) {
if(sppIndex >= sizeof(sppOutputBuffer)/sizeof(sppOutputBuffer[0])) if(sppIndex >= sizeof (sppOutputBuffer) / sizeof (sppOutputBuffer[0]))
send(); // Send the current data in the buffer send(); // Send the current data in the buffer
sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function
} }
@ -748,7 +752,7 @@ void SPP::write(const uint8_t *data, size_t size) {
} }
void SPP::send() { void SPP::send() {
if (!connected || !sppIndex) if(!connected || !sppIndex)
return; return;
uint8_t length; // This is the length of the string we are sending uint8_t length; // This is the length of the string we are sending
uint8_t offset = 0; // This is used to keep track of where we are in the string uint8_t offset = 0; // This is used to keep track of where we are in the string
@ -756,15 +760,15 @@ void SPP::send() {
l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address
l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
while (sppIndex) { // We will run this while loop until this variable is 0 while(sppIndex) { // We will run this while loop until this variable is 0
if (sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer if(sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer
length = sizeof (l2capoutbuf) - 4; length = sizeof (l2capoutbuf) - 4;
else else
length = sppIndex; length = sppIndex;
l2capoutbuf[2] = length << 1 | 1; // Length l2capoutbuf[2] = length << 1 | 1; // Length
uint8_t i = 0; uint8_t i = 0;
for (; i < length; i++) for(; i < length; i++)
l2capoutbuf[i + 3] = sppOutputBuffer[i + offset]; l2capoutbuf[i + 3] = sppOutputBuffer[i + offset];
l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum
@ -784,20 +788,20 @@ void SPP::discard(void) {
} }
int SPP::peek(void) { int SPP::peek(void) {
if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer
return -1; return -1;
return rfcommDataBuffer[0]; return rfcommDataBuffer[0];
} }
int SPP::read(void) { int SPP::read(void) {
if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer
return -1; return -1;
uint8_t output = rfcommDataBuffer[0]; uint8_t output = rfcommDataBuffer[0];
for (uint8_t i = 1; i < rfcommAvailable; i++) for(uint8_t i = 1; i < rfcommAvailable; i++)
rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left
rfcommAvailable--; rfcommAvailable--;
bytesRead++; bytesRead++;
if (bytesRead > (sizeof (rfcommDataBuffer) - 5)) { // We will send the command just before it runs out of credit if(bytesRead > (sizeof (rfcommDataBuffer) - 5)) { // We will send the command just before it runs out of credit
bytesRead = 0; bytesRead = 0;
sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit
#ifdef EXTRADEBUG #ifdef EXTRADEBUG

1
SPP.h
View file

@ -98,6 +98,7 @@ public:
* @return Return the number of bytes ready to be read. * @return Return the number of bytes ready to be read.
*/ */
virtual int available(void); virtual int available(void);
/** Send out all bytes in the buffer. */ /** Send out all bytes in the buffer. */
virtual void flush(void) { virtual void flush(void) {
send(); send();

173
Usb.cpp
View file

@ -44,13 +44,13 @@ void USB::setUsbTaskState(uint8_t state) {
EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) { EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
UsbDevice *p = addrPool.GetUsbDevicePtr(addr); UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if (!p || !p->epinfo) if(!p || !p->epinfo)
return NULL; return NULL;
EpInfo *pep = p->epinfo; EpInfo *pep = p->epinfo;
for (uint8_t i = 0; i < p->epcount; i++) { for(uint8_t i = 0; i < p->epcount; i++) {
if ((pep)->epAddr == ep) if((pep)->epAddr == ep)
return pep; return pep;
pep++; pep++;
@ -62,12 +62,12 @@ EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */ /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) { uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) {
if (!eprecord_ptr) if(!eprecord_ptr)
return USB_ERROR_INVALID_ARGUMENT; return USB_ERROR_INVALID_ARGUMENT;
UsbDevice *p = addrPool.GetUsbDevicePtr(addr); UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->address.devAddress = addr; p->address.devAddress = addr;
@ -80,15 +80,15 @@ uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr)
uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit) { uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit) {
UsbDevice *p = addrPool.GetUsbDevicePtr(addr); UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo) if(!p->epinfo)
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
*ppep = getEpInfoEntry(addr, ep); *ppep = getEpInfoEntry(addr, ep);
if (!*ppep) if(!*ppep)
return USB_ERROR_EP_NOT_FOUND_IN_TBL; return USB_ERROR_EP_NOT_FOUND_IN_TBL;
nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower)); nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
@ -134,7 +134,7 @@ uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bReque
rcode = SetAddress(addr, ep, &pep, nak_limit); rcode = SetAddress(addr, ep, &pep, nak_limit);
if (rcode) if(rcode)
return rcode; return rcode;
direction = ((bmReqType & 0x80) > 0); direction = ((bmReqType & 0x80) > 0);
@ -151,39 +151,39 @@ uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bReque
rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet
if (rcode) //return HRSLT if not zero if(rcode) //return HRSLT if not zero
return ( rcode); return ( rcode);
if (dataptr != NULL) //data stage, if present if(dataptr != NULL) //data stage, if present
{ {
if (direction) //IN transfer if(direction) //IN transfer
{ {
uint16_t left = total; uint16_t left = total;
pep->bmRcvToggle = 1; //bmRCVTOG1; pep->bmRcvToggle = 1; //bmRCVTOG1;
while (left) { while(left) {
// Bytes read into buffer // Bytes read into buffer
uint16_t read = nbytes; uint16_t read = nbytes;
//uint16_t read = (left<nbytes) ? left : nbytes; //uint16_t read = (left<nbytes) ? left : nbytes;
rcode = InTransfer(pep, nak_limit, &read, dataptr); rcode = InTransfer(pep, nak_limit, &read, dataptr);
if (rcode == hrTOGERR) { if(rcode == hrTOGERR) {
// yes, we flip it wrong here so that next time it is actually correct! // yes, we flip it wrong here so that next time it is actually correct!
pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
continue; continue;
} }
if (rcode) if(rcode)
return rcode; return rcode;
// Invoke callback function if inTransfer completed successfully and callback function pointer is specified // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
if (!rcode && p) if(!rcode && p)
((USBReadParser*)p)->Parse(read, dataptr, total - left); ((USBReadParser*)p)->Parse(read, dataptr, total - left);
left -= read; left -= read;
if (read < nbytes) if(read < nbytes)
break; break;
} }
} else //OUT transfer } else //OUT transfer
@ -191,7 +191,7 @@ uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bReque
pep->bmSndToggle = 1; //bmSNDTOG1; pep->bmSndToggle = 1; //bmSNDTOG1;
rcode = OutTransfer(pep, nak_limit, nbytes, dataptr); rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
} }
if (rcode) //return error if(rcode) //return error
return ( rcode); return ( rcode);
} }
// Status stage // Status stage
@ -209,7 +209,7 @@ uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t*
uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit); uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit);
if (rcode) { if(rcode) {
USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81); USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81); USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81); USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
@ -229,22 +229,22 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
*nbytesptr = 0; *nbytesptr = 0;
regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
while (1) // use a 'return' to exit this loop // use a 'break' to exit this loop
{ while(1) {
rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS. rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
if (rcode == hrTOGERR) { if(rcode == hrTOGERR) {
// yes, we flip it wrong here so that next time it is actually correct! // yes, we flip it wrong here so that next time it is actually correct!
pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
continue; continue;
} }
if (rcode) { if(rcode) {
//printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode); //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
break; //should be 0, indicating ACK. Else return error code. break; //should be 0, indicating ACK. Else return error code.
} }
/* check for RCVDAVIRQ and generate error if not present */ /* check for RCVDAVIRQ and generate error if not present */
/* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */ /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */
if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) { if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
//printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n"); //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n");
rcode = 0xf0; //receive error rcode = 0xf0; //receive error
break; break;
@ -253,7 +253,7 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
//printf("Got %i bytes \r\n", pktsize); //printf("Got %i bytes \r\n", pktsize);
// This would be OK, but... // This would be OK, but...
//assert(pktsize <= nbytes); //assert(pktsize <= nbytes);
if (pktsize > nbytes) { if(pktsize > nbytes) {
// This can happen. Use of assert on Arduino locks up the Arduino. // This can happen. Use of assert on Arduino locks up the Arduino.
// So I will trim the value, and hope for the best. // So I will trim the value, and hope for the best.
//printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize); //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
@ -262,7 +262,7 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
if (mem_left < 0) if(mem_left < 0)
mem_left = 0; mem_left = 0;
data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
@ -273,7 +273,7 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
/* The transfer is complete under two conditions: */ /* The transfer is complete under two conditions: */
/* 1. The device sent a short packet (L.T. maxPacketSize) */ /* 1. The device sent a short packet (L.T. maxPacketSize) */
/* 2. 'nbytes' have been transferred. */ /* 2. 'nbytes' have been transferred. */
if ((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes? if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?
{ {
// Save toggle value // Save toggle value
pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
@ -295,7 +295,7 @@ uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dat
uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit); uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit);
if (rcode) if(rcode)
return rcode; return rcode;
return OutTransfer(pep, nak_limit, nbytes, data); return OutTransfer(pep, nak_limit, nbytes, data);
@ -309,35 +309,35 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8
uint8_t maxpktsize = pep->maxPktSize; uint8_t maxpktsize = pep->maxPktSize;
if (maxpktsize < 1 || maxpktsize > 64) if(maxpktsize < 1 || maxpktsize > 64)
return USB_ERROR_INVALID_MAX_PKT_SIZE; return USB_ERROR_INVALID_MAX_PKT_SIZE;
unsigned long timeout = millis() + USB_XFER_TIMEOUT; unsigned long timeout = millis() + USB_XFER_TIMEOUT;
regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
while (bytes_left) { while(bytes_left) {
retry_count = 0; retry_count = 0;
nak_count = 0; nak_count = 0;
bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
regWr(rSNDBC, bytes_tosend); //set number of bytes regWr(rSNDBC, bytes_tosend); //set number of bytes
regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
rcode = (regRd(rHRSL) & 0x0f); rcode = (regRd(rHRSL) & 0x0f);
while (rcode && (timeout > millis())) { while(rcode && (timeout > millis())) {
switch (rcode) { switch(rcode) {
case hrNAK: case hrNAK:
nak_count++; nak_count++;
if (nak_limit && (nak_count == nak_limit)) if(nak_limit && (nak_count == nak_limit))
goto breakout; goto breakout;
//return ( rcode); //return ( rcode);
break; break;
case hrTIMEOUT: case hrTIMEOUT:
retry_count++; retry_count++;
if (retry_count == USB_RETRY_LIMIT) if(retry_count == USB_RETRY_LIMIT)
goto breakout; goto breakout;
//return ( rcode); //return ( rcode);
break; break;
@ -355,7 +355,7 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8
regWr(rSNDFIFO, *data_p); regWr(rSNDFIFO, *data_p);
regWr(rSNDBC, bytes_tosend); regWr(rSNDBC, bytes_tosend);
regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
rcode = (regRd(rHRSL) & 0x0f); rcode = (regRd(rHRSL) & 0x0f);
}//while( rcode && .... }//while( rcode && ....
@ -380,15 +380,15 @@ uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
uint8_t retry_count = 0; uint8_t retry_count = 0;
uint16_t nak_count = 0; uint16_t nak_count = 0;
while (timeout > millis()) { while(timeout > millis()) {
regWr(rHXFR, (token | ep)); //launch the transfer regWr(rHXFR, (token | ep)); //launch the transfer
rcode = USB_ERROR_TRANSFER_TIMEOUT; rcode = USB_ERROR_TRANSFER_TIMEOUT;
while (timeout > millis()) //wait for transfer completion while(timeout > millis()) //wait for transfer completion
{ {
tmpdata = regRd(rHIRQ); tmpdata = regRd(rHIRQ);
if (tmpdata & bmHXFRDNIRQ) { if(tmpdata & bmHXFRDNIRQ) {
regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
rcode = 0x00; rcode = 0x00;
break; break;
@ -401,15 +401,15 @@ uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
switch (rcode) { switch(rcode) {
case hrNAK: case hrNAK:
nak_count++; nak_count++;
if (nak_limit && (nak_count == nak_limit)) if(nak_limit && (nak_count == nak_limit))
return (rcode); return (rcode);
break; break;
case hrTIMEOUT: case hrTIMEOUT:
retry_count++; retry_count++;
if (retry_count == USB_RETRY_LIMIT) if(retry_count == USB_RETRY_LIMIT)
return (rcode); return (rcode);
break; break;
default: default:
@ -434,13 +434,13 @@ void USB::Task(void) //USB state machine
tmpdata = getVbusState(); tmpdata = getVbusState();
/* modify USB task state if Vbus changed */ /* modify USB task state if Vbus changed */
switch (tmpdata) { switch(tmpdata) {
case SE1: //illegal state case SE1: //illegal state
usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
lowspeed = false; lowspeed = false;
break; break;
case SE0: //disconnected case SE0: //disconnected
if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED) if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
lowspeed = false; lowspeed = false;
break; break;
@ -449,23 +449,23 @@ void USB::Task(void) //USB state machine
lowspeed = true; lowspeed = true;
//intentional fallthrough //intentional fallthrough
case FSHOST: //attached case FSHOST: //attached
if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) { if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
delay = millis() + USB_SETTLE_DELAY; delay = millis() + USB_SETTLE_DELAY;
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
} }
break; break;
}// switch( tmpdata }// switch( tmpdata
for (uint8_t i = 0; i < USB_NUMDEVICES; i++) for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
if (devConfig[i]) if(devConfig[i])
rcode = devConfig[i]->Poll(); rcode = devConfig[i]->Poll();
switch (usb_task_state) { switch(usb_task_state) {
case USB_DETACHED_SUBSTATE_INITIALIZE: case USB_DETACHED_SUBSTATE_INITIALIZE:
init(); init();
for (uint8_t i = 0; i < USB_NUMDEVICES; i++) for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
if (devConfig[i]) if(devConfig[i])
rcode = devConfig[i]->Release(); rcode = devConfig[i]->Release();
usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
@ -475,7 +475,7 @@ void USB::Task(void) //USB state machine
case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
break; break;
case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
if (delay < millis()) if(delay < millis())
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
else break; // don't fall through else break; // don't fall through
case USB_ATTACHED_SUBSTATE_RESET_DEVICE: case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
@ -483,7 +483,7 @@ void USB::Task(void) //USB state machine
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE; usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
break; break;
case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
if ((regRd(rHCTL) & bmBUSRST) == 0) { if((regRd(rHCTL) & bmBUSRST) == 0) {
tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
regWr(rMODE, tmpdata); regWr(rMODE, tmpdata);
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF; usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
@ -491,7 +491,7 @@ void USB::Task(void) //USB state machine
} }
break; break;
case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
if (regRd(rHIRQ) & bmFRAMEIRQ) { if(regRd(rHIRQ) & bmFRAMEIRQ) {
//when first SOF received _and_ 20ms has passed we can continue //when first SOF received _and_ 20ms has passed we can continue
/* /*
if (delay < millis()) //20ms passed if (delay < millis()) //20ms passed
@ -502,7 +502,7 @@ void USB::Task(void) //USB state machine
} }
break; break;
case USB_ATTACHED_SUBSTATE_WAIT_RESET: case USB_ATTACHED_SUBSTATE_WAIT_RESET:
if (delay < millis()) usb_task_state = USB_STATE_CONFIGURING; if(delay < millis()) usb_task_state = USB_STATE_CONFIGURING;
else break; // don't fall through else break; // don't fall through
case USB_STATE_CONFIGURING: case USB_STATE_CONFIGURING:
@ -511,8 +511,8 @@ void USB::Task(void) //USB state machine
rcode = Configuring(0, 0, lowspeed); rcode = Configuring(0, 0, lowspeed);
if (rcode) { if(rcode) {
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) { if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {
usb_error = rcode; usb_error = rcode;
usb_task_state = USB_STATE_ERROR; usb_task_state = USB_STATE_ERROR;
} }
@ -535,10 +535,10 @@ uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p0 = addrPool.GetUsbDevicePtr(0); p0 = addrPool.GetUsbDevicePtr(0);
if (!p0) if(!p0)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p0->epinfo) if(!p0->epinfo)
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
p0->lowspeed = (lowspeed) ? true : false; p0->lowspeed = (lowspeed) ? true : false;
@ -546,12 +546,12 @@ uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
// Allocate new address according to device class // Allocate new address according to device class
uint8_t bAddress = addrPool.AllocAddress(parent, false, port); uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
@ -559,7 +559,7 @@ uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign new address to the device // Assign new address to the device
rcode = setAddr(0, 0, bAddress); rcode = setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
return rcode; return rcode;
@ -573,8 +573,8 @@ uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lo
again: again:
uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed); uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
if (rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) { if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) {
if (parent == 0) { if(parent == 0) {
// Send a bus reset on the root interface. // Send a bus reset on the root interface.
regWr(rHCTL, bmBUSRST); //issue bus reset regWr(rHCTL, bmBUSRST); //issue bus reset
delay(102); // delay 102ms, compensate for clock inaccuracy. delay(102); // delay 102ms, compensate for clock inaccuracy.
@ -582,22 +582,22 @@ again:
// reset parent port // reset parent port
devConfig[parent]->ResetHubPort(port); devConfig[parent]->ResetHubPort(port);
} }
} else if (rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
delay(100); delay(100);
retries++; retries++;
goto again; goto again;
} else if (rcode) } else if(rcode)
return rcode; return rcode;
rcode = devConfig[driver]->Init(parent, port, lowspeed); rcode = devConfig[driver]->Init(parent, port, lowspeed);
if (rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
delay(100); delay(100);
retries++; retries++;
goto again; goto again;
} }
if (rcode) { if(rcode) {
// Issue a bus reset, because the device may be in a limbo state // Issue a bus reset, because the device may be in a limbo state
if (parent == 0) { if(parent == 0) {
// Send a bus reset on the root interface. // Send a bus reset on the root interface.
regWr(rHCTL, bmBUSRST); //issue bus reset regWr(rHCTL, bmBUSRST); //issue bus reset
delay(102); // delay 102ms, compensate for clock inaccuracy. delay(102); // delay 102ms, compensate for clock inaccuracy.
@ -669,7 +669,7 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
AddressPool &addrPool = GetAddressPool(); AddressPool &addrPool = GetAddressPool();
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) { if(!p) {
//printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n"); //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
@ -689,7 +689,7 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (rcode) { if(rcode) {
//printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n"); //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
return rcode; return rcode;
} }
@ -705,30 +705,30 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
uint8_t klass = udd->bDeviceClass; uint8_t klass = udd->bDeviceClass;
// Attempt to configure if VID/PID or device class matches with a driver // Attempt to configure if VID/PID or device class matches with a driver
for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
if (!devConfig[devConfigIndex]) continue; // no driver if(!devConfig[devConfigIndex]) continue; // no driver
if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
if (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) { if(devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) {
rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED) if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
break; break;
} }
} }
if (devConfigIndex < USB_NUMDEVICES) { if(devConfigIndex < USB_NUMDEVICES) {
return rcode; return rcode;
} }
// blindly attempt to configure // blindly attempt to configure
for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
if (!devConfig[devConfigIndex]) continue; if(!devConfig[devConfigIndex]) continue;
if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
if (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above if(devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
//printf("ERROR ENUMERATING %2.2x\r\n", rcode); //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) { if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
// in case of an error dev_index should be reset to 0 // in case of an error dev_index should be reset to 0
// in order to start from the very beginning the // in order to start from the very beginning the
// next time the program gets here // next time the program gets here
@ -744,12 +744,12 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
} }
uint8_t USB::ReleaseDevice(uint8_t addr) { uint8_t USB::ReleaseDevice(uint8_t addr) {
if (!addr) if(!addr)
return 0; return 0;
for (uint8_t i = 0; i < USB_NUMDEVICES; i++) { for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
if (!devConfig[i]) continue; if(!devConfig[i]) continue;
if (devConfig[i]->GetAddress() == addr) if(devConfig[i]->GetAddress() == addr)
return devConfig[i]->Release(); return devConfig[i]->Release();
} }
return 0; return 0;
@ -776,7 +776,7 @@ uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser
uint8_t ret = getConfDescr(addr, ep, 9, conf, buf); uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
if (ret) if(ret)
return ret; return ret;
uint16_t total = ucd->wTotalLength; uint16_t total = ucd->wTotalLength;
@ -807,4 +807,3 @@ uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
} }
#endif // defined(USB_METHODS_INLINE) #endif // defined(USB_METHODS_INLINE)

View file

@ -104,14 +104,38 @@ typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega
class USBDeviceConfig { class USBDeviceConfig {
public: public:
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) { return 0; }
virtual uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {return 0; } virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) {
virtual uint8_t Release() { return 0; } return 0;
virtual uint8_t Poll() { return 0; } }
virtual uint8_t GetAddress() { return 0; }
virtual void ResetHubPort(uint8_t port) { return; } // Note used for hubs only! virtual uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
virtual boolean VIDPIDOK(uint16_t vid, uint16_t pid) { return false; } return 0;
virtual boolean DEVCLASSOK(uint8_t klass) { return false; } }
virtual uint8_t Release() {
return 0;
}
virtual uint8_t Poll() {
return 0;
}
virtual uint8_t GetAddress() {
return 0;
}
virtual void ResetHubPort(uint8_t port) {
return;
} // Note used for hubs only!
virtual boolean VIDPIDOK(uint16_t vid, uint16_t pid) {
return false;
}
virtual boolean DEVCLASSOK(uint8_t klass) {
return false;
}
}; };
/* USB Setup Packet Structure */ /* USB Setup Packet Structure */
@ -138,7 +162,7 @@ typedef struct {
} wVal_u; } wVal_u;
uint16_t wIndex; // 4 Depends on bRequest uint16_t wIndex; // 4 Depends on bRequest
uint16_t wLength; // 6 Depends on bRequest uint16_t wLength; // 6 Depends on bRequest
}__attribute__((packed)) SETUP_PKT, *PSETUP_PKT; } __attribute__((packed)) SETUP_PKT, *PSETUP_PKT;
@ -166,7 +190,7 @@ public:
}; };
AddressPool& GetAddressPool() { AddressPool& GetAddressPool() {
return(AddressPool&) addrPool; return (AddressPool&)addrPool;
}; };
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) { uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) {
@ -225,30 +249,29 @@ private:
//get device descriptor //get device descriptor
inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) { inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
return( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr)); return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr));
} }
//get configuration descriptor //get configuration descriptor
inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) { inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
return( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr)); return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr));
} }
//get string descriptor //get string descriptor
inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) { inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) {
return( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr)); return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr));
} }
//set address //set address
inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) { inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
return( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL)); return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));
} }
//set configuration //set configuration
inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
return( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL)); return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));
} }
#endif // defined(USB_METHODS_INLINE) #endif // defined(USB_METHODS_INLINE)
#endif /* USBCORE_H */ #endif /* USBCORE_H */

281
Wii.cpp
View file

@ -84,7 +84,7 @@ const uint32_t PROCONTROLLERBUTTONS[] PROGMEM = {
WII::WII(BTD *p, bool pair) : WII::WII(BTD *p, bool pair) :
pBtd(p) // pointer to USB class instance - mandatory pBtd(p) // pointer to USB class instance - mandatory
{ {
if (pBtd) if(pBtd)
pBtd->registerServiceClass(this); // Register it as a Bluetooth service pBtd->registerServiceClass(this); // Register it as a Bluetooth service
pBtd->pairWithWii = pair; pBtd->pairWithWii = pair;
@ -115,8 +115,8 @@ void WII::Reset() {
} }
void WII::disconnect() { // Use this void to disconnect any of the controllers void WII::disconnect() { // Use this void to disconnect any of the controllers
if (!motionPlusInside) { // The old Wiimote needs a delay after the first command or it will automatically reconnect if(!motionPlusInside) { // The old Wiimote needs a delay after the first command or it will automatically reconnect
if (motionPlusConnected) { if(motionPlusConnected) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80); Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80);
#endif #endif
@ -132,9 +132,9 @@ void WII::disconnect() { // Use this void to disconnect any of the controllers
} }
void WII::ACLData(uint8_t* l2capinbuf) { void WII::ACLData(uint8_t* l2capinbuf) {
if (!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) { if(!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) {
if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
motionPlusInside = pBtd->motionPlusInside; motionPlusInside = pBtd->motionPlusInside;
pBtd->incomingWii = false; pBtd->incomingWii = false;
pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
@ -144,9 +144,9 @@ void WII::ACLData(uint8_t* l2capinbuf) {
} }
} }
} }
if ((l2capinbuf[0] | (uint16_t)l2capinbuf[1] << 8) == (hci_handle | 0x2000U)) { // acl_handle_ok or it's a new connection if((l2capinbuf[0] | (uint16_t)l2capinbuf[1] << 8) == (hci_handle | 0x2000U)) { // acl_handle_ok or it's a new connection
if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { //l2cap_control - Channel ID for ACL-U if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { //l2cap_control - Channel ID for ACL-U
if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
@ -161,15 +161,15 @@ void WII::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
#endif #endif
} else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {
if (((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success
if (l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) {
//Notify(PSTR("\r\nHID Control Connection Complete"), 0x80); //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
control_scid[0] = l2capinbuf[12]; control_scid[0] = l2capinbuf[12];
control_scid[1] = l2capinbuf[13]; control_scid[1] = l2capinbuf[13];
l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED); l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED);
} else if (l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {
//Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80); //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
interrupt_scid[0] = l2capinbuf[12]; interrupt_scid[0] = l2capinbuf[12];
@ -177,7 +177,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED); l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED);
} }
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
@ -190,46 +190,46 @@ void WII::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR(" Identifier: "), 0x80); Notify(PSTR(" Identifier: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
#endif #endif
if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
control_scid[0] = l2capinbuf[14]; control_scid[0] = l2capinbuf[14];
control_scid[1] = l2capinbuf[15]; control_scid[1] = l2capinbuf[15];
l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);
} else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
interrupt_scid[0] = l2capinbuf[14]; interrupt_scid[0] = l2capinbuf[14];
interrupt_scid[1] = l2capinbuf[15]; interrupt_scid[1] = l2capinbuf[15];
l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);
} }
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
#endif #endif
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
Reset(); Reset();
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
#endif #endif
@ -237,12 +237,12 @@ void WII::ACLData(uint8_t* l2capinbuf) {
pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
Reset(); Reset();
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
//Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);
} else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
//Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);
@ -255,41 +255,41 @@ void WII::ACLData(uint8_t* l2capinbuf) {
D_PrintHex<uint8_t > (l2capinbuf[8], 0x80); D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
} }
#endif #endif
} else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
//Notify(PSTR("\r\nL2CAP Interrupt"), 0x80); //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
if ((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons
if ((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes
ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));
else if (wiiUProControllerConnected) else if(wiiUProControllerConnected)
ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16)); ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16));
else if (motionPlusConnected) { else if(motionPlusConnected) {
if (l2capinbuf[20] & 0x02) // Only update the wiimote buttons, since the extension bytes are from the Motion Plus if(l2capinbuf[20] & 0x02) // Only update the wiimote buttons, since the extension bytes are from the Motion Plus
ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000))); ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000)));
else if (nunchuckConnected) // Update if it's a report from the Nunchuck else if(nunchuckConnected) // Update if it's a report from the Nunchuck
ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14)); ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14));
//else if(classicControllerConnected) // Update if it's a report from the Classic Controller //else if(classicControllerConnected) // Update if it's a report from the Classic Controller
} else if (nunchuckConnected) // The Nunchuck is directly connected } else if(nunchuckConnected) // The Nunchuck is directly connected
ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16)); ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16));
//else if(classicControllerConnected) // The Classic Controller is directly connected //else if(classicControllerConnected) // The Classic Controller is directly connected
else if (!unknownExtensionConnected) else if(!unknownExtensionConnected)
ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));
#ifdef PRINTREPORT #ifdef PRINTREPORT
Notify(PSTR("ButtonState: "), 0x80); Notify(PSTR("ButtonState: "), 0x80);
D_PrintHex<uint32_t > (ButtonState, 0x80); D_PrintHex<uint32_t > (ButtonState, 0x80);
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
#endif #endif
if (ButtonState != OldButtonState) { if(ButtonState != OldButtonState) {
ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
OldButtonState = ButtonState; OldButtonState = ButtonState;
} }
} }
if (l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer if(l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer
accXwiimote = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5)) - 500; accXwiimote = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5)) - 500;
accYwiimote = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4)) - 500; accYwiimote = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4)) - 500;
accZwiimote = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5)) - 500; accZwiimote = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5)) - 500;
} }
switch (l2capinbuf[9]) { switch(l2capinbuf[9]) {
case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nStatus report was received"), 0x80); Notify(PSTR("\r\nStatus report was received"), 0x80);
@ -297,33 +297,33 @@ void WII::ACLData(uint8_t* l2capinbuf) {
wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)
batteryLevel = l2capinbuf[15]; // Update battery level batteryLevel = l2capinbuf[15]; // Update battery level
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (l2capinbuf[12] & 0x01) if(l2capinbuf[12] & 0x01)
Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80); Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80);
#endif #endif
if (checkExtension) { // If this is false it means that the user must have called getBatteryLevel() if(checkExtension) { // If this is false it means that the user must have called getBatteryLevel()
if (l2capinbuf[12] & 0x02) { // Check if a extension is connected if(l2capinbuf[12] & 0x02) { // Check if a extension is connected
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (!unknownExtensionConnected) if(!unknownExtensionConnected)
Notify(PSTR("\r\nExtension connected"), 0x80); Notify(PSTR("\r\nExtension connected"), 0x80);
#endif #endif
unknownExtensionConnected = true; unknownExtensionConnected = true;
#ifdef WIICAMERA #ifdef WIICAMERA
if (!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
#endif #endif
setReportMode(false, 0x35); // Also read the extension setReportMode(false, 0x35); // Also read the extension
} else { } else {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nExtension disconnected"), 0x80); Notify(PSTR("\r\nExtension disconnected"), 0x80);
#endif #endif
if (motionPlusConnected) { if(motionPlusConnected) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR(" - from Motion Plus"), 0x80); Notify(PSTR(" - from Motion Plus"), 0x80);
#endif #endif
wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED); wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED);
if (!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false if(!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false
nunchuckConnected = false; nunchuckConnected = false;
//else if(classicControllerConnected) //else if(classicControllerConnected)
} else if (nunchuckConnected) { } else if(nunchuckConnected) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR(" - Nunchuck"), 0x80); Notify(PSTR(" - Nunchuck"), 0x80);
#endif #endif
@ -338,28 +338,28 @@ void WII::ACLData(uint8_t* l2capinbuf) {
checkExtension = true; // Check for extensions by default checkExtension = true; // Check for extensions by default
break; break;
case 0x21: // Read Memory Data case 0x21: // Read Memory Data
if ((l2capinbuf[12] & 0x0F) == 0) { // No error if((l2capinbuf[12] & 0x0F) == 0) { // No error
// See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers
if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) { if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nNunchuck connected"), 0x80); Notify(PSTR("\r\nNunchuck connected"), 0x80);
#endif #endif
wii_set_flag(WII_FLAG_NUNCHUCK_CONNECTED); wii_set_flag(WII_FLAG_NUNCHUCK_CONNECTED);
} else if (l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) { } else if(l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nMotion Plus connected"), 0x80); Notify(PSTR("\r\nMotion Plus connected"), 0x80);
#endif #endif
wii_set_flag(WII_FLAG_MOTION_PLUS_CONNECTED); wii_set_flag(WII_FLAG_MOTION_PLUS_CONNECTED);
} else if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) { } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80); Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80);
#endif #endif
motionPlusConnected = true; motionPlusConnected = true;
#ifdef WIICAMERA #ifdef WIICAMERA
if (!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
#endif #endif
setReportMode(false, 0x35); // Also read the extension setReportMode(false, 0x35); // Also read the extension
} else if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) { } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80); Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80);
#endif #endif
@ -367,16 +367,16 @@ void WII::ACLData(uint8_t* l2capinbuf) {
motionPlusConnected = true; motionPlusConnected = true;
nunchuckConnected = true; nunchuckConnected = true;
#ifdef WIICAMERA #ifdef WIICAMERA
if (!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
#endif #endif
setReportMode(false, 0x35); // Also read the extension setReportMode(false, 0x35); // Also read the extension
} else if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) { } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80); Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80);
Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80); Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80);
#endif #endif
stateCounter = 300; // Skip the rest in "WII_CHECK_MOTION_PLUS_STATE" stateCounter = 300; // Skip the rest in "WII_CHECK_MOTION_PLUS_STATE"
} else if (l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) { } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80); Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80);
#endif #endif
@ -388,7 +388,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
Notify(PSTR("\r\nData: "), 0x80); Notify(PSTR("\r\nData: "), 0x80);
for (uint8_t i = 0; i < ((l2capinbuf[12] >> 4) + 1); i++) { // bit 4-7 is the length-1 for(uint8_t i = 0; i < ((l2capinbuf[12] >> 4) + 1); i++) { // bit 4-7 is the length-1
D_PrintHex<uint8_t > (l2capinbuf[15 + i], 0x80); D_PrintHex<uint8_t > (l2capinbuf[15 + i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -405,7 +405,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
break; break;
case 0x22: // Acknowledge output report, return function result case 0x22: // Acknowledge output report, return function result
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (l2capinbuf[13] != 0x00) { // Check if there is an error if(l2capinbuf[13] != 0x00) { // Check if there is an error
Notify(PSTR("\r\nCommand failed: "), 0x80); Notify(PSTR("\r\nCommand failed: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[12], 0x80); D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
} }
@ -461,9 +461,9 @@ void WII::ACLData(uint8_t* l2capinbuf) {
break; break;
case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes
// (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
if (motionPlusConnected) { if(motionPlusConnected) {
if (l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension
if (motionValuesReset) { // We will only use the values when the gyro value has been set if(motionValuesReset) { // We will only use the values when the gyro value has been set
gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)) - gyroYawZero); gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)) - gyroYawZero);
gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero); gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero);
gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero); gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero);
@ -473,11 +473,11 @@ void WII::ACLData(uint8_t* l2capinbuf) {
pitchGyroSpeed = (double)gyroPitchRaw / ((double)gyroPitchZero / pitchGyroScale); pitchGyroSpeed = (double)gyroPitchRaw / ((double)gyroPitchZero / pitchGyroScale);
/* The onboard gyro has two ranges for slow and fast mode */ /* The onboard gyro has two ranges for slow and fast mode */
if (!(l2capinbuf[18] & 0x02)) // Check if fast mode is used if(!(l2capinbuf[18] & 0x02)) // Check if fast mode is used
yawGyroSpeed *= 4.545; yawGyroSpeed *= 4.545;
if (!(l2capinbuf[18] & 0x01)) // Check if fast mode is used if(!(l2capinbuf[18] & 0x01)) // Check if fast mode is used
pitchGyroSpeed *= 4.545; pitchGyroSpeed *= 4.545;
if (!(l2capinbuf[19] & 0x02)) // Check if fast mode is used if(!(l2capinbuf[19] & 0x02)) // Check if fast mode is used
rollGyroSpeed *= 4.545; rollGyroSpeed *= 4.545;
compPitch = (0.93 * (compPitch + (pitchGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimotePitch()); // Use a complimentary filter to calculate the angle compPitch = (0.93 * (compPitch + (pitchGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimotePitch()); // Use a complimentary filter to calculate the angle
@ -495,15 +495,15 @@ void WII::ACLData(uint8_t* l2capinbuf) {
Notify(gyroRoll, 0x80); Notify(gyroRoll, 0x80);
Notify(PSTR("\tgyroPitch: "), 0x80); Notify(PSTR("\tgyroPitch: "), 0x80);
Notify(gyroPitch, 0x80); Notify(gyroPitch, 0x80);
*/ */
/* /*
Notify(PSTR("\twiimoteRoll: "), 0x80); Notify(PSTR("\twiimoteRoll: "), 0x80);
Notify(wiimoteRoll, 0x80); Notify(wiimoteRoll, 0x80);
Notify(PSTR("\twiimotePitch: "), 0x80); Notify(PSTR("\twiimotePitch: "), 0x80);
Notify(wiimotePitch, 0x80); Notify(wiimotePitch, 0x80);
*/ */
} else { } else {
if ((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values if((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nThe gyro values has been reset"), 0x80); Notify(PSTR("\r\nThe gyro values has been reset"), 0x80);
#endif #endif
@ -524,7 +524,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
} }
} }
} else { } else {
if (nunchuckConnected) { if(nunchuckConnected) {
hatValues[HatX] = l2capinbuf[15]; hatValues[HatX] = l2capinbuf[15];
hatValues[HatY] = l2capinbuf[16]; hatValues[HatY] = l2capinbuf[16];
accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3)) - 416; accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3)) - 416;
@ -533,8 +533,8 @@ void WII::ACLData(uint8_t* l2capinbuf) {
} }
//else if(classicControllerConnected) { } //else if(classicControllerConnected) { }
} }
if (l2capinbuf[19] & 0x01) { if(l2capinbuf[19] & 0x01) {
if (!extensionConnected) { if(!extensionConnected) {
extensionConnected = true; extensionConnected = true;
unknownExtensionConnected = true; unknownExtensionConnected = true;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -542,7 +542,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
#endif #endif
} }
} else { } else {
if (extensionConnected && !unknownExtensionConnected) { if(extensionConnected && !unknownExtensionConnected) {
extensionConnected = false; extensionConnected = false;
unknownExtensionConnected = true; unknownExtensionConnected = true;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -552,13 +552,13 @@ void WII::ACLData(uint8_t* l2capinbuf) {
} }
} }
} else if (nunchuckConnected) { } else if(nunchuckConnected) {
hatValues[HatX] = l2capinbuf[15]; hatValues[HatX] = l2capinbuf[15];
hatValues[HatY] = l2capinbuf[16]; hatValues[HatY] = l2capinbuf[16];
accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2)) - 416; accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2)) - 416;
accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4)) - 416; accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4)) - 416;
accZnunchuck = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6)) - 416; accZnunchuck = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6)) - 416;
} else if (wiiUProControllerConnected) { } else if(wiiUProControllerConnected) {
hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8); hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8);
hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8); hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8);
hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8); hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8);
@ -579,10 +579,10 @@ void WII::ACLData(uint8_t* l2capinbuf) {
} }
void WII::L2CAP_task() { void WII::L2CAP_task() {
switch (l2cap_state) { switch(l2cap_state) {
/* These states are used if the Wiimote is the host */ /* These states are used if the Wiimote is the host */
case L2CAP_CONTROL_SUCCESS: case L2CAP_CONTROL_SUCCESS:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
#endif #endif
@ -591,7 +591,7 @@ void WII::L2CAP_task() {
break; break;
case L2CAP_INTERRUPT_SETUP: case L2CAP_INTERRUPT_SETUP:
if (l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
#endif #endif
@ -608,7 +608,7 @@ void WII::L2CAP_task() {
/* These states are used if the Arduino is the host */ /* These states are used if the Arduino is the host */
case L2CAP_CONTROL_CONNECT_REQUEST: case L2CAP_CONTROL_CONNECT_REQUEST:
if (l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) { if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); Notify(PSTR("\r\nSend HID Control Config Request"), 0x80);
#endif #endif
@ -619,7 +619,7 @@ void WII::L2CAP_task() {
break; break;
case L2CAP_CONTROL_CONFIG_REQUEST: case L2CAP_CONTROL_CONFIG_REQUEST:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80);
#endif #endif
@ -630,7 +630,7 @@ void WII::L2CAP_task() {
break; break;
case L2CAP_INTERRUPT_CONNECT_REQUEST: case L2CAP_INTERRUPT_CONNECT_REQUEST:
if (l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) { if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80);
#endif #endif
@ -641,7 +641,7 @@ void WII::L2CAP_task() {
break; break;
case L2CAP_INTERRUPT_CONFIG_REQUEST: case L2CAP_INTERRUPT_CONFIG_REQUEST:
if (l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Channels Established"), 0x80); Notify(PSTR("\r\nHID Channels Established"), 0x80);
#endif #endif
@ -655,7 +655,7 @@ void WII::L2CAP_task() {
/* The next states are in run() */ /* The next states are in run() */
case L2CAP_INTERRUPT_DISCONNECT: case L2CAP_INTERRUPT_DISCONNECT:
if (l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && millis() > timer) { if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && millis() > timer) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
#endif #endif
@ -666,7 +666,7 @@ void WII::L2CAP_task() {
break; break;
case L2CAP_CONTROL_DISCONNECT: case L2CAP_CONTROL_DISCONNECT:
if (l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
#endif #endif
@ -680,12 +680,12 @@ void WII::L2CAP_task() {
} }
void WII::Run() { void WII::Run() {
if (l2cap_state == L2CAP_INTERRUPT_DISCONNECT && millis() > timer) if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && millis() > timer)
L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough
switch (l2cap_state) { switch(l2cap_state) {
case L2CAP_WAIT: case L2CAP_WAIT:
if (pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) { if(pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) {
pBtd->l2capConnectionClaimed = true; pBtd->l2capConnectionClaimed = true;
activeConnection = true; activeConnection = true;
motionPlusInside = pBtd->motionPlusInside; motionPlusInside = pBtd->motionPlusInside;
@ -697,7 +697,7 @@ void WII::Run() {
identifier = 0; identifier = 0;
pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM); pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM);
l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;
} else if (l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
#endif #endif
@ -713,25 +713,25 @@ void WII::Run() {
case WII_CHECK_MOTION_PLUS_STATE: case WII_CHECK_MOTION_PLUS_STATE:
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (stateCounter == 0) // Only print onnce if(stateCounter == 0) // Only print onnce
Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80); Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80);
#endif #endif
stateCounter++; stateCounter++;
if (stateCounter % 200 == 0) if(stateCounter % 200 == 0)
checkMotionPresent(); // Check if there is a motion plus connected checkMotionPresent(); // Check if there is a motion plus connected
if (wii_check_flag(WII_FLAG_MOTION_PLUS_CONNECTED)) { if(wii_check_flag(WII_FLAG_MOTION_PLUS_CONNECTED)) {
stateCounter = 0; stateCounter = 0;
l2cap_state = WII_INIT_MOTION_PLUS_STATE; l2cap_state = WII_INIT_MOTION_PLUS_STATE;
timer = micros(); timer = micros();
if (unknownExtensionConnected) { if(unknownExtensionConnected) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nA extension is also connected"), 0x80); Notify(PSTR("\r\nA extension is also connected"), 0x80);
#endif #endif
activateNunchuck = true; // For we will just set this to true as this the only extension supported so far activateNunchuck = true; // For we will just set this to true as this the only extension supported so far
} }
} else if (stateCounter == 601) { // We will try three times to check for the motion plus } else if(stateCounter == 601) { // We will try three times to check for the motion plus
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80); Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80);
#endif #endif
@ -742,23 +742,23 @@ void WII::Run() {
case WII_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port case WII_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (stateCounter == 0) // Only print onnce if(stateCounter == 0) // Only print onnce
Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80); Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80);
#endif #endif
stateCounter++; // We use this counter as there has to be a short delay between the commands stateCounter++; // We use this counter as there has to be a short delay between the commands
if (stateCounter == 1) if(stateCounter == 1)
statusRequest(); // See if a new device has connected statusRequest(); // See if a new device has connected
if (stateCounter == 100) { if(stateCounter == 100) {
if (unknownExtensionConnected) // Check if there is a extension is connected to the port if(unknownExtensionConnected) // Check if there is a extension is connected to the port
initExtension1(); initExtension1();
else else
stateCounter = 399; stateCounter = 399;
} else if (stateCounter == 200) } else if(stateCounter == 200)
initExtension2(); initExtension2();
else if (stateCounter == 300) { else if(stateCounter == 300) {
readExtensionType(); readExtensionType();
unknownExtensionConnected = false; unknownExtensionConnected = false;
} else if (stateCounter == 400) { } else if(stateCounter == 400) {
stateCounter = 0; stateCounter = 0;
l2cap_state = TURN_ON_LED; l2cap_state = TURN_ON_LED;
} }
@ -766,13 +766,13 @@ void WII::Run() {
case WII_INIT_MOTION_PLUS_STATE: case WII_INIT_MOTION_PLUS_STATE:
stateCounter++; stateCounter++;
if (stateCounter == 1) if(stateCounter == 1)
initMotionPlus(); initMotionPlus();
else if (stateCounter == 100) else if(stateCounter == 100)
activateMotionPlus(); activateMotionPlus();
else if (stateCounter == 200) else if(stateCounter == 200)
readExtensionType(); // Check if it has been activated readExtensionType(); // Check if it has been activated
else if (stateCounter == 300) { else if(stateCounter == 300) {
stateCounter = 0; stateCounter = 0;
unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus
l2cap_state = TURN_ON_LED; l2cap_state = TURN_ON_LED;
@ -780,7 +780,7 @@ void WII::Run() {
break; break;
case TURN_ON_LED: case TURN_ON_LED:
if (wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED))
nunchuckConnected = true; nunchuckConnected = true;
wiimoteConnected = true; wiimoteConnected = true;
onInit(); onInit();
@ -788,46 +788,46 @@ void WII::Run() {
break; break;
case L2CAP_DONE: case L2CAP_DONE:
if (unknownExtensionConnected) { if(unknownExtensionConnected) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if (stateCounter == 0) // Only print once if(stateCounter == 0) // Only print once
Notify(PSTR("\r\nChecking extension port"), 0x80); Notify(PSTR("\r\nChecking extension port"), 0x80);
#endif #endif
stateCounter++; // We will use this counter as there has to be a short delay between the commands stateCounter++; // We will use this counter as there has to be a short delay between the commands
if (stateCounter == 50) if(stateCounter == 50)
statusRequest(); statusRequest();
else if (stateCounter == 100) else if(stateCounter == 100)
initExtension1(); initExtension1();
else if (stateCounter == 150) else if(stateCounter == 150)
if ((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected)) if((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected))
initExtension2(); initExtension2();
else else
stateCounter = 299; // There is no extension connected stateCounter = 299; // There is no extension connected
else if (stateCounter == 200) else if(stateCounter == 200)
readExtensionType(); readExtensionType();
else if (stateCounter == 250) { else if(stateCounter == 250) {
if (wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) { if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nNunchuck was reconnected"), 0x80); Notify(PSTR("\r\nNunchuck was reconnected"), 0x80);
#endif #endif
activateNunchuck = true; activateNunchuck = true;
nunchuckConnected = true; nunchuckConnected = true;
} }
if (!motionPlusConnected) if(!motionPlusConnected)
stateCounter = 449; stateCounter = 449;
} else if (stateCounter == 300) { } else if(stateCounter == 300) {
if (motionPlusConnected) { if(motionPlusConnected) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80); Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80);
#endif #endif
initMotionPlus(); initMotionPlus();
} else } else
stateCounter = 449; stateCounter = 449;
} else if (stateCounter == 350) } else if(stateCounter == 350)
activateMotionPlus(); activateMotionPlus();
else if (stateCounter == 400) else if(stateCounter == 400)
readExtensionType(); // Check if it has been activated readExtensionType(); // Check if it has been activated
else if (stateCounter == 450) { else if(stateCounter == 450) {
onInit(); onInit();
stateCounter = 0; stateCounter = 0;
unknownExtensionConnected = false; unknownExtensionConnected = false;
@ -843,7 +843,7 @@ void WII::Run() {
/************************************************************/ /************************************************************/
void WII::HID_Command(uint8_t* data, uint8_t nbytes) { void WII::HID_Command(uint8_t* data, uint8_t nbytes) {
if (motionPlusInside) if(motionPlusInside)
pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new wiimote with the Motion Plus Inside pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new wiimote with the Motion Plus Inside
else else
pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);
@ -878,6 +878,7 @@ void WII::setLedRaw(uint8_t value) {
HIDBuffer[2] = value | (HIDBuffer[2] & 0x01); // Keep the rumble bit HIDBuffer[2] = value | (HIDBuffer[2] & 0x01); // Keep the rumble bit
HID_Command(HIDBuffer, 3); HID_Command(HIDBuffer, 3);
} }
void WII::setLedOff(LED a) { void WII::setLedOff(LED a) {
HIDBuffer[1] = 0x11; HIDBuffer[1] = 0x11;
HIDBuffer[2] &= ~(pgm_read_byte(&LEDS[(uint8_t)a])); HIDBuffer[2] &= ~(pgm_read_byte(&LEDS[(uint8_t)a]));
@ -899,11 +900,11 @@ void WII::setLedToggle(LED a) {
void WII::setLedStatus() { void WII::setLedStatus() {
HIDBuffer[1] = 0x11; HIDBuffer[1] = 0x11;
HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit
if (wiimoteConnected) if(wiimoteConnected)
HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up
if (motionPlusConnected) if(motionPlusConnected)
HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up
if (nunchuckConnected) if(nunchuckConnected)
HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up
HID_Command(HIDBuffer, 3); HID_Command(HIDBuffer, 3);
@ -919,7 +920,7 @@ void WII::setReportMode(bool continuous, uint8_t mode) {
uint8_t cmd_buf[4]; uint8_t cmd_buf[4];
cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
cmd_buf[1] = 0x12; cmd_buf[1] = 0x12;
if (continuous) if(continuous)
cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit
else else
cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit
@ -949,9 +950,9 @@ void WII::writeData(uint32_t offset, uint8_t size, uint8_t* data) {
cmd_buf[5] = (uint8_t)(offset & 0xFF); cmd_buf[5] = (uint8_t)(offset & 0xFF);
cmd_buf[6] = size; cmd_buf[6] = size;
uint8_t i = 0; uint8_t i = 0;
for (; i < size; i++) for(; i < size; i++)
cmd_buf[7 + i] = data[i]; cmd_buf[7 + i] = data[i];
for (; i < 16; i++) // Set the rest to zero for(; i < 16; i++) // Set the rest to zero
cmd_buf[7 + i] = 0x00; cmd_buf[7 + i] = 0x00;
HID_Command(cmd_buf, 23); HID_Command(cmd_buf, 23);
} }
@ -976,17 +977,17 @@ void WII::initMotionPlus() {
void WII::activateMotionPlus() { void WII::activateMotionPlus() {
uint8_t buf[1]; uint8_t buf[1];
if (pBtd->wiiUProController) { if(pBtd->wiiUProController) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80); Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80);
#endif #endif
buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07 buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07
} else if (activateNunchuck) { } else if(activateNunchuck) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80); Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80);
#endif #endif
buf[0] = 0x05; // Activate nunchuck pass-through mode buf[0] = 0x05; // Activate nunchuck pass-through mode
} //else if(classicControllerConnected && extensionConnected) }//else if(classicControllerConnected && extensionConnected)
//buf[0] = 0x07; //buf[0] = 0x07;
else { else {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -1001,7 +1002,7 @@ void WII::readData(uint32_t offset, uint16_t size, bool EEPROM) {
uint8_t cmd_buf[8]; uint8_t cmd_buf[8];
cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
cmd_buf[1] = 0x17; // Read data cmd_buf[1] = 0x17; // Read data
if (EEPROM) if(EEPROM)
cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM
else else
cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory
@ -1032,7 +1033,7 @@ void WII::checkMotionPresent() {
/************************************************************/ /************************************************************/
bool WII::getButtonPress(Button b) { // Return true when a button is pressed bool WII::getButtonPress(Button b) { // Return true when a button is pressed
if (wiiUProControllerConnected) if(wiiUProControllerConnected)
return (ButtonState & pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b])); return (ButtonState & pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b]));
else else
return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b])); return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b]));
@ -1040,7 +1041,7 @@ bool WII::getButtonPress(Button b) { // Return true when a button is pressed
bool WII::getButtonClick(Button b) { // Only return true when a button is clicked bool WII::getButtonClick(Button b) { // Only return true when a button is clicked
uint32_t button; uint32_t button;
if (wiiUProControllerConnected) if(wiiUProControllerConnected)
button = pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b]); button = pgm_read_dword(&PROCONTROLLERBUTTONS[(uint8_t)b]);
else else
button = pgm_read_dword(&BUTTONS[(uint8_t)b]); button = pgm_read_dword(&BUTTONS[(uint8_t)b]);
@ -1050,11 +1051,11 @@ bool WII::getButtonClick(Button b) { // Only return true when a button is clicke
} }
uint8_t WII::getAnalogHat(Hat a) { uint8_t WII::getAnalogHat(Hat a) {
if (!nunchuckConnected) if(!nunchuckConnected)
return 127; // Return center position return 127; // Return center position
else { else {
uint8_t output = hatValues[(uint8_t)a]; uint8_t output = hatValues[(uint8_t)a];
if (output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position if(output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position
return 127; return 127;
else else
return output; return output;
@ -1062,11 +1063,11 @@ uint8_t WII::getAnalogHat(Hat a) {
} }
uint16_t WII::getAnalogHat(AnalogHat a) { uint16_t WII::getAnalogHat(AnalogHat a) {
if (!wiiUProControllerConnected) if(!wiiUProControllerConnected)
return 2000; return 2000;
else { else {
uint16_t output = hatValues[(uint8_t)a]; uint16_t output = hatValues[(uint8_t)a];
if (output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position if(output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position
return 2000; return 2000;
else else
return output; return output;
@ -1074,7 +1075,7 @@ uint16_t WII::getAnalogHat(AnalogHat a) {
} }
void WII::onInit() { void WII::onInit() {
if (pFuncOnInit) if(pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
else else
setLedStatus(); setLedStatus();

13
Wii.h
View file

@ -85,6 +85,7 @@ public:
/**@}*/ /**@}*/
/** @name Wii Controller functions */ /** @name Wii Controller functions */
/** Call this to start the paring sequence with a controller */ /** Call this to start the paring sequence with a controller */
void pair(void) { void pair(void) {
if(pBtd) if(pBtd)
@ -108,7 +109,7 @@ public:
* @return Pitch in the range from 0-360. * @return Pitch in the range from 0-360.
*/ */
double getPitch() { double getPitch() {
if (motionPlusConnected) if(motionPlusConnected)
return compPitch; return compPitch;
return getWiimotePitch(); return getWiimotePitch();
}; };
@ -118,7 +119,7 @@ public:
* @return Roll in the range from 0-360. * @return Roll in the range from 0-360.
*/ */
double getRoll() { double getRoll() {
if (motionPlusConnected) if(motionPlusConnected)
return compRoll; return compRoll;
return getWiimoteRoll(); return getWiimoteRoll();
}; };
@ -147,6 +148,7 @@ public:
* @param value See: ::LED enum. * @param value See: ::LED enum.
*/ */
void setLedRaw(uint8_t value); void setLedRaw(uint8_t value);
/** Turn all LEDs off. */ /** Turn all LEDs off. */
void setLedOff() { void setLedOff() {
setLedRaw(0); setLedRaw(0);
@ -180,6 +182,7 @@ public:
* @return The battery level in the range 0-255. * @return The battery level in the range 0-255.
*/ */
uint8_t getBatteryLevel(); uint8_t getBatteryLevel();
/** /**
* Return the Wiimote state. * Return the Wiimote state.
* @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status. * @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status.
@ -211,20 +214,24 @@ public:
/* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */ /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
/**@{*/ /**@{*/
/** Pitch and roll calculated from the accelerometer inside the Wiimote. */ /** Pitch and roll calculated from the accelerometer inside the Wiimote. */
double getWiimotePitch() { double getWiimotePitch() {
return (atan2(accYwiimote, accZwiimote) + PI) * RAD_TO_DEG; return (atan2(accYwiimote, accZwiimote) + PI) * RAD_TO_DEG;
}; };
double getWiimoteRoll() { double getWiimoteRoll() {
return (atan2(accXwiimote, accZwiimote) + PI) * RAD_TO_DEG; return (atan2(accXwiimote, accZwiimote) + PI) * RAD_TO_DEG;
}; };
/**@}*/ /**@}*/
/**@{*/ /**@{*/
/** Pitch and roll calculated from the accelerometer inside the Nunchuck. */ /** Pitch and roll calculated from the accelerometer inside the Nunchuck. */
double getNunchuckPitch() { double getNunchuckPitch() {
return (atan2(accYnunchuck, accZnunchuck) + PI) * RAD_TO_DEG; return (atan2(accYnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
}; };
double getNunchuckRoll() { double getNunchuckRoll() {
return (atan2(accXnunchuck, accZnunchuck) + PI) * RAD_TO_DEG; return (atan2(accXnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
}; };
@ -381,7 +388,7 @@ public:
* @return True if it's enabled, false if not. * @return True if it's enabled, false if not.
*/ */
bool isIRCameraEnabled() { bool isIRCameraEnabled() {
return(wiiState & 0x08); return (wiiState & 0x08);
}; };
/**@}*/ /**@}*/
#endif #endif

View file

@ -48,14 +48,14 @@ XBOXOLD::XBOXOLD(USB *p) :
pUsb(p), // pointer to USB class instance - mandatory pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory bAddress(0), // device address - mandatory
bPollEnable(false) { // don't start polling before dongle is connected bPollEnable(false) { // don't start polling before dongle is connected
for (uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
} }
if (pUsb) // register in USB subsystem if(pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry pUsb->RegisterDeviceClass(this); //set devConfig[] entry
} }
@ -74,7 +74,7 @@ uint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
Notify(PSTR("\r\nXBOXUSB Init"), 0x80); Notify(PSTR("\r\nXBOXUSB Init"), 0x80);
#endif #endif
// check if address has already been assigned to an instance // check if address has already been assigned to an instance
if (bAddress) { if(bAddress) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress in use"), 0x80); Notify(PSTR("\r\nAddress in use"), 0x80);
#endif #endif
@ -84,14 +84,14 @@ uint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) { if(!p) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
if (!p->epinfo) { if(!p->epinfo) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nepinfo is null"), 0x80); Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif #endif
@ -111,19 +111,19 @@ uint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
VID = udd->idVendor; VID = udd->idVendor;
PID = udd->idProduct; PID = udd->idProduct;
if ((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_OLD_PID1 && PID != XBOX_OLD_PID2 && PID != XBOX_OLD_PID3 && PID != XBOX_OLD_PID4)) // Check if VID and PID match if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_OLD_PID1 && PID != XBOX_OLD_PID2 && PID != XBOX_OLD_PID3 && PID != XBOX_OLD_PID4)) // Check if VID and PID match
goto FailUnknownDevice; goto FailUnknownDevice;
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from device descriptor // Extract Max Packet Size from device descriptor
@ -131,7 +131,7 @@ uint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -151,14 +151,14 @@ uint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
//get pointer to assigned address record //get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known // Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
/* The application will work in reduced host mode, so we can save program and data /* The application will work in reduced host mode, so we can save program and data
@ -180,19 +180,19 @@ uint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0; epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0;
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
delay(200); // Give time for address change delay(200); // Give time for address change
rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nXbox Controller Connected\r\n"), 0x80); Notify(PSTR("\r\nXbox Controller Connected\r\n"), 0x80);
#endif #endif
if (pFuncOnInit) if(pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
XboxConnected = true; XboxConnected = true;
bPollEnable = true; bPollEnable = true;
@ -242,7 +242,7 @@ uint8_t XBOXOLD::Release() {
} }
uint8_t XBOXOLD::Poll() { uint8_t XBOXOLD::Poll() {
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1
@ -256,8 +256,8 @@ uint8_t XBOXOLD::Poll() {
void XBOXOLD::readReport() { void XBOXOLD::readReport() {
ButtonState = readBuf[2]; ButtonState = readBuf[2];
for (uint8_t i = 0; i < sizeof(buttonValues); i++) for(uint8_t i = 0; i < sizeof (buttonValues); i++)
buttonValues[i] = readBuf[i + 4]; // A, B, X, Y, BLACK, WHITE, L1, and R1 buttonValues[i] = readBuf[i + 4]; // A, B, X, Y, BLACK, WHITE, L1, and R1
hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[12] << 8) | readBuf[13]); hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[12] << 8) | readBuf[13]);
hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[14] << 8) | readBuf[15]); hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[14] << 8) | readBuf[15]);
@ -267,23 +267,23 @@ void XBOXOLD::readReport() {
//Notify(PSTR("\r\nButtonState"), 0x80); //Notify(PSTR("\r\nButtonState"), 0x80);
//PrintHex<uint8_t>(ButtonState, 0x80); //PrintHex<uint8_t>(ButtonState, 0x80);
if (ButtonState != OldButtonState || memcmp(buttonValues, oldButtonValues, sizeof(buttonValues)) != 0) { if(ButtonState != OldButtonState || memcmp(buttonValues, oldButtonValues, sizeof (buttonValues)) != 0) {
ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
OldButtonState = ButtonState; OldButtonState = ButtonState;
for (uint8_t i = 0; i < sizeof(buttonValues); i++) { for(uint8_t i = 0; i < sizeof (buttonValues); i++) {
if (oldButtonValues[i] == 0 && buttonValues[i] != 0) if(oldButtonValues[i] == 0 && buttonValues[i] != 0)
buttonClicked[i] = true; // Update A, B, X, Y, BLACK, WHITE, L1, and R1 click state buttonClicked[i] = true; // Update A, B, X, Y, BLACK, WHITE, L1, and R1 click state
oldButtonValues[i] = buttonValues[i]; oldButtonValues[i] = buttonValues[i];
} }
} }
} }
void XBOXOLD::printReport(uint16_t length) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox controller void XBOXOLD::printReport(uint16_t length) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox controller
#ifdef PRINTREPORT #ifdef PRINTREPORT
if (readBuf == NULL) if(readBuf == NULL)
return; return;
for (uint8_t i = 0; i < length; i++) { for(uint8_t i = 0; i < length; i++) {
D_PrintHex<uint8_t > (readBuf[i], 0x80); D_PrintHex<uint8_t > (readBuf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -293,19 +293,19 @@ void XBOXOLD::printReport(uint16_t length) { //Uncomment "#define PRINTREPORT" t
uint8_t XBOXOLD::getButtonPress(Button b) { uint8_t XBOXOLD::getButtonPress(Button b) {
uint8_t button = pgm_read_byte(&XBOXOLDBUTTONS[(uint8_t)b]); uint8_t button = pgm_read_byte(&XBOXOLDBUTTONS[(uint8_t)b]);
if (b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons
return buttonValues[button]; // Analog buttons return buttonValues[button]; // Analog buttons
return (ButtonState & button); // Digital buttons return (ButtonState & button); // Digital buttons
} }
bool XBOXOLD::getButtonClick(Button b) { bool XBOXOLD::getButtonClick(Button b) {
uint8_t button = pgm_read_byte(&XBOXOLDBUTTONS[(uint8_t)b]); uint8_t button = pgm_read_byte(&XBOXOLDBUTTONS[(uint8_t)b]);
if (b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) { // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) { // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons
if (buttonClicked[button]) { if(buttonClicked[button]) {
buttonClicked[button] = false; buttonClicked[button] = false;
return true; return true;
} }
return false; return false;
} }
bool click = (ButtonClickState & button); bool click = (ButtonClickState & button);

View file

@ -26,14 +26,14 @@ XBOXRECV::XBOXRECV(USB *p) :
pUsb(p), // pointer to USB class instance - mandatory pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory bAddress(0), // device address - mandatory
bPollEnable(false) { // don't start polling before dongle is connected bPollEnable(false) { // don't start polling before dongle is connected
for (uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
} }
if (pUsb) // register in USB subsystem if(pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry pUsb->RegisterDeviceClass(this); //set devConfig[] entry
} }
@ -51,7 +51,7 @@ uint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
Notify(PSTR("\r\nXBOXRECV Init"), 0x80); Notify(PSTR("\r\nXBOXRECV Init"), 0x80);
#endif #endif
if (bAddress) { // Check if address has already been assigned to an instance if(bAddress) { // Check if address has already been assigned to an instance
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress in use"), 0x80); Notify(PSTR("\r\nAddress in use"), 0x80);
#endif #endif
@ -60,14 +60,14 @@ uint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned
if (!p) { if(!p) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
if (!p->epinfo) { if(!p->epinfo) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nepinfo is null"), 0x80); Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif #endif
@ -82,13 +82,13 @@ uint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
p->epinfo = oldep_ptr; // Restore p->epinfo p->epinfo = oldep_ptr; // Restore p->epinfo
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
VID = udd->idVendor; VID = udd->idVendor;
PID = udd->idProduct; PID = udd->idProduct;
if ((VID != XBOX_VID && VID != MADCATZ_VID) || (PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID)) { // Check if it's a Xbox receiver using the Vendor ID and Product ID if((VID != XBOX_VID && VID != MADCATZ_VID) || (PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID)) { // Check if it's a Xbox receiver using the Vendor ID and Product ID
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80); Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80);
#endif #endif
@ -97,7 +97,7 @@ uint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class
if (!bAddress) { if(!bAddress) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nOut of address space"), 0x80); Notify(PSTR("\r\nOut of address space"), 0x80);
#endif #endif
@ -115,13 +115,13 @@ FailGetDevDescr:
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
NotifyFailGetDevDescr(rcode); NotifyFailGetDevDescr(rcode);
#endif #endif
if (rcode != hrJERR) if(rcode != hrJERR)
rcode = USB_ERROR_FailGetDevDescr; rcode = USB_ERROR_FailGetDevDescr;
goto Fail; goto Fail;
FailUnknownDevice: FailUnknownDevice:
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
NotifyFailUnknownDevice(VID,PID); NotifyFailUnknownDevice(VID, PID);
#endif #endif
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
@ -143,7 +143,7 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) {
#endif #endif
UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
if (!p) { if(!p) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
@ -153,7 +153,7 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) {
delay(300); // Assign new address to the device delay(300); // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device
if (rcode) { if(rcode) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nsetAddr: "), 0x80); Notify(PSTR("\r\nsetAddr: "), 0x80);
D_PrintHex<uint8_t > (rcode, 0x80); D_PrintHex<uint8_t > (rcode, 0x80);
@ -169,7 +169,7 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = false; p->lowspeed = false;
p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
if (!p) { if(!p) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
@ -179,7 +179,7 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
/* The application will work in reduced host mode, so we can save program and data /* The application will work in reduced host mode, so we can save program and data
@ -240,13 +240,13 @@ uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) {
epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = 0; epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = 0;
rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
delay(200); //Give time for address change delay(200); //Give time for address change
rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -281,7 +281,7 @@ Fail:
/* Performs a cleanup after failed Init() attempt */ /* Performs a cleanup after failed Init() attempt */
uint8_t XBOXRECV::Release() { uint8_t XBOXRECV::Release() {
XboxReceiverConnected = false; XboxReceiverConnected = false;
for (uint8_t i = 0; i < 4; i++) for(uint8_t i = 0; i < 4; i++)
Xbox360Connected[i] = 0x00; Xbox360Connected[i] = 0x00;
pUsb->GetAddressPool().FreeAddress(bAddress); pUsb->GetAddressPool().FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -290,28 +290,28 @@ uint8_t XBOXRECV::Release() {
} }
uint8_t XBOXRECV::Poll() { uint8_t XBOXRECV::Poll() {
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
if (!checkStatusTimer || ((millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds if(!checkStatusTimer || ((millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds
checkStatusTimer = millis(); checkStatusTimer = millis();
checkStatus(); checkStatus();
} }
uint8_t inputPipe; uint8_t inputPipe;
uint16_t bufferSize; uint16_t bufferSize;
for (uint8_t i = 0; i < 4; i++) { for(uint8_t i = 0; i < 4; i++) {
if (i == 0) if(i == 0)
inputPipe = XBOX_INPUT_PIPE_1; inputPipe = XBOX_INPUT_PIPE_1;
else if (i == 1) else if(i == 1)
inputPipe = XBOX_INPUT_PIPE_2; inputPipe = XBOX_INPUT_PIPE_2;
else if (i == 2) else if(i == 2)
inputPipe = XBOX_INPUT_PIPE_3; inputPipe = XBOX_INPUT_PIPE_3;
else else
inputPipe = XBOX_INPUT_PIPE_4; inputPipe = XBOX_INPUT_PIPE_4;
bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive
pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf); pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf);
if (bufferSize > 0) { // The number of received bytes if(bufferSize > 0) { // The number of received bytes
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("Bytes Received: "), 0x80); Notify(PSTR("Bytes Received: "), 0x80);
D_PrintHex<uint16_t > (bufferSize, 0x80); D_PrintHex<uint16_t > (bufferSize, 0x80);
@ -327,19 +327,19 @@ uint8_t XBOXRECV::Poll() {
} }
void XBOXRECV::readReport(uint8_t controller) { void XBOXRECV::readReport(uint8_t controller) {
if (readBuf == NULL) if(readBuf == NULL)
return; return;
// This report is send when a controller is connected and disconnected // This report is send when a controller is connected and disconnected
if (readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) { if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) {
Xbox360Connected[controller] = readBuf[1]; Xbox360Connected[controller] = readBuf[1];
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("Controller "), 0x80); Notify(PSTR("Controller "), 0x80);
Notify(controller, 0x80); Notify(controller, 0x80);
#endif #endif
if (Xbox360Connected[controller]) { if(Xbox360Connected[controller]) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
const char* str = 0; const char* str = 0;
switch (readBuf[1]) { switch(readBuf[1]) {
case 0x80: str = PSTR(" as controller\r\n"); case 0x80: str = PSTR(" as controller\r\n");
break; break;
case 0x40: str = PSTR(" as headset\r\n"); case 0x40: str = PSTR(" as headset\r\n");
@ -359,15 +359,15 @@ void XBOXRECV::readReport(uint8_t controller) {
return; return;
} }
// Controller status report // Controller status report
if (readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) { if(readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) {
controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4]; controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4];
return; return;
} }
if (readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports
return; return;
// A controller must be connected if it's sending data // A controller must be connected if it's sending data
if (!Xbox360Connected[controller]) if(!Xbox360Connected[controller])
Xbox360Connected[controller] |= 0x80; Xbox360Connected[controller] |= 0x80;
ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24)); ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24));
@ -380,12 +380,12 @@ void XBOXRECV::readReport(uint8_t controller) {
//Notify(PSTR("\r\nButtonState: "), 0x80); //Notify(PSTR("\r\nButtonState: "), 0x80);
//PrintHex<uint32_t>(ButtonState[controller], 0x80); //PrintHex<uint32_t>(ButtonState[controller], 0x80);
if (ButtonState[controller] != OldButtonState[controller]) { if(ButtonState[controller] != OldButtonState[controller]) {
buttonStateChanged[controller] = true; buttonStateChanged[controller] = true;
ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2
if (((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons if(((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons
R2Clicked[controller] = true; R2Clicked[controller] = true;
if ((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0) if((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0)
L2Clicked[controller] = true; L2Clicked[controller] = true;
OldButtonState[controller] = ButtonState[controller]; OldButtonState[controller] = ButtonState[controller];
} }
@ -393,12 +393,12 @@ void XBOXRECV::readReport(uint8_t controller) {
void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
#ifdef PRINTREPORT #ifdef PRINTREPORT
if (readBuf == NULL) if(readBuf == NULL)
return; return;
Notify(PSTR("Controller "), 0x80); Notify(PSTR("Controller "), 0x80);
Notify(controller, 0x80); Notify(controller, 0x80);
Notify(PSTR(": "), 0x80); Notify(PSTR(": "), 0x80);
for (uint8_t i = 0; i < nBytes; i++) { for(uint8_t i = 0; i < nBytes; i++) {
D_PrintHex<uint8_t > (readBuf[i], 0x80); D_PrintHex<uint8_t > (readBuf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -407,22 +407,22 @@ void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#d
} }
uint8_t XBOXRECV::getButtonPress(Button b, uint8_t controller) { uint8_t XBOXRECV::getButtonPress(Button b, uint8_t controller) {
if (b == L2) // These are analog buttons if(b == L2) // These are analog buttons
return (uint8_t)(ButtonState[controller] >> 8); return (uint8_t)(ButtonState[controller] >> 8);
else if (b == R2) else if(b == R2)
return (uint8_t)ButtonState[controller]; return (uint8_t)ButtonState[controller];
return (bool)(ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16)); return (bool)(ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16));
} }
bool XBOXRECV::getButtonClick(Button b, uint8_t controller) { bool XBOXRECV::getButtonClick(Button b, uint8_t controller) {
if (b == L2) { if(b == L2) {
if (L2Clicked[controller]) { if(L2Clicked[controller]) {
L2Clicked[controller] = false; L2Clicked[controller] = false;
return true; return true;
} }
return false; return false;
} else if (b == R2) { } else if(b == R2) {
if (R2Clicked[controller]) { if(R2Clicked[controller]) {
R2Clicked[controller] = false; R2Clicked[controller] = false;
return true; return true;
} }
@ -472,7 +472,7 @@ void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) {
uint8_t rcode; uint8_t rcode;
#endif #endif
uint8_t outputPipe; uint8_t outputPipe;
switch (controller) { switch(controller) {
case 0: outputPipe = XBOX_OUTPUT_PIPE_1; case 0: outputPipe = XBOX_OUTPUT_PIPE_1;
break; break;
case 1: outputPipe = XBOX_OUTPUT_PIPE_2; case 1: outputPipe = XBOX_OUTPUT_PIPE_2;
@ -489,7 +489,7 @@ void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) {
#endif #endif
pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data); pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data);
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
if (rcode) if(rcode)
Notify(PSTR("Error sending Xbox message\r\n"), 0x80); Notify(PSTR("Error sending Xbox message\r\n"), 0x80);
#endif #endif
} }
@ -513,7 +513,7 @@ void XBOXRECV::setLedRaw(uint8_t value, uint8_t controller) {
} }
void XBOXRECV::setLedOn(LED led, uint8_t controller) { void XBOXRECV::setLedOn(LED led, uint8_t controller) {
if (led != ALL) // All LEDs can't be on a the same time if(led != ALL) // All LEDs can't be on a the same time
setLedRaw(pgm_read_byte(&XBOXLEDS[(uint8_t)led]) + 4, controller); setLedRaw(pgm_read_byte(&XBOXLEDS[(uint8_t)led]) + 4, controller);
} }
@ -530,14 +530,14 @@ Thanks to BusHound from Perisoft.net for the Windows USB Analysis output
Found by timstamp.co.uk Found by timstamp.co.uk
*/ */
void XBOXRECV::checkStatus() { void XBOXRECV::checkStatus() {
if (!bPollEnable) if(!bPollEnable)
return; return;
// Get controller info // Get controller info
writeBuf[0] = 0x08; writeBuf[0] = 0x08;
writeBuf[1] = 0x00; writeBuf[1] = 0x00;
writeBuf[2] = 0x0f; writeBuf[2] = 0x0f;
writeBuf[3] = 0xc0; writeBuf[3] = 0xc0;
for (uint8_t i = 0; i < 4; i++) { for(uint8_t i = 0; i < 4; i++) {
XboxCommand(i, writeBuf, 4); XboxCommand(i, writeBuf, 4);
} }
// Get battery status // Get battery status
@ -545,8 +545,8 @@ void XBOXRECV::checkStatus() {
writeBuf[1] = 0x00; writeBuf[1] = 0x00;
writeBuf[2] = 0x00; writeBuf[2] = 0x00;
writeBuf[3] = 0x40; writeBuf[3] = 0x40;
for (uint8_t i = 0; i < 4; i++) { for(uint8_t i = 0; i < 4; i++) {
if (Xbox360Connected[i]) if(Xbox360Connected[i])
XboxCommand(i, writeBuf, 4); XboxCommand(i, writeBuf, 4);
} }
} }
@ -564,18 +564,18 @@ void XBOXRECV::setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller) {
} }
void XBOXRECV::onInit(uint8_t controller) { void XBOXRECV::onInit(uint8_t controller) {
if (pFuncOnInit) if(pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
else { else {
LED led; LED led;
if (controller == 0) if(controller == 0)
led = LED1; led = LED1;
else if (controller == 1) else if(controller == 1)
led = LED2; led = LED2;
else if (controller == 2) else if(controller == 2)
led = LED3; led = LED3;
else else
led = LED4; led = LED4;
setLedOn(led, controller); setLedOn(led, controller);
} }
} }

View file

@ -24,14 +24,14 @@ XBOXUSB::XBOXUSB(USB *p) :
pUsb(p), // pointer to USB class instance - mandatory pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory bAddress(0), // device address - mandatory
bPollEnable(false) { // don't start polling before dongle is connected bPollEnable(false) { // don't start polling before dongle is connected
for (uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
} }
if (pUsb) // register in USB subsystem if(pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry pUsb->RegisterDeviceClass(this); //set devConfig[] entry
} }
@ -50,7 +50,7 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
Notify(PSTR("\r\nXBOXUSB Init"), 0x80); Notify(PSTR("\r\nXBOXUSB Init"), 0x80);
#endif #endif
// check if address has already been assigned to an instance // check if address has already been assigned to an instance
if (bAddress) { if(bAddress) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress in use"), 0x80); Notify(PSTR("\r\nAddress in use"), 0x80);
#endif #endif
@ -60,14 +60,14 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) { if(!p) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
if (!p->epinfo) { if(!p->epinfo) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nepinfo is null"), 0x80); Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif #endif
@ -87,31 +87,31 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
VID = udd->idVendor; VID = udd->idVendor;
PID = udd->idProduct; PID = udd->idProduct;
if (VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID && VID != GAMESTOP_VID) // Check VID if(VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID && VID != GAMESTOP_VID) // Check VID
goto FailUnknownDevice; goto FailUnknownDevice;
if (PID == XBOX_WIRELESS_PID) { if(PID == XBOX_WIRELESS_PID) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80); Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80);
#endif #endif
goto FailUnknownDevice; goto FailUnknownDevice;
} else if (PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { } else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80); Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80);
#endif #endif
goto FailUnknownDevice; goto FailUnknownDevice;
} else if (PID != XBOX_WIRED_PID && PID != GAMESTOP_WIRED_PID) // Check PID } else if(PID != XBOX_WIRED_PID && PID != GAMESTOP_WIRED_PID) // Check PID
goto FailUnknownDevice; goto FailUnknownDevice;
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from device descriptor // Extract Max Packet Size from device descriptor
@ -119,7 +119,7 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -139,14 +139,14 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
//get pointer to assigned address record //get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known // Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
/* The application will work in reduced host mode, so we can save program and data /* The application will work in reduced host mode, so we can save program and data
@ -168,13 +168,13 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0; epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0;
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
delay(200); // Give time for address change delay(200); // Give time for address change
rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -229,7 +229,7 @@ uint8_t XBOXUSB::Release() {
} }
uint8_t XBOXUSB::Poll() { uint8_t XBOXUSB::Poll() {
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1
@ -241,9 +241,9 @@ uint8_t XBOXUSB::Poll() {
} }
void XBOXUSB::readReport() { void XBOXUSB::readReport() {
if (readBuf == NULL) if(readBuf == NULL)
return; return;
if (readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports
return; return;
} }
@ -257,11 +257,11 @@ void XBOXUSB::readReport() {
//Notify(PSTR("\r\nButtonState"), 0x80); //Notify(PSTR("\r\nButtonState"), 0x80);
//PrintHex<uint32_t>(ButtonState, 0x80); //PrintHex<uint32_t>(ButtonState, 0x80);
if (ButtonState != OldButtonState) { if(ButtonState != OldButtonState) {
ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2
if (((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons
R2Clicked = true; R2Clicked = true;
if ((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0) if((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0)
L2Clicked = true; L2Clicked = true;
OldButtonState = ButtonState; OldButtonState = ButtonState;
} }
@ -269,9 +269,9 @@ void XBOXUSB::readReport() {
void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
#ifdef PRINTREPORT #ifdef PRINTREPORT
if (readBuf == NULL) if(readBuf == NULL)
return; return;
for (uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) { for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) {
D_PrintHex<uint8_t > (readBuf[i], 0x80); D_PrintHex<uint8_t > (readBuf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -280,22 +280,22 @@ void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the rep
} }
uint8_t XBOXUSB::getButtonPress(Button b) { uint8_t XBOXUSB::getButtonPress(Button b) {
if (b == L2) // These are analog buttons if(b == L2) // These are analog buttons
return (uint8_t)(ButtonState >> 8); return (uint8_t)(ButtonState >> 8);
else if (b == R2) else if(b == R2)
return (uint8_t)ButtonState; return (uint8_t)ButtonState;
return (bool)(ButtonState & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16)); return (bool)(ButtonState & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16));
} }
bool XBOXUSB::getButtonClick(Button b) { bool XBOXUSB::getButtonClick(Button b) {
if (b == L2) { if(b == L2) {
if (L2Clicked) { if(L2Clicked) {
L2Clicked = false; L2Clicked = false;
return true; return true;
} }
return false; return false;
} else if (b == R2) { } else if(b == R2) {
if (R2Clicked) { if(R2Clicked) {
R2Clicked = false; R2Clicked = false;
return true; return true;
} }
@ -326,7 +326,7 @@ void XBOXUSB::setLedRaw(uint8_t value) {
} }
void XBOXUSB::setLedOn(LED led) { void XBOXUSB::setLedOn(LED led) {
if (led != ALL) // All LEDs can't be on a the same time if(led != ALL) // All LEDs can't be on a the same time
setLedRaw((pgm_read_byte(&XBOXLEDS[(uint8_t)led])) + 4); setLedRaw((pgm_read_byte(&XBOXLEDS[(uint8_t)led])) + 4);
} }
@ -352,7 +352,7 @@ void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) {
} }
void XBOXUSB::onInit() { void XBOXUSB::onInit() {
if (pFuncOnInit) if(pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
else else
setLedOn(LED1); setLedOn(LED1);

View file

@ -111,6 +111,7 @@ class AddressPoolImpl : public AddressPool {
}; };
// Returns thePool index for a given address // Returns thePool index for a given address
uint8_t FindAddressIndex(uint8_t address = 0) { uint8_t FindAddressIndex(uint8_t address = 0) {
for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) {
if(thePool[i].address.devAddress == address) if(thePool[i].address.devAddress == address)
@ -120,6 +121,7 @@ class AddressPoolImpl : public AddressPool {
}; };
// Returns thePool child index for a given parent // Returns thePool child index for a given parent
uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) { uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) {
for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) { for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {
if(thePool[i].address.bmParent == addr.bmAddress) if(thePool[i].address.bmParent == addr.bmAddress)
@ -129,6 +131,7 @@ class AddressPoolImpl : public AddressPool {
}; };
// Frees address entry specified by index parameter // Frees address entry specified by index parameter
void FreeAddressByIndex(uint8_t index) { void FreeAddressByIndex(uint8_t index) {
// Zero field is reserved and should not be affected // Zero field is reserved and should not be affected
if(index == 0) if(index == 0)
@ -148,6 +151,7 @@ class AddressPoolImpl : public AddressPool {
} }
// Initializes the whole address pool at once // Initializes the whole address pool at once
void InitAllAddresses() { void InitAllAddresses() {
for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
InitEntry(i); InitEntry(i);
@ -172,16 +176,18 @@ public:
}; };
// Returns a pointer to a specified address entry // Returns a pointer to a specified address entry
virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) {
if(!addr) if(!addr)
return thePool; return thePool;
uint8_t index = FindAddressIndex(addr); uint8_t index = FindAddressIndex(addr);
return(!index) ? NULL : thePool + index; return (!index) ? NULL : thePool + index;
}; };
// Performs an operation specified by pfunc for each addressed device // Performs an operation specified by pfunc for each addressed device
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
if(!pfunc) if(!pfunc)
return; return;
@ -192,13 +198,14 @@ public:
}; };
// Allocates new address // Allocates new address
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) {
/* if (parent != 0 && port == 0) /* if (parent != 0 && port == 0)
USB_HOST_SERIAL.println("PRT:0"); */ USB_HOST_SERIAL.println("PRT:0"); */
UsbDeviceAddress _parent; UsbDeviceAddress _parent;
_parent.devAddress = parent; _parent.devAddress = parent;
if(_parent.bmReserved || port > 7) if(_parent.bmReserved || port > 7)
//if(parent > 127 || port > 7) //if(parent > 127 || port > 7)
return 0; return 0;
if(is_hub && hubCounter == 7) if(is_hub && hubCounter == 7)
@ -243,6 +250,7 @@ public:
}; };
// Empties pool entry // Empties pool entry
virtual void FreeAddress(uint8_t addr) { virtual void FreeAddress(uint8_t addr) {
// if the root hub is disconnected all the addresses should be initialized // if the root hub is disconnected all the addresses should be initialized
if(addr == 0x41) { if(addr == 0x41) {

50
adk.cpp
View file

@ -13,7 +13,7 @@ Contact information
Circuits At Home, LTD Circuits At Home, LTD
Web : http://www.circuitsathome.com Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com e-mail : support@circuitsathome.com
*/ */
/* Google ADK interface */ /* Google ADK interface */
@ -42,7 +42,7 @@ bConfNum(0), //configuration number
bNumEP(1), //if config descriptor needs to be parsed bNumEP(1), //if config descriptor needs to be parsed
ready(false) { ready(false) {
// initialize endpoint data structures // initialize endpoint data structures
for (uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) { for(uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
@ -50,7 +50,7 @@ ready(false) {
}//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++... }//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++...
// register in USB subsystem // register in USB subsystem
if (pUsb) { if(pUsb) {
pUsb->RegisterDeviceClass(this); //set devConfig[] entry pUsb->RegisterDeviceClass(this); //set devConfig[] entry
} }
} }
@ -74,7 +74,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
USBTRACE("\r\nADK Init"); USBTRACE("\r\nADK Init");
// check if address has already been assigned to an instance // check if address has already been assigned to an instance
if (bAddress) { if(bAddress) {
USBTRACE("\r\nAddress in use"); USBTRACE("\r\nAddress in use");
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
} }
@ -82,12 +82,12 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) { if(!p) {
USBTRACE("\r\nAddress not found"); USBTRACE("\r\nAddress not found");
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
if (!p->epinfo) { if(!p->epinfo) {
USBTRACE("epinfo is null\r\n"); USBTRACE("epinfo is null\r\n");
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
@ -106,7 +106,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (rcode) { if(rcode) {
goto FailGetDevDescr; goto FailGetDevDescr;
} }
@ -118,7 +118,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -134,7 +134,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
//get pointer to assigned address record //get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) { if(!p) {
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
@ -142,49 +142,49 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign epInfo to epinfo pointer - only EP0 is known // Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) { if(rcode) {
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
} }
//check if ADK device is already in accessory mode; if yes, configure and exit //check if ADK device is already in accessory mode; if yes, configure and exit
if (udd->idVendor == ADK_VID && if(udd->idVendor == ADK_VID &&
(udd->idProduct == ADK_PID || udd->idProduct == ADB_PID)) { (udd->idProduct == ADK_PID || udd->idProduct == ADB_PID)) {
USBTRACE("\r\nAcc.mode device detected"); USBTRACE("\r\nAcc.mode device detected");
/* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */ /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
num_of_conf = udd->bNumConfigurations; num_of_conf = udd->bNumConfigurations;
//USBTRACE2("\r\nNC:",num_of_conf); //USBTRACE2("\r\nNC:",num_of_conf);
for (uint8_t i = 0; i < num_of_conf; i++) { for(uint8_t i = 0; i < num_of_conf; i++) {
ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this); ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this);
delay(1); delay(1);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
#if defined(XOOM) #if defined(XOOM)
//added by Jaylen Scott Vanorden //added by Jaylen Scott Vanorden
if (rcode) { if(rcode) {
USBTRACE2("\r\nGot 1st bad code for config: ", rcode); USBTRACE2("\r\nGot 1st bad code for config: ", rcode);
// Try once more // Try once more
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
} }
#endif #endif
if (rcode) { if(rcode) {
goto FailGetConfDescr; goto FailGetConfDescr;
} }
if (bNumEP > 2) { if(bNumEP > 2) {
break; break;
} }
} // for (uint8_t i=0; i<num_of_conf; i++... } // for (uint8_t i=0; i<num_of_conf; i++...
if (bNumEP == 3) { if(bNumEP == 3) {
// Assign epInfo to epinfo pointer - this time all 3 endpoins // Assign epInfo to epinfo pointer - this time all 3 endpoins
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if (rcode) { if(rcode) {
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
} }
} }
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode) { if(rcode) {
goto FailSetConfDescr; goto FailSetConfDescr;
} }
/* print endpoint structure */ /* print endpoint structure */
@ -202,7 +202,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr); USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr);
USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize); USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize);
USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs); USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs);
*/ */
USBTRACE("\r\nConfiguration successful"); USBTRACE("\r\nConfiguration successful");
ready = true; ready = true;
@ -216,13 +216,13 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
rcode = getProto((uint8_t*) & adkproto); rcode = getProto((uint8_t*) & adkproto);
#if defined(XOOM) #if defined(XOOM)
//added by Jaylen Scott Vanorden //added by Jaylen Scott Vanorden
if (rcode) { if(rcode) {
USBTRACE2("\r\nGot 1st bad code for proto: ", rcode); USBTRACE2("\r\nGot 1st bad code for proto: ", rcode);
// Try once more // Try once more
rcode = getProto((uint8_t*) & adkproto); rcode = getProto((uint8_t*) & adkproto);
} }
#endif #endif
if (rcode) { if(rcode) {
goto FailGetProto; //init fails goto FailGetProto; //init fails
} }
USBTRACE2("\r\nADK protocol rev. ", adkproto); USBTRACE2("\r\nADK protocol rev. ", adkproto);
@ -248,7 +248,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
//switch to accessory mode //switch to accessory mode
//the Android phone will reset //the Android phone will reset
rcode = switchAcc(); rcode = switchAcc();
if (rcode) { if(rcode) {
goto FailSwAcc; //init fails goto FailSwAcc; //init fails
} }
rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
@ -292,7 +292,7 @@ FailSwAcc:
goto Fail; goto Fail;
#endif #endif
//FailOnInit: //FailOnInit:
// USBTRACE("OnInit:"); // USBTRACE("OnInit:");
// goto Fail; // goto Fail;
// //
@ -314,13 +314,13 @@ void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
//ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt); //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
//added by Yuuichi Akagawa //added by Yuuichi Akagawa
if (bNumEP == 3) { if(bNumEP == 3) {
return; return;
} }
bConfNum = conf; bConfNum = conf;
if ((pep->bmAttributes & 0x02) == 2) { if((pep->bmAttributes & 0x02) == 2) {
uint8_t index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; uint8_t index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
// Fill in the endpoint info structure // Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);

12
adk.h
View file

@ -13,7 +13,7 @@ Contact information
Circuits At Home, LTD Circuits At Home, LTD
Web : http://www.circuitsathome.com Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com e-mail : support@circuitsathome.com
*/ */
/* Google ADK interface support header */ /* Google ADK interface support header */
@ -27,8 +27,8 @@ e-mail : support@circuitsathome.com
#define ADB_PID 0x2D01 #define ADB_PID 0x2D01
#define XOOM //enables repeating getProto() and getConf() attempts #define XOOM //enables repeating getProto() and getConf() attempts
//necessary for slow devices such as Motorola XOOM //necessary for slow devices such as Motorola XOOM
//defined by default, can be commented out to save memory //defined by default, can be commented out to save memory
/* requests */ /* requests */
@ -124,17 +124,17 @@ public:
/* returns 2 bytes in *adkproto */ /* returns 2 bytes in *adkproto */
inline uint8_t ADK::getProto(uint8_t* adkproto) { inline uint8_t ADK::getProto(uint8_t* adkproto) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));
} }
/* send ADK string */ /* send ADK string */
inline uint8_t ADK::sendStr(uint8_t index, const char* str) { inline uint8_t ADK::sendStr(uint8_t index, const char* str) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*) str, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*)str, NULL));
} }
/* switch to accessory mode */ /* switch to accessory mode */
inline uint8_t ADK::switchAcc(void) { inline uint8_t ADK::switchAcc(void) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));
} }
#endif // _ADK_H_ #endif // _ADK_H_

View file

@ -218,7 +218,7 @@ public:
} }
static uint8_t IsSet() { static uint8_t IsSet() {
return PORT::PinRead() & (uint8_t) (1 << PIN); return PORT::PinRead() & (uint8_t)(1 << PIN);
} }
static void WaiteForSet() { static void WaiteForSet() {

View file

@ -30,7 +30,7 @@ bNumEP(1),
qNextPollTime(0), qNextPollTime(0),
bPollEnable(false), bPollEnable(false),
ready(false) { ready(false) {
for (uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) { for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
@ -40,7 +40,7 @@ ready(false) {
//if (!i) //if (!i)
epInfo[i].bmNakPower = USB_NAK_MAX_POWER; epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
} }
if (pUsb) if(pUsb)
pUsb->RegisterDeviceClass(this); pUsb->RegisterDeviceClass(this);
} }
@ -59,16 +59,16 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
USBTRACE("ACM Init\r\n"); USBTRACE("ACM Init\r\n");
if (bAddress) if(bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo) { if(!p->epinfo) {
USBTRACE("epinfo\r\n"); USBTRACE("epinfo\r\n");
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
@ -87,13 +87,13 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
@ -102,7 +102,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -116,7 +116,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
@ -126,12 +126,12 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
USBTRACE2("NC:", num_of_conf); USBTRACE2("NC:", num_of_conf);
for (uint8_t i = 0; i < num_of_conf; i++) { for(uint8_t i = 0; i < num_of_conf; i++) {
ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL, ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,
CDC_SUBCLASS_ACM, CDC_SUBCLASS_ACM,
CDC_PROTOCOL_ITU_T_V_250, CDC_PROTOCOL_ITU_T_V_250,
@ -144,19 +144,19 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
if (bNumEP > 1) if(bNumEP > 1)
break; break;
} // for } // for
if (bNumEP < 4) if(bNumEP < 4)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
@ -167,12 +167,12 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
rcode = pAsync->OnInit(this); rcode = pAsync->OnInit(this);
if (rcode) if(rcode)
goto FailOnInit; goto FailOnInit;
USBTRACE("ACM configured\r\n"); USBTRACE("ACM configured\r\n");
@ -230,10 +230,10 @@ void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
uint8_t index; uint8_t index;
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
index = epInterruptInIndex; index = epInterruptInIndex;
else else
if ((pep->bmAttributes & 0x02) == 2) if((pep->bmAttributes & 0x02) == 2)
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
else else
return; return;
@ -264,7 +264,7 @@ uint8_t ACM::Release() {
uint8_t ACM::Poll() { uint8_t ACM::Poll() {
uint8_t rcode = 0; uint8_t rcode = 0;
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
//uint32_t time_now = millis(); //uint32_t time_now = millis();

View file

@ -114,14 +114,13 @@ typedef struct {
uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16) uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16)
} LINE_CODING; } LINE_CODING;
typedef struct typedef struct {
{ uint8_t bmRequestType; // 0xa1 for class-specific notifications
uint8_t bmRequestType; // 0xa1 for class-specific notifications uint8_t bNotification;
uint8_t bNotification; uint16_t wValue;
uint16_t wValue; uint16_t wIndex;
uint16_t wIndex; uint16_t wLength;
uint16_t wLength; uint16_t bmState; //UART state bitmap for SERIAL_STATE, other notifications variable length
uint16_t bmState; //UART state bitmap for SERIAL_STATE, other notifications variable length
} CLASS_NOTIFICATION; } CLASS_NOTIFICATION;
class ACM; class ACM;
@ -151,7 +150,7 @@ protected:
uint8_t bNumEP; // total number of EP in the configuration uint8_t bNumEP; // total number of EP in the configuration
uint32_t qNextPollTime; // next poll time uint32_t qNextPollTime; // next poll time
bool bPollEnable; // poll enable flag bool bPollEnable; // poll enable flag
bool ready; //device ready indicator bool ready; //device ready indicator
EpInfo epInfo[ACM_MAX_ENDPOINTS]; EpInfo epInfo[ACM_MAX_ENDPOINTS];
@ -167,7 +166,7 @@ public:
uint8_t GetLineCoding(LINE_CODING *dataptr); uint8_t GetLineCoding(LINE_CODING *dataptr);
uint8_t SetControlLineState(uint8_t state); uint8_t SetControlLineState(uint8_t state);
uint8_t SendBreak(uint16_t duration); uint8_t SendBreak(uint16_t duration);
uint8_t GetNotif( uint16_t *bytes_rcvd, uint8_t *dataptr ); uint8_t GetNotif(uint16_t *bytes_rcvd, uint8_t *dataptr);
// Methods for recieving and sending data // Methods for recieving and sending data
uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr);
@ -182,9 +181,9 @@ public:
return bAddress; return bAddress;
}; };
virtual bool isReady() { virtual bool isReady() {
return ready; return ready;
}; };
// UsbConfigXtracter implementation // UsbConfigXtracter implementation
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);

View file

@ -26,7 +26,7 @@ pUsb(p),
bAddress(0), bAddress(0),
bNumEP(1), bNumEP(1),
wFTDIType(0) { wFTDIType(0) {
for (uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) { for(uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
@ -34,7 +34,7 @@ wFTDIType(0) {
//if (!i) //if (!i)
epInfo[i].bmNakPower = USB_NAK_MAX_POWER; epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
} }
if (pUsb) if(pUsb)
pUsb->RegisterDeviceClass(this); pUsb->RegisterDeviceClass(this);
} }
@ -56,16 +56,16 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
USBTRACE("FTDI Init\r\n"); USBTRACE("FTDI Init\r\n");
if (bAddress) if(bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo) { if(!p->epinfo) {
USBTRACE("epinfo\r\n"); USBTRACE("epinfo\r\n");
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
@ -84,9 +84,9 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
if (udd->idVendor != FTDI_VID || udd->idProduct != FTDI_PID) if(udd->idVendor != FTDI_VID || udd->idProduct != FTDI_PID)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Save type of FTDI chip // Save type of FTDI chip
@ -95,7 +95,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
@ -104,7 +104,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -118,7 +118,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
@ -128,30 +128,30 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
USBTRACE2("NC:", num_of_conf); USBTRACE2("NC:", num_of_conf);
for (uint8_t i = 0; i < num_of_conf; i++) { for(uint8_t i = 0; i < num_of_conf; i++) {
HexDumper<USBReadParser, uint16_t, uint16_t> HexDump; HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
ConfigDescParser < 0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this); ConfigDescParser < 0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this);
rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
if (bNumEP > 1) if(bNumEP > 1)
break; break;
} // for } // for
if (bNumEP < 2) if(bNumEP < 2)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
USBTRACE2("NumEP:", bNumEP); USBTRACE2("NumEP:", bNumEP);
@ -164,12 +164,12 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
rcode = pAsync->OnInit(this); rcode = pAsync->OnInit(this);
if (rcode) if(rcode)
goto FailOnInit; goto FailOnInit;
USBTRACE("FTDI configured\r\n"); USBTRACE("FTDI configured\r\n");
@ -221,10 +221,10 @@ void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t prot
uint8_t index; uint8_t index;
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
index = epInterruptInIndex; index = epInterruptInIndex;
else else
if ((pep->bmAttributes & 0x02) == 2) if((pep->bmAttributes & 0x02) == 2)
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
else else
return; return;
@ -270,19 +270,19 @@ uint8_t FTDI::SetBaudRate(uint32_t baud) {
divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left
if (wFTDIType == FT232AM) { if(wFTDIType == FT232AM) {
if ((divisor3 & 0x7) == 7) if((divisor3 & 0x7) == 7)
divisor3++; // round x.7/8 up to x+1 divisor3++; // round x.7/8 up to x+1
baud_value = divisor3 >> 3; baud_value = divisor3 >> 3;
divisor3 &= 0x7; divisor3 &= 0x7;
if (divisor3 == 1) baud_value |= 0xc000; if(divisor3 == 1) baud_value |= 0xc000;
else // 0.125 else // 0.125
if (divisor3 >= 4) baud_value |= 0x4000; if(divisor3 >= 4) baud_value |= 0x4000;
else // 0.5 else // 0.5
if (divisor3 != 0) baud_value |= 0x8000; // 0.25 if(divisor3 != 0) baud_value |= 0x8000; // 0.25
if (baud_value == 1) baud_value = 0; /* special case for maximum baud rate */ if(baud_value == 1) baud_value = 0; /* special case for maximum baud rate */
} else { } else {
static const unsigned char divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3}; static const unsigned char divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3};
static const unsigned char divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1}; static const unsigned char divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1};
@ -292,9 +292,9 @@ uint8_t FTDI::SetBaudRate(uint32_t baud) {
baud_index = divindex[divisor3 & 0x7]; baud_index = divindex[divisor3 & 0x7];
/* Deal with special cases for highest baud rates. */ /* Deal with special cases for highest baud rates. */
if (baud_value == 1) baud_value = 0; if(baud_value == 1) baud_value = 0;
else // 1.0 else // 1.0
if (baud_value == 0x4001) baud_value = 1; // 1.5 if(baud_value == 0x4001) baud_value = 1; // 1.5
} }
USBTRACE2("baud_value:", baud_value); USBTRACE2("baud_value:", baud_value);
USBTRACE2("baud_index:", baud_index); USBTRACE2("baud_index:", baud_index);

View file

@ -35,16 +35,16 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
USBTRACE("PL Init\r\n"); USBTRACE("PL Init\r\n");
if (bAddress) if(bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo) { if(!p->epinfo) {
USBTRACE("epinfo\r\n"); USBTRACE("epinfo\r\n");
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
@ -63,10 +63,10 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
if (udd->idVendor != PL_VID && udd->idProduct != PL_PID) if(udd->idVendor != PL_VID && udd->idProduct != PL_PID)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Save type of PL chip // Save type of PL chip
@ -75,7 +75,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
@ -84,7 +84,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -98,7 +98,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
@ -108,30 +108,30 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
USBTRACE2("NC:", num_of_conf); USBTRACE2("NC:", num_of_conf);
for (uint8_t i = 0; i < num_of_conf; i++) { for(uint8_t i = 0; i < num_of_conf; i++) {
HexDumper<USBReadParser, uint16_t, uint16_t> HexDump; HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this);
rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
if (bNumEP > 1) if(bNumEP > 1)
break; break;
} // for } // for
if (bNumEP < 2) if(bNumEP < 2)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
@ -142,12 +142,12 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
rcode = pAsync->OnInit(this); rcode = pAsync->OnInit(this);
if (rcode) if(rcode)
goto FailOnInit; goto FailOnInit;
USBTRACE("PL configured\r\n"); USBTRACE("PL configured\r\n");
@ -208,5 +208,3 @@ Fail:
// //} // //}
// return rcode; // return rcode;
//} //}

View file

@ -58,7 +58,10 @@ class ConfigDescParser : public USBReadParser {
void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
public: public:
void SetOR(void) { UseOr = true; }
void SetOR(void) {
UseOr = true;
}
ConfigDescParser(UsbConfigXtracter *xtractor); ConfigDescParser(UsbConfigXtracter *xtractor);
virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
}; };
@ -75,11 +78,10 @@ UseOr(false) {
theSkipper.Initialize(&theBuffer); theSkipper.Initialize(&theBuffer);
}; };
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) {
uint16_t cntdn = (uint16_t) len; uint16_t cntdn = (uint16_t)len;
uint8_t *p = (uint8_t*) pbuf; uint8_t *p = (uint8_t*)pbuf;
while(cntdn) while(cntdn)
if(!ParseDescriptor(&p, &cntdn)) if(!ParseDescriptor(&p, &cntdn))
@ -90,8 +92,8 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uin
compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) { bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) {
USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*> (varBuffer); USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*> (varBuffer); USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
switch(stateParseDescr) { switch(stateParseDescr) {
case 0: case 0:
theBuffer.valueSize = 2; theBuffer.valueSize = 2;
@ -100,8 +102,8 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
case 1: case 1:
if(!valParser.Parse(pp, pcntdn)) if(!valParser.Parse(pp, pcntdn))
return false; return false;
dscrLen = *((uint8_t*) theBuffer.pValue); dscrLen = *((uint8_t*)theBuffer.pValue);
dscrType = *((uint8_t*) theBuffer.pValue + 1); dscrType = *((uint8_t*)theBuffer.pValue + 1);
stateParseDescr = 2; stateParseDescr = 2;
case 2: case 2:
// This is a sort of hack. Assuming that two bytes are all ready in the buffer // This is a sort of hack. Assuming that two bytes are all ready in the buffer
@ -116,10 +118,10 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
case USB_DESCRIPTOR_INTERFACE: case USB_DESCRIPTOR_INTERFACE:
isGoodInterface = false; isGoodInterface = false;
case USB_DESCRIPTOR_CONFIGURATION: case USB_DESCRIPTOR_CONFIGURATION:
theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) - 2; theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2;
break; break;
case USB_DESCRIPTOR_ENDPOINT: case USB_DESCRIPTOR_ENDPOINT:
theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2; theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2;
break; break;
case HID_DESCRIPTOR_HID: case HID_DESCRIPTOR_HID:
theBuffer.valueSize = dscrLen - 2; theBuffer.valueSize = dscrLen - 2;
@ -158,7 +160,7 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
return false; return false;
if(isGoodInterface) if(isGoodInterface)
if(theXtractor) if(theXtractor)
theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*) varBuffer); theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
break; break;
//case HID_DESCRIPTOR_HID: //case HID_DESCRIPTOR_HID:
// if (!valParser.Parse(pp, pcntdn)) // if (!valParser.Parse(pp, pcntdn))

View file

@ -41,7 +41,7 @@ public:
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE> template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) { void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {
if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug. if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug.
for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) { for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) {
if(!byteCount) { if(!byteCount) {
PrintHex<OFFSET_TYPE > (byteTotal, 0x80); PrintHex<OFFSET_TYPE > (byteTotal, 0x80);

View file

@ -1,6 +1,7 @@
#include "hid.h" #include "hid.h"
//get HID report descriptor //get HID report descriptor
/* WRONG! Endpoint is _ALWAYS_ ZERO for HID! We want the _INTERFACE_ value here! /* WRONG! Endpoint is _ALWAYS_ ZERO for HID! We want the _INTERFACE_ value here!
uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) { uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) {
const uint8_t constBufLen = 64; const uint8_t constBufLen = 64;
@ -12,7 +13,7 @@ uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) {
//return ((rcode != hrSTALL) ? rcode : 0); //return ((rcode != hrSTALL) ? rcode : 0);
return rcode; return rcode;
} }
*/ */
uint8_t HID::GetReportDescr(uint16_t wIndex, USBReadParser *parser) { uint8_t HID::GetReportDescr(uint16_t wIndex, USBReadParser *parser) {
const uint8_t constBufLen = 64; const uint8_t constBufLen = 64;
uint8_t buf[constBufLen]; uint8_t buf[constBufLen];

1
hid.h
View file

@ -140,7 +140,6 @@ public:
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0; virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0;
}; };
class HID : public USBDeviceConfig, public UsbConfigXtracter { class HID : public USBDeviceConfig, public UsbConfigXtracter {
protected: protected:
USB *pUsb; // USB class instance pointer USB *pUsb; // USB class instance pointer

View file

@ -980,7 +980,7 @@ void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const
totalSize = 0; totalSize = 0;
while (cntdn) { while(cntdn) {
//USB_HOST_SERIAL.println(""); //USB_HOST_SERIAL.println("");
//PrintHex<uint16_t>(offset + len - cntdn); //PrintHex<uint16_t>(offset + len - cntdn);
//USB_HOST_SERIAL.print(":"); //USB_HOST_SERIAL.print(":");
@ -995,7 +995,7 @@ void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const
void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) { void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) {
E_Notify(PSTR("("), 0x80); E_Notify(PSTR("("), 0x80);
for (; len; p++, len--) for(; len; p++, len--)
PrintHex<uint8_t > (*p, 0x80); PrintHex<uint8_t > (*p, 0x80);
E_Notify(PSTR(")"), 0x80); E_Notify(PSTR(")"), 0x80);
} }
@ -1007,7 +1007,7 @@ void ReportDescParserBase::PrintByteValue(uint8_t data) {
} }
void ReportDescParserBase::PrintItemTitle(uint8_t prefix) { void ReportDescParserBase::PrintItemTitle(uint8_t prefix) {
switch (prefix & (TYPE_MASK | TAG_MASK)) { switch(prefix & (TYPE_MASK | TAG_MASK)) {
case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):
E_Notify(PSTR("\r\nPush"), 0x80); E_Notify(PSTR("\r\nPush"), 0x80);
break; break;
@ -1074,9 +1074,9 @@ void ReportDescParserBase::PrintItemTitle(uint8_t prefix) {
uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) { uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
//uint8_t ret = enErrorSuccess; //uint8_t ret = enErrorSuccess;
//reinterpret_cast<>(varBuffer); //reinterpret_cast<>(varBuffer);
switch (itemParseState) { switch(itemParseState) {
case 0: case 0:
if (**pp == HID_LONG_ITEM_PREFIX) if(**pp == HID_LONG_ITEM_PREFIX)
USBTRACE("\r\nLONG\r\n"); USBTRACE("\r\nLONG\r\n");
else { else {
uint8_t size = ((**pp) & DATA_SIZE_MASK); uint8_t size = ((**pp) & DATA_SIZE_MASK);
@ -1091,10 +1091,10 @@ switch (itemParseState) {
itemSize--; itemSize--;
itemParseState = 1; itemParseState = 1;
if (!itemSize) if(!itemSize)
break; break;
if (!pcntdn) if(!pcntdn)
return enErrorIncomplete; return enErrorIncomplete;
case 1: case 1:
//USBTRACE2("\r\niSz:",itemSize); //USBTRACE2("\r\niSz:",itemSize);
@ -1103,18 +1103,18 @@ switch (itemParseState) {
valParser.Initialize(&theBuffer); valParser.Initialize(&theBuffer);
itemParseState = 2; itemParseState = 2;
case 2: case 2:
if (!valParser.Parse(pp, pcntdn)) if(!valParser.Parse(pp, pcntdn))
return enErrorIncomplete; return enErrorIncomplete;
itemParseState = 3; itemParseState = 3;
case 3: case 3:
{ {
uint8_t data = *((uint8_t*)varBuffer); uint8_t data = *((uint8_t*)varBuffer);
switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { switch(itemPrefix & (TYPE_MASK | TAG_MASK)) {
case (TYPE_LOCAL | TAG_LOCAL_USAGE): case (TYPE_LOCAL | TAG_LOCAL_USAGE):
if (pfUsage) { if(pfUsage) {
if (theBuffer.valueSize > 1) { if(theBuffer.valueSize > 1) {
uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer); uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer);
pfUsage(*ui16); pfUsage(*ui16);
} else } else
pfUsage(data); pfUsage(data);
@ -1149,7 +1149,7 @@ switch (itemParseState) {
break; break;
case (TYPE_MAIN | TAG_MAIN_COLLECTION): case (TYPE_MAIN | TAG_MAIN_COLLECTION):
case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):
switch (data) { switch(data) {
case 0x00: case 0x00:
E_Notify(PSTR(" Physical"), 0x80); E_Notify(PSTR(" Physical"), 0x80);
break; break;
@ -1216,23 +1216,23 @@ ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /
void ReportDescParserBase::SetUsagePage(uint16_t page) { void ReportDescParserBase::SetUsagePage(uint16_t page) {
pfUsage = NULL; pfUsage = NULL;
if (VALUE_BETWEEN(page, 0x00, 0x11)) if(VALUE_BETWEEN(page, 0x00, 0x11))
pfUsage = (usagePageFunctions[page - 1]); pfUsage = (usagePageFunctions[page - 1]);
// Dead code... // Dead code...
// //
// pfUsage = (UsagePageFunc)pgm_read_pointer(usagePageFunctions[page - 1]); // pfUsage = (UsagePageFunc)pgm_read_pointer(usagePageFunctions[page - 1]);
//else if (page > 0x7f && page < 0x84) //else if (page > 0x7f && page < 0x84)
// E_Notify(pstrUsagePageMonitor); // E_Notify(pstrUsagePageMonitor);
//else if (page > 0x83 && page < 0x8c) //else if (page > 0x83 && page < 0x8c)
// E_Notify(pstrUsagePagePower); // E_Notify(pstrUsagePagePower);
//else if (page > 0x8b && page < 0x92) //else if (page > 0x8b && page < 0x92)
// E_Notify((char*)pgm_read_pointer(&usagePageTitles1[page - 0x8c])); // E_Notify((char*)pgm_read_pointer(&usagePageTitles1[page - 0x8c]));
//else if (page > 0xfeff && page <= 0xffff) //else if (page > 0xfeff && page <= 0xffff)
// E_Notify(pstrUsagePageVendorDefined); // E_Notify(pstrUsagePageVendorDefined);
// //
else else
switch (page) { switch(page) {
case 0x14: case 0x14:
pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage; pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage;
break; break;
@ -1248,14 +1248,14 @@ void ReportDescParserBase::PrintUsagePage(uint16_t page) {
output_if_between(page, 0x00, 0x11, w, E_Notify, usagePageTitles0, 0x80) output_if_between(page, 0x00, 0x11, w, E_Notify, usagePageTitles0, 0x80)
else output_if_between(page, 0x8b, 0x92, w, E_Notify, usagePageTitles1, 0x80) else output_if_between(page, 0x8b, 0x92, w, E_Notify, usagePageTitles1, 0x80)
else if (VALUE_BETWEEN(page, 0x7f, 0x84)) else if(VALUE_BETWEEN(page, 0x7f, 0x84))
E_Notify(pstrUsagePageMonitor, 0x80); E_Notify(pstrUsagePageMonitor, 0x80);
else if (VALUE_BETWEEN(page, 0x83, 0x8c)) else if(VALUE_BETWEEN(page, 0x83, 0x8c))
E_Notify(pstrUsagePagePower, 0x80); E_Notify(pstrUsagePagePower, 0x80);
else if (page > 0xfeff /* && page <= 0xffff */) else if(page > 0xfeff /* && page <= 0xffff */)
E_Notify(pstrUsagePageVendorDefined, 0x80); E_Notify(pstrUsagePageVendorDefined, 0x80);
else else
switch (page) { switch(page) {
case 0x14: case 0x14:
E_Notify(pstrUsagePageAlphaNumericDisplay, 0x80); E_Notify(pstrUsagePageAlphaNumericDisplay, 0x80);
break; break;
@ -1409,8 +1409,8 @@ void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) {
const char * const * w; const char * const * w;
E_Notify(pstrSpace, 0x80); E_Notify(pstrSpace, 0x80);
if (usage == 1) E_Notify(pstrUsageMedicalUltrasound, 0x80); if(usage == 1) E_Notify(pstrUsageMedicalUltrasound, 0x80);
else if (usage == 0x70) else if(usage == 0x70)
E_Notify(pstrUsageDepthGainCompensation, 0x80); E_Notify(pstrUsageDepthGainCompensation, 0x80);
else output_if_between(usage, 0x1f, 0x28, w, E_Notify, medInstrTitles0, 0x80) else output_if_between(usage, 0x1f, 0x28, w, E_Notify, medInstrTitles0, 0x80)
else output_if_between(usage, 0x3f, 0x45, w, E_Notify, medInstrTitles1, 0x80) else output_if_between(usage, 0x3f, 0x45, w, E_Notify, medInstrTitles1, 0x80)
@ -1423,9 +1423,9 @@ void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) {
uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) { uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
//uint8_t ret = enErrorSuccess; //uint8_t ret = enErrorSuccess;
switch (itemParseState) { switch(itemParseState) {
case 0: case 0:
if (**pp == HID_LONG_ITEM_PREFIX) if(**pp == HID_LONG_ITEM_PREFIX)
USBTRACE("\r\nLONG\r\n"); USBTRACE("\r\nLONG\r\n");
else { else {
uint8_t size = ((**pp) & DATA_SIZE_MASK); uint8_t size = ((**pp) & DATA_SIZE_MASK);
@ -1437,28 +1437,28 @@ uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
itemSize--; itemSize--;
itemParseState = 1; itemParseState = 1;
if (!itemSize) if(!itemSize)
break; break;
if (!pcntdn) if(!pcntdn)
return enErrorIncomplete; return enErrorIncomplete;
case 1: case 1:
theBuffer.valueSize = itemSize; theBuffer.valueSize = itemSize;
valParser.Initialize(&theBuffer); valParser.Initialize(&theBuffer);
itemParseState = 2; itemParseState = 2;
case 2: case 2:
if (!valParser.Parse(pp, pcntdn)) if(!valParser.Parse(pp, pcntdn))
return enErrorIncomplete; return enErrorIncomplete;
itemParseState = 3; itemParseState = 3;
case 3: case 3:
{ {
uint8_t data = *((uint8_t*)varBuffer); uint8_t data = *((uint8_t*)varBuffer);
switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { switch(itemPrefix & (TYPE_MASK | TAG_MASK)) {
case (TYPE_LOCAL | TAG_LOCAL_USAGE): case (TYPE_LOCAL | TAG_LOCAL_USAGE):
if (pfUsage) { if(pfUsage) {
if (theBuffer.valueSize > 1) { if(theBuffer.valueSize > 1) {
uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer); uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer);
pfUsage(*ui16); pfUsage(*ui16);
} else } else
pfUsage(data); pfUsage(data);
@ -1512,7 +1512,7 @@ void ReportDescParser2::OnInputItem(uint8_t itm) {
uint8_t bit_offset = totalSize - tmp; // number of bits in the current byte already handled uint8_t bit_offset = totalSize - tmp; // number of bits in the current byte already handled
uint8_t *p = pBuf + byte_offset; // current byte pointer uint8_t *p = pBuf + byte_offset; // current byte pointer
if (bit_offset) if(bit_offset)
*p >>= bit_offset; *p >>= bit_offset;
uint8_t usage = useMin; uint8_t usage = useMin;
@ -1522,7 +1522,7 @@ void ReportDescParser2::OnInputItem(uint8_t itm) {
uint8_t bits_of_byte = 8; uint8_t bits_of_byte = 8;
// for each field in field array defined by rptCount // for each field in field array defined by rptCount
for (uint8_t field = 0; field < rptCount; field++, usage++) { for(uint8_t field = 0; field < rptCount; field++, usage++) {
union { union {
uint8_t bResult[4]; uint8_t bResult[4];
@ -1533,7 +1533,7 @@ void ReportDescParser2::OnInputItem(uint8_t itm) {
result.dwResult = 0; result.dwResult = 0;
uint8_t mask = 0; uint8_t mask = 0;
if (print_usemin_usemax) if(print_usemin_usemax)
pfUsage(usage); pfUsage(usage);
// bits_left - number of bits in the field(array of fields, depending on Report Count) left to process // bits_left - number of bits in the field(array of fields, depending on Report Count) left to process
@ -1541,7 +1541,7 @@ void ReportDescParser2::OnInputItem(uint8_t itm) {
// bits_to_copy - number of bits to copy to result buffer // bits_to_copy - number of bits to copy to result buffer
// for each bit in a field // for each bit in a field
for (uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left; for(uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left;
bits_left -= bits_to_copy) { bits_left -= bits_to_copy) {
bits_to_copy = (bits_left > bits_of_byte) ? bits_of_byte : bits_left; bits_to_copy = (bits_left > bits_of_byte) ? bits_of_byte : bits_left;
@ -1553,7 +1553,7 @@ void ReportDescParser2::OnInputItem(uint8_t itm) {
mask = 0; mask = 0;
for (uint8_t j = bits_to_copy; j; j--) { for(uint8_t j = bits_to_copy; j; j--) {
mask <<= 1; mask <<= 1;
mask |= 1; mask |= 1;
} }
@ -1562,7 +1562,7 @@ void ReportDescParser2::OnInputItem(uint8_t itm) {
bits_of_byte -= bits_to_copy; bits_of_byte -= bits_to_copy;
if (bits_of_byte < 1) { if(bits_of_byte < 1) {
bits_of_byte = 8; bits_of_byte = 8;
p++; p++;
} }
@ -1577,6 +1577,6 @@ void UniversalReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t
uint8_t ret = hid->GetReportDescr(0, &prs); uint8_t ret = hid->GetReportDescr(0, &prs);
if (ret) if(ret)
ErrorMessage<uint8_t > (PSTR("GetReportDescr-2"), ret); ErrorMessage<uint8_t > (PSTR("GetReportDescr-2"), ret);
} }

View file

@ -101,7 +101,7 @@ protected:
MultiValueBuffer theBuffer; MultiValueBuffer theBuffer;
MultiByteValueParser valParser; MultiByteValueParser valParser;
ByteSkipper theSkipper; ByteSkipper theSkipper;
uint8_t varBuffer[sizeof(USB_CONFIGURATION_DESCRIPTOR)]; uint8_t varBuffer[sizeof (USB_CONFIGURATION_DESCRIPTOR)];
uint8_t itemParseState; // Item parser state variable uint8_t itemParseState; // Item parser state variable
uint8_t itemSize; // Item size uint8_t itemSize; // Item size
@ -126,8 +126,7 @@ public:
itemPrefix(0), itemPrefix(0),
rptSize(0), rptSize(0),
rptCount(0), rptCount(0),
pfUsage(NULL) pfUsage(NULL) {
{
theBuffer.pValue = varBuffer; theBuffer.pValue = varBuffer;
valParser.Initialize(&theBuffer); valParser.Initialize(&theBuffer);
theSkipper.Initialize(&theBuffer); theSkipper.Initialize(&theBuffer);

View file

@ -7,14 +7,14 @@ bPollEnable(false),
bHasReportId(false) { bHasReportId(false) {
Initialize(); Initialize();
if (pUsb) if(pUsb)
pUsb->RegisterDeviceClass(this); pUsb->RegisterDeviceClass(this);
} }
uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) { uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) {
for (uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
if (descrInfo[i].bDescrType == type) { if(descrInfo[i].bDescrType == type) {
if (n == num) if(n == num)
return descrInfo[i].wDescriptorLength; return descrInfo[i].wDescriptorLength;
n++; n++;
} }
@ -23,22 +23,22 @@ uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) {
} }
void HIDUniversal::Initialize() { void HIDUniversal::Initialize() {
for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
rptParsers[i].rptId = 0; rptParsers[i].rptId = 0;
rptParsers[i].rptParser = NULL; rptParsers[i].rptParser = NULL;
} }
for (uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
descrInfo[i].bDescrType = 0; descrInfo[i].bDescrType = 0;
descrInfo[i].wDescriptorLength = 0; descrInfo[i].wDescriptorLength = 0;
} }
for (uint8_t i = 0; i < maxHidInterfaces; i++) { for(uint8_t i = 0; i < maxHidInterfaces; i++) {
hidInterfaces[i].bmInterface = 0; hidInterfaces[i].bmInterface = 0;
hidInterfaces[i].bmProtocol = 0; hidInterfaces[i].bmProtocol = 0;
for (uint8_t j = 0; j < maxEpPerInterface; j++) for(uint8_t j = 0; j < maxEpPerInterface; j++)
hidInterfaces[i].epIndex[j] = 0; hidInterfaces[i].epIndex[j] = 0;
} }
for (uint8_t i = 0; i < totalEndpoints; i++) { for(uint8_t i = 0; i < totalEndpoints; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
@ -52,8 +52,8 @@ void HIDUniversal::Initialize() {
} }
bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) { bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) {
for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
if (rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) { if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) {
rptParsers[i].rptId = id; rptParsers[i].rptId = id;
rptParsers[i].rptParser = prs; rptParsers[i].rptParser = prs;
return true; return true;
@ -63,11 +63,11 @@ bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) {
} }
HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) { HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) {
if (!bHasReportId) if(!bHasReportId)
return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL); return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);
for (uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
if (rptParsers[i].rptId == id) if(rptParsers[i].rptId == id)
return rptParsers[i].rptParser; return rptParsers[i].rptParser;
} }
return NULL; return NULL;
@ -90,16 +90,16 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
USBTRACE("HU Init\r\n"); USBTRACE("HU Init\r\n");
if (bAddress) if(bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo) { if(!p->epinfo) {
USBTRACE("epinfo\r\n"); USBTRACE("epinfo\r\n");
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
@ -115,10 +115,10 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
if (!rcode) if(!rcode)
len = (buf[0] > constBufSize) ? constBufSize : buf[0]; len = (buf[0] > constBufSize) ? constBufSize : buf[0];
if (rcode) { if(rcode) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
@ -131,7 +131,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
@ -140,7 +140,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -156,15 +156,15 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
if (len) if(len)
rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
num_of_conf = udd->bNumConfigurations; num_of_conf = udd->bNumConfigurations;
@ -172,12 +172,12 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
USBTRACE2("NC:", num_of_conf); USBTRACE2("NC:", num_of_conf);
for (uint8_t i = 0; i < num_of_conf; i++) { for(uint8_t i = 0; i < num_of_conf; i++) {
//HexDumper<USBReadParser, uint16_t, uint16_t> HexDump; //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
ConfigDescParser<USB_CLASS_HID, 0, 0, ConfigDescParser<USB_CLASS_HID, 0, 0,
CP_MASK_COMPARE_CLASS> confDescrParser(this); CP_MASK_COMPARE_CLASS> confDescrParser(this);
@ -185,14 +185,14 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
//rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
if (bNumEP > 1) if(bNumEP > 1)
break; break;
} // for } // for
if (bNumEP < 2) if(bNumEP < 2)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
@ -203,16 +203,16 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
for (uint8_t i = 0; i < bNumIface; i++) { for(uint8_t i = 0; i < bNumIface; i++) {
if (hidInterfaces[i].epIndex[epInterruptInIndex] == 0) if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
continue; continue;
rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0); rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);
if (rcode && rcode != hrSTALL) if(rcode && rcode != hrSTALL)
goto FailSetIdle; goto FailSetIdle;
} }
@ -262,8 +262,8 @@ Fail:
} }
HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) { HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {
for (uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++) for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)
if (hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
&& hidInterfaces[i].bmProtocol == proto) && hidInterfaces[i].bmProtocol == proto)
return hidInterfaces + i; return hidInterfaces + i;
return NULL; return NULL;
@ -271,7 +271,7 @@ HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t a
void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
// If the first configuration satisfies, the others are not concidered. // If the first configuration satisfies, the others are not concidered.
if (bNumEP > 1 && conf != bConfNum) if(bNumEP > 1 && conf != bConfNum)
return; return;
//ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf); //ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf);
@ -284,7 +284,7 @@ void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint
HIDInterface *piface = FindInterface(iface, alt, proto); HIDInterface *piface = FindInterface(iface, alt, proto);
// Fill in interface structure in case of new interface // Fill in interface structure in case of new interface
if (!piface) { if(!piface) {
piface = hidInterfaces + bNumIface; piface = hidInterfaces + bNumIface;
piface->bmInterface = iface; piface->bmInterface = iface;
piface->bmAltSet = alt; piface->bmAltSet = alt;
@ -292,12 +292,12 @@ void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint
bNumIface++; bNumIface++;
} }
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
index = epInterruptInIndex; index = epInterruptInIndex;
else else
index = epInterruptOutIndex; index = epInterruptOutIndex;
if (index) { if(index) {
// Fill in the endpoint info structure // Fill in the endpoint info structure
epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
@ -323,34 +323,34 @@ uint8_t HIDUniversal::Release() {
} }
bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) { bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) {
for (uint8_t i = 0; i < len; i++) for(uint8_t i = 0; i < len; i++)
if (buf1[i] != buf2[i]) if(buf1[i] != buf2[i])
return false; return false;
return true; return true;
} }
void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) { void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) {
for (uint8_t i = 0; i < len; i++) for(uint8_t i = 0; i < len; i++)
buf[i] = 0; buf[i] = 0;
} }
void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) { void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) {
for (uint8_t i = 0; i < len; i++) for(uint8_t i = 0; i < len; i++)
dest[i] = src[i]; dest[i] = src[i];
} }
uint8_t HIDUniversal::Poll() { uint8_t HIDUniversal::Poll() {
uint8_t rcode = 0; uint8_t rcode = 0;
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
if (qNextPollTime <= millis()) { if(qNextPollTime <= millis()) {
qNextPollTime = millis() + 50; qNextPollTime = millis() + 50;
uint8_t buf[constBuffLen]; uint8_t buf[constBuffLen];
for (uint8_t i = 0; i < bNumIface; i++) { for(uint8_t i = 0; i < bNumIface; i++) {
uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex]; uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
uint16_t read = (uint16_t)epInfo[index].maxPktSize; uint16_t read = (uint16_t)epInfo[index].maxPktSize;
@ -358,32 +358,32 @@ uint8_t HIDUniversal::Poll() {
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf); uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);
if (rcode) { if(rcode) {
if (rcode != hrNAK) if(rcode != hrNAK)
USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81); USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81);
return rcode; return rcode;
} }
if (read > constBuffLen) if(read > constBuffLen)
read = constBuffLen; read = constBuffLen;
bool identical = BuffersIdentical(read, buf, prevBuf); bool identical = BuffersIdentical(read, buf, prevBuf);
SaveBuffer(read, buf, prevBuf); SaveBuffer(read, buf, prevBuf);
if (identical) if(identical)
return 0; return 0;
Notify(PSTR("\r\nBuf: "), 0x80); Notify(PSTR("\r\nBuf: "), 0x80);
for (uint8_t i = 0; i < read; i++) for(uint8_t i = 0; i < read; i++)
D_PrintHex<uint8_t > (buf[i], 0x80); D_PrintHex<uint8_t > (buf[i], 0x80);
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0)); HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
if (prs) if(prs)
prs->Parse(this, bHasReportId, (uint8_t)read, buf); prs->Parse(this, bHasReportId, (uint8_t)read, buf);
} }
} }

View file

@ -63,6 +63,7 @@
* Debug macros: Strings are stored in progmem (flash) instead of RAM. * Debug macros: Strings are stored in progmem (flash) instead of RAM.
*/ */
#define USBTRACE(s) (Notify(PSTR(s), 0x80)) #define USBTRACE(s) (Notify(PSTR(s), 0x80))
#define USBTRACE1(s,l) (Notify(PSTR(s), l))
#define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), D_PrintHex((r), 0x80), Notify(PSTR("\r\n"), 0x80)) #define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), D_PrintHex((r), 0x80), Notify(PSTR("\r\n"), 0x80))
#define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR("\r\n"), l)) #define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR("\r\n"), l))

View file

@ -17,7 +17,7 @@ const uint8_t BulkOnly::epInterruptInIndex = 3;
* @return media capacity * @return media capacity
*/ */
uint32_t BulkOnly::GetCapacity(uint8_t lun) { uint32_t BulkOnly::GetCapacity(uint8_t lun) {
if (LUNOk[lun]) if(LUNOk[lun])
return CurrentCapacity[lun]; return CurrentCapacity[lun];
return 0LU; return 0LU;
} }
@ -29,7 +29,7 @@ uint32_t BulkOnly::GetCapacity(uint8_t lun) {
* @return media sector size * @return media sector size
*/ */
uint16_t BulkOnly::GetSectorSize(uint8_t lun) { uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
if (LUNOk[lun]) if(LUNOk[lun])
return CurrentSectorSize[lun]; return CurrentSectorSize[lun];
return 0U; return 0U;
} }
@ -115,7 +115,7 @@ uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
Notify(PSTR("-----------------\r\n"), 0x80); Notify(PSTR("-----------------\r\n"), 0x80);
uint8_t rcode = MASS_ERR_UNIT_NOT_READY; uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
if (bAddress) { if(bAddress) {
CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0); CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);
rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT); rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT);
} else { } else {
@ -135,7 +135,7 @@ uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
* @return 0 on success * @return 0 on success
*/ */
uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) { uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA; if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
Notify(PSTR("\r\nRead LUN:\t"), 0x80); Notify(PSTR("\r\nRead LUN:\t"), 0x80);
D_PrintHex<uint8_t > (lun, 0x90); D_PrintHex<uint8_t > (lun, 0x90);
Notify(PSTR("\r\nLBA:\t\t"), 0x90); Notify(PSTR("\r\nLBA:\t\t"), 0x90);
@ -150,10 +150,10 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
again: again:
uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN); uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN);
if (er == MASS_ERR_STALL) { if(er == MASS_ERR_STALL) {
MediaCTL(lun, 1); MediaCTL(lun, 1);
delay(150); delay(150);
if (!TestUnitReady(lun)) goto again; if(!TestUnitReady(lun)) goto again;
} }
return er; return er;
} }
@ -169,8 +169,8 @@ again:
* @return 0 on success * @return 0 on success
*/ */
uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) { uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA; if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
if (!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED; if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;
Notify(PSTR("\r\nWrite LUN:\t"), 0x80); Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
D_PrintHex<uint8_t > (lun, 0x90); D_PrintHex<uint8_t > (lun, 0x90);
Notify(PSTR("\r\nLBA:\t\t"), 0x90); Notify(PSTR("\r\nLBA:\t\t"), 0x90);
@ -185,10 +185,10 @@ uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t bloc
again: again:
uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT); uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT);
if (er == MASS_ERR_WRITE_STALL) { if(er == MASS_ERR_WRITE_STALL) {
MediaCTL(lun, 1); MediaCTL(lun, 1);
delay(150); delay(150);
if (!TestUnitReady(lun)) goto again; if(!TestUnitReady(lun)) goto again;
} }
return er; return er;
} }
@ -213,7 +213,7 @@ bPollEnable(false),
bLastUsbError(0) { bLastUsbError(0) {
ClearAllEP(); ClearAllEP();
dCBWTag = 0; dCBWTag = 0;
if (pUsb) if(pUsb)
pUsb->RegisterDeviceClass(this); pUsb->RegisterDeviceClass(this);
} }
@ -245,17 +245,17 @@ uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
if (bAddress) if(bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// <TECHNICAL> // <TECHNICAL>
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) { if(!p) {
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
if (!p->epinfo) { if(!p->epinfo) {
USBTRACE("epinfo\r\n"); USBTRACE("epinfo\r\n");
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
@ -273,13 +273,13 @@ uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (rcode) { if(rcode) {
goto FailGetDevDescr; goto FailGetDevDescr;
} }
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
@ -315,14 +315,14 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
// Assign new address to the device // Assign new address to the device
delay(2000); delay(2000);
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -336,7 +336,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
@ -344,12 +344,12 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
USBTRACE2("NC:", num_of_conf); USBTRACE2("NC:", num_of_conf);
for (uint8_t i = 0; i < num_of_conf; i++) { for(uint8_t i = 0; i < num_of_conf; i++) {
ConfigDescParser< USB_CLASS_MASS_STORAGE, ConfigDescParser< USB_CLASS_MASS_STORAGE,
MASS_SUBCLASS_SCSI, MASS_SUBCLASS_SCSI,
MASS_PROTO_BBB, MASS_PROTO_BBB,
@ -359,14 +359,14 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
if (bNumEP > 1) if(bNumEP > 1)
break; break;
} }
if (bNumEP < 3) if(bNumEP < 3)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
@ -377,38 +377,38 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
//Linux does a 1sec delay after this. //Linux does a 1sec delay after this.
delay(1000); delay(1000);
rcode = GetMaxLUN(&bMaxLUN); rcode = GetMaxLUN(&bMaxLUN);
if (rcode) if(rcode)
goto FailGetMaxLUN; goto FailGetMaxLUN;
if (bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1; if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;
ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN); ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
delay(1000); // Delay a bit for slow firmware. delay(1000); // Delay a bit for slow firmware.
for (uint8_t lun = 0; lun <= bMaxLUN; lun++) { for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
InquiryResponse response; InquiryResponse response;
rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response); rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
if (rcode) { if(rcode) {
ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode); ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
} else { } else {
#if 0 #if 0
printf("LUN %i `", lun); printf("LUN %i `", lun);
uint8_t *buf = response.VendorID; uint8_t *buf = response.VendorID;
for (int i = 0; i < 28; i++) printf("%c", buf[i]); for(int i = 0; i < 28; i++) printf("%c", buf[i]);
printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier); printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier);
printf("Device type %2.2X ", response.DeviceType); printf("Device type %2.2X ", response.DeviceType);
printf("RMB %1.1X ", response.Removable); printf("RMB %1.1X ", response.Removable);
printf("SSCS %1.1X ", response.SCCS); printf("SSCS %1.1X ", response.SCCS);
uint8_t sv = response.Version; uint8_t sv = response.Version;
printf("SCSI version %2.2X\r\nDevice conforms to ", sv); printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
switch (sv) { switch(sv) {
case 0: case 0:
printf("No specific"); printf("No specific");
break; break;
@ -436,20 +436,20 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
printf(" standards.\r\n"); printf(" standards.\r\n");
#endif #endif
uint8_t tries = 0xf0; uint8_t tries = 0xf0;
while ((rcode = TestUnitReady(lun))) { while((rcode = TestUnitReady(lun))) {
if (rcode == 0x08) break; // break on no media, this is OK to do. if(rcode == 0x08) break; // break on no media, this is OK to do.
// try to lock media and spin up // try to lock media and spin up
if (tries < 14) { if(tries < 14) {
LockMedia(lun, 1); LockMedia(lun, 1);
MediaCTL(lun, 1); // I actually have a USB stick that needs this! MediaCTL(lun, 1); // I actually have a USB stick that needs this!
} else delay(2 * (tries + 1)); } else delay(2 * (tries + 1));
tries++; tries++;
if (!tries) break; if(!tries) break;
} }
if (!rcode) { if(!rcode) {
delay(1000); delay(1000);
LUNOk[lun] = CheckLUN(lun); LUNOk[lun] = CheckLUN(lun);
if (!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun); if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
} }
} }
} }
@ -459,7 +459,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
rcode = OnInit(); rcode = OnInit();
if (rcode) if(rcode)
goto FailOnInit; goto FailOnInit;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -489,11 +489,11 @@ FailGetMaxLUN:
goto Fail; goto Fail;
#endif #endif
//#ifdef DEBUG_USB_HOST //#ifdef DEBUG_USB_HOST
//FailInvalidSectorSize: //FailInvalidSectorSize:
// USBTRACE("Sector Size is NOT VALID: "); // USBTRACE("Sector Size is NOT VALID: ");
// goto Fail; // goto Fail;
//#endif //#endif
FailSetDevTblEntry: FailSetDevTblEntry:
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -532,10 +532,10 @@ void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t
uint8_t index; uint8_t index;
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
index = epInterruptInIndex; index = epInterruptInIndex;
else else
if ((pep->bmAttributes & 0x02) == 2) if((pep->bmAttributes & 0x02) == 2)
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
else else
return; return;
@ -570,35 +570,35 @@ uint8_t BulkOnly::Release() {
boolean BulkOnly::CheckLUN(uint8_t lun) { boolean BulkOnly::CheckLUN(uint8_t lun) {
uint8_t rcode; uint8_t rcode;
Capacity capacity; Capacity capacity;
for (uint8_t i = 0; i < 8; i++) capacity.data[i] = 0; for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;
rcode = ReadCapacity10(lun, (uint8_t*)capacity.data); rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);
if (rcode) { if(rcode) {
//printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode); //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
return false; return false;
} }
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun); ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
for (uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++) for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)
D_PrintHex<uint8_t > (capacity.data[i], 0x80); D_PrintHex<uint8_t > (capacity.data[i], 0x80);
Notify(PSTR("\r\n\r\n"), 0x80); Notify(PSTR("\r\n\r\n"), 0x80);
// Only 512/1024/2048/4096 are valid values! // Only 512/1024/2048/4096 are valid values!
uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]); uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);
if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) { if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
return false; return false;
} }
// Store capacity information. // Store capacity information.
CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF); CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);
CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1; CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;
if (CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) { if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) {
// Buggy firmware will report 0xffffffff or 0 for no media // Buggy firmware will report 0xffffffff or 0 for no media
if (CurrentCapacity[lun]) if(CurrentCapacity[lun])
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun); ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
return false; return false;
} }
delay(20); delay(20);
Page3F(lun); Page3F(lun);
if (!TestUnitReady(lun)) return true; if(!TestUnitReady(lun)) return true;
return false; return false;
} }
@ -608,18 +608,18 @@ boolean BulkOnly::CheckLUN(uint8_t lun) {
* Scan for media change on all LUNs * Scan for media change on all LUNs
*/ */
void BulkOnly::CheckMedia() { void BulkOnly::CheckMedia() {
for (uint8_t lun = 0; lun <= bMaxLUN; lun++) { for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
if (TestUnitReady(lun)) { if(TestUnitReady(lun)) {
LUNOk[lun] = false; LUNOk[lun] = false;
continue; continue;
} }
if (!LUNOk[lun]) if(!LUNOk[lun])
LUNOk[lun] = CheckLUN(lun); LUNOk[lun] = CheckLUN(lun);
} }
#if 0 #if 0
printf("}}}}}}}}}}}}}}}}STATUS "); printf("}}}}}}}}}}}}}}}}STATUS ");
for (uint8_t lun = 0; lun <= bMaxLUN; lun++) { for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
if (LUNOk[lun]) if(LUNOk[lun])
printf("#"); printf("#");
else printf("."); else printf(".");
} }
@ -636,10 +636,10 @@ void BulkOnly::CheckMedia() {
uint8_t BulkOnly::Poll() { uint8_t BulkOnly::Poll() {
//uint8_t rcode = 0; //uint8_t rcode = 0;
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
if (qNextPollTime <= millis()) { if(qNextPollTime <= millis()) {
CheckMedia(); CheckMedia();
} }
//rcode = 0; //rcode = 0;
@ -664,7 +664,7 @@ uint8_t BulkOnly::Poll() {
uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) { uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL); uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
if (ret == hrSTALL) if(ret == hrSTALL)
*plun = 0; *plun = 0;
return 0; return 0;
@ -696,7 +696,7 @@ uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
*/ */
uint8_t BulkOnly::TestUnitReady(uint8_t lun) { uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
//SetCurLUN(lun); //SetCurLUN(lun);
if (!bAddress) if(!bAddress)
return MASS_ERR_UNIT_NOT_READY; return MASS_ERR_UNIT_NOT_READY;
Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80); Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
@ -752,15 +752,15 @@ uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {
*/ */
uint8_t BulkOnly::Page3F(uint8_t lun) { uint8_t BulkOnly::Page3F(uint8_t lun) {
uint8_t buf[192]; uint8_t buf[192];
for (int i = 0; i < 192; i++) { for(int i = 0; i < 192; i++) {
buf[i] = 0x00; buf[i] = 0x00;
} }
WriteOk[lun] = true; WriteOk[lun] = true;
uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf); uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
if (!rc) { if(!rc) {
WriteOk[lun] = ((buf[2] & 0x80) == 0); WriteOk[lun] = ((buf[2] & 0x80) == 0);
Notify(PSTR("Mode Sense: "), 0x80); Notify(PSTR("Mode Sense: "), 0x80);
for (int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
D_PrintHex<uint8_t > (buf[i], 0x80); D_PrintHex<uint8_t > (buf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -803,15 +803,15 @@ uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
* @return * @return
*/ */
uint8_t BulkOnly::ClearEpHalt(uint8_t index) { uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
if (index == 0) if(index == 0)
return 0; return 0;
uint8_t ret = 0; uint8_t ret = 0;
while ((ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)) == 0x01)) while((ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)) == 0x01))
delay(6); delay(6);
if (ret) { if(ret) {
ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret); ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr)); ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
return ret; return ret;
@ -827,7 +827,7 @@ uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
* *
*/ */
void BulkOnly::Reset() { void BulkOnly::Reset() {
while (pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6); while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
} }
/** /**
@ -855,7 +855,7 @@ uint8_t BulkOnly::ResetRecovery() {
* Clear all EP data and clear all LUN status * Clear all EP data and clear all LUN status
*/ */
void BulkOnly::ClearAllEP() { void BulkOnly::ClearAllEP() {
for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) { for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
@ -863,7 +863,7 @@ void BulkOnly::ClearAllEP() {
epInfo[i].bmNakPower = USB_NAK_DEFAULT; epInfo[i].bmNakPower = USB_NAK_DEFAULT;
} }
for (uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) { for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {
LUNOk[i] = false; LUNOk[i] = false;
WriteOk[i] = false; WriteOk[i] = false;
CurrentCapacity[i] = 0lu; CurrentCapacity[i] = 0lu;
@ -888,11 +888,11 @@ void BulkOnly::ClearAllEP() {
* @return * @return
*/ */
bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) { bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
if (pcsw->dCSWSignature != MASS_CSW_SIGNATURE) { if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
Notify(PSTR("CSW:Sig error\r\n"), 0x80); Notify(PSTR("CSW:Sig error\r\n"), 0x80);
return false; return false;
} }
if (pcsw->dCSWTag != pcbw->dCBWTag) { if(pcsw->dCSWTag != pcbw->dCBWTag) {
Notify(PSTR("CSW:Wrong tag\r\n"), 0x80); Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
return false; return false;
} }
@ -912,12 +912,12 @@ uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
bLastUsbError = error; bLastUsbError = error;
//if (error) //if (error)
//ClearEpHalt(index); //ClearEpHalt(index);
while (error && count) { while(error && count) {
if (error != hrSUCCESS) { if(error != hrSUCCESS) {
ErrorMessage<uint8_t > (PSTR("USB Error"), error); ErrorMessage<uint8_t > (PSTR("USB Error"), error);
ErrorMessage<uint8_t > (PSTR("Index"), index); ErrorMessage<uint8_t > (PSTR("Index"), index);
} }
switch (error) { switch(error) {
// case hrWRONGPID: // case hrWRONGPID:
case hrSUCCESS: case hrSUCCESS:
return MASS_ERR_SUCCESS; return MASS_ERR_SUCCESS;
@ -927,15 +927,15 @@ uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
case hrTIMEOUT: case hrTIMEOUT:
case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED; case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED;
case hrSTALL: case hrSTALL:
if (index == 0) if(index == 0)
return MASS_ERR_STALL; return MASS_ERR_STALL;
ClearEpHalt(index); ClearEpHalt(index);
if (index != epDataInIndex) if(index != epDataInIndex)
return MASS_ERR_WRITE_STALL; return MASS_ERR_WRITE_STALL;
return MASS_ERR_STALL; return MASS_ERR_STALL;
case hrNAK: case hrNAK:
if (index == 0) if(index == 0)
return MASS_ERR_UNIT_BUSY; return MASS_ERR_UNIT_BUSY;
return MASS_ERR_UNIT_BUSY; return MASS_ERR_UNIT_BUSY;
@ -944,10 +944,10 @@ uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
// I have only ran into one device that has this firmware bug, and this is // I have only ran into one device that has this firmware bug, and this is
// the only clean way to get back into sync with the buggy device firmware. // the only clean way to get back into sync with the buggy device firmware.
// --AJK // --AJK
if (bAddress && bConfNum) { if(bAddress && bConfNum) {
error = pUsb->setConf(bAddress, 0, bConfNum); error = pUsb->setConf(bAddress, 0, bConfNum);
if (error) if(error)
break; break;
} }
return MASS_ERR_SUCCESS; return MASS_ERR_SUCCESS;
@ -999,33 +999,33 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
SetCurLUN(pcbw->bmCBWLUN); SetCurLUN(pcbw->bmCBWLUN);
ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1); while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
ret = HandleUsbError(usberr, epDataOutIndex); ret = HandleUsbError(usberr, epDataOutIndex);
//ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex); //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
if (ret) { if(ret) {
ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret); ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
} else { } else {
if (bytes) { if(bytes) {
if (!write) { if(!write) {
#if MS_WANT_PARSER #if MS_WANT_PARSER
if (callback) { if(callback) {
uint8_t rbuf[bytes]; uint8_t rbuf[bytes];
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1); while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0); if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
} else { } else {
#endif #endif
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1); while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
#if MS_WANT_PARSER #if MS_WANT_PARSER
} }
#endif #endif
ret = HandleUsbError(usberr, epDataInIndex); ret = HandleUsbError(usberr, epDataInIndex);
} else { } else {
while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1); while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
ret = HandleUsbError(usberr, epDataOutIndex); ret = HandleUsbError(usberr, epDataOutIndex);
} }
if (ret) { if(ret) {
ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret); ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
} }
} }
@ -1034,13 +1034,13 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
{ {
bytes = sizeof (CommandStatusWrapper); bytes = sizeof (CommandStatusWrapper);
int tries = 2; int tries = 2;
while (tries--) { while(tries--) {
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1); while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
if (!usberr) break; if(!usberr) break;
ClearEpHalt(epDataInIndex); ClearEpHalt(epDataInIndex);
if (tries) ResetRecovery(); if(tries) ResetRecovery();
} }
if (!ret) { if(!ret) {
Notify(PSTR("CBW:\t\tOK\r\n"), 0x80); Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
Notify(PSTR("Data Stage:\tOK\r\n"), 0x80); Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
} else { } else {
@ -1049,11 +1049,11 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
return ret; return ret;
} }
ret = HandleUsbError(usberr, epDataInIndex); ret = HandleUsbError(usberr, epDataInIndex);
if (ret) { if(ret) {
ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret); ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
} }
if (usberr == hrSUCCESS) { if(usberr == hrSUCCESS) {
if (IsValidCSW(&csw, pcbw)) { if(IsValidCSW(&csw, pcbw)) {
//ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag); //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
//ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus); //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
//ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue); //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
@ -1082,7 +1082,7 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
* @return * @return
*/ */
uint8_t BulkOnly::SetCurLUN(uint8_t lun) { uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
if (lun > bMaxLUN) if(lun > bMaxLUN)
return MASS_ERR_INVALID_LUN; return MASS_ERR_INVALID_LUN;
bTheLUN = lun; bTheLUN = lun;
return MASS_ERR_SUCCESS; return MASS_ERR_SUCCESS;
@ -1097,7 +1097,7 @@ uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
uint8_t BulkOnly::HandleSCSIError(uint8_t status) { uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
uint8_t ret = 0; uint8_t ret = 0;
switch (status) { switch(status) {
case 0: return MASS_ERR_SUCCESS; case 0: return MASS_ERR_SUCCESS;
case 2: case 2:
@ -1113,13 +1113,13 @@ uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp); ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
if (ret) { if(ret) {
return MASS_ERR_GENERAL_SCSI_ERROR; return MASS_ERR_GENERAL_SCSI_ERROR;
} }
ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode); ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
if (rsp.bResponseCode & 0x80) { if(rsp.bResponseCode & 0x80) {
Notify(PSTR("Information field: "), 0x80); Notify(PSTR("Information field: "), 0x80);
for (int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80); D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
@ -1129,23 +1129,23 @@ uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode); ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier); ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
// warning, this is not testing ASQ, only SK and ASC. // warning, this is not testing ASQ, only SK and ASC.
switch (rsp.bmSenseKey) { switch(rsp.bmSenseKey) {
case SCSI_S_UNIT_ATTENTION: case SCSI_S_UNIT_ATTENTION:
switch (rsp.bAdditionalSenseCode) { switch(rsp.bAdditionalSenseCode) {
case SCSI_ASC_MEDIA_CHANGED: case SCSI_ASC_MEDIA_CHANGED:
return MASS_ERR_MEDIA_CHANGED; return MASS_ERR_MEDIA_CHANGED;
default: default:
return MASS_ERR_UNIT_NOT_READY; return MASS_ERR_UNIT_NOT_READY;
} }
case SCSI_S_NOT_READY: case SCSI_S_NOT_READY:
switch (rsp.bAdditionalSenseCode) { switch(rsp.bAdditionalSenseCode) {
case SCSI_ASC_MEDIUM_NOT_PRESENT: case SCSI_ASC_MEDIUM_NOT_PRESENT:
return MASS_ERR_NO_MEDIA; return MASS_ERR_NO_MEDIA;
default: default:
return MASS_ERR_UNIT_NOT_READY; return MASS_ERR_UNIT_NOT_READY;
} }
case SCSI_S_ILLEGAL_REQUEST: case SCSI_S_ILLEGAL_REQUEST:
switch (rsp.bAdditionalSenseCode) { switch(rsp.bAdditionalSenseCode) {
case SCSI_ASC_LBA_OUT_OF_RANGE: case SCSI_ASC_LBA_OUT_OF_RANGE:
return MASS_ERR_BAD_LBA; return MASS_ERR_BAD_LBA;
default: default:
@ -1207,7 +1207,7 @@ void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {
/* We won't be needing this... */ /* We won't be needing this... */
uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) { uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
#if MS_WANT_PARSER #if MS_WANT_PARSER
if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA; if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80); Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
Notify(PSTR("---------\r\n"), 0x80); Notify(PSTR("---------\r\n"), 0x80);

View file

@ -396,7 +396,7 @@ public:
// Type punning can cause optimization problems and bugs. // Type punning can cause optimization problems and bugs.
// Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this. // Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this.
//(((BASICCDB_t *) CBWCB)->LUN) = cmd; //(((BASICCDB_t *) CBWCB)->LUN) = cmd;
BASICCDB_t *x = reinterpret_cast<BASICCDB_t *> (CBWCB); BASICCDB_t *x = reinterpret_cast<BASICCDB_t *>(CBWCB);
x->LUN = cmd; x->LUN = cmd;
} }
@ -516,7 +516,7 @@ public:
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
virtual boolean DEVCLASSOK(uint8_t klass) { virtual boolean DEVCLASSOK(uint8_t klass) {
return(klass == USB_CLASS_MASS_STORAGE); return (klass == USB_CLASS_MASS_STORAGE);
} }
uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);

View file

@ -52,14 +52,14 @@ void Max_LCD::init() {
} }
void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
if (lines > 1) { if(lines > 1) {
_displayfunction |= LCD_2LINE; _displayfunction |= LCD_2LINE;
} }
_numlines = lines; _numlines = lines;
_currline = 0; _currline = 0;
// for some 1 line displays you can select a 10 pixel high font // for some 1 line displays you can select a 10 pixel high font
if ((dotsize != 0) && (lines == 1)) { if((dotsize != 0) && (lines == 1)) {
_displayfunction |= LCD_5x10DOTS; _displayfunction |= LCD_5x10DOTS;
} }
@ -123,7 +123,7 @@ void Max_LCD::home() {
void Max_LCD::setCursor(uint8_t col, uint8_t row) { void Max_LCD::setCursor(uint8_t col, uint8_t row) {
int row_offsets[] = {0x00, 0x40, 0x14, 0x54}; int row_offsets[] = {0x00, 0x40, 0x14, 0x54};
if (row > _numlines) { if(row > _numlines) {
row = _numlines - 1; // we count rows starting w/0 row = _numlines - 1; // we count rows starting w/0
} }
@ -211,7 +211,7 @@ void Max_LCD::noAutoscroll(void) {
void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) { void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7 location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3)); command(LCD_SETCGRAMADDR | (location << 3));
for (int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
write(charmap[i]); write(charmap[i]);
} }
} }
@ -224,11 +224,13 @@ inline void Max_LCD::command(uint8_t value) {
} }
#if defined(ARDUINO) && ARDUINO >=100 #if defined(ARDUINO) && ARDUINO >=100
inline size_t Max_LCD::write(uint8_t value) { inline size_t Max_LCD::write(uint8_t value) {
LCD_sendchar(value); LCD_sendchar(value);
return 1; // Assume success return 1; // Assume success
} }
#else #else
inline void Max_LCD::write(uint8_t value) { inline void Max_LCD::write(uint8_t value) {
LCD_sendchar(value); LCD_sendchar(value);
} }

View file

@ -62,8 +62,7 @@ e-mail : support@circuitsathome.com
#define LCD_5x10DOTS 0x04 #define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00 #define LCD_5x8DOTS 0x00
class Max_LCD : public Print class Max_LCD : public Print {
{
USB *pUsb; USB *pUsb;
public: public:

View file

@ -22,7 +22,7 @@ e-mail : support@circuitsathome.com
int UsbDEBUGlvl = 0x80; int UsbDEBUGlvl = 0x80;
void E_Notifyc(char c, int lvl) { void E_Notifyc(char c, int lvl) {
if (UsbDEBUGlvl < lvl) return; if(UsbDEBUGlvl < lvl) return;
#if defined(ARDUINO) && ARDUINO >=100 #if defined(ARDUINO) && ARDUINO >=100
USB_HOST_SERIAL.print(c); USB_HOST_SERIAL.print(c);
#else #else
@ -32,23 +32,23 @@ void E_Notifyc(char c, int lvl) {
} }
void E_Notify(char const * msg, int lvl) { void E_Notify(char const * msg, int lvl) {
if (UsbDEBUGlvl < lvl) return; if(UsbDEBUGlvl < lvl) return;
if (!msg) return; if(!msg) return;
char c; char c;
while ((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl); while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl);
} }
void E_NotifyStr(char const * msg, int lvl) { void E_NotifyStr(char const * msg, int lvl) {
if (UsbDEBUGlvl < lvl) return; if(UsbDEBUGlvl < lvl) return;
if (!msg) return; if(!msg) return;
char c; char c;
while ((c = *msg++)) E_Notifyc(c, lvl); while((c = *msg++)) E_Notifyc(c, lvl);
} }
void E_Notify(uint8_t b, int lvl) { void E_Notify(uint8_t b, int lvl) {
if (UsbDEBUGlvl < lvl) return; if(UsbDEBUGlvl < lvl) return;
#if defined(ARDUINO) && ARDUINO >=100 #if defined(ARDUINO) && ARDUINO >=100
USB_HOST_SERIAL.print(b); USB_HOST_SERIAL.print(b);
#else #else
@ -58,12 +58,13 @@ void E_Notify(uint8_t b, int lvl) {
} }
void E_Notify(double d, int lvl) { void E_Notify(double d, int lvl) {
if (UsbDEBUGlvl < lvl) return; if(UsbDEBUGlvl < lvl) return;
USB_HOST_SERIAL.print(d); USB_HOST_SERIAL.print(d);
//USB_HOST_SERIAL.flush(); //USB_HOST_SERIAL.flush();
} }
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
void NotifyFailGetDevDescr(void) { void NotifyFailGetDevDescr(void) {
Notify(PSTR("\r\ngetDevDescr "), 0x80); Notify(PSTR("\r\ngetDevDescr "), 0x80);
} }
@ -71,6 +72,7 @@ void NotifyFailGetDevDescr(void) {
void NotifyFailSetDevTblEntry(void) { void NotifyFailSetDevTblEntry(void) {
Notify(PSTR("\r\nsetDevTblEn "), 0x80); Notify(PSTR("\r\nsetDevTblEn "), 0x80);
} }
void NotifyFailGetConfDescr(void) { void NotifyFailGetConfDescr(void) {
Notify(PSTR("\r\ngetConf "), 0x80); Notify(PSTR("\r\ngetConf "), 0x80);
} }

View file

@ -17,14 +17,14 @@ e-mail : support@circuitsathome.com
#include "Usb.h" #include "Usb.h"
bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) { bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) {
if (!pBuf) { if(!pBuf) {
Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80); Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80);
return false; return false;
} }
for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++) for(; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
pBuf[valueSize - countDown] = (**pp); pBuf[valueSize - countDown] = (**pp);
if (countDown) if(countDown)
return false; return false;
countDown = valueSize; countDown = valueSize;
@ -32,14 +32,14 @@ bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) {
} }
bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) { bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) {
switch (nStage) { switch(nStage) {
case 0: case 0:
pBuf->valueSize = lenSize; pBuf->valueSize = lenSize;
theParser.Initialize(pBuf); theParser.Initialize(pBuf);
nStage = 1; nStage = 1;
case 1: case 1:
if (!theParser.Parse(pp, pcntdn)) if(!theParser.Parse(pp, pcntdn))
return false; return false;
arLen = 0; arLen = 0;
@ -53,11 +53,11 @@ bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf,
nStage = 3; nStage = 3;
case 3: case 3:
for (; arLenCntdn; arLenCntdn--) { for(; arLenCntdn; arLenCntdn--) {
if (!theParser.Parse(pp, pcntdn)) if(!theParser.Parse(pp, pcntdn))
return false; return false;
if (pf) if(pf)
pf(pBuf, (arLen - arLenCntdn), me); pf(pBuf, (arLen - arLenCntdn), me);
} }

View file

@ -40,7 +40,7 @@ public:
}; };
void Initialize(MultiValueBuffer * const pbuf) { void Initialize(MultiValueBuffer * const pbuf) {
pBuf = (uint8_t*) pbuf->pValue; pBuf = (uint8_t*)pbuf->pValue;
countDown = valueSize = pbuf->valueSize; countDown = valueSize = pbuf->valueSize;
}; };
@ -58,7 +58,7 @@ public:
}; };
void Initialize(MultiValueBuffer *pbuf) { void Initialize(MultiValueBuffer *pbuf) {
pBuf = (uint8_t*) pbuf->pValue; pBuf = (uint8_t*)pbuf->pValue;
countDown = 0; countDown = 0;
}; };
@ -73,7 +73,7 @@ public:
if(!countDown) if(!countDown)
nStage = 0; nStage = 0;
}; };
return(!countDown); return (!countDown);
}; };
}; };

View file

@ -24,7 +24,7 @@ void E_Notifyc(char c, int lvl);
template <class T> template <class T>
void PrintHex(T val, int lvl) { void PrintHex(T val, int lvl) {
int num_nibbles = sizeof(T) * 2; int num_nibbles = sizeof (T) * 2;
do { do {
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
@ -35,7 +35,7 @@ void PrintHex(T val, int lvl) {
template <class T> template <class T>
void PrintBin(T val, int lvl) { void PrintBin(T val, int lvl) {
for(T mask = (((T) 1) << ((sizeof(T) << 3) - 1)); mask; mask >>= 1) for(T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1)
if(val & mask) if(val & mask)
E_Notifyc('1', lvl); E_Notifyc('1', lvl);
else else
@ -44,7 +44,7 @@ void PrintBin(T val, int lvl) {
template <class T> template <class T>
void SerialPrintHex(T val) { void SerialPrintHex(T val) {
int num_nibbles = sizeof(T) * 2; int num_nibbles = sizeof (T) * 2;
do { do {
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
@ -55,7 +55,7 @@ void SerialPrintHex(T val) {
template <class T> template <class T>
void PrintHex2(Print *prn, T val) { void PrintHex2(Print *prn, T val) {
T mask = (((T) 1) << (((sizeof(T) << 1) - 1) << 2)); T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2));
while(mask > 1) { while(mask > 1) {
if(val < mask) if(val < mask)
@ -63,19 +63,19 @@ void PrintHex2(Print *prn, T val) {
mask >>= 4; mask >>= 4;
} }
prn->print((T) val, HEX); prn->print((T)val, HEX);
} }
template <class T> void D_PrintHex(T val, int lvl) { template <class T> void D_PrintHex(T val, int lvl) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
PrintHex<T>(val, lvl); PrintHex<T > (val, lvl);
#endif #endif
} }
template <class T> template <class T>
void D_PrintBin(T val, int lvl) { void D_PrintBin(T val, int lvl) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
PrintBin<T>(val, lvl); PrintBin<T > (val, lvl);
#endif #endif
} }

View file

@ -22,14 +22,19 @@ e-mail : support@circuitsathome.com
extern int UsbDEBUGlvl; extern int UsbDEBUGlvl;
// This parser does absolutely nothing with the data, just swallows it. // This parser does absolutely nothing with the data, just swallows it.
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE> template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
class SinkParser : public BASE_CLASS { class SinkParser : public BASE_CLASS {
public: public:
SinkParser() {}; SinkParser() {
void Initialize() {}; };
void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {};
void Initialize() {
};
void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {
};
}; };

View file

@ -162,7 +162,7 @@ uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t*
#endif #endif
SPI_SS::Set(); SPI_SS::Set();
XMEM_RELEASE_SPI(); XMEM_RELEASE_SPI();
return( data_p); return ( data_p);
} }
/* GPIO write */ /* GPIO write */
/*GPIO byte is split between 2 registers, so two writes are needed to write one byte */ /*GPIO byte is split between 2 registers, so two writes are needed to write one byte */
@ -194,7 +194,7 @@ uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) {
uint8_t rv = SPDR; uint8_t rv = SPDR;
#endif #endif
XMEM_RELEASE_SPI(); XMEM_RELEASE_SPI();
return(rv); return (rv);
} }
/* multiple-byte register read */ /* multiple-byte register read */
@ -229,7 +229,7 @@ uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t*
#endif #endif
SPI_SS::Set(); SPI_SS::Set();
XMEM_RELEASE_SPI(); XMEM_RELEASE_SPI();
return( data_p); return ( data_p);
} }
/* GPIO read. See gpioWr for explanation */ /* GPIO read. See gpioWr for explanation */
@ -240,7 +240,7 @@ uint8_t MAX3421e< SPI_SS, INTR >::gpioRd() {
gpin = regRd(rIOPINS2); //pins 4-7 gpin = regRd(rIOPINS2); //pins 4-7
gpin &= 0xf0; //clean lower nibble gpin &= 0xf0; //clean lower nibble
gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation. gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation.
return( gpin); return ( gpin);
} }
/* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset /* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset
@ -255,7 +255,7 @@ uint16_t MAX3421e< SPI_SS, INTR >::reset() {
break; break;
} }
} }
return( i); return ( i);
} }
/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
@ -276,7 +276,7 @@ int8_t MAX3421e< SPI_SS, INTR >::Init() {
regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
if(reset() == 0) { //OSCOKIRQ hasn't asserted in time if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
return( -1); return ( -1);
} }
regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
@ -292,7 +292,7 @@ int8_t MAX3421e< SPI_SS, INTR >::Init() {
regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
regWr(rCPUCTL, 0x01); //enable interrupt pin regWr(rCPUCTL, 0x01); //enable interrupt pin
return( 0); return ( 0);
} }
/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
@ -312,7 +312,7 @@ int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) {
regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET)); regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET));
if(reset() == 0) { //OSCOKIRQ hasn't asserted in time if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
return( -1); return ( -1);
} }
// Delay a minimum of 1 second to ensure any capacitors are drained. // Delay a minimum of 1 second to ensure any capacitors are drained.
@ -336,7 +336,7 @@ int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) {
// GPX pin on. This is done here so that busprobe will fail if we have a switch connected. // GPX pin on. This is done here so that busprobe will fail if we have a switch connected.
regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
return( 0); return ( 0);
} }
/* probe bus to determine device presence and speed and switch host to this speed */ /* probe bus to determine device presence and speed and switch host to this speed */
@ -391,7 +391,7 @@ uint8_t MAX3421e< SPI_SS, INTR >::Task(void) {
// GpxHandler(); // GpxHandler();
// } // }
// usbSM(); //USB state machine // usbSM(); //USB state machine
return( rcode); return ( rcode);
} }
template< typename SPI_SS, typename INTR > template< typename SPI_SS, typename INTR >
@ -408,7 +408,7 @@ uint8_t MAX3421e< SPI_SS, INTR >::IntHandler() {
} }
/* End HIRQ interrupts handling, clear serviced IRQs */ /* End HIRQ interrupts handling, clear serviced IRQs */
regWr(rHIRQ, HIRQ_sendback); regWr(rHIRQ, HIRQ_sendback);
return( HIRQ_sendback); return ( HIRQ_sendback);
} }
//template< typename SPI_SS, typename INTR > //template< typename SPI_SS, typename INTR >
//uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler() //uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler()

View file

@ -35,7 +35,7 @@ bPollEnable(false) {
epInfo[1].epAttribs = 0; epInfo[1].epAttribs = 0;
epInfo[1].bmNakPower = USB_NAK_NOWAIT; epInfo[1].bmNakPower = USB_NAK_NOWAIT;
if (pUsb) if(pUsb)
pUsb->RegisterDeviceClass(this); pUsb->RegisterDeviceClass(this);
} }
@ -57,133 +57,133 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
//switch (bInitState) { //switch (bInitState) {
// case 0: // case 0:
if (bAddress) if(bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo) if(!p->epinfo)
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
// Save old pointer to EP_RECORD of address 0 // Save old pointer to EP_RECORD of address 0
oldep_ptr = p->epinfo; oldep_ptr = p->epinfo;
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo; p->epinfo = epInfo;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
p->lowspeed = false; p->lowspeed = false;
if (!rcode) if(!rcode)
len = (buf[0] > 32) ? 32 : buf[0]; len = (buf[0] > 32) ? 32 : buf[0];
if (rcode) { if(rcode) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
return rcode; return rcode;
} }
// Extract device class from device descriptor // Extract device class from device descriptor
// If device class is not a hub return // If device class is not a hub return
if (udd->bDeviceClass != 0x09) if(udd->bDeviceClass != 0x09)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, (udd->bDeviceClass == 0x09) ? true : false, port); bAddress = addrPool.AllocAddress(parent, (udd->bDeviceClass == 0x09) ? true : false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
epInfo[0].maxPktSize = udd->bMaxPacketSize0; epInfo[0].maxPktSize = udd->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
return rcode; return rcode;
} }
//USBTRACE2("\r\nHub address: ", bAddress ); //USBTRACE2("\r\nHub address: ", bAddress );
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (len) if(len)
rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
// bInitState = 1; // bInitState = 1;
// case 1: // case 1:
// Get hub descriptor // Get hub descriptor
rcode = GetHubDescriptor(0, 8, buf); rcode = GetHubDescriptor(0, 8, buf);
if (rcode) if(rcode)
goto FailGetHubDescr; goto FailGetHubDescr;
// Save number of ports for future use // Save number of ports for future use
bNbrPorts = hd->bNbrPorts; bNbrPorts = hd->bNbrPorts;
// bInitState = 2; // bInitState = 2;
// case 2: // case 2:
// Read configuration Descriptor in Order To Obtain Proper Configuration Value // Read configuration Descriptor in Order To Obtain Proper Configuration Value
rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf);
if (!rcode) { if(!rcode) {
cd_len = ucd->wTotalLength; cd_len = ucd->wTotalLength;
rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf); rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf);
} }
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
// The following code is of no practical use in real life applications. // The following code is of no practical use in real life applications.
// It only intended for the usb protocol sniffer to properly parse hub-class requests. // It only intended for the usb protocol sniffer to properly parse hub-class requests.
{ {
uint8_t buf2[24]; uint8_t buf2[24];
rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2); rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2);
if (rcode) if(rcode)
goto FailGetConfDescr; goto FailGetConfDescr;
} }
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, buf[5]); rcode = pUsb->setConf(bAddress, 0, buf[5]);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
// bInitState = 3; // bInitState = 3;
// case 3: // case 3:
// Power on all ports // Power on all ports
for (uint8_t j = 1; j <= bNbrPorts; j++) for(uint8_t j = 1; j <= bNbrPorts; j++)
SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j); SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j);
pUsb->SetHubPreMask(); pUsb->SetHubPreMask();
bPollEnable = true; bPollEnable = true;
// bInitState = 0; // bInitState = 0;
//} //}
//bInitState = 0; //bInitState = 0;
@ -214,7 +214,7 @@ Fail:
uint8_t USBHub::Release() { uint8_t USBHub::Release() {
pUsb->GetAddressPool().FreeAddress(bAddress); pUsb->GetAddressPool().FreeAddress(bAddress);
if (bAddress == 0x41) if(bAddress == 0x41)
pUsb->SetHubPreMask(); pUsb->SetHubPreMask();
bAddress = 0; bAddress = 0;
@ -227,10 +227,10 @@ uint8_t USBHub::Release() {
uint8_t USBHub::Poll() { uint8_t USBHub::Poll() {
uint8_t rcode = 0; uint8_t rcode = 0;
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
if (qNextPollTime <= millis()) { if(qNextPollTime <= millis()) {
rcode = CheckHubStatus(); rcode = CheckHubStatus();
qNextPollTime = millis() + 100; qNextPollTime = millis() + 100;
} }
@ -244,7 +244,7 @@ uint8_t USBHub::CheckHubStatus() {
rcode = pUsb->inTransfer(bAddress, 1, &read, buf); rcode = pUsb->inTransfer(bAddress, 1, &read, buf);
if (rcode) if(rcode)
return rcode; return rcode;
//if (buf[0] & 0x01) // Hub Status Change //if (buf[0] & 0x01) // Hub Status Change
@ -258,36 +258,36 @@ uint8_t USBHub::CheckHubStatus() {
// return rcode; // return rcode;
// } // }
//} //}
for (uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) { for(uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) {
if (buf[0] & mask) { if(buf[0] & mask) {
HubEvent evt; HubEvent evt;
evt.bmEvent = 0; evt.bmEvent = 0;
rcode = GetPortStatus(port, 4, evt.evtBuff); rcode = GetPortStatus(port, 4, evt.evtBuff);
if (rcode) if(rcode)
continue; continue;
rcode = PortStatusChange(port, evt); rcode = PortStatusChange(port, evt);
if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
return 0; return 0;
if (rcode) if(rcode)
return rcode; return rcode;
} }
} // for } // for
for (uint8_t port = 1; port <= bNbrPorts; port++) { for(uint8_t port = 1; port <= bNbrPorts; port++) {
HubEvent evt; HubEvent evt;
evt.bmEvent = 0; evt.bmEvent = 0;
rcode = GetPortStatus(port, 4, evt.evtBuff); rcode = GetPortStatus(port, 4, evt.evtBuff);
if (rcode) if(rcode)
continue; continue;
if ((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED) if((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED)
continue; continue;
// Emulate connection event for the port // Emulate connection event for the port
@ -295,10 +295,10 @@ uint8_t USBHub::CheckHubStatus() {
rcode = PortStatusChange(port, evt); rcode = PortStatusChange(port, evt);
if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
return 0; return 0;
if (rcode) if(rcode)
return rcode; return rcode;
} // for } // for
return 0; return 0;
@ -314,10 +314,10 @@ void USBHub::ResetHubPort(uint8_t port) {
SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0);
for (int i = 0; i < 3; i++) { for(int i = 0; i < 3; i++) {
rcode = GetPortStatus(port, 4, evt.evtBuff); rcode = GetPortStatus(port, 4, evt.evtBuff);
if (rcode) break; // Some kind of error, bail. if(rcode) break; // Some kind of error, bail.
if (evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) { if(evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) {
break; break;
} }
delay(100); // simulate polling. delay(100); // simulate polling.
@ -328,11 +328,11 @@ void USBHub::ResetHubPort(uint8_t port) {
} }
uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) { uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) {
switch (evt.bmEvent) { switch(evt.bmEvent) {
// Device connected event // Device connected event
case bmHUB_PORT_EVENT_CONNECT: case bmHUB_PORT_EVENT_CONNECT:
case bmHUB_PORT_EVENT_LS_CONNECT: case bmHUB_PORT_EVENT_LS_CONNECT:
if (bResetInitiated) if(bResetInitiated)
return 0; return 0;
ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
@ -379,7 +379,7 @@ void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_c
rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff); rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff);
if (rcode) { if(rcode) {
USB_HOST_SERIAL.println("ERROR!"); USB_HOST_SERIAL.println("ERROR!");
return; return;
} }
@ -408,7 +408,7 @@ void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_c
USB_HOST_SERIAL.print("INDICATOR:\t"); USB_HOST_SERIAL.print("INDICATOR:\t");
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC); USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC);
if (!print_changes) if(!print_changes)
return; return;
USB_HOST_SERIAL.println("\r\nChange"); USB_HOST_SERIAL.println("\r\nChange");

View file

@ -170,7 +170,7 @@ class USBHub : USBDeviceConfig {
uint8_t bAddress; // address uint8_t bAddress; // address
uint8_t bNbrPorts; // number of ports uint8_t bNbrPorts; // number of ports
// uint8_t bInitState; // initialization state variable // uint8_t bInitState; // initialization state variable
uint32_t qNextPollTime; // next poll time uint32_t qNextPollTime; // next poll time
bool bPollEnable; // poll enable flag bool bPollEnable; // poll enable flag
@ -195,52 +195,56 @@ public:
virtual uint8_t Release(); virtual uint8_t Release();
virtual uint8_t Poll(); virtual uint8_t Poll();
virtual void ResetHubPort(uint8_t port); virtual void ResetHubPort(uint8_t port);
virtual uint8_t GetAddress() { virtual uint8_t GetAddress() {
return bAddress; return bAddress;
}; };
virtual boolean DEVCLASSOK(uint8_t klass) { return (klass == 0x09); }
virtual boolean DEVCLASSOK(uint8_t klass) {
return (klass == 0x09);
}
}; };
// Clear Hub Feature // Clear Hub Feature
inline uint8_t USBHub::ClearHubFeature(uint8_t fid) { inline uint8_t USBHub::ClearHubFeature(uint8_t fid) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
} }
// Clear Port Feature // Clear Port Feature
inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) { inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL));
} }
// Get Hub Descriptor // Get Hub Descriptor
inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) { inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL));
} }
// Get Hub Status // Get Hub Status
inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) { inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL));
} }
// Get Port Status // Get Port Status
inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) { inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL));
} }
// Set Hub Descriptor // Set Hub Descriptor
inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) { inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL));
} }
// Set Hub Feature // Set Hub Feature
inline uint8_t USBHub::SetHubFeature(uint8_t fid) { inline uint8_t USBHub::SetHubFeature(uint8_t fid) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
} }
// Set Port Feature // Set Port Feature
inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) { inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
return( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL));
} }
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false);