From 4df85b2fb8cf360f6fe36bb0d3121b55ac51a84e Mon Sep 17 00:00:00 2001 From: DizzyOfCRN Date: Thu, 7 Aug 2014 14:23:08 +0000 Subject: [PATCH] Binds with USB3.0 root hub devices - asks and receives the correct root hub descriptor (UDT_SSHUB) git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@49253 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- rom/usb/classes/hubss/hubss.class.c | 287 ++++++++++++++++++------------------ rom/usb/classes/hubss/hubss.h | 28 ++-- 2 files changed, 157 insertions(+), 158 deletions(-) diff --git a/rom/usb/classes/hubss/hubss.class.c b/rom/usb/classes/hubss/hubss.class.c index 79b6427a7b..3bb39091e9 100644 --- a/rom/usb/classes/hubss/hubss.class.c +++ b/rom/usb/classes/hubss/hubss.class.c @@ -8,6 +8,8 @@ #include "debug.h" +#include + #include "hubss.class.h" /* /// "Lib Stuff" */ @@ -58,11 +60,9 @@ struct NepClassHub * GM_UNIQUENAME(usbAttemptDeviceBinding)(struct NepHubBase *n KPRINTF(1, ("nepHubAttemptDeviceBinding(%p)\n", pd)); if((ps = OpenLibrary("poseidon.library", 4))) { - psdGetAttrs(PGA_DEVICE, pd, - DA_Class, &devclass, - DA_IsSuperspeed, &issuperspeed, - TAG_DONE); + psdGetAttrs(PGA_DEVICE, pd, DA_Class, &devclass, DA_IsSuperspeed, &issuperspeed, TAG_DONE); CloseLibrary(ps); + if((devclass == HUB_CLASSCODE) && (issuperspeed)) { return(GM_UNIQUENAME(usbForceDeviceBinding)(nh, pd)); } @@ -734,7 +734,7 @@ AROS_UFH0(void, GM_UNIQUENAME(nHubTask)) /* /// "nAllocHub()" */ struct NepClassHub * GM_UNIQUENAME(nAllocHub)(void) { - struct UsbHubDesc *uhd; + struct UsbSSHubDesc *usshd; struct Task *thistask; struct NepClassHub *nch; struct UsbHubStatus uhhs; @@ -742,207 +742,205 @@ struct NepClassHub * GM_UNIQUENAME(nAllocHub)(void) { LONG ioerr; ULONG len; UWORD num; - UBYTE buf; - IPTR ishighspeed = 0; + UBYTE buf[2]; + IPTR issuperspeed = 0; IPTR prodid; IPTR vendid; BOOL overcurrent = FALSE; thistask = FindTask(NULL); nch = thistask->tc_UserData; - do - { - if(!(nch->nch_Base = OpenLibrary("poseidon.library", 4))) - { + + do { + if(!(nch->nch_Base = OpenLibrary("poseidon.library", 4))) { Alert(AG_OpenLib); break; } psdGetAttrs(PGA_DEVICE, nch->nch_Device, DA_Hardware, &nch->nch_Hardware, - DA_IsHighspeed, &ishighspeed, + DA_IsSuperspeed, &issuperspeed, DA_ProductID, &prodid, DA_VendorID, &vendid, DA_HubDevice, &parenthub, TAG_END); nch->nch_IsRootHub = (parenthub ? FALSE : TRUE); - nch->nch_IsUSB20 = ishighspeed; + nch->nch_IsUSB30 = issuperspeed; + // try to select multi TT interface first nch->nch_Interface = psdFindInterface(nch->nch_Device, NULL, IFA_Class, HUB_CLASSCODE, IFA_Protocol, 2, IFA_AlternateNum, 0xffffffff, TAG_END); - if(!nch->nch_Interface) - { + + if(!nch->nch_Interface) { // any will do nch->nch_Interface = psdFindInterface(nch->nch_Device, NULL, IFA_Class, HUB_CLASSCODE, TAG_END); } - if((vendid == 0x05E3) && ishighspeed) - { - psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, "Genesys Logic hubs are broken and will cause failures with USB 2.0 devices."); - psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, "If you encounter problems, try the device without the hub."); - psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, "If this solves the problem, you need to buy a different USB 2.0 hub."); - } - if(!nch->nch_Interface) - { + if(!nch->nch_Interface) { KPRINTF(1, ("Ooops!?! No interfaces defined?\n")); break; } + nch->nch_EP1 = psdFindEndpoint(nch->nch_Interface, NULL, EA_IsIn, TRUE, EA_TransferType, USEAF_INTERRUPT, TAG_END); - if(!nch->nch_EP1) - { + if(!nch->nch_EP1) { psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "Ooops!?! No endpoints defined?"); KPRINTF(1, ("Ooops!?! No Endpoints defined?\n")); break; } - if((nch->nch_CtrlMsgPort = CreateMsgPort())) - { - if((nch->nch_TaskMsgPort = CreateMsgPort())) - { - if((nch->nch_EP0Pipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, NULL))) - { + + if((nch->nch_CtrlMsgPort = CreateMsgPort())) { + if((nch->nch_TaskMsgPort = CreateMsgPort())) { + if((nch->nch_EP0Pipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, NULL))) { + psdSetAttrs(PGA_PIPE, nch->nch_EP0Pipe, PPA_NakTimeout, TRUE, PPA_NakTimeoutTime, 1000, TAG_END); + psdSetAltInterface(nch->nch_EP0Pipe, nch->nch_Interface); - if((nch->nch_EP1Pipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, nch->nch_EP1))) - { - psdSetAttrs(PGA_PIPE, nch->nch_EP1Pipe, - PPA_AllowRuntPackets, TRUE, - TAG_END); - psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_CLASS|URTF_DEVICE, - USR_GET_DESCRIPTOR, UDT_HUB<<8, 0); - ioerr = psdDoPipe(nch->nch_EP0Pipe, &buf, 1); - if((!ioerr) || (ioerr == UHIOERR_OVERFLOW)) - { - len = buf; - if((uhd = psdAllocVec(len))) - { - ioerr = psdDoPipe(nch->nch_EP0Pipe, uhd, len); - if(!ioerr) - { - nch->nch_NumPorts = uhd->bNbrPorts; - nch->nch_HubAttr = AROS_WORD2LE(uhd->wHubCharacteristics); - nch->nch_PwrGoodTime = uhd->bPwrOn2PwrGood<<1; - nch->nch_HubCurrent = uhd->bHubContrCurrent; - nch->nch_Removable = 0; - if(nch->nch_HubAttr & UHCM_THINK_TIME) - { - psdSetAttrs(PGA_DEVICE, nch->nch_Device, - DA_HubThinkTime, (nch->nch_HubAttr & UHCM_THINK_TIME)>>UHCS_THINK_TIME, - TAG_END); - } - for(num = 0; num < ((nch->nch_NumPorts + 7)>>3); num++) - { - nch->nch_Removable |= ((&uhd->DeviceRemovable)[num])<<(num<<3); - } - KPRINTF(2, ("Hub with %ld ports\n" - " Characteristics 0x%04lx\n" - " PowerGood after %ld ms\n" - " Power consumption %ld mA\n", - nch->nch_NumPorts, - nch->nch_HubAttr, - nch->nch_PwrGoodTime, nch->nch_HubCurrent)); - psdFreeVec(uhd); - - psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_CLASS|URTF_DEVICE, - USR_GET_STATUS, 0, 0); - ioerr = psdDoPipe(nch->nch_EP0Pipe, &uhhs, sizeof(struct UsbHubStatus)); - uhhs.wHubStatus = AROS_WORD2LE(uhhs.wHubStatus); - uhhs.wHubChange = AROS_WORD2LE(uhhs.wHubChange); - if(!ioerr) - { - struct PsdConfig *pc = NULL; - struct PsdHardware *phw = NULL; - if(uhhs.wHubStatus & UHSF_OVER_CURRENT) - { - psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, - "Hub over-current situation detected! Resolve this first!"); - //overcurrent = TRUE; + if((nch->nch_EP1Pipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, nch->nch_EP1))) { + + psdSetAttrs(PGA_PIPE, nch->nch_EP1Pipe, PPA_AllowRuntPackets, TRUE, TAG_END); + psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_CLASS|URTF_DEVICE, USR_GET_DESCRIPTOR, UDT_SSHUB<<8, 0); + + ioerr = psdDoPipe(nch->nch_EP0Pipe, &buf, 2); + + if(buf[1] == UDT_SSHUB) { + + if((!ioerr) || (ioerr == UHIOERR_OVERFLOW)) { + len = buf[0]; + + if((usshd = psdAllocVec(len))) { + ioerr = psdDoPipe(nch->nch_EP0Pipe, usshd, len); + + if(!ioerr) { + nch->nch_NumPorts = usshd->bNbrPorts; + nch->nch_HubAttr = AROS_WORD2LE(usshd->wHubCharacteristics); + nch->nch_PwrGoodTime = usshd->bPwrOn2PwrGood<<1; + nch->nch_HubCurrent = usshd->bHubContrCurrent; + nch->nch_HubHdrDecLat = usshd->bHubHdrDecLat; + nch->nch_HubDelay = usshd->wHubDelay; + nch->nch_Removable = 0; //usshd->DeviceRemovable; + + if(nch->nch_HubAttr & UHCM_THINK_TIME) { + psdSetAttrs(PGA_DEVICE, nch->nch_Device, DA_HubThinkTime, (nch->nch_HubAttr & UHCM_THINK_TIME)>>UHCS_THINK_TIME, TAG_END); } - psdGetAttrs(PGA_DEVICE, nch->nch_Device, - DA_Config, &pc, - DA_Hardware, &phw, - TAG_END); - if(uhhs.wHubStatus & UHSF_LOCAL_POWER_LOST) + for(num = 0; num < ((nch->nch_NumPorts + 7)>>3); num++) { + nch->nch_Removable |= ((&usshd->DeviceRemovable)[num])<<(num<<3); + } + KPRINTF(2, ("Hub with %ld ports\n" + " Characteristics 0x%04lx\n" + " PowerGood after %ld ms\n" + " Power consumption %ld mA\n", + nch->nch_NumPorts, + nch->nch_HubAttr, + nch->nch_PwrGoodTime, nch->nch_HubCurrent)); + + psdFreeVec(usshd); + + psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_CLASS|URTF_DEVICE, + USR_GET_STATUS, 0, 0); + ioerr = psdDoPipe(nch->nch_EP0Pipe, &uhhs, sizeof(struct UsbHubStatus)); + uhhs.wHubStatus = AROS_WORD2LE(uhhs.wHubStatus); + uhhs.wHubChange = AROS_WORD2LE(uhhs.wHubChange); + if(!ioerr) { - if(pc && phw) + struct PsdConfig *pc = NULL; + struct PsdHardware *phw = NULL; + if(uhhs.wHubStatus & UHSF_OVER_CURRENT) { - psdSetAttrs(PGA_CONFIG, pc, CA_SelfPowered, FALSE, TAG_END); - psdCalculatePower(phw); + psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, + "Hub over-current situation detected! Resolve this first!"); + //overcurrent = TRUE; } - } else { - if(pc && phw) + + psdGetAttrs(PGA_DEVICE, nch->nch_Device, + DA_Config, &pc, + DA_Hardware, &phw, + TAG_END); + if(uhhs.wHubStatus & UHSF_LOCAL_POWER_LOST) { - psdSetAttrs(PGA_CONFIG, pc, CA_SelfPowered, TRUE, TAG_END); - psdCalculatePower(phw); + if(pc && phw) + { + psdSetAttrs(PGA_CONFIG, pc, CA_SelfPowered, FALSE, TAG_END); + psdCalculatePower(phw); + } + } else { + if(pc && phw) + { + psdSetAttrs(PGA_CONFIG, pc, CA_SelfPowered, TRUE, TAG_END); + psdCalculatePower(phw); + } } } - } - if(!overcurrent) - { - if((nch->nch_Downstream = psdAllocVec((ULONG) nch->nch_NumPorts*sizeof(APTR)))) + if(!overcurrent) { - /*for(num = 1; num <= nch->nch_NumPorts; num++) + if((nch->nch_Downstream = psdAllocVec((ULONG) nch->nch_NumPorts*sizeof(APTR)))) { - GM_UNIQUENAME(nClearPortStatus)(nch, num); - } - psdDelayMS(20);*/ - KPRINTF(2, ("Powering up ports...\n")); - for(num = 1; num <= nch->nch_NumPorts; num++) - { - psdPipeSetup(nch->nch_EP0Pipe, URTF_CLASS|URTF_OTHER, - USR_SET_FEATURE, UFS_PORT_POWER, (ULONG) num); - ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0); - if(ioerr) + /*for(num = 1; num <= nch->nch_NumPorts; num++) { - psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, - "PORT_POWER for port %ld failed: %s (%ld)", - num, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr); - KPRINTF(1, ("PORT_POWER for port %ld failed %ld!\n", num, ioerr)); + GM_UNIQUENAME(nClearPortStatus)(nch, num); } - } - psdDelayMS((ULONG) nch->nch_PwrGoodTime + 15); - - psdAddErrorMsg(RETURN_OK, (STRPTR) libname, - "Hub with %ld ports successfully configured.", - nch->nch_NumPorts); + psdDelayMS(20);*/ + KPRINTF(2, ("Powering up ports...\n")); + for(num = 1; num <= nch->nch_NumPorts; num++) + { + psdPipeSetup(nch->nch_EP0Pipe, URTF_CLASS|URTF_OTHER, + USR_SET_FEATURE, UFS_PORT_POWER, (ULONG) num); + ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0); + if(ioerr) + { + psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, + "PORT_POWER for port %ld failed: %s (%ld)", + num, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr); + KPRINTF(1, ("PORT_POWER for port %ld failed %ld!\n", num, ioerr)); + } + } + psdDelayMS((ULONG) nch->nch_PwrGoodTime + 15); - KPRINTF(10, ("%s ready!\n", thistask->tc_Node.ln_Name)); - nch->nch_Task = thistask; - return(nch); - } else { - KPRINTF(1, ("No downstream port array memory!\n")); + psdAddErrorMsg(RETURN_OK, (STRPTR) libname, + "Hub with %ld ports successfully configured.", + nch->nch_NumPorts); + + KPRINTF(10, ("%s ready!\n", thistask->tc_Node.ln_Name)); + nch->nch_Task = thistask; + return(nch); + } else { + KPRINTF(1, ("No downstream port array memory!\n")); + } } + } else { + psdFreeVec(usshd); + psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, + "GET_HUB_DESCRIPTOR (%ld) failed: %s (%ld)", + len, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr); + KPRINTF(1, ("GET_HUB_DESCRIPTOR (%ld) failed %ld!\n", len, ioerr)); } + } else { - psdFreeVec(uhd); - psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, - "GET_HUB_DESCRIPTOR (%ld) failed: %s (%ld)", - len, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr); - KPRINTF(1, ("GET_HUB_DESCRIPTOR (%ld) failed %ld!\n", len, ioerr)); + KPRINTF(1, ("No Hub Descriptor memory!\n")); } } else { - KPRINTF(1, ("No Hub Descriptor memory!\n")); + psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, + "GET_HUB_DESCRIPTOR (%ld) failed: %s (%ld)", + 1, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr); + KPRINTF(1, ("GET_HUB_DESCRIPTOR (1) failed %ld!\n", ioerr)); } - } else { - psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, - "GET_HUB_DESCRIPTOR (%ld) failed: %s (%ld)", - 1, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr); - KPRINTF(1, ("GET_HUB_DESCRIPTOR (1) failed %ld!\n", ioerr)); + } + psdFreePipe(nch->nch_EP1Pipe); } psdFreePipe(nch->nch_EP0Pipe); @@ -952,13 +950,16 @@ struct NepClassHub * GM_UNIQUENAME(nAllocHub)(void) { DeleteMsgPort(nch->nch_CtrlMsgPort); } } while(FALSE); + CloseLibrary(nch->nch_Base); + Forbid(); nch->nch_Task = NULL; - if(nch->nch_ReadySigTask) - { + + if(nch->nch_ReadySigTask) { Signal(nch->nch_ReadySigTask, 1L<nch_ReadySignal); } + return(NULL); } /* \\\ */ @@ -1227,11 +1228,7 @@ struct PsdDevice * GM_UNIQUENAME(nConfigurePort)(struct NepClassHub *nch, UWORD // inherit needs split from hub psdGetAttrs(PGA_DEVICE, nch->nch_Device, DA_NeedsSplitTrans, &needssplit, TAG_END); KPRINTF(2, (" Needs split transfers: %ld\n", needssplit)); - if(nch->nch_IsUSB20) /* this is a low/full speed device connected to a 2.0 hub! */ - { - KPRINTF(2, (" Enforcing split transfers\n")); - needssplit = TRUE; - } + psdSetAttrs(PGA_DEVICE, pd, DA_NeedsSplitTrans, needssplit, TAG_END); } GM_UNIQUENAME(nClearPortStatus)(nch, port); diff --git a/rom/usb/classes/hubss/hubss.h b/rom/usb/classes/hubss/hubss.h index 2eb6d9bc50..739ab78118 100644 --- a/rom/usb/classes/hubss/hubss.h +++ b/rom/usb/classes/hubss/hubss.h @@ -1,12 +1,11 @@ -#ifndef HUB_H -#define HUB_H +#ifndef HUBSS_H +#define HUBSS_H #include #include #include -struct NepHubBase -{ +struct NepHubBase { struct Library nh_Library; /* standard */ UWORD nh_Flags; /* various flags */ @@ -15,8 +14,7 @@ struct NepHubBase struct SignalSemaphore nh_Adr0Sema; /* Address 0 Semaphore */ }; -struct NepClassHub -{ +struct NepClassHub { struct Node nch_Node; /* Node linkage */ struct NepHubBase *nch_HubBase; /* hub.class base */ struct Library *nch_Base; /* Poseidon base */ @@ -24,9 +22,11 @@ struct NepClassHub struct PsdDevice *nch_Device; /* Up linkage */ struct PsdConfig *nch_Config; /* Up linkage */ struct PsdInterface *nch_Interface; /* Up linkage */ + struct PsdEndpoint *nch_EP1; /* Endpoint 1 */ struct PsdPipe *nch_EP0Pipe; /* Endpoint 0 pipe */ struct PsdPipe *nch_EP1Pipe; /* Endpoint 1 pipe */ + BOOL nch_IOStarted; /* IO Running */ BOOL nch_Running; /* Not suspended */ struct Task *nch_ReadySigTask; /* Task to send ready signal to */ @@ -34,29 +34,31 @@ struct NepClassHub struct Task *nch_Task; /* Subtask */ struct MsgPort *nch_TaskMsgPort; /* Message Port of Subtask */ struct MsgPort *nch_CtrlMsgPort; /* Message Port for control messages */ - UWORD nch_NumPorts; /* Number of ports at this hub */ - BOOL nch_IsUSB20; /* Is this a highspeed hub? */ -#ifdef AROS_USB30_CODE + BOOL nch_IsUSB30; /* Is this a superspeed hub? */ -#endif + UWORD nch_NumPorts; /* Number of ports at this hub */ UWORD nch_HubAttr; /* Hub Characteristics (see UHCF flags) */ UWORD nch_PwrGoodTime; /* Time in ms for power to become good */ UWORD nch_HubCurrent; /* Max hub current in mA */ + UWORD nch_HubHdrDecLat; + UWORD nch_HubDelay; ULONG nch_Removable; /* Bitmask for device removable */ + ULONG nch_PowerCycle; /* Bitmask of devices to powercycle */ ULONG nch_DisablePort; /* Bitmask of devices to disable */ + BOOL nch_ClassScan; /* Flag to cause class scan */ BOOL nch_IsRootHub; /* Is this a Root Hub? */ + UBYTE nch_PortChanges[4]; /* Buffer for port changes */ struct PsdDevice **nch_Downstream; /* Pointer to array of down stream device pointers */ }; -struct NepHubMsg -{ +struct NepHubMsg { struct Message nhm_Msg; /* Message body */ ULONG nhm_MethodID; /* The method ID (see usbclass.h) */ IPTR *nhm_Params; /* Pointer to parameters of the method (all of them!) */ IPTR nhm_Result; /* Result of call */ }; -#endif /* HUB_H */ +#endif /* HUBSS_H */ -- 2.11.4.GIT