void Ep0Handler(void) { static int ep0SubState; // int i; u_char ep0_csr; rINDEX_REG=0; ep0_csr=rEP0_CSR; // DbgOut("<0:%x]",ep0_csr); //DATAEND interrupt(ep0_csr==0x0) will be ignored //because ep0State==EP0_STATE_INIT when the DATAEND interrupt is issued. if(ep0_csr & EP0_SETUP_END) { // Host may end GET_DESCRIPTOR operation without completing the IN data stage. // If host does that, SETUP_END bit will be set. // OUT_PKT_RDY has to be also cleared because status stage sets OUT_PKT_RDY to 1. // DbgOut("[SETUPEND]"); CLR_EP0_SETUP_END(); if(ep0_csr & EP0_OUT_PKT_READY) { FLUSH_EP0_FIFO(); //(???) //I think this isn't needed because EP0 flush is done automatically. CLR_EP0_OUT_PKT_RDY(); } ep0State=EP0_STATE_INIT; return; } //I think that EP0_SENT_STALL will not be set to 1. if(ep0_csr & EP0_SENT_STALL) { // DbgOut("[STALL]"); CLR_EP0_SENT_STALL(); if(ep0_csr & EP0_OUT_PKT_READY) { CLR_EP0_OUT_PKT_RDY(); } ep0State=EP0_STATE_INIT; return; } if((ep0_csr & EP0_OUT_PKT_READY) && (ep0State==EP0_STATE_INIT)) { RdPktEp0((u_char *)&descSetup,EP0_PKT_SIZE); switch(descSetup.bRequest) { case GET_DESCRIPTOR: switch(descSetup.bValueH) { case DEVICE_TYPE: // DbgOut("[GDD]"); CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_STATE_GD_DEV_0; break; case CONFIGURATION_TYPE: // DbgOut("[GDC]"); CLR_EP0_OUT_PKT_RDY(); if((descSetup.bLengthL+(descSetup.bLengthH<<8))>0x9) //bLengthH should be used for bLength=0x209 at WIN2K. ep0State=EP0_STATE_GD_CFG_0; //for WIN98,WIN2K else ep0State=EP0_STATE_GD_CFG_ONLY_0; //for WIN2K break; case STRING_TYPE: // DbgOut("[GDS]"); CLR_EP0_OUT_PKT_RDY(); switch(descSetup.bValueL) { case 0: ep0State=EP0_STATE_GD_STR_I0; break; case 1: ep0State=EP0_STATE_GD_STR_I1; break; case 2: ep0State=EP0_STATE_GD_STR_I2; break; default: // DbgOut("[UE:STRI?]"); break; } ep0SubState=0; break; case INTERFACE_TYPE: // DbgOut("[GDI]"); CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_STATE_GD_IF_ONLY_0; //for WIN98 break; case ENDPOINT_TYPE: // DbgOut("[GDE]"); CLR_EP0_OUT_PKT_RDY(); switch(descSetup.bValueL&0xf) { case 0: ep0State=EP0_STATE_GD_EP0_ONLY_0; break; case 1: ep0State=EP0_STATE_GD_EP1_ONLY_0; break; default: // DbgOut("[UE:GDE?]"); break; } break; default: // DbgOut("[UE:GD?]"); break; } break; case SET_ADDRESS: // DbgOut("[SA:%d]",descSetup.bValueL); rFUNC_ADDR_REG=descSetup.bValueL | 0x80; CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. ep0State=EP0_STATE_INIT; break; case SET_CONFIGURATION: // DbgOut("[SC]"); CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. ep0State=EP0_STATE_INIT; isUSBSet=true; break; default: // DbgOut("[UE:SETUP=%x]",descSetup.bRequest); CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. ep0State=EP0_STATE_INIT; break; } } switch(ep0State) { case EP0_STATE_INIT: break; //=== GET_DESCRIPTOR:DEVICE === case EP0_STATE_GD_DEV_0: // DbgOut("[GDD0]"); WrPktEp0((u_char *)&descDev+0,8); //EP0_PKT_SIZE SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_DEV_1; break; case EP0_STATE_GD_DEV_1: // DbgOut("[GDD1]"); WrPktEp0((u_char *)&descDev+0x8,8); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_DEV_2; break; case EP0_STATE_GD_DEV_2: // DbgOut("[GDD2]"); WrPktEp0((u_char *)&descDev+0x10,2); //8+8+2=0x12 SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:CONFIGURATION+INTERFACE+ENDPOINT0+ENDPOINT1 === //Windows98 gets these 4 descriptors all together by issuing only a request. //Windows2000 gets each descriptor seperately. case EP0_STATE_GD_CFG_0: // DbgOut("[GDC0]"); WrPktEp0((u_char *)&descConf+0,8); //EP0_PKT_SIZE SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_1; break; case EP0_STATE_GD_CFG_1: // DbgOut("[GDC1]"); WrPktEp0((u_char *)&descConf+8,1); WrPktEp0((u_char *)&descIf+0,7); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_2; break; case EP0_STATE_GD_CFG_2: // DbgOut("[GDC2]"); WrPktEp0((u_char *)&descIf+7,2); WrPktEp0((u_char *)&descEndpt0+0,6); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_3; break; case EP0_STATE_GD_CFG_3: // DbgOut("[GDC3]"); WrPktEp0((u_char *)&descEndpt0+6,1); WrPktEp0((u_char *)&descEndpt1+0,7); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_4; break; case EP0_STATE_GD_CFG_4: // DbgOut("[GDC4]"); //zero length data packit SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:CONFIGURATION ONLY=== case EP0_STATE_GD_CFG_ONLY_0: // DbgOut("[GDCO0]"); WrPktEp0((u_char *)&descConf+0,8); //EP0_PKT_SIZE SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_ONLY_1; break; case EP0_STATE_GD_CFG_ONLY_1: // DbgOut("[GDCO1]"); WrPktEp0((u_char *)&descConf+8,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:INTERFACE ONLY=== case EP0_STATE_GD_IF_ONLY_0: // DbgOut("[GDI0]"); WrPktEp0((u_char *)&descIf+0,8); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_IF_ONLY_1; break; case EP0_STATE_GD_IF_ONLY_1: // DbgOut("[GDI1]"); WrPktEp0((u_char *)&descIf+8,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:ENDPOINT 0 ONLY=== case EP0_STATE_GD_EP0_ONLY_0: // DbgOut("[GDE00]"); WrPktEp0((u_char *)&descEndpt0+0,7); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:ENDPOINT 1 ONLY=== case EP0_STATE_GD_EP1_ONLY_0: // DbgOut("[GDE10]"); WrPktEp0((u_char *)&descEndpt1+0,7); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:STRING === case EP0_STATE_GD_STR_I0: // DbgOut("[GDS0_0]"); WrPktEp0((u_char *)descStr0, 4 ); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; break; case EP0_STATE_GD_STR_I1: // DbgOut("[GDS1_%d]",ep0SubState); if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr1) ) { WrPktEp0((u_char *)descStr1+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_STR_I1; ep0SubState++; } else { WrPktEp0((u_char *)descStr1+(ep0SubState*EP0_PKT_SIZE), sizeof(descStr1)-(ep0SubState*EP0_PKT_SIZE)); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; } break; case EP0_STATE_GD_STR_I2: // DbgOut("[GDS2_%d]",ep0SubState); if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr2) ) { WrPktEp0((u_char *)descStr2+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_STR_I2; ep0SubState++; } else { // DbgOut("[E]"); WrPktEp0((u_char *)descStr2+(ep0SubState*EP0_PKT_SIZE), sizeof(descStr2)-(ep0SubState*EP0_PKT_SIZE)); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; } break; default: // DbgOut("UE:G?D"); break; } }
void Ep0Handler(void) { static int ep0SubState; int i; U8 ep0_csr; usbdevregs->INDEX_REG=0; ep0_csr=usbdevregs->EP0_CSR_IN_CSR1_REG; DbgPrintf("<0:%x]",ep0_csr); //DATAEND interrupt(ep0_csr==0x0) will be ignored //because ep0State==EP0_STATE_INIT when the DATAEND interrupt is issued. if(ep0_csr & EP0_SETUP_END) { // Host may end GET_DESCRIPTOR operation without completing the IN data stage. // If host does that, SETUP_END bit will be set. // OUT_PKT_RDY has to be also cleared because status stage sets OUT_PKT_RDY to 1. DbgPrintf("[SETUPEND]"); CLR_EP0_SETUP_END(); if(ep0_csr & EP0_OUT_PKT_READY) { FLUSH_EP0_FIFO(); //(???) //I think this isn't needed because EP0 flush is done automatically. CLR_EP0_OUT_PKT_RDY(); } ep0State=EP0_STATE_INIT; return; } //I think that EP0_SENT_STALL will not be set to 1. if(ep0_csr & EP0_SENT_STALL) { DbgPrintf("[STALL]"); CLR_EP0_SENT_STALL(); if(ep0_csr & EP0_OUT_PKT_READY) { CLR_EP0_OUT_PKT_RDY(); } ep0State=EP0_STATE_INIT; return; } if((ep0_csr & EP0_OUT_PKT_READY)) // && (ep0State==EP0_STATE_INIT)) { RdPktEp0((U8 *)&descSetup,EP0_PKT_SIZE); PrintEp0Pkt((U8 *)(&descSetup)); //DEBUG switch(descSetup.bRequest) { case GET_DESCRIPTOR: switch(descSetup.bValueH) { case DEVICE_TYPE: DbgPrintf("[GDD]"); CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_STATE_GD_DEV_0; break; case CONFIGURATION_TYPE: DbgPrintf("[GDC]"); CLR_EP0_OUT_PKT_RDY(); if((descSetup.bLengthL+(descSetup.bLengthH<<8))>0x9) //bLengthH should be used for bLength=0x209 at WIN2K. ep0State=EP0_STATE_GD_CFG_0; //for WIN98,WIN2K else ep0State=EP0_STATE_GD_CFG_ONLY_0; //for WIN2K break; case STRING_TYPE: DbgPrintf("[GDS]"); CLR_EP0_OUT_PKT_RDY(); switch(descSetup.bValueL) { case 0: ep0State=EP0_STATE_GD_STR_I0; break; case 1: ep0State=EP0_STATE_GD_STR_I1; break; case 2: ep0State=EP0_STATE_GD_STR_I2; break; default: DbgPrintf("[UE:STRI?]"); break; } ep0SubState=0; break; case INTERFACE_TYPE: DbgPrintf("[GDI]"); CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_STATE_GD_IF_ONLY_0; //for WIN98 break; case ENDPOINT_TYPE: DbgPrintf("[GDE]"); CLR_EP0_OUT_PKT_RDY(); switch(descSetup.bValueL&0xf) { case 0: ep0State=EP0_STATE_GD_EP0_ONLY_0; break; case 1: ep0State=EP0_STATE_GD_EP1_ONLY_0; break; default: DbgPrintf("[UE:GDE?]"); break; } break; default: DbgPrintf("[UE:GD?]"); break; } break; case SET_ADDRESS: DbgPrintf("[SA:%d]",descSetup.bValueL); usbdevregs->FUNC_ADDR_REG=descSetup.bValueL | 0x80; CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. ep0State=EP0_STATE_INIT; break; case SET_CONFIGURATION: DbgPrintf("[SC]"); ConfigSet.ConfigurationValue=descSetup.bValueL; CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. ep0State=EP0_STATE_INIT; isUsbdSetConfiguration=1; break; //////////////////////// For chapter 9 test //////////////////// case CLEAR_FEATURE: switch (descSetup.bmRequestType) { case DEVICE_RECIPIENT: if (descSetup.bValueL == 1) Rwuen = FALSE; break; case ENDPOINT_RECIPIENT: if (descSetup.bValueL == 0) { if((descSetup.bIndexL & 0x7f) == 0x00){ StatusGet.Endpoint0= 0; } if((descSetup.bIndexL & 0x8f) == 0x81){ // IN Endpoint 1 StatusGet.Endpoint1= 0; } if((descSetup.bIndexL & 0x8f) == 0x03){ // OUT Endpoint 3 StatusGet.Endpoint3= 0; } } break; default: break; } CLR_EP0_OUTPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case GET_CONFIGURATION: CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_CONFIG_SET; break; case GET_INTERFACE: CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_INTERFACE_GET; break; case GET_STATUS: switch(descSetup.bmRequestType) { case (0x80): CLR_EP0_OUT_PKT_RDY(); StatusGet.Device=((U8)Rwuen<<1)|(U8)Selfpwr; ep0State=EP0_GET_STATUS0; break; case (0x81): CLR_EP0_OUT_PKT_RDY(); StatusGet.Interface=0; ep0State=EP0_GET_STATUS1; break; case (0x82): CLR_EP0_OUT_PKT_RDY(); if((descSetup.bIndexL & 0x7f) == 0x00){ ep0State=EP0_GET_STATUS2; } if((descSetup.bIndexL & 0x8f) == 0x81){ ep0State=EP0_GET_STATUS3; } if((descSetup.bIndexL & 0x8f) == 0x03){ ep0State=EP0_GET_STATUS4; } break; default: break; } break; case SET_DESCRIPTOR: CLR_EP0_OUTPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case SET_FEATURE: switch (descSetup.bmRequestType) { case DEVICE_RECIPIENT: if (descSetup.bValueL == 1) Rwuen = TRUE; break; case ENDPOINT_RECIPIENT: if (descSetup.bValueL == 0) { if((descSetup.bIndexL & 0x7f) == 0x00){ StatusGet.Endpoint0= 1; } if((descSetup.bIndexL & 0x8f) == 0x81){ StatusGet.Endpoint1= 1; } if((descSetup.bIndexL & 0x8f) == 0x03){ StatusGet.Endpoint3= 1; } } break; default: break; } CLR_EP0_OUTPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case SET_INTERFACE: InterfaceGet.AlternateSetting= descSetup.bValueL; CLR_EP0_OUTPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case SYNCH_FRAME: ep0State=EP0_STATE_INIT; break; ////////////////////////////////////////////////////////////// default: DbgPrintf("[UE:SETUP=%x]",descSetup.bRequest); CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. ep0State=EP0_STATE_INIT; break; } } switch(ep0State) { case EP0_STATE_INIT: break; //=== GET_DESCRIPTOR:DEVICE === case EP0_STATE_GD_DEV_0: DbgPrintf("[GDD0]"); WrPktEp0((U8 *)&descDev+0,8); //EP0_PKT_SIZE SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_DEV_1; break; case EP0_STATE_GD_DEV_1: DbgPrintf("[GDD1]"); WrPktEp0((U8 *)&descDev+0x8,8); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_DEV_2; break; case EP0_STATE_GD_DEV_2: DbgPrintf("[GDD2]"); WrPktEp0((U8 *)&descDev+0x10,2); //8+8+2=0x12 SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:CONFIGURATION+INTERFACE+ENDPOINT0+ENDPOINT1 === //Windows98 gets these 4 descriptors all together by issuing only a request. //Windows2000 gets each descriptor seperately. case EP0_STATE_GD_CFG_0: DbgPrintf("[GDC0]"); WrPktEp0((U8 *)&descConf+0,8); //EP0_PKT_SIZE SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_1; break; case EP0_STATE_GD_CFG_1: DbgPrintf("[GDC1]"); WrPktEp0((U8 *)&descConf+8,1); WrPktEp0((U8 *)&descIf+0,7); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_2; break; case EP0_STATE_GD_CFG_2: DbgPrintf("[GDC2]"); WrPktEp0((U8 *)&descIf+7,2); WrPktEp0((U8 *)&descEndpt0+0,6); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_3; break; case EP0_STATE_GD_CFG_3: DbgPrintf("[GDC3]"); WrPktEp0((U8 *)&descEndpt0+6,1); WrPktEp0((U8 *)&descEndpt1+0,7); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_4; break; case EP0_STATE_GD_CFG_4: DbgPrintf("[GDC4]"); //zero length data packit SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:CONFIGURATION ONLY=== case EP0_STATE_GD_CFG_ONLY_0: DbgPrintf("[GDCO0]"); WrPktEp0((U8 *)&descConf+0,8); //EP0_PKT_SIZE SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_ONLY_1; break; case EP0_STATE_GD_CFG_ONLY_1: DbgPrintf("[GDCO1]"); WrPktEp0((U8 *)&descConf+8,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:INTERFACE ONLY=== case EP0_STATE_GD_IF_ONLY_0: DbgPrintf("[GDI0]"); WrPktEp0((U8 *)&descIf+0,8); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_IF_ONLY_1; break; case EP0_STATE_GD_IF_ONLY_1: DbgPrintf("[GDI1]"); WrPktEp0((U8 *)&descIf+8,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:ENDPOINT 0 ONLY=== case EP0_STATE_GD_EP0_ONLY_0: DbgPrintf("[GDE00]"); WrPktEp0((U8 *)&descEndpt0+0,7); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:ENDPOINT 1 ONLY=== case EP0_STATE_GD_EP1_ONLY_0: DbgPrintf("[GDE10]"); WrPktEp0((U8 *)&descEndpt1+0,7); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //////////////////////////////////////////// case EP0_INTERFACE_GET: WrPktEp0((U8 *)&InterfaceGet+0,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:STRING === case EP0_STATE_GD_STR_I0: DbgPrintf("[GDS0_0]"); WrPktEp0((U8 *)descStr0, 4 ); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; break; case EP0_STATE_GD_STR_I1: DbgPrintf("[GDS1_%d]",ep0SubState); if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr1) ) { WrPktEp0((U8 *)descStr1+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_STR_I1; ep0SubState++; } else { WrPktEp0((U8 *)descStr1+(ep0SubState*EP0_PKT_SIZE), sizeof(descStr1)-(ep0SubState*EP0_PKT_SIZE)); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; } break; case EP0_STATE_GD_STR_I2: DbgPrintf("[GDS2_%d]",ep0SubState); if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr2) ) { WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_STR_I2; ep0SubState++; } else { DbgPrintf("[E]"); WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE), sizeof(descStr2)-(ep0SubState*EP0_PKT_SIZE)); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; } break; case EP0_CONFIG_SET: WrPktEp0((U8 *)&ConfigSet+0,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS0: WrPktEp0((U8 *)&StatusGet+0,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS1: WrPktEp0((U8 *)&StatusGet+1,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS2: WrPktEp0((U8 *)&StatusGet+2,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS3: WrPktEp0((U8 *)&StatusGet+3,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS4: WrPktEp0((U8 *)&StatusGet+4,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; default: DbgPrintf("UE:G?D"); break; } }
void Ep0Handler(void) { static int ep0SubState; int i; U8 ep0_csr; //U8 in_csr1; rINDEX_REG=0; ep0_csr=rEP0_CSR; //DbgPrintf("<0:%x]",ep0_csr); //DATAEND interrupt(ep0_csr==0x0) will be ignored //because ep0State==EP0_STATE_INIT when the DATAEND interrupt is issued. if(ep0_csr & EP0_SETUP_END) { //Uart_Printf("EP0_SETUP_END\n"); // Host may end GET_DESCRIPTOR operation without completing the IN data stage. // If host does that, SETUP_END bit will be set. // OUT_PKT_RDY has to be also cleared because status stage sets OUT_PKT_RDY to 1. //DbgPrintf("[SETUPEND]"); CLR_EP0_SETUP_END(); if(ep0_csr & EP0_OUT_PKT_READY) { //Uart_Printf("EP0_OUT_PKT_READY\n"); FLUSH_EP0_FIFO(); //(???) //I think this isn't needed because EP0 flush is done automatically. CLR_EP0_OUT_PKT_RDY(); } ep0State=EP0_STATE_INIT; return; } //I think that EP0_SENT_STALL will not be set to 1. if(ep0_csr & EP0_SENT_STALL) { //Uart_Printf("EP0_SENT_STALL\n"); //DbgPrintf("[STALL]"); CLR_EP0_SENT_STALL(); if(ep0_csr & EP0_OUT_PKT_READY) { CLR_EP0_OUT_PKT_RDY(); } ep0State=EP0_STATE_INIT; return; } if((ep0_csr & EP0_OUT_PKT_READY) && (ep0State==EP0_STATE_INIT)) { RdPktEp0((U8 *)&descSetup,EP0_PKT_SIZE); //if((descSetup.bmRequestType != 0xa1) && (descSetup.bmRequestType != 0x21)) if(descSetup.bmRequestType != 0x21) { switch(descSetup.bRequest) { case GET_DESCRIPTOR: switch(descSetup.bValueH) { case DEVICE_TYPE: Uart_Printf("DEVICE_DESCRIPTOR\n"); CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_STATE_GD_DEV_0; break; case CONFIGURATION_TYPE: Uart_Printf("CONFIGURATION_DESCRIPTOR\n"); CLR_EP0_OUT_PKT_RDY(); if((descSetup.bLengthL+(descSetup.bLengthH<<8))>0x9) //bLengthH should be used for bLength=0x209 at WIN2K. ep0State=EP0_STATE_GD_CFG_0; //for WIN98,WIN2K else ep0State=EP0_STATE_GD_CFG_ONLY_0; //for WIN2K break; case STRING_TYPE: Uart_Printf("STRING_TYPE_DESCRIPTOR\n"); CLR_EP0_OUT_PKT_RDY(); switch(descSetup.bValueL) { case 0: ep0State=EP0_STATE_GD_STR_I0; break; case 1: ep0State=EP0_STATE_GD_STR_I1; break; case 2: ep0State=EP0_STATE_GD_STR_I2; break; case 3: ep0State=EP0_STATE_GD_STR_I3; break; default: break; } ep0SubState=0; break; case INTERFACE_TYPE: Uart_Printf("INTERFACE_DESCRIPTOR\n"); CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_STATE_GD_IF_ONLY_0; //for WIN98 break; case ENDPOINT_TYPE: Uart_Printf("ENDPOINT_DESCRIPTOR\n"); CLR_EP0_OUT_PKT_RDY(); switch(descSetup.bValueL&0xf) { case 0: ep0State=EP0_STATE_GD_EP1_ONLY_0; break; case 1: ep0State=EP0_STATE_GD_EP3_ONLY_0; break; default: break; } break; case REPORT_TYPE: Uart_Printf("GET_REPORT_DESCRIPTOR\n"); CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_STATE_REPORT_DESCIRPTOR0; break; default: break; } break; case SET_ADDRESS: Uart_Printf("SET_ADDRESS\n"); rFUNC_ADDR_REG=descSetup.bValueL | 0x80; CLR_EP0_OUTPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case SET_CONFIGURATION: Uart_Printf("SET_CONFIGURATION\n"); ConfigSet.ConfigurationValue=descSetup.bValueL; Uart_Printf("%d\n",ConfigSet.ConfigurationValue); CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. ep0State=EP0_STATE_INIT; //isUsbdSetConfiguration=1; break; /* //////////////////////// For chapter 9 test //////////////////// case CLEAR_FEATURE: Uart_Printf("CLEAR_FEATURE\n"); switch (descSetup.bmRequestType) { case DEVICE_RECIPIENT: if (descSetup.bValueL == 1) Rwuen = FALSE; break; case ENDPOINT_RECIPIENT: if (descSetup.bValueL == 0) { if((descSetup.bIndexL & 0x7f) == 0x00){ StatusGet.Endpoint0= 0; } if((descSetup.bIndexL & 0x8f) == 0x81){ // IN Endpoint 1 StatusGet.Endpoint1= 0; } if((descSetup.bIndexL & 0x8f) == 0x03){ // OUT Endpoint 3 StatusGet.Endpoint3= 0; } } break; default: break; } CLR_EP0_OUTPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case GET_CONFIGURATION: Uart_Printf("GET_CONFIGURATION\n"); CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_CONFIG_SET; break; case GET_INTERFACE: Uart_Printf("GET_INTERACE\n"); CLR_EP0_OUT_PKT_RDY(); ep0State=EP0_INTERFACE_GET; break; case GET_STATUS: Uart_Printf("GET_STATUS\n"); switch(descSetup.bmRequestType) { case (0x80): CLR_EP0_OUT_PKT_RDY(); StatusGet.Device=((U8)Rwuen<<1)|(U8)Selfpwr; ep0State=EP0_GET_STATUS0; break; case (0x81): CLR_EP0_OUT_PKT_RDY(); StatusGet.Interface=0; ep0State=EP0_GET_STATUS1; break; case (0x82): CLR_EP0_OUT_PKT_RDY(); if((descSetup.bIndexL & 0x7f) == 0x00){ ep0State=EP0_GET_STATUS2; } if((descSetup.bIndexL & 0x8f) == 0x81){ ep0State=EP0_GET_STATUS3; } if((descSetup.bIndexL & 0x8f) == 0x03){ ep0State=EP0_GET_STATUS4; } break; default: break; } break; case SET_DESCRIPTOR: Uart_Printf("SET_DESCRIPTOR\n"); CLR_EP0_OUTPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case SET_FEATURE: Uart_Printf("SET_FEARURE\n"); switch (descSetup.bmRequestType) { case DEVICE_RECIPIENT: if (descSetup.bValueL == 1) Rwuen = TRUE; break; case ENDPOINT_RECIPIENT: if (descSetup.bValueL == 0) { if((descSetup.bIndexL & 0x7f) == 0x00){ StatusGet.Endpoint0= 1; } if((descSetup.bIndexL & 0x8f) == 0x81){ StatusGet.Endpoint1= 1; } if((descSetup.bIndexL & 0x8f) == 0x03){ StatusGet.Endpoint3= 1; } } break; default: break; } CLR_EP0_OUTPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case SET_INTERFACE: InterfaceGet.AlternateSetting= descSetup.bValueL; CLR_EP0_OUTPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case SYNCH_FRAME: ep0State=EP0_STATE_INIT; break; ///////////////////////////////////////////////////////////// */ default: CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. ep0State=EP0_STATE_INIT; break; } } else { CLR_EP0_OUT_PKT_RDY(); //CLR_EP0_SENT_STALL(); //CLR_EP0_SETUP_END(); Uart_Printf("HDI_REQUEST\n"); //if(descSetup.bRequest == 0x0a) //{ //case SET_IDLE: //Uart_Printf("ÉèÖÿÕÏÐ\n"); //WrPktEp0(Buf_Idle,0); //break; //} } } switch(ep0State) { case EP0_STATE_INIT: break; //------------------------------------GET_DESCRIPTOR:DEVICE----------------------------- case EP0_STATE_GD_DEV_0: WrPktEp0((U8 *)&descDev+0,8); //EP0_PKT_SIZE SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_DEV_1; break; case EP0_STATE_GD_DEV_1: WrPktEp0((U8 *)&descDev+0x8,8); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_DEV_2; break; case EP0_STATE_GD_DEV_2: WrPktEp0((U8 *)&descDev+0x10,2); //8+8+2=0x12 SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:CONFIGURATION+INTERFACE+ENDPOINT0+ENDPOINT1 === //Windows98 gets these 4 descriptors all together by issuing only a request. //Windows2000 gets each descriptor seperately. case EP0_STATE_GD_CFG_0: WrPktEp0((U8 *)&descConf+0,8); //EP0_PKT_SIZE SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_1; break; case EP0_STATE_GD_CFG_1: WrPktEp0((U8 *)&descConf+8,1); WrPktEp0((U8 *)&descIf+0,7); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_2; break; case EP0_STATE_GD_CFG_2: WrPktEp0((U8 *)&descIf+7,2); WrPktEp0((U8 *)&descHID+0,6); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_3; break; case EP0_STATE_GD_CFG_3: WrPktEp0((U8 *)&descHID+6,3); WrPktEp0((U8 *)&descEndpt1+0,5); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_4; break; case EP0_STATE_GD_CFG_4: WrPktEp0((U8 *)&descEndpt1+5,2); WrPktEp0((U8 *)&descEndpt3,6); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_5; // SET_EP0_INPKTRDY_DATAEND(); // ep0State=EP0_STATE_INIT; break; case EP0_STATE_GD_CFG_5: WrPktEp0((U8 *)&descEndpt3+5,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; /* case EP0_STATE_GD_CFG_5: //DbgPrintf("[GDC4]"); WrPktEp0((U8 *)&descEndpt3+6,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; */ /* case EP0_STATE_GD_CFG_2: DbgPrintf("[GDC2]"); WrPktEp0((U8 *)&descIf+7,2); WrPktEp0((U8 *)&descEndpt0+0,6); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_3; break; case EP0_STATE_GD_CFG_3: DbgPrintf("[GDC3]"); WrPktEp0((U8 *)&descEndpt0+6,1); WrPktEp0((U8 *)&descEndpt1+0,7); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_4; break; case EP0_STATE_GD_CFG_4: DbgPrintf("[GDC4]"); //zero length data packit SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; */ //=== GET_DESCRIPTOR:CONFIGURATION ONLY=== case EP0_STATE_GD_CFG_ONLY_0: WrPktEp0((U8 *)&descConf+0,8); //EP0_PKT_SIZE SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_CFG_ONLY_1; break; case EP0_STATE_GD_CFG_ONLY_1: WrPktEp0((U8 *)&descConf+8,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:INTERFACE ONLY=== case EP0_STATE_GD_IF_ONLY_0: WrPktEp0((U8 *)&descIf+0,8); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_IF_ONLY_1; break; case EP0_STATE_GD_IF_ONLY_1: WrPktEp0((U8 *)&descIf+8,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:ENDPOINT 0 ONLY=== case EP0_STATE_GD_EP1_ONLY_0: WrPktEp0((U8 *)&descEndpt1+0,7); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:ENDPOINT 1 ONLY=== case EP0_STATE_GD_EP3_ONLY_0: DbgPrintf("[GDE10]"); WrPktEp0((U8 *)&descEndpt3+0,7); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //////////////////////////////////////////// case EP0_INTERFACE_GET: WrPktEp0((U8 *)&InterfaceGet+0,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; //=== GET_DESCRIPTOR:STRING === case EP0_STATE_GD_STR_I0: WrPktEp0((U8 *)descStr0, 4 ); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; break; case EP0_STATE_GD_STR_I1: if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr1) ) { WrPktEp0((U8 *)descStr1+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_STR_I1; ep0SubState++; } else { WrPktEp0((U8 *)descStr1+(ep0SubState*EP0_PKT_SIZE), sizeof(descStr1)-(ep0SubState*EP0_PKT_SIZE)); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; } break; case EP0_STATE_GD_STR_I2: if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr2) ) { WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_STR_I2; ep0SubState++; } else { WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE), sizeof(descStr2)-(ep0SubState*EP0_PKT_SIZE)); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; } break; case EP0_STATE_GD_STR_I3: if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr3) ) { WrPktEp0((U8 *)descStr3+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_GD_STR_I3; ep0SubState++; } else { WrPktEp0((U8 *)descStr3+(ep0SubState*EP0_PKT_SIZE), sizeof(descStr3)-(ep0SubState*EP0_PKT_SIZE)); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; } break; case EP0_CONFIG_SET: WrPktEp0((U8 *)&ConfigSet+0,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS0: WrPktEp0((U8 *)&StatusGet+0,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS1: WrPktEp0((U8 *)&StatusGet+1,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS2: WrPktEp0((U8 *)&StatusGet+2,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS3: WrPktEp0((U8 *)&StatusGet+3,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_GET_STATUS4: WrPktEp0((U8 *)&StatusGet+4,1); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; break; case EP0_STATE_REPORT_DESCIRPTOR0: if((ep0SubState*8+8) < sizeof(ReportDescriptor)) { WrPktEp0((U8*)ReportDescriptor+8*ep0SubState,8); SET_EP0_IN_PKT_RDY(); ep0State=EP0_STATE_REPORT_DESCIRPTOR0; ep0SubState++; } else { WrPktEp0((U8 *)ReportDescriptor+(ep0SubState*8),sizeof(ReportDescriptor)-(ep0SubState*8)); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_INIT; ep0SubState=0; } break; /* case EP0_STATE_REPORT_DESCIRPTOR1: WrPktEp0((U8*)ReportDescriptor+7,8); SET_EP0_IN_PKT_RDY(); SET_EP0_INPKTRDY_DATAEND(); ep0State=EP0_STATE_REPORT_DESCIRPTOR2; break; */ default: break; } }