You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					511 lines
				
				15 KiB
			
		
		
			
		
	
	
					511 lines
				
				15 KiB
			| 
								 
											9 years ago
										 
									 | 
							
								// **** supporting defines ****
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  __IO uint32_t HPRT;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								USB_OTG_HostPortTypeDef;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define USBx_HOST       ((USB_OTG_HostTypeDef *)((uint32_t)USBx + USB_OTG_HOST_BASE))
							 | 
						||
| 
								 | 
							
								#define USBx_HOST_PORT  ((USB_OTG_HostPortTypeDef *)((uint32_t)USBx + USB_OTG_HOST_PORT_BASE))
							 | 
						||
| 
								 | 
							
								#define USBx_DEVICE     ((USB_OTG_DeviceTypeDef *)((uint32_t)USBx + USB_OTG_DEVICE_BASE))
							 | 
						||
| 
								 | 
							
								#define USBx_INEP(i)    ((USB_OTG_INEndpointTypeDef *)((uint32_t)USBx + USB_OTG_IN_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE))        
							 | 
						||
| 
								 | 
							
								#define USBx_OUTEP(i)   ((USB_OTG_OUTEndpointTypeDef *)((uint32_t)USBx + USB_OTG_OUT_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE))        
							 | 
						||
| 
								 | 
							
								#define USBx_DFIFO(i)   *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_FIFO_BASE + (i) * USB_OTG_FIFO_SIZE)
							 | 
						||
| 
								 | 
							
								#define USBx_PCGCCTL    *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_PCGCCTL_BASE)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_GET_STATUS                             0x00
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_CLEAR_FEATURE                          0x01
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_SET_FEATURE                            0x03
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_SET_ADDRESS                            0x05
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_GET_DESCRIPTOR                         0x06
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_SET_DESCRIPTOR                         0x07
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_GET_CONFIGURATION                      0x08
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_SET_CONFIGURATION                      0x09
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_GET_INTERFACE                          0x0A
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_SET_INTERFACE                          0x0B
							 | 
						||
| 
								 | 
							
								#define  USB_REQ_SYNCH_FRAME                            0x0C
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define  USB_DESC_TYPE_DEVICE                              1
							 | 
						||
| 
								 | 
							
								#define  USB_DESC_TYPE_CONFIGURATION                       2
							 | 
						||
| 
								 | 
							
								#define  USB_DESC_TYPE_STRING                              3
							 | 
						||
| 
								 | 
							
								#define  USB_DESC_TYPE_INTERFACE                           4
							 | 
						||
| 
								 | 
							
								#define  USB_DESC_TYPE_ENDPOINT                            5
							 | 
						||
| 
								 | 
							
								#define  USB_DESC_TYPE_DEVICE_QUALIFIER                    6
							 | 
						||
| 
								 | 
							
								#define  USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION           7
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define STS_GOUT_NAK                           1
							 | 
						||
| 
								 | 
							
								#define STS_DATA_UPDT                          2
							 | 
						||
| 
								 | 
							
								#define STS_XFER_COMP                          3
							 | 
						||
| 
								 | 
							
								#define STS_SETUP_COMP                         4
							 | 
						||
| 
								 | 
							
								#define STS_SETUP_UPDT                         6
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define USBD_FS_TRDT_VALUE           5
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// interfaces
							 | 
						||
| 
								 | 
							
								void usb_cb_control_msg();
							 | 
						||
| 
								 | 
							
								void usb_cb_ep1_in(int len);
							 | 
						||
| 
								 | 
							
								void usb_cb_ep2_out(uint8_t *usbdata, int len);
							 | 
						||
| 
								 | 
							
								void usb_cb_ep3_out(uint8_t *usbdata, int len);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint8_t device_desc[] = {
							 | 
						||
| 
								 | 
							
								  0x12,0x01,0x00,0x01,
							 | 
						||
| 
								 | 
							
								  0xFF,0xFF,0xFF,0x40,
							 | 
						||
| 
								 | 
							
								  (USB_VID>>0)&0xFF,(USB_VID>>8)&0xFF,
							 | 
						||
| 
								 | 
							
								  (USB_PID>>0)&0xFF,(USB_PID>>8)&0xFF,
							 | 
						||
| 
								 | 
							
								  0x00,0x22,0x00,0x00,
							 | 
						||
| 
								 | 
							
								  0x00,0x01};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint8_t configuration_desc[] = {
							 | 
						||
| 
								 | 
							
								  0x09, 0x02, 0x27, 0x00,
							 | 
						||
| 
								 | 
							
								  0x01, 0x01, 0x00, 0xc0,
							 | 
						||
| 
								 | 
							
								  0x32,
							 | 
						||
| 
								 | 
							
								  // interface 0
							 | 
						||
| 
								 | 
							
								  0x09, 0x04, 0x00, 0x00,
							 | 
						||
| 
								 | 
							
								  0x03, 0xff, 0xFF, 0xFF,
							 | 
						||
| 
								 | 
							
								  0x00,
							 | 
						||
| 
								 | 
							
								  // endpoint 1, read CAN
							 | 
						||
| 
								 | 
							
								  0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00,
							 | 
						||
| 
								 | 
							
								  // endpoint 2, AES load
							 | 
						||
| 
								 | 
							
								  0x07, 0x05, 0x02, 0x02, 0x10, 0x00, 0x00,
							 | 
						||
| 
								 | 
							
								  // endpoint 3, send CAN
							 | 
						||
| 
								 | 
							
								  0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef union
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  uint16_t w;
							 | 
						||
| 
								 | 
							
								  struct BW
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    uint8_t msb;
							 | 
						||
| 
								 | 
							
								    uint8_t lsb;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  bw; 
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								uint16_t_uint8_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef union _USB_Setup
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  uint32_t d8[2];
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  struct _SetupPkt_Struc
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    uint8_t           bmRequestType;
							 | 
						||
| 
								 | 
							
								    uint8_t           bRequest;
							 | 
						||
| 
								 | 
							
								    uint16_t_uint8_t  wValue;
							 | 
						||
| 
								 | 
							
								    uint16_t_uint8_t  wIndex;
							 | 
						||
| 
								 | 
							
								    uint16_t_uint8_t  wLength;
							 | 
						||
| 
								 | 
							
								  } b;
							 | 
						||
| 
								 | 
							
								} 
							 | 
						||
| 
								 | 
							
								USB_Setup_TypeDef; 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// current packet
							 | 
						||
| 
								 | 
							
								USB_Setup_TypeDef setup;
							 | 
						||
| 
								 | 
							
								uint8_t usbdata[0x100];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// packet read and write
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void *USB_ReadPacket(void *dest, uint16_t len) {
							 | 
						||
| 
								 | 
							
								  uint32_t i=0; 
							 | 
						||
| 
								 | 
							
								  uint32_t count32b = (len + 3) / 4; 
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  for ( i = 0; i < count32b; i++, dest += 4 ) {
							 | 
						||
| 
								 | 
							
								    // packed?
							 | 
						||
| 
								 | 
							
								    *(__attribute__((__packed__)) uint32_t *)dest = USBx_DFIFO(0);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return ((void *)dest);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void USB_WritePacket(const uint8_t *src, uint16_t len, uint32_t ep) {
							 | 
						||
| 
								 | 
							
								  #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								    puts("writing ");
							 | 
						||
| 
								 | 
							
								    hexdump(src, len);
							 | 
						||
| 
								 | 
							
								  #endif
							 | 
						||
| 
								 | 
							
								  uint32_t count32b = 0, i = 0;
							 | 
						||
| 
								 | 
							
								  count32b = (len + 3) / 4; 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // bullshit
							 | 
						||
| 
								 | 
							
								  USBx_INEP(ep)->DIEPTSIZ = (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) | (len & USB_OTG_DIEPTSIZ_XFRSIZ);
							 | 
						||
| 
								 | 
							
								  USBx_INEP(ep)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // load the FIFO
							 | 
						||
| 
								 | 
							
								  for (i = 0; i < count32b; i++, src += 4) {
							 | 
						||
| 
								 | 
							
								    USBx_DFIFO(ep) = *((__attribute__((__packed__)) uint32_t *)src);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void usb_reset() {
							 | 
						||
| 
								 | 
							
								  // unmask endpoint interrupts, so many sets
							 | 
						||
| 
								 | 
							
								  USBx_DEVICE->DAINT = 0xFFFFFFFF;
							 | 
						||
| 
								 | 
							
								  USBx_DEVICE->DAINTMSK = 0xFFFFFFFF;
							 | 
						||
| 
								 | 
							
								  //USBx_DEVICE->DOEPMSK = (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
							 | 
						||
| 
								 | 
							
								  //USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM | USB_OTG_DIEPMSK_ITTXFEMSK);
							 | 
						||
| 
								 | 
							
								  //USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // all interrupts for debugging
							 | 
						||
| 
								 | 
							
								  USBx_DEVICE->DIEPMSK = 0xFFFFFFFF;
							 | 
						||
| 
								 | 
							
								  USBx_DEVICE->DOEPMSK = 0xFFFFFFFF;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // clear interrupts
							 | 
						||
| 
								 | 
							
								  USBx_INEP(0)->DIEPINT = 0xFF;
							 | 
						||
| 
								 | 
							
								  USBx_OUTEP(0)->DOEPINT = 0xFF;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // unset the address
							 | 
						||
| 
								 | 
							
								  USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // set up USB FIFOs
							 | 
						||
| 
								 | 
							
								  // RX start address is fixed to 0
							 | 
						||
| 
								 | 
							
								  USBx->GRXFSIZ = 0x40;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // 0x100 to offset past GRXFSIZ
							 | 
						||
| 
								 | 
							
								  USBx->DIEPTXF0_HNPTXFSIZ = (0x40 << 16) | 0x40;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // EP1, massive
							 | 
						||
| 
								 | 
							
								  USBx->DIEPTXF[0] = (0x40 << 16) | 0x80;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // flush TX fifo
							 | 
						||
| 
								 | 
							
								  USBx->GRSTCTL = USB_OTG_GRSTCTL_TXFFLSH | USB_OTG_GRSTCTL_TXFNUM_4;
							 | 
						||
| 
								 | 
							
								  while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH);
							 | 
						||
| 
								 | 
							
								  // flush RX FIFO
							 | 
						||
| 
								 | 
							
								  USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
							 | 
						||
| 
								 | 
							
								  while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // no global NAK
							 | 
						||
| 
								 | 
							
								  USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // ready to receive setup packets
							 | 
						||
| 
								 | 
							
								  USBx_OUTEP(0)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) | (3 * 8);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void usb_setup() {
							 | 
						||
| 
								 | 
							
								  uint8_t resp[0x20];
							 | 
						||
| 
								 | 
							
								  // setup packet is ready
							 | 
						||
| 
								 | 
							
								  switch (setup.b.bRequest) {
							 | 
						||
| 
								 | 
							
								    case USB_REQ_SET_CONFIGURATION:
							 | 
						||
| 
								 | 
							
								      // enable other endpoints, has to be here?
							 | 
						||
| 
								 | 
							
								      USBx_INEP(1)->DIEPCTL = (0x40 & USB_OTG_DIEPCTL_MPSIZ) | (2 << 18) | (1 << 22) |
							 | 
						||
| 
								 | 
							
								                              USB_OTG_DIEPCTL_SD0PID_SEVNFRM | USB_OTG_DIEPCTL_USBAEP;
							 | 
						||
| 
								 | 
							
								      USBx_INEP(1)->DIEPINT = 0xFF;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(2)->DOEPTSIZ = (1 << 19) | 0x10;
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(2)->DOEPCTL = (0x10 & USB_OTG_DOEPCTL_MPSIZ) | (2 << 18) |
							 | 
						||
| 
								 | 
							
								                               USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP;
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(2)->DOEPINT = 0xFF;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40;
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(3)->DOEPCTL = (0x40 & USB_OTG_DOEPCTL_MPSIZ) | (2 << 18) |
							 | 
						||
| 
								 | 
							
								                               USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP;
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(3)->DOEPINT = 0xFF;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // mark ready to receive
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(2)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      USB_WritePacket(0, 0, 0);
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case USB_REQ_SET_ADDRESS:
							 | 
						||
| 
								 | 
							
								      // set now?
							 | 
						||
| 
								 | 
							
								      USBx_DEVICE->DCFG |= ((setup.b.wValue.w & 0x7f) << 4);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								        puts(" set address\n");
							 | 
						||
| 
								 | 
							
								      #endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      USB_WritePacket(0, 0, 0);
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case USB_REQ_GET_DESCRIPTOR:
							 | 
						||
| 
								 | 
							
								      switch (setup.b.wValue.bw.lsb) {
							 | 
						||
| 
								 | 
							
								        case USB_DESC_TYPE_DEVICE:
							 | 
						||
| 
								 | 
							
								          //puts("    writing device descriptor\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // setup transfer
							 | 
						||
| 
								 | 
							
								          USB_WritePacket(device_desc, min(sizeof(device_desc), setup.b.wLength.w), 0);
							 | 
						||
| 
								 | 
							
								          USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          //puts("D");
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        case USB_DESC_TYPE_CONFIGURATION:
							 | 
						||
| 
								 | 
							
								          USB_WritePacket(configuration_desc, min(sizeof(configuration_desc), setup.b.wLength.w), 0);
							 | 
						||
| 
								 | 
							
								          USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        default:
							 | 
						||
| 
								 | 
							
								          // nothing here?
							 | 
						||
| 
								 | 
							
								          USB_WritePacket(0, 0, 0);
							 | 
						||
| 
								 | 
							
								          USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case USB_REQ_GET_STATUS:
							 | 
						||
| 
								 | 
							
								      // empty resp?
							 | 
						||
| 
								 | 
							
								      resp[0] = 0;
							 | 
						||
| 
								 | 
							
								      resp[1] = 0;
							 | 
						||
| 
								 | 
							
								      USB_WritePacket((void*)&resp, 2, 0);
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      usb_cb_control_msg();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void usb_init() {
							 | 
						||
| 
								 | 
							
								  // internal PHY set before reset
							 | 
						||
| 
								 | 
							
								  USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // full speed PHY, do reset and remove power down
							 | 
						||
| 
								 | 
							
								  puth(USBx->GRSTCTL);
							 | 
						||
| 
								 | 
							
								  puts(" resetting PHY\n");
							 | 
						||
| 
								 | 
							
								  while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0);
							 | 
						||
| 
								 | 
							
								  puts("AHB idle\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // reset PHY here?
							 | 
						||
| 
								 | 
							
								  USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
							 | 
						||
| 
								 | 
							
								  while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
							 | 
						||
| 
								 | 
							
								  puts("reset done\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // power up the PHY
							 | 
						||
| 
								 | 
							
								  USBx->GCCFG = USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // be a device, slowest timings
							 | 
						||
| 
								 | 
							
								  //USBx->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
							 | 
						||
| 
								 | 
							
								  USBx->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL;
							 | 
						||
| 
								 | 
							
								  USBx->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
							 | 
						||
| 
								 | 
							
								  //USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // **** for debugging, doesn't seem to work ****
							 | 
						||
| 
								 | 
							
								  //USBx->GUSBCFG |= USB_OTG_GUSBCFG_CTXPKT;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // reset PHY clock
							 | 
						||
| 
								 | 
							
								  USBx_PCGCCTL = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // enable the fancy OTG things
							 | 
						||
| 
								 | 
							
								  USBx->GUSBCFG |= USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  USBx_DEVICE->DCFG = USB_OTG_DCFG_NZLSOHSK | USB_OTG_DCFG_DSPD;
							 | 
						||
| 
								 | 
							
								  //USBx_DEVICE->DCFG = USB_OTG_DCFG_DSPD;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // setup USB interrupts
							 | 
						||
| 
								 | 
							
								  // all interrupts except TXFIFO EMPTY
							 | 
						||
| 
								 | 
							
								  //USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
							 | 
						||
| 
								 | 
							
								  USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  USBx->GAHBCFG = USB_OTG_GAHBCFG_GINT;
							 | 
						||
| 
								 | 
							
								  USBx->GINTSTS = 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// ***************************** USB port *****************************
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void usb_irqhandler(void) {
							 | 
						||
| 
								 | 
							
								  USBx->GINTMSK = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  unsigned int gintsts = USBx->GINTSTS;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // gintsts SUSPEND? 04008428
							 | 
						||
| 
								 | 
							
								  #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								    unsigned int daint = USBx_DEVICE->DAINT;
							 | 
						||
| 
								 | 
							
								    puth(gintsts);
							 | 
						||
| 
								 | 
							
								    puts(" ep ");
							 | 
						||
| 
								 | 
							
								    puth(daint);
							 | 
						||
| 
								 | 
							
								    puts(" USB interrupt!\n");
							 | 
						||
| 
								 | 
							
								  #endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_ESUSP) {
							 | 
						||
| 
								 | 
							
								    puts("ESUSP detected\n");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_USBRST) {
							 | 
						||
| 
								 | 
							
								    puts("USB reset\n");
							 | 
						||
| 
								 | 
							
								    usb_reset();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_ENUMDNE) {
							 | 
						||
| 
								 | 
							
								    puts("enumeration done ");
							 | 
						||
| 
								 | 
							
								    // Full speed, ENUMSPD
							 | 
						||
| 
								 | 
							
								    puth(USBx_DEVICE->DSTS);
							 | 
						||
| 
								 | 
							
								    puts("\n");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_OTGINT) {
							 | 
						||
| 
								 | 
							
								    puts("OTG int:");
							 | 
						||
| 
								 | 
							
								    puth(USBx->GOTGINT);
							 | 
						||
| 
								 | 
							
								    puts("\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // getting ADTOCHG
							 | 
						||
| 
								 | 
							
								    USBx->GOTGINT = USBx->GOTGINT;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // RX FIFO first
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_RXFLVL) {
							 | 
						||
| 
								 | 
							
								    // 1. Read the Receive status pop register
							 | 
						||
| 
								 | 
							
								    volatile unsigned int rxst = USBx->GRXSTSP;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								      puts(" RX FIFO:");
							 | 
						||
| 
								 | 
							
								      puth(rxst);
							 | 
						||
| 
								 | 
							
								      puts(" status: ");
							 | 
						||
| 
								 | 
							
								      puth((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17);
							 | 
						||
| 
								 | 
							
								      puts(" len: ");
							 | 
						||
| 
								 | 
							
								      puth((rxst & USB_OTG_GRXSTSP_BCNT) >> 4);
							 | 
						||
| 
								 | 
							
								      puts("\n");
							 | 
						||
| 
								 | 
							
								    #endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT) {
							 | 
						||
| 
								 | 
							
								      int endpoint = (rxst & USB_OTG_GRXSTSP_EPNUM);
							 | 
						||
| 
								 | 
							
								      int len = (rxst & USB_OTG_GRXSTSP_BCNT) >> 4;
							 | 
						||
| 
								 | 
							
								      USB_ReadPacket(&usbdata, len);
							 | 
						||
| 
								 | 
							
								      #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								        puts("  data ");
							 | 
						||
| 
								 | 
							
								        puth(len);
							 | 
						||
| 
								 | 
							
								        puts("\n");
							 | 
						||
| 
								 | 
							
								        hexdump(&usbdata, len);
							 | 
						||
| 
								 | 
							
								      #endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (endpoint == 2) {
							 | 
						||
| 
								 | 
							
								        usb_cb_ep2_out(usbdata, len);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (endpoint == 3) {
							 | 
						||
| 
								 | 
							
								        usb_cb_ep3_out(usbdata, len);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else if (((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT) {
							 | 
						||
| 
								 | 
							
								      USB_ReadPacket(&setup, 8);
							 | 
						||
| 
								 | 
							
								      #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								        puts("  setup ");
							 | 
						||
| 
								 | 
							
								        hexdump(&setup, 8);
							 | 
						||
| 
								 | 
							
								        puts("\n");
							 | 
						||
| 
								 | 
							
								      #endif
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_HPRTINT) {
							 | 
						||
| 
								 | 
							
								    // host
							 | 
						||
| 
								 | 
							
								    puts("HPRT:");
							 | 
						||
| 
								 | 
							
								    puth(USBx_HOST_PORT->HPRT);
							 | 
						||
| 
								 | 
							
								    puts("\n");
							 | 
						||
| 
								 | 
							
								    if (USBx_HOST_PORT->HPRT & USB_OTG_HPRT_PCDET) {
							 | 
						||
| 
								 | 
							
								      USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PRST;
							 | 
						||
| 
								 | 
							
								      USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PCDET;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_BOUTNAKEFF) {
							 | 
						||
| 
								 | 
							
								    // no global NAK, why is this getting set?
							 | 
						||
| 
								 | 
							
								    #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								      puts("GLOBAL NAK\n");
							 | 
						||
| 
								 | 
							
								    #endif
							 | 
						||
| 
								 | 
							
								    USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK | USB_OTG_DCTL_CGINAK;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_SRQINT) {
							 | 
						||
| 
								 | 
							
								    // we want to do "A-device host negotiation protocol" since we are the A-device
							 | 
						||
| 
								 | 
							
								    puts("start request\n");
							 | 
						||
| 
								 | 
							
								    //USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
							 | 
						||
| 
								 | 
							
								    //USBx_HOST_PORT->HPRT = USB_OTG_HPRT_PPWR | USB_OTG_HPRT_PENA;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // out endpoint hit
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_OEPINT) {
							 | 
						||
| 
								 | 
							
								    #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								      puts("  0:");
							 | 
						||
| 
								 | 
							
								      puth(USBx_OUTEP(0)->DOEPINT);
							 | 
						||
| 
								 | 
							
								      puts(" 2:");
							 | 
						||
| 
								 | 
							
								      puth(USBx_OUTEP(2)->DOEPINT);
							 | 
						||
| 
								 | 
							
								      puts(" 3:");
							 | 
						||
| 
								 | 
							
								      puth(USBx_OUTEP(3)->DOEPINT);
							 | 
						||
| 
								 | 
							
								      puts(" ");
							 | 
						||
| 
								 | 
							
								      puth(USBx_OUTEP(3)->DOEPCTL);
							 | 
						||
| 
								 | 
							
								      puts(" 4:");
							 | 
						||
| 
								 | 
							
								      puth(USBx_OUTEP(4)->DOEPINT);
							 | 
						||
| 
								 | 
							
								      puts(" OUT ENDPOINT\n");
							 | 
						||
| 
								 | 
							
								    #endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (USBx_OUTEP(2)->DOEPINT & USB_OTG_DOEPINT_XFRC) {
							 | 
						||
| 
								 | 
							
								      #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								        puts("  OUT2 PACKET XFRC\n"); 
							 | 
						||
| 
								 | 
							
								      #endif
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(2)->DOEPTSIZ = (1 << 19) | 0x10;
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(2)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (USBx_OUTEP(3)->DOEPINT & USB_OTG_DOEPINT_XFRC) {
							 | 
						||
| 
								 | 
							
								      #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								        puts("  OUT3 PACKET XFRC\n"); 
							 | 
						||
| 
								 | 
							
								      #endif
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40;
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								    } else if (USBx_OUTEP(3)->DOEPINT & 0x2000) {
							 | 
						||
| 
								 | 
							
								      #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								        puts("  OUT3 PACKET WTF\n"); 
							 | 
						||
| 
								 | 
							
								      #endif
							 | 
						||
| 
								 | 
							
								      // if NAK was set trigger this, unknown interrupt
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40;
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
							 | 
						||
| 
								 | 
							
								    } else if (USBx_OUTEP(3)->DOEPINT) {
							 | 
						||
| 
								 | 
							
								      puts("OUTEP3 error ");
							 | 
						||
| 
								 | 
							
								      puth(USBx_OUTEP(3)->DOEPINT);
							 | 
						||
| 
								 | 
							
								      puts("\n");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (USBx_OUTEP(0)->DOEPINT & USB_OTG_DIEPINT_XFRC) {
							 | 
						||
| 
								 | 
							
								      // ready for next packet
							 | 
						||
| 
								 | 
							
								      USBx_OUTEP(0)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) | (1 * 8);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // respond to setup packets
							 | 
						||
| 
								 | 
							
								    if (USBx_OUTEP(0)->DOEPINT & USB_OTG_DOEPINT_STUP) {
							 | 
						||
| 
								 | 
							
								      usb_setup();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    USBx_OUTEP(0)->DOEPINT = USBx_OUTEP(0)->DOEPINT;
							 | 
						||
| 
								 | 
							
								    USBx_OUTEP(2)->DOEPINT = USBx_OUTEP(2)->DOEPINT;
							 | 
						||
| 
								 | 
							
								    USBx_OUTEP(3)->DOEPINT = USBx_OUTEP(3)->DOEPINT;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // in endpoint hit
							 | 
						||
| 
								 | 
							
								  if (gintsts & USB_OTG_GINTSTS_IEPINT) {
							 | 
						||
| 
								 | 
							
								    #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								      puts("  ");
							 | 
						||
| 
								 | 
							
								      puth(USBx_INEP(0)->DIEPINT);
							 | 
						||
| 
								 | 
							
								      puts(" ");
							 | 
						||
| 
								 | 
							
								      puth(USBx_INEP(1)->DIEPINT);
							 | 
						||
| 
								 | 
							
								      puts(" IN ENDPOINT\n");
							 | 
						||
| 
								 | 
							
								    #endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // this happens first
							 | 
						||
| 
								 | 
							
								    if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPINT_XFRC) {
							 | 
						||
| 
								 | 
							
								      #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								        puts("  IN PACKET SEND\n"); 
							 | 
						||
| 
								 | 
							
								      #endif
							 | 
						||
| 
								 | 
							
								      //USBx_DEVICE->DIEPEMPMSK = ~(1 << 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    // *** IN token received when TxFIFO is empty
							 | 
						||
| 
								 | 
							
								    if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
							 | 
						||
| 
								 | 
							
								      #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								        puts("  IN PACKET QUEUE\n"); 
							 | 
						||
| 
								 | 
							
								      #endif
							 | 
						||
| 
								 | 
							
								      // TODO: always assuming max len, can we get the length?
							 | 
						||
| 
								 | 
							
								      usb_cb_ep1_in(0x40);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // clear interrupts
							 | 
						||
| 
								 | 
							
								    USBx_INEP(0)->DIEPINT = USBx_INEP(0)->DIEPINT;
							 | 
						||
| 
								 | 
							
								    USBx_INEP(1)->DIEPINT = USBx_INEP(1)->DIEPINT;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // clear all interrupts
							 | 
						||
| 
								 | 
							
								  USBx_DEVICE->DAINT = USBx_DEVICE->DAINT;
							 | 
						||
| 
								 | 
							
								  USBx->GINTSTS = USBx->GINTSTS;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 |