From e986282fa59c42368239e929e5bbb6079c4be448 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Mon, 28 Apr 2014 22:01:38 +0200 Subject: [PATCH 01/23] Forgot to call setLedRaw with the controller as the second argument in setLedOn --- XBOXRECV.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XBOXRECV.cpp b/XBOXRECV.cpp index e70e322a..144a4aa4 100644 --- a/XBOXRECV.cpp +++ b/XBOXRECV.cpp @@ -514,9 +514,9 @@ void XBOXRECV::setLedRaw(uint8_t value, uint8_t controller) { void XBOXRECV::setLedOn(LEDEnum led, uint8_t controller) { if(led == OFF) - setLedRaw(0); + setLedRaw(0, controller); else if(led != ALL) // All LEDs can't be on a the same time - setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4); + setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4, controller); } void XBOXRECV::setLedBlink(LEDEnum led, uint8_t controller) { From 67cb06e858582cf642a6df062a891659574b62e9 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Wed, 21 May 2014 23:29:15 +0200 Subject: [PATCH 02/23] Add space between bytes printed for debugging --- hiduniversal.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hiduniversal.cpp b/hiduniversal.cpp index c2f33533..3bd30339 100644 --- a/hiduniversal.cpp +++ b/hiduniversal.cpp @@ -401,8 +401,10 @@ uint8_t HIDUniversal::Poll() { #if 1 Notify(PSTR("\r\nBuf: "), 0x80); - for(uint8_t i = 0; i < read; i++) + for(uint8_t i = 0; i < read; i++) { D_PrintHex (buf[i], 0x80); + Notify(PSTR(" "), 0x80); + } Notify(PSTR("\r\n"), 0x80); #endif From b1ac5161757a2d97579a7a24507b87737c847d39 Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Thu, 22 May 2014 01:33:01 -0400 Subject: [PATCH 03/23] Better/smaller EndpointXtract method, Removes buggy/unused/dead block of code. --- masstorage.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/masstorage.cpp b/masstorage.cpp index 19da7b19..90f76b3c 100644 --- a/masstorage.cpp +++ b/masstorage.cpp @@ -532,6 +532,20 @@ void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t uint8_t index; +#if 1 + if((pep->bmAttributes & 0x02) == 2) { + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); + + } +#else if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) index = epInterruptInIndex; else @@ -548,6 +562,7 @@ void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t bNumEP++; PrintEndpointDescriptor(pep); +#endif } /** From d56ed57495a9c8d01c4cd94653c5ea3d28ba60c6 Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Thu, 22 May 2014 23:36:33 -0400 Subject: [PATCH 04/23] Fix 1 month rollover bug -- Lei Shi found this one in one place, I found the problem all over the library and patched them all. --- BTD.cpp | 2 +- Usb.cpp | 10 +- Wii.cpp | 4 +- examples/hub_demo/hub_demo.ino | 2 +- examples/pl2303/pl2303_gps/pl2303_gps.ino | 109 ++++++------ examples/testusbhostFAT/testusbhostFAT.ino | 182 ++++++++++----------- hidboot.h | 2 +- hiduniversal.cpp | 2 +- masstorage.cpp | 2 +- usbhub.cpp | 2 +- 10 files changed, 155 insertions(+), 162 deletions(-) diff --git a/BTD.cpp b/BTD.cpp index 4de668d9..1812f391 100755 --- a/BTD.cpp +++ b/BTD.cpp @@ -371,7 +371,7 @@ uint8_t BTD::Release() { uint8_t BTD::Poll() { if(!bPollEnable) return 0; - if(qNextPollTime <= millis()) { // Don't poll if shorter than polling interval + if((long)(millis() - qNextPollTime) >= 0L) { // Don't poll if shorter than polling interval qNextPollTime = millis() + pollInterval; // Set new poll time HCI_event_task(); // Poll the HCI event pipe HCI_task(); // HCI state machine diff --git a/Usb.cpp b/Usb.cpp index e21ca1fe..d75149d8 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -327,7 +327,7 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8 regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ rcode = (regRd(rHRSL) & 0x0f); - while(rcode && (timeout > millis())) { + while(rcode && ((long)(millis() - timeout) >= 0L)) { switch(rcode) { case hrNAK: nak_count++; @@ -380,11 +380,11 @@ uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) { uint8_t retry_count = 0; uint16_t nak_count = 0; - while(timeout > millis()) { + while((long)(millis() - timeout) >= 0L) { regWr(rHXFR, (token | ep)); //launch the transfer rcode = USB_ERROR_TRANSFER_TIMEOUT; - while(timeout > millis()) //wait for transfer completion + while((long)(millis() - timeout) >= 0L) //wait for transfer completion { tmpdata = regRd(rHIRQ); @@ -475,7 +475,7 @@ void USB::Task(void) //USB state machine case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here break; case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device - if(delay < millis()) + if((long)(millis() - delay) >= 0L) usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; else break; // don't fall through case USB_ATTACHED_SUBSTATE_RESET_DEVICE: @@ -502,7 +502,7 @@ void USB::Task(void) //USB state machine } break; case USB_ATTACHED_SUBSTATE_WAIT_RESET: - if(delay < millis()) usb_task_state = USB_STATE_CONFIGURING; + if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING; else break; // don't fall through case USB_STATE_CONFIGURING: diff --git a/Wii.cpp b/Wii.cpp index 62af423a..8106666b 100755 --- a/Wii.cpp +++ b/Wii.cpp @@ -657,7 +657,7 @@ void WII::L2CAP_task() { /* The next states are in run() */ case L2CAP_INTERRUPT_DISCONNECT: - if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && millis() > timer) { + if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && ((long)(millis() - timer) >= 0L)) { #ifdef DEBUG_USB_HOST Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); #endif @@ -682,7 +682,7 @@ void WII::L2CAP_task() { } void WII::Run() { - if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && millis() > timer) + if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && ((long)(millis() - timer) >= 0L)) L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough switch(l2cap_state) { diff --git a/examples/hub_demo/hub_demo.ino b/examples/hub_demo/hub_demo.ino index 466ae4d7..bede0f4b 100644 --- a/examples/hub_demo/hub_demo.ino +++ b/examples/hub_demo/hub_demo.ino @@ -97,7 +97,7 @@ void loop() if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) { - if (millis() >= next_time) + if ((next_time - millis()) >= 0L) { Usb.ForEachUsbDevice(&PrintAllDescriptors); Usb.ForEachUsbDevice(&PrintAllAddresses); diff --git a/examples/pl2303/pl2303_gps/pl2303_gps.ino b/examples/pl2303/pl2303_gps/pl2303_gps.ino index 9f33766a..908763c4 100644 --- a/examples/pl2303/pl2303_gps/pl2303_gps.ino +++ b/examples/pl2303/pl2303_gps/pl2303_gps.ino @@ -10,80 +10,75 @@ #include #endif -class PLAsyncOper : public CDCAsyncOper -{ +class PLAsyncOper : public CDCAsyncOper { public: - virtual uint8_t OnInit(ACM *pacm); + virtual uint8_t OnInit(ACM *pacm); }; -uint8_t PLAsyncOper::OnInit(ACM *pacm) -{ - uint8_t rcode; +uint8_t PLAsyncOper::OnInit(ACM *pacm) { + uint8_t rcode; - // Set DTR = 1 - rcode = pacm->SetControlLineState(1); + // Set DTR = 1 + rcode = pacm->SetControlLineState(1); + + if(rcode) { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + lc.dwDTERate = 4800; //default serial speed of GPS unit + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if(rcode) + ErrorMessage(PSTR("SetLineCoding"), rcode); - if (rcode) - { - ErrorMessage(PSTR("SetControlLineState"), rcode); return rcode; - } - - LINE_CODING lc; - lc.dwDTERate = 4800; //default serial speed of GPS unit - lc.bCharFormat = 0; - lc.bParityType = 0; - lc.bDataBits = 8; - - rcode = pacm->SetLineCoding(&lc); - - if (rcode) - ErrorMessage(PSTR("SetLineCoding"), rcode); - - return rcode; } -USB Usb; -USBHub Hub(&Usb); -PLAsyncOper AsyncOper; -PL2303 Pl(&Usb, &AsyncOper); +USB Usb; +USBHub Hub(&Usb); +PLAsyncOper AsyncOper; +PL2303 Pl(&Usb, &AsyncOper); uint32_t read_delay; #define READ_DELAY 100 -void setup() -{ - Serial.begin( 115200 ); - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection - Serial.println("Start"); +void setup() { + Serial.begin(115200); + while(!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection + Serial.println("Start"); - if (Usb.Init() == -1) - Serial.println("OSCOKIRQ failed to assert"); + if(Usb.Init() == -1) + Serial.println("OSCOKIRQ failed to assert"); - delay( 200 ); + delay(200); } -void loop() -{ -uint8_t rcode; -uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint -uint16_t rcvd = 64; +void loop() { + uint8_t rcode; + uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint + uint16_t rcvd = 64; - Usb.Task(); + Usb.Task(); - if( Pl.isReady()) { - /* reading the GPS */ - if( read_delay < millis() ){ - read_delay += READ_DELAY; - rcode = Pl.RcvData(&rcvd, buf); - if ( rcode && rcode != hrNAK ) - ErrorMessage(PSTR("Ret"), rcode); - if( rcvd ) { //more than zero bytes received - for( uint16_t i=0; i < rcvd; i++ ) { - Serial.print((char)buf[i]); //printing on the screen - }//for( uint16_t i=0; i < rcvd; i++... - }//if( rcvd - }//if( read_delay > millis()... - }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. + if(Pl.isReady()) { + /* reading the GPS */ + if((long)(millis() - read_delay) >= 0L) { + read_delay += READ_DELAY; + rcode = Pl.RcvData(&rcvd, buf); + if(rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + if(rcvd) { //more than zero bytes received + for(uint16_t i = 0; i < rcvd; i++) { + Serial.print((char)buf[i]); //printing on the screen + }//for( uint16_t i=0; i < rcvd; i++... + }//if( rcvd + }//if( read_delay > millis()... + }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. } diff --git a/examples/testusbhostFAT/testusbhostFAT.ino b/examples/testusbhostFAT/testusbhostFAT.ino index f316a49b..c7110632 100644 --- a/examples/testusbhostFAT/testusbhostFAT.ino +++ b/examples/testusbhostFAT/testusbhostFAT.ino @@ -126,7 +126,7 @@ static int tty_std_putc(char c, FILE *t) { } static int tty_std_getc(FILE *t) { - while (!Serial.available()); + while(!Serial.available()); return Serial.read(); } @@ -140,18 +140,18 @@ extern "C" { int _write(int fd, const char *ptr, int len) { int j; - for (j = 0; j < len; j++) { - if (fd == 1) + for(j = 0; j < len; j++) { + if(fd == 1) Serial.write(*ptr++); - else if (fd == 2) + else if(fd == 2) USB_HOST_SERIAL.write(*ptr++); } return len; } int _read(int fd, char *ptr, int len) { - if (len > 0 && fd == 0) { - while (!Serial.available()); + if(len > 0 && fd == 0) { + while(!Serial.available()); *ptr = Serial.read(); return 1; } @@ -175,7 +175,7 @@ extern "C" { void setup() { boolean serr = false; - for (int i = 0; i < _VOLUMES; i++) { + for(int i = 0; i < _VOLUMES; i++) { Fats[i] = NULL; sto[i].private_data = new pvt_t; ((pvt_t *)sto[i].private_data)->B = 255; // impossible @@ -193,7 +193,7 @@ void setup() { // Initialize 'debug' serial port USB_HOST_SERIAL.begin(115200); // Do not start primary Serial port if already started. - if (bit_is_clear(UCSR0B, TXEN0)) { + if(bit_is_clear(UCSR0B, TXEN0)) { Serial.begin(115200); serr = true; } @@ -220,7 +220,7 @@ void setup() { analogWrite(LED_BUILTIN, 0); delay(500); #else - while (!Serial); + while(!Serial); #endif printf_P(PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n")); @@ -236,7 +236,7 @@ void setup() { "Disabled" #endif "\r\n")); - if (serr) { + if(serr) { fprintf_P(stderr, PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n")); fprintf_P(stderr, PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl); fprintf_P(stderr, PSTR("Long filename support: " @@ -274,7 +274,7 @@ void setup() { // I want to be able to have slightly more control. // Besides, it is easier to initialize stuff... #if WANT_HUB_TEST - for (int i = 0; i < MAX_HUBS; i++) { + for(int i = 0; i < MAX_HUBS; i++) { Hubs[i] = new USBHub(&Usb); #if defined(AVR) printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); @@ -284,7 +284,7 @@ void setup() { // Initialize generic storage. This must be done before USB starts. InitStorage(); - while (Usb.Init(1000) == -1) { + while(Usb.Init(1000) == -1) { printf_P(PSTR("No USB HOST Shield?\r\n")); Notify(PSTR("OSC did not start."), 0x40); } @@ -316,7 +316,7 @@ void setup() { //printf("SPI_CTAR0 = %8.8X\r\n", ctar); uint32_t mcr = SPI0_MCR; - if (mcr & SPI_MCR_MDIS) { + if(mcr & SPI_MCR_MDIS) { SPI0_CTAR0 = ctar; } else { SPI0_MCR = mcr | SPI_MCR_MDIS | SPI_MCR_HALT; @@ -334,23 +334,23 @@ void serialEvent() { // . to increase by 16, , to decrease by 16 // e to flick VBUS // * to report debug level - if (Serial.available()) { + if(Serial.available()) { int inByte = Serial.read(); - switch (inByte) { + switch(inByte) { case '+': - if (UsbDEBUGlvl < 0xff) UsbDEBUGlvl++; + if(UsbDEBUGlvl < 0xff) UsbDEBUGlvl++; reportlvl = true; break; case '-': - if (UsbDEBUGlvl > 0x00) UsbDEBUGlvl--; + if(UsbDEBUGlvl > 0x00) UsbDEBUGlvl--; reportlvl = true; break; case '.': - if (UsbDEBUGlvl < 0xf0) UsbDEBUGlvl += 16; + if(UsbDEBUGlvl < 0xf0) UsbDEBUGlvl += 16; reportlvl = true; break; case ',': - if (UsbDEBUGlvl > 0x0f) UsbDEBUGlvl -= 16; + if(UsbDEBUGlvl > 0x0f) UsbDEBUGlvl -= 16; reportlvl = true; break; case '*': @@ -370,7 +370,7 @@ void serialEvent() { #if defined(AVR) ISR(TIMER3_COMPA_vect) { - if (millis() >= LEDnext_time) { + if(millis() >= LEDnext_time) { LEDnext_time = millis() + 30; // set the brightness of LED @@ -380,11 +380,11 @@ ISR(TIMER3_COMPA_vect) { brightness = brightness + fadeAmount; // reverse the direction of the fading at the ends of the fade: - if (brightness <= 0) { + if(brightness <= 0) { brightness = 0; fadeAmount = -fadeAmount; } - if (brightness >= 255) { + if(brightness >= 255) { brightness = 255; fadeAmount = -fadeAmount; } @@ -406,8 +406,8 @@ void loop() { #if defined(AVR) // Print a heap status report about every 10 seconds. - if (millis() >= HEAPnext_time) { - if (UsbDEBUGlvl > 0x50) { + if(millis() >= HEAPnext_time) { + if(UsbDEBUGlvl > 0x50) { printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); } HEAPnext_time = millis() + 10000; @@ -419,14 +419,14 @@ void loop() { #endif // Horrid! This sort of thing really belongs in an ISR, not here! // We also will be needing to test each hub port, we don't do this yet! - if (!change && !usbon && millis() >= usbon_time) { + if(!change && !usbon && millis() >= usbon_time) { change = true; usbon = true; } - if (change) { + if(change) { change = false; - if (usbon) { + if(usbon) { Usb.vbusPower(vbus_on); printf_P(PSTR("VBUS on\r\n")); } else { @@ -436,21 +436,21 @@ void loop() { } Usb.Task(); current_state = Usb.getUsbTaskState(); - if (current_state != last_state) { - if (UsbDEBUGlvl > 0x50) + if(current_state != last_state) { + if(UsbDEBUGlvl > 0x50) printf_P(PSTR("USB state = %x\r\n"), current_state); #if defined(AVR) - if (current_state == USB_STATE_RUNNING) { + if(current_state == USB_STATE_RUNNING) { fadeAmount = 30; } #endif - if (current_state == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) { + if(current_state == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) { #if defined(AVR) fadeAmount = 80; #endif partsready = false; - for (int i = 0; i < cpart; i++) { - if (Fats[i] != NULL) + for(int i = 0; i < cpart; i++) { + if(Fats[i] != NULL) delete Fats[i]; Fats[i] = NULL; } @@ -462,28 +462,27 @@ void loop() { } // only do any of this if usb is on - if (usbon) { - if (partsready && !fatready) { - if (cpart > 0) fatready = true; + if(usbon) { + if(partsready && !fatready) { + if(cpart > 0) fatready = true; } // This is horrible, and needs to be moved elsewhere! - for (int B = 0; B < MAX_USB_MS_DRIVERS; B++) { - if (!partsready && (Bulk[B]->GetAddress() != NULL)) { + for(int B = 0; B < MAX_USB_MS_DRIVERS; B++) { + if(!partsready && (Bulk[B]->GetAddress() != NULL)) { // Build a list. int ML = Bulk[B]->GetbMaxLUN(); //printf("MAXLUN = %i\r\n", ML); ML++; - for (int i = 0; i < ML; i++) { - if (Bulk[B]->LUNIsGood(i)) { + for(int i = 0; i < ML; i++) { + if(Bulk[B]->LUNIsGood(i)) { partsready = true; ((pvt_t *)(sto[i].private_data))->lun = i; ((pvt_t *)(sto[i].private_data))->B = B; - sto[i].Read = *PRead; - sto[i].Write = *PWrite; sto[i].Reads = *PReads; sto[i].Writes = *PWrites; sto[i].Status = *PStatus; + sto[i].Commit = *UHS_USB_BulkOnly_Commit; sto[i].TotalSectors = Bulk[B]->GetCapacity(i); sto[i].SectorSize = Bulk[B]->GetSectorSize(i); printf_P(PSTR("LUN:\t\t%u\r\n"), i); @@ -492,18 +491,18 @@ void loop() { // get the partition data... PT = new PCPartition; - if (!PT->Init(&sto[i])) { + if(!PT->Init(&sto[i])) { part_t *apart; - for (int j = 0; j < 4; j++) { + for(int j = 0; j < 4; j++) { apart = PT->GetPart(j); - if (apart != NULL && apart->type != 0x00) { + if(apart != NULL && apart->type != 0x00) { memcpy(&(parts[cpart]), apart, sizeof (part_t)); printf_P(PSTR("Partition %u type %#02x\r\n"), j, parts[cpart].type); // for now - if (isfat(parts[cpart].type)) { + if(isfat(parts[cpart].type)) { Fats[cpart] = new PFAT(&sto[i], cpart, parts[cpart].firstSector); //int r = Fats[cpart]->Good(); - if (Fats[cpart]->MountStatus()) { + if(Fats[cpart]->MountStatus()) { delete Fats[cpart]; Fats[cpart] = NULL; } else cpart++; @@ -514,7 +513,7 @@ void loop() { // try superblock Fats[cpart] = new PFAT(&sto[i], cpart, 0); //int r = Fats[cpart]->Good(); - if (Fats[cpart]->MountStatus()) { + if(Fats[cpart]->MountStatus()) { //printf_P(PSTR("Superblock error %x\r\n"), r); delete Fats[cpart]; Fats[cpart] = NULL; @@ -535,18 +534,18 @@ void loop() { } } - if (fatready) { - if (Fats[0] != NULL) { + if(fatready) { + if(Fats[0] != NULL) { struct Pvt * p; p = ((struct Pvt *)(Fats[0]->storage->private_data)); - if (!Bulk[p->B]->LUNIsGood(p->lun)) { + if(!Bulk[p->B]->LUNIsGood(p->lun)) { // media change #if defined(AVR) fadeAmount = 80; #endif partsready = false; - for (int i = 0; i < cpart; i++) { - if (Fats[i] != NULL) + for(int i = 0; i < cpart; i++) { + if(Fats[i] != NULL) delete Fats[i]; Fats[cpart] = NULL; } @@ -557,62 +556,61 @@ void loop() { } } - if (fatready) { + if(fatready) { FRESULT rc; /* Result code */ UINT bw, br, i; - if (!notified) { + if(!notified) { #if defined(AVR) fadeAmount = 5; #endif notified = true; printf_P(PSTR("\r\nOpen an existing file (message.txt).\r\n")); rc = f_open(&My_File_Object_x, "0:/MESSAGE.TXT", FA_READ); - if (rc) printf_P(PSTR("Error %i, message.txt not found.\r\n"), rc); + if(rc) printf_P(PSTR("Error %i, message.txt not found.\r\n"), rc); else { printf_P(PSTR("\r\nType the file content.\r\n")); - for (;;) { + for(;;) { rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &br); /* Read a chunk of file */ - if (rc || !br) break; /* Error or end of file */ - for (i = 0; i < br; i++) { + if(rc || !br) break; /* Error or end of file */ + for(i = 0; i < br; i++) { /* Type the data */ - if (My_Buff_x[i] == '\n') + if(My_Buff_x[i] == '\n') Serial.write('\r'); - if (My_Buff_x[i] != '\r') + if(My_Buff_x[i] != '\r') Serial.write(My_Buff_x[i]); Serial.flush(); } } - if (rc) { + if(rc) { f_close(&My_File_Object_x); goto out; } printf_P(PSTR("\r\nClose the file.\r\n")); rc = f_close(&My_File_Object_x); - if (rc) goto out; + if(rc) goto out; } printf_P(PSTR("\r\nCreate a new file (hello.txt).\r\n")); rc = f_open(&My_File_Object_x, "0:/Hello.TxT", FA_WRITE | FA_CREATE_ALWAYS); - if (rc) { + if(rc) { die(rc); goto outdir; } printf_P(PSTR("\r\nWrite a text data. (Hello world!)\r\n")); rc = f_write(&My_File_Object_x, "Hello world!\r\n", 14, &bw); - if (rc) { + if(rc) { goto out; } printf_P(PSTR("%u bytes written.\r\n"), bw); printf_P(PSTR("\r\nClose the file.\r\n")); rc = f_close(&My_File_Object_x); - if (rc) { + if(rc) { die(rc); goto out; } -outdir: - { +outdir:{ #if _USE_LFN char lfn[_MAX_LFN + 1]; FILINFO My_File_Info_Object_x; /* File information object */ @@ -621,7 +619,7 @@ outdir: DIR My_Dir_Object_x; /* Directory object */ printf_P(PSTR("\r\nOpen root directory.\r\n")); rc = f_opendir(&My_Dir_Object_x, "0:/"); - if (rc) { + if(rc) { die(rc); goto out; } @@ -630,46 +628,46 @@ outdir: #if defined(AVR) printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); #endif - for (;;) { + for(;;) { #if _USE_LFN My_File_Info_Object_x.lfsize = _MAX_LFN; #endif rc = f_readdir(&My_Dir_Object_x, &My_File_Info_Object_x); /* Read a directory item */ - if (rc || !My_File_Info_Object_x.fname[0]) break; /* Error or end of dir */ + if(rc || !My_File_Info_Object_x.fname[0]) break; /* Error or end of dir */ - if (My_File_Info_Object_x.fattrib & AM_DIR) { + if(My_File_Info_Object_x.fattrib & AM_DIR) { Serial.write('d'); } else { Serial.write('-'); } Serial.write('r'); - if (My_File_Info_Object_x.fattrib & AM_RDO) { + if(My_File_Info_Object_x.fattrib & AM_RDO) { Serial.write('-'); } else { Serial.write('w'); } - if (My_File_Info_Object_x.fattrib & AM_HID) { + if(My_File_Info_Object_x.fattrib & AM_HID) { Serial.write('h'); } else { Serial.write('-'); } - if (My_File_Info_Object_x.fattrib & AM_SYS) { + if(My_File_Info_Object_x.fattrib & AM_SYS) { Serial.write('s'); } else { Serial.write('-'); } - if (My_File_Info_Object_x.fattrib & AM_ARC) { + if(My_File_Info_Object_x.fattrib & AM_ARC) { Serial.write('a'); } else { Serial.write('-'); } #if _USE_LFN - if (*My_File_Info_Object_x.lfname) + if(*My_File_Info_Object_x.lfname) printf_P(PSTR(" %8lu %s (%s)\r\n"), My_File_Info_Object_x.fsize, My_File_Info_Object_x.fname, My_File_Info_Object_x.lfname); else #endif @@ -677,48 +675,48 @@ outdir: } } out: - if (rc) die(rc); + if(rc) die(rc); printf_P(PSTR("\r\nTest completed.\r\n")); } - if (runtest) { + if(runtest) { ULONG ii, wt, rt, start, end; runtest = false; f_unlink("0:/10MB.bin"); printf_P(PSTR("\r\nCreate a new 10MB test file (10MB.bin).\r\n")); rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_WRITE | FA_CREATE_ALWAYS); - if (rc) goto failed; - for (bw = 0; bw < mbxs; bw++) My_Buff_x[bw] = bw & 0xff; + if(rc) goto failed; + for(bw = 0; bw < mbxs; bw++) My_Buff_x[bw] = bw & 0xff; fflush(stdout); start = millis(); - while (start == millis()); - for (ii = 10485760LU / mbxs; ii > 0LU; ii--) { + while(start == millis()); + for(ii = 10485760LU / mbxs; ii > 0LU; ii--) { rc = f_write(&My_File_Object_x, My_Buff_x, mbxs, &bw); - if (rc || !bw) goto failed; + if(rc || !bw) goto failed; } rc = f_close(&My_File_Object_x); - if (rc) goto failed; + if(rc) goto failed; end = millis(); wt = (end - start) - 1; printf_P(PSTR("Time to write 10485760 bytes: %lu ms (%lu sec) \r\n"), wt, (500 + wt) / 1000UL); rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_READ); fflush(stdout); start = millis(); - while (start == millis()); - if (rc) goto failed; - for (;;) { + while(start == millis()); + if(rc) goto failed; + for(;;) { rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &bw); /* Read a chunk of file */ - if (rc || !bw) break; /* Error or end of file */ + if(rc || !bw) break; /* Error or end of file */ } end = millis(); - if (rc) goto failed; + if(rc) goto failed; rc = f_close(&My_File_Object_x); - if (rc) goto failed; + if(rc) goto failed; rt = (end - start) - 1; printf_P(PSTR("Time to read 10485760 bytes: %lu ms (%lu sec)\r\nDelete test file\r\n"), rt, (500 + rt) / 1000UL); failed: - if (rc) die(rc); + if(rc) die(rc); printf_P(PSTR("10MB timing test finished.\r\n")); } } diff --git a/hidboot.h b/hidboot.h index 2218eb9e..0326bf25 100644 --- a/hidboot.h +++ b/hidboot.h @@ -536,7 +536,7 @@ template uint8_t HIDBoot::Poll() { uint8_t rcode = 0; - if(bPollEnable && qNextPollTime <= millis()) { + if(bPollEnable && ((long)(millis() - qNextPollTime) >= 0L)) { // To-do: optimize manually, using the for loop only if needed. for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { diff --git a/hiduniversal.cpp b/hiduniversal.cpp index c2f33533..acc1b00c 100644 --- a/hiduniversal.cpp +++ b/hiduniversal.cpp @@ -370,7 +370,7 @@ uint8_t HIDUniversal::Poll() { if(!bPollEnable) return 0; - if(qNextPollTime <= millis()) { + if((long)(millis() - qNextPollTime) >= 0L) { qNextPollTime = millis() + pollInterval; uint8_t buf[constBuffLen]; diff --git a/masstorage.cpp b/masstorage.cpp index 3c014f89..ab9ad4ff 100644 --- a/masstorage.cpp +++ b/masstorage.cpp @@ -671,7 +671,7 @@ uint8_t BulkOnly::Poll() { if(!bPollEnable) return 0; - if(qNextPollTime <= millis()) { + if((long)(millis() - qNextPollTime) >= 0L) { CheckMedia(); } //rcode = 0; diff --git a/usbhub.cpp b/usbhub.cpp index 82fc30f5..a3ab21eb 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -230,7 +230,7 @@ uint8_t USBHub::Poll() { if(!bPollEnable) return 0; - if(qNextPollTime <= millis()) { + if(((long)(millis() - qNextPollTime) >= 0L)) { rcode = CheckHubStatus(); qNextPollTime = millis() + 100; } From a50baa8aecdc62fe23f212e92a2f29e75fe6cf74 Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Fri, 23 May 2014 00:12:55 -0400 Subject: [PATCH 05/23] Merge in masters --- examples/testusbhostFAT/Arduino_Makefile_master | 2 +- examples/testusbhostFAT/RTClib | 2 +- examples/testusbhostFAT/generic_storage | 2 +- examples/testusbhostFAT/xmem2 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/testusbhostFAT/Arduino_Makefile_master b/examples/testusbhostFAT/Arduino_Makefile_master index 1cacea4e..d35bb955 160000 --- a/examples/testusbhostFAT/Arduino_Makefile_master +++ b/examples/testusbhostFAT/Arduino_Makefile_master @@ -1 +1 @@ -Subproject commit 1cacea4e8933b37b9f98528b2a831031f69905de +Subproject commit d35bb955e3818f0c14e47c8a1998003da8dc1b5a diff --git a/examples/testusbhostFAT/RTClib b/examples/testusbhostFAT/RTClib index 9108effe..7fd6a306 160000 --- a/examples/testusbhostFAT/RTClib +++ b/examples/testusbhostFAT/RTClib @@ -1 +1 @@ -Subproject commit 9108effe4d4e556198e3e7b95365d1c898680dae +Subproject commit 7fd6a306ca53d08bf53b2bbfc1b80eb056f2c55b diff --git a/examples/testusbhostFAT/generic_storage b/examples/testusbhostFAT/generic_storage index ab85718a..0b8e3076 160000 --- a/examples/testusbhostFAT/generic_storage +++ b/examples/testusbhostFAT/generic_storage @@ -1 +1 @@ -Subproject commit ab85718a917094391762b79140d8e3a03af136a4 +Subproject commit 0b8e3076b5a072251e01cfc6e6333b364d4e71e7 diff --git a/examples/testusbhostFAT/xmem2 b/examples/testusbhostFAT/xmem2 index dd85091a..2bf8f633 160000 --- a/examples/testusbhostFAT/xmem2 +++ b/examples/testusbhostFAT/xmem2 @@ -1 +1 @@ -Subproject commit dd85091abaca7cc6055ff515a5e42f32198380d2 +Subproject commit 2bf8f633e7f9bc5a7bf4c00f3f45c7b79484198e From f6244bbe59c46a176251125f07bca1b92daf4d6a Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Sat, 24 May 2014 00:31:26 -0400 Subject: [PATCH 06/23] bugfix --- Usb.cpp | 6 +++--- examples/hub_demo/hub_demo.ino | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Usb.cpp b/Usb.cpp index d75149d8..ca81cf99 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -327,7 +327,7 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8 regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ rcode = (regRd(rHRSL) & 0x0f); - while(rcode && ((long)(millis() - timeout) >= 0L)) { + while(rcode && ((long)(millis() - timeout) < 0L)) { switch(rcode) { case hrNAK: nak_count++; @@ -380,11 +380,11 @@ uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) { uint8_t retry_count = 0; uint16_t nak_count = 0; - while((long)(millis() - timeout) >= 0L) { + while((long)(millis() - timeout) < 0L) { regWr(rHXFR, (token | ep)); //launch the transfer rcode = USB_ERROR_TRANSFER_TIMEOUT; - while((long)(millis() - timeout) >= 0L) //wait for transfer completion + while((long)(millis() - timeout) < 0L) //wait for transfer completion { tmpdata = regRd(rHIRQ); diff --git a/examples/hub_demo/hub_demo.ino b/examples/hub_demo/hub_demo.ino index bede0f4b..329c6230 100644 --- a/examples/hub_demo/hub_demo.ino +++ b/examples/hub_demo/hub_demo.ino @@ -97,7 +97,7 @@ void loop() if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) { - if ((next_time - millis()) >= 0L) + if ((millis() - next_time) >= 0L) { Usb.ForEachUsbDevice(&PrintAllDescriptors); Usb.ForEachUsbDevice(&PrintAllAddresses); From d9dac13225e806db5e445733c94c3e6c965d701c Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Tue, 27 May 2014 09:42:13 +0200 Subject: [PATCH 07/23] Updated testusbhostFAT example and submodules --- .../testusbhostFAT/Arduino_Makefile_master | 2 +- examples/testusbhostFAT/Makefile | 4 + examples/testusbhostFAT/RTClib | 2 +- examples/testusbhostFAT/generic_storage | 2 +- examples/testusbhostFAT/testusbhostFAT.ino | 340 +++++++++--------- examples/testusbhostFAT/xmem2 | 2 +- 6 files changed, 175 insertions(+), 177 deletions(-) mode change 100644 => 100755 examples/testusbhostFAT/testusbhostFAT.ino diff --git a/examples/testusbhostFAT/Arduino_Makefile_master b/examples/testusbhostFAT/Arduino_Makefile_master index 1cacea4e..d35bb955 160000 --- a/examples/testusbhostFAT/Arduino_Makefile_master +++ b/examples/testusbhostFAT/Arduino_Makefile_master @@ -1 +1 @@ -Subproject commit 1cacea4e8933b37b9f98528b2a831031f69905de +Subproject commit d35bb955e3818f0c14e47c8a1998003da8dc1b5a diff --git a/examples/testusbhostFAT/Makefile b/examples/testusbhostFAT/Makefile index 7e5ebaec..232d338e 100644 --- a/examples/testusbhostFAT/Makefile +++ b/examples/testusbhostFAT/Makefile @@ -9,6 +9,10 @@ BOARD = mega PROGRAMMER = arduino +#BOARD = teensypp2 +#BOARD = teensy3 +#BOARD = teensy31 + # set your Arduino tty port here PORT = /dev/ttyUSB0 diff --git a/examples/testusbhostFAT/RTClib b/examples/testusbhostFAT/RTClib index 9108effe..7fd6a306 160000 --- a/examples/testusbhostFAT/RTClib +++ b/examples/testusbhostFAT/RTClib @@ -1 +1 @@ -Subproject commit 9108effe4d4e556198e3e7b95365d1c898680dae +Subproject commit 7fd6a306ca53d08bf53b2bbfc1b80eb056f2c55b diff --git a/examples/testusbhostFAT/generic_storage b/examples/testusbhostFAT/generic_storage index ab85718a..0b8e3076 160000 --- a/examples/testusbhostFAT/generic_storage +++ b/examples/testusbhostFAT/generic_storage @@ -1 +1 @@ -Subproject commit ab85718a917094391762b79140d8e3a03af136a4 +Subproject commit 0b8e3076b5a072251e01cfc6e6333b364d4e71e7 diff --git a/examples/testusbhostFAT/testusbhostFAT.ino b/examples/testusbhostFAT/testusbhostFAT.ino old mode 100644 new mode 100755 index f316a49b..70107963 --- a/examples/testusbhostFAT/testusbhostFAT.ino +++ b/examples/testusbhostFAT/testusbhostFAT.ino @@ -19,35 +19,39 @@ * */ +///////////////////////////////////////////////////////////// +// Please Note: // +// This section is for info with the Arduino IDE ONLY. // +// Unfortunately due to short sightedness of the Arduino // +// code team, that you must set the following in the // +// respective libraries. // +// Changing them here will have _NO_ effect! // +///////////////////////////////////////////////////////////// + +// Uncomment to enable debugging +//#define DEBUG_USB_HOST +// This is where stderr/USB debugging goes to +//#define USB_HOST_SERIAL Serial3 + +// If you have external memory, setting this to 0 enables FAT table caches. +// The 0 setting is recommended only if you have external memory. +//#define _FS_TINY 1 + +//#define _USE_LFN 3 +//#define EXT_RAM_STACK 1 +//#define EXT_RAM_HEAP 1 +//#define _MAX_SS 512 +///////////////////////////////////////////////////////////// +// End of Arduino IDE specific information // +///////////////////////////////////////////////////////////// + // You can set this to 0 if you are not using a USB hub. // It will save a little bit of flash and RAM. // Set to 1 if you want to use a hub. #define WANT_HUB_TEST 0 -///////////////////////////////////////////////////////////// -// Please Note: This section is for Arduino IDE ONLY. // -// Use of Make creates a flash image that is 3.3KB smaller // -///////////////////////////////////////////////////////////// -#ifndef USING_MAKEFILE -// Uncomment to enable debugging -//#define DEBUG_USB_HOST -// This is where stderr/USB debugging goes to -#define USB_HOST_SERIAL Serial3 -// If you have external memory, setting this to 0 enables FAT table caches. -// The 0 setting is recommended only if you have external memory. -#define _FS_TINY 1 - -// These you can safely leave alone. -#define _USE_LFN 3 -#define EXT_RAM_STACK 1 -#define EXT_RAM_HEAP 1 -#define _MAX_SS 512 -#endif -///////////////////////////////////////////////////////////// -// End of Arduino IDE specific hacks // -///////////////////////////////////////////////////////////// -#if defined(AVR) +#if defined(__AVR__) #include #else #include @@ -63,7 +67,7 @@ #include #include #include -#if defined(AVR) +#if defined(__AVR__) static FILE tty_stdio; static FILE tty_stderr; volatile uint32_t LEDnext_time; // fade timeout @@ -100,7 +104,7 @@ static storage_t sto[_VOLUMES]; #define mbxs 128 static uint8_t My_Buff_x[mbxs]; /* File read buffer */ -#if defined(AVR) +#if defined(__AVR__) #define prescale1 ((1 << WGM12) | (1 << CS10)) #define prescale8 ((1 << WGM12) | (1 << CS11)) @@ -126,7 +130,7 @@ static int tty_std_putc(char c, FILE *t) { } static int tty_std_getc(FILE *t) { - while (!Serial.available()); + while(!Serial.available()); return Serial.read(); } @@ -140,18 +144,18 @@ extern "C" { int _write(int fd, const char *ptr, int len) { int j; - for (j = 0; j < len; j++) { - if (fd == 1) + for(j = 0; j < len; j++) { + if(fd == 1) Serial.write(*ptr++); - else if (fd == 2) + else if(fd == 2) USB_HOST_SERIAL.write(*ptr++); } return len; } int _read(int fd, char *ptr, int len) { - if (len > 0 && fd == 0) { - while (!Serial.available()); + if(len > 0 && fd == 0) { + while(!Serial.available()); *ptr = Serial.read(); return 1; } @@ -175,7 +179,7 @@ extern "C" { void setup() { boolean serr = false; - for (int i = 0; i < _VOLUMES; i++) { + for(int i = 0; i < _VOLUMES; i++) { Fats[i] = NULL; sto[i].private_data = new pvt_t; ((pvt_t *)sto[i].private_data)->B = 255; // impossible @@ -184,7 +188,7 @@ void setup() { // minimum 0x00, maximum 0xff UsbDEBUGlvl = 0x51; -#if defined(AVR) +#if !defined(CORE_TEENSY) && defined(__AVR__) // make LED pin as an output: pinMode(LED_BUILTIN, OUTPUT); pinMode(2, OUTPUT); @@ -193,11 +197,23 @@ void setup() { // Initialize 'debug' serial port USB_HOST_SERIAL.begin(115200); // Do not start primary Serial port if already started. - if (bit_is_clear(UCSR0B, TXEN0)) { + if(bit_is_clear(UCSR0B, TXEN0)) { Serial.begin(115200); serr = true; } + + // Blink LED + delay(500); + analogWrite(LED_BUILTIN, 255); + delay(500); + analogWrite(LED_BUILTIN, 0); + delay(500); +#else + while(!Serial); + Serial.begin(115200); // On the Teensy 3.x we get a delay at least! +#endif +#if defined(__AVR__) // Set up stdio/stderr tty_stdio.put = tty_std_putc; tty_stdio.get = tty_std_getc; @@ -212,17 +228,7 @@ void setup() { stdout = &tty_stdio; stdin = &tty_stdio; stderr = &tty_stderr; - - // Blink LED - delay(500); - analogWrite(LED_BUILTIN, 255); - delay(500); - analogWrite(LED_BUILTIN, 0); - delay(500); -#else - while (!Serial); #endif - printf_P(PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n")); printf_P(PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl); printf_P(PSTR("'+' and '-' increase/decrease by 0x01\r\n")); @@ -236,7 +242,7 @@ void setup() { "Disabled" #endif "\r\n")); - if (serr) { + if(serr) { fprintf_P(stderr, PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n")); fprintf_P(stderr, PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl); fprintf_P(stderr, PSTR("Long filename support: " @@ -247,8 +253,8 @@ void setup() { #endif "\r\n")); } -#if defined(AVR) +#if !defined(CORE_TEENSY) && defined(__AVR__) analogWrite(LED_BUILTIN, 255); delay(500); analogWrite(LED_BUILTIN, 0); @@ -263,7 +269,7 @@ void setup() { delay(500); LEDnext_time = millis() + 1; -#ifdef EXT_RAM +#if EXT_RAM printf_P(PSTR("Total EXT RAM banks %i\r\n"), xmem::getTotalBanks()); #endif printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); @@ -274,22 +280,22 @@ void setup() { // I want to be able to have slightly more control. // Besides, it is easier to initialize stuff... #if WANT_HUB_TEST - for (int i = 0; i < MAX_HUBS; i++) { + for(int i = 0; i < MAX_HUBS; i++) { Hubs[i] = new USBHub(&Usb); -#if defined(AVR) +#if defined(__AVR__) printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); #endif } #endif // Initialize generic storage. This must be done before USB starts. - InitStorage(); + Init_Generic_Storage(); - while (Usb.Init(1000) == -1) { + while(Usb.Init(1000) == -1) { printf_P(PSTR("No USB HOST Shield?\r\n")); Notify(PSTR("OSC did not start."), 0x40); } -#if defined(AVR) +#if !defined(CORE_TEENSY) && defined(__AVR__) cli(); TCCR3A = 0; TCCR3B = 0; @@ -300,32 +306,10 @@ void setup() { sei(); HEAPnext_time = millis() + 10000; -#else -#if 0 - // - // On the teensy 3 we can raise the speed of SPI here. - // - // Default seen is 0xB8011001. - // - - uint32_t ctar = SPI0_CTAR0; - //printf("SPI_CTAR0 = %8.8X\r\n", ctar); - ctar &= 0x7FFCFFF0; // 1/4 fSYS, 12.5Mhz - //printf("SPI_CTAR0 = %8.8X\r\n", ctar); - ctar |= 0x80000000; // 1/2 fSYS 25Mhz - //printf("SPI_CTAR0 = %8.8X\r\n", ctar); - - uint32_t mcr = SPI0_MCR; - if (mcr & SPI_MCR_MDIS) { - SPI0_CTAR0 = ctar; - } else { - SPI0_MCR = mcr | SPI_MCR_MDIS | SPI_MCR_HALT; - SPI0_CTAR0 = ctar; - SPI0_MCR = mcr; - } #endif +#if defined(__AVR__) + HEAPnext_time = millis() + 10000; #endif - } void serialEvent() { @@ -334,23 +318,23 @@ void serialEvent() { // . to increase by 16, , to decrease by 16 // e to flick VBUS // * to report debug level - if (Serial.available()) { + if(Serial.available()) { int inByte = Serial.read(); - switch (inByte) { + switch(inByte) { case '+': - if (UsbDEBUGlvl < 0xff) UsbDEBUGlvl++; + if(UsbDEBUGlvl < 0xff) UsbDEBUGlvl++; reportlvl = true; break; case '-': - if (UsbDEBUGlvl > 0x00) UsbDEBUGlvl--; + if(UsbDEBUGlvl > 0x00) UsbDEBUGlvl--; reportlvl = true; break; case '.': - if (UsbDEBUGlvl < 0xf0) UsbDEBUGlvl += 16; + if(UsbDEBUGlvl < 0xf0) UsbDEBUGlvl += 16; reportlvl = true; break; case ',': - if (UsbDEBUGlvl > 0x0f) UsbDEBUGlvl -= 16; + if(UsbDEBUGlvl > 0x0f) UsbDEBUGlvl -= 16; reportlvl = true; break; case '*': @@ -367,10 +351,11 @@ void serialEvent() { } } -#if defined(AVR) +#if !defined(CORE_TEENSY) && defined(__AVR__) +// ALL teensy versions LACK PWM ON LED ISR(TIMER3_COMPA_vect) { - if (millis() >= LEDnext_time) { + if((long)(millis() - LEDnext_time) >= 0L) { LEDnext_time = millis() + 30; // set the brightness of LED @@ -380,11 +365,11 @@ ISR(TIMER3_COMPA_vect) { brightness = brightness + fadeAmount; // reverse the direction of the fading at the ends of the fade: - if (brightness <= 0) { + if(brightness <= 0) { brightness = 0; fadeAmount = -fadeAmount; } - if (brightness >= 255) { + if(brightness >= 255) { brightness = 255; fadeAmount = -fadeAmount; } @@ -404,29 +389,30 @@ void die(FRESULT rc) { void loop() { FIL My_File_Object_x; /* File object */ -#if defined(AVR) +#if defined(__AVR__) // Print a heap status report about every 10 seconds. - if (millis() >= HEAPnext_time) { - if (UsbDEBUGlvl > 0x50) { + if((long)(millis() - HEAPnext_time) >= 0L) { + if(UsbDEBUGlvl > 0x50) { printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); } HEAPnext_time = millis() + 10000; } TCCR3B = 0; -#else - // Arm suffers here, oh well... +#endif +#if defined(CORE_TEENSY) + // Teensy suffers here, oh well... serialEvent(); #endif // Horrid! This sort of thing really belongs in an ISR, not here! // We also will be needing to test each hub port, we don't do this yet! - if (!change && !usbon && millis() >= usbon_time) { + if(!change && !usbon && (long)(millis() - usbon_time) >= 0L) { change = true; usbon = true; } - if (change) { + if(change) { change = false; - if (usbon) { + if(usbon) { Usb.vbusPower(vbus_on); printf_P(PSTR("VBUS on\r\n")); } else { @@ -436,21 +422,21 @@ void loop() { } Usb.Task(); current_state = Usb.getUsbTaskState(); - if (current_state != last_state) { - if (UsbDEBUGlvl > 0x50) + if(current_state != last_state) { + if(UsbDEBUGlvl > 0x50) printf_P(PSTR("USB state = %x\r\n"), current_state); -#if defined(AVR) - if (current_state == USB_STATE_RUNNING) { +#if !defined(CORE_TEENSY) && defined(__AVR__) + if(current_state == USB_STATE_RUNNING) { fadeAmount = 30; } #endif - if (current_state == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) { -#if defined(AVR) + if(current_state == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) { +#if !defined(CORE_TEENSY) && defined(__AVR__) fadeAmount = 80; #endif partsready = false; - for (int i = 0; i < cpart; i++) { - if (Fats[i] != NULL) + for(int i = 0; i < cpart; i++) { + if(Fats[i] != NULL) delete Fats[i]; Fats[i] = NULL; } @@ -462,48 +448,48 @@ void loop() { } // only do any of this if usb is on - if (usbon) { - if (partsready && !fatready) { - if (cpart > 0) fatready = true; + if(usbon) { + if(partsready && !fatready) { + if(cpart > 0) fatready = true; } // This is horrible, and needs to be moved elsewhere! - for (int B = 0; B < MAX_USB_MS_DRIVERS; B++) { - if (!partsready && (Bulk[B]->GetAddress() != NULL)) { + for(int B = 0; B < MAX_USB_MS_DRIVERS; B++) { + if(!partsready && (UHS_USB_BulkOnly[B]->GetAddress() != NULL)) { // Build a list. - int ML = Bulk[B]->GetbMaxLUN(); + int ML = UHS_USB_BulkOnly[B]->GetbMaxLUN(); //printf("MAXLUN = %i\r\n", ML); ML++; - for (int i = 0; i < ML; i++) { - if (Bulk[B]->LUNIsGood(i)) { + for(int i = 0; i < ML; i++) { + if(UHS_USB_BulkOnly[B]->LUNIsGood(i)) { partsready = true; ((pvt_t *)(sto[i].private_data))->lun = i; ((pvt_t *)(sto[i].private_data))->B = B; - sto[i].Read = *PRead; - sto[i].Write = *PWrite; - sto[i].Reads = *PReads; - sto[i].Writes = *PWrites; - sto[i].Status = *PStatus; - sto[i].TotalSectors = Bulk[B]->GetCapacity(i); - sto[i].SectorSize = Bulk[B]->GetSectorSize(i); + sto[i].Reads = *UHS_USB_BulkOnly_Read; + sto[i].Writes = *UHS_USB_BulkOnly_Write; + sto[i].Status = *UHS_USB_BulkOnly_Status; + sto[i].Initialize = *UHS_USB_BulkOnly_Initialize; + sto[i].Commit = *UHS_USB_BulkOnly_Commit; + sto[i].TotalSectors = UHS_USB_BulkOnly[B]->GetCapacity(i); + sto[i].SectorSize = UHS_USB_BulkOnly[B]->GetSectorSize(i); printf_P(PSTR("LUN:\t\t%u\r\n"), i); printf_P(PSTR("Total Sectors:\t%08lx\t%lu\r\n"), sto[i].TotalSectors, sto[i].TotalSectors); printf_P(PSTR("Sector Size:\t%04x\t\t%u\r\n"), sto[i].SectorSize, sto[i].SectorSize); // get the partition data... PT = new PCPartition; - if (!PT->Init(&sto[i])) { + if(!PT->Init(&sto[i])) { part_t *apart; - for (int j = 0; j < 4; j++) { + for(int j = 0; j < 4; j++) { apart = PT->GetPart(j); - if (apart != NULL && apart->type != 0x00) { + if(apart != NULL && apart->type != 0x00) { memcpy(&(parts[cpart]), apart, sizeof (part_t)); printf_P(PSTR("Partition %u type %#02x\r\n"), j, parts[cpart].type); // for now - if (isfat(parts[cpart].type)) { + if(isfat(parts[cpart].type)) { Fats[cpart] = new PFAT(&sto[i], cpart, parts[cpart].firstSector); //int r = Fats[cpart]->Good(); - if (Fats[cpart]->MountStatus()) { + if(Fats[cpart]->MountStatus()) { delete Fats[cpart]; Fats[cpart] = NULL; } else cpart++; @@ -514,7 +500,7 @@ void loop() { // try superblock Fats[cpart] = new PFAT(&sto[i], cpart, 0); //int r = Fats[cpart]->Good(); - if (Fats[cpart]->MountStatus()) { + if(Fats[cpart]->MountStatus()) { //printf_P(PSTR("Superblock error %x\r\n"), r); delete Fats[cpart]; Fats[cpart] = NULL; @@ -523,10 +509,9 @@ void loop() { } delete PT; } else { - sto[i].Read = NULL; - sto[i].Write = NULL; sto[i].Writes = NULL; sto[i].Reads = NULL; + sto[i].Initialize = NULL; sto[i].TotalSectors = 0UL; sto[i].SectorSize = 0; } @@ -535,18 +520,18 @@ void loop() { } } - if (fatready) { - if (Fats[0] != NULL) { + if(fatready) { + if(Fats[0] != NULL) { struct Pvt * p; p = ((struct Pvt *)(Fats[0]->storage->private_data)); - if (!Bulk[p->B]->LUNIsGood(p->lun)) { + if(!UHS_USB_BulkOnly[p->B]->LUNIsGood(p->lun)) { // media change -#if defined(AVR) +#if !defined(CORE_TEENSY) && defined(__AVR__) fadeAmount = 80; #endif partsready = false; - for (int i = 0; i < cpart; i++) { - if (Fats[i] != NULL) + for(int i = 0; i < cpart; i++) { + if(Fats[i] != NULL) delete Fats[i]; Fats[cpart] = NULL; } @@ -557,62 +542,64 @@ void loop() { } } - if (fatready) { + if(fatready) { FRESULT rc; /* Result code */ UINT bw, br, i; - - if (!notified) { -#if defined(AVR) + if(!notified) { +#if !defined(CORE_TEENSY) && defined(__AVR__) fadeAmount = 5; #endif notified = true; + FATFS *fs = NULL; + for(int zz = 0; zz < _VOLUMES; zz++) { + if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs; + } printf_P(PSTR("\r\nOpen an existing file (message.txt).\r\n")); rc = f_open(&My_File_Object_x, "0:/MESSAGE.TXT", FA_READ); - if (rc) printf_P(PSTR("Error %i, message.txt not found.\r\n"), rc); + if(rc) printf_P(PSTR("Error %i, message.txt not found.\r\n"), rc); else { printf_P(PSTR("\r\nType the file content.\r\n")); - for (;;) { + for(;;) { rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &br); /* Read a chunk of file */ - if (rc || !br) break; /* Error or end of file */ - for (i = 0; i < br; i++) { + if(rc || !br) break; /* Error or end of file */ + for(i = 0; i < br; i++) { /* Type the data */ - if (My_Buff_x[i] == '\n') + if(My_Buff_x[i] == '\n') Serial.write('\r'); - if (My_Buff_x[i] != '\r') + if(My_Buff_x[i] != '\r') Serial.write(My_Buff_x[i]); Serial.flush(); } } - if (rc) { + if(rc) { f_close(&My_File_Object_x); goto out; } printf_P(PSTR("\r\nClose the file.\r\n")); rc = f_close(&My_File_Object_x); - if (rc) goto out; + if(rc) goto out; } printf_P(PSTR("\r\nCreate a new file (hello.txt).\r\n")); rc = f_open(&My_File_Object_x, "0:/Hello.TxT", FA_WRITE | FA_CREATE_ALWAYS); - if (rc) { + if(rc) { die(rc); goto outdir; } printf_P(PSTR("\r\nWrite a text data. (Hello world!)\r\n")); rc = f_write(&My_File_Object_x, "Hello world!\r\n", 14, &bw); - if (rc) { + if(rc) { goto out; } printf_P(PSTR("%u bytes written.\r\n"), bw); printf_P(PSTR("\r\nClose the file.\r\n")); rc = f_close(&My_File_Object_x); - if (rc) { + if(rc) { die(rc); goto out; } -outdir: - { +outdir:{ #if _USE_LFN char lfn[_MAX_LFN + 1]; FILINFO My_File_Info_Object_x; /* File information object */ @@ -621,55 +608,55 @@ outdir: DIR My_Dir_Object_x; /* Directory object */ printf_P(PSTR("\r\nOpen root directory.\r\n")); rc = f_opendir(&My_Dir_Object_x, "0:/"); - if (rc) { + if(rc) { die(rc); goto out; } printf_P(PSTR("\r\nDirectory listing...\r\n")); -#if defined(AVR) +#if defined(__AVR__) printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); #endif - for (;;) { + for(;;) { #if _USE_LFN My_File_Info_Object_x.lfsize = _MAX_LFN; #endif rc = f_readdir(&My_Dir_Object_x, &My_File_Info_Object_x); /* Read a directory item */ - if (rc || !My_File_Info_Object_x.fname[0]) break; /* Error or end of dir */ + if(rc || !My_File_Info_Object_x.fname[0]) break; /* Error or end of dir */ - if (My_File_Info_Object_x.fattrib & AM_DIR) { + if(My_File_Info_Object_x.fattrib & AM_DIR) { Serial.write('d'); } else { Serial.write('-'); } Serial.write('r'); - if (My_File_Info_Object_x.fattrib & AM_RDO) { + if(My_File_Info_Object_x.fattrib & AM_RDO) { Serial.write('-'); } else { Serial.write('w'); } - if (My_File_Info_Object_x.fattrib & AM_HID) { + if(My_File_Info_Object_x.fattrib & AM_HID) { Serial.write('h'); } else { Serial.write('-'); } - if (My_File_Info_Object_x.fattrib & AM_SYS) { + if(My_File_Info_Object_x.fattrib & AM_SYS) { Serial.write('s'); } else { Serial.write('-'); } - if (My_File_Info_Object_x.fattrib & AM_ARC) { + if(My_File_Info_Object_x.fattrib & AM_ARC) { Serial.write('a'); } else { Serial.write('-'); } #if _USE_LFN - if (*My_File_Info_Object_x.lfname) + if(*My_File_Info_Object_x.lfname) printf_P(PSTR(" %8lu %s (%s)\r\n"), My_File_Info_Object_x.fsize, My_File_Info_Object_x.fname, My_File_Info_Object_x.lfname); else #endif @@ -677,48 +664,55 @@ outdir: } } out: - if (rc) die(rc); + if(rc) die(rc); + + DISK_IOCTL(fs->drv, CTRL_COMMIT, 0); printf_P(PSTR("\r\nTest completed.\r\n")); } - if (runtest) { + if(runtest) { ULONG ii, wt, rt, start, end; + FATFS *fs = NULL; + for(int zz = 0; zz < _VOLUMES; zz++) { + if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs; + } runtest = false; f_unlink("0:/10MB.bin"); printf_P(PSTR("\r\nCreate a new 10MB test file (10MB.bin).\r\n")); rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_WRITE | FA_CREATE_ALWAYS); - if (rc) goto failed; - for (bw = 0; bw < mbxs; bw++) My_Buff_x[bw] = bw & 0xff; + if(rc) goto failed; + for(bw = 0; bw < mbxs; bw++) My_Buff_x[bw] = bw & 0xff; fflush(stdout); start = millis(); - while (start == millis()); - for (ii = 10485760LU / mbxs; ii > 0LU; ii--) { + while(start == millis()); + for(ii = 10485760LU / mbxs; ii > 0LU; ii--) { rc = f_write(&My_File_Object_x, My_Buff_x, mbxs, &bw); - if (rc || !bw) goto failed; + if(rc || !bw) goto failed; } rc = f_close(&My_File_Object_x); - if (rc) goto failed; + if(rc) goto failed; end = millis(); wt = (end - start) - 1; printf_P(PSTR("Time to write 10485760 bytes: %lu ms (%lu sec) \r\n"), wt, (500 + wt) / 1000UL); rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_READ); fflush(stdout); start = millis(); - while (start == millis()); - if (rc) goto failed; - for (;;) { + while(start == millis()); + if(rc) goto failed; + for(;;) { rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &bw); /* Read a chunk of file */ - if (rc || !bw) break; /* Error or end of file */ + if(rc || !bw) break; /* Error or end of file */ } end = millis(); - if (rc) goto failed; + if(rc) goto failed; rc = f_close(&My_File_Object_x); - if (rc) goto failed; + if(rc) goto failed; rt = (end - start) - 1; printf_P(PSTR("Time to read 10485760 bytes: %lu ms (%lu sec)\r\nDelete test file\r\n"), rt, (500 + rt) / 1000UL); failed: - if (rc) die(rc); + if(rc) die(rc); + DISK_IOCTL(fs->drv, CTRL_COMMIT, 0); printf_P(PSTR("10MB timing test finished.\r\n")); } } diff --git a/examples/testusbhostFAT/xmem2 b/examples/testusbhostFAT/xmem2 index dd85091a..2bf8f633 160000 --- a/examples/testusbhostFAT/xmem2 +++ b/examples/testusbhostFAT/xmem2 @@ -1 +1 @@ -Subproject commit dd85091abaca7cc6055ff515a5e42f32198380d2 +Subproject commit 2bf8f633e7f9bc5a7bf4c00f3f45c7b79484198e From 05bbfaad6f09baf3e15fbd61ce461b79ab2f0020 Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Mon, 2 Jun 2014 10:48:29 -0400 Subject: [PATCH 08/23] Update heads --- examples/testusbhostFAT/RTClib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/testusbhostFAT/RTClib b/examples/testusbhostFAT/RTClib index 7fd6a306..31e9226c 160000 --- a/examples/testusbhostFAT/RTClib +++ b/examples/testusbhostFAT/RTClib @@ -1 +1 @@ -Subproject commit 7fd6a306ca53d08bf53b2bbfc1b80eb056f2c55b +Subproject commit 31e9226c2098f9d516c4fe05befe07f542ee5740 From 7034b2d4aabaa80d67130a09bdb258f372522407 Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Mon, 2 Jun 2014 17:37:54 -0400 Subject: [PATCH 09/23] Update heads --- examples/testusbhostFAT/RTClib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/testusbhostFAT/RTClib b/examples/testusbhostFAT/RTClib index 31e9226c..ce052844 160000 --- a/examples/testusbhostFAT/RTClib +++ b/examples/testusbhostFAT/RTClib @@ -1 +1 @@ -Subproject commit 31e9226c2098f9d516c4fe05befe07f542ee5740 +Subproject commit ce052844c99801e4c6248aa5bf11b09c479a1ab6 From 2e4f3ad4da30f5d1d19644228a25dcea106cab42 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Mon, 9 Jun 2014 16:59:14 +0200 Subject: [PATCH 10/23] Updated comment --- PS4BT.h | 1 - 1 file changed, 1 deletion(-) diff --git a/PS4BT.h b/PS4BT.h index 3c0aae12..ff3168a3 100644 --- a/PS4BT.h +++ b/PS4BT.h @@ -58,7 +58,6 @@ protected: /** @name BTHID implementation */ /** * Used to parse Bluetooth HID data. - * @param bthid Pointer to the BTHID class. * @param len The length of the incoming data. * @param buf Pointer to the data buffer. */ From 5f1e4d5b7527fe072317b0b602dbe1e4dec442dc Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Thu, 12 Jun 2014 22:31:14 -0400 Subject: [PATCH 11/23] Update heads --- examples/testusbhostFAT/RTClib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/testusbhostFAT/RTClib b/examples/testusbhostFAT/RTClib index ce052844..ddc8ebef 160000 --- a/examples/testusbhostFAT/RTClib +++ b/examples/testusbhostFAT/RTClib @@ -1 +1 @@ -Subproject commit ce052844c99801e4c6248aa5bf11b09c479a1ab6 +Subproject commit ddc8ebef0c311240b3068cdd4c03d64c0e72ee7d From 16689cdf1442e1575e3a66d576b45bd3035f8cbe Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Thu, 12 Jun 2014 23:12:43 -0400 Subject: [PATCH 12/23] Update heads --- examples/testusbhostFAT/RTClib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/testusbhostFAT/RTClib b/examples/testusbhostFAT/RTClib index ce052844..ddc8ebef 160000 --- a/examples/testusbhostFAT/RTClib +++ b/examples/testusbhostFAT/RTClib @@ -1 +1 @@ -Subproject commit ce052844c99801e4c6248aa5bf11b09c479a1ab6 +Subproject commit ddc8ebef0c311240b3068cdd4c03d64c0e72ee7d From 577619552315e815c2ed007ac7076dd7190f3fea Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Tue, 24 Jun 2014 17:46:43 -0400 Subject: [PATCH 13/23] Update heads Tue Jun 24 21:46:25 UTC 2014 --- examples/testusbhostFAT/RTClib | 2 +- examples/testusbhostFAT/generic_storage | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/testusbhostFAT/RTClib b/examples/testusbhostFAT/RTClib index ddc8ebef..b119b97e 160000 --- a/examples/testusbhostFAT/RTClib +++ b/examples/testusbhostFAT/RTClib @@ -1 +1 @@ -Subproject commit ddc8ebef0c311240b3068cdd4c03d64c0e72ee7d +Subproject commit b119b97e1484a08aebcf24e070113d78c82fb023 diff --git a/examples/testusbhostFAT/generic_storage b/examples/testusbhostFAT/generic_storage index 0b8e3076..72b5bf46 160000 --- a/examples/testusbhostFAT/generic_storage +++ b/examples/testusbhostFAT/generic_storage @@ -1 +1 @@ -Subproject commit 0b8e3076b5a072251e01cfc6e6333b364d4e71e7 +Subproject commit 72b5bf467a1c2479ba7354ee4d864e382c167425 From 25117ab9260b64b1870c6982d73bc190e00b0313 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sun, 29 Jun 2014 18:05:50 +0200 Subject: [PATCH 14/23] Added support for the Playstation Buzz controllers See #71 --- PSBuzz.cpp | 82 ++++++++++++++++ PSBuzz.h | 185 +++++++++++++++++++++++++++++++++++++ README.md | 13 ++- controllerEnums.h | 8 ++ examples/PSBuzz/PSBuzz.ino | 46 +++++++++ keywords.txt | 31 ++++++- 6 files changed, 362 insertions(+), 3 deletions(-) create mode 100644 PSBuzz.cpp create mode 100644 PSBuzz.h create mode 100644 examples/PSBuzz/PSBuzz.ino diff --git a/PSBuzz.cpp b/PSBuzz.cpp new file mode 100644 index 00000000..56ae618d --- /dev/null +++ b/PSBuzz.cpp @@ -0,0 +1,82 @@ +/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "PSBuzz.h" + +// To enable serial debugging see "settings.h" +//#define PRINTREPORT // Uncomment to print the report send by the PS Buzz Controllers + +void PSBuzz::ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID && len > 0 && buf) { +#ifdef PRINTREPORT + Notify(PSTR("\r\n"), 0x80); + for (uint8_t i = 0; i < len; i++) { + D_PrintHex (buf[i], 0x80); + Notify(PSTR(" "), 0x80); + } +#endif + memcpy(&psbuzzButtons, buf + 2, min(len - 2, sizeof(psbuzzButtons))); + + if (psbuzzButtons.val != oldButtonState.val) { // Check if anything has changed + buttonClickState.val = psbuzzButtons.val & ~oldButtonState.val; // Update click state variable + oldButtonState.val = psbuzzButtons.val; + } + } +}; + +uint8_t PSBuzz::OnInitSuccessful() { + if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID) { + Reset(); + if (pFuncOnInit) + pFuncOnInit(); // Call the user function + else + setLedOnAll(); // Turn the LED on, on all four controllers + }; + return 0; +}; + +bool PSBuzz::getButtonPress(ButtonEnum b, uint8_t controller) { + return psbuzzButtons.val & (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller +}; + +bool PSBuzz::getButtonClick(ButtonEnum b, uint8_t controller) { + uint32_t mask = (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller + bool click = buttonClickState.val & mask; + buttonClickState.val &= ~mask; // Clear "click" event + return click; +}; + +// Source: http://www.developerfusion.com/article/84338/making-usb-c-friendly/ and https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c +void PSBuzz::setLedRaw(bool value, uint8_t controller) { + ledState[controller] = value; // Save value for next time it is called + + uint8_t buf[7]; + buf[0] = 0x00; + buf[1] = ledState[0] ? 0xFF : 0x00; + buf[2] = ledState[1] ? 0xFF : 0x00; + buf[3] = ledState[2] ? 0xFF : 0x00; + buf[4] = ledState[3] ? 0xFF : 0x00; + buf[5] = 0x00; + buf[6] = 0x00; + + PSBuzz_Command(buf, sizeof(buf)); +}; + +void PSBuzz::PSBuzz_Command(uint8_t *data, uint16_t nbytes) { + // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); +}; \ No newline at end of file diff --git a/PSBuzz.h b/PSBuzz.h new file mode 100644 index 00000000..1d7859d2 --- /dev/null +++ b/PSBuzz.h @@ -0,0 +1,185 @@ +/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _psbuzz_h_ +#define _psbuzz_h_ + +#include "hiduniversal.h" +#include "controllerEnums.h" + +#define PSBUZZ_VID 0x054C // Sony Corporation +#define PSBUZZ_PID 0x1000 // PS Buzz Controller + +/** Struct used to easily read the different buttons on the controllers */ +union PSBUZZButtons { + struct { + uint8_t red : 1; + uint8_t yellow : 1; + uint8_t green : 1; + uint8_t orange : 1; + uint8_t blue : 1; + } __attribute__((packed)) btn[4]; + uint32_t val : 20; +} __attribute__((packed)); + +/** + * This class implements support for the PS Buzz controllers via USB. + * It uses the HIDUniversal class for all the USB communication. + */ +class PSBuzz : public HIDUniversal { +public: + /** + * Constructor for the PSBuzz class. + * @param p Pointer to the USB class instance. + */ + PSBuzz(USB *p) : + HIDUniversal(p) { + Reset(); + }; + + /** + * Used to check if a PS Buzz controller is connected. + * @return Returns true if it is connected. + */ + bool connected() { + return HIDUniversal::isReady() && HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID; + }; + + /** + * Used to call your own function when the device is successfully initialized. + * @param funcOnInit Function to call. + */ + void attachOnInit(void (*funcOnInit)(void)) { + pFuncOnInit = funcOnInit; + }; + + /** @name PS Buzzer Controller functions */ + /** + * getButtonPress(ButtonEnum b) will return true as long as the button is held down. + * + * While getButtonClick(ButtonEnum b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), + * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). + * @param b ::ButtonEnum to read. + * @param controller The controller to read from. Default to 0. + * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. + */ + bool getButtonPress(ButtonEnum b, uint8_t controller = 0); + bool getButtonClick(ButtonEnum b, uint8_t controller = 0); + /**@}*/ + /** @name PS Buzzer Controller functions */ + /** + * Set LED value without using ::LEDEnum. + * @param value See: ::LEDEnum. + */ + /** + * Set LED values directly. + * @param value Used to set whenever the LED should be on or off + * @param controller The controller to control. Defaults to 0. + */ + void setLedRaw(bool value, uint8_t controller = 0); + + /** Turn all LEDs off. */ + void setLedOffAll() { + for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw + ledState[i] = false; // Just an easy way to set all four off at the same time + setLedRaw(false); // Turn the LED off, on all four controllers + }; + + /** + * Turn the LED off on a specific controller. + * @param controller The controller to turn off. Defaults to 0. + */ + void setLedOff(uint8_t controller = 0) { + setLedRaw(false, controller); + }; + + + /** Turn all LEDs on. */ + void setLedOnAll() { + for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw + ledState[i] = true; // Just an easy way to set all four off at the same time + setLedRaw(true); // Turn the LED on, on all four controllers + }; + + /** + * Turn the LED on on a specific controller. + * @param controller The controller to turn off. Defaults to 0. + */ + void setLedOn(uint8_t controller = 0) { + setLedRaw(true, controller); + }; + + /** + * Toggle the LED on a specific controller. + * @param controller The controller to turn off. Defaults to 0. + */ + void setLedToggle(uint8_t controller = 0) { + setLedRaw(!ledState[controller], controller); + }; + /**@}*/ + +protected: + /** @name HIDUniversal implementation */ + /** + * Used to parse USB HID data. + * @param hid Pointer to the HID class. + * @param is_rpt_id Only used for Hubs. + * @param len The length of the incoming data. + * @param buf Pointer to the data buffer. + */ + virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); + + /** + * Called when a device is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + virtual uint8_t OnInitSuccessful(); + /**@}*/ + + /** Used to reset the different buffers to their default values */ + void Reset() { + psbuzzButtons.val = 0; + oldButtonState.val = 0; + buttonClickState.val = 0; + for (uint8_t i = 0; i < sizeof(ledState); i++) + ledState[i] = 0; + }; + + /** @name USBDeviceConfig implementation */ + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual boolean VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == PSBUZZ_VID && pid == PSBUZZ_PID); + }; + /**@}*/ + +private: + void (*pFuncOnInit)(void); // Pointer to function called in onInit() + + void PSBuzz_Command(uint8_t *data, uint16_t nbytes); + + PSBUZZButtons psbuzzButtons, oldButtonState, buttonClickState; + bool ledState[4]; +}; +#endif \ No newline at end of file diff --git a/README.md b/README.md index 35a786e5..2fc7305c 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ For more information about the hardware see the [Hardware Manual](http://www.cir * __Alexei Glushchenko, Circuits@Home__ - * Developers of the USB Core, HID, FTDI, ADK, ACM, and PL2303 libraries * __Kristian Lauszus, TKJ Electronics__ - - * Developer of the [BTD](#bluetooth-libraries), [BTHID](#bthid-library), [SPP](#spp-library), [PS4](#ps4-library), [PS3](#ps3-library), [Wii](#wii-library), and [Xbox](#xbox-library) libraries + * Developer of the [BTD](#bluetooth-libraries), [BTHID](#bthid-library), [SPP](#spp-library), [PS4](#ps4-library), [PS3](#ps3-library), [Wii](#wii-library), [Xbox](#xbox-library), and [PSBuzz](#ps-buzz-library) libraries * __Andrew Kroll__ - * Major contributor to mass storage code @@ -240,6 +240,17 @@ All the information about the Wii controllers are from these sites: * * The old library created by _Tomoyuki Tanaka_: also helped a lot. +### [PS Buzz Library](PSBuzz.cpp) + +This library implements support for the Playstation Buzz controllers via USB. + +It is essentially just a wrapper around the [HIDUniversal](hiduniversal.cpp) which takes care of the initializing and reading of the controllers. The [PSBuzz](PSBuzz.cpp) class simply inherits this and parses the data, so it is easy for users to read the buttons and turn the big red button on the controllers on and off. + +More information about the controller can be found at the following sites: + +* http://www.developerfusion.com/article/84338/making-usb-c-friendly/ +* https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c + # FAQ > When I plug my device into the USB connector nothing happens? diff --git a/controllerEnums.h b/controllerEnums.h index 295b6ae4..0169c763 100644 --- a/controllerEnums.h +++ b/controllerEnums.h @@ -137,6 +137,14 @@ enum ButtonEnum { BLACK = 8, // Available on the original Xbox controller WHITE = 9, // Available on the original Xbox controller /**@}*/ + + /** PS Buzz controllers */ + RED = 0, + YELLOW = 1, + GREEN = 2, + ORANGE = 3, + BLUE = 4, + /**@}*/ }; /** Joysticks on the PS3 and Xbox controllers. */ diff --git a/examples/PSBuzz/PSBuzz.ino b/examples/PSBuzz/PSBuzz.ino new file mode 100644 index 00000000..6944cb6b --- /dev/null +++ b/examples/PSBuzz/PSBuzz.ino @@ -0,0 +1,46 @@ +/* + Example sketch for the Playstation Buzz library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#endif + +USB Usb; +PSBuzz Buzz(&Usb); + +void setup() { + Serial.begin(115200); + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); // Halt + } + Serial.println(F("\r\nPS Buzz Library Started")); +} + +void loop() { + Usb.Task(); + + if (Buzz.connected()) { + for (uint8_t i = 0; i < 4; i++) { + if (Buzz.getButtonClick(RED, i)) { + Buzz.setLedToggle(i); // Toggle the LED + Serial.println(F("RED")); + } + if (Buzz.getButtonClick(YELLOW, i)) + Serial.println(F("YELLOW")); + if (Buzz.getButtonClick(GREEN, i)) + Serial.println(F("GREEN")); + if (Buzz.getButtonClick(ORANGE, i)) + Serial.println(F("ORANGE")); + if (Buzz.getButtonClick(BLUE, i)) + Serial.println(F("BLUE")); + } + } +} diff --git a/keywords.txt b/keywords.txt index 58496f4b..c7bd007c 100644 --- a/keywords.txt +++ b/keywords.txt @@ -318,7 +318,7 @@ getIRy4 KEYWORD2 getIRs4 KEYWORD2 #################################################### -# Syntax Coloring Map For RFCOMM/SPP Library +# Syntax Coloring Map For BTHID Library #################################################### #################################################### @@ -331,4 +331,31 @@ BTHID KEYWORD1 # Methods and Functions (KEYWORD2) #################################################### SetReportParser KEYWORD2 -setProtocolMode KEYWORD2 \ No newline at end of file +setProtocolMode KEYWORD2 + +#################################################### +# Syntax Coloring Map For PS Buzz Library +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +PSBuzz KEYWORD1 + +#################################################### +# Methods and Functions (KEYWORD2) +#################################################### + +setLedOnAll KEYWORD2 +setLedOffAll KEYWORD2 + +#################################################### +# Constants and enums (LITERAL1) +#################################################### + +RED LITERAL1 +YELLOW LITERAL1 +GREEN LITERAL1 +ORANGE LITERAL1 +BLUE LITERAL1 \ No newline at end of file From dd600b489521dbf0102dd4f6135fdda6e4a42df3 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sun, 29 Jun 2014 18:06:27 +0200 Subject: [PATCH 15/23] Don't print incoming serial data if debugging is on by default --- hiduniversal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hiduniversal.cpp b/hiduniversal.cpp index ad1ad190..e7a65e39 100644 --- a/hiduniversal.cpp +++ b/hiduniversal.cpp @@ -398,7 +398,7 @@ uint8_t HIDUniversal::Poll() { if(identical) return 0; -#if 1 +#if 0 Notify(PSTR("\r\nBuf: "), 0x80); for(uint8_t i = 0; i < read; i++) { From 6152175f487ad6c1d20ce6fa7e1e9955762fa812 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sun, 29 Jun 2014 18:11:45 +0200 Subject: [PATCH 16/23] Added link to PSBuzz example --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2fc7305c..f9d0db0f 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,8 @@ This library implements support for the Playstation Buzz controllers via USB. It is essentially just a wrapper around the [HIDUniversal](hiduniversal.cpp) which takes care of the initializing and reading of the controllers. The [PSBuzz](PSBuzz.cpp) class simply inherits this and parses the data, so it is easy for users to read the buttons and turn the big red button on the controllers on and off. +The example [PSBuzz.ino](examples/PSBuzz/PSBuzz.ino) shows how one can do this with just a few lines of code. + More information about the controller can be found at the following sites: * http://www.developerfusion.com/article/84338/making-usb-c-friendly/ From e78d880bb481edeff5a607f60e026e43521533c3 Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Mon, 30 Jun 2014 12:54:16 -0400 Subject: [PATCH 17/23] Update heads Mon Jun 30 16:53:58 UTC 2014 --- examples/testusbhostFAT/Arduino_Makefile_master | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/testusbhostFAT/Arduino_Makefile_master b/examples/testusbhostFAT/Arduino_Makefile_master index d35bb955..1edd5f46 160000 --- a/examples/testusbhostFAT/Arduino_Makefile_master +++ b/examples/testusbhostFAT/Arduino_Makefile_master @@ -1 +1 @@ -Subproject commit d35bb955e3818f0c14e47c8a1998003da8dc1b5a +Subproject commit 1edd5f46188a6c4b68d6f9120fa72359a12e38f1 From c589731974816a5a145f1db800b515c4e33f0be4 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Tue, 1 Jul 2014 11:31:45 +0200 Subject: [PATCH 18/23] Added "Interface modifications" section to readme --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index f9d0db0f..21d3eaf5 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,26 @@ More information about the controller can be found at the following sites: * http://www.developerfusion.com/article/84338/making-usb-c-friendly/ * https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c +# Interface modifications + +The shield is using SPI for communicating with the MAX3421E USB host controller. It uses the SCK, MISO and MOSI pins via the ICSP on your board. + +Furthermore it uses one pin as SS and one INT pin. These are by default located on pin 10 and 9 respectively. They can easily be reconfigured in case you need to use them for something else by cutting the jumper on the shield and then solder a wire from the pad to the new pin. + +After that you need modify the following entry in [UsbCore.h](UsbCore.h): + +```C++ +typedef MAX3421e MAX3421E; +``` + +For instance if you have rerouted SS to pin 7 it should read: + +```C++ +typedef MAX3421e MAX3421E; +``` + +See the "Interface modifications" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information. + # FAQ > When I plug my device into the USB connector nothing happens? From efeb80855ec8cf64d31d140daf61c321e1550b45 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Tue, 1 Jul 2014 11:47:39 +0200 Subject: [PATCH 19/23] Added table of contents --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 21d3eaf5..edb440a2 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,26 @@ For more information about the hardware see the [Hardware Manual](http://www.cir * __Andrew Kroll__ - * Major contributor to mass storage code +# Table of Contents + +* [How to include the library](#how-to-include-the-library) +* [How to use the library](#how-to-use-the-library) + * [Documentation](#documentation) + * [Enable debugging](#enable-debugging) + * [Boards](#boards) + * [Bluetooth libraries](#bluetooth-libraries) + * [BTHID library](#bthid-library) + * [SPP library](#spp-library) + * [PS4 Library](#ps4-library) + * [PS3 Library](#ps3-library) + * [Xbox Libraries](#xbox-libraries) + * [Xbox library](#xbox-library) + * [Xbox 360 Library](#xbox-360-library) + * [Wii library](#wii-library) + * [PS Buzz Library](#ps-buzz-library) +* [Interface modifications](#interface-modifications) +* [FAQ](#faq) + # How to include the library First download the library by clicking on the following link: . From 4a44c8f0392926c75ec539c7bc8d1f44c1b95b17 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Tue, 1 Jul 2014 13:17:56 +0200 Subject: [PATCH 20/23] Implemented VIDPIDOK in PS4USB --- PS4USB.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/PS4USB.h b/PS4USB.h index ea38455a..16dabad4 100644 --- a/PS4USB.h +++ b/PS4USB.h @@ -112,6 +112,18 @@ protected: }; /**@}*/ + /** @name USBDeviceConfig implementation */ + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual boolean VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == PS4_VID && pid == PS4_PID); + }; + /**@}*/ + private: void (*pFuncOnInit)(void); // Pointer to function called in onInit() }; From b82835c877adecf507312b742dd687e2ea03628f Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Tue, 1 Jul 2014 13:22:44 +0200 Subject: [PATCH 21/23] Break for loop if HID device is found --- BTD.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/BTD.cpp b/BTD.cpp index 2506cdf1..de83da95 100755 --- a/BTD.cpp +++ b/BTD.cpp @@ -464,6 +464,7 @@ void BTD::HCI_event_task() { disc_bdaddr[j] = hcibuf[j + 3 + 6 * i]; hci_set_flag(HCI_FLAG_DEVICE_FOUND); + break; } #ifdef EXTRADEBUG else { From 35bb596601954d80e03569f858e4ad6ce264adb8 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Tue, 1 Jul 2014 13:43:45 +0200 Subject: [PATCH 22/23] Cleaned up SPPMulti example --- examples/Bluetooth/SPPMulti/SPPMulti.ino | 33 ++++++++++-------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/examples/Bluetooth/SPPMulti/SPPMulti.ino b/examples/Bluetooth/SPPMulti/SPPMulti.ino index 262a2927..0304257e 100644 --- a/examples/Bluetooth/SPPMulti/SPPMulti.ino +++ b/examples/Bluetooth/SPPMulti/SPPMulti.ino @@ -6,7 +6,7 @@ #include #include -// Satisfy IDE, which only needs to see the include statment in the ino. +// Satisfy IDE, which only needs to see the include statement in the ino. #ifdef dobogusinclude #include #endif @@ -15,10 +15,11 @@ USB Usb; //USBHub Hub1(&Usb); // Some dongles have a hub inside BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so -SPP *SerialBT[2]; // We will use this pointer to store the two instance, you can easily make it larger if you like, but it will use a lot of RAM! -const uint8_t length = sizeof(SerialBT) / sizeof(SerialBT[0]); // Get the lenght of the array + +const uint8_t length = 2; // Set the number of instances here +SPP *SerialBT[length]; // We will use this pointer to store the instances, you can easily make it larger if you like, but it will use a lot of RAM! + boolean firstMessage[length] = { true }; // Set all to true -uint8_t buffer[50]; void setup() { for (uint8_t i = 0; i < length; i++) @@ -28,10 +29,11 @@ void setup() { while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection if (Usb.Init() == -1) { Serial.print(F("\r\nOSC did not start")); - while (1); //halt + while (1); // Halt } Serial.print(F("\r\nSPP Bluetooth Library Started")); } + void loop() { Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well @@ -47,22 +49,15 @@ void loop() { else firstMessage[i] = true; } + + // Set the connection you want to send to using the first character + // For instance "0Hello World" would send "Hello World" to connection 0 if (Serial.available()) { delay(10); // Wait for the rest of the data to arrive - uint8_t i = 0; - while (Serial.available() && i < sizeof(buffer)) // Read the data - buffer[i++] = Serial.read(); - /* - Set the connection you want to send to using the first character - For instace "0Hello World" would send "Hello World" to connection 0 - */ - uint8_t id = buffer[0] - '0'; // Convert from ASCII - if (id < length && i > 1) { // And then compare to length and make sure there is any text - if (SerialBT[id]->connected) { // Check if a device is actually connected - for (uint8_t i2 = 0; i2 < i - 1; i2++) // Don't include the first character - buffer[i2] = buffer[i2 + 1]; - SerialBT[id]->write(buffer, i - 1); // Send the data - } + uint8_t id = Serial.read() - '0'; // Convert from ASCII + if (id < length && SerialBT[id]->connected) { // Make sure that the id is valid and make sure that a device is actually connected + while (Serial.available()) // Check if data is available + SerialBT[id]->write(Serial.read()); // Send the data } } } From 6a9e574bf2b86f54050009ec128dca40947ccec7 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Tue, 22 Apr 2014 16:54:41 +0200 Subject: [PATCH 23/23] Added comments for "SDP_ServiceSearchAttributeResponse" --- SPP.cpp | 155 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 84 insertions(+), 71 deletions(-) diff --git a/SPP.cpp b/SPP.cpp index ef0cf216..562a68ca 100644 --- a/SPP.cpp +++ b/SPP.cpp @@ -538,15 +538,15 @@ void SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLo l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; l2capoutbuf[1] = transactionIDHigh; l2capoutbuf[2] = transactionIDLow; - l2capoutbuf[3] = 0x00; // Parameter Length - l2capoutbuf[4] = 0x05; // Parameter Length - l2capoutbuf[5] = 0x00; // AttributeListsByteCount - l2capoutbuf[6] = 0x02; // AttributeListsByteCount + l2capoutbuf[3] = 0x00; // MSB Parameter Length + l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5 + l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount + l2capoutbuf[6] = 0x02; // LSB AttributeListsByteCount = 2 /* Attribute ID/Value Sequence: */ - l2capoutbuf[7] = 0x35; - l2capoutbuf[8] = 0x00; - l2capoutbuf[9] = 0x00; + l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[8] = 0x00; // Length = 0 + l2capoutbuf[9] = 0x00; // No continuation state SDP_Command(l2capoutbuf, 10); } @@ -555,56 +555,60 @@ void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLo l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; l2capoutbuf[1] = transactionIDHigh; l2capoutbuf[2] = transactionIDLow; - l2capoutbuf[3] = 0x00; // Parameter Length - l2capoutbuf[4] = 0x2B; // Parameter Length - l2capoutbuf[5] = 0x00; // AttributeListsByteCount - l2capoutbuf[6] = 0x26; // AttributeListsByteCount + l2capoutbuf[3] = 0x00; // MSB Parameter Length + l2capoutbuf[4] = 0x2B; // LSB Parameter Length = 43 + l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount + l2capoutbuf[6] = 0x26; // LSB AttributeListsByteCount = 38 /* Attribute ID/Value Sequence: */ - l2capoutbuf[7] = 0x36; - l2capoutbuf[8] = 0x00; - l2capoutbuf[9] = 0x3C; - l2capoutbuf[10] = 0x36; - l2capoutbuf[11] = 0x00; + l2capoutbuf[7] = 0x36; // Data element sequence - length in next two bytes + l2capoutbuf[8] = 0x00; // MSB Length + l2capoutbuf[9] = 0x3C; // LSB Length = 60 - l2capoutbuf[12] = 0x39; - l2capoutbuf[13] = 0x09; - l2capoutbuf[14] = 0x00; - l2capoutbuf[15] = 0x00; - l2capoutbuf[16] = 0x0A; - l2capoutbuf[17] = 0x00; + l2capoutbuf[10] = 0x36; // Data element sequence - length in next two bytes + l2capoutbuf[11] = 0x00; // MSB Length + l2capoutbuf[12] = 0x39; // LSB Length = 57 + + l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[14] = 0x00; // MSB ServiceRecordHandle + l2capoutbuf[15] = 0x00; // LSB ServiceRecordHandle + l2capoutbuf[16] = 0x0A; // Unsigned int - length 4 bytes + l2capoutbuf[17] = 0x00; // ServiceRecordHandle value - TODO: Is this related to HCI_Handle? l2capoutbuf[18] = 0x01; l2capoutbuf[19] = 0x00; l2capoutbuf[20] = 0x06; - l2capoutbuf[21] = 0x09; - l2capoutbuf[22] = 0x00; - l2capoutbuf[23] = 0x01; - l2capoutbuf[24] = 0x35; - l2capoutbuf[25] = 0x03; - l2capoutbuf[26] = 0x19; - l2capoutbuf[27] = 0x11; - l2capoutbuf[28] = 0x01; - l2capoutbuf[29] = 0x09; - l2capoutbuf[30] = 0x00; - l2capoutbuf[31] = 0x04; - l2capoutbuf[32] = 0x35; - l2capoutbuf[33] = 0x0C; - l2capoutbuf[34] = 0x35; - l2capoutbuf[35] = 0x03; - l2capoutbuf[36] = 0x19; - l2capoutbuf[37] = 0x01; - l2capoutbuf[38] = 0x00; - l2capoutbuf[39] = 0x35; - l2capoutbuf[40] = 0x05; - l2capoutbuf[41] = 0x19; - l2capoutbuf[42] = 0x00; - l2capoutbuf[43] = 0x03; + l2capoutbuf[21] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[22] = 0x00; // MSB ServiceClassIDList + l2capoutbuf[23] = 0x01; // LSB ServiceClassIDList + l2capoutbuf[24] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[25] = 0x03; // Length = 3 + l2capoutbuf[26] = 0x19; // UUID (universally unique identifier) - length = 2 bytes + l2capoutbuf[27] = 0x11; // MSB SerialPort + l2capoutbuf[28] = 0x01; // LSB SerialPort - l2capoutbuf[44] = 0x08; - l2capoutbuf[45] = 0x02; // Two extra bytes - l2capoutbuf[46] = 0x00; // 25 (0x19) more bytes to come - l2capoutbuf[47] = 0x19; + l2capoutbuf[29] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[30] = 0x00; // MSB ProtocolDescriptorList + l2capoutbuf[31] = 0x04; // LSB ProtocolDescriptorList + l2capoutbuf[32] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[33] = 0x0C; // Length = 12 + + l2capoutbuf[34] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[35] = 0x03; // Length = 3 + l2capoutbuf[36] = 0x19; // UUID (universally unique identifier) - length = 2 bytes + l2capoutbuf[37] = 0x01; // MSB L2CAP + l2capoutbuf[38] = 0x00; // LSB L2CAP + + l2capoutbuf[39] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[40] = 0x05; // Length = 5 + l2capoutbuf[41] = 0x19; // UUID (universally unique identifier) - length = 2 bytes + l2capoutbuf[42] = 0x00; // MSB RFCOMM + l2capoutbuf[43] = 0x03; // LSB RFCOMM + l2capoutbuf[44] = 0x08; // Unsigned Integer - length 1 byte + + l2capoutbuf[45] = 0x02; // ContinuationState - Two more bytes + l2capoutbuf[46] = 0x00; // MSB length + l2capoutbuf[47] = 0x19; // LSB length = 25 more bytes to come SDP_Command(l2capoutbuf, 48); } @@ -613,40 +617,49 @@ void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLo l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; l2capoutbuf[1] = transactionIDHigh; l2capoutbuf[2] = transactionIDLow; - l2capoutbuf[3] = 0x00; // Parameter Length - l2capoutbuf[4] = 0x1C; // Parameter Length - l2capoutbuf[5] = 0x00; // AttributeListsByteCount - l2capoutbuf[6] = 0x19; // AttributeListsByteCount + l2capoutbuf[3] = 0x00; // MSB Parameter Length + l2capoutbuf[4] = 0x1C; // LSB Parameter Length = 28 + l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount + l2capoutbuf[6] = 0x19; // LSB AttributeListsByteCount = 25 /* Attribute ID/Value Sequence: */ - l2capoutbuf[7] = 0x01; - l2capoutbuf[8] = 0x09; - l2capoutbuf[9] = 0x00; - l2capoutbuf[10] = 0x06; - l2capoutbuf[11] = 0x35; + l2capoutbuf[7] = 0x01; // Channel 1 - TODO: Try different values, so multiple servers can be used at once - l2capoutbuf[12] = 0x09; - l2capoutbuf[13] = 0x09; - l2capoutbuf[14] = 0x65; - l2capoutbuf[15] = 0x6E; - l2capoutbuf[16] = 0x09; - l2capoutbuf[17] = 0x00; - l2capoutbuf[18] = 0x6A; - l2capoutbuf[19] = 0x09; + l2capoutbuf[8] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[9] = 0x00; // MSB LanguageBaseAttributeIDList + l2capoutbuf[10] = 0x06; // LSB LanguageBaseAttributeIDList + l2capoutbuf[11] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[12] = 0x09; // Length = 9 + + // Identifier representing the natural language = en = English - see: "ISO 639:1988" + l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[14] = 0x65; // 'e' + l2capoutbuf[15] = 0x6E; // 'n' + + // "The second element of each triplet contains an identifier that specifies a character encoding used for the language" + // Encoding is set to 106 (UTF-8) - see: http://www.iana.org/assignments/character-sets/character-sets.xhtml + l2capoutbuf[16] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[17] = 0x00; // MSB of character encoding + l2capoutbuf[18] = 0x6A; // LSB of character encoding (106) + + // Attribute ID that serves as the base attribute ID for the natural language in the service record + // "To facilitate the retrieval of human-readable universal attributes in a principal language, the base attribute ID value for the primary language supported by a service record shall be 0x0100" + l2capoutbuf[19] = 0x09; // Unsigned Integer - length 2 bytes l2capoutbuf[20] = 0x01; l2capoutbuf[21] = 0x00; - l2capoutbuf[22] = 0x09; - l2capoutbuf[23] = 0x01; - l2capoutbuf[24] = 0x00; - l2capoutbuf[25] = 0x25; + l2capoutbuf[22] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[23] = 0x01; // MSB ServiceDescription + l2capoutbuf[24] = 0x00; // LSB ServiceDescription + + l2capoutbuf[25] = 0x25; // Text string - length in next byte l2capoutbuf[26] = 0x05; // Name length l2capoutbuf[27] = 'T'; l2capoutbuf[28] = 'K'; l2capoutbuf[29] = 'J'; l2capoutbuf[30] = 'S'; l2capoutbuf[31] = 'P'; - l2capoutbuf[32] = 0x00; // No more data + l2capoutbuf[32] = 0x00; // No continuation state SDP_Command(l2capoutbuf, 33); }