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.
		
		
		
		
		
			
		
			
				
					
					
						
							805 lines
						
					
					
						
							26 KiB
						
					
					
				
			
		
		
	
	
							805 lines
						
					
					
						
							26 KiB
						
					
					
				// IRQs: OTG_FS
 | 
						|
 | 
						|
// **** supporting defines ****
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
  __IO uint32_t HPRT;
 | 
						|
}
 | 
						|
USB_OTG_HostPortTypeDef;
 | 
						|
 | 
						|
USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS;
 | 
						|
 | 
						|
#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
 | 
						|
 | 
						|
#define USB_OTG_SPEED_FULL 3
 | 
						|
 | 
						|
uint8_t resp[MAX_RESP_LEN];
 | 
						|
 | 
						|
// descriptor types
 | 
						|
// same as setupdat.h
 | 
						|
#define DSCR_DEVICE_TYPE 1
 | 
						|
#define DSCR_CONFIG_TYPE 2
 | 
						|
#define DSCR_STRING_TYPE 3
 | 
						|
#define DSCR_INTERFACE_TYPE 4
 | 
						|
#define DSCR_ENDPOINT_TYPE 5
 | 
						|
#define DSCR_DEVQUAL_TYPE 6
 | 
						|
 | 
						|
// for the repeating interfaces
 | 
						|
#define DSCR_INTERFACE_LEN 9
 | 
						|
#define DSCR_ENDPOINT_LEN 7
 | 
						|
#define DSCR_CONFIG_LEN 9
 | 
						|
#define DSCR_DEVICE_LEN 18
 | 
						|
 | 
						|
// endpoint types
 | 
						|
#define ENDPOINT_TYPE_CONTROL 0
 | 
						|
#define ENDPOINT_TYPE_ISO 1
 | 
						|
#define ENDPOINT_TYPE_BULK 2
 | 
						|
#define ENDPOINT_TYPE_INT 3
 | 
						|
 | 
						|
// This is an arbitrary value used in bRequest
 | 
						|
#define  MS_VENDOR_CODE 0x20
 | 
						|
 | 
						|
//Convert machine byte order to USB byte order
 | 
						|
#define TOUSBORDER(num)\
 | 
						|
  (num&0xFF), ((num>>8)&0xFF)
 | 
						|
 | 
						|
uint8_t device_desc[] = {
 | 
						|
  DSCR_DEVICE_LEN, DSCR_DEVICE_TYPE, 0x00, 0x02, //Length, Type, bcdUSB
 | 
						|
  0xFF, 0xFF, 0xFF, 0x40, // Class, Subclass, Protocol, Max Packet Size
 | 
						|
  TOUSBORDER(USB_VID), // idVendor
 | 
						|
  TOUSBORDER(USB_PID), // idProduct
 | 
						|
#ifdef STM32F4
 | 
						|
  0x00, 0x23, // bcdDevice
 | 
						|
#else
 | 
						|
  0x00, 0x22, // bcdDevice
 | 
						|
#endif
 | 
						|
  0x01, 0x02, // Manufacturer, Product
 | 
						|
  0x03, 0x01 // Serial Number, Num Configurations
 | 
						|
};
 | 
						|
 | 
						|
#define ENDPOINT_RCV 0x80
 | 
						|
#define ENDPOINT_SND 0x00
 | 
						|
 | 
						|
uint8_t configuration_desc[] = {
 | 
						|
  DSCR_CONFIG_LEN, DSCR_CONFIG_TYPE, // Length, Type,
 | 
						|
  TOUSBORDER(0x0045), // Total Len (uint16)
 | 
						|
  0x01, 0x01, 0x00, // Num Interface, Config Value, Configuration
 | 
						|
  0xc0, 0x32, // Attributes, Max Power
 | 
						|
  // interface 0 ALT 0
 | 
						|
  DSCR_INTERFACE_LEN, DSCR_INTERFACE_TYPE, // Length, Type
 | 
						|
  0x00, 0x00, 0x03, // Index, Alt Index idx, Endpoint count
 | 
						|
  0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol
 | 
						|
  0x00, // Interface
 | 
						|
    // endpoint 1, read CAN
 | 
						|
    DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
 | 
						|
    ENDPOINT_RCV | 1, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
 | 
						|
    TOUSBORDER(0x0040), // Max Packet (0x0040)
 | 
						|
    0x00, // Polling Interval (NA)
 | 
						|
    // endpoint 2, send serial
 | 
						|
    DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
 | 
						|
    ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
 | 
						|
    TOUSBORDER(0x0040), // Max Packet (0x0040)
 | 
						|
    0x00, // Polling Interval
 | 
						|
    // endpoint 3, send CAN
 | 
						|
    DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
 | 
						|
    ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
 | 
						|
    TOUSBORDER(0x0040), // Max Packet (0x0040)
 | 
						|
    0x00, // Polling Interval
 | 
						|
  // interface 0 ALT 1
 | 
						|
  DSCR_INTERFACE_LEN, DSCR_INTERFACE_TYPE, // Length, Type
 | 
						|
  0x00, 0x01, 0x03, // Index, Alt Index idx, Endpoint count
 | 
						|
  0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol
 | 
						|
  0x00, // Interface
 | 
						|
    // endpoint 1, read CAN
 | 
						|
    DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
 | 
						|
    ENDPOINT_RCV | 1, ENDPOINT_TYPE_INT, // Endpoint Num/Direction, Type
 | 
						|
    TOUSBORDER(0x0040), // Max Packet (0x0040)
 | 
						|
    0x05, // Polling Interval (5 frames)
 | 
						|
    // endpoint 2, send serial
 | 
						|
    DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
 | 
						|
    ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
 | 
						|
    TOUSBORDER(0x0040), // Max Packet (0x0040)
 | 
						|
    0x00, // Polling Interval
 | 
						|
    // endpoint 3, send CAN
 | 
						|
    DSCR_ENDPOINT_LEN, DSCR_ENDPOINT_TYPE, // Length, Type
 | 
						|
    ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type
 | 
						|
    TOUSBORDER(0x0040), // Max Packet (0x0040)
 | 
						|
    0x00, // Polling Interval
 | 
						|
};
 | 
						|
 | 
						|
uint8_t string_0_desc[] = {
 | 
						|
  0x04, DSCR_STRING_TYPE, 0x09, 0x04
 | 
						|
};
 | 
						|
 | 
						|
uint16_t string_1_desc[] = {
 | 
						|
  0x0312,
 | 
						|
  'c', 'o', 'm', 'm', 'a', '.', 'a', 'i'
 | 
						|
};
 | 
						|
 | 
						|
#ifdef PANDA
 | 
						|
uint16_t string_2_desc[] = {
 | 
						|
  0x030c,
 | 
						|
  'p', 'a', 'n', 'd', 'a'
 | 
						|
};
 | 
						|
#else
 | 
						|
uint16_t string_2_desc[] = {
 | 
						|
  0x030c,
 | 
						|
  'N', 'E', 'O', 'v', '1'
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
uint16_t string_3_desc[] = {
 | 
						|
  0x030a,
 | 
						|
  'n', 'o', 'n', 'e'
 | 
						|
};
 | 
						|
 | 
						|
#ifdef PANDA
 | 
						|
// WCID (auto install WinUSB driver)
 | 
						|
// https://github.com/pbatard/libwdi/wiki/WCID-Devices
 | 
						|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb-installation#automatic-installation-of--winusb-without-an-inf-file
 | 
						|
uint8_t string_238_desc[] = {
 | 
						|
  0x12, 0x03, // bLength, bDescriptorType
 | 
						|
  'M',0, 'S',0, 'F',0, 'T',0, '1',0, '0',0, '0',0, // qwSignature (MSFT100)
 | 
						|
  MS_VENDOR_CODE, 0x00 // bMS_VendorCode, bPad
 | 
						|
};
 | 
						|
uint8_t winusb_ext_compatid_os_desc[] = {
 | 
						|
  0x28, 0x00, 0x00, 0x00, // dwLength
 | 
						|
  0x00, 0x01, // bcdVersion
 | 
						|
  0x04, 0x00, // wIndex
 | 
						|
  0x01, // bCount
 | 
						|
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved
 | 
						|
  0x00, // bFirstInterfaceNumber
 | 
						|
  0x00, // Reserved
 | 
						|
  'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB)
 | 
						|
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subcompatible ID (none)
 | 
						|
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved
 | 
						|
};
 | 
						|
uint8_t winusb_ext_prop_os_desc[] = {
 | 
						|
  0x8e, 0x00, 0x00, 0x00, // dwLength
 | 
						|
  0x00, 0x01, // bcdVersion
 | 
						|
  0x05, 0x00, // wIndex
 | 
						|
  0x01, 0x00, // wCount
 | 
						|
  // first property
 | 
						|
  0x84, 0x00, 0x00, 0x00, // dwSize
 | 
						|
  0x01, 0x00, 0x00, 0x00, // dwPropertyDataType
 | 
						|
  0x28, 0x00, // wPropertyNameLength
 | 
						|
  'D',0, 'e',0, 'v',0, 'i',0, 'c',0, 'e',0, 'I',0, 'n',0, 't',0, 'e',0, 'r',0, 'f',0, 'a',0, 'c',0, 'e',0, 'G',0, 'U',0, 'I',0, 'D',0, 0, 0, // bPropertyName (DeviceInterfaceGUID)
 | 
						|
  0x4e, 0x00, 0x00, 0x00, // dwPropertyDataLength
 | 
						|
  '{',0, 'c',0, 'c',0, 'e',0, '5',0, '2',0, '9',0, '1',0, 'c',0, '-',0, 'a',0, '6',0, '9',0, 'f',0, '-',0, '4',0 ,'9',0 ,'9',0 ,'5',0 ,'-',0, 'a',0, '4',0, 'c',0, '2',0, '-',0, '2',0, 'a',0, 'e',0, '5',0, '7',0, 'a',0, '5',0, '1',0, 'a',0, 'd',0, 'e',0, '9',0, '}',0, 0, 0, // bPropertyData ({CCE5291C-A69F-4995-A4C2-2AE57A51ADE9})
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
// current packet
 | 
						|
USB_Setup_TypeDef setup;
 | 
						|
uint8_t usbdata[0x100];
 | 
						|
uint8_t* ep0_txdata = NULL;
 | 
						|
uint16_t ep0_txlen = 0;
 | 
						|
 | 
						|
// Store the current interface alt setting.
 | 
						|
int current_int0_alt_setting = 0;
 | 
						|
 | 
						|
// 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_USB
 | 
						|
  puts("writing ");
 | 
						|
  hexdump(src, len);
 | 
						|
  #endif
 | 
						|
 | 
						|
  uint8_t numpacket = (len+(MAX_RESP_LEN-1))/MAX_RESP_LEN;
 | 
						|
  uint32_t count32b = 0, i = 0;
 | 
						|
  count32b = (len + 3) / 4;
 | 
						|
 | 
						|
  // bullshit
 | 
						|
  USBx_INEP(ep)->DIEPTSIZ = ((numpacket << 19) & USB_OTG_DIEPTSIZ_PKTCNT) |
 | 
						|
                            (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);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// IN EP 0 TX FIFO has a max size of 127 bytes (much smaller than the rest)
 | 
						|
// so use TX FIFO empty interrupt to send larger amounts of data
 | 
						|
void USB_WritePacket_EP0(uint8_t *src, uint16_t len) {
 | 
						|
  #ifdef DEBUG_USB
 | 
						|
  puts("writing ");
 | 
						|
  hexdump(src, len);
 | 
						|
  #endif
 | 
						|
 | 
						|
  uint16_t wplen = min(len, 0x40);
 | 
						|
  USB_WritePacket(src, wplen, 0);
 | 
						|
 | 
						|
  if (wplen < len) {
 | 
						|
    ep0_txdata = src + wplen;
 | 
						|
    ep0_txlen = len - wplen;
 | 
						|
    USBx_DEVICE->DIEPEMPMSK |= 1;
 | 
						|
  } else {
 | 
						|
    USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
char to_hex_char(int a) {
 | 
						|
  if (a < 10) {
 | 
						|
    return '0' + a;
 | 
						|
  } else {
 | 
						|
    return 'a' + (a-10);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void usb_setup() {
 | 
						|
  int resp_len;
 | 
						|
  // 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) | 0x40;
 | 
						|
      USBx_OUTEP(2)->DOEPCTL = (0x40 & 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_USB
 | 
						|
        puts(" set address\n");
 | 
						|
      #endif
 | 
						|
 | 
						|
      // TODO: this isn't enumeration complete
 | 
						|
      // moved here to work better on OS X
 | 
						|
      usb_cb_enumeration_complete();
 | 
						|
 | 
						|
      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;
 | 
						|
        case USB_DESC_TYPE_STRING:
 | 
						|
          switch (setup.b.wValue.bw.msb) {
 | 
						|
            case 0:
 | 
						|
              USB_WritePacket((uint8_t*)string_0_desc, min(sizeof(string_0_desc), setup.b.wLength.w), 0);
 | 
						|
              break;
 | 
						|
            case 1:
 | 
						|
              USB_WritePacket((uint8_t*)string_1_desc, min(sizeof(string_1_desc), setup.b.wLength.w), 0);
 | 
						|
              break;
 | 
						|
            case 2:
 | 
						|
              USB_WritePacket((uint8_t*)string_2_desc, min(sizeof(string_2_desc), setup.b.wLength.w), 0);
 | 
						|
              break;
 | 
						|
            case 3:
 | 
						|
              #ifdef PANDA
 | 
						|
                resp[0] = 0x02 + 12*4;
 | 
						|
                resp[1] = 0x03;
 | 
						|
 | 
						|
                // 96 bits = 12 bytes
 | 
						|
                for (int i = 0; i < 12; i++){
 | 
						|
                  uint8_t cc = ((uint8_t *)UID_BASE)[i];
 | 
						|
                  resp[2 + i*4 + 0] = to_hex_char((cc>>4)&0xF);
 | 
						|
                  resp[2 + i*4 + 1] = '\0';
 | 
						|
                  resp[2 + i*4 + 2] = to_hex_char((cc>>0)&0xF);
 | 
						|
                  resp[2 + i*4 + 3] = '\0';
 | 
						|
                }
 | 
						|
 | 
						|
                USB_WritePacket(resp, min(resp[0], setup.b.wLength.w), 0);
 | 
						|
              #else
 | 
						|
                USB_WritePacket((const uint8_t *)string_3_desc, min(sizeof(string_3_desc), setup.b.wLength.w), 0);
 | 
						|
              #endif
 | 
						|
              break;
 | 
						|
            #ifdef PANDA
 | 
						|
            case 238:
 | 
						|
              USB_WritePacket((uint8_t*)string_238_desc, min(sizeof(string_238_desc), setup.b.wLength.w), 0);
 | 
						|
              break;
 | 
						|
            #endif
 | 
						|
            default:
 | 
						|
              // nothing
 | 
						|
              USB_WritePacket(0, 0, 0);
 | 
						|
              break;
 | 
						|
          }
 | 
						|
          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;
 | 
						|
    case USB_REQ_SET_INTERFACE:
 | 
						|
      // Store the alt setting number for IN EP behavior.
 | 
						|
      current_int0_alt_setting = setup.b.wValue.w;
 | 
						|
      USB_WritePacket(0, 0, 0);
 | 
						|
      USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
 | 
						|
      break;
 | 
						|
    #ifdef PANDA
 | 
						|
    case MS_VENDOR_CODE:
 | 
						|
      switch (setup.b.wIndex.w) {
 | 
						|
        // Extended Compat ID OS Descriptor
 | 
						|
        case 4:
 | 
						|
          USB_WritePacket_EP0((uint8_t*)winusb_ext_compatid_os_desc, min(sizeof(winusb_ext_compatid_os_desc), setup.b.wLength.w));
 | 
						|
          break;
 | 
						|
        // Extended Properties OS Descriptor
 | 
						|
        case 5:
 | 
						|
          USB_WritePacket_EP0((uint8_t*)winusb_ext_prop_os_desc, min(sizeof(winusb_ext_prop_os_desc), setup.b.wLength.w));
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          USB_WritePacket_EP0(0, 0);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    #endif
 | 
						|
    default:
 | 
						|
      resp_len = usb_cb_control_msg(&setup, resp, 1);
 | 
						|
      USB_WritePacket(resp, min(resp_len, setup.b.wLength.w), 0);
 | 
						|
      USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void usb_init() {
 | 
						|
  // 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");
 | 
						|
 | 
						|
  // internal PHY, force device mode
 | 
						|
  USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_FDMOD;
 | 
						|
 | 
						|
  // slowest timings
 | 
						|
  USBx->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
 | 
						|
 | 
						|
  // power up the PHY
 | 
						|
#ifdef STM32F4
 | 
						|
  USBx->GCCFG = USB_OTG_GCCFG_PWRDWN;
 | 
						|
 | 
						|
  //USBx->GCCFG |= USB_OTG_GCCFG_VBDEN | USB_OTG_GCCFG_SDEN |USB_OTG_GCCFG_PDEN | USB_OTG_GCCFG_DCDEN;
 | 
						|
 | 
						|
  /* B-peripheral session valid override enable*/
 | 
						|
  USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
 | 
						|
  USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
 | 
						|
#else
 | 
						|
  USBx->GCCFG = USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS;
 | 
						|
#endif
 | 
						|
 | 
						|
  // 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 |= (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
 | 
						|
  // DCFG_FRAME_INTERVAL_80 is 0
 | 
						|
  //USBx->GUSBCFG |= USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP;
 | 
						|
  USBx_DEVICE->DCFG |= USB_OTG_SPEED_FULL | USB_OTG_DCFG_NZLSOHSK;
 | 
						|
 | 
						|
  //USBx_DEVICE->DCFG = USB_OTG_DCFG_NZLSOHSK | USB_OTG_DCFG_DSPD;
 | 
						|
  //USBx_DEVICE->DCFG = USB_OTG_DCFG_DSPD;
 | 
						|
 | 
						|
  // clear pending interrupts
 | 
						|
  USBx->GINTSTS = 0xBFFFFFFFU;
 | 
						|
 | 
						|
  // 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->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_OTGINT |
 | 
						|
                  USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_GONAKEFFM | USB_OTG_GINTMSK_GINAKEFFM |
 | 
						|
                  USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_USBSUSPM |
 | 
						|
                  USB_OTG_GINTMSK_CIDSCHGM | USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_MMISM;
 | 
						|
 | 
						|
  USBx->GAHBCFG = USB_OTG_GAHBCFG_GINT;
 | 
						|
 | 
						|
  // DCTL startup value is 2 on new chip, 0 on old chip
 | 
						|
  // THIS IS FUCKING BULLSHIT
 | 
						|
  USBx_DEVICE->DCTL = 0;
 | 
						|
 | 
						|
  // enable the IRQ
 | 
						|
  NVIC_EnableIRQ(OTG_FS_IRQn);
 | 
						|
}
 | 
						|
 | 
						|
// ***************************** USB port *****************************
 | 
						|
 | 
						|
void usb_irqhandler(void) {
 | 
						|
  //USBx->GINTMSK = 0;
 | 
						|
 | 
						|
  unsigned int gintsts = USBx->GINTSTS;
 | 
						|
  unsigned int gotgint = USBx->GOTGINT;
 | 
						|
  unsigned int daint = USBx_DEVICE->DAINT;
 | 
						|
 | 
						|
  // gintsts SUSPEND? 04008428
 | 
						|
  #ifdef DEBUG_USB
 | 
						|
    puth(gintsts);
 | 
						|
    puts(" ");
 | 
						|
    /*puth(USBx->GCCFG);
 | 
						|
    puts(" ");*/
 | 
						|
    puth(gotgint);
 | 
						|
    puts(" ep ");
 | 
						|
    puth(daint);
 | 
						|
    puts(" USB interrupt!\n");
 | 
						|
  #endif
 | 
						|
 | 
						|
  if (gintsts & USB_OTG_GINTSTS_CIDSCHG) {
 | 
						|
    puts("connector ID status change\n");
 | 
						|
  }
 | 
						|
 | 
						|
  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_USB
 | 
						|
      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_USB
 | 
						|
        puts("  data ");
 | 
						|
        puth(len);
 | 
						|
        puts("\n");
 | 
						|
        hexdump(&usbdata, len);
 | 
						|
      #endif
 | 
						|
 | 
						|
      if (endpoint == 2) {
 | 
						|
        usb_cb_ep2_out(usbdata, len, 1);
 | 
						|
      }
 | 
						|
 | 
						|
      if (endpoint == 3) {
 | 
						|
        usb_cb_ep3_out(usbdata, len, 1);
 | 
						|
      }
 | 
						|
    } else if (((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT) {
 | 
						|
      USB_ReadPacket(&setup, 8);
 | 
						|
      #ifdef DEBUG_USB
 | 
						|
        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) || (gintsts & USB_OTG_GINTSTS_GINAKEFF)) {
 | 
						|
    // no global NAK, why is this getting set?
 | 
						|
    #ifdef DEBUG_USB
 | 
						|
      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");
 | 
						|
    puth(USBx->GOTGCTL);
 | 
						|
    puts("\n");*/
 | 
						|
    //USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
 | 
						|
    //USBx_HOST_PORT->HPRT = USB_OTG_HPRT_PPWR | USB_OTG_HPRT_PENA;
 | 
						|
    //USBx->GOTGCTL |= USB_OTG_GOTGCTL_SRQ;
 | 
						|
  }
 | 
						|
 | 
						|
  // out endpoint hit
 | 
						|
  if (gintsts & USB_OTG_GINTSTS_OEPINT) {
 | 
						|
    #ifdef DEBUG_USB
 | 
						|
      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_USB
 | 
						|
        puts("  OUT2 PACKET XFRC\n");
 | 
						|
      #endif
 | 
						|
      USBx_OUTEP(2)->DOEPTSIZ = (1 << 19) | 0x40;
 | 
						|
      USBx_OUTEP(2)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
 | 
						|
    }
 | 
						|
 | 
						|
    if (USBx_OUTEP(3)->DOEPINT & USB_OTG_DOEPINT_XFRC) {
 | 
						|
      #ifdef DEBUG_USB
 | 
						|
        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_USB
 | 
						|
        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;
 | 
						|
  }
 | 
						|
 | 
						|
  // interrupt endpoint hit (Page 1221)
 | 
						|
  if (gintsts & USB_OTG_GINTSTS_IEPINT) {
 | 
						|
    #ifdef DEBUG_USB
 | 
						|
      puts("  ");
 | 
						|
      puth(USBx_INEP(0)->DIEPINT);
 | 
						|
      puts(" ");
 | 
						|
      puth(USBx_INEP(1)->DIEPINT);
 | 
						|
      puts(" IN ENDPOINT\n");
 | 
						|
    #endif
 | 
						|
 | 
						|
    // Should likely check the EP of the IN request even if there is
 | 
						|
    // only one IN endpoint.
 | 
						|
 | 
						|
    // No need to set NAK in OTG_DIEPCTL0 when nothing to send,
 | 
						|
    // Appears USB core automatically sets NAK. WritePacket clears it.
 | 
						|
 | 
						|
    // Handle the two interface alternate settings. Setting 0 is has
 | 
						|
    // EP1 as bulk. Setting 1 has EP1 as interrupt. The code to handle
 | 
						|
    // these two EP variations are very similar and can be
 | 
						|
    // restructured for smaller code footprint. Keeping split out for
 | 
						|
    // now for clarity.
 | 
						|
 | 
						|
    //TODO add default case. Should it NAK?
 | 
						|
    switch (current_int0_alt_setting) {
 | 
						|
      case 0: ////// Bulk config
 | 
						|
        // *** IN token received when TxFIFO is empty
 | 
						|
        if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
 | 
						|
          #ifdef DEBUG_USB
 | 
						|
          puts("  IN PACKET QUEUE\n");
 | 
						|
          #endif
 | 
						|
          // TODO: always assuming max len, can we get the length?
 | 
						|
          USB_WritePacket((void *)resp, usb_cb_ep1_in(resp, 0x40, 1), 1);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
      case 1: ////// Interrupt config
 | 
						|
        // *** IN token received when TxFIFO is empty
 | 
						|
        if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
 | 
						|
          #ifdef DEBUG_USB
 | 
						|
          puts("  IN PACKET QUEUE\n");
 | 
						|
          #endif
 | 
						|
          // TODO: always assuming max len, can we get the length?
 | 
						|
          int len = usb_cb_ep1_in(resp, 0x40, 1);
 | 
						|
          if (len > 0) {
 | 
						|
            USB_WritePacket((void *)resp, len, 1);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (USBx_INEP(0)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
 | 
						|
      #ifdef DEBUG_USB
 | 
						|
      puts("  IN PACKET QUEUE\n");
 | 
						|
      #endif
 | 
						|
 | 
						|
      if (ep0_txlen != 0 && (USBx_INEP(0)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40) {
 | 
						|
        uint16_t len = min(ep0_txlen, 0x40);
 | 
						|
        USB_WritePacket(ep0_txdata, len, 0);
 | 
						|
        ep0_txdata += len;
 | 
						|
        ep0_txlen -= len;
 | 
						|
        if (ep0_txlen == 0) {
 | 
						|
          ep0_txdata = NULL;
 | 
						|
          USBx_DEVICE->DIEPEMPMSK &= ~1;
 | 
						|
          USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    // clear interrupts
 | 
						|
    USBx_INEP(0)->DIEPINT = USBx_INEP(0)->DIEPINT; // Why ep0?
 | 
						|
    USBx_INEP(1)->DIEPINT = USBx_INEP(1)->DIEPINT;
 | 
						|
  }
 | 
						|
 | 
						|
  // clear all interrupts we handled
 | 
						|
  USBx_DEVICE->DAINT = daint;
 | 
						|
  USBx->GOTGINT = gotgint;
 | 
						|
  USBx->GINTSTS = gintsts;
 | 
						|
 | 
						|
  //USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
 | 
						|
}
 | 
						|
 | 
						|
void OTG_FS_IRQHandler(void) {
 | 
						|
  NVIC_DisableIRQ(OTG_FS_IRQn);
 | 
						|
  //__disable_irq();
 | 
						|
  usb_irqhandler();
 | 
						|
  //__enable_irq();
 | 
						|
  NVIC_EnableIRQ(OTG_FS_IRQn);
 | 
						|
}
 | 
						|
 | 
						|
 |