X-Git-Url: https://git.sur5r.net/?p=armstart-ibdap;a=blobdiff_plain;f=src%2Fusb_driver.c;fp=src%2Fusb_driver.c;h=bdb3b414210ba1aa62d235df64c0562a34ddc243;hp=0000000000000000000000000000000000000000;hb=8dc27fcbb690f5a27358b78782f7d217253b5235;hpb=7cdc866d982b6bb662fa3b2eceb621f5369267d2 diff --git a/src/usb_driver.c b/src/usb_driver.c new file mode 100644 index 0000000..bdb3b41 --- /dev/null +++ b/src/usb_driver.c @@ -0,0 +1,187 @@ +/* + * usb_driver.c + * + * Created on: Jun 18, 2015 + * Author: yliu + */ + +#include +#include + +#ifdef __USE_CMSIS +#include "LPC11Uxx.h" +#endif + + +#include "usb_driver.h" + +#define PDRUNCFGUSEMASK 0x0000E800 +#define PDRUNCFGMASKTMP 0x000005FF + +USBD_HANDLE_T g_usb_hnd; +const USBD_API_T *g_pUsbApi; + + +/* Find the address of interface descriptor for given class type. */ +USB_INTERFACE_DESCRIPTOR *find_IntfDesc(const uint8_t *pDesc, uint32_t intfClass) +{ + USB_COMMON_DESCRIPTOR *pD; + USB_INTERFACE_DESCRIPTOR *pIntfDesc = 0; + uint32_t next_desc_adr; + + pD = (USB_COMMON_DESCRIPTOR *) pDesc; + next_desc_adr = (uint32_t) pDesc; + + while (pD->bLength) { + /* is it interface descriptor */ + if (pD->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) { + + pIntfDesc = (USB_INTERFACE_DESCRIPTOR *) pD; + /* did we find the right interface descriptor */ + if (pIntfDesc->bInterfaceClass == intfClass) { + break; + } + } + pIntfDesc = 0; + next_desc_adr = (uint32_t) pD + pD->bLength; + pD = (USB_COMMON_DESCRIPTOR *) next_desc_adr; + } + + return pIntfDesc; +} + + + + +void init_usb_clock () { + // no need to do this: LPC_SYSCON->PDRUNCFG &= ~(1 << 8); + // system_LPC11Uxx.c done that already. + // configure SYSAHBCLKCTRL + + // no need to do this: enabled in ResetISR() + //LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 26; // ram1 clock source enable + //LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 27; // usbram clock source enable + // conf usb main clock + LPC_SYSCON->USBCLKSEL = 0; + LPC_SYSCON->USBCLKUEN = 0; + LPC_SYSCON->USBCLKUEN = 1; + LPC_SYSCON->USBCLKDIV = 1; + + LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 14; // usb clock source + //LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 26; + LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 27; +} + +void init_usb_power () { + uint32_t pdrun; + pdrun = LPC_SYSCON->PDRUNCFG & PDRUNCFGMASKTMP; + pdrun &= ~((1 << 10) & PDRUNCFGMASKTMP); + LPC_SYSCON->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK); +} + +void USB_IRQHandler(void) { + uint32_t *addr = (uint32_t *) LPC_USB->EPLISTSTART; + + /* WORKAROUND for artf32289 ROM driver BUG: + As part of USB specification the device should respond + with STALL condition for any unsupported setup packet. The host will send + new setup packet/request on seeing STALL condition for EP0 instead of sending + a clear STALL request. Current driver in ROM doesn't clear the STALL + condition on new setup packet which should be fixed. + */ + if ( LPC_USB->DEVCMDSTAT & (1 << 8) ) { /* if setup packet is received */ + addr[0] &= ~(1 << 29); /* clear EP0_OUT stall */ + addr[2] &= ~(1 << 29); /* clear EP0_IN stall */ + } + USBD_API->hw->ISR(g_usb_hnd); +} + +int init_usb_driver (USBD_API_INIT_PARAM_T *usb_param) { + USB_CORE_DESCS_T desc; + ErrorCode_t ret = LPC_OK; + + g_pUsbApi = (const USBD_API_T *) LPC_ROM_API->usbdApiBase; + memset((void *) usb_param, 0, sizeof(USBD_API_INIT_PARAM_T)); + usb_param->usb_reg_base = LPC_USB_BASE; + /* WORKAROUND for artf44835 ROM driver BUG: + Code clearing STALL bits in endpoint reset routine corrupts memory area + next to the endpoint control data. For example When EP0, EP1_IN, EP1_OUT, + EP2_IN are used we need to specify 3 here. But as a workaround for this + issue specify 4. So that extra EPs control structure acts as padding buffer + to avoid data corruption. Corruption of padding memory doesn’t affect the + stack/program behaviour. + */ + usb_param->max_num_ep = 2 + 1; + usb_param->mem_base = USB_STACK_MEM_BASE; + usb_param->mem_size = USB_STACK_MEM_SIZE; + + desc.device_desc = (uint8_t *) USB_DeviceDescriptor; + desc.string_desc = (uint8_t *) USB_StringDescriptor; + + desc.high_speed_desc = USB_FsConfigDescriptor; + desc.full_speed_desc = USB_FsConfigDescriptor; + desc.device_qualifier = 0; + + ret = USBD_API->hw->Init(&g_usb_hnd, &desc, usb_param); + if (ret != LPC_OK) return -1; + + usb_param->mem_base = USB_STACK_MEM_BASE + (USB_STACK_MEM_SIZE - usb_param->mem_size); + return 0; +} + + + +int init_usb_hid (USBD_API_INIT_PARAM_T *usb_param, + HID_GetReport_Func_T getreport_fun, HID_SetReport_Func_T setreport_fun, + HID_EpIn_Hdlr_Func_T epin_hdlr_fun, HID_EpOut_Hdlr_Func_T epout_hdlr_fun, + uint8_t** report_saddr, int report_size) { + USBD_HID_INIT_PARAM_T hid_param; + USB_HID_REPORT_T reports_data[1]; + ErrorCode_t ret = LPC_OK; + + memset((void *) &hid_param, 0, sizeof(USBD_HID_INIT_PARAM_T)); + hid_param.max_reports = 1; + + /* Init reports_data */ + reports_data[0].len = hid_report_size; + reports_data[0].idle_time = 0; + reports_data[0].desc = (uint8_t *) &HID_ReportDescriptor[0]; + + USB_INTERFACE_DESCRIPTOR *pIntfDesc = (USB_INTERFACE_DESCRIPTOR *) &USB_FsConfigDescriptor[sizeof(USB_CONFIGURATION_DESCRIPTOR)]; + + if ((pIntfDesc == 0) || (pIntfDesc->bInterfaceClass != USB_DEVICE_CLASS_HUMAN_INTERFACE)) { + return -1; + } + + hid_param.mem_base = usb_param->mem_base; + hid_param.mem_size = usb_param->mem_size; + hid_param.intf_desc = (uint8_t *) pIntfDesc; + /* user defined functions */ + hid_param.HID_GetReport = getreport_fun; + hid_param.HID_SetReport = setreport_fun; + hid_param.HID_EpIn_Hdlr = epin_hdlr_fun; + hid_param.HID_EpOut_Hdlr = epout_hdlr_fun; + hid_param.report_data = reports_data; + + ret = USBD_API->hid->init(g_usb_hnd, &hid_param); + if (ret != LPC_OK) return -2; + /* allocate USB accessable memory space for report data */ + *report_saddr = (uint8_t *) hid_param.mem_base; + memset (hid_param.mem_base, 0, report_size); + hid_param.mem_base += report_size; + hid_param.mem_size -= report_size; + /* update memory variables */ + usb_param->mem_base = hid_param.mem_base; + usb_param->mem_size = hid_param.mem_size; + return 0; +} + +void connect_to_usb_bus () { + NVIC_EnableIRQ (USB_IRQn); + USBD_API->hw->Connect (g_usb_hnd, 1); +} + +void disconnect_to_usb_bus () { + USBD_API->hw->Connect (g_usb_hnd, 0); + NVIC_DisableIRQ (USB_IRQn); +}