diff --git a/examples/debugdevice_full_duplex/.gitignore b/examples/debugdevice_full_duplex/.gitignore index 123ad57..a5ee017 100644 --- a/examples/debugdevice_full_duplex/.gitignore +++ b/examples/debugdevice_full_duplex/.gitignore @@ -1,2 +1,8 @@ +# binaries terminal test + +# work products +vend_ax.hex +debuglog.txt + diff --git a/examples/debugdevice_full_duplex/master/download.sh b/examples/debugdevice_full_duplex/master/download.sh index 372a192..05f2acf 100755 --- a/examples/debugdevice_full_duplex/master/download.sh +++ b/examples/debugdevice_full_duplex/master/download.sh @@ -9,7 +9,7 @@ fi for dev in $DEVS;do echo "Downloading $1 to $dev" - sudo /sbin/fxload -v -D /dev/bus/usb/$dev -t fx2lp -I $1 -c 0x01 -s /home/administrator/Vend_Ax.hex + sudo /sbin/fxload -v -D /dev/bus/usb/$dev -t fx2lp -I $1 -c 0x01 -s ../vend_ax.hex done exit 0 diff --git a/examples/debugdevice_full_duplex/slave/debugdev_slave.c b/examples/debugdevice_full_duplex/slave/debugdev_slave.c index 8d96472..32a1c33 100644 --- a/examples/debugdevice_full_duplex/slave/debugdev_slave.c +++ b/examples/debugdevice_full_duplex/slave/debugdev_slave.c @@ -16,7 +16,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **/ -#include #include #include @@ -25,50 +24,59 @@ #include #include #include +#include #define SYNCDELAY SYNCDELAY4 +// uncomment the next line to enable debugging via printf() via I2C. +// this can be used to feed an I2C/UART converter e.g. based on an Arduino. +// note: the default I2C target address is 0x10. +// note: ONLY ENABLE THIS IF a consumer is present on the I2C bus, as the write +// will block until the data is read - i.e. it will hang the device and +// no output will be produced! +//#define DEBUG_DEBUGSLAVE + +#ifdef DEBUG_DEBUGSLAVE +#include +#include + +#define I2CDEBUG_ADDR (0x10) +void putchar(char c) { + i2c_write (I2CDEBUG_ADDR, 1, &c, 0, NULL); +} +#else +#define printf(...) +#endif + volatile __bit got_sud; extern __code WORD debug_dscr; /* PORTA.3 */ -#define PA_LED1 (1 << 0) -#define PA_LED2 (1 << 1) -#define PA_MASTER_SELECT (1 << 3) +// indicate on D1 that IN EP6 is full +#define PA_LED1 (1 << 0) +// indicate on D2 that OUT EP2 is empty +#define PA_LED2 (1 << 1) // PA5/4 (FIFOADR1,0) select the endpoint to communicate with #define PA_nFIFOADDR (3 << 4) #define PA_nPKTEND (1 << 6) -#define EP2EMPTY 0x02 -#define EP6FULL 0x01 - -static void mainloop(void) -{ - int count = 0; - while(TRUE) { - if (got_sud) { - handle_setupdata(); - got_sud=FALSE; - } - if (EP24FIFOFLGS & EP2EMPTY) - IOA &= ~PA_LED2; - else - IOA |= PA_LED2; - - if (EP68FIFOFLGS & EP6FULL) - IOA &= ~PA_LED1; - else - IOA |= PA_LED1; - } -} +#define EP2EMPTY (0x02) +#define EP6FULL (0x01) void main() { + // Bit7: reserved + // Bit6: reserved + // Bit5: PORTCSTB + // Bit4-3: CLKSPD[1:0] - 0b10: 48MHz clock + // Bit2: CLKINV + // Bit1: CLKOE - enable CLKOUT pin + // Bit0: 8051RES CPUCS = 0x12; // Bit7: 0 = External, 1 = Internal...1 - Internal - // Bit6: 0 = 30Mhz Clk, 1 = 48 Mhz Clk...1 - 48Mhz + // Bit6: 0 = 30Mhz Clk, 1 = 48 Mhz Clk...1 - 48Mhz // Bit5: 0 = No ClkOut, 1 = ClkOut...0 - No ClkOut // Bit4: 0 = NormalPol, 1 = InvPol...0 = NormalPol // Bit3: 0 = Synchronous, 1 = Asynchronous...1 = Async @@ -78,52 +86,52 @@ void main() // Bit0 = ENH_PKT - Enhanced Packet Handling. // Bit1 = DYN_OUT - Disable Auto-Arming at the 0-1 transition of AUTOOUT. - RENUMERATE_UNCOND(); - - USE_USB_INTS(); - ENABLE_SUDAV(); - ENABLE_SOF(); - ENABLE_HISPEED(); - ENABLE_USBRESET(); - - /* INT endpoint */ - EP1INCFG = bmVALID | (3 << 4); SYNCDELAY; - - /* disable all other endpoints */ - EP1OUTCFG &= ~bmVALID; SYNCDELAY; - - /* BULK OUT endpoint EP2 */ - // Bit1:0 = BUF1:0 = 0, 0 = QUAD - // Bit1:0 = BUF1:0 = 0, 1 = INVALID - // Bit1:0 = BUF1:0 = 1, 0 = DOUBLE - // Bit1:0 = BUF1:0 = 1, 1 = TRIPLE - // Bit2 = 0 - // Bit3 = SIZE, 0 = 512 bytes, 1 = 1024 bytes - // Bit5:4 = TYPE1:0 = 0, 0 = INVALID - // Bit5:4 = TYPE1:0 = 0, 1 = ISO - // Bit5:4 = TYPE1:0 = 1, 0 = BULK (def) - // Bit5:4 = TYPE1:0 = 1, 1 = INT - // Bit6 = DIR, 0 = OUT, 1 = IN - // Bit7 = VALID - // 10100010 - DIR=OUT, TYPE=BULK, SIZE=512, BUF=QUAD - EP2CFG = 0xA0; SYNCDELAY; - EP6CFG = 0xE0; SYNCDELAY; - EP4CFG &= ~bmVALID; SYNCDELAY; - EP8CFG &= ~bmVALID; SYNCDELAY; - - RESETFIFOS(); - - /* BULK OUT endpoint EP2 */ - // Bit0 = WORDWIDE - // Bit1 = 0 - // Bit2 = ZEROLENIN - // Bit3 = AUTOIN - // Bit4 = AUTOOUT - // Bit5 = OEP2 - // Bit6 = INFM2 - // Bit7 = 0 + RENUMERATE_UNCOND(); + + USE_USB_INTS(); + ENABLE_SUDAV(); + ENABLE_SOF(); + ENABLE_HISPEED(); + ENABLE_USBRESET(); + + /* INT endpoint */ + EP1INCFG = bmVALID | (3 << 4); SYNCDELAY; + + /* disable all other endpoints */ + EP1OUTCFG &= ~bmVALID; SYNCDELAY; + + // Bit1:0 = BUF1:0 = 0, 0 = QUAD + // Bit1:0 = BUF1:0 = 0, 1 = INVALID + // Bit1:0 = BUF1:0 = 1, 0 = DOUBLE + // Bit1:0 = BUF1:0 = 1, 1 = TRIPLE + // Bit2 = 0 + // Bit3 = SIZE, 0 = 512 bytes, 1 = 1024 bytes + // Bit5:4 = TYPE1:0 = 0, 0 = INVALID + // Bit5:4 = TYPE1:0 = 0, 1 = ISO + // Bit5:4 = TYPE1:0 = 1, 0 = BULK (def) + // Bit5:4 = TYPE1:0 = 1, 1 = INT + // Bit6 = DIR, 0 = OUT, 1 = IN + // Bit7 = VALID + // EP2: 10100000 - DIR=OUT, TYPE=BULK, SIZE=512, BUF=QUAD + EP2CFG = 0xA0; SYNCDELAY; + // EP6: 11100000 - DIR=IN, TYPE=BULK, SIZE=512, BUF=QUAD + EP6CFG = 0xE0; SYNCDELAY; + EP4CFG &= ~bmVALID; SYNCDELAY; + EP8CFG &= ~bmVALID; SYNCDELAY; + + RESETFIFOS(); + + /* BULK OUT endpoint EP2 */ + // Bit0 = WORDWIDE + // Bit1 = 0 + // Bit2 = ZEROLENIN + // Bit3 = AUTOIN + // Bit4 = AUTOOUT + // Bit5 = OEP2 + // Bit6 = INFM2 + // Bit7 = 0 /* BULK OUT endpoint EP2 */ - EP2FIFOCFG = 0; SYNCDELAY; + EP2FIFOCFG = 0; SYNCDELAY; EP2FIFOCFG = bmAUTOOUT; SYNCDELAY; EP6FIFOCFG = bmAUTOIN; SYNCDELAY; @@ -133,122 +141,126 @@ void main() * are labelled incorrectly and need to be swapped. */ - // 0xE = EP6 FF - // 0x8 = EP2 EF // FLAGA = Indexed // FLAGB = EP6 FF/CTL1 (Master RDY0) - PINFLAGSAB = 0xE0; SYNCDELAY; + PINFLAGSAB = 0xE0; SYNCDELAY; // FLAGC = EP2 EF/CTL2 (Master RDY1) // FLAGD = Indexed - PINFLAGSCD = 0x08; SYNCDELAY; + PINFLAGSCD = 0x08; SYNCDELAY; + + FIFOPINPOLAR = 0x00; SYNCDELAY; - FIFOPINPOLAR = 0x00; SYNCDELAY; + // enable LEDs as output and light up LED2 + // note: you can verify that the firmware is reaching this stage once + // D2 is lit on the FX2LP board + OEA = PA_LED1|PA_LED2; SYNCDELAY; + IOA = PA_LED2; SYNCDELAY; - OEA = PA_LED2; SYNCDELAY; - IOA = PA_LED2; SYNCDELAY; + delay(10); - delay(10); + EA=1; // global __interrupt enable - EA=1; // global __interrupt enable + printf("entering main loop...\n"); + while(TRUE) { + if (got_sud) { + handle_setupdata(); + got_sud=FALSE; + } + if (EP24FIFOFLGS & EP2EMPTY) + IOA &= ~PA_LED2; + else + IOA |= PA_LED2; - mainloop(); + if (EP68FIFOFLGS & EP6FULL) + IOA &= ~PA_LED1; + else + IOA |= PA_LED1; + } } -#define VC_EPSTAT 0xB1 +/** + * Handle DEBUG descriptor reporting here. + * GET_DESCRIPTOR calls for other descriptor types are passed on + * to _handle_get_descriptor() in setupdat. + */ +BOOL handle_get_descriptor() +{ + BYTE desc_type = SETUPDAT[3]; // wValueH [TRM 2.3.4.1] + + printf("handle_get_descriptor(DT=%d)\n", desc_type); + if (desc_type != DSCR_DEBUG_TYPE) + return FALSE; + + // prepare to send the device debug descriptor [TRM 2.3.4] + SUDPTRH = MSB((WORD)&debug_dscr); + SUDPTRL = LSB((WORD)&debug_dscr); // load SUDPTRL last to initiate transfer + return TRUE; +} + +// this firmware does not implement any vendor commands BOOL handle_vendorcommand(BYTE cmd) { - __xdata BYTE* pep; - switch ( cmd ) { - case 6: - return TRUE; - case VC_EPSTAT: - - pep = ep_addr(SETUPDAT[2]); - if (pep) { - EP0BUF[0] = *pep; - EP0BCH=0; - EP0BCL=1; - return TRUE; - } - default: - } - return FALSE; + printf("handle_vendorcommand(%d)\n", cmd); + + return FALSE; } // this firmware only supports 0,0 -BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc) +BOOL handle_get_interface(BYTE *ifc, BYTE *alt_ifc) { - if (ifc) - return FALSE; - *alt_ifc=0; - return TRUE; -} + printf("handle_get_interface()\n"); + *ifc=0; + *alt_ifc=0; + return TRUE; +} +// this firmware only supports 0,0 BOOL handle_set_interface(BYTE ifc, BYTE alt_ifc) { - if (ifc==1 && alt_ifc==0) { - // SEE TRM 2.3.7 - // reset toggles - RESETTOGGLE(0x02); - RESETTOGGLE(0x86); - - // restore endpoints to default condition - RESETFIFOS(); - EP2FIFOCFG = 0; SYNCDELAY; - EP2FIFOCFG = bmAUTOOUT; SYNCDELAY; -// EP6FIFOCFG = bmAUTOIN; SYNCDELAY; -// EP6AUTOINLENH = 0x00; SYNCDELAY; -// EP6AUTOINLENL = 0x08; SYNCDELAY; - return TRUE; - } else - return FALSE; -} + printf("handle_set_interface(%d, %d)\n", ifc, alt_ifc); -// get/set configuration -BYTE handle_get_configuration() -{ - return 1; + return ((ifc == 0) && (alt_ifc == 0)); } -BOOL handle_get_descriptor(BYTE desc) +// this firmware only supports configuration '1' +BYTE handle_get_configuration() { - if (desc != DSCR_DEBUG_TYPE) - return FALSE; + printf("handle_get_configuration()\n"); - SUDPTRH = MSB((WORD)&debug_dscr); - SUDPTRL = LSB((WORD)&debug_dscr); - return TRUE; + return 1; } - +// this firmware only supports configuration '1' BOOL handle_set_configuration(BYTE cfg) { + printf("handle_set_configuration(%d)\n", cfg); + EP6AUTOINLENH = 0x00; SYNCDELAY; EP6AUTOINLENL = 0x08; SYNCDELAY; - return cfg==1 ? TRUE : FALSE; // we only handle cfg 1 + return (cfg == 1); } - // copied usb jt routines from usbjt.h void sudav_isr() __interrupt SUDAV_ISR { - got_sud = TRUE; - CLEAR_SUDAV(); + got_sud = TRUE; + CLEAR_SUDAV(); } void sof_isr () __interrupt SOF_ISR __using 1 { - CLEAR_SOF(); + CLEAR_SOF(); } void usbreset_isr() __interrupt USBRESET_ISR { - handle_hispeed(FALSE); - CLEAR_USBRESET(); + handle_hispeed(FALSE); + CLEAR_USBRESET(); } void hispeed_isr() __interrupt HISPEED_ISR { - handle_hispeed(TRUE); - CLEAR_HISPEED(); + handle_hispeed(TRUE); + CLEAR_HISPEED(); } + diff --git a/examples/debugdevice_full_duplex/slave/download.sh b/examples/debugdevice_full_duplex/slave/download.sh index 10ce4dc..d458220 100755 --- a/examples/debugdevice_full_duplex/slave/download.sh +++ b/examples/debugdevice_full_duplex/slave/download.sh @@ -9,7 +9,7 @@ fi for dev in $DEVS;do echo "Downloading $1 to $dev" - sudo /sbin/fxload -v -D /dev/bus/usb/$dev -t fx2lp -I $1 -c 0x01 -s /home/administrator/Vend_Ax.hex + sudo /sbin/fxload -v -D /dev/bus/usb/$dev -t fx2lp -I $1 -c 0x01 -s ../vend_ax.hex done exit 0 diff --git a/examples/debugdevice_full_duplex/slave/dscr.a51 b/examples/debugdevice_full_duplex/slave/dscr.a51 index 6246acc..908fd29 100644 --- a/examples/debugdevice_full_duplex/slave/dscr.a51 +++ b/examples/debugdevice_full_duplex/slave/dscr.a51 @@ -15,7 +15,7 @@ ; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ; this is a the default -; full speed and high speed +; high speed only ; descriptors found in the TRM ; change however you want but leave ; the descriptor pointers so the setupdat.c file works right @@ -31,6 +31,7 @@ DSCR_STRING_TYPE=3 DSCR_INTERFACE_TYPE=4 DSCR_ENDPOINT_TYPE=5 DSCR_DEVQUAL_TYPE=6 +DSCR_DEBUG_TYPE=10 ; for the repeating interfaces DSCR_INTERFACE_LEN=9 @@ -49,111 +50,60 @@ ENDPOINT_TYPE_INT=3 .area DSCR_AREA (CODE) _dev_dscr: - .db dev_dscr_end-_dev_dscr ; len - .db DSCR_DEVICE_TYPE ; type - .dw 0x0002 ; usb 2.0 - .db 0x02 ; class (vendor specific) - .db 0x00 ; subclass (vendor specific) - .db 0x00 ; protocol (vendor specific) - .db 0x40 ; packet size (ep0) - .dw 0xb404 ; vendor id - .dw 0x2086 ; product id - .dw 0x0100 ; version id - .db 0x01 ; manufacturure str idx - .db 0x02 ; product str idx - .db 0x00 ; serial str idx - .db 0x01 ; n configurations + .db dev_dscr_end-_dev_dscr ; dscr len + .db DSCR_DEVICE_TYPE + .dw 0x0002 ; usb 2.0 + .db 0x02 ; class (vendor specific) + .db 0x00 ; subclass (vendor specific) + .db 0x00 ; protocol (vendor specific) + .db 0x40 ; packet size (ep0) + .dw 0xb404 ; vendor id + .dw 0x2086 ; product id + .dw 0x0100 ; version id + .db 0x01 ; manufacturure str idx + .db 0x02 ; product str idx + .db 0x00 ; serial str idx + .db 0x01 ; n configurations dev_dscr_end: _dev_qual_dscr: - .db dev_qualdscr_end-_dev_qual_dscr + .db dev_qualdscr_end-_dev_qual_dscr ; dscr len .db DSCR_DEVQUAL_TYPE - .dw 0x0002 ; usb 2.0 - .db 0x2 - .db 0x00 - .db 0x0 - .db 64 ; max packet - .db 1 ; n configs - .db 0 ; extra reserved byte + .dw 0x0002 ; usb 2.0 + .db 0x2 ; + .db 0x00 ; + .db 0x0 ; + .db 64 ; max packet + .db 1 ; n configs + .db 0 ; extra reserved byte dev_qualdscr_end: _debug_dscr: - .db _debug_dscr_end - _debug_dscr - .db 10 - .db 0x86 - .db 0x02 + .db _debug_dscr_end - _debug_dscr ; dscr len + .db DSCR_DEBUG_TYPE + .db 0x86 ; debug IN endpoint + .db 0x02 ; debug OUT endpoint _debug_dscr_end: _highspd_dscr: - .db highspd_dscr_end-_highspd_dscr ; dscr len ;; Descriptor length + .db highspd_dscr_end-_highspd_dscr ; dscr len .db DSCR_CONFIG_TYPE ; can't use .dw because byte order is different .db (highspd_dscr_realend-_highspd_dscr) % 256 ; total length of config lsb .db (highspd_dscr_realend-_highspd_dscr) / 256 ; total length of config msb - .db 2 ; n interfaces + .db 1 ; n interfaces .db 1 ; config number .db 0 ; config string - .db 0x80 ; attrs = bus powered, no wakeup - .db 0x32 ; max power = 100ma + .db 0x80 ; attrs = bus powered, no wakeup + .db 0x32 ; max power = 100ma highspd_dscr_end: ; all the interfaces next -; NOTE the default TRM actually has more alt interfaces -; but you can add them back in if you need them. -; here, we just use the default alt setting 1 from the trm - ; control endpoints - .db DSCR_INTERFACE_LEN - .db DSCR_INTERFACE_TYPE - .db 0x00 ; index - .db 0x00 ; alt setting idx - .db 0x01 ; n endpoints - .db 0x02 ; class - .db 0x02 - .db 0x01 - .db 0x00 ; string index - - ; CDC header - .db 0x05 - .db 0x24 - .db 0x00 - .db 0x10 - .db 0x01 - - ; CDC ACM - .db 0x04 - .db 0x24 - .db 0x02 - .db 0x00 - - ; CDC union - .db 0x05 - .db 0x24 - .db 0x06 - .db 0x00 - .db 0x01 - - ; CDC call managment - .db 0x05 - .db 0x24 - .db 0x01 - .db 0x01 - .db 0x01 - -; endpoint 1 in - .db DSCR_ENDPOINT_LEN - .db DSCR_ENDPOINT_TYPE - .db 0x81 ; ep1 dir=IN and address - .db ENDPOINT_TYPE_INT ; type - .db 0x40 ; max packet LSB - .db 0x00 ; max packet size=512 bytes - .db 0x40 ; polling interval - - - ; data endpoints - .db DSCR_INTERFACE_LEN +; debug device interface + .db DSCR_INTERFACE_LEN ; dscr len .db DSCR_INTERFACE_TYPE - .db 0x01 ; index + .db 0x00 ; index .db 0x00 ; alt setting idx .db 0x02 ; n endpoints .db 0x0a ; class @@ -162,128 +112,49 @@ highspd_dscr_end: .db 0x00 ; string index ; endpoint 2 out - .db DSCR_ENDPOINT_LEN + .db DSCR_ENDPOINT_LEN ; dscr len .db DSCR_ENDPOINT_TYPE .db 0x02 ; ep2 dir=OUT and address - .db ENDPOINT_TYPE_BULK ; type + .db ENDPOINT_TYPE_BULK ; type .db 0x00 ; max packet LSB .db 0x02 ; max packet size=512 bytes .db 0x00 ; polling interval ; endpoint 6 in - .db DSCR_ENDPOINT_LEN + .db DSCR_ENDPOINT_LEN ; dscr len .db DSCR_ENDPOINT_TYPE .db 0x86 ; ep6 dir=in and address - .db ENDPOINT_TYPE_BULK ; type + .db ENDPOINT_TYPE_BULK ; type .db 0x00 ; max packet LSB .db 0x02 ; max packet size=512 bytes .db 0x00 ; polling interval highspd_dscr_realend: +; the (empty) full speed descriptor - this is not needed, as the debug device +; will only be working as high speed device according to EHCI specification .even _fullspd_dscr: - .db fullspd_dscr_end-_fullspd_dscr ; dscr len + .db fullspd_dscr_end-_fullspd_dscr ; dscr len .db DSCR_CONFIG_TYPE ; can't use .dw because byte order is different .db (fullspd_dscr_realend-_fullspd_dscr) % 256 ; total length of config lsb .db (fullspd_dscr_realend-_fullspd_dscr) / 256 ; total length of config msb - .db 2 ; n interfaces - .db 1 ; config number + .db 0 ; n interfaces + .db 0 ; config number .db 0 ; config string - .db 0x80 ; attrs = bus powered, no wakeup - .db 0x32 ; max power = 100ma + .db 0x80 ; attrs = bus powered, no wakeup + .db 0x32 ; max power = 100ma fullspd_dscr_end: - -; all the interfaces next -; NOTE the default TRM actually has more alt interfaces -; but you can add them back in if you need them. -; here, we just use the default alt setting 1 from the trm - .db DSCR_INTERFACE_LEN - .db DSCR_INTERFACE_TYPE - .db 0 ; index - .db 0 ; alt setting idx - .db 2 ; n endpoints - .db 0x2 ; class - .db 0x2 - .db 0x1 - .db 3 ; string index - - ; CDC header - .db 0x05 - .db 0x24 - .db 0x00 - .db 0x10 - .db 0x01 - - ; CDC ACM - .db 0x04 - .db 0x24 - .db 0x02 - .db 0x00 - - ; CDC union - .db 0x05 - .db 0x24 - .db 0x06 - .db 0x00 - .db 0x01 - - ; CDC call managment - .db 0x05 - .db 0x24 - .db 0x01 - .db 0x01 - .db 0x01 - -; endpoint 1 in - .db DSCR_ENDPOINT_LEN - .db DSCR_ENDPOINT_TYPE - .db 0x81 ; ep1 dir=IN and address - .db ENDPOINT_TYPE_INT ; type - .db 0x40 ; max packet LSB - .db 0x00 ; max packet size=512 bytes - .db 0x40 ; polling interval - - - ; data endpoints - .db DSCR_INTERFACE_LEN - .db DSCR_INTERFACE_TYPE - .db 0x01 ; index - .db 0x00 ; alt setting idx - .db 0x02 ; n endpoints - .db 0x0a ; class - .db 0x00 - .db 0x00 - .db 0x00 ; string index - -; endpoint 2 out - .db DSCR_ENDPOINT_LEN - .db DSCR_ENDPOINT_TYPE - .db 0x02 ; ep2 dir=OUT and address - .db ENDPOINT_TYPE_BULK ; type - .db 0x40 ; max packet LSB - .db 0x00 ; max packet size=64 bytes - .db 0x00 ; polling interval - -; endpoint 6 in - .db DSCR_ENDPOINT_LEN - .db DSCR_ENDPOINT_TYPE - .db 0x86 ; ep6 dir=in and address - .db ENDPOINT_TYPE_BULK ; type - .db 0x40 ; max packet LSB - .db 0x00 ; max packet size=64 bytes - .db 0x00 ; polling interval - fullspd_dscr_realend: .even _dev_strings: ; sample string _string0: - .db string0end-_string0 ; len - .db DSCR_STRING_TYPE - .db 0x09, 0x04 ; who knows + .db string0end-_string0 ; len + .db DSCR_STRING_TYPE + .db 0x09, 0x04 ; language (0x0409) English - United States string0end: ; add more strings here @@ -354,3 +225,4 @@ string3end: _dev_strings_end: .dw 0x0000 ; just in case someone passes an index higher than the end to the firmware + diff --git a/examples/debugdevice_full_duplex/terminal.c b/examples/debugdevice_full_duplex/terminal.c index a9d5eef..4bf751b 100644 --- a/examples/debugdevice_full_duplex/terminal.c +++ b/examples/debugdevice_full_duplex/terminal.c @@ -15,6 +15,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **/ +#include #include #include #include @@ -24,130 +25,148 @@ void tp_diff(struct timespec *diff, struct timespec *start, struct timespec *end) { - if (end->tv_nsec - start->tv_nsec < 0) { - diff->tv_sec = end->tv_sec - start->tv_sec - 1; - diff->tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec; - } else { - diff->tv_sec = end->tv_sec - start->tv_sec; - diff->tv_nsec = end->tv_nsec - start->tv_nsec; - } + if (end->tv_nsec - start->tv_nsec < 0) { + diff->tv_sec = end->tv_sec - start->tv_sec - 1; + diff->tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec; + } else { + diff->tv_sec = end->tv_sec - start->tv_sec; + diff->tv_nsec = end->tv_nsec - start->tv_nsec; + } } static int format_timediff(struct timespec *diff, char *out, int outlen) { - if (diff->tv_sec > 1) - return snprintf(out, outlen, "%d.%02lds", (int)diff->tv_sec, - diff->tv_nsec / 10000000); + if (diff->tv_sec > 1) + return snprintf(out, outlen, "%d.%02lds", (int)diff->tv_sec, + diff->tv_nsec / 10000000); - if (diff->tv_nsec > 1000000) - return snprintf(out, outlen, "%ldms", diff->tv_nsec / 1000000); + if (diff->tv_nsec > 1000000) + return snprintf(out, outlen, "%ldms", diff->tv_nsec / 1000000); - if (diff->tv_nsec > 1000) - return snprintf(out, outlen, "%ldus", diff->tv_nsec / 1000); + if (diff->tv_nsec > 1000) + return snprintf(out, outlen, "%ldus", diff->tv_nsec / 1000); - return snprintf(out, outlen, "%ldns", diff->tv_nsec); + return snprintf(out, outlen, "%ldns", diff->tv_nsec); } -static int terminal_loop(libusb_device_handle *hndl, FILE *outfile) -{ - unsigned char buf[512]; - char timebuf[32]; +volatile int exit_terminal = 0; +void handle_sigint(int sig) { + (void)sig; - struct timespec tp, oldtp, diff, lastlinetp, linediff; - unsigned char c; - int print_time = 1; - int len, ret, i; + fflush(stdout); + exit_terminal = 1; +} - if (clock_gettime(CLOCK_MONOTONIC, &oldtp) == -1) { - fprintf(stderr, "clock_gettime: %s\n", strerror(errno)); - return -1; - } +static int terminal_loop(libusb_device_handle *hndl, FILE *outfile) +{ + unsigned char buf[512]; + char timebuf[32]; - memcpy(&lastlinetp, &oldtp, sizeof(lastlinetp)); - for(;;) { - ret = libusb_bulk_transfer(hndl, 0x86, (unsigned char*)buf ,sizeof(buf), &len, sizeof(buf)); + struct timespec tp, oldtp, diff, lastlinetp, linediff; + unsigned char c; + int print_time = 1; + int len, ret, i; - if (ret == -4) { - fprintf(stderr, "device disappeared\n"); - return -1; - } + if (clock_gettime(CLOCK_MONOTONIC, &oldtp) == -1) { + fprintf(stderr, "clock_gettime: %s\n", strerror(errno)); + return -1; + } - if(ret != -7 && ret != 0) { - printf("IN Transfer failed: %d\n", ret); - return -1; - } + memcpy(&lastlinetp, &oldtp, sizeof(lastlinetp)); + while(!exit_terminal) { + ret = libusb_bulk_transfer(hndl, 0x86, buf, sizeof(buf), &len, sizeof(buf)); - for (i = 0; i < len; i++) { + if (ret == -4) { + fprintf(stderr, "\nDevice disappeared - will try to reconnect...\n"); + return -1; + } - if (print_time) { - print_time = 0; - if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) { - fprintf(stderr, "clock_gettime: %s\n", strerror(errno)); - return -1; - } + if(ret != -7 && ret != 0) { + fprintf(stderr, "\nIN Transfer failed: %d\n", ret); + return -1; + } - tp_diff(&diff, &oldtp, &tp); - tp_diff(&linediff, &lastlinetp, &tp); + for (i = 0; i < len; i++) { - format_timediff(&linediff, timebuf, sizeof(timebuf)-1); + if (print_time) { + print_time = 0; + if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) { + fprintf(stderr, "\nclock_gettime: %s\n", strerror(errno)); + return -1; + } - printf("%3d.%03ld [%5s]: ", (int)diff.tv_sec, diff.tv_nsec / 1000000, timebuf); - fprintf(outfile, "%3d.%03ld [%5s]: ", (int)diff.tv_sec, diff.tv_nsec / 1000000, timebuf); + tp_diff(&diff, &oldtp, &tp); + tp_diff(&linediff, &lastlinetp, &tp); - memcpy(&lastlinetp, &tp, sizeof(lastlinetp)); - } + format_timediff(&linediff, timebuf, sizeof(timebuf)-1); - c = buf[i]; + printf("%3d.%03ld [%5s]: ", (int)diff.tv_sec, diff.tv_nsec / 1000000, timebuf); + fprintf(outfile, "%3d.%03ld [%5s]: ", (int)diff.tv_sec, diff.tv_nsec / 1000000, timebuf); - if (c == '\r') - continue; + memcpy(&lastlinetp, &tp, sizeof(lastlinetp)); + } - printf ("%c", c); + c = buf[i]; - print_time = !!(c == '\n'); + if (c == '\r') + continue; + printf ("%c", c); + print_time = !!(c == '\n'); - if (outfile) - fputc(buf[i], outfile); - } - } + if (outfile) + fputc(buf[i], outfile); + } + } + return 0; } int main(int argc __attribute__((unused)), - char **argv __attribute__((unused))) + char **argv __attribute__((unused))) { - FILE *outfile; - libusb_context* ctx; - libusb_device_handle *hndl; + FILE *outfile = NULL; + libusb_context* ctx; + libusb_device_handle *hndl = NULL; - libusb_init(&ctx); + libusb_init(&ctx); + + struct sigaction sa; + sa.sa_handler = handle_sigint; + sigaction(SIGINT, &sa, NULL); + + printf("Waiting for EHCI Debug Master device...\n"); restart: - hndl = libusb_open_device_with_vid_pid(ctx, 0x4b4, 0x8613); - if (!hndl) { -// fprintf(stderr, "failed to open device\n"); - sleep(1); - goto restart; - } + if (exit_terminal) { + goto out; + } + + hndl = libusb_open_device_with_vid_pid(ctx, 0x4b4, 0x8619); + if (!hndl) { + sleep(1); + goto restart; + } + + libusb_detach_kernel_driver(hndl, 1); + libusb_claim_interface(hndl, 1); - libusb_claim_interface(hndl, 0); - libusb_set_interface_alt_setting(hndl, 0, 0); + libusb_set_interface_alt_setting(hndl, 1, 0); - printf("Device opened\n"); + printf("EHCI Debug Master device opened.\n"); - outfile = fopen("debuglog.txt", "w+"); - if (!outfile) { - fprintf(stderr, "fopen: debuglog.txt: %s", strerror(errno)); - goto out; - } + outfile = fopen("debuglog.txt", "w+"); + if (!outfile) { + fprintf(stderr, "fopen: debuglog.txt: %s", strerror(errno)); + goto out; + } - if (terminal_loop(hndl, outfile) == -1) - goto restart; + if (terminal_loop(hndl, outfile) == -1) + goto restart; out: - if (outfile) - fclose(outfile); - libusb_close(hndl); - return 0; + if (outfile) + fclose(outfile); + libusb_close(hndl); + return 0; } diff --git a/examples/debugdevice_full_duplex/test.cpp b/examples/debugdevice_full_duplex/test.cpp index e18c96a..8593da1 100644 --- a/examples/debugdevice_full_duplex/test.cpp +++ b/examples/debugdevice_full_duplex/test.cpp @@ -23,115 +23,172 @@ #define BUFSIZE 256 -int main(int argc __attribute__((unused)), - char **argv __attribute__((unused))) +int main(int argc, char **argv) { - int transferred, rv, i, devmask; - libusb_context* ctx; - unsigned char buf[BUFSIZE]; - libusb_device_handle *hndl[2]; - ssize_t devcount; - struct libusb_device_descriptor desc; + int transferred, rv, i, devmask, errors; + size_t total; + libusb_context* ctx; + unsigned char buf[BUFSIZE]; + libusb_device_handle *hndl[2]; + ssize_t devcount; + struct libusb_device_descriptor desc; - libusb_device **devlist; - libusb_init(&ctx); + (void)argc; + (void)argv; - devcount = libusb_get_device_list(ctx, &devlist); + libusb_device **devlist; + libusb_init(&ctx); + + devcount = libusb_get_device_list(ctx, &devlist); devmask = 0; - printf("looking through: %d devices\n", devcount); - for(i = 0; i < devcount; i++) { - if (libusb_get_device_descriptor(devlist[i], &desc) != 0) - continue; + printf("looking through: %ld devices\n", devcount); + for(i = 0; i < devcount; i++) { + if (libusb_get_device_descriptor(devlist[i], &desc) != 0) + continue; - if (desc.idVendor == 0x04b4 && desc.idProduct == 0x8619) + if (desc.idVendor == 0x04b4 && desc.idProduct == 0x8619) { printf("found %04x:%04x - master device\n", desc.idVendor, desc.idProduct); - if (!(libusb_open(devlist[i], &hndl[0]))) { - printf("opened device %d\n", 0); + if (!(libusb_open(devlist[i], &hndl[0]))) { + printf("opened device %d\n", 0); devmask |= 1; - } - } - if (desc.idVendor == 0x04b4 && desc.idProduct == 0x8620) + } + } + if (desc.idVendor == 0x04b4 && desc.idProduct == 0x8620) { printf("found %04x:%04x - slave device\n", desc.idVendor, desc.idProduct); - if (!(libusb_open(devlist[i], &hndl[1]))) { - printf("opened device %d\n", 1); + if (!(libusb_open(devlist[i], &hndl[1]))) { + printf("opened device %d\n", 1); devmask |= 2; - } - } - } + } + } + } + + if (devmask != 0x3) { + fprintf(stderr, "Need two devices, have %d\n", devmask); + return 1; + } - if (devmask != 0x3) { - fprintf(stderr, "Need two devices, have %d\n", devmask); - return 1; - } + libusb_detach_kernel_driver(hndl[0], 1); + libusb_detach_kernel_driver(hndl[1], 1); - libusb_claim_interface(hndl[0],1); - libusb_claim_interface(hndl[1],1); + rv = libusb_claim_interface(hndl[0],1); + if(rv) { + printf("Claiming interface 0 failed : %d, %s\n", rv, libusb_error_name(rv)); + goto cleanup; + } + rv = libusb_claim_interface(hndl[1],1); + if(rv) { + printf("Claiming interface 1 failed : %d, %s\n", rv, libusb_error_name(rv)); + goto cleanup; + } - libusb_set_interface_alt_setting(hndl[0], 1, 0); - libusb_set_interface_alt_setting(hndl[1], 1, 0); + libusb_set_interface_alt_setting(hndl[0], 1, 0); + libusb_set_interface_alt_setting(hndl[1], 1, 0); - for (i = 0; i < (int)sizeof(buf); i++) - buf[i] = i; + for (i = 0; i < (int)sizeof(buf); i++) + buf[i] = i; - printf("OUT transfer to master, endpoint 2\n"); - rv = libusb_bulk_transfer(hndl[0], 0x02, buf, sizeof(buf), &transferred, sizeof(buf)); + printf("OUT transfer to master, endpoint 2, %ld bytes\n", sizeof(buf)); + rv = libusb_bulk_transfer(hndl[0], 0x02, buf, sizeof(buf), &transferred, sizeof(buf)); - if(rv) - printf("OUT Transfer failed: %d, %s\n", rv, libusb_error_name(rv)); + if(rv) + printf("OUT Transfer failed: %d, %s\n", rv, libusb_error_name(rv)); sleep(1); printf("IN transfer from slave, endpoint 6\n"); - rv = 0; + rv = total = errors = 0; while (!rv) { - memset(buf, 0, sizeof(buf)); - transferred = 0; - - rv=libusb_bulk_transfer(hndl[1], 0x86, (unsigned char*)buf ,sizeof(buf), &transferred, sizeof(buf)); - if(rv) - printf("IN Transfer failed: %d, %s\n", rv, libusb_error_name(rv)); - - printf("received %d bytes:\n", transferred); - - for (i = 0; i < transferred; i++) - printf ("%d: %02x ", i, buf[i]); - printf("\n"); + memset(buf, 0, sizeof(buf)); + transferred = 0; + + rv = libusb_bulk_transfer(hndl[1], 0x86, (unsigned char*)buf,sizeof(buf), &transferred, sizeof(buf)); + if(rv) { + printf("IN Transfer failed: %d, %s\n", rv, libusb_error_name(rv)); + errors++; + break; + } + + printf("received %d bytes [0..%d]: ", transferred, transferred - 1); + for (i = 0; i < transferred; i++) { + if(buf[i] != (total + i)) { + printf("(!)"); + errors++; + } + printf ("0x%02x ", buf[i]); + } + + total += transferred; + printf(" [total=%3ld]\n", total); + + if(total >= sizeof(buf)) + break; } - for (i = 0; i < (int)sizeof(buf); i++) - buf[i] = i; + if(!errors) + printf("transfer slave->master successful!\n"); + else { + printf("transfer slave->master encountered %d errors - aborting!\n", errors); + goto cleanup; + } + + for (i = 0; i < (int)sizeof(buf); i++) + buf[i] = i; - printf("OUT transfer to slave, endpoint 2\n"); - rv = libusb_bulk_transfer(hndl[1], 0x02, buf, sizeof(buf), &transferred, sizeof(buf)); + printf("OUT transfer to slave, endpoint 2, %ld bytes\n", sizeof(buf)); + rv = libusb_bulk_transfer(hndl[1], 0x02, buf, sizeof(buf), &transferred, sizeof(buf)); - if(rv) - printf("OUT Transfer failed: %d\n", rv); + if(rv) + printf("OUT Transfer failed: %d\n", rv); - printf("IN transfer from master, endpoint 6\n"); + printf("IN transfer from master, endpoint 6\n"); - memset(buf, 0, sizeof(buf)); - transferred = 0; + memset(buf, 0, sizeof(buf)); + transferred = 0; - rv = 0; + rv = total = errors = 0; while (!rv) { - rv=libusb_bulk_transfer(hndl[0], 0x86, (unsigned char*)buf ,sizeof(buf), &transferred, sizeof(buf)); - if(rv) - printf("IN Transfer failed: %d\n", rv); - - printf("received %d bytes:\n", transferred); + rv=libusb_bulk_transfer(hndl[0], 0x86, (unsigned char*)buf,sizeof(buf), &transferred, sizeof(buf)); + if(rv) { + printf("IN Transfer failed: %d\n", rv); + errors++; + break; + } + + printf("received %d bytes [0..%d]: ", transferred, transferred - 1); + + for (i = 0; i < transferred; i++) { + if(buf[i] != (total + i)) { + printf("(!)"); + errors++; + } + printf ("0x%02x ", buf[i]); + } + + total += transferred; + printf(" [total=%3ld]\n", total); + + if(total >= sizeof(buf)) + break; + } - for (i = 0; i < transferred; i++) - printf ("%d: %02x ", i, buf[i]); - printf("\n"); + if(!errors) + printf("transfer master->slave successful!\n"); + else { + printf("transfer master->slave encountered %d errors - aborting!\n", errors); + goto cleanup; } - libusb_free_device_list(devlist, 1); - libusb_close(hndl[0]); - libusb_close(hndl[1]); - return 0; + printf("dongle is working properly - happy debugging!\n"); + +cleanup: + libusb_free_device_list(devlist, 1); + libusb_close(hndl[0]); + libusb_close(hndl[1]); + return 0; } +