icE1usb fw: Cleanup USB code a bit

Some of it was written before some of the helpers were provided
by the no2usb code and was never update. So instead of manually
setting up a bunch of stuff we make proper use of some of the provided
helpers.

Side effects:

 - We recall e1_init(0,0) when enabling which happens to work
   around a bug ... proper fix coming later.

 - The 'dual BD' config for EP 0x81 and 0x83 is fixed. It didn't
   matter before since we overwrote it anyway, but now it's used
   and so needs to be correct.

 - The descriptors don't have the isoc endpoints at all in the
   "OFF" alt setting.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Change-Id: I33c92896acfba023abe0152d63dff3afe43b53cd
diff --git a/firmware/ice40-riscv/icE1usb/usb_e1.c b/firmware/ice40-riscv/icE1usb/usb_e1.c
index e180fec..b4d8839 100644
--- a/firmware/ice40-riscv/icE1usb/usb_e1.c
+++ b/firmware/ice40-riscv/icE1usb/usb_e1.c
@@ -71,8 +71,7 @@
 		val -= 256;
 
 	/* Prepare buffer */
-	usb_data_write(64, &val, 4);
-	usb_ep_regs[1].in.bd[0].ptr = 64;
+	usb_data_write(usb_ep_regs[1].in.bd[0].ptr, &val, 4);
 	usb_ep_regs[1].in.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(3);
 }
 
@@ -189,33 +188,6 @@
 	}
 }
 
-static const struct usb_intf_desc *
-_find_intf(const struct usb_conf_desc *conf, uint8_t idx)
-{
-	const struct usb_intf_desc *intf = NULL;
-	const void *sod, *eod;
-
-	if (!conf)
-		return NULL;
-
-	sod = conf;
-	eod = sod + conf->wTotalLength;
-
-	while (1) {
-		sod = usb_desc_find(sod, eod, USB_DT_INTF);
-		if (!sod)
-			break;
-
-		intf = (void*)sod;
-		if (intf->bInterfaceNumber == idx)
-			return intf;
-
-		sod = usb_desc_next(sod);
-	}
-
-	return NULL;
-}
-
 static enum usb_fnd_resp
 _e1_set_conf(const struct usb_conf_desc *conf)
 {
@@ -225,16 +197,16 @@
 	if (!conf)
 		return USB_FND_SUCCESS;
 
-	intf = _find_intf(conf, 0);
+	intf = usb_desc_find_intf(conf, 0, 0, NULL);
 	if (!intf)
 		return USB_FND_ERROR;
 
 	printf("e1 set_conf %08x\n", intf);
 
 	usb_ep_boot(intf, 0x01, true);
-	usb_ep_boot(intf, 0x81, true);
+	usb_ep_boot(intf, 0x81, false);
 	usb_ep_boot(intf, 0x82, true);
-	usb_ep_boot(intf, 0x83, true);
+	usb_ep_boot(intf, 0x83, false);
 
 	return USB_FND_SUCCESS;
 }
@@ -257,76 +229,50 @@
 static enum usb_fnd_resp
 _e1_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
 {
+	/* Validity checks */
 	if (base->bInterfaceNumber != 0)
 		return USB_FND_CONTINUE;
 
-	switch (sel->bAlternateSetting) {
-	case 0:
-		if (!g_usb_e1.running)
-			return USB_FND_SUCCESS;
+	if (sel->bAlternateSetting > 1)
+		return USB_FND_ERROR;
 
-		/* disable E1 rx/tx */
+	/* Don't do anything if no change */
+	if (g_usb_e1.running == (sel->bAlternateSetting != 0))
+		return USB_FND_SUCCESS;
+
+	g_usb_e1.running = (sel->bAlternateSetting != 0);
+
+	/* Reconfigure the endpoints */
+	usb_ep_reconf(sel, 0x01);
+	usb_ep_reconf(sel, 0x81);
+	usb_ep_reconf(sel, 0x82);
+	usb_ep_reconf(sel, 0x83);
+
+	/* Update E1 and USB state */
+	switch (g_usb_e1.running) {
+	case false:
+		/* Disable E1 rx/tx */
 		e1_init(0, 0);
-
-		/* EP1 OUT */
-		usb_ep_regs[1].out.bd[0].csr = 0;
-		usb_ep_regs[1].out.bd[1].csr = 0;
-
-		/* EP1 IN (feedback) */
-		usb_ep_regs[1].in.bd[0].csr = 0;
-
-		/* EP2 IN (data) */
-		usb_ep_regs[2].in.bd[0].csr = 0;
-		usb_ep_regs[2].in.bd[1].csr = 0;
-
-		/* EP3 IN: Interrupt */
-		usb_ep_regs[3].in.bd[0].csr = 0;
-
-		g_usb_e1.running = false;
 		break;
-	case 1:
-		/* Hack to avoid re-setting while running ... avoid BD desync */
-		if (g_usb_e1.running)
-			return USB_FND_SUCCESS;
 
+	case true:
+		/* Reset and Re-Enable E1 */
+		e1_init(0, 0);
 		_perform_rx_config();
 		_perform_tx_config();
 
-		g_usb_e1.running = true;
-
-		/* Configure EP1 OUT / EP2 IN */
-		usb_ep_regs[1].out.status = USB_EP_TYPE_ISOC | USB_EP_BD_DUAL;	/* Type=Isochronous, dual buffered */
-		usb_ep_regs[2].in.status  = USB_EP_TYPE_ISOC | USB_EP_BD_DUAL;	/* Type=Isochronous, dual buffered */
-
-		/* Configure EP1 IN (feedback) */
-		usb_ep_regs[1].in.status  = USB_EP_TYPE_ISOC; /* Type=Isochronous, single buffered */
-
-		/* EP2 IN: Prepare two buffers */
+		/* Reset BDI */
 		g_usb_e1.in_bdi = 0;
-		usb_ep_regs[2].in.bd[0].ptr = 1024;
-		usb_ep_regs[2].in.bd[0].csr = 0;
-
-		usb_ep_regs[2].in.bd[1].ptr = 1536;
-		usb_ep_regs[2].in.bd[1].csr = 0;
+		g_usb_e1.out_bdi = 0;
 
 		/* EP1 OUT: Queue two buffers */
-		g_usb_e1.out_bdi = 0;
-		usb_ep_regs[1].out.bd[0].ptr = 1024;
 		usb_ep_regs[1].out.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(388);
-
-		usb_ep_regs[1].out.bd[1].ptr = 1536;
 		usb_ep_regs[1].out.bd[1].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(388);
 
 		/* EP1 IN: Queue buffer */
 		_usb_fill_feedback_ep();
 
-		/* EP3 IN: Interrupt */
-		usb_ep_regs[3].in.status = USB_EP_TYPE_INT;
-		usb_ep_regs[3].in.bd[0].ptr = 68;
-		usb_ep_regs[3].in.bd[0].csr = 0;
 		break;
-	default:
-		return USB_FND_ERROR;
 	}
 
 	return USB_FND_SUCCESS;