#include "terasic_includes.h" #include "usb_device.h" #include "usb_protocol.h" #ifdef DEBUG_USBDEV #define DEBUG_OUT(x) {printf("[USBDEV]"); printf x;} #define DEBUG_ERR(x) {printf("[USBDEV_ERR]!!!"); printf x;} #define DEBUG_CB(x) {printf("[USBDEV_CB]"); printf x;} #else #define DEBUG_OUT(x) #define DEBUG_ERR(x) #define DEBUG_CB(x) #endif /* * Values of device states */ typedef enum{ USBDEV_STATE_INIT = 0, USBDEV_STATE_ATTACHED, USBDEV_STATE_DEFAULT, USBDEV_STATE_ADDRESSED, USBDEV_STATE_CONFIGURED, USBDEV_STATE_SUSPENDED, USBDEV_STATE_UNKNOWN = 0xFF }USBDEV_STATE; typedef struct{ // USBDEV_NOTIFY DeviceNotify; // USBDEV_STATE State; USBDEV_STATE PreState; // alt_u8 ConfigurationNum; alt_u8 InterfaceNum; alt_u8 AlternateNum; // DC_CONFIG_DEVICE *pDcConfig; DC_PIPE_HANDLE ControlPipe; DC_PIPE_DESC PipeDesc; // struct DC_URB CtrlWriteUrb; /* Control pipe write URB */ struct DC_URB CtrlReadUrb; /* Control pipe read URB */ // DEVICE_DRIVER *pDeviceDriver; // bool bHighSpeed; }USBDEV_DRIVER; DC_PIPE_OPERATION gControlPipeOperation; //extern alt_u8 HS_Dev_flag; bool usbdNotifyWriteControlPipe(USBDEV_DRIVER *pUsbd, alt_u8 *pData, alt_u16 DataLen); void usbdStallControlPipe(USBDEV_DRIVER *pUsbd); void usbdSetConfiguration(USBDEV_DRIVER *pUsbd, unsigned char *szCommand); #define DC_FILL_NON_ISO_URB(urb, handle, type, opr, buff, len, callback,priv) {urb->pNext = NULL; urb->Pipe = handle; urb->PipeType = type; urb->Operation = opr; urb->pTransferBuffer = buff; urb->TransferBufferLength = len; urb->ActualLength = 0; urb->Complete = callback; urb->pReqPriv = priv;} //============================================================================= static void usbdDeviceNotify(alt_u32 Context, alt_u32 Notify){ USBDEV_DRIVER *pUsbd = (USBDEV_DRIVER *)Context; //DEBUG_CB(("Context=%08lXh, Notify=%08lXh\n", Context, Notify)); switch(Notify){ case DC_RESET: DEBUG_CB(("DC_RESET\n")); if (pUsbd->ConfigurationNum){ int EpNum; DEVICE_DRIVER *pDeviceDriver = pUsbd->pDeviceDriver; pUsbd->ConfigurationNum = 0; if (pDeviceDriver && pDeviceDriver->DeviceNotify){ USBDEV_EVENT_CONTEXT EventContext; memset(&EventContext, 0, sizeof(EventContext)); EventContext.Event = USBDEV_EVENT_SET_CONFIGURATION; EventContext.u.SetConfigurationValue = 0; // unconfig none-control pipe pDeviceDriver->DeviceNotify(&EventContext, pDeviceDriver->pPrivateData); } // reconfig control pipe only EpNum = pUsbd->pDcConfig->EpNum; pUsbd->pDcConfig->EpNum = 1; /* control */ DC_ConfigDevice(pUsbd->pDcConfig); pUsbd->pDcConfig->EpNum = EpNum; // restore } pUsbd->ConfigurationNum = 0; pUsbd->State = USBDEV_STATE_DEFAULT; pUsbd->bHighSpeed = FALSE; break; case DC_SUSPEND: DEBUG_CB(("DC_SUSPEND\n")); pUsbd->PreState = pUsbd->State; pUsbd->State = USBDEV_STATE_SUSPENDED; break; case DC_RESUME: DEBUG_CB(("DC_RESUME\n")); pUsbd->State = pUsbd->PreState; break; case DC_HIGH_SPEED: DEBUG_CB(("DC_HIGH_SPEED\n")); pUsbd->bHighSpeed = TRUE; break; } } static int usbdCtrlPipeNotify(alt_u32 NotifyType, void *pPriv, alt_u8 *szCommand){ bool bWriteControlPipe = FALSE; USBDEV_DRIVER *pUsbd = (USBDEV_DRIVER *)pPriv; DEVICE_DRIVER *pDeviceDriver = pUsbd->pDeviceDriver; alt_u8 RequestType, bRequest; alt_u16 DescLen, wLength; USBDEV_EVENT_CONTEXT EventContext; DEBUG_OUT(("usbdCtrlPipeNotify, Notify=%08lXh\n", NotifyType)); wLength = szCommand[6] | szCommand[7] << 8; memset(&EventContext, 0, sizeof(EventContext)); EventContext.bHighSpeed = pUsbd->bHighSpeed; if (NotifyType == DC_SETUP_COMMAND){ RequestType = szCommand[0] & 0x60; if (RequestType == STANDARD_REQUEST){ bRequest = szCommand[1]; if (bRequest == GET_DESCRIPTOR){ if (pUsbd && pDeviceDriver && pDeviceDriver->DeviceNotify){ switch(szCommand[3]){ case DC_DEV_DESC_TYPE: DEBUG_OUT(("Get Device Descriptor\n")); EventContext.Event = USBDEV_EVENT_GET_DEVICE_DESC; bWriteControlPipe = pDeviceDriver->DeviceNotify(&EventContext, pDeviceDriver->pPrivateData); break; case DC_CONFIG_DESC_TYPE: DEBUG_OUT(("Get Configuration Descriptor\n")); EventContext.Event = USBDEV_EVENT_GET_CONFIGURATION_DESC; bWriteControlPipe = pDeviceDriver->DeviceNotify(&EventContext, pDeviceDriver->pPrivateData); break; case DC_STRING_DESC_TYPE: DEBUG_OUT(("Get String(ID=%d) Descriptor\n", szCommand[2])); EventContext.Event = USBDEV_EVENT_GET_STRING_DESC; EventContext.u.GetStringID = szCommand[2]; bWriteControlPipe = pDeviceDriver->DeviceNotify(&EventContext, pDeviceDriver->pPrivateData); break; case DC_CONFIG_QUALIFIER_TYPE: DEBUG_OUT(("Get Configuration Qualifier Descriptor\n")); DEBUG_OUT(("???? not implement\n")); break; } // switch //funcStandardRequestHandle(szCommand); } // if }else if (bRequest == SET_CONFIGURATION){ usbdSetConfiguration(pUsbd, szCommand); return 0; }else if (bRequest == SET_ADDRESS){ alt_u8 Address = szCommand[2] & 0x7F; DEBUG_OUT(("Set Address=%d\n", Address)); if (pUsbd && pDeviceDriver->DeviceNotify){ EventContext.Event = USBDEV_EVENT_SET_ADDRESS; EventContext.u.SetAddress = Address; pDeviceDriver->DeviceNotify(&EventContext, pDeviceDriver->pPrivateData); } // setup chip address DC_SetDeviceAddress((unsigned long)pUsbd->pDcConfig,Address); EventContext.DataLen = 0; bWriteControlPipe = TRUE; //usbdNotifyWriteControlPipe(pUsbd, NULL, 0); if(Address){ pUsbd->State = USBDEV_STATE_ADDRESSED; }else{ pUsbd->State = USBDEV_STATE_DEFAULT; } }else if (bRequest == SET_INTERFACE){ DEBUG_OUT(("CLEAR_FEATURE ???? not implement\n")); }else if (bRequest == CLEAR_FEATURE){ DEBUG_OUT(("CLEAR_FEATURE ???? not implement\n")); }else if (bRequest == SET_FEATURE){ DEBUG_OUT(("SET_FEATURE ???? not implement\n")); }else{ DEBUG_OUT(("Not supported request (%d). ?????\n", bRequest)); } }else{ DEBUG_OUT(("Not supported RequestType(%d). ?????\n", RequestType)); } } // end of if if (bWriteControlPipe){ /* Get max length that remote end wants */ DescLen = EventContext.DataLen; if (DescLen > wLength ) DescLen = wLength ; usbdNotifyWriteControlPipe(pUsbd, EventContext.pData, DescLen); }else{ //pdc_bus_stall_control_pipe(); usbdStallControlPipe(pUsbd); DEBUG_OUT(("Issue Stall\n")); } return 0; //????? } //============================================================================= void usbdStallControlPipe(USBDEV_DRIVER *pUsbd){ /* Stall Control Out Pipe */ gControlPipeOperation.Handle = pUsbd->ControlPipe; gControlPipeOperation.Context = (alt_u32) pUsbd; gControlPipeOperation.Operation = DC_PIPE_STALL; DC_PipeOperation(&gControlPipeOperation); } //============================================================================= bool usbdNotifyWriteControlPipe(USBDEV_DRIVER *pUsbd, alt_u8 *pData, alt_u16 DataLen){ //DC_FUNCTION *pFunc = &gDcFunction; struct DC_URB *pUrb; pUrb = &pUsbd->CtrlWriteUrb; if(!pData) DataLen = 0; /* Fill the URB and submit it */ DC_FILL_NON_ISO_URB(pUrb, pUsbd->ControlPipe, DC_PIPE_CONTROL, DC_OPR_WRITE, pData, DataLen, NULL,NULL); //#define DC_FILL_NON_ISO_URB(urb, handle, type, opr, buff, len, callback,priv) { //pUrb->pNext = NULL; //pUrb->Pipe = pFunc->ControlPipe; //urb->PipeType = type; urb->Operation = opr; urb->pTransferBuffer = buff; urb->TransferBufferLength = len; urb->ActualLength = 0; urb->Complete = callback; urb->pReqPriv = priv;} return DC_SubmitUrb(pUrb); } //============================================================================= USBDEV_HANDLE USBDEV_Init(DEVICE_DRIVER *pDeviceDriver){ int i; USBDEV_DRIVER *pUsbd; alt_irq_context IrgContext; bool bSuccess; alt_u32 Size; DC_EP_DESC *pEpDesc; pUsbd = (USBDEV_DRIVER *)malloc(sizeof(USBDEV_DRIVER)); if (!pUsbd) return 0; memset(pUsbd, 0, sizeof(USBDEV_DRIVER)); Size = sizeof(DC_CONFIG_DEVICE) + (sizeof(DC_EP_DESC) * DC_MAX_PIPES); pUsbd->pDcConfig = (DC_CONFIG_DEVICE *)malloc(Size); if (!pUsbd->pDcConfig){ free(pUsbd); return 0; } memset(pUsbd->pDcConfig, 0, Size); pUsbd->pDeviceDriver = pDeviceDriver; pUsbd->bHighSpeed = FALSE; // pUsbd->DeviceNotify = DeviceNotify; pUsbd->State = USBDEV_STATE_UNKNOWN; pUsbd->PreState = USBDEV_STATE_UNKNOWN; pUsbd->ControlPipe = DC_INVALID_PIPE_HANDLE; pUsbd->ConfigurationNum = 0; pUsbd->InterfaceNum = 0; pUsbd->AlternateNum = 0; // pUsbd->pDcConfig->EpNum = pDeviceDriver->NumOfEp; pUsbd->pDcConfig->Context = (alt_u32)pUsbd; pUsbd->pDcConfig->DeviceNotify = usbdDeviceNotify; for(i=0;iNumOfEp;i++){ pUsbd->pDcConfig->szEpDesc[i] = pDeviceDriver->szEpDesc[i]; } // disable interrupt IrgContext = alt_irq_disable_all(); // pUsbd->pDcConfig->EpNum = 1; // enble control-out pipe only bSuccess = DC_Init(pUsbd->pDcConfig); pUsbd->pDcConfig->EpNum = pDeviceDriver->NumOfEp; if (bSuccess){ pEpDesc = pUsbd->pDcConfig->szEpDesc; // open control pipe pUsbd->PipeDesc.Ep = pEpDesc->Number; pUsbd->PipeDesc.Dir = pEpDesc->Dir; pUsbd->PipeDesc.Context = (alt_u32)pEpDesc; pUsbd->PipeDesc.pPriv = (void*)pUsbd; pUsbd->PipeDesc.CtrlPipeNotify = usbdCtrlPipeNotify; pUsbd->ControlPipe = DC_OpenPipe(&pUsbd->PipeDesc); if(pUsbd->ControlPipe == DC_INVALID_PIPE_HANDLE) bSuccess = FALSE; } if (!bSuccess){ if (pUsbd->pDcConfig) free(pUsbd->pDcConfig); free(pUsbd); pUsbd = 0; } // enable interrupt alt_irq_enable_all(IrgContext); if (!pUsbd) DEBUG_ERR(("USBD_Init fail\n")); return pUsbd; } //============================================================================= void USBDEV_UnInit(USBDEV_HANDLE hUsbDevice){ USBDEV_DRIVER *pUsbDriver; pUsbDriver = (USBDEV_DRIVER *)hUsbDevice; if (pUsbDriver){ if (pUsbDriver->pDcConfig) free(pUsbDriver->pDcConfig); free(pUsbDriver); } } //============================================================================= //============================================================================= //============================================================================= /*--------------------------------------------------------------* * USB Class/Vendor specific functions *--------------------------------------------------------------*/ /* Make a configuration active */ void usbdSetConfiguration(USBDEV_DRIVER *pUsbd, unsigned char *szCommand) { int result; DEVICE_DRIVER *pDeviceDriver = pUsbd->pDeviceDriver; // struct list_head *tmp; DEBUG_OUT(("++ usbdSetConfiguration((command=%p)\n",szCommand)); if((pUsbd->State < USBDEV_STATE_ADDRESSED) || (szCommand[0] & DC_REQTYPE_DIR_MASK)) { /* You are not supposed to receive this in these states */ usbdStallControlPipe(pUsbd); return; } if(szCommand[2] > 1) { /* Invalid configuration */ /* Stall control in and out pipes */ usbdStallControlPipe(pUsbd); } else { USBDEV_EVENT_CONTEXT EventContext; if((pUsbd->ConfigurationNum) || (szCommand[2] == 0)) { int nOrgEpNum = pUsbd->pDcConfig->EpNum; /* Unconfigure the class drivers */ DEBUG_OUT(("Unconfigure the class drivers\n")); if (pUsbd && pDeviceDriver->DeviceNotify){ DEBUG_OUT(("Set Configuration(%d)\n",szCommand[2])); EventContext.Event = USBDEV_EVENT_SET_CONFIGURATION; EventContext.u.SetConfigurationValue = szCommand[2]; pDeviceDriver->DeviceNotify(&EventContext, pDeviceDriver->pPrivateData); } pUsbd->pDcConfig->EpNum = 1; /* Control */ result = DC_ConfigDevice(pUsbd->pDcConfig); pUsbd->State = USBDEV_STATE_ADDRESSED; pUsbd->pDcConfig->EpNum = nOrgEpNum; // restore } pUsbd->ConfigurationNum = szCommand[2]; pUsbd->InterfaceNum = pUsbd->AlternateNum = 0; if(pUsbd->ConfigurationNum) { bool bSuccess; /* Configure the class drivers */ DEBUG_OUT(("Configure the class drivers\n")); DEBUG_OUT(("Number of Endpoint=%d\n",pUsbd->pDcConfig->EpNum)); //pUsbd->pDcConfig->EpNum = 3; /* Control + bulk */ bSuccess = DC_ConfigDevice(pUsbd->pDcConfig); if (bSuccess) pUsbd->State = USBDEV_STATE_CONFIGURED; #if 1 if (pUsbd && pDeviceDriver->DeviceNotify){ DEBUG_OUT(("Set Configuration(%d)\n", szCommand[2])); EventContext.Event = USBDEV_EVENT_SET_CONFIGURATION; EventContext.u.SetConfigurationValue = szCommand[2]; pDeviceDriver->DeviceNotify(&EventContext, pDeviceDriver->pPrivateData); } #else tmp = pdc_class_drv_list.next; /* Find the class driver that supports this request */ while (tmp != &pdc_class_drv_list) { struct pdc_class_drv *cd = list_entry(tmp,struct pdc_class_drv, driver_list); tmp = tmp->next; if(cd->set_config) cd->set_config(cd->priv_data,bus_dev->configuration); } #endif } usbdNotifyWriteControlPipe(pUsbd, NULL, 0); } return; } /* End of usbdSetConfiguration() */