| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711 |
- //*****************************************************************************
- //
- // usbhostenum.c - Device enumeration code for the USB host library.
- //
- // Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved.
- // Software License Agreement
- //
- // Texas Instruments (TI) is supplying this software for use solely and
- // exclusively on TI's microcontroller products. The software is owned by
- // TI and/or its suppliers, and is protected under applicable copyright
- // laws. You may not combine this software with "viral" open-source
- // software in order to form a larger program.
- //
- // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
- // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
- // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
- // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
- // DAMAGES, FOR ANY REASON WHATSOEVER.
- //
- // This is part of AM1808 StarterWare USB Library, modified resused from revision 6288 of the
- // stellaris USB Library.
- //
- //*****************************************************************************
- #include "hw_usb.h"
- #include "hw_types.h"
- #include "debug.h"
- #include "interrupt.h"
- #include "usb.h"
- #include "usblib.h"
- #include "usblibpriv.h"
- #include "usbhost.h"
- #include "delay.h"
- #include "cppi41dma.h"
- #include <string.h>
- #ifdef DMA_MODE
- unsigned char *rxBuffer;
- #endif
- //*****************************************************************************
- //
- //! \addtogroup usblib_hcd
- //! @{
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- // External prototypes.
- //
- //*****************************************************************************
- //extern tUSBMode g_eUSBMode;
- static tUSBMode g_eUSBMode = USB_MODE_HOST;
- //*****************************************************************************
- //
- // USB instance Object
- //
- //*****************************************************************************
- extern tUSBInstanceObject g_USBInstance[];
- //*****************************************************************************
- //
- // Internal function prototypes.
- //
- //*****************************************************************************
- static void USBHCDEP0StateTx(unsigned int ulIndex);
- static void USBHCDEnumHandler(unsigned int ulIndex);
- static void USBHCDClearFeature(unsigned int ulIndex,
- unsigned int ulDevAddress,
- unsigned int ulEndpoint,
- unsigned int ulFeature);
- static unsigned int USBHCDTxAbort(unsigned int ulIndex, unsigned int endPoint) ;
- static unsigned int USBHCDRxAbort(unsigned int ulIndex, unsigned int endPoint);
- static unsigned int USBHCDRetryConnect(unsigned int ulIndex);
- //*****************************************************************************
- //
- // Automatic power enable.
- //
- //*****************************************************************************
- #define USB_HOST_PWREN_AUTO 0x00000002
- //*****************************************************************************
- //
- // Flags used to signal between the interrupt handler and USBHCDMain().
- //
- //*****************************************************************************
- #define INT_EVENT_VBUS_ERR 0x01
- #define INT_EVENT_CONNECT 0x02
- #define INT_EVENT_DISCONNECT 0x04
- #define INT_EVENT_POWER_FAULT 0x08
- #define INT_EVENT_BABBLE_FAULT 0x10
- //volatile unsigned int g_ulUSBHIntEvents;
- unsigned int g_ulConnectRetry[USB_NUM_INSTANCE];
- //*****************************************************************************
- //
- // Flags used to indicate that a uDMA transfer is pending on a pipe.
- //
- //*****************************************************************************
- #define DMA_PEND_TRANSMIT_FLAG 0x10000
- #define DMA_PEND_RECEIVE_FLAG 0x1
- //volatile unsigned int g_ulDMAPending = 0;
- //*****************************************************************************
- //
- // This holds the current power configuration that is used when USBHCDInit()
- // is called.
- //
- //*****************************************************************************
- //static unsigned int g_ulPowerConfig = USBHCD_VBUS_AUTO_HIGH;
- //*****************************************************************************
- //
- // The states for endpoint 0 during enumeration.
- //
- //*****************************************************************************
- typedef enum
- {
- //
- // The USB device is waiting on a request from the host controller on
- // endpoint 0.
- //
- EP0_STATE_IDLE,
- //
- // Setup packet is expecting data IN.
- //
- EP0_STATE_SETUP_IN,
- //
- // Setup packet is sending data OUT.
- //
- EP0_STATE_SETUP_OUT,
- //
- // The USB device is receiving data from the device due to an SETUP IN
- // request.
- //
- EP0_STATE_RX,
- //
- // The USB device has completed the IN or OUT request and is now waiting
- // for the host to acknowledge the end of the IN/OUT transaction. This
- // is the status phase for a USB control transaction.
- //
- EP0_STATE_STATUS,
- //
- // This state is for when a response only has a status phase and no
- // data phase.
- //
- EP0_STATE_STATUS_IN,
- //
- // This endpoint has signaled a stall condition and is waiting for the
- // stall to be acknowledged by the host controller.
- //
- EP0_STATE_STALL,
- //
- // An error has occurred on endpoint 0.
- //
- EP0_STATE_ERROR
- }
- tEP0State;
- //*****************************************************************************
- //
- // This structure holds the full state for the device enumeration.
- //
- //*****************************************************************************
- typedef struct
- {
- //
- // This is the pointer to the current data being sent out or received
- // on endpoint 0.
- //
- unsigned char *pData;
- //
- // This is the number of bytes that remain to be sent from or received
- // into the g_DeviceState.pEP0Data data buffer.
- //
- volatile unsigned int ulBytesRemaining;
- //
- // The amount of data being sent/received due to a request.
- //
- unsigned int ulDataSize;
- //
- // This is the current device address in use by endpoint 0.
- //
- unsigned int ulDevAddress;
- //
- // The maximum packet size for the device responding to the setup packet.
- //
- unsigned int ulMaxPacketSize;
- //
- // The host controller's state.
- //
- tEP0State eState;
- }
- tHostState;
- //*****************************************************************************
- //
- // This variable holds the current state of endpoint 0.
- //
- //*****************************************************************************
- static volatile tHostState g_sUSBHEP0State[USB_NUM_INSTANCE] =
- {
- {
- 0, // pData
- 0, // ulBytesRemaining
- 0, // ulDataSize
- 0, // ulDevAddress
- 0, // ulMaxPacketSize
- EP0_STATE_IDLE // eState
- }
- #if (USB_NUM_INSTANCE == 2)
- ,{
- 0, // pData
- 0, // ulBytesRemaining
- 0, // ulDataSize
- 0, // ulDevAddress
- 0, // ulMaxPacketSize
- EP0_STATE_IDLE // eState
- }
- #endif
- };
- //*****************************************************************************
- //
- // The global tick counter
- //
- //*****************************************************************************
- //static volatile unsigned int g_ulCurrentTick = 0;
- //*****************************************************************************
- //
- // The current active driver.
- //
- //*****************************************************************************
- //static int g_iUSBHActiveDriver = -1;
- //static void *g_pvDriverInstance = 0;
- //*****************************************************************************
- //
- // These definitions are used to manipulate the values returned as allocated
- // USB pipes.
- //
- //*****************************************************************************
- #define EP_PIPE_USE_UDMA 0x01000000
- #define EP_PIPE_TYPE_ISOC 0x00800000
- #define EP_PIPE_TYPE_INTR 0x00400000
- #define EP_PIPE_TYPE_BULK 0x00200000
- #define EP_PIPE_TYPE_CONTROL 0x00100000
- #define EP_PIPE_TYPE_IN 0x00020000
- #define EP_PIPE_TYPE_OUT 0x00010000
- #define EP_PIPE_IDX_M 0x0000ffff
- //*****************************************************************************
- //
- // This creates a USB pipe handle from an index.
- //
- //*****************************************************************************
- #define OUT_PIPE_HANDLE(ulIndex, ulIdx) (g_sUSBHCD[ulIndex].USBOUTPipes[ulIdx].ulType | ulIdx)
- #define IN_PIPE_HANDLE(ulIndex, ulIdx) (g_sUSBHCD[ulIndex].USBINPipes[ulIdx].ulType | ulIdx)
- //*****************************************************************************
- //
- // Converts from an endpoint specifier to the offset of the endpoint's
- // control/status registers.
- //
- //*****************************************************************************
- #define EP_OFFSET(Endpoint) (Endpoint - 0x10)
- //*****************************************************************************
- //
- // The global to hold all of the state information for a given host controller.
- //
- //*****************************************************************************
- tUSBHCD g_sUSBHCD[USB_NUM_INSTANCE];
- //*****************************************************************************
- //
- // If there is an event driver this function will send out a generic connection
- // event USB_EVENT_CONNECTED indicating that an unknown connection event has
- // occurred.
- //
- //*****************************************************************************
- static void
- SendUnknownConnect(unsigned int ulIndex, unsigned int ulClass, unsigned int ulInstance)
- {
-
- if((g_sUSBHCD[ulIndex].iEventDriver != -1) &&
- (g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex]
- .iEventDriver]->pfnIntHandler))
- {
- //
- // Send the generic connected event.
- //
- g_sUSBHCD[ulIndex].EventInfo.ulEvent = USB_EVENT_CONNECTED;
- //
- // Save the class for later incase and application needs it.
- //
- g_sUSBHCD[ulIndex].ulClass = ulClass;
- g_sUSBHCD[ulIndex].EventInfo.ulInstance = ulInstance;
- g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex]
- .iEventDriver]->pfnIntHandler(&g_sUSBHCD[ulIndex].EventInfo);
- }
- }
- //*****************************************************************************
- //
- // Internal memory allocation space is two unsigned int values where each
- // bit represents a 64 byte block in the FIFO. This requires 64 bits for
- // the 4096 bytes of FIFO available.
- //
- //*****************************************************************************
- static unsigned int g_ulAlloc[2];
- //*****************************************************************************
- //
- // This function handles freeing FIFO memory that has been allocated using the
- // FIFOAlloc() function.
- //
- //*****************************************************************************
- static void
- FIFOFree(tUSBHCDPipe *pUSBPipe)
- {
- unsigned int ulMask;
- //
- // Calculate the mask value to use to clear off the allocated blocks used
- // by the USB pipe specified by pUSBPipe.
- //
- ulMask = (1 << (pUSBPipe->ucFIFOSize - 2)) - 1;
- ulMask = ulMask << pUSBPipe->ucFIFOBitOffset;
- //
- // Determine which 32 bit word to access based on the size.
- //
- if(pUSBPipe->ucFIFOSize > USB_FIFO_SZ_64)
- {
- //
- // If the FIFO size is greater than 64 then use the upper 32 bits.
- //
- g_ulAlloc[1] &= ~ulMask;
- }
- else
- {
- //
- // If the FIFO size is less than or equal to 64 then use the lower
- // 32 bits.
- //
- g_ulAlloc[0] &= ~ulMask;
- }
- }
- //*****************************************************************************
- //
- // This function is used to allocate FIFO memory to a given USB pipe.
- //
- // \param pUSBPipe is the USB pipe that needs FIFO memory allocated.
- // \param ulSize is the minimum size in bytes of the FIFO to allocate.
- //
- // This function will allocate \e ulSize bytes to the USB pipe in the
- // \e pUSBPipe parameter. The function will fill the pUSBPipe structure
- // members ucFIFOSize and ucFIFOAddr with values that can be used with the
- // USBFIFOConfigSet() API. This allocation uses a first fit algorithm.
- //
- // \return This function returns the size of the block allocated.
- //
- //*****************************************************************************
- static unsigned int
- FIFOAlloc(tUSBHCDPipe *pUSBPipe, unsigned int ulSize)
- {
- unsigned int ulBlocks, ulStart, ulBlockSize;
- unsigned short usFIFOAddr;
- unsigned int ulTemp, ulIndex;
- //
- // Save which 32 bit value to access, the upper is for blocks greater
- // than 64 and the lower is for block 64 or less.
- //
- if(ulSize > 64)
- {
- ulIndex = 1;
- }
- else
- {
- ulIndex = 0;
- }
- //
- // Initial FIFO address is 0.
- //
- usFIFOAddr = 0;
- //
- // Initialize the bit pattern and bit location.
- //
- ulBlocks = 1;
- ulStart = 0;
- //
- // The initial block size is always the minimum size of 64 bytes.
- //
- ulBlockSize = 64;
- //
- // The initial size and offset are 64 and 0.
- //
- pUSBPipe->ucFIFOBitOffset = 0;
- pUSBPipe->ucFIFOSize = 3;
- //
- // Scan through 32 bits looking for a memory block large enough to fill
- // the request.
- //
- while(usFIFOAddr <= 32)
- {
- //
- // If the pattern is zero then it is a possible match.
- //
- if((g_ulAlloc[ulIndex] & ulBlocks) == 0)
- {
- //
- // If the size is large enough then save it and break out of the
- // loop.
- //
- if(ulBlockSize >= ulSize)
- {
- //
- // Mark the memory as allocated.
- //
- g_ulAlloc[ulIndex] |= ulBlocks;
- break;
- }
- //
- // Increment the size of the FIFO block.
- //
- pUSBPipe->ucFIFOSize++;
- //
- // Add in a new bit to the size of the allocation.
- //
- ulBlocks = ulBlocks | (ulBlocks << 1) ;
- //
- // Double the current size.
- //
- ulBlockSize <<= 1;
- }
- else
- {
- //
- // Need to start over looking because the last allocation match
- // failed, so reset the bit offset to the current location and the
- // size to 64 bytes.
- //
- pUSBPipe->ucFIFOBitOffset = usFIFOAddr;
- pUSBPipe->ucFIFOSize = 3;
- //
- // Reset the block size to the minimum (64 bytes).
- //
- ulBlockSize = 64;
- //
- // Store the current starting bit location and set the block mask
- // to this value.
- //
- ulStart = 1 << usFIFOAddr;
- ulBlocks = ulStart;
- }
- //
- // Increase the address of the FIFO offset.
- //
- usFIFOAddr++;
- }
- //
- // If there was no block large enough then fail this call.
- //
- if(usFIFOAddr > 32)
- {
- ulBlockSize = 0;
- pUSBPipe->usFIFOAddr = 0;
- pUSBPipe->ucFIFOBitOffset = 0;
- pUSBPipe->ucFIFOSize = 0;
- }
- else
- {
- //
- // Calculate the offset in the FIFO.
- //
- ulTemp = pUSBPipe->ucFIFOBitOffset * 64;
- //
- // Sizes greater than 64 are allocated in the second half of the FIFO
- // memory space.
- //
- if(ulSize > 64)
- {
- ulTemp += 2048;
- }
- //
- // Convert this to the value that can be set in the USB controller.
- //
- pUSBPipe->usFIFOAddr = (unsigned short)ulTemp;
- }
- return(ulBlockSize);
- }
- //*****************************************************************************
- //
- //! This function is used to allocate a USB HCD pipe.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param ulEndpointType is the type of endpoint that this pipe will be
- //! communicating with.
- //! \param ulDevAddr is the device address to use for this endpoint.
- //! \param ulSize is the size of the FIFO in bytes.
- //! \param pfnCallback is the function that will be called when events occur on
- //! this USB Pipe.
- //!
- //! Since there are a limited number of USB HCD pipes that can be used in the
- //! host controller, this function is used to temporarily or permanently
- //! acquire one of the endpoints. Unlike the USBHCDPipeAlloc() function this
- //! function allows the caller to specify the size of the FIFO allocated to
- //! this endpoint in the \e ulSize parameter. This function also provides a
- //! method to register a callback for status changes on this endpoint. If no
- //! callbacks are desired then the \e pfnCallback function should be set to 0.
- //! The callback should be used when using the USBHCDPipeSchedule() function
- //! so that the caller is notified when the action is complete.
- //!
- //! \return This function returns a value indicating which pipe was reserved.
- //! If the value is 0 then there were no pipes currently available. This value
- //! should be passed to any USBHCDPipe APIs to indicate which pipe is being
- //! accessed.
- //
- //*****************************************************************************
- unsigned int
- USBHCDPipeAllocSize(unsigned int ulIndex, unsigned int ulEndpointType,
- unsigned int ulDevAddr, unsigned int ulSize,
- tHCDPipeCallback pfnCallback)
- {
- int iIdx;
-
- ASSERT(ulIndex == 0);
- //
- // Find a USB pipe that is free.
- //
- for(iIdx = 0; iIdx < MAX_NUM_PIPES; iIdx++)
- {
- //
- // Handle OUT Pipes.
- //
- if(ulEndpointType & EP_PIPE_TYPE_OUT)
- {
- //
- // A zero address indicates free.
- //
- if(g_sUSBHCD[ulIndex].USBOUTPipes[iIdx].ulDevAddr == 0)
- {
-
- //
- // Save the endpoint type and device address and callback
- // function.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[iIdx].ulType = ulEndpointType;
- g_sUSBHCD[ulIndex].USBOUTPipes[iIdx].ulDevAddr = ulDevAddr;
- g_sUSBHCD[ulIndex].USBOUTPipes[iIdx].pfnCallback = pfnCallback;
- g_sUSBHCD[ulIndex].USBOUTPipes[iIdx].ulEpMaxPacketSize = ulSize;
- //
- // Initialize the endpoint as idle.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[iIdx].eState = PIPE_IDLE;
- //
- // Allocate space in the FIFO for this endpoint.
- //
- if(FIFOAlloc(&g_sUSBHCD[ulIndex].USBOUTPipes[iIdx], ulSize) != 0)
- {
- //
- // Configure the FIFO.
- //
- USBFIFOConfigSet(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(iIdx + 1),
- g_sUSBHCD[ulIndex].USBOUTPipes[iIdx]
- .usFIFOAddr, g_sUSBHCD[ulIndex]
- .USBOUTPipes[iIdx].ucFIFOSize,
- USB_EP_HOST_OUT);
- }
- //
- // Set the function address for this endpoint.
- //
- USBHostAddrSet(g_USBInstance[ulIndex].uiBaseAddr,
- INDEX_TO_USB_EP(iIdx + 1), ulDevAddr,
- USB_EP_HOST_OUT);
- break;
- }
- }
- //
- // Handle IN Pipes.
- //
- else if(ulEndpointType & EP_PIPE_TYPE_IN)
- {
- //
- // A zero address indicates free.
- //
- if(g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulDevAddr == 0)
- {
-
- //
- // Save the endpoint type and device address and callback
- // function.
- //
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulType = ulEndpointType;
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulDevAddr = ulDevAddr;
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].pfnCallback = pfnCallback;
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulEpMaxPacketSize = ulSize;
- //
- // Allocate space in the FIFO for this endpoint.
- //
- if(FIFOAlloc(&g_sUSBHCD[ulIndex].USBINPipes[iIdx], ulSize) != 0)
- {
- //
- // Configure the FIFO.
- //
- USBFIFOConfigSet(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(iIdx + 1),
- g_sUSBHCD[ulIndex].USBINPipes[iIdx]
- .usFIFOAddr, g_sUSBHCD[ulIndex]
- .USBINPipes[iIdx].ucFIFOSize,
- USB_EP_HOST_IN);
- }
- //
- // Set the function address for this endpoint.
- //
- USBHostAddrSet(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(iIdx + 1), ulDevAddr,
- USB_EP_HOST_IN);
- //
- // Reset the state of the pipe to idle.
- //
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].eState = PIPE_IDLE;
- break;
- }
- }
- }
- //
- // Did not find a free pipe.
- //
- if(iIdx == MAX_NUM_PIPES)
- {
- return(0);
- }
- //
- // Return the pipe index and type that was allocated.
- //
- return(ulEndpointType | iIdx);
- }
- //*****************************************************************************
- //
- //! This function is used to allocate a USB HCD pipe.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param ulEndpointType is the type of endpoint that this pipe will be
- //! communicating with.
- //! \param ulDevAddr is the device address to use for this endpoint.
- //! \param pfnCallback is the function that will be called when events occur on
- //! this USB Pipe.
- //!
- //! Since there are a limited number of USB HCD pipes that can be used in the
- //! host controller, this function is used to temporarily or permanently
- //! acquire one of the endpoints. It also provides a method to register a
- //! callback for status changes on this endpoint. If no callbacks are desired
- //! then the \e pfnCallback function should be set to 0. The callback should
- //! be used when using the USBHCDPipeSchedule() function so that the caller is
- //! notified when the action is complete.
- //!
- //! \return This function returns a value indicating which pipe was reserved.
- //! If the value is 0 then there were no pipes currently available. This value
- //! should be passed to any USBHCDPipe APIs to indicate which pipe is being
- //! accessed.
- //
- //*****************************************************************************
- unsigned int
- USBHCDPipeAlloc(unsigned int ulIndex, unsigned int ulEndpointType,
- unsigned int ulDevAddr, tHCDPipeCallback pfnCallback)
- {
- //
- // The old API allocated only 64 bytes to each endpoint.
- //
- return(USBHCDPipeAllocSize(ulIndex, ulEndpointType, ulDevAddr, 64,
- pfnCallback));
- }
- //*****************************************************************************
- //
- //! This function is used to configure a USB HCD pipe.
- //!
- //! This should be called after allocating a USB pipe with a call to
- //! USBHCDPipeAlloc(). It is used to set the configuration associated with an
- //! endpoint like the max payload and target endpoint. The \e ulMaxPayload
- //! parameter is typically read directly from the devices endpoint descriptor
- //! and is expressed in bytes.
- //!
- //! Setting the \e ulInterval parameter depends on the type of endpoint being
- //! configured. For endpoints that do not need to use the \e ulInterval
- //! parameter \e ulInterval should be set to 0. For Bulk \e ulInterval is a
- //! value from 2-16 and will set the NAK timeout value as 2^(\e ulInterval-1)
- //! frames. For interrupt endpoints \e ulInterval is a value from 1-255 and
- //! is the count in frames between polling the endpoint. For isochronous
- //! endpoints \e ulInterval ranges from 1-16 and is the polling interval in
- //! frames represented as 2^(\e ulInterval-1) frames.
- //!
- //! \param ulPipe is the allocated endpoint to modify.
- //! \param ulMaxPayload is maximum data that can be handled per transaction.
- //! \param ulInterval is the polling interval for data transfers expressed in
- //! frames.
- //! \param ulTargetEndpoint is the target endpoint on the device to communicate
- //! with.
- //!
- //! \return If the call was successful, this function returns zero any other
- //! value indicates an error.
- //
- //*****************************************************************************
- unsigned int
- USBHCDPipeConfig(unsigned int devIndex, unsigned int ulPipe,
- unsigned int ulMaxPayload, unsigned int ulInterval,
- unsigned int ulTargetEndpoint)
- {
- unsigned int ulFlags;
- unsigned int ulIndex;
- //
- // Get the index number from the allocated pipe.
- //
- ulIndex = (ulPipe & EP_PIPE_IDX_M);
- //
- // Set the direction.
- //
- if(ulPipe & EP_PIPE_TYPE_OUT)
- {
- //
- // Set the mode for this endpoint.
- //
- if(g_sUSBHCD[devIndex].USBOUTPipes[ulIndex].ulType & EP_PIPE_TYPE_BULK)
- {
- ulFlags = USB_EP_MODE_BULK;
- }
- else if(g_sUSBHCD[devIndex].USBOUTPipes[ulIndex].ulType & EP_PIPE_TYPE_INTR)
- {
- ulFlags = USB_EP_MODE_INT;
- }
- else if(g_sUSBHCD[devIndex].USBOUTPipes[ulIndex].ulType & EP_PIPE_TYPE_ISOC)
- {
- ulFlags = USB_EP_MODE_ISOC;
- }
- else
- {
- ulFlags = USB_EP_MODE_CTRL;
- }
- ulFlags |= USB_EP_HOST_OUT;
- g_sUSBHCD[devIndex].USBOUTPipes[ulIndex].ucEPNumber =
- (unsigned char)ulTargetEndpoint;
- //
- // Save the interval and the next tick to trigger a scheduler event.
- //
- g_sUSBHCD[devIndex].USBOUTPipes[ulIndex].ulInterval = ulInterval;
- g_sUSBHCD[devIndex].USBOUTPipes[ulIndex].ulNextEventTick =
- ulInterval + g_sUSBHCD[devIndex].ulCurrentTick;
-
- //
- // Get pipe speed
- //
- g_sUSBHCD[devIndex].USBOUTPipes[ulIndex].ulPipeSpeed =
- g_sUSBHCD[devIndex].USBDevice[ulIndex].ulDeviceSpeed;
- //
- // Speed configuration in type0 register
- //
- switch(g_sUSBHCD[devIndex].USBDevice[ulIndex].ulDeviceSpeed)
- {
- case USB_HIGH_SPEED:
- ulFlags |= USB_EP_SPEED_HIGH;
- break;
- case USB_FULL_SPEED:
- ulFlags |= USB_EP_SPEED_FULL;
- break;
-
- default:
- ulFlags |= USB_EP_SPEED_LOW;
- break;
- }
- }
- else
- {
- //
- // Set the mode for this endpoint.
- //
- if(g_sUSBHCD[devIndex].USBINPipes[ulIndex].ulType & EP_PIPE_TYPE_BULK)
- {
- ulFlags = USB_EP_MODE_BULK;
- }
- else if(g_sUSBHCD[devIndex].USBINPipes[ulIndex].ulType & EP_PIPE_TYPE_INTR)
- {
- ulFlags = USB_EP_MODE_INT;
- }
- else if(g_sUSBHCD[devIndex].USBINPipes[ulIndex].ulType & EP_PIPE_TYPE_ISOC)
- {
- ulFlags = USB_EP_MODE_ISOC;
- }
- else
- {
- ulFlags = USB_EP_MODE_CTRL;
- }
- ulFlags |= USB_EP_HOST_IN;
- g_sUSBHCD[devIndex].USBINPipes[ulIndex].ucEPNumber =
- (unsigned char)ulTargetEndpoint;
- //
- // Save the interval and the next tick to trigger a scheduler event.
- //
- g_sUSBHCD[devIndex].USBINPipes[ulIndex].ulInterval = ulInterval;
- g_sUSBHCD[devIndex].USBINPipes[ulIndex].ulNextEventTick =
- ulInterval + g_sUSBHCD[devIndex].ulCurrentTick;
- //
- // Get pipe speed
- //
- g_sUSBHCD[devIndex].USBINPipes[ulIndex].ulPipeSpeed =
- g_sUSBHCD[devIndex].USBDevice[ulIndex].ulDeviceSpeed;
-
- //
- // Speed configuration in type0 register
- //
- switch(g_sUSBHCD[devIndex].USBDevice[ulIndex].ulDeviceSpeed)
- {
- case USB_HIGH_SPEED:
- ulFlags |= USB_EP_SPEED_HIGH;
- break;
-
- case USB_FULL_SPEED:
- ulFlags |= USB_EP_SPEED_FULL;
- break;
- default:
- ulFlags |= USB_EP_SPEED_LOW;
- break;
- }
- }
- //
- // Configure the endpoint according to the flags determined above.
- //
- USBHostEndpointConfig(g_USBInstance[devIndex].uiBaseAddr ,
- INDEX_TO_USB_EP((ulPipe & EP_PIPE_IDX_M) + 1),
- ulMaxPayload, ulInterval, ulTargetEndpoint,
- ulFlags);
- return(0);
- }
- //*****************************************************************************
- //
- //! This function is used to return the current status of a USB HCD pipe.
- //!
- //! This function will return the current status for a given USB pipe. If
- //! there is no status to report this call will simply return
- //! \b USBHCD_PIPE_NO_CHANGE.
- //!
- //! \param ulPipe is the USB pipe for this status request.
- //!
- //! \return This function returns the current status for the given endpoint.
- //! This will be one of the \b USBHCD_PIPE_* values.
- //
- //*****************************************************************************
- unsigned int
- USBHCDPipeStatus(unsigned int ulPipe)
- {
- return(0);
- }
- //*****************************************************************************
- //
- //! This function is used to write data to a USB HCD pipe.
- //!
- //! \param ulPipe is the USB pipe to put data into.
- //! \param pucData is a pointer to the data to send.
- //! \param ulSize is the amount of data to send.
- //!
- //! This function will block until it has sent as much data as was
- //! requested using the USB pipe's FIFO. The caller should have registered a
- //! callback with the USBHCDPipeAlloc() call in order to be informed when the
- //! data has been transmitted. The value returned by this function can be less
- //! than the \e ulSize requested if the USB pipe has less space available than
- //! this request is making.
- //!
- //! \return This function returns the number of bytes that were scheduled to
- //! be sent on the given USB pipe.
- //
- //*****************************************************************************
- unsigned int
- USBHCDPipeWrite(unsigned int ulIndex, unsigned int ulPipe,
- unsigned char *pucData, unsigned int ulSize)
- {
- unsigned int ulEndpoint;
- unsigned int ulRemainingBytes;
- unsigned int ulByteToSend;
- unsigned int ulPipeIdx;
- unsigned int ulEPStatus;
- unsigned int ulConnectRetry;
- #ifdef DMA_MODE
- unsigned int txBuffer;
- unsigned int nBlocks;
- #endif
- unsigned int ulTimer = 0;
- //
- // Determine which endpoint interface that this pipe is using.
- //
- ulEndpoint = INDEX_TO_USB_EP((EP_PIPE_IDX_M & ulPipe) + 1);
- //
- // Get index used for looking up pipe data
- //
- ulPipeIdx = ulPipe & EP_PIPE_IDX_M;
- //
- // Set the total number of bytes to send out.
- //
- ulRemainingBytes = ulSize;
- //
- // Send all of the requested data.
- //
- while(ulRemainingBytes != 0)
- {
- //
- // Start a write request.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState = PIPE_WRITING;
-
- //
- //Calculate the Number of blocks to Transmit
- //
- if(ulRemainingBytes <=
- (g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].ulEpMaxPacketSize))
- {
- ulByteToSend = ulRemainingBytes;
- }
- else
- {
- ulByteToSend =
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].ulEpMaxPacketSize;
- }
- #ifdef DMA_MODE
- nBlocks = 1;
- //
- //Allocate enough buffer
- //
- txBuffer=(unsigned int)cppiDmaAllocnBuffer(nBlocks);
- ASSERT(NULL!=txBuffer);
-
- //
- // Set pending transmit DMA flag
- //
- g_sUSBHCD[ulIndex].ulDMAPending |= DMA_PEND_TRANSMIT_FLAG << ulPipeIdx;
- //
- //Copy the data to the TX buffer
- //
- memcpy((unsigned char *)txBuffer, pucData, ulByteToSend);
- //
- //Load the DMA queue with the data buffer
- //
- doDmaTxTransfer(ulIndex, (unsigned char *)txBuffer,
- ulByteToSend, ulEndpoint);
- //
- //Enable the DMA for TX operation
- //
- enableCoreTxDMA(ulIndex, ulEndpoint);
- #else
- //
- // Put the data in the buffer.
- //
- USBEndpointDataPut(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint,
- pucData, ulByteToSend);
- //
- // Schedule the data to be sent.
- //
- USBEndpointDataSend(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint,
- USB_TRANS_OUT);
- #endif
-
- //
- // Wait for a status change.
- //
- if(USB_TIMEOUT_DISABLE!=g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0)
- {
- ulTimer = g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0;
- StartTimer(ulTimer);
- }
- while(g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState == PIPE_WRITING)
- {
- //
- // Exit the loop for any of the event(s): Disconnect.
- //
- if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & INT_EVENT_DISCONNECT)
- {
- //
- // Update the Pipe status
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState = PIPE_ERROR;
- continue;
- }
- else if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & INT_EVENT_BABBLE_FAULT)
- {
- //
- // Update the Pipe status
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState = PIPE_ERROR;
- continue;
- }
- //
- // Read endpoint status.
- //
- ulEPStatus = USBEndpointStatus(g_USBInstance[ulIndex].uiBaseAddr,
- ulEndpoint);
- //
- // Check for stall condition occurence.
- //
- if(ulEPStatus & USB_HOST_OUT_STALL)
- {
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState = PIPE_STALLED;
- continue;
- }
- else if(ulEPStatus & USB_HOST_OUT_ERROR)
- {
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState = PIPE_ERROR;
- continue;
- }
- if(USB_TIMEOUT_DISABLE!=g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0)
- {
- if(IsTimerElapsed())
- {
- ulTimer = 0;
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState = PIPE_ERROR;
- g_sUSBHCD[ulIndex].USBHTimeOut.Status.slNonEP0 = (1<<(ulPipeIdx + 1));
- break;
- }
- }
- }
- if(USB_TIMEOUT_DISABLE!=g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0)
- {
- StopTimer();
- ulTimer = 0;
- }
- //
- // If the data was successfully sent then decrement the count and
- // continue.
- //
- if(g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState == PIPE_DATA_SENT)
- {
- #ifdef DMA_MODE
- disableCoreTxDMA(g_USBInstance[ulIndex].uiUSBInstance, ulEndpoint);
- //
- //Free the TX buffer
- //
- cppiDmaFreenBuffer((unsigned int *)txBuffer);
- #endif
- //
- // Decrement the remaining data and advance the pointer.
- //
- ulRemainingBytes -= ulByteToSend;
- pucData += ulByteToSend;
- }
- else if(g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState == PIPE_STALLED)
- {
- //
- // Zero out the size so that the caller knows that no data was
- // written.
- //
- ulSize = 0;
- USBHCDTxAbort(ulIndex, ulEndpoint);
- //
- // This is the actual endpoint number.
- //
- USBHCDClearFeature(ulIndex, 1, ulPipe, USB_FEATURE_EP_HALT);
- //
- // If there was a stall, then no more data is coming so break out.
- //
- break;
- }
- else if(g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState == PIPE_ERROR)
- {
- // Clean-up the EP FIFOs and CPPIDMA (if applicable)
- USBHCDTxAbort(ulIndex, ulEndpoint);
- if(USB_TIMEOUT_DISABLE!=g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0)
- {
- if(!ulTimer)
- {
- // Try re-establising the connection with device
- ulConnectRetry = g_sUSBHCD[ulIndex].ulConnectRetry;
- for(;ulConnectRetry;--ulConnectRetry)
- {
- if(USBHCDRetryConnect(ulIndex))
- {
- break;
- }
- }
- // Abort the transfer if re-establising the connection with device failed.
- if(!ulConnectRetry)
- {
- //
- // Set the size to 0 to indicate Error.
- //
- ulSize = 0;
- break;
- }
- }
- }
- else
- {
- //
- // Set the size to 0 to indicate Error.
- //
- ulSize = 0;
- break;
- }
- }
- //
- // If there are less than 64 bytes to send then this is the last
- // of the data to go out.
- //
- if(ulRemainingBytes < 64)
- {
- ulByteToSend = ulRemainingBytes;
- }
- }
- //
- // Go Idle once this state has been reached.
- //
- if(!ulRemainingBytes)
- {
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipeIdx].eState = PIPE_IDLE;
- }
- return(ulSize);
- }
- //*****************************************************************************
- //
- //! This function is used to schedule and IN transaction on a USB HCD pipe.
- //!
- //! \param ulPipe is the USB pipe to read data from.
- //! \param pucData is a pointer to store the data that is received.
- //! \param ulSize is the size in bytes of the buffer pointed to by pucData.
- //!
- //! This function will not block depending on the type of pipe passed in will
- //! schedule either a send of data to the device or a read of data from the
- //! device. In either case the amount of data will be limited to what will
- //! fit in the FIFO for a given endpoint.
- //!
- //! \return This function returns the number of bytes that sent in the case
- //! of a transfer of data or it will return 0 for a request on a USB IN pipe.
- //
- //*****************************************************************************
- unsigned int
- USBHCDPipeSchedule(unsigned int ulIndex, unsigned int ulPipe,
- unsigned char *pucData, unsigned int ulSize)
- {
- unsigned int ulEndpoint;
- //
- // Determine which endpoint interface that this pipe is using.
- //
- ulEndpoint = INDEX_TO_USB_EP((EP_PIPE_IDX_M & ulPipe) + 1);
- if(ulPipe & EP_PIPE_TYPE_OUT)
- {
- //
- // Start a write request.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[EP_PIPE_IDX_M & ulPipe].eState = PIPE_WRITING;
- //
- // Put the data in the buffer.
- //
- USBEndpointDataPut(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint, pucData, ulSize);
- //
- // Schedule the data to be sent.
- //
- USBEndpointDataSend(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint, USB_TRANS_OUT);
- }
- else
- {
- //
- // Start a read request.
- //
- g_sUSBHCD[ulIndex].USBINPipes[EP_PIPE_IDX_M & ulPipe].eState = PIPE_READING;
-
- //
- // Trigger a request for data from the device.
- //
- USBHostRequestIN(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint);
- //
- // No data was put into or read from the buffer.
- //
- ulSize = 0;
- }
- return(ulSize);
- }
- //*****************************************************************************
- //
- //! This function is used to read data from a USB HCD pipe.
- //!
- //! \param ulPipe is the USB pipe to read data from.
- //! \param pucData is a pointer to store the data that is received.
- //! \param ulSize is the size in bytes of the buffer pointed to by pucData.
- //!
- //! This function will not block and will only read as much data as requested
- //! or as much data is currently available from the USB pipe. The caller
- //! should have registered a callback with the USBHCDPipeAlloc() call in order
- //! to be informed when the data has been received. The value returned by this
- //! function can be less than the \e ulSize requested if the USB pipe has less
- //! data available than was requested.
- //!
- //! \return This function returns the number of bytes that were returned in the
- //! \e pucData buffer.
- //
- //*****************************************************************************
- unsigned int
- USBHCDPipeReadNonBlocking(unsigned int ulIndex, unsigned int ulPipe,
- unsigned char *pucData, unsigned int ulSize)
- {
- unsigned int ulEndpoint;
- //
- // Determine which endpoint interface that this pipe is using.
- //
- ulEndpoint = INDEX_TO_USB_EP((EP_PIPE_IDX_M & ulPipe) + 1);
- //
- // Read the data out of the USB endpoint interface.
- //
- USBEndpointDataGet(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint, pucData, &ulSize);
- //
- // Acknowledge that the data was read from the endpoint.
- //
- USBHostEndpointDataAck(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint);
- //
- // Go Idle once this state has been reached.
- //
- g_sUSBHCD[ulIndex].USBINPipes[EP_PIPE_IDX_M & ulPipe].eState = PIPE_IDLE;
- return(ulSize);
- }
- //*****************************************************************************
- //
- //! This function is used to read data from a USB HCD pipe.
- //!
- //! \param ulPipe is the USB pipe to read data from.
- //! \param pucData is a pointer to store the data that is received.
- //! \param ulSize is the size in bytes of the buffer pointed to by pucData.
- //!
- //! This function will block and will only return when it has read as much data
- //! as requested from the USB pipe. The caller should have registered a
- //! callback with the USBHCDPipeAlloc() call in order to be informed when the
- //! data has been received. The value returned by this function can be less
- //! than the \e ulSize requested if the USB pipe has less data available than
- //! was requested.
- //!
- //! \return This function returns the number of bytes that were returned in the
- //! \e pucData buffer.
- //
- //*****************************************************************************
- unsigned int
- USBHCDPipeRead(unsigned int ulIndex, unsigned int ulPipe,
- unsigned char *pucData, unsigned int ulSize)
- {
- unsigned int ulEndpoint;
- unsigned int ulRemainingBytes;
- unsigned int ulPipeIdx;
- unsigned int ulEPStatus;
- unsigned int ulConnectRetry;
- #ifdef DMA_MODE
- unsigned int ulLength;
- #else
- unsigned int ulBytesRead = 0;
- #endif
- unsigned int ulTimer = 0;
- //
- // Get index used for looking up pipe data
- //
- ulPipeIdx = ulPipe & EP_PIPE_IDX_M;
-
- //
- // Determine which endpoint interface that this pipe is using.
- //
- ulEndpoint = INDEX_TO_USB_EP(ulPipeIdx + 1);
- //
- // Set the remaining bytes to received.
- //
- ulRemainingBytes = ulSize;
- //
- // Continue until all data requested has been received.
- //
- #ifdef DMA_MODE
- //
- //Calculate the Number of blocks requested
- //
- if(ulSize <=
- (g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].ulEpMaxPacketSize))
- {
- ulLength = ulSize;
- }
- else
- {
- ulLength =
- (g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].ulEpMaxPacketSize);
- }
-
- #endif
- while(ulRemainingBytes != 0)
- {
- #ifdef DMA_MODE
- //
- // Give enough buffer to DMA
- //
- g_sUSBHCD[ulIndex].rxBuffer = (unsigned char *)cppiDmaAllocBuffer();
- ASSERT(NULL!=g_sUSBHCD[ulIndex].rxBuffer);
- doDmaRxTransfer(ulIndex, ulLength, g_sUSBHCD[ulIndex].rxBuffer,
- ulEndpoint);
- //
- //Enable the DMA
- //
- enableCoreRxDMA(g_USBInstance[ulIndex].uiUSBInstance, ulEndpoint);
- #endif
- //
- // Start a read request.
- //
- g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState = PIPE_READING;
- //
- // Set pending DMA flag
- //
- g_sUSBHCD[ulIndex].ulDMAPending |= DMA_PEND_RECEIVE_FLAG << ulPipeIdx;
- //
- // Trigger a request for data from the device.
- //
- USBHostRequestIN(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint);
- //
- // Wait for a status change.
- //
- if(USB_TIMEOUT_DISABLE!=g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0)
- {
- ulTimer = g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0;
- StartTimer(ulTimer);
- }
- while(g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState == PIPE_READING)
- {
- //
- // Exit the loop for any of the event(s): Disconnect.
- //
- if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & INT_EVENT_DISCONNECT)
- {
- //
- // Update the Pipe status
- //
- g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState = PIPE_ERROR;
- continue;
- }
- else if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & INT_EVENT_BABBLE_FAULT)
- {
- //
- // Update the Pipe status
- //
- g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState = PIPE_ERROR;
- continue;
- }
- //
- // Read endpoint status.
- //
- ulEPStatus = USBEndpointStatus(g_USBInstance[ulIndex].uiBaseAddr,
- ulEndpoint);
- //
- // Check for stall condition occurence.
- //
- if(ulEPStatus & USB_HOST_IN_STALL)
- {
- g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState = PIPE_STALLED;
- continue;
- }
- else if(ulEPStatus & USB_HOST_IN_ERROR)
- {
- g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState = PIPE_ERROR;
- continue;
- }
- if(USB_TIMEOUT_DISABLE!=g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0)
- {
- if(IsTimerElapsed())
- {
- ulTimer = 0;
- g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState = PIPE_ERROR;
- g_sUSBHCD[ulIndex].USBHTimeOut.Status.slNonEP0 = (1<<((ulPipeIdx + 1)+16));
- break;
- }
- }
- }
- if(USB_TIMEOUT_DISABLE!=g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0)
- {
- StopTimer();
- ulTimer = 0;
- }
- //
- // If data is ready then return it.
- //
- if(g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState == PIPE_DATA_READY)
- {
- #ifdef DMA_MODE
- disableCoreRxDMA(g_USBInstance[ulIndex].uiUSBInstance, ulEndpoint);
- //
- //Copy the data from DMA buffer to application buffer
- //
- //memset (pucData, 0, ulLength);
- memcpy(pucData, g_sUSBHCD[ulIndex].rxBuffer, ulLength);
-
- //
- //Free the DMA Buffer
- //
- cppiDmaFreeBuffer((unsigned int * )g_sUSBHCD[ulIndex].rxBuffer);
- //
- //Claculate the packet length
- //
- if(ulRemainingBytes <=
- (g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].ulEpMaxPacketSize))
- {
- ulRemainingBytes = ulRemainingBytes - ulLength;
- }
- else
- {
- ulRemainingBytes = ulRemainingBytes - ulLength;
- pucData += ulLength;
- }
- //
- //Update the Pipe status
- //
- if(ulRemainingBytes != 0)
- {
- g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState = PIPE_READING;
- }
- #else
- //
- // Request all of the remaining bytes.
- //
- ulBytesRead = ulRemainingBytes;
- //
- // Read the data out of the USB endpoint interface.
- //
- USBEndpointDataGet(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint, pucData,
- &ulBytesRead);
- //
- // Acknowledge that the data was read from the endpoint.
- //
- USBHostEndpointDataAck(g_USBInstance[ulIndex].uiBaseAddr , ulEndpoint);
- //
- // Subtract the number of bytes read from the bytes remaining.
- //
- ulRemainingBytes -= ulBytesRead;
- //
- // If there were less than 64 bytes read, then this was a short
- // packet and no more data will be returned.
- //
- if(ulBytesRead < g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].ulEpMaxPacketSize)
- {
- //
- // Subtract off the bytes that were not received and exit the
- // loop.
- //
- ulSize = ulSize - ulRemainingBytes;
- break;
- }
- else
- {
- //
- // Move the buffer ahead to receive more data into the buffer.
- //
- pucData += g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].ulEpMaxPacketSize;
- }
- #endif
- }
- else if(g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState == PIPE_STALLED)
- {
- USBHCDRxAbort(ulIndex, ulEndpoint);
- //
- // Zero out the size so that the caller knows that no data was read.
- //
- ulSize = 0;
- //
- // This is the actual endpoint number.
- //
- USBHCDClearFeature(ulIndex, 1, ulPipe, USB_FEATURE_EP_HALT);
- //
- // If there was a stall, then no more data is coming so break out.
- //
- break;
- }
- else if(g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState == PIPE_ERROR)
- {
- // Clean-up the EP FIFOs and CPPIDMA (if applicable)
- USBHCDRxAbort(ulIndex, ulEndpoint);
- if(USB_TIMEOUT_DISABLE!=g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0)
- {
- if(!ulTimer)
- {
- // Try re-establising the connection with device
- ulConnectRetry = g_sUSBHCD[ulIndex].ulConnectRetry;
- for(;ulConnectRetry;--ulConnectRetry)
- {
- if(USBHCDRetryConnect(ulIndex))
- {
- break;
- }
- }
- // Abort the transfer if re-establising the connection with device failed.
- if(!ulConnectRetry)
- {
- //
- // Set the size to 0 to indicate Error.
- //
- ulSize = 0;
- break;
- }
- }
- }
- else
- {
- //
- // Set the size to 0 to indicate Error.
- //
- ulSize = 0;
- break;
- }
- }
- }
- //
- // Go Idle once this state has been reached.
- //
- if(!ulRemainingBytes)
- {
- g_sUSBHCD[ulIndex].USBINPipes[ulPipeIdx].eState = PIPE_IDLE;
- }
- return(ulSize);
- }
- //*****************************************************************************
- //
- //! This function is used to release a USB pipe.
- //!
- //! \param ulPipe is the allocated USB pipe to release.
- //!
- //! This function is used to release a USB pipe that was allocated by a call to
- //! USBHCDPipeAlloc() for use by some other device endpoint in the system.
- //! Freeing an unallocated or invalid pipe will not generate an error and will
- //! instead simply return.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDPipeFree(unsigned int ulIndex, unsigned int ulPipe)
- {
- int iDMAIdx;
- if(ulPipe & EP_PIPE_TYPE_OUT)
- {
- //
- // Clear the address and type for this endpoint to free it up.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipe & EP_PIPE_IDX_M].ulDevAddr = 0;
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipe & EP_PIPE_IDX_M].ulType = 0;
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipe & EP_PIPE_IDX_M].pfnCallback = 0;
- //
- // Get the dma channel used by this pipe.
- //
- iDMAIdx = g_sUSBHCD[ulIndex].USBOUTPipes[ulPipe & EP_PIPE_IDX_M].ucDMAChannel;
- //
- // Mark the channel as free for use.
- //
- g_sUSBHCD[ulIndex].ucDMAChannels[iDMAIdx] = USBHCD_DMA_UNUSED;
- //
- // Clear out the current channel in use by this pipe.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[ulPipe & EP_PIPE_IDX_M].ucDMAChannel =
- USBHCD_DMA_UNUSED;
- //
- // Free up the FIFO memory used by this endpoint.
- //
- if(g_sUSBHCD[ulIndex].USBOUTPipes[ulPipe & EP_PIPE_IDX_M].ucFIFOSize)
- {
- FIFOFree(&g_sUSBHCD[ulIndex].USBOUTPipes[ulPipe & EP_PIPE_IDX_M]);
- }
- }
- else if(ulPipe & EP_PIPE_TYPE_IN)
- {
- //
- // Clear the address and type for this endpoint to free it up.
- //
- g_sUSBHCD[ulIndex].USBINPipes[ulPipe & EP_PIPE_IDX_M].ulDevAddr = 0;
- g_sUSBHCD[ulIndex].USBINPipes[ulPipe & EP_PIPE_IDX_M].ulType = 0;
- g_sUSBHCD[ulIndex].USBINPipes[ulPipe & EP_PIPE_IDX_M].pfnCallback = 0;
- //
- // Get the dma channel used by this pipe.
- //
- iDMAIdx = g_sUSBHCD[ulIndex].USBINPipes[ulPipe & EP_PIPE_IDX_M].ucDMAChannel;
- //
- // Mark the channel as free for use.
- //
- g_sUSBHCD[ulIndex].ucDMAChannels[iDMAIdx] = USBHCD_DMA_UNUSED;
- //
- // Clear out the current channel in use by this pipe.
- //
- g_sUSBHCD[ulIndex].USBINPipes[ulPipe & EP_PIPE_IDX_M].ucDMAChannel =
- USBHCD_DMA_UNUSED;
- //
- // Free up the FIFO memory used by this endpoint.
- //
- if(g_sUSBHCD[ulIndex].USBINPipes[ulPipe & EP_PIPE_IDX_M].ucFIFOSize)
- {
- FIFOFree(&g_sUSBHCD[ulIndex].USBINPipes[ulPipe & EP_PIPE_IDX_M]);
- }
- }
- }
- //*****************************************************************************
- //
- // This internal function initializes the HCD code.
- //
- // \param ulIndex specifies which USB controller to use.
- // \param pvPool is a pointer to the data to use as a memory pool for this
- // controller.
- // \param ulPoolSize is the size in bytes of the buffer passed in as pvPool.
- //
- // This function will perform all the necessary operations to allow the USB
- // host controller to begin enumeration and communication with a device. This
- // function should typically be called once at the start of an application
- // before any other calls are made to the host controller.
- //
- // \return None.
- //
- //*****************************************************************************
- static void
- USBHCDInitInternal(unsigned int ulIndex, void *pvPool,
- unsigned int ulPoolSize)
- {
- int iIdx;
- ASSERT(ulIndex == 0);
- //
- // The first 64 Bytes are allocated to endpoint 0.
- //
- g_ulAlloc[0] = 1;
- g_ulAlloc[1] = 0;
- //
- // Save the base address for this controller.
- //
- g_sUSBHCD[ulIndex].ulUSBBase = g_USBInstance[ulIndex].uiBaseAddr ;
- //
- // All Pipes are unused at start.
- //
- for(iIdx = 0; iIdx < MAX_NUM_PIPES; iIdx++)
- {
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulDevAddr = 0;
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulType = USBHCD_PIPE_UNUSED;
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].ucDMAChannel = USBHCD_DMA_UNUSED;
- g_sUSBHCD[ulIndex].USBOUTPipes[iIdx].ulDevAddr = 0;
- g_sUSBHCD[ulIndex].USBOUTPipes[iIdx].ulType = USBHCD_PIPE_UNUSED;
- g_sUSBHCD[ulIndex].USBOUTPipes[iIdx].ucDMAChannel = USBHCD_DMA_UNUSED;
- }
- //
- // All DMA channels are unused at start.
- //
- for(iIdx = 0; iIdx < MAX_NUM_DMA_CHANNELS; iIdx++)
- {
- g_sUSBHCD[ulIndex].ucDMAChannels[iIdx] = USBHCD_DMA_UNUSED;
- }
- //
- // Initialized the device structure.
- //
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_IDLE;
- g_sUSBHCD[ulIndex].USBDevice[0].pConfigDescriptor = 0;
- //
- // Initialize the device descriptor.
- //
- g_sUSBHCD[ulIndex].USBDevice[0].DeviceDescriptor.bLength = 0;
- g_sUSBHCD[ulIndex].USBDevice[0].DeviceDescriptor.bMaxPacketSize0 = 0;
- //
- // Initialize the device address.
- //
- g_sUSBHCD[ulIndex].USBDevice[0].ulAddress = 0;
- //
- // Set the current interface to 0.
- //
- g_sUSBHCD[ulIndex].USBDevice[0].ulInterface = 0;
- //
- // Allocate the memory needed for reading descriptors.
- //
- g_sUSBHCD[ulIndex].pvPool = pvPool;
- g_sUSBHCD[ulIndex].ulPoolSize = ulPoolSize;
- //
- // Initialize the device class.
- //
- g_sUSBHCD[ulIndex].ulClass = USB_CLASS_EVENTS;
- //
- // Initialize the USB tick module.
- //
- InternalUSBTickInit();
- //
- // Only do hardware update if the stack is in Host mode, do not touch the
- // hardware for OTG mode operation.
- //
- if(g_eUSBMode == USB_MODE_HOST)
- {
- //
- // Configure the End point 0.
- //
- USBHostEndpointConfig(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0, 64, 0, 0,
- (USB_EP_MODE_CTRL | USB_EP_SPEED_HIGH |
- USB_EP_HOST_OUT));
-
- USBEnableOtgIntr(g_USBInstance[ulIndex].uiSubBaseAddr);
- //
- // Enable USB Interrupts.
- //
- USBIntEnableControl(g_USBInstance[ulIndex].uiBaseAddr , USB_INTCTRL_RESET |
- USB_INTCTRL_DISCONNECT |
- USB_INTCTRL_SOF |
- USB_INTCTRL_SESSION |
- USB_INTCTRL_BABBLE |
- USB_INTCTRL_CONNECT |
- USB_INTCTRL_RESUME |
- USB_INTCTRL_SUSPEND |
- USB_INTCTRL_VBUS_ERR |
- USB_INTCTRL_POWER_FAULT);
- USBIntEnableEndpoint(g_USBInstance[ulIndex].uiBaseAddr , USB_INTEP_ALL);
- //
- // Enable the USB interrupt.
- //
- //IntEnable(INT_USB0);
- #ifdef _TMS320C6X
- /* No DSP API to enable USB0 event */
- #else
- IntSystemEnable(g_USBInstance[ulIndex].uiInterruptNum);
- #endif
- //
- // There is no automatic power in pure host mode.
- //
- USBHCDPowerConfigSet(ulIndex, g_sUSBHCD[ulIndex].ulPowerConfig & ~USB_HOST_PWREN_AUTO);
- //
- // This is required to get into host mode.
- //
- USBOTGSessionRequest(g_USBInstance[ulIndex].uiBaseAddr , true);
- }
- }
- //*****************************************************************************
- //
- //! This function is used to set the power pin and power fault configuration.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param ulPwrConfig is the power configuration to use for the application.
- //!
- //! This function must be called before HCDInit() is called so that the power
- //! pin configuration can be set before power is enabled. The \e ulPwrConfig
- //! flags specify the power fault level sensitivity, the power fault action,
- //! and the power enable pin level and source.
- //!
- //! One of the following can be selected as the power fault level sensitivity:
- //!
- //! - \b USBHCD_FAULT_LOW - An external power fault is indicated by the pin
- //! being driven low.
- //! - \b USBHCD_FAULT_HIGH - An external power fault is indicated by the pin
- //! being driven high.
- //!
- //! One of the following can be selected as the power fault action:
- //!
- //! - \b USBHCD_FAULT_VBUS_NONE - No automatic action when power fault
- //! detected.
- //! - \b USBHCD_FAULT_VBUS_TRI - Automatically Tri-state the USBnEPEN pin on a
- //! power fault.
- //! - \b USBHCD_FAULT_VBUS_DIS - Automatically drive the USBnEPEN pin to it's
- //! inactive state on a power fault.
- //!
- //! One of the following can be selected as the power enable level and source:
- //!
- //! - \b USBHCD_VBUS_MANUAL - Power control is completely managed by the
- //! application, the USB library will provide a
- //! power callback to request power state changes.
- //! - \b USBHCD_VBUS_AUTO_LOW - USBEPEN is driven low by the USB controller
- //! automatically if USBOTGSessionRequest() has
- //! enabled a session.
- //! - \b USBHCD_VBUS_AUTO_HIGH - USBEPEN is driven high by the USB controller
- //! automatically if USBOTGSessionRequest() has
- //! enabled a session.
- //!
- //! If USBHCD_VBUS_MANUAL is used then the application must provide an
- //! event driver to receive the USB_EVENT_POWER_ENABLE and
- //! USB_EVENT_POWER_DISABLE events and enable and disable power to VBUS when
- //! requested by the USB library. The application should respond to a power
- //! control callback by enabling or disabling VBUS as soon as possible and
- //! before returning from the callback function.
- //!
- //! \note The following values should no longer be used with the USB library:
- //! USB_HOST_PWRFLT_LOW, USB_HOST_PWRFLT_HIGH, USB_HOST_PWRFLT_EP_NONE,
- //! USB_HOST_PWRFLT_EP_TRI, USB_HOST_PWRFLT_EP_LOW, USB_HOST_PWRFLT_EP_HIGH,
- //! USB_HOST_PWREN_LOW, USB_HOST_PWREN_HIGH, USB_HOST_PWREN_VBLOW, and
- //! USB_HOST_PWREN_VBHIGH.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDPowerConfigInit(unsigned int ulIndex, unsigned int ulPwrConfig)
- {
- ASSERT(ulIndex == 0);
- //
- // Save the value as it will be used later.
- //
- g_sUSBHCD[ulIndex].ulPowerConfig = ulPwrConfig;
- }
- //*****************************************************************************
- //
- //! This function is used to get the power pin and power fault configuration.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //!
- //! This function will return the current power control pin configuration as
- //! set by the USBHCDPowerConfigInit() function or the defaults if not yet set.
- //! See the USBHCDPowerConfigInit() documentation for the meaning of the bits
- //! that are returned by this function.
- //!
- //! \return The configuration of the power control pins.
- //!
- //*****************************************************************************
- unsigned int
- USBHCDPowerConfigGet(unsigned int ulIndex)
- {
- ASSERT(ulIndex == 0);
- //
- // Save the value as it will be used later.
- //
- return(g_sUSBHCD[ulIndex].ulPowerConfig);
- }
- //*****************************************************************************
- //
- //! This function is used to set the power pin and power fault configuration.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param ulConfig specifies which USB power configuration to use.
- //!
- //! This function will set the current power control pin configuration as
- //! set by the USBHCDPowerConfigInit() function or the defaults if not yet set.
- //! See the USBHCDPowerConfigInit() documentation for the meaning of the bits
- //! that are set by this function.
- //!
- //! \return Returns zero to indicate the power setting is now active.
- //!
- //*****************************************************************************
- unsigned int
- USBHCDPowerConfigSet(unsigned int ulIndex, unsigned int ulConfig)
- {
- ASSERT(ulIndex == 0);
- //
- // Remember the current setting.
- //
- g_sUSBHCD[ulIndex].ulPowerConfig = ulConfig;
- //
- // Clear out the two flag bits.
- //
- ulConfig = g_sUSBHCD[ulIndex].ulPowerConfig & ~(USBHCD_VBUS_MANUAL | USBHCD_FAULT_VBUS_DIS);
- //
- // If there is an automatic disable power action specified then set the
- // polarity of the signal to match EPEN.
- //
- if(g_sUSBHCD[ulIndex].ulPowerConfig & USBHCD_FAULT_VBUS_DIS)
- {
- //
- // Insure that the assumption below is true.
- //
- ASSERT((USBHCD_VBUS_AUTO_HIGH & 1) == 1);
- ASSERT((USBHCD_VBUS_AUTO_LOW & 1) == 0);
- //
- // This is taking advantage of the difference between
- // USBHCD_VBUS_AUTO_LOW and USBHCD_VBUS_AUTO_HIGH being that bit
- // one is set when EPEN is active high.
- //
- if(g_sUSBHCD[ulIndex].ulPowerConfig & 1)
- {
- g_sUSBHCD[ulIndex].ulPowerConfig |= USB_HOST_PWRFLT_EP_HIGH;
- }
- else
- {
- g_sUSBHCD[ulIndex].ulPowerConfig |= USB_HOST_PWRFLT_EP_LOW;
- }
- }
- //
- // Initialize the power configuration.
- //
- USBHostPwrConfig(g_USBInstance[ulIndex].uiBaseAddr , ulConfig);
- //
- // If not in manual mode then just turn on power.
- //
- if((g_sUSBHCD[ulIndex].ulPowerConfig & USBHCD_VBUS_MANUAL) == 0)
- {
- //
- // Power the USB bus.
- //
- USBHostPwrEnable(g_USBInstance[ulIndex].uiBaseAddr );
- }
- //
- // Return success.
- //
- return(0);
- }
- //*****************************************************************************
- //
- //! This function returns if the current power settings will automatically
- //! handle enabling and disabling VBUS power.
- //!
- //! \param ulIndex specifies which USB controller to query.
- //!
- //! This function returns if the current power control pin configuration will
- //! automatically apply power or whether it will be left to the application
- //! to turn on power when it is notified.
- //!
- //! \return A non-zero value indicates that power is automatically applied and
- //! a value of zero indicates that the application must manually apply power.
- //!
- //*****************************************************************************
- unsigned int
- USBHCDPowerAutomatic(unsigned int ulIndex)
- {
- //
- // Check if the controller is automatically applying power or not.
- //
- if(g_sUSBHCD[ulIndex].ulPowerConfig & USBHCD_VBUS_MANUAL)
- {
- return(0);
- }
- return(1);
- }
- //*****************************************************************************
- //
- //! This function is used to initialize the HCD code.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param pvPool is a pointer to the data to use as a memory pool for this
- //! controller.
- //! \param ulPoolSize is the size in bytes of the buffer passed in as pvPool.
- //!
- //! This function will perform all the necessary operations to allow the USB
- //! host controller to begin enumeration and communication with devices. This
- //! function should typically be called once at the start of an application
- //! once all of the device and class drivers are ready for normal operation.
- //! This call will start up the USB host controller and any connected device
- //! will immediately start the enumeration sequence.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDInit(unsigned int ulIndex, void *pvPool, unsigned int ulPoolSize)
- {
- int iDriver;
- //
- // Check the arguments.
- //
- ASSERT(ulIndex == 0);
- //
- // Make sure there is at least enough to read the configuration descriptor.
- //
- ASSERT(ulPoolSize >= sizeof(tConfigDescriptor));
- //
- // Should not call this if the stack is in device mode.
- //
- ASSERT(g_eUSBMode != USB_MODE_DEVICE)
-
- if(ulIndex == 0)
- {
- g_USBInstance[ulIndex].uiUSBInstance = ulIndex;
- g_USBInstance[ulIndex].uiBaseAddr = USB0_BASE;
- g_USBInstance[ulIndex].uiSubBaseAddr = USB_0_OTGBASE;
- g_USBInstance[ulIndex].uiInterruptNum = SYS_INT_USB0;
- g_USBInstance[ulIndex].uiSubInterruptNum = SYS_INT_USBSSINT;
- g_USBInstance[ulIndex].uiPHYConfigRegAddr = CFGCHIP2_USBPHYCTRL;
- }
- #if (USB_NUM_INSTANCE == 2)
- else if(ulIndex == 1)
- {
- g_USBInstance[ulIndex].uiUSBInstance = ulIndex;
- g_USBInstance[ulIndex].uiBaseAddr = USB1_BASE;
- g_USBInstance[ulIndex].uiSubBaseAddr = USB_1_OTGBASE;
- g_USBInstance[ulIndex].uiInterruptNum = SYS_INT_USB1;
- g_USBInstance[ulIndex].uiSubInterruptNum = SYS_INT_USBSSINT;
- g_USBInstance[ulIndex].uiPHYConfigRegAddr = CFGCHIP2_USB1PHYCTRL;
- }
- #endif
- g_sUSBHCD[ulIndex].USBHTimeOut.Value.slEP0 = USB_EP0_TIMEOUT_MILLISECS;
- g_sUSBHCD[ulIndex].USBHTimeOut.Value.slNonEP0= USB_NONEP0_TIMEOUT_MILLISECS;
- g_sUSBHCD[ulIndex].USBHTimeOut.Status.slEP0 = 0;
- g_sUSBHCD[ulIndex].USBHTimeOut.Status.slNonEP0= 0;
- //
- // If no mode is set then make the mode become host mode.
- //
- if(g_eUSBMode == USB_MODE_NONE)
- {
- g_eUSBMode = USB_MODE_HOST;
- }
- //
- // Only do hardware update if the stack is in Host mode, do not touch the
- // hardware for OTG mode operation.
- //
- if(g_eUSBMode == USB_MODE_HOST)
- {
- //
- // Enable Clocking to the USB controller.
- //
- USBModuleClkEnable(ulIndex, g_USBInstance[ulIndex].uiBaseAddr );
- USBReset(g_USBInstance[ulIndex].uiSubBaseAddr);
- //
- // Turn on USB Phy clock.
- //
- UsbPhyOn(ulIndex);
- }
- //
- // Call our internal function to perform the initialization.
- //
- USBHCDInitInternal(ulIndex, pvPool, ulPoolSize);
- //
- // No event driver is present by default.
- //
- g_sUSBHCD[ulIndex].iEventDriver = -1;
-
- //
- // Retry recovery and comunication with device on error.
- //
- g_sUSBHCD[ulIndex].ulConnectRetry = USBHCD_DEV_RECOVER_RETRY;
- //
- // Search through the Host Class driver list for the devices class.
- //
- for(iDriver = 0; iDriver < g_sUSBHCD[ulIndex].ulNumClassDrivers; iDriver++)
- {
- if(g_sUSBHCD[ulIndex].pClassDrivers[iDriver]->ulInterfaceClass ==
- USB_CLASS_EVENTS)
- {
- //
- // Event driver was found so remember it.
- //
- g_sUSBHCD[ulIndex].iEventDriver = iDriver;
- }
- }
-
- }
- //*****************************************************************************
- //
- //! This function is used to initialize the HCD class driver list.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param ppHClassDrvs is an array of host class drivers that are
- //! supported on this controller.
- //! \param ulNumDrivers is the number of entries in the \e pHostClassDrivers
- //! array.
- //!
- //! This function will set the host classes supported by the host controller
- //! specified by the \e ulIndex parameter. This function should be called
- //! before enabling the host controller driver with the USBHCDInit() function.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDRegisterDrivers(unsigned int ulIndex,
- const tUSBHostClassDriver * const *ppHClassDrvs,
- unsigned int ulNumDrivers)
- {
- ASSERT(ulIndex == 0);
- g_sUSBHCD[ulIndex].ulIndex = ulIndex;
- //
- // Save the class drivers.
- //
- g_sUSBHCD[ulIndex].pClassDrivers = ppHClassDrvs;
- //
- // Save the number of class drivers.
- //
- g_sUSBHCD[ulIndex].ulNumClassDrivers = ulNumDrivers;
- }
- //*****************************************************************************
- //
- //! This function is used to terminate the HCD code.
- //!
- //! \param ulIndex specifies which USB controller to release.
- //!
- //! This function will clean up the USB host controller and disable it in
- //! preparation for shutdown or a switch to USB device mode. Once this call is
- //! made, \e USBHCDInit() may be called to reinitialize the controller and
- //! prepare for host mode operation.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDTerm(unsigned int ulIndex)
- {
- ASSERT(ulIndex == 0);
- //
- // End the session.
- //
- USBOTGSessionRequest(g_USBInstance[ulIndex].uiBaseAddr , false);
- //
- // Remove power from the USB bus.
- //
- USBHostPwrDisable(g_USBInstance[ulIndex].uiBaseAddr );
- //
- // Disable USB interrupts.
- //
- #ifdef _TMS320C6X
- /* No DSP API to disable USB0 event */
- #else
- IntSystemDisable(g_USBInstance[ulIndex].uiInterruptNum);
- #endif
- USBIntDisableControl(g_USBInstance[ulIndex].uiBaseAddr , USB_INTCTRL_ALL);
- USBIntDisableEndpoint(g_USBInstance[ulIndex].uiBaseAddr , USB_INTEP_ALL);
- //
- // Set the host controller state back to it's initial values.
- //
- g_sUSBHCD[ulIndex].USBINPipes[0].ulType = USBHCD_PIPE_UNUSED;
- g_sUSBHCD[ulIndex].USBINPipes[1].ulType = USBHCD_PIPE_UNUSED;
- g_sUSBHCD[ulIndex].USBINPipes[2].ulType = USBHCD_PIPE_UNUSED;
- g_sUSBHCD[ulIndex].USBOUTPipes[0].ulType = USBHCD_PIPE_UNUSED;
- g_sUSBHCD[ulIndex].USBOUTPipes[1].ulType = USBHCD_PIPE_UNUSED;
- g_sUSBHCD[ulIndex].USBOUTPipes[2].ulType = USBHCD_PIPE_UNUSED;
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_IDLE;
- g_sUSBHCD[ulIndex].USBDevice[0].pConfigDescriptor = 0;
- g_sUSBHCD[ulIndex].USBDevice[0].DeviceDescriptor.bLength = 0;
- g_sUSBHCD[ulIndex].USBDevice[0].DeviceDescriptor.bMaxPacketSize0 = 0;
- g_sUSBHCD[ulIndex].USBDevice[0].ulAddress = 0;
- g_sUSBHCD[ulIndex].USBDevice[0].ulInterface = 0;
- g_sUSBHCD[ulIndex].pvPool = 0;
- g_sUSBHCD[ulIndex].ulPoolSize = 0;
- }
- //*****************************************************************************
- //
- //! This function generates reset signaling on the USB bus.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //!
- //! This function handles sending out reset signaling on the USB bus. After
- //! returning from this function, any attached device on the USB bus should
- //! have returned to it's reset state.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDReset(unsigned int ulIndex)
- {
- ASSERT(ulIndex == 0);
- //
- // Start the reset signaling.
- //
- USBHostReset(g_USBInstance[ulIndex].uiBaseAddr , 1);
- //
- // Wait 20ms
- //
- delay(20);
- //
- // End reset signaling on the bus.
- //
- USBHostReset(g_USBInstance[ulIndex].uiBaseAddr , 0);
- //
- // Need to wait at least 10ms to let the device recover from
- // the reset. This is the delay specified in the USB 2.0 spec.
- // We will hold the reset for 20ms.
- //
- delay(20);
- }
- //*****************************************************************************
- //
- //! This function will generate suspend signaling on the USB bus.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //!
- //! This function is used to generate suspend signaling on the USB bus. In
- //! order to leave the suspended state, the application should call
- //! USBHCDResume().
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDSuspend(unsigned int ulIndex)
- {
- ASSERT(ulIndex == 0);
- //
- // Start the suspend signaling.
- //
- USBHostSuspend(g_USBInstance[ulIndex].uiBaseAddr );
- }
- //*****************************************************************************
- //
- //! This function will generate resume signaling on the USB bus.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //!
- //! This function is used to generate resume signaling on the USB bus in order
- //! to cause USB devices to leave their suspended state. This call should
- //! not be made unless a preceding call to USBHCDSuspend() has been made.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDResume(unsigned int ulIndex)
- {
- ASSERT(ulIndex == 0);
- //
- // Start the resume signaling.
- //
- USBHostResume(g_USBInstance[ulIndex].uiBaseAddr , 1);
- //
- // Wait 100ms
- //
- delay(100);
- //
- // End reset signaling on the bus.
- //
- USBHostResume(g_USBInstance[ulIndex].uiBaseAddr , 0);
- }
- //*****************************************************************************
- //
- //! This function issues a request for the current configuration descriptor
- //! from a device.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param pDevice is a pointer to the device structure that holds the buffer
- //! to store the configuration descriptor.
- //!
- //! This function will request the configuration descriptor from the device.
- //! The \e pDevice->ConfigDescriptor member variable is used to hold the data
- //! for this request. This buffer will be allocated from the pool provided by
- //! the HCDInit() function. \e pDevice->DeviceDescriptor.bMaxPacketSize0
- //! should be valid prior to this call in order to correctly receive the
- //! configuration descriptor. If this variable is not valid then this call
- //! will not return accurate data.
- //!
- //! \return The number of bytes returned due to the request. This value can be
- //! zero if the device did not respond.
- //
- //*****************************************************************************
- static unsigned int
- USBHCDGetConfigDescriptor(unsigned int ulIndex, tUSBHostDevice *pDevice)
- {
- tUSBRequest SetupPacket;
- unsigned int ulBytes;
- ASSERT(ulIndex == 0);
- ulBytes = 0;
- //
- // This is a Standard Device IN request.
- //
- SetupPacket.bmRequestType =
- USB_RTYPE_DIR_IN | USB_RTYPE_STANDARD | USB_RTYPE_DEVICE;
- //
- // Request a Device Descriptor.
- //
- SetupPacket.bRequest = USBREQ_GET_DESCRIPTOR;
- SetupPacket.wValue = USB_DTYPE_CONFIGURATION << 8;
- //
- // Index is always 0 for device configurations requests.
- //
- SetupPacket.wIndex = 0;
- //
- // Only ask for the configuration header first to see how big the
- // whole thing is.
- //
- if(g_sUSBHCD[ulIndex].USBDevice[0].pConfigDescriptor == 0)
- {
- //
- // Only request the space available.
- //
- SetupPacket.wLength = sizeof(tConfigDescriptor);
- //
- // Set the memory to use for the config descriptor and save the size.
- //
- g_sUSBHCD[ulIndex].USBDevice[0].pConfigDescriptor = g_sUSBHCD[ulIndex].pvPool;
- g_sUSBHCD[ulIndex].USBDevice[0].ulConfigDescriptorSize = g_sUSBHCD[ulIndex].ulPoolSize;
- //
- // Put the setup packet in the buffer.
- //
- ulBytes =
- USBHCDControlTransfer(ulIndex, &SetupPacket, pDevice->ulAddress,
- (unsigned char *)pDevice->pConfigDescriptor,
- sizeof(tConfigDescriptor),
- pDevice->DeviceDescriptor.bMaxPacketSize0);
- }
- //
- // If the Configuration header was successfully returned then get the
- // full configuration descriptor.
- //
- if(ulBytes == sizeof(tConfigDescriptor))
- {
- //
- // Save the total size and request the full configuration descriptor.
- //
- SetupPacket.wLength =
- g_sUSBHCD[ulIndex].USBDevice[0].pConfigDescriptor->wTotalLength;
- //
- // Don't allow the buffer to be larger than was allocated.
- //
- if(SetupPacket.wLength > g_sUSBHCD[ulIndex].ulPoolSize)
- {
- SetupPacket.wLength = g_sUSBHCD[ulIndex].ulPoolSize;
- }
- //
- // Put the setup packet in the buffer.
- //
- ulBytes =
- USBHCDControlTransfer(ulIndex, &SetupPacket, pDevice->ulAddress,
- (unsigned char *)pDevice->pConfigDescriptor,
- SetupPacket.wLength,
- pDevice->DeviceDescriptor.bMaxPacketSize0);
- }
- return(ulBytes);
- }
- //*****************************************************************************
- //
- //! This function issues a request for a device descriptor from a device.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param pDevice is a pointer to the device structure that holds the buffer
- //! to store the device descriptor into.
- //!
- //! This function will request the device descriptor from the device. The
- //! \e pDevice->DeviceDescriptor descriptor is used to hold the data for this
- //! request. \e pDevice->DeviceDescriptor.bMaxPacketSize0 should be
- //! initialized to zero or to the valid maximum packet size if it is known. If
- //! this variable is not set to zero, then this call will determine the maximum
- //! packet size for endpoint 0 and save it in the structure member
- //! bMaxPacketSize0.
- //!
- //! \return The number of bytes returned due to the request. This value can be
- //! zero if the device did not respond.
- //
- //*****************************************************************************
- static unsigned int
- USBHCDGetDeviceDescriptor(unsigned int ulIndex, tUSBHostDevice *pDevice)
- {
- tUSBRequest SetupPacket;
- unsigned int ulBytes;
- unsigned int retStatus = 1;
- ASSERT(ulIndex == 0);
- //
- // This is a Standard Device IN request.
- //
- SetupPacket.bmRequestType =
- USB_RTYPE_DIR_IN | USB_RTYPE_STANDARD | USB_RTYPE_DEVICE;
- //
- // Request a Device Descriptor.
- //
- SetupPacket.bRequest = USBREQ_GET_DESCRIPTOR;
- SetupPacket.wValue = USB_DTYPE_DEVICE << 8;
- //
- // Index is always 0 for device requests.
- //
- SetupPacket.wIndex = 0;
- //
- // All devices must have at least an 8 byte max packet size so just ask
- // for 8 bytes to start with.
- //
- SetupPacket.wLength = 8;
- ulBytes = 0;
- //
- // Discover the max packet size for endpoint 0.
- //
- if(pDevice->DeviceDescriptor.bMaxPacketSize0 == 0)
- {
- //
- // Put the setup packet in the buffer.
- //
- ulBytes =
- USBHCDControlTransfer(ulIndex, &SetupPacket, pDevice->ulAddress,
- (unsigned char *)&(pDevice->DeviceDescriptor),
- sizeof(tDeviceDescriptor),
- MAX_PACKET_SIZE_EP0);
- }
- retStatus = ulBytes;
- //
- // Now get the full descriptor now that the actual maximum packet size
- // is known.
- //
- if(retStatus && (ulBytes < sizeof(tDeviceDescriptor)))
- {
- SetupPacket.wLength = (unsigned short)sizeof(tDeviceDescriptor);
- ulBytes =
- USBHCDControlTransfer(ulIndex, &SetupPacket, pDevice->ulAddress,
- (unsigned char *)&(pDevice->DeviceDescriptor),
- sizeof(tDeviceDescriptor),
- pDevice->DeviceDescriptor.bMaxPacketSize0);
- }
- return(ulBytes);
- }
- //*****************************************************************************
- //
- //! This function is used to send the set address command to a device.
- //!
- //! \param ulDevAddress is the new device address to use for a device.
- //!
- //! The USBHCDSetAddress() function is used to set the USB device address, once
- //! a device has been discovered on the bus. This is typically issued
- //! following a USB reset which is triggered by a call the USBHCDReset(). The
- //! address passed into this function via the \e ulDevAddress parameter should
- //! be used for all further communications with the device once this function
- //! returns.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDSetAddress(unsigned int ulIndex, unsigned int ulDevAddress)
- {
- tUSBRequest SetupPacket;
- //
- // This is a Standard Device OUT request.
- //
- SetupPacket.bmRequestType =
- USB_RTYPE_DIR_OUT | USB_RTYPE_STANDARD | USB_RTYPE_DEVICE;
- //
- // Request a Device Descriptor.
- //
- SetupPacket.bRequest = USBREQ_SET_ADDRESS;
- SetupPacket.wValue = ulDevAddress;
- //
- // Index is always 0 for device requests.
- //
- SetupPacket.wIndex = 0;
- //
- // Only request the space available.
- //
- SetupPacket.wLength = 0;
- //
- // Put the setup packet in the buffer.
- //
- USBHCDControlTransfer(ulIndex, &SetupPacket, 0, 0, 0, MAX_PACKET_SIZE_EP0);
- //
- // Must delay 2ms after setting the address.
- //
- delay(2);
- }
- //*****************************************************************************
- //
- //! This function is used to send a Clear Feature request to a device.
- //!
- //! \param ulDevAddress is the USB bus address of the device that will receive
- //! this request.
- //! \param ulPipe is the pipe that will be used to send the request.
- //! \param ulFeature is one of the USB_FEATURE_* definitions.
- //!
- //! This function will issue a Clear Feature request to the device indicated
- //! by the \e ulDevAddress parameter. The \e ulPipe parameter is the USB pipe
- //! that should be used to send this request. The \e ulFeature parameter
- //! should be one of the following values:
- //!
- //! * \b USB_FEATURE_EP_HALT is used to end a HALT condition on a devices
- //! endpoint.
- //! * \b USB_FEATURE_REMOTE_WAKE is used to disable a device's remote wake
- //! feature.
- //! * \b USB_FEATURE_TEST_MODE is used take the USB device out of test mode.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDClearFeature(unsigned int devIndex, unsigned int ulDevAddress,
- unsigned int ulPipe, unsigned int ulFeature)
- {
- tUSBRequest SetupPacket;
- unsigned int ulIndex;
-
- //
- // Get the index number from the allocated pipe.
- //
- ulIndex = (ulPipe & EP_PIPE_IDX_M);
- //
- // This is a Standard Device OUT request.
- //
- SetupPacket.bmRequestType =
- USB_RTYPE_DIR_OUT | USB_RTYPE_STANDARD | USB_RTYPE_ENDPOINT;
- //
- // Request a Device Descriptor.
- //
- SetupPacket.bRequest = USBREQ_CLEAR_FEATURE;
- SetupPacket.wValue = ulFeature;
- //
- // Set the endpoint to access.
- //
- if(ulPipe & EP_PIPE_TYPE_IN)
- {
- SetupPacket.wIndex = g_sUSBHCD[devIndex].USBINPipes[ulIndex].ucEPNumber | 0x80;
- }
- else
- {
- SetupPacket.wIndex = g_sUSBHCD[devIndex].USBOUTPipes[ulIndex].ucEPNumber;
- }
- //
- // This is always 0.
- //
- SetupPacket.wLength = 0;
- //
- // Put the setup packet in the buffer.
- //
- USBHCDControlTransfer(devIndex, &SetupPacket, ulDevAddress, 0, 0,
- MAX_PACKET_SIZE_EP0);
- //
- // Set the endpoint to access.
- //
- if(ulPipe & EP_PIPE_TYPE_IN)
- {
- USBEndpointDataToggleClear(g_USBInstance[devIndex].uiBaseAddr , INDEX_TO_USB_EP(ulIndex + 1),
- USB_EP_HOST_IN);
- }
- else
- {
- USBEndpointDataToggleClear(g_USBInstance[devIndex].uiBaseAddr , INDEX_TO_USB_EP(ulIndex + 1),
- USB_EP_HOST_OUT);
- }
- //
- // Must delay 2ms after clearing the feature.
- //
- delay(2);
- }
- //*****************************************************************************
- //
- //! This function is used to set the current configuration for a device.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param ulDevice is the USB device for this function.
- //! \param ulConfiguration is one of the devices valid configurations.
- //!
- //! This function is used to set the current device configuration for a USB
- //! device. The \e ulConfiguration value must be one of the configuration
- //! indexes that was returned in the configuration descriptor from the device,
- //! or a value of 0. If 0 is passed in, the device will return to it's
- //! addressed state and no longer be in a configured state. If the value is
- //! non-zero then the device will change to the requested configuration.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDSetConfig(unsigned int ulIndex, unsigned int ulDevice,
- unsigned int ulConfiguration)
- {
- tUSBRequest SetupPacket;
- tUSBHostDevice *pDevice;
- ASSERT(ulIndex == 0);
- pDevice = (tUSBHostDevice *)ulDevice;
- //
- // This is a Standard Device OUT request.
- //
- SetupPacket.bmRequestType =
- USB_RTYPE_DIR_OUT | USB_RTYPE_STANDARD | USB_RTYPE_DEVICE;
- //
- // Request a Device Descriptor.
- //
- SetupPacket.bRequest = USBREQ_SET_CONFIG;
- SetupPacket.wValue = ulConfiguration;
- //
- // Index is always 0 for device requests.
- //
- SetupPacket.wIndex = 0;
- //
- // Only request the space available.
- //
- SetupPacket.wLength = 0;
- //
- // Put the setup packet in the buffer.
- //
- USBHCDControlTransfer(ulIndex, &SetupPacket, pDevice->ulAddress, 0, 0,
- MAX_PACKET_SIZE_EP0);
- }
- //*****************************************************************************
- //
- //! This function is used to set the current interface and alternate setting
- //! for an interface on a device.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param ulDevice is the USB device for this function.
- //! \param ulInterface is one of the valid interface numbers for a device.
- //! \param ulAltSetting is one of the valid alternate interfaces for the
- //! ulInterface number.
- //!
- //! This function is used to change the alternate setting for one of the valid
- //! interfaces on a USB device. The \e ulDevice specifies the device instance
- //! that was returned when the device was connected. This call will set the
- //! USB device's interface based on the \e ulInterface and \e ulAltSetting.
- //!
- //! \b Example: Set the USB device interface 2 to alternate setting 1.
- //!
- //! \verbatim
- //! USBHCDSetInterface(0, ulDevice, 2, 1);
- //! \endverbatim
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDSetInterface(unsigned int ulIndex, unsigned int ulDevice,
- unsigned int ulInterface, unsigned ulAltSetting)
- {
- tUSBRequest SetupPacket;
- tUSBHostDevice *pDevice;
- ASSERT(ulIndex == 0);
- pDevice = (tUSBHostDevice *)ulDevice;
- //
- // This is a Standard Device OUT request.
- //
- SetupPacket.bmRequestType =
- USB_RTYPE_DIR_OUT | USB_RTYPE_STANDARD | USB_RTYPE_INTERFACE;
- //
- // Request a Device Descriptor.
- //
- SetupPacket.bRequest = USBREQ_SET_INTERFACE;
- //
- // Index is the interface to access.
- //
- SetupPacket.wIndex = ulInterface;
- //
- // wValue is the alternate setting.
- //
- SetupPacket.wValue = ulAltSetting;
- //
- // Only request the space available.
- //
- SetupPacket.wLength = 0;
- //
- // Put the setup packet in the buffer.
- //
- USBHCDControlTransfer(ulIndex, &SetupPacket, pDevice->ulAddress, 0, 0,
- MAX_PACKET_SIZE_EP0);
- }
- //*****************************************************************************
- //
- // The internal function to see if a new schedule event should occur.
- //
- // This function is called by the main interrupt handler due to start of frame
- // interrupts to determine if a new scheduler event should be sent to the USB
- // pipe.
- //
- // \return None.
- //
- //*****************************************************************************
- void
- USBHostCheckPipes(unsigned int ulIndex)
- {
- int iIdx;
- for(iIdx = 0; iIdx < 3; iIdx++)
- {
- //
- // Skip unused pipes.
- //
- if(g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulType == USBHCD_PIPE_UNUSED)
- {
- continue;
- }
- //
- // If the tick has expired and it has an interval then update it.
- //
- if((g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulInterval != 0) &&
- (g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulNextEventTick == g_sUSBHCD[ulIndex].ulCurrentTick))
- {
- //
- // Schedule the next event.
- //
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulNextEventTick +=
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].ulInterval;
- //
- // If the pipe is IDLE and there is a callback, let the higher
- // level drivers know that a new transfer can be scheduled.
- //
- if((g_sUSBHCD[ulIndex].USBINPipes[iIdx].eState == PIPE_IDLE) &&
- (g_sUSBHCD[ulIndex].USBINPipes[iIdx].pfnCallback))
- {
- g_sUSBHCD[ulIndex].USBINPipes[iIdx].pfnCallback(ulIndex, IN_PIPE_HANDLE(ulIndex, iIdx),
- USB_EVENT_SCHEDULER);
- }
- }
- }
- }
- //*****************************************************************************
- //
- // The internal USB host mode interrupt handler.
- //
- // \param ulIndex is the USB controller associated with this interrupt.
- // \param ulStatus is the current interrupt status as read via a call to
- // \e USBIntStatusControl().
- //
- // This the main USB interrupt handler called when operating in host mode.
- // This handler will branch the interrupt off to the appropriate handlers
- // depending on the current status of the USB controller.
- //
- // The two-tiered structure for the interrupt handler ensures that it is
- // possible to use the same handler code in both host and OTG modes and
- // means that device code can be excluded from applications that only require
- // support for USB host mode operation.
- //
- // \return None.
- //
- //*****************************************************************************
- void
- USBHostIntHandlerInternal(unsigned int ulIndex, unsigned int ulStatus, unsigned int *endPStatus)
- {
- unsigned int ulEPStatus;
- static unsigned int ulSOFDivide = 0;
- unsigned int ulEvent;
- unsigned int ulIdx;
- unsigned int epStatus;
- unsigned int epnStatus = 0;
- #ifdef DMA_MODE
- unsigned int pendReg = 0;
- #endif
- //
- // Get the controller interrupt status from the wrapper registers
- // Only the lower 16bits contain EP intr data
- //
- if(endPStatus == NULL)
- {
- epStatus= 0xFFFF & ulStatus;
- ulStatus >>=16;
- }
- else
- {
- epStatus = *endPStatus;
- }
- ulStatus |= USBIntStatusControl(g_USBInstance[ulIndex].uiBaseAddr );
- if(ulStatus & USB_INTCTRL_SOF)
- {
- g_sUSBHCD[ulIndex].ulCurrentTick++;
- USBHostCheckPipes(ulIndex);
- }
- //
- // In the event of a USB VBUS error, end the session and remove power to
- // the device.
- //
- if(ulStatus & USB_INTCTRL_VBUS_ERR)
- {
- //
- // Set the VBUS error event. We deliberately clear all other events
- // since this one means anything else that is outstanding is
- // irrelevant.
- //
- g_sUSBHCD[ulIndex].ulUSBHIntEvents = INT_EVENT_VBUS_ERR;
- return;
- }
- //
- // Babble Interrupt generated.
- //
- if(ulStatus & USB_INTCTRL_BABBLE)
- {
- g_sUSBHCD[ulIndex].ulUSBHIntEvents |= INT_EVENT_BABBLE_FAULT;
- return;
- }
- //
- // Suspend was signaled on the bus.
- //
- if(ulStatus & USB_INTCTRL_SUSPEND)
- {
- }
- //
- // Start the session.
- //
- if(ulStatus & USB_INTCTRL_SESSION)
- {
- //
- // Power the USB bus.
- //
- USBHostPwrEnable(g_USBInstance[ulIndex].uiBaseAddr );
- USBOTGSessionRequest(g_USBInstance[ulIndex].uiBaseAddr , true);
- }
- //
- // Resume was signaled on the bus.
- //
- if(ulStatus & USB_INTCTRL_RESUME)
- {
- }
- //
- // Device connected so tell the main routine to issue a reset.
- //
- if(ulStatus & USB_INTCTRL_CONNECT)
- {
- //
- // Set the connect flag and clear disconnect if it happens to be set.
- //
- g_sUSBHCD[ulIndex].ulUSBHIntEvents |= INT_EVENT_CONNECT;
- g_sUSBHCD[ulIndex].ulUSBHIntEvents &= ~INT_EVENT_DISCONNECT;
- //
- // Power the USB bus.
- //
- USBHostPwrEnable(g_USBInstance[ulIndex].uiBaseAddr );
- }
- //
- // Device was unplugged.
- //
- if(ulStatus & USB_INTCTRL_DISCONNECT)
- {
- //
- // Set the disconnect flag and clear connect if it happens to be set.
- //
- g_sUSBHCD[ulIndex].ulUSBHIntEvents |= INT_EVENT_DISCONNECT;
- g_sUSBHCD[ulIndex].ulUSBHIntEvents &= ~INT_EVENT_CONNECT;
- }
- //
- // Start of Frame was received.
- //
- if(ulStatus & USB_INTCTRL_SOF)
- {
- //
- // Increment the global Start of Frame counter.
- //
- g_ulUSBSOFCount++;
- //
- // Increment our SOF divider.
- //
- ulSOFDivide++;
- //
- // Have we counted enough SOFs to allow us to call the tick function?
- //
- if(ulSOFDivide == USB_SOF_TICK_DIVIDE)
- {
- //
- // Yes - reset the divider and call the SOF tick handler.
- //
- ulSOFDivide = 0;
- InternalUSBStartOfFrameTick(USB_SOF_TICK_DIVIDE, ulIndex);
- }
- }
- //
- // Handle end point 0 interrupts.
- //
- if(epStatus & USB_INTEP_0)
- {
- USBHCDEnumHandler(ulIndex);
- }
-
- /*
- converting the epstatus(Wrapper register data) to ulStatus( MUSB register data)
- */
-
- if(endPStatus == NULL)
- {
- epnStatus = 0xFF & epStatus;
- epnStatus = epnStatus | ((0xFF00 & epStatus)<<8);
- }
- else
- {
- epnStatus = epStatus;
- }
- #ifdef DMA_MODE
- // Get the DMA Interrupt status
- pendReg = CppiDmaGetPendStatus(ulIndex);
- #endif
- //
- // Check to see if any uDMA transfers are pending
- //
- for(ulIdx = 0; ulIdx < MAX_NUM_PIPES; ulIdx++)
- {
-
- if((epnStatus == 0) && (g_sUSBHCD[ulIndex].ulDMAPending == 0))
- {
- break;
- }
- #ifdef DMA_MODE
- //
- // Check for any pending RX transaction
- //
- if((pendReg & CPDMA_RX_PENDING) && (g_sUSBHCD[ulIndex].ulDMAPending &
- (DMA_PEND_RECEIVE_FLAG << ulIdx)))
- {
- //
- //Reset the pending flag
- //
- g_sUSBHCD[ulIndex].ulDMAPending &= ~(DMA_PEND_RECEIVE_FLAG << ulIdx);
- //
- //Read the completion queue
- //
- g_sUSBHCD[ulIndex].rxBuffer = (unsigned char *)dmaRxCompletion(ulIndex,
- INDEX_TO_USB_EP(ulIdx + 1));
- //
- //Send an ACk
- //
- USBHostEndpointDataAck(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(ulIdx + 1));
- //
- //Set the pipe status
- //
- g_sUSBHCD[ulIndex].USBINPipes[ulIdx].eState = PIPE_DATA_READY;
- //
- //Set the RX event
- //
- ulEvent = USB_EVENT_RX_AVAILABLE;
- //
- // Only call a handler if one is present.
- //
- if(g_sUSBHCD[ulIndex].USBINPipes[ulIdx].pfnCallback)
- {
- g_sUSBHCD[ulIndex].USBINPipes[ulIdx].pfnCallback(ulIndex,
- IN_PIPE_HANDLE(ulIndex, ulIdx), ulEvent);
- }
- }
- //
- //Check for any pending TX transaction
- //
- if((pendReg & CPDMA_TX_PENDING) && (g_sUSBHCD[ulIndex].ulDMAPending &
- (DMA_PEND_TRANSMIT_FLAG << ulIdx)))
- {
- //
- // Handle the case where the pipe is writing
- //
- if(g_sUSBHCD[ulIndex].USBOUTPipes[ulIdx].eState == PIPE_WRITING)
- {
- //
- //Reset the the pending flag
- //
- g_sUSBHCD[ulIndex].ulDMAPending &= ~(DMA_PEND_TRANSMIT_FLAG << ulIdx);
- //
- //Read the completion queue
- //
- dmaTxCompletion(ulIndex,
- INDEX_TO_USB_EP(ulIdx + 1));
- //
- // Data was transmitted successfully.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[ulIdx].eState = PIPE_DATA_SENT;
- //
- // Notify the pipe that its last transaction was completed.
- //
- ulEvent = USB_EVENT_TX_COMPLETE;
-
- }
- }
-
- #endif
- //
- // Check the next pipe, the first time through this will clear out
- // any interrupts dealing with endpoint zero since it was handled above.
- //
-
- epnStatus >>= 1;
- //
- // Check the status of the transmit(OUT) pipes.
- //
- if(epnStatus & 1)
- {
- //
- // Read the status of the endpoint connected to this pipe.
- //
- ulEPStatus = USBEndpointStatus(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(ulIdx + 1));
- if(ulEPStatus & USB_HOST_OUT_ERROR)
- {
- //
- // 3 failed attemps made to send packet. Device is non responsive.
- // Clear the error condition on the endpoint.
- //
- USBHostEndpointStatusClear(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(ulIdx + 1),
- USB_HOST_OUT_ERROR);
- //
- // Data OUT failed. Flush the FIFO.
- //
- USBFIFOFlush(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(ulIdx + 1),
- USB_EP_HOST_OUT);
- //
- // Save the Pipes error state.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[ulIdx].eState = PIPE_ERROR;
- //
- // Notify the pipe that had an error.
- //
- ulEvent = USB_EVENT_ERROR;
- }
- else if(ulEPStatus & USB_HOST_OUT_STALL)
- {
- //
- // Clear the stall condition on this endpoint pipe.
- //
- USBHostEndpointStatusClear(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(ulIdx + 1),
- USB_HOST_OUT_STALL);
- //
- // Save the STALLED state.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[ulIdx].eState = PIPE_STALLED;
- //
- // Notify the pipe that it was stalled.
- //
- ulEvent = USB_EVENT_STALL;
- }
- else
- {
- //
- // Data was transmitted successfully.
- //
- g_sUSBHCD[ulIndex].USBOUTPipes[ulIdx].eState = PIPE_DATA_SENT;
- //
- // Notify the pipe that its last transaction was completed.
- //
- ulEvent = USB_EVENT_TX_COMPLETE;
- }
- // Clear the stall condition on this endpoint pipe.
- //
- USBHostEndpointStatusClear(g_USBInstance[ulIndex].uiBaseAddr,
- INDEX_TO_USB_EP(ulIdx + 1),
- ulEPStatus);
- //
- // Only call a handler if one is present.
- //
- if(g_sUSBHCD[ulIndex].USBOUTPipes[ulIdx].pfnCallback)
- {
- g_sUSBHCD[ulIndex].USBOUTPipes[ulIdx].pfnCallback(ulIndex, OUT_PIPE_HANDLE(ulIndex, ulIdx),
- ulEvent);
- }
- }
- //
- // Check the status of the receive(IN) pipes.
- //
- if(epnStatus & 0x10000)
- {
- //
- // Clear the status flag for the IN Pipe.
- //
- epnStatus &= ~0x10000;
- //
- // Read the status of the endpoint connected to this pipe.
- //
- ulEPStatus = USBEndpointStatus(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(ulIdx + 1));
- if(ulEPStatus & USB_HOST_IN_ERROR)
- {
- //
- // 3 failed attemps made to receive packet. Device is non responsive.
- // Clear the error condition on the endpoint.
- //
- USBHostEndpointStatusClear(g_USBInstance[ulIndex].uiBaseAddr,
- INDEX_TO_USB_EP(ulIdx + 1),
- USB_HOST_IN_ERROR);
- //
- // Data IN failed. Flush the FIFO.
- //
- USBFIFOFlush(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(ulIdx + 1),
- USB_EP_HOST_IN);
- //
- // Save the Pipes error state.
- //
- g_sUSBHCD[ulIndex].USBINPipes[ulIdx].eState = PIPE_ERROR;
- //
- // Notify the pipe that it was stalled.
- //
- ulEvent = USB_EVENT_ERROR;
- }
- else if(ulEPStatus & USB_HOST_IN_STALL)
- {
- //
- // Clear the stall condition on this endpoint pipe.
- //
- USBHostEndpointStatusClear(g_USBInstance[ulIndex].uiBaseAddr ,
- INDEX_TO_USB_EP(ulIdx + 1),
- USB_HOST_IN_STALL);
- //
- // Save the STALLED state.
- //
- g_sUSBHCD[ulIndex].USBINPipes[ulIdx].eState = PIPE_STALLED;
- //
- // Notify the pipe that it was stalled.
- //
- ulEvent = USB_EVENT_STALL;
- }
- else
- {
- //
- // Data is available.
- //
- g_sUSBHCD[ulIndex].USBINPipes[ulIdx].eState = PIPE_DATA_READY;
- //
- // Notify the pipe that its last transaction was completed.
- //
- ulEvent = USB_EVENT_RX_AVAILABLE;
- }
- //
- // Only call a handler if one is present.
- //
- if(g_sUSBHCD[ulIndex].USBINPipes[ulIdx].pfnCallback)
- {
- g_sUSBHCD[ulIndex].USBINPipes[ulIdx].pfnCallback(ulIndex, IN_PIPE_HANDLE(ulIndex, ulIdx),
- ulEvent);
- }
- }
- }
- //
- // If there is an active driver and it has a call back then call it.
- //
- if((g_sUSBHCD[ulIndex].iUSBHActiveDriver >= 0) &&
- (g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex].iUSBHActiveDriver]->pfnIntHandler))
- {
- g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex].iUSBHActiveDriver]->
- pfnIntHandler(g_sUSBHCD[ulIndex].pvDriverInstance);
- }
- }
- //*****************************************************************************
- //
- //! The USB host mode interrupt handler for controller index 0.
- //!
- //! This the main USB interrupt handler entry point. This handler will branch
- //! the interrupt off to the appropriate handlers depending on the current
- //! status of the USB controller. This function must be placed in the
- //! interrupt table in order for the USB Library host stack to function.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USB0HostIntHandler(void)
- {
- unsigned int ulStatus = 0;
- unsigned int ulIndex = 0;
- #if defined (am335x_15x15) || defined(am335x) || defined(c6a811x)
- unsigned int epStatus = 0;
- ulStatus = HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_STATUS_1);
- epStatus = HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_STATUS_0);
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_STATUS_1) = ulStatus;
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_STATUS_0) = epStatus;
- #ifdef DMA_MODE
- HWREG(USBSS_BASE + USBSS_IRQ_STATUS) =
- HWREG(USBSS_BASE + USBSS_IRQ_STATUS);
- #endif
- USBHostIntHandlerInternal(ulIndex, ulStatus, &epStatus);
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_EOI) = 0;
- #ifdef DMA_MODE
- HWREG(USBSS_BASE + USBSS_IRQ_EOI) = 0;
- #endif
- #else
- //
- // Get the control interrupt status.
- //
-
- ulStatus = HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_INTR_SRC);
-
- // Clear the Interrupts
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_INTR_SRC_CLEAR) = ulStatus;
- #ifdef _TMS320C6X
- IntEventClear(g_USBInstance[ulIndex].uiInterruptNum);
- #else
- IntSystemStatusClear(g_USBInstance[ulIndex].uiInterruptNum);
- #endif
- //
- // Call the internal handler to process the interrupts.
- //
- USBHostIntHandlerInternal(ulIndex, ulStatus, NULL);
- // End of Interrupts
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_END_OF_INTR) = 0;
- #endif
- }
- //*****************************************************************************
- //
- //! The USB host mode interrupt handler for controller index 1.
- //!
- //! This the main USB interrupt handler entry point. This handler will branch
- //! the interrupt off to the appropriate handlers depending on the current
- //! status of the USB controller. This function must be placed in the
- //! interrupt table in order for the USB Library host stack to function.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USB1HostIntHandler(void)
- {
- unsigned int ulStatus = 0;
- unsigned int ulIndex = 1;
- #if defined (am335x_15x15) || defined(am335x) || defined(c6a811x)
- unsigned int epStatus = 0;
- ulStatus = HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_STATUS_1);
- epStatus = HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_STATUS_0);
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_STATUS_1) = ulStatus;
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_STATUS_0) = epStatus;
- #ifdef DMA_MODE
- HWREG(USBSS_BASE + USBSS_IRQ_STATUS) =
- HWREG(USBSS_BASE + USBSS_IRQ_STATUS);
- #endif
- USBHostIntHandlerInternal(ulIndex, ulStatus, &epStatus);
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_IRQ_EOI) = 0;
- #ifdef DMA_MODE
- HWREG(USBSS_BASE + USBSS_IRQ_EOI) = 0;
- #endif
- #else
- //
- // Get the control interrupt status.
- //
-
- ulStatus = HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_INTR_SRC);
-
- // Clear the Interrupts
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_INTR_SRC_CLEAR) = ulStatus;
- #ifdef _TMS320C6X
- IntEventClear(g_USBInstance[ulIndex].uiInterruptNum);
- #else
- IntSystemStatusClear(g_USBInstance[ulIndex].uiInterruptNum);
- #endif
- //
- // Call the internal handler to process the interrupts.
- //
- USBHostIntHandlerInternal(ulIndex, ulStatus, NULL);
- // End of Interrupts
- HWREG(g_USBInstance[ulIndex].uiSubBaseAddr + USB_0_END_OF_INTR) = 0;
- #endif
- }
- //*****************************************************************************
- //
- //! This function opens the class driver.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //! \param ulDeviceNum is the device number for the driver to load.
- //!
- //! This function opens the driver needed based on the class value found in
- //! the device's interface descriptor.
- //!
- //! \return This function returns -1 if no driver is found, or it returns the
- //! index of the driver found in the list of host class drivers.
- //
- //*****************************************************************************
- static int
- USBHCDOpenDriver(unsigned int ulIndex, unsigned int ulDeviceNum)
- {
- int iDriver;
- unsigned int ulClass;
- tInterfaceDescriptor *pInterface;
- ASSERT(ulIndex == 0);
- //
- // Get the interface descriptor.
- //
- pInterface = USBDescGetInterface(g_sUSBHCD[ulIndex].USBDevice[0].pConfigDescriptor,
- g_sUSBHCD[ulIndex].USBDevice[0].ulInterface,
- USB_DESC_ANY);
- //
- // Read the interface class.
- //
- ulClass = pInterface->bInterfaceClass;
- //
- // Search through the Host Class driver list for the devices class.
- //
- for(iDriver = 0; iDriver < g_sUSBHCD[ulIndex].ulNumClassDrivers; iDriver++)
- {
- //
- // If a driver was found call the open for this driver and save which
- // driver is in use.
- //
- if(g_sUSBHCD[ulIndex].pClassDrivers[iDriver]->ulInterfaceClass == ulClass)
- {
- //
- // Call the open function for the class driver.
- //
- g_sUSBHCD[ulIndex].pvDriverInstance = g_sUSBHCD[ulIndex].pClassDrivers[iDriver]->pfnOpen(
- &g_sUSBHCD[ulIndex].USBDevice[0], ulDeviceNum);
- //
- // If the driver was successfully loaded then break out of the
- // loop.
- //
- if(g_sUSBHCD[ulIndex].pvDriverInstance != 0)
- {
- break;
- }
- }
- }
- //
- // If no drivers were found then return -1 to indicate an invalid
- // driver instance.
- //
- if(iDriver == g_sUSBHCD[ulIndex].ulNumClassDrivers)
- {
- //
- // Send an unknown connection event.
- //
- SendUnknownConnect(ulIndex, ulClass, ulDeviceNum);
- //
- // Indicate that no driver was found.
- //
- iDriver = -1;
- }
- return(iDriver);
- }
- //*****************************************************************************
- //
- // This function will send an event to a registered event driver.
- //
- // \param ulIndex is one of the USB_EVENT_* values.
- //
- // This function is only used internally to the USB library and will check
- // if an event driver is registered and send on the event.
- //
- // Note: This function should not be called outside of the USB library.
- //
- // \return None.
- //
- //*****************************************************************************
- void
- InternalUSBHCDSendEvent(unsigned int ulIndex, unsigned int ulEvent)
- {
- //
- // Make sure that an event driver has been registered.
- //
- if((g_sUSBHCD[ulIndex].iEventDriver != -1) &&
- (g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex].iEventDriver]->pfnIntHandler))
- {
- //
- // Send an event to the application.
- //
- g_sUSBHCD[ulIndex].EventInfo.ulEvent = ulEvent;
- g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex].iEventDriver]->pfnIntHandler(
- &g_sUSBHCD[ulIndex].EventInfo);
- }
- }
- //*****************************************************************************
- //
- // This function handles the necessary clean up for device disconnect.
- //
- // \param ulIndex is the device number for the device that was disconnected.
- //
- // This function handles all of the necessary clean up after a device
- // disconnect has been detected by the stack. This includes calling back the
- // appropriate driver if necessary.
- //
- // \return None.
- //
- //*****************************************************************************
- static void
- USBHCDDeviceDisconnected(unsigned int ulIndex, unsigned int ulInstance)
- {
- ASSERT(ulIndex == 0);
- if(g_sUSBHCD[ulIndex].USBDevice[0].pConfigDescriptor)
- {
- //
- // Invalidate the configuration descriptor.
- //
- g_sUSBHCD[ulIndex].USBDevice[0].pConfigDescriptor = 0;
- }
- //
- // Reset the max packet size so that this will be re-read from new devices.
- //
- g_sUSBHCD[ulIndex].USBDevice[0].DeviceDescriptor.bMaxPacketSize0 = 0;
- //
- // No longer have a device descriptor.
- //
- g_sUSBHCD[ulIndex].USBDevice[0].DeviceDescriptor.bLength = 0;
- //
- // No longer addressed.
- //
- g_sUSBHCD[ulIndex].USBDevice[0].ulAddress = 0;
- //
- // If this was an active driver then close it out.
- //
- if(g_sUSBHCD[ulIndex].iUSBHActiveDriver >= 0)
- {
- //
- // Call the driver Close entry point.
- //
- g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex].iUSBHActiveDriver]->
- pfnClose((void *)ulInstance);
- //
- // No active driver now present.
- //
- g_sUSBHCD[ulIndex].iUSBHActiveDriver = -1;
- g_sUSBHCD[ulIndex].pvDriverInstance = 0;
- }
- else
- {
- if((g_sUSBHCD[ulIndex].iEventDriver != -1) &&
- (g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex].iEventDriver]->pfnIntHandler))
- {
- //
- // Send the generic disconnect event.
- //
- g_sUSBHCD[ulIndex].EventInfo.ulEvent = USB_EVENT_DISCONNECTED;
- g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex].iEventDriver]->pfnIntHandler(
- &g_sUSBHCD[ulIndex].EventInfo);
- //
- // Reset the class and the instance.
- //
- g_sUSBHCD[ulIndex].ulClass = USB_CLASS_EVENTS;
- g_sUSBHCD[ulIndex].EventInfo.ulInstance = 0;
- }
- }
-
- }
- //*****************************************************************************
- //
- //! This function is the main routine for the Host Controller Driver.
- //!
- //! This function is the main routine for the host controller driver, and must
- //! be called periodically by the main application outside of a callback
- //! context. This allows for a simple cooperative system to access the the
- //! host controller driver interface without the need for an RTOS. All time
- //! critical operations are handled in interrupt context but all blocking
- //! operations are run from the this function to allow them to block and wait
- //! for completion without holding off other interrupts.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- USBHCDMain(unsigned int ulIndex, unsigned int ulInstance)
- {
- unsigned int ulIntState;
- tUSBHDeviceState eOldState;
- //
- // Save the old state to detect changes properly.
- //
- eOldState = g_sUSBHCD[ulIndex].eDeviceState[0];
- //
- // Perform this fixup with interrupts disabled to prevent race
- // conditions related to g_sUSBHCD[ulIndex].ulUSBHIntEvents.
- //
- #ifdef _TMS320C6X
- ulIntState = IntGlobalDisable();
- #else
- ulIntState = IntDisable();
- #endif
- //
- // Fix up the state if any important interrupt events occurred.
- //
- if(g_sUSBHCD[ulIndex].ulUSBHIntEvents)
- {
- if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & INT_EVENT_POWER_FAULT)
- {
- //
- // A power fault has occurred so notify the application.
- //
- if((g_sUSBHCD[ulIndex].iEventDriver != -1) &&
- (g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex]
- .iEventDriver]->pfnIntHandler))
- {
- //
- // Send the generic power fault event.
- //
- g_sUSBHCD[ulIndex].EventInfo.ulEvent = USB_EVENT_POWER_FAULT;
- g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex]
- .iEventDriver]->pfnIntHandler(&g_sUSBHCD[ulIndex].EventInfo);
- }
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_POWER_FAULT;
- }
- else if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & INT_EVENT_VBUS_ERR)
- {
- //
- // A VBUS error has occurred. This event trumps connect and
- // disconnect since it will cause a controller reset.
- //
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_VBUS_ERROR;
- }
- else if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & INT_EVENT_BABBLE_FAULT)
- {
- //
- // A VBUS error has occurred. This event trumps connect and
- // disconnect since it will cause a controller reset.
- //
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_BABBLE_ERROR;
- }
- else
- {
- //
- // Has a device connected?
- //
- if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & INT_EVENT_CONNECT)
- {
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_DEV_RESET;
- }
- else
- {
- //
- // Has a device disconnected?
- //
- if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & INT_EVENT_DISCONNECT)
- {
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_DEV_DISCONNECTED;
- }
- }
- }
- //
- // Clear the flags.
- //
- g_sUSBHCD[ulIndex].ulUSBHIntEvents = 0;
- //
- // Turn interrupts back on if they were on when we were called.
- //
- }
- #ifdef _TMS320C6X
- IntGlobalRestore(ulIntState);
- #else
- IntEnable(ulIntState);
- #endif
- switch(g_sUSBHCD[ulIndex].eDeviceState[0])
- {
- //
- // There was a power fault condition so shut down and wait for the
- // application to re-initialized the system.
- //
- case HCD_POWER_FAULT:
- {
- break;
- }
- //
- // There was a VBUS error so handle it.
- //
- case HCD_VBUS_ERROR:
- {
- //
- // Disable USB interrupts.
- //
- #ifdef _TMS320C6X
- /* No DSP API to disable USB0 event */
- #else
- IntSystemDisable(g_USBInstance[ulIndex].uiInterruptNum);
- #endif
-
- //
- // If there was a device in any state of connection then indicate
- // that it has been disconnected.
- //
- if((eOldState != HCD_IDLE) && (eOldState != HCD_POWER_FAULT))
- {
- //
- // Handle device disconnect.
- //
- USBHCDDeviceDisconnected(ulIndex, ulInstance);
- }
- //
- // Reset the controller.
- //
- //SysCtlPeripheralReset(SYSCTL_PERIPH_USB0);
- USBReset(g_USBInstance[ulIndex].uiSubBaseAddr);
- //
- // Wait for 100ms before trying to re-power the device.
- //
- delay(100);
- //
- // Re-initialize the HCD.
- //
- USBHCDInitInternal(ulIndex, g_sUSBHCD[ulIndex].pvPool,
- g_sUSBHCD[ulIndex].ulPoolSize);
- #ifdef _TMS320C6X
- /* No DSP API to disable USB0 event */
- #else
- IntSystemEnable(g_USBInstance[ulIndex].uiInterruptNum);
- #endif
- break;
- }
- //
- // Trigger a reset to the connected device.
- //
- case HCD_DEV_RESET:
- {
- //
- // Trigger a Reset.
- //
- USBHCDReset(ulIndex);
- //
- // The state moves to connected but not configured.
- //
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_DEV_CONNECTED;
- break;
- }
- //
- // Device connection has been established now start enumerating
- // the device.
- //
- case HCD_DEV_CONNECTED:
- {
- //
- // First get the speed of the device
- //
- g_sUSBHCD[ulIndex].USBDevice[0].ulDeviceSpeed =
- USBHCDGetSpeed(ulIndex);
-
- //
- // First check if we have read the device descriptor at all
- // before proceeding.
- //
- if(g_sUSBHCD[ulIndex].USBDevice[0].DeviceDescriptor.bLength == 0)
- {
- //
- // Initialize a request for the device descriptor.
- //
- if(USBHCDGetDeviceDescriptor(ulIndex, &g_sUSBHCD[ulIndex]
- .USBDevice[0]) == 0)
- {
- //
- // If the device descriptor cannot be read then the device
- // will be treated as unknown.
- //
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_DEV_ERROR;
- //
- // Send an unknown connection event.
- //
- SendUnknownConnect(ulIndex, 0, ulInstance);
- }
- }
- //
- // If we have the device descriptor then move on to setting
- // the address of the device.
- //
- else if(g_sUSBHCD[ulIndex].USBDevice[0].ulAddress == 0)
- {
- //
- // Send the set address command.
- //
- USBHCDSetAddress(ulIndex, 1);
- //
- // Save the address.
- //
- g_sUSBHCD[ulIndex].USBDevice[0].ulAddress = 1;
- //
- // Move on to the addressed state.
- //
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_DEV_ADDRESSED;
- }
- break;
- }
- case HCD_DEV_ADDRESSED:
- {
- //
- // First check if we have read the configuration descriptor.
- //
- if (g_sUSBHCD[ulIndex].USBDevice[0].pConfigDescriptor == 0)
- {
- //
- // Initialize a request for the device descriptor.
- //
- if(USBHCDGetConfigDescriptor(ulIndex, &g_sUSBHCD[ulIndex]
- .USBDevice[0]) == 0)
- {
- //
- // If the device descriptor cannot be read then the device
- // will be treated as unknown.
- //
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_DEV_ERROR;
- //
- // Send an unknown connection event.
- //
- SendUnknownConnect(ulIndex, 0, ulInstance);
- }
- }
- //
- // Now have addressed and received the device configuration,
- // so get ready to set the device configuration.
- //
- else
- {
- //
- // Use the first configuration to set the device
- // configuration.
- //
- USBHCDSetConfig(ulIndex, (unsigned int)&g_sUSBHCD[ulIndex]
- .USBDevice[0], 1);
- //
- // Move on to the configured state.
- //
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_DEV_CONFIGURED;
- //
- // Open the driver for device 0.
- //
- g_sUSBHCD[ulIndex].iUSBHActiveDriver =
- USBHCDOpenDriver(ulIndex, ulInstance);
- }
- break;
- }
- //
- // The device was making a request and is now complete.
- //
- case HCD_DEV_REQUEST:
- {
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_DEV_CONNECTED;
- break;
- }
- //
- // The strings are currently not accessed.
- //
- case HCD_DEV_GETSTRINGS:
- {
- break;
- }
- //
- // Basically Idle at this point.
- //
- case HCD_DEV_DISCONNECTED:
- {
- //
- // Handle device disconnect.
- //
- USBHCDDeviceDisconnected(ulIndex, ulInstance);
- //
- // Return to the Idle state.
- //
- g_sUSBHCD[ulIndex].eDeviceState[0] = HCD_IDLE;
- break;
- }
- //
- // Connection and enumeration is complete so allow this function
- // to exit.
- //
- case HCD_DEV_CONFIGURED:
- {
- break;
- }
- case HCD_BABBLE_ERROR:
- {
- USBHCDTerm(ulIndex);
- USBHCDDeviceDisconnected(ulIndex, ulInstance);
- UsbPhyOff(ulIndex);
- USBReset(g_USBInstance[ulIndex].uiSubBaseAddr);
- g_sUSBHCD[ulIndex].EventInfo.ulEvent = USB_EVENT_BABBLE_ERROR;
- g_sUSBHCD[ulIndex].EventInfo.ulInstance = ulIndex;
- g_sUSBHCD[ulIndex].pClassDrivers[g_sUSBHCD[ulIndex].iEventDriver]->pfnIntHandler(
- &g_sUSBHCD[ulIndex].EventInfo);
- break;
- }
-
- //
- // Poorly behaving device are in limbo in this state until removed.
- //
- case HCD_DEV_ERROR:
- {
- //
- // If there was a device in any state of connection then indicate
- // that it has been disconnected.
- //
- if((eOldState != HCD_IDLE) && (eOldState != HCD_POWER_FAULT))
- {
- //
- // Handle device disconnect.
- //
- USBHCDDeviceDisconnected(ulIndex, ulInstance);
- }
- //
- // Reset the controller.
- //
- USBReset(g_USBInstance[ulIndex].uiSubBaseAddr);
- //
- // Wait for 100ms before trying to re-power the device.
- //
- delay(100);
- //
- // Re-initialize the HCD.
- //
- USBHCDInitInternal(ulIndex, g_sUSBHCD[ulIndex].pvPool,
- g_sUSBHCD[ulIndex].ulPoolSize);
- break;
- }
- default:
- {
- break;
- }
- }
- g_sUSBHCD[ulIndex].ulConnectRetry = g_ulConnectRetry[ulIndex];
- }
- //*****************************************************************************
- //
- //! This function completes a control transaction to a device.
- //!
- //! \param ulIndex is the controller index to use for this transfer.
- //! \param pSetupPacket is the setup request to be sent.
- //! \param ulDevAddress is the address of the device for this request.
- //! \param pData is the data to send for OUT requests or the receive buffer
- //! for IN requests.
- //! \param ulSize is the size of the buffer in pData.
- //! \param ulMaxPacketSize is the maximum packet size for the device for this
- //! request.
- //!
- //! This function handles the state changes necessary to send a control
- //! transaction to a device. This function should not be called from within
- //! an interrupt callback as it is a blocking function.
- //!
- //! \return The number of bytes of data that were sent or received as a result
- //! of this request.
- //
- //*****************************************************************************
- unsigned int
- USBHCDControlTransfer(unsigned int ulIndex, tUSBRequest *pSetupPacket,
- unsigned int ulDevAddress, unsigned char *pData,
- unsigned int ulSize, unsigned int ulMaxPacketSize)
- {
- unsigned int ulRemaining;
- unsigned int ulDataSize;
- unsigned int ulTimer = 0;
- unsigned int retStatus = 1;
- ASSERT(g_sUSBHEP0State[ulIndex].eState == EP0_STATE_IDLE);
- ASSERT(ulIndex == 0);
- //
- // Initialize the state of the data for this request.
- //
- g_sUSBHEP0State[ulIndex].pData = pData;
- g_sUSBHEP0State[ulIndex].ulBytesRemaining = ulSize;
- g_sUSBHEP0State[ulIndex].ulDataSize = ulSize;
- //
- // Set the maximum packet size.
- //
- g_sUSBHEP0State[ulIndex].ulMaxPacketSize = ulMaxPacketSize;
- //
- // Save the current address.
- //
- g_sUSBHEP0State[ulIndex].ulDevAddress = ulDevAddress;
- //
- // Set the address the host will used to communicate with the device.
- //
- USBHostAddrSet(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0,
- g_sUSBHEP0State[ulIndex].ulDevAddress, USB_EP_HOST_OUT);
- //
- // Put the data in the correct FIFO.
- //
- USBEndpointDataPut(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0,
- (unsigned char *)pSetupPacket, sizeof(tUSBRequest));
- //
- // If this is an IN request, change to that state.
- //
- if(pSetupPacket->bmRequestType & USB_RTYPE_DIR_IN)
- {
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_SETUP_IN;
- }
- else
- {
- //
- // If there is no data then this is not an OUT request.
- //
- if(ulSize != 0)
- {
- //
- // Since there is data, this is an OUT request.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_SETUP_OUT;
- }
- else
- {
- //
- // Otherwise this request has no data and just a status phase.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_STATUS_IN;
- }
- }
- //
- // Send the Setup packet.
- //
- USBEndpointDataSend(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0,
- USB_TRANS_SETUP);
- if(USB_TIMEOUT_DISABLE!=g_sUSBHCD[ulIndex].USBHTimeOut.Value.slEP0)
- {
- ulTimer = g_sUSBHCD[ulIndex].USBHTimeOut.Value.slEP0;
- }
- StartTimer(ulTimer);
- //
- // Block until endpoint 0 returns to the IDLE state.
- //
- while((g_sUSBHEP0State[ulIndex].eState != EP0_STATE_IDLE)&&(!IsTimerElapsed()))
- {
- if(g_sUSBHEP0State[ulIndex].eState == EP0_STATE_ERROR)
- {
- USBHCDTxAbort(ulIndex, 0);
- USBHCDRxAbort(ulIndex, 0);
- retStatus = 0;
- break;
- }
- //
- // If we aborted the transfer due to an error, tell the caller
- // that no bytes were transferred.
- //
- if(g_sUSBHCD[ulIndex].ulUSBHIntEvents & (INT_EVENT_VBUS_ERR
- | INT_EVENT_DISCONNECT|INT_EVENT_BABBLE_FAULT))
- {
- USBHCDTxAbort(ulIndex, 0);
- USBHCDRxAbort(ulIndex, 0);
- retStatus = 0;
- break;
- }
- }
- StopTimer();
- //
- // Calculate and return the number of bytes that were sent or received.
- // The extra copy into local variables is required to prevent some
- // compilers from warning about undefined order of volatile access.
- //
- if(g_sUSBHEP0State[ulIndex].eState == EP0_STATE_IDLE)
- {
- ulDataSize = g_sUSBHEP0State[ulIndex].ulDataSize;
- ulRemaining = g_sUSBHEP0State[ulIndex].ulBytesRemaining;
- retStatus = (ulDataSize - ulRemaining);
- }
- else
- {
- retStatus = 0;
- g_sUSBHCD[ulIndex].USBHTimeOut.Status.slEP0 = 1;
- }
- return retStatus;
- }
- //*****************************************************************************
- //
- // This is the endpoint 0 interrupt handler.
- //
- // \return None.
- //
- //*****************************************************************************
- static void
- USBHCDEnumHandler(unsigned int ulIndex)
- {
- unsigned int ulEPStatus;
- unsigned int ulDataSize;
- //
- // Get the end point 0 status.
- //
- ulEPStatus = USBEndpointStatus(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0);
- //
- // If there was an error then go to the error state.
- //
- if(ulEPStatus == USB_HOST_EP0_ERROR)
- {
- //
- // Clear this status indicating that the status packet was
- // received.
- //
- USBHostEndpointStatusClear(g_USBInstance[ulIndex].uiBaseAddr,
- USB_EP_0, USB_HOST_EP0_ERROR);
- USBFIFOFlush(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0, 0);
- //
- // Just go back to the idle state.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_ERROR;
- return;
- }
- switch(g_sUSBHEP0State[ulIndex].eState)
- {
- //
- // Handle the status state, this is a transitory state from
- // USB_STATE_TX or USB_STATE_RX back to USB_STATE_IDLE.
- //
- case EP0_STATE_STATUS:
- {
- //
- // Handle the case of a received status packet.
- //
- if(ulEPStatus & (USB_HOST_EP0_RXPKTRDY | USB_HOST_EP0_STATUS))
- {
- //
- // Clear this status indicating that the status packet was
- // received.
- //
- USBHostEndpointStatusClear(g_USBInstance[ulIndex].uiBaseAddr,
- USB_EP_0, (USB_HOST_EP0_RXPKTRDY |
- USB_HOST_EP0_STATUS));
- }
- //
- // Just go back to the idle state.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_IDLE;
- break;
- }
- //
- // This state triggers a STATUS IN request from the device.
- //
- case EP0_STATE_STATUS_IN:
- {
- //
- // Generate an IN request from the device.
- //
- USBHostRequestStatus(g_USBInstance[ulIndex].uiBaseAddr );
- //
- // Change to the status phase and wait for the response.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_STATUS;
- break;
- }
- //
- // In the IDLE state the code is waiting to receive data from the host.
- //
- case EP0_STATE_IDLE:
- {
- break;
- }
- //
- // Data is still being sent to the host so handle this in the
- // EP0StateTx() function.
- //
- case EP0_STATE_SETUP_OUT:
- {
- //
- // Send remaining data if necessary.
- //
- USBHCDEP0StateTx(ulIndex);
- break;
- }
- //
- // Handle the receive state for commands that are receiving data on
- // endpoint 0.
- //
- case EP0_STATE_SETUP_IN:
- {
- //
- // Generate a new IN request to the device.
- //
- USBHostRequestIN(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0);
- //
- // Proceed to the RX state to receive the requested data.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_RX;
- break;
- }
- //
- // The endponit remains in this state until all requested data has
- // been received.
- //
- case EP0_STATE_RX:
- {
- //
- // There was a stall on endpoint 0 so go back to the idle state
- // as this command has been terminated.
- //
- if(ulEPStatus & USB_HOST_EP0_RX_STALL)
- {
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_IDLE;
- //
- // Clear the stalled state on endpoint 0.
- //
- USBHostEndpointStatusClear(g_USBInstance[ulIndex].uiBaseAddr,
- USB_EP_0, ulEPStatus);
- break;
- }
- //
- // Set the number of bytes to get out of this next packet.
- //
- if(g_sUSBHEP0State[ulIndex].ulBytesRemaining > MAX_PACKET_SIZE_EP0)
- {
- //
- // Don't send more than EP0_MAX_PACKET_SIZE bytes.
- //
- ulDataSize = MAX_PACKET_SIZE_EP0;
- }
- else
- {
- //
- // There was space so send the remaining bytes.
- //
- ulDataSize = g_sUSBHEP0State[ulIndex].ulBytesRemaining;
- }
- if(ulDataSize != 0)
- {
- //
- // Get the data from the USB controller end point 0.
- //
- USBEndpointDataGet(g_USBInstance[ulIndex].uiBaseAddr ,
- USB_EP_0, g_sUSBHEP0State[ulIndex].pData,
- &ulDataSize);
- }
- //
- // Advance the pointer.
- //
- g_sUSBHEP0State[ulIndex].pData += ulDataSize;
- //
- // Decrement the number of bytes that are being waited on.
- //
- g_sUSBHEP0State[ulIndex].ulBytesRemaining -= ulDataSize;
- //
- // Need to ack the data on end point 0 in this case
- // without setting data end.
- //
- USBDevEndpointDataAck(g_USBInstance[ulIndex].uiBaseAddr,
- USB_EP_0, false);
- //
- // If there was not more than the maximum packet size bytes of data
- // the this was a short packet and indicates that this transfer is
- // complete. If there were exactly g_sUSBHEP0State[ulIndex].ulMaxPacketSize
- // remaining then there still needs to be null packet sent before
- // this transfer is complete.
- //
- if((ulDataSize < g_sUSBHEP0State[ulIndex].ulMaxPacketSize) ||
- (g_sUSBHEP0State[ulIndex].ulBytesRemaining == 0))
- {
- //
- // Return to the idle state.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_STATUS;
- //
- // No more data.
- //
- g_sUSBHEP0State[ulIndex].pData = 0;
- //
- // Send a null packet to acknowledge that all data was received.
- //
- USBEndpointDataSend(g_USBInstance[ulIndex].uiBaseAddr,
- USB_EP_0, USB_TRANS_STATUS);
- }
- else
- {
- //
- // Request more data.
- //
- USBHostRequestIN(g_USBInstance[ulIndex].uiBaseAddr, USB_EP_0);
- }
- break;
- }
- //
- // The device stalled endpoint zero so check if the stall needs to be
- // cleared once it has been successfully sent.
- //
- case EP0_STATE_STALL:
- {
- //
- // Reset the global end point 0 state to IDLE.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_IDLE;
- break;
- }
- //
- // Halt on an unknown state, but only in DEBUG builds.
- //
- default:
- {
- ASSERT(0);
- break;
- }
- }
- }
- //*****************************************************************************
- //
- // This internal function handles sending data on endpoint 0.
- //
- // \return None.
- //
- //*****************************************************************************
- static void
- USBHCDEP0StateTx(unsigned int ulIndex)
- {
- unsigned int ulNumBytes;
- unsigned char *pData;
-
- //
- // In the TX state on endpoint 0.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_SETUP_OUT;
- //
- // Set the number of bytes to send this iteration.
- //
- ulNumBytes = g_sUSBHEP0State[ulIndex].ulBytesRemaining;
- //
- // Limit individual transfers to 64 bytes.
- //
- if(ulNumBytes > 64)
- {
- ulNumBytes = 64;
- }
- //
- // Save the pointer so that it can be passed to the USBEndpointDataPut()
- // function.
- //
- pData = (unsigned char *)g_sUSBHEP0State[ulIndex].pData;
- //
- // Advance the data pointer and counter to the next data to be sent.
- //
- g_sUSBHEP0State[ulIndex].ulBytesRemaining -= ulNumBytes;
- g_sUSBHEP0State[ulIndex].pData += ulNumBytes;
- //
- // Put the data in the correct FIFO.
- //
- USBEndpointDataPut(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0,
- pData, ulNumBytes);
- //
- // If this is exactly 64 then don't set the last packet yet.
- //
- if(ulNumBytes == 64)
- {
- //
- // There is more data to send or exactly 64 bytes were sent, this
- // means that there is either more data coming or a null packet needs
- // to be sent to complete the transaction.
- //
- USBEndpointDataSend(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0,
- USB_TRANS_OUT);
- }
- else
- {
- //
- // Send the last bit of data.
- //
- USBEndpointDataSend(g_USBInstance[ulIndex].uiBaseAddr , USB_EP_0,
- USB_TRANS_OUT);
- //
- // Now go to the status state and wait for the transmit to complete.
- //
- g_sUSBHEP0State[ulIndex].eState = EP0_STATE_STATUS_IN;
- }
- }
- //*****************************************************************************
- //
- // This internal function handles Aborts Tx by flusing the EP FIFOs and DMA(when enabled).
- //
- // \return None.
- //
- //*****************************************************************************
- static unsigned int
- USBHCDTxAbort(unsigned int ulIndex, unsigned int endPoint)
- {
- USBFIFOFlush(g_USBInstance[ulIndex].uiBaseAddr,
- endPoint, USB_EP_HOST_OUT);
- USBFIFOFlush(g_USBInstance[ulIndex].uiBaseAddr,
- endPoint, USB_EP_HOST_OUT);
- return 1;
- }
- //*****************************************************************************
- //
- // This internal function handles Aborts Rx by flusing the EP FIFOs and DMA(when enabled).
- //
- // \return None.
- //
- //*****************************************************************************
- static unsigned int
- USBHCDRxAbort(unsigned int ulIndex, unsigned int endPoint)
- {
- USBHostAutoReqClear(g_USBInstance[ulIndex].uiBaseAddr,
- endPoint);
- USBHostRequestINClear(g_USBInstance[ulIndex].uiBaseAddr,
- endPoint);
- USBFIFOFlush(g_USBInstance[ulIndex].uiBaseAddr,
- endPoint, USB_EP_HOST_IN);
- USBFIFOFlush(g_USBInstance[ulIndex].uiBaseAddr,
- endPoint, USB_EP_HOST_IN);
- USBHostAutoReqSet(g_USBInstance[ulIndex].uiBaseAddr,
- endPoint);
- return 1;
- }
- //*****************************************************************************
- //
- // This internal function trys to re-establish connenction with the device.
- //
- // \return None.
- //
- //*****************************************************************************
- static unsigned int
- USBHCDRetryConnect(unsigned int ulIndex)
- {
- //
- // Trigger a Reset.
- //
- USBHCDReset(ulIndex);
- if(USBHCDGetDeviceDescriptor(ulIndex, &g_sUSBHCD[ulIndex].USBDevice[0]) == 0)
- {
- return 0;
- }
- return 1;
- }
- //*****************************************************************************
- //
- // This function sets the timeout value applicable communication types.
- // This API should be called after 'USBHCDInit' call.
- //
- // \return None.
- //
- //*****************************************************************************
- void
- USBHCDTimeOutHook(unsigned int ulIndex, tUSBHTimeOut **USBHTimeOut)
- {
- (*USBHTimeOut) = &(g_sUSBHCD[ulIndex].USBHTimeOut);
- }
- //*****************************************************************************
- //
- //! This function returns the speed of the device connected on the bus.
- //!
- //! \param ulIndex specifies which USB controller to use.
- //!
- //! This function calls the HCD lower layer function to return the speed
- //! of the connected device. High speed devices get detected as high speed
- //! only after the 2nd reset and chirp sequence. Till that time they report FS
- //!
- //! \return device speed as unsigned integer.
- //
- //*****************************************************************************
- unsigned int
- USBHCDGetSpeed(unsigned int ulIndex)
- {
- ASSERT(ulIndex == 0);
-
- //
- // Call the lower Abstraction layer speed get routine
- //
- return( USBHostSpeedGet( g_USBInstance[ulIndex].uiBaseAddr ) );
- }
- //*****************************************************************************
- //
- // Close the Doxygen group.
- //! @}
- //
- //*****************************************************************************
|