+#ifdef WIN32_NATIVE
+#include "libnexys.win32.c"
+#else
+#define LIBNEXYS_INTERNAL
+#include "libnexys.h"
+#include <stdio.h>
+#include <usb.h>
+
+#define NEXYS2_VENDOR 0x1443
+#define NEXYS2_DEVICE 0x0005
+
+nexys2_t nexys2_init(void) {
+ struct usb_bus *bus;
+ struct usb_device *dev;
+ usb_dev_handle *udev;
+ int dev_found, ret;
+ unsigned char buf[15];
+
+ usb_init();
+
+ usb_find_busses();
+ usb_find_devices();
+
+ udev = NULL;
+ for (bus = usb_get_busses(); bus && !udev; bus = bus->next)
+ for (dev = bus->devices; dev && !udev; dev = dev->next)
+ if ((dev->descriptor.idVendor == NEXYS2_VENDOR) && (dev->descriptor.idProduct == NEXYS2_DEVICE))
+ udev = usb_open(dev);
+
+ if (!udev)
+ {
+ fprintf(stderr, "nexys2_init: no device found or device open failed\n");
+ return NULL;
+ }
+
+ if (usb_set_configuration(udev, 1) < 0)
+ {
+ fprintf(stderr, "nexys2_init: failed to set configuration 1 -- check your permissions\n");
+ return NULL;
+ }
+
+ if (usb_claim_interface(udev, 0) < 0) /* Needed for libusb on win32. This code somehow crashes win32 libusb/kernel anyway, but... */
+ {
+ fprintf(stderr, "nexys2_init: failed to claim interface 0 -- check your permissions\n");
+ return NULL;
+ }
+
+ if (usb_clear_halt(udev, 0x01) < 0) /* Sometimes the board locks up when you close it, so send this. */
+ {
+ fprintf(stderr, "nexys2_init: failed to clear halt on interface 0x01\n");
+ return NULL;
+ }
+
+ ret = usb_control_msg(udev, 0x00, 0x09, 1, 0, NULL, 0, 1000);
+ if (ret < 0)
+ {
+ fprintf(stderr, "nexys2_init: failed to send setup control message\n");
+ return NULL;
+ }
+
+ ret = usb_control_msg(udev, 0xC0, 0xE4, 0, 0, buf, 14, 1000);
+ if (ret < 0)
+ {
+ fprintf(stderr, "nexys2_init: failed to send serial number control message\n");
+ return NULL;
+ }
+
+ buf[ret] = 0;
+ fprintf(stderr, "nexys2_init: got serial number \"%s\" (%d bytes)\n", buf, ret);
+
+ ret = usb_control_msg(udev, 0xC0, 0xE6, 0, 0, buf, 4, 1000);
+ if (ret < 0)
+ {
+ fprintf(stderr, "nexys2_init: failed to send magic goo message\n");
+ return NULL;
+ }
+ if (memcmp(buf, "\x01\x00\x02\x00", 4))
+ {
+ fprintf(stderr, "nexys2_init: magic goo did not return what we expected (%d, %02x %02x %02x %02x)\n", ret, buf[0], buf[1], buf[2], buf[3]);
+ return NULL;
+ }
+
+ return udev;
+}
+
+static unsigned char common_response[64] =
+ { 0x00, 0x03, 0xf3, 0x77, 0x9f, 0xf5, 0xdf, 0xdd,
+ 0xdf, 0xfe, 0x5f, 0xac, 0xff, 0xad, 0xf3, 0x34,
+ 0xaf, 0xf5, 0xac, 0xf7, 0xca, 0xb7, 0xf7, 0x6f,
+ 0xff, 0x5e, 0x5e, 0xf7, 0xfb, 0xfd, 0xfb, 0x37,
+ 0x81, 0x53, 0xbf, 0x64, 0x59, 0x47, 0x59, 0x2d,
+ 0xe8, 0x30, 0x77, 0xda, 0x4f, 0xaf, 0x7f, 0xd7,
+ 0x5f, 0xee, 0xc7, 0x3b, 0xdf, 0x3e, 0xbf, 0x35,
+ 0xd1, 0xdf, 0xef, 0x3f, 0x9f, 0xde, 0xfa, 0xe2
+ };
+
+int nexys2_jtag_enable(usb_dev_handle *udev)
+{
+ int ret;
+ unsigned char message[64] =
+ { 0x07, 0x01, 0x00, 0x00, 0xdc, 0xff, 0xd3, 0x00,
+ 0xf3, 0x99, 0x83, 0x7c, 0x08, 0x26, 0x80, 0x7c,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x26, 0x80, 0x7c,
+ 0xf1, 0xe2, 0x90, 0x7c, 0xb7, 0x24, 0x80, 0x7c,
+ 0x14, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2a, 0x95, 0x80, 0x7c, 0x5b, 0x3d, 0x00, 0x11,
+ 0x14, 0x07, 0x00, 0x00, 0xe8, 0x22, 0xa0, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xb3, 0x9e, 0x01, 0x11 /* XXX does this need to be sequenced? */
+ };
+ unsigned char resp[64];
+
+ if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+ {
+ fprintf(stderr, "nexys2_jtag_enable: write failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+
+ if ((ret = usb_bulk_read(udev, 0x81, resp, 64, 1000)) < 64)
+ {
+ fprintf(stderr, "nexys2_jtag_enable: short read on response: %d\n", ret);
+ return -1;
+ }
+
+ if (memcmp(resp, common_response, 64))
+ {
+ fprintf(stderr, "nexys2_jtag_enable: incorrect response?\n");
+// return -1;
+ }
+
+ return 0;
+}
+
+int nexys2_jtag_disable(usb_dev_handle *udev)
+{
+ int ret;
+ unsigned char message[64] =
+ { 0x07, 0x00, 0xf3, 0x76, 0xdc, 0xff, 0xd3, 0x00,
+ 0xf3, 0x99, 0x83, 0x7c, 0x08, 0x26, 0x80, 0x7c,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x26, 0x80, 0x7c,
+ 0xf1, 0xe2, 0x90, 0x7c, 0xb7, 0x24, 0x80, 0x7c,
+ 0x14, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2a, 0x95, 0x80, 0x7c, 0x5b, 0x3d, 0x00, 0x11,
+ 0x14, 0x07, 0x00, 0x00, 0xe8, 0x22, 0xa0, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0xb3, 0x9e, 0x01, 0x11 /* XXX does this need to be sequenced? */
+ };
+ unsigned char resp[64];
+
+ if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+ {
+ fprintf(stderr, "nexys2_jtag_disable: write failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+
+ if ((ret = usb_bulk_read(udev, 0x81, resp, 64, 1000)) < 64)
+ {
+ fprintf(stderr, "nexys2_jtag_disable: short read on response: %d\n", ret);
+ return -1;
+ }
+
+ if (memcmp(resp, common_response, 64))
+ {
+ fprintf(stderr, "nexys2_jtag_disable: incorrect response?\n");
+// return -1;
+ }
+
+ return 0;
+}
+
+int nexys2_jtag_setbits(usb_dev_handle *udev, int tms, int tdi, int tck)
+{
+ int ret;
+ unsigned char message[64] =
+ { 0x08, !!tms, !!tdi, !!tck, 0xdc, 0xff, 0xd3, 0x00,
+ 0xf3, 0x99, 0x83, 0x7c, 0x08, 0x26, 0x80, 0x7c,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x26, 0x80, 0x7c,
+ 0xf1, 0xe2, 0x90, 0x7c, 0xb7, 0x24, 0x80, 0x7c,
+ 0x14, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2a, 0x95, 0x80, 0x7c, 0x5b, 0x3d, 0x00, 0x11,
+ 0x14, 0x07, 0x00, 0x00, 0xe8, 0x22, 0xa0, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xb3, 0x9e, 0x01, 0x11 /* XXX does this need to be sequenced? */
+ };
+ unsigned char resp[64];
+
+ if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+ {
+ fprintf(stderr, "nexys2_jtag_setbits: write failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+
+/* if ((ret = usb_bulk_read(udev, 0x81, resp, 64, 1000)) < 64)
+ {
+ fprintf(stderr, "nexys2_jtag_setbits: short read on response: %d\n", ret);
+ return -1;
+ }
+
+ if (memcmp(resp, common_response, 64))
+ {
+ fprintf(stderr, "nexys2_jtag_setbits: incorrect response?\n");
+ return -1;
+ }*/
+
+ return 0;
+}
+
+int nexys2_jtag_puttdi(usb_dev_handle *udev, int tms, int nbits, unsigned char *bits, unsigned char *obits)
+{
+ int wanttdo = obits ? 1 : 0;
+ int bytesrem;
+ int ret;
+
+ unsigned char message[64] =
+ { 0x09, wanttdo, !!tms, 0x00, 0x00, (nbits >> 8) & 0xFF, nbits & 0xFF, 0x7C,
+ 0xeb, 0x06, 0x91, 0x7c, 0x28, 0xfa, 0xd3, 0x00,
+ 0xec, 0xfc, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ if (nbits > 0xFFFF)
+ {
+ fprintf(stderr, "nexys2_jtag_puttdi: too many bits!\n");
+ return -1;
+ }
+
+ if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+ {
+ fprintf(stderr, "nexys2_jtag_puttdi: write failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+
+ bytesrem = nbits / 8 + ((nbits % 8) != 0);
+ while (bytesrem)
+ {
+ int nbytes = (bytesrem > 512) ? 512 : bytesrem;
+ if ((ret = usb_bulk_write(udev, 0x02, bits, nbytes, 1000)) < nbytes)
+ {
+ fprintf(stderr, "nexys2_jtag_puttdi: data write failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+ bits += nbytes;
+ bytesrem -= nbytes;
+ }
+
+ if (obits)
+ {
+ bytesrem = nbits / 8 + ((nbits % 8) != 0);
+ while (bytesrem)
+ {
+ int nbytes = (bytesrem > 512) ? 512 : bytesrem;
+ if ((ret = usb_bulk_read(udev, 0x86, obits, nbytes, 1000)) < nbytes)
+ {
+ fprintf(stderr, "nexys2_jtag_puttdi: data read failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+ obits += nbytes;
+ bytesrem -= nbytes;
+ }
+ }
+
+ return 0;
+}
+
+int nexys2_jtag_puttmstdi(usb_dev_handle *udev, int nbits, unsigned char *bits, unsigned char *obits)
+{
+ int wanttdo = obits ? 1 : 0;
+ int bytesrem;
+ int ret;
+
+ unsigned char message[64] =
+ { 0x0a, wanttdo, 0x00, 0x00, (nbits >> 8) & 0xFF, nbits & 0xFF, 0x91, 0x7C,
+ 0xeb, 0x06, 0x91, 0x7c, 0x28, 0xfa, 0xd3, 0x00,
+ 0xec, 0xfc, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ if (nbits > 0xFFFF)
+ {
+ fprintf(stderr, "nexys2_jtag_puttmstdi: too many bits!\n");
+ return -1;
+ }
+
+ if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+ {
+ fprintf(stderr, "nexys2_jtag_puttmstdi: write failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+
+ bytesrem = nbits / 4 + ((nbits % 4) != 0);
+ while (bytesrem)
+ {
+ int nbytes = (bytesrem > 512) ? 512 : bytesrem;
+ if ((ret = usb_bulk_write(udev, 0x02, bits, nbytes, 1000)) < nbytes)
+ {
+ fprintf(stderr, "nexys2_jtag_puttmstdi: data write failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+ if (obits)
+ {
+ int nrbytes = nbytes/2 + (nbytes % 2);
+ if ((ret = usb_bulk_read(udev, 0x86, obits, nrbytes, 1000)) < nrbytes)
+ {
+ fprintf(stderr, "nexys2_jtag_puttmstdi: data read failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+ obits += nrbytes;
+ }
+ bits += nbytes;
+ bytesrem -= nbytes;
+ }
+
+ return 0;
+}
+
+int nexys2_jtag_gettdo(usb_dev_handle *udev, int tdi, int tms, int nbits, unsigned char *obits)
+{
+ int wanttdo = obits ? 1 : 0;
+ int bytesrem;
+ int ret;
+
+ unsigned char message[64] =
+ { 0x0B, !!tdi, !!tms, 0x00, 0x00, (nbits >> 8) & 0xFF, nbits & 0xFF, 0x7C,
+ 0xeb, 0x06, 0x91, 0x7c, 0x28, 0xfa, 0xd3, 0x00,
+ 0xec, 0xfc, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ if (nbits > 0xFFFF)
+ {
+ fprintf(stderr, "nexys2_jtag_puttdo: too many bits!\n");
+ return -1;
+ }
+
+ if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+ {
+ fprintf(stderr, "nexys2_jtag_gettdo: write failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+
+ bytesrem = nbits / 8 + ((nbits % 8) != 0);
+ while (bytesrem)
+ {
+ int nbytes = (bytesrem > 512) ? 512 : bytesrem;
+ if ((ret = usb_bulk_read(udev, 0x86, obits, nbytes, 1000)) < nbytes)
+ {
+ fprintf(stderr, "nexys2_jtag_gettdo: data read failed: %d (%s)\n", ret, usb_strerror());
+ return -1;
+ }
+ obits += nbytes;
+ bytesrem -= nbytes;
+ }
+
+ return 0;
+}
+
+#endif
+
+#ifdef TEST_DRIVER
+
+void poke_idcode(nexys2_t nexys)
+{
+ unsigned char seq1[] = { 0xaa, 0x22};
+ unsigned char seq2[] = { 0xaa, 0x02};
+ unsigned int idcode = 0;
+
+// while(1)
+ {
+ while (nexys2_jtag_enable(nexys) < 0)
+ ;
+ if (nexys2_jtag_puttmstdi(nexys, 8, seq1, NULL) < 0)
+ return;
+ do
+ {
+ if (nexys2_jtag_gettdo(nexys, 0, 0, 32, &idcode) < 0)
+ return;
+ printf("IDCODE: %08x\n", idcode);
+ } while(idcode && (idcode != 0xFFFFFFFF));
+ if (nexys2_jtag_puttmstdi(nexys, 8, seq2, NULL) < 0)
+ return;
+ if (nexys2_jtag_disable(nexys) < 0)
+ return;
+ }
+}
+
+void main()
+{
+ nexys2_t nexys;
+ nexys = nexys2_init();
+ if (!nexys)
+ return;
+ poke_idcode(nexys);
+}
+
+#endif
+