1 /****************************************************************************
5 | | | | (o o)W () || ||
6 |__|_|_"| | / |Mw || ||//
9 _____ ___ ______ _____ __ _____ ___ __ __/~~__ ~~\ _||
10 |"(" \()/\" \ ()/"_ )|"(___) ) )|"(" \ ()/\" \(__)/" ) /" ) " \ /_)O
11 | ) )/" \ \ (_/"\__/ | )_ ( ( | )_ ) /" \ \ / /|/ / �\ \/ ,|O
12 | (___/( (_\__) _\ \_ | (__) ) )| (__) |( (_\__)/ /"/ / |\ '_|O
13 | | _ \ / / /" \_/ ) | ")__ ( ( | )" ) \ / // /|/ / . .|/\__/ ||
14 |__| (_) \/__/ (______/ |_(___) )_)|_(___/ . \/__/(__/ (__/ .:.:| ||
16 |" __ \ Poseidon -- The divine USB stack for Amiga computers
18 | __ ( Designed and written by
19 |"(__) ) Chris Hodges <chrisly@platon42.de>
20 |_____/ Copyright �2002-2009 Chris Hodges. All rights reserved.
22 ****************************************************************************/
25 *----------------------------------------------------------------------------
26 * Poseidon main library
27 *----------------------------------------------------------------------------
28 * By Chris Hodges <chrisly@platon42.de>
33 #include "poseidon.library.h"
37 #include <proto/exec.h>
38 #include <proto/dos.h>
39 #include <proto/utility.h>
40 #include <proto/usbclass.h>
41 #include <proto/timer.h>
46 #include <aros/bootloader.h>
47 #include <proto/bootloader.h>
50 #define NewList(list) NEWLIST(list)
52 #define min(x,y) (((x) < (y)) ? (x) : (y))
53 #define max(x,y) (((x) > (y)) ? (x) : (y))
55 extern const struct PsdWStringMap usbclasscodestr
[];
56 extern const struct PsdULStringMap usbcomboclasscodestr
[];
57 extern const struct PsdULStringMap usbdesctypestr
[];
58 extern const struct PsdWStringMap usbhwioerrstr
[];
59 extern const struct PsdUWStringMap usblangids
[];
60 extern const struct PsdUWStringMap usbvendorids
[];
62 #if !defined(__AROS__)
63 extern struct ExecBase
*SysBase
;
67 const char GM_UNIQUENAME(libname
)[] = MOD_NAME_STRING
;
69 #define UsbClsBase puc->puc_ClassBase
70 #define DOSBase ps->ps_DosBase
71 #define TimerBase ps->ps_TimerIOReq.tr_node.io_Device
74 static int GM_UNIQUENAME(libInit
)(LIBBASETYPEPTR ps
)
76 KPRINTF(10, ("libInit ps: 0x%p SysBase: 0x%p\n",
79 ps
->ps_StackInit
= FALSE
;
80 ps
->ps_UtilityBase
= (struct UtilityBase
*) OpenLibrary("utility.library", 39);
82 #define UtilityBase ps->ps_UtilityBase
87 APTR BootLoaderBase
= OpenResource("bootloader.resource");
91 struct List
*args
= GetBootInfo(BL_Args
);
97 for (node
= args
->lh_Head
; node
->ln_Succ
; node
= node
->ln_Succ
)
99 if (stricmp(node
->ln_Name
, "usbdebug") == 0)
101 ps
->ps_Flags
= PSF_KLOG
;
109 NewList(&ps
->ps_Hardware
);
110 NewList(&ps
->ps_Classes
);
111 NewList(&ps
->ps_ErrorMsgs
);
112 NewList(&ps
->ps_EventHooks
);
113 memset(&ps
->ps_EventReplyPort
, 0, sizeof(ps
->ps_EventReplyPort
));
114 ps
->ps_EventReplyPort
.mp_Flags
= PA_IGNORE
;
115 NewList(&ps
->ps_EventReplyPort
.mp_MsgList
);
116 NewList(&ps
->ps_ConfigRoot
);
117 NewList(&ps
->ps_AlienConfigs
);
119 NewList(&ps
->ps_DeadlockDebug
);
121 InitSemaphore(&ps
->ps_ReentrantLock
);
122 InitSemaphore(&ps
->ps_PoPoLock
);
124 if((ps
->ps_MemPool
= CreatePool(MEMF_CLEAR
|MEMF_PUBLIC
|MEMF_SEM_PROTECTED
, 16384, 1024)))
126 if((ps
->ps_SemaMemPool
= CreatePool(MEMF_CLEAR
|MEMF_PUBLIC
, 16*sizeof(struct PsdReadLock
), sizeof(struct PsdBorrowLock
))))
128 pInitSem(ps
, &ps
->ps_Lock
, "PBase");
129 pInitSem(ps
, &ps
->ps_ConfigLock
, "ConfigLock");
130 KPRINTF(20, ("libInit: Done!\n"));
133 DeletePool(ps
->ps_MemPool
);
135 KPRINTF(20, ("libInit: CreatePool() failed!\n"));
137 CloseLibrary((struct Library
*) UtilityBase
);
139 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
145 static int GM_UNIQUENAME(libOpen
)(LIBBASETYPEPTR ps
)
147 struct PsdIFFContext
*pic
;
149 KPRINTF(10, ("libOpen ps: 0x%p\n", ps
));
150 ObtainSemaphore(&ps
->ps_ReentrantLock
);
151 if(!ps
->ps_StackInit
)
153 ps
->ps_TimerIOReq
.tr_node
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
154 ps
->ps_TimerIOReq
.tr_node
.io_Message
.mn_ReplyPort
= NULL
;
155 ps
->ps_TimerIOReq
.tr_node
.io_Message
.mn_Length
= sizeof(struct timerequest
);
156 if(!OpenDevice("timer.device", UNIT_MICROHZ
, (struct IORequest
*) &ps
->ps_TimerIOReq
, 0))
158 ps
->ps_TimerIOReq
.tr_node
.io_Message
.mn_Node
.ln_Name
= "Poseidon";
159 ps
->ps_TimerIOReq
.tr_node
.io_Command
= TR_ADDREQUEST
;
161 ps
->ps_ReleaseVersion
= RELEASEVERSION
;
162 ps
->ps_OSVersion
= MAKE_ID('A','R','O','S');
164 pic
= pAllocForm(ps
, NULL
, IFFFORM_PSDCFG
);
165 if((ps
->ps_GlobalCfg
= psdAllocVec(sizeof(struct PsdGlobalCfg
))))
167 ps
->ps_GlobalCfg
->pgc_ChunkID
= AROS_LONG2BE(IFFCHNK_GLOBALCFG
);
168 ps
->ps_GlobalCfg
->pgc_Length
= AROS_LONG2BE(sizeof(struct PsdGlobalCfg
)-8);
169 ps
->ps_GlobalCfg
->pgc_LogInfo
= TRUE
;
170 ps
->ps_GlobalCfg
->pgc_LogWarning
= TRUE
;
171 ps
->ps_GlobalCfg
->pgc_LogError
= TRUE
;
172 ps
->ps_GlobalCfg
->pgc_LogFailure
= TRUE
;
173 ps
->ps_GlobalCfg
->pgc_BootDelay
= 2;
174 ps
->ps_GlobalCfg
->pgc_SubTaskPri
= 5;
175 ps
->ps_GlobalCfg
->pgc_PopupDeviceNew
= PGCP_ISNEW
;
176 ps
->ps_GlobalCfg
->pgc_PopupDeviceGone
= TRUE
;
177 ps
->ps_GlobalCfg
->pgc_PopupDeviceDeath
= TRUE
;
178 ps
->ps_GlobalCfg
->pgc_PopupCloseDelay
= 5;
179 ps
->ps_GlobalCfg
->pgc_PopupActivateWin
= FALSE
;
180 ps
->ps_GlobalCfg
->pgc_PopupWinToFront
= TRUE
;
181 ps
->ps_GlobalCfg
->pgc_AutoDisableLP
= FALSE
;
182 ps
->ps_GlobalCfg
->pgc_AutoDisableDead
= FALSE
;
183 ps
->ps_GlobalCfg
->pgc_AutoRestartDead
= TRUE
;
184 ps
->ps_GlobalCfg
->pgc_PowerSaving
= FALSE
;
185 ps
->ps_GlobalCfg
->pgc_ForceSuspend
= FALSE
;
186 ps
->ps_GlobalCfg
->pgc_SuspendTimeout
= 30;
188 ps
->ps_GlobalCfg
->pgc_PrefsVersion
= 0; // is updated on writing
189 ps
->ps_ConfigRead
= FALSE
;
192 pic
= pAllocForm(ps
, pic
, IFFFORM_STACKCFG
);
195 pAddCfgChunk(ps
, pic
, ps
->ps_GlobalCfg
);
198 ps
->ps_PoPo
.po_InsertSndFile
= psdCopyStr("SYS:Prefs/Presets/Poseidon/Connect.iff");
199 ps
->ps_PoPo
.po_RemoveSndFile
= psdCopyStr("SYS:Prefs/Presets/Poseidon/Disconnect.iff");
203 tmpstr
= psdCopyStr((STRPTR
) VERSION_STRING
);
206 tmpstr
[strlen(tmpstr
)-2] = 0;
207 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Welcome to %s (%p)!", tmpstr
, ps
->ps_ReleaseVersion
);
210 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Welcome to %s", VERSION_STRING
);
214 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "This is the AROS port.");
216 KPRINTF(10, ("libOpen: Ok\n"));
217 ps
->ps_StackInit
= TRUE
;
218 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
219 pStartEventHandler(ps
);
223 KPRINTF(20, ("libOpen: No memory for cfg!\n"));
226 KPRINTF(20, ("libOpen: OpenDevice(timer.device) failed!\n"));
228 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
231 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
232 KPRINTF(5, ("libOpen: openCnt = %ld\n", ps
->ps_Library
.lib_OpenCnt
));
236 int GM_UNIQUENAME(libExpunge
)(LIBBASETYPEPTR ps
)
238 struct PsdHardware
*phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
239 struct PsdUsbClass
*puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
240 struct PsdErrorMsg
*pem
= (struct PsdErrorMsg
*) ps
->ps_ErrorMsgs
.lh_Head
;
241 struct PsdIFFContext
*pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
242 KPRINTF(10, ("libExpunge ps: 0x%p\n", ps
));
243 while(phw
->phw_Node
.ln_Succ
)
246 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
248 while(puc
->puc_Node
.ln_Succ
)
251 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
253 while(pem
->pem_Node
.ln_Succ
)
256 pem
= (struct PsdErrorMsg
*) ps
->ps_ErrorMsgs
.lh_Head
;
259 while(pic
->pic_Node
.ln_Succ
)
262 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
265 if(ps
->ps_PoPo
.po_Task
)
267 ps
->ps_PoPo
.po_ReadySignal
= SIGB_SINGLE
;
268 ps
->ps_PoPo
.po_ReadySigTask
= FindTask(NULL
);
269 Signal(ps
->ps_PoPo
.po_Task
, SIGBREAKF_CTRL_C
);
270 while(ps
->ps_PoPo
.po_Task
)
272 Wait(1L<<ps
->ps_PoPo
.po_ReadySignal
);
274 ps
->ps_PoPo
.po_ReadySigTask
= NULL
;
275 //FreeSignal(ps->ps_PoPo.po_ReadySignal);
277 if(ps
->ps_EventHandler
.ph_Task
)
279 ps
->ps_EventHandler
.ph_ReadySignal
= SIGB_SINGLE
;
280 ps
->ps_EventHandler
.ph_ReadySigTask
= FindTask(NULL
);
281 Signal(ps
->ps_EventHandler
.ph_Task
, SIGBREAKF_CTRL_C
);
282 while(ps
->ps_EventHandler
.ph_Task
)
284 Wait(1L<<ps
->ps_EventHandler
.ph_ReadySignal
);
286 ps
->ps_EventHandler
.ph_ReadySigTask
= NULL
;
287 //FreeSignal(ps->ps_EventHandler.ph_ReadySignal);
289 psdFreeVec(ps
->ps_PoPo
.po_InsertSndFile
);
290 psdFreeVec(ps
->ps_PoPo
.po_RemoveSndFile
);
291 pGarbageCollectEvents(ps
);
293 CloseDevice((struct IORequest
*) &ps
->ps_TimerIOReq
);
294 DeletePool(ps
->ps_SemaMemPool
);
295 DeletePool(ps
->ps_MemPool
);
297 KPRINTF(1, ("libExpunge: closelibrary utilitybase 0x%p\n",
299 CloseLibrary((struct Library
*) UtilityBase
);
301 CloseLibrary(DOSBase
);
303 KPRINTF(1, ("libExpunge: removing library node 0x%p\n",
304 &ps
->ps_Library
.lib_Node
));
305 Remove(&ps
->ps_Library
.lib_Node
);
311 ADD2INITLIB(GM_UNIQUENAME(libInit
), 0)
312 ADD2OPENLIB(GM_UNIQUENAME(libOpen
), 0)
313 ADD2EXPUNGELIB(GM_UNIQUENAME(libExpunge
), 0);
316 * ***********************************************************************
317 * * Library functions *
318 * ***********************************************************************
321 static const ULONG
*PsdPTArray
[PGA_LAST
+1];
325 /* /// "psdAllocVec()" */
326 AROS_LH1(APTR
, psdAllocVec
,
327 AROS_LHA(ULONG
, size
, D0
),
328 LIBBASETYPEPTR
, ps
, 5, psd
)
332 KPRINTF(1, ("psdAllocVec(%ld)\n", size
));
334 if((pmem
= AllocPooled(ps
->ps_MemPool
, size
+ (1*sizeof(ULONG
)))))
337 if((pmem
= AllocPooled(ps
->ps_MemPool
, size
+ (1*sizeof(ULONG
)) + 1024)))
339 ULONG upos
= size
+ (1*sizeof(ULONG
));
341 UBYTE
*dbptr
= (UBYTE
*) pmem
;
349 ps
->ps_MemAllocated
+= size
;
357 /* /// "psdFreeVec()" */
358 AROS_LH1(void, psdFreeVec
,
359 AROS_LHA(APTR
, pmem
, A1
),
360 LIBBASETYPEPTR
, ps
, 6, psd
)
365 KPRINTF(1, ("psdFreeVec(%p)\n", pmem
));
368 size
= ((ULONG
*) pmem
)[-1];
369 ps
->ps_MemAllocated
-= size
;
372 FreePooled(ps
->ps_MemPool
, &((ULONG
*) pmem
)[-1], size
+ (1*sizeof(ULONG
)) + 1024);
374 FreePooled(ps
->ps_MemPool
, &((ULONG
*) pmem
)[-1], size
+ (1*sizeof(ULONG
)));
383 /* /// "pDebugSemaInfo()" */
384 void pDebugSemaInfo(LIBBASETYPEPTR ps
, struct PsdSemaInfo
*psi
)
386 struct PsdReadLock
*prl
;
387 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
388 "Semaphore %p %s (Excl/SharedLockCount %ld/%ld) (Owner: %s):",
390 psi
->psi_LockSem
->pls_Node
.ln_Name
,
391 psi
->psi_LockSem
->pls_ExclLockCount
,
392 psi
->psi_LockSem
->pls_SharedLockCount
,
393 psi
->psi_LockSem
->pls_Owner
? (const char *)psi
->psi_LockSem
->pls_Owner
->tc_Node
.ln_Name
: "None");
395 prl
= (struct PsdReadLock
*) psi
->psi_LockSem
->pls_WaitQueue
.lh_Head
;
396 while(prl
->prl_Node
.ln_Succ
)
398 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
399 " Waiting Task: %p (%s) %s",
400 prl
->prl_Task
, prl
->prl_Task
->tc_Node
.ln_Name
,
401 prl
->prl_IsExcl
? "Excl" : "Shared");
402 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
404 prl
= (struct PsdReadLock
*) psi
->psi_LockSem
->pls_ReadLocks
.lh_Head
;
405 while(prl
->prl_Node
.ln_Succ
)
407 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
408 " Readlock Task: %p (%s), Count %ld",
409 prl
->prl_Task
, prl
->prl_Task
->tc_Node
.ln_Name
,
411 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
416 /* /// "pInitSem()" */
417 void pInitSem(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
, STRPTR name
)
419 struct PsdSemaInfo
*psi
= NULL
;
420 NewList(&pls
->pls_WaitQueue
);
421 NewList(&pls
->pls_ReadLocks
);
422 pls
->pls_Node
.ln_Name
= name
;
423 // struct should be nulled anyway
424 pls
->pls_Owner
= NULL
;
425 pls
->pls_ExclLockCount
= 0;
426 pls
->pls_SharedLockCount
= 0;
427 pls
->pls_Dead
= FALSE
;
430 psi
= (struct PsdSemaInfo
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdSemaInfo
));
436 psi
->psi_LockSem
= pls
;
437 AddTail(&ps
->ps_DeadlockDebug
, &psi
->psi_Node
);
442 /* /// "pDeleteSem()" */
443 void pDeleteSem(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
)
445 struct PsdSemaInfo
*psi
;
447 pls
->pls_Dead
= TRUE
;
448 psi
= (struct PsdSemaInfo
*) ps
->ps_DeadlockDebug
.lh_Head
;
449 while(psi
->psi_Node
.ln_Succ
)
451 if(psi
->psi_LockSem
== pls
)
453 if(pls
->pls_SharedLockCount
+ pls
->pls_ExclLockCount
)
455 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Semaphore still locked when attempting to delete it!\n");
456 pDebugSemaInfo(ps
, psi
);
458 Remove(&psi
->psi_Node
);
459 FreePooled(ps
->ps_SemaMemPool
, psi
, sizeof(struct PsdSemaInfo
));
463 psi
= (struct PsdSemaInfo
*) psi
->psi_Node
.ln_Succ
;
469 /* /// "pLockSemExcl()" */
470 void pLockSemExcl(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
)
472 struct PsdReadLock waitprl
;
473 struct Task
*thistask
= FindTask(NULL
);
475 waitprl
.prl_Task
= thistask
;
476 waitprl
.prl_IsExcl
= TRUE
;
481 // it's already mine!!
482 if(thistask
== pls
->pls_Owner
)
486 if(!pls
->pls_ExclLockCount
)
488 // easy case: no shared locks, no exclusive locker
489 if(!pls
->pls_SharedLockCount
)
493 // sole readlock promotion case
494 if((pls
->pls_SharedLockCount
== 1) && ((struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
)->prl_Task
== thistask
)
496 KPRINTF(1, ("Promoting read lock (%p) to write lock!\n", thistask
));
501 // okay, bad luck, we've got to wait somehow
502 AddHead(&pls
->pls_WaitQueue
, &waitprl
.prl_Node
);
503 thistask
->tc_SigRecvd
&= ~SIGF_SINGLE
;
507 Remove(&waitprl
.prl_Node
);
509 pls
->pls_Owner
= thistask
;
510 pls
->pls_ExclLockCount
++;
515 /* /// "pLockSemShared()" */
516 void pLockSemShared(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
)
518 struct PsdReadLock
*prl
;
519 struct Task
*thistask
= FindTask(NULL
);
522 // is this already locked exclusively by me?
523 if(thistask
== pls
->pls_Owner
)
525 // yes? then just increase exclusive lock count
526 pls
->pls_ExclLockCount
++;
531 // find existing readlock
532 prl
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
533 while(prl
->prl_Node
.ln_Succ
)
535 if(prl
->prl_Task
== thistask
)
537 KPRINTF(1, ("Increasing ReadLock (%p) count to %ld\n", thistask
, prl
->prl_Count
));
542 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
545 // this is a new readlock, generate context
546 if(!(prl
= (struct PsdReadLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdReadLock
))))
548 KPRINTF(20, ("No mem for shared lock! context (%p) on %p\n", thistask
, pls
));
549 // try exclusive lock as fallback (needs no memory)
551 pLockSemExcl(ps
, pls
);
555 KPRINTF(1, ("New ReadLockShared context (%p) on %p\n", thistask
, pls
));
556 prl
->prl_Task
= thistask
;
558 prl
->prl_IsExcl
= FALSE
;
560 // if it's exclusively locked, wait for this lock to vanish
561 while(pls
->pls_Owner
)
563 AddTail(&pls
->pls_WaitQueue
, &prl
->prl_Node
);
564 thistask
->tc_SigRecvd
&= ~SIGF_SINGLE
;
568 Remove(&prl
->prl_Node
);
573 // we got promoted by BorrowLocks during the process! So we don't need the shared stuff anymore
574 FreePooled(ps
->ps_SemaMemPool
, prl
, sizeof(struct PsdReadLock
));
575 pls
->pls_Owner
= thistask
;
576 pls
->pls_ExclLockCount
++;
579 AddHead(&pls
->pls_ReadLocks
, &prl
->prl_Node
);
581 pls
->pls_SharedLockCount
++;
588 /* /// "pUnlockSem()" */
589 void pUnlockSem(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
)
591 struct PsdReadLock
*prl
;
592 struct Task
*thistask
= FindTask(NULL
);
598 // exclusively locked, this means unlocking task must be owner
599 if(pls
->pls_Owner
!= thistask
)
602 psdDebugSemaphores();
603 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
604 "Attempt to unlock exclusive semaphore %p not owned by task %s!",
605 pls
, thistask
->tc_Node
.ln_Name
);
609 if(--pls
->pls_ExclLockCount
)
615 pls
->pls_Owner
= NULL
;
616 // otherwise drop through and notify
618 if(!pls
->pls_SharedLockCount
)
621 psdDebugSemaphores();
622 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
623 "Attempt to unlock (free) semaphore %p once too often by task %s!",
624 pls
, thistask
->tc_Node
.ln_Name
);
628 prl
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
629 while(prl
->prl_Node
.ln_Succ
)
631 if(prl
->prl_Task
== thistask
)
635 // can't be the last lock, so just reduce count and return
639 // remove read lock, it's no longer needed
640 KPRINTF(1, ("Removing read lock context (%p) on %p!\n", thistask
, pls
));
641 Remove(&prl
->prl_Node
);
642 FreePooled(ps
->ps_SemaMemPool
, prl
, sizeof(struct PsdReadLock
));
644 // losing a designated lock
645 pls
->pls_SharedLockCount
--;
648 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
653 psdDebugSemaphores();
654 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
655 "Attempt to unlock (shared) semaphore %p once too often by task %s!",
656 pls
, thistask
->tc_Node
.ln_Name
);
660 // we need to notify anyway, because the waiter could already have a shared lock
661 // on the same semaphore, and if we only notified on LockCount reaching zero,
662 // the locker would wait forever.
665 // notify waiting tasks
666 prl
= (struct PsdReadLock
*) pls
->pls_WaitQueue
.lh_Head
;
667 while(prl
->prl_Node
.ln_Succ
)
669 Signal(prl
->prl_Task
, SIGF_SINGLE
);
670 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
676 /* /// "psdDebugSemaphores()" */
677 AROS_LH0(void, psdDebugSemaphores
,
678 LIBBASETYPEPTR
, ps
, 81, psd
)
681 struct Task
*thistask
= FindTask(NULL
);
682 struct PsdSemaInfo
*psi
;
684 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
685 "Debug Semaphores (%p)", thistask
);
688 // search for context
689 psi
= (struct PsdSemaInfo
*) ps
->ps_DeadlockDebug
.lh_Head
;
690 while(psi
->psi_Node
.ln_Succ
)
692 pDebugSemaInfo(ps
, psi
);
693 psi
= (struct PsdSemaInfo
*) psi
->psi_Node
.ln_Succ
;
700 /* /// "psdLockReadPBase()" */
701 AROS_LH0(void, psdLockReadPBase
,
702 LIBBASETYPEPTR
, ps
, 8, psd
)
705 KPRINTF(2, ("psdLockReadPBase(%p)\n", FindTask(NULL
)));
706 pLockSemShared(ps
, &ps
->ps_Lock
);
711 /* /// "psdLockWritePBase()" */
712 AROS_LH0(void, psdLockWritePBase
,
713 LIBBASETYPEPTR
, ps
, 7, psd
)
716 KPRINTF(2, ("psdLockWritePBase(%p)\n", FindTask(NULL
)));
717 pLockSemExcl(ps
, &ps
->ps_Lock
);
722 /* /// "psdUnlockPBase()" */
723 AROS_LH0(void, psdUnlockPBase
,
724 LIBBASETYPEPTR
, ps
, 9, psd
)
727 KPRINTF(2, ("psdUnlockPBase(%p)\n", FindTask(NULL
)));
728 pUnlockSem(ps
, &ps
->ps_Lock
);
733 /* /// "psdBorrowLocksWait()" */
734 AROS_LH2(ULONG
, psdBorrowLocksWait
,
735 AROS_LHA(struct Task
*, task
, A1
),
736 AROS_LHA(ULONG
, signals
, D0
),
737 LIBBASETYPEPTR
, ps
, 97, psd
)
740 struct Task
*thistask
= FindTask(NULL
);
743 struct PsdSemaInfo
*psi
;
744 struct PsdLockSem
*pls
;
745 struct PsdReadLock
*prl
;
746 struct PsdBorrowLock
*pbl
;
748 struct List reclaims
;
751 XPRINTF(10, ("Borrowing locks from %p (%s) to %p (%s)!\n",
752 thistask
, thistask
->tc_Node
.ln_Name
, task
, task
->tc_Node
.ln_Name
));
755 psi
= (struct PsdSemaInfo
*) ps
->ps_DeadlockDebug
.lh_Head
;
756 while(psi
->psi_Node
.ln_Succ
)
758 pls
= psi
->psi_LockSem
;
759 if(pls
->pls_Owner
== thistask
)
763 if(pls
->pls_SharedLockCount
)
765 struct PsdReadLock
*prl
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
768 if(prl
->prl_Task
== thistask
)
773 } while((prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
)->prl_Node
.ln_Succ
);
775 psi
= (struct PsdSemaInfo
*) psi
->psi_Node
.ln_Succ
;
780 XPRINTF(10, ("Nothing to borrow!\n"));
781 return(Wait(signals
));
786 XPRINTF(10, ("Borrowing %ld locks\n", cnt
));
788 psi
= (struct PsdSemaInfo
*) ps
->ps_DeadlockDebug
.lh_Head
;
789 while(psi
->psi_Node
.ln_Succ
)
792 pls
= psi
->psi_LockSem
;
793 if(pls
->pls_Owner
== thistask
)
795 // check if the target task is already waiting for that lock
796 // in this case, we simply remove our exclusive lock and let
797 // the other task catch it
798 prl
= (struct PsdReadLock
*) pls
->pls_WaitQueue
.lh_Head
;
799 while(prl
->prl_Node
.ln_Succ
)
801 if(prl
->prl_Task
== task
)
805 // if we hand over the excl lock, we have to make sure that the exclusiveness is kept
806 // and no other thread may catch it while it is shared.
807 // hence we will need set this lock exclusive aswell
808 // this no optimal solution, but it guarantees the same
809 // behaviour with pending lock and no pending lock
810 prl
->prl_IsExcl
= TRUE
;
811 XPRINTF(10, ("Promo waiting lock to excl\n"));
813 // move shared lock to top of the list
814 Remove(&prl
->prl_Node
);
815 AddHead(&pls
->pls_WaitQueue
, &prl
->prl_Node
);
816 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
818 pbl
->pbl_LockSem
= pls
;
819 pbl
->pbl_ExclLockCount
= pls
->pls_ExclLockCount
;
820 AddTail(&reclaims
, &pbl
->pbl_Node
);
822 // unlock exclusive lock
823 pls
->pls_ExclLockCount
= 0;
824 pls
->pls_Owner
= NULL
;
825 Signal(task
, SIGF_SINGLE
);
826 XPRINTF(10, ("Waiting lock %p transfer\n", pls
));
831 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
835 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
837 pbl
->pbl_LockSem
= pls
;
838 pbl
->pbl_ExclLockCount
= pls
->pls_ExclLockCount
;
839 AddTail(&borrows
, &pbl
->pbl_Node
);
840 pls
->pls_Owner
= task
;
841 XPRINTF(10, ("Lock %p transfer\n", pls
));
845 if(pls
->pls_SharedLockCount
)
847 prl
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
850 if(prl
->prl_Task
== thistask
)
852 // check if target task is waiting for this task
853 struct PsdReadLock
*prl2
= (struct PsdReadLock
*) pls
->pls_WaitQueue
.lh_Head
;
854 while(prl2
->prl_Node
.ln_Succ
)
856 if(prl2
->prl_Task
== task
)
858 // move lock to top of the list
859 Remove(&prl2
->prl_Node
);
860 AddHead(&pls
->pls_WaitQueue
, &prl2
->prl_Node
);
861 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
863 pbl
->pbl_LockSem
= pls
;
864 pbl
->pbl_ReadLock
= prl
;
865 pbl
->pbl_Count
= prl
->prl_Count
;
866 AddHead(&reclaims
, &pbl
->pbl_Node
);
868 // unlock shared lock
869 Remove(&prl
->prl_Node
);
870 FreePooled(ps
->ps_SemaMemPool
, prl
, sizeof(struct PsdReadLock
));
871 pls
->pls_SharedLockCount
--;
872 Signal(task
, SIGF_SINGLE
);
875 XPRINTF(10, ("Waiting shared lock %p transfer\n", pls
));
878 prl2
= (struct PsdReadLock
*) prl2
->prl_Node
.ln_Succ
;
882 // check if target task already has a shared lock on this
883 prl2
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
886 if(prl2
->prl_Task
== task
)
888 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
890 // we redirect to this other lock
891 pbl
->pbl_LockSem
= pls
;
892 pbl
->pbl_ReadLock
= prl2
;
893 pbl
->pbl_Count
= prl
->prl_Count
; // save the old lock count
894 AddTail(&borrows
, &pbl
->pbl_Node
);
896 // unlock shared lock
897 Remove(&prl
->prl_Node
);
898 FreePooled(ps
->ps_SemaMemPool
, prl
, sizeof(struct PsdReadLock
));
899 pls
->pls_SharedLockCount
--;
900 // just increase lockcount, so a split occurs automatically
901 prl2
->prl_Count
+= pbl
->pbl_Count
;
903 XPRINTF(10, ("Already locked %p transfer\n", pls
));
907 } while((prl2
= (struct PsdReadLock
*) prl2
->prl_Node
.ln_Succ
)->prl_Node
.ln_Succ
);
911 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
913 pbl
->pbl_LockSem
= pls
;
914 pbl
->pbl_ReadLock
= prl
;
915 pbl
->pbl_Count
= prl
->prl_Count
;
916 AddTail(&borrows
, &pbl
->pbl_Node
);
917 prl
->prl_Task
= task
;
918 XPRINTF(10, ("Std lock %p transfer\n", pls
));
923 } while((prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
)->prl_Node
.ln_Succ
);
925 psi
= (struct PsdSemaInfo
*) psi
->psi_Node
.ln_Succ
;
928 sigmask
= Wait(signals
);
930 // try to get moved locks back first
931 pbl
= (struct PsdBorrowLock
*) borrows
.lh_Head
;
932 while(pbl
->pbl_Node
.ln_Succ
)
934 Remove(&pbl
->pbl_Node
);
935 pls
= pbl
->pbl_LockSem
;
936 if(pbl
->pbl_ExclLockCount
)
938 if(pbl
->pbl_ExclLockCount
== pls
->pls_ExclLockCount
)
940 // all fine, other task didn't use the locks or returned them already
941 pls
->pls_Owner
= thistask
;
942 FreePooled(ps
->ps_SemaMemPool
, pbl
, sizeof(struct PsdBorrowLock
));
944 // okay, bad thing, release lock and try to obtain it again -- eventually the other task should free the lock again
945 pls
->pls_ExclLockCount
-= pbl
->pbl_ExclLockCount
;
946 AddTail(&reclaims
, &pbl
->pbl_Node
);
949 if(pls
->pls_Owner
== task
)
951 // oh, damn. The other task converted our shared lock into an exclusive lock --
952 // we cannot claim this back right now. This gets tricky now.
953 if(pbl
->pbl_Count
== pbl
->pbl_ReadLock
->prl_Count
)
955 // luckily, the count didn't change, so we just release the shared lock and requeue us into the reclaim list
956 Remove(&pbl
->pbl_ReadLock
->prl_Node
);
957 FreePooled(ps
->ps_SemaMemPool
, pbl
->pbl_ReadLock
, sizeof(struct PsdReadLock
));
958 pbl
->pbl_ReadLock
= NULL
;
959 pls
->pls_SharedLockCount
--; // should turn to 0
961 // can it get worse? obviously, the alien task also has added some read locks
962 // this means we need to split up!
963 // therefore we leave a few lock counts and requeue
964 pbl
->pbl_ReadLock
->prl_Count
-= pbl
->pbl_Count
;
965 pbl
->pbl_ReadLock
= NULL
;
967 AddHead(&reclaims
, &pbl
->pbl_Node
);
969 if(pbl
->pbl_Count
== pbl
->pbl_ReadLock
->prl_Count
)
971 // the count didn't change, just so just change owner
972 pbl
->pbl_ReadLock
->prl_Task
= thistask
;
973 FreePooled(ps
->ps_SemaMemPool
, pbl
, sizeof(struct PsdBorrowLock
));
975 // the alien task still has some read locks
976 // this means we need to split up!
977 // therefore we leave a few lock counts and requeue
978 pbl
->pbl_ReadLock
->prl_Count
-= pbl
->pbl_Count
;
979 pbl
->pbl_ReadLock
= NULL
;
980 AddHead(&reclaims
, &pbl
->pbl_Node
);
984 pbl
= (struct PsdBorrowLock
*) borrows
.lh_Head
;
987 // try to reclaim released locks
988 pbl
= (struct PsdBorrowLock
*) reclaims
.lh_Head
;
989 while(pbl
->pbl_Node
.ln_Succ
)
991 Remove(&pbl
->pbl_Node
);
992 pls
= pbl
->pbl_LockSem
;
993 while(pbl
->pbl_Count
)
995 pLockSemShared(ps
, pls
);
998 while(pbl
->pbl_ExclLockCount
)
1000 pLockSemExcl(ps
, pls
);
1001 --pbl
->pbl_ExclLockCount
;
1003 FreePooled(ps
->ps_SemaMemPool
, pbl
, sizeof(struct PsdBorrowLock
));
1004 pbl
= (struct PsdBorrowLock
*) reclaims
.lh_Head
;
1013 /* *** Support *** */
1015 /* /// "psdCopyStr()" */
1016 AROS_LH1(STRPTR
, psdCopyStr
,
1017 AROS_LHA(CONST_STRPTR
, name
, A0
),
1018 LIBBASETYPEPTR
, ps
, 10, psd
)
1021 STRPTR rs
= psdAllocVec((ULONG
) strlen(name
)+1);
1022 KPRINTF(1, ("psdCopyStr(%s)\n", name
));
1032 /* /// "psdSafeRawDoFmtA()" */
1033 AROS_LH4(void, psdSafeRawDoFmtA
,
1034 AROS_LHA(STRPTR
, buf
, A0
),
1035 AROS_LHA(ULONG
, len
, D0
),
1036 AROS_LHA(CONST_STRPTR
, fmtstr
, A1
),
1037 AROS_LHA(RAWARG
, fmtdata
, A2
),
1038 LIBBASETYPEPTR
, ps
, 42, psd
)
1041 struct PsdRawDoFmt rdf
;
1047 RawDoFmt(fmtstr
, fmtdata
, (void (*)()) pPutChar
, &rdf
);
1054 /* /// "pPutChar()" */
1055 AROS_UFH2(void, pPutChar
,
1056 AROS_UFHA(char, ch
, D0
),
1057 AROS_UFHA(struct PsdRawDoFmt
*, rdf
, A3
))
1063 *rdf
->rdf_Buf
++ = ch
;
1069 /* /// "psdCopyStrFmtA()" */
1070 AROS_LH2(STRPTR
, psdCopyStrFmtA
,
1071 AROS_LHA(CONST_STRPTR
, fmtstr
, A0
),
1072 AROS_LHA(RAWARG
, fmtdata
, A1
),
1073 LIBBASETYPEPTR
, ps
, 68, psd
)
1079 RawDoFmt(fmtstr
, fmtdata
, (void (*)()) pRawFmtLength
, &len
);
1080 buf
= psdAllocVec(len
+1);
1083 psdSafeRawDoFmtA(buf
, len
+1, fmtstr
, fmtdata
);
1090 /* /// "pRawFmtLength()" */
1091 AROS_UFH2(void, pRawFmtLength
,
1092 AROS_UFHA(char, ch
, D0
),
1093 AROS_UFHA(ULONG
*, len
, A3
))
1101 /* /// "psdDelayMS()" */
1102 AROS_LH1(void, psdDelayMS
,
1103 AROS_LHA(ULONG
, milli
, D0
),
1104 LIBBASETYPEPTR
, ps
, 11, psd
)
1108 struct timerequest tr
;
1110 /* Clear memory for messageport */
1111 memset(&mp
, 0, sizeof(mp
));
1113 KPRINTF(1, ("psdDelayMS(%ld)\n", milli
));
1114 mp
.mp_Flags
= PA_SIGNAL
;
1115 mp
.mp_SigBit
= SIGB_SINGLE
;
1116 mp
.mp_SigTask
= FindTask(NULL
);
1117 NewList(&mp
.mp_MsgList
);
1118 CopyMem(&ps
->ps_TimerIOReq
, &tr
, sizeof(tr
));
1119 tr
.tr_node
.io_Message
.mn_ReplyPort
= &mp
;
1120 tr
.tr_time
.tv_secs
= 0;
1121 tr
.tr_time
.tv_micro
= milli
* 1000;
1122 DoIO((struct IORequest
*) &tr
);
1127 /* /// "psdGetAttrsA()" */
1128 AROS_LH3(LONG
, psdGetAttrsA
,
1129 AROS_LHA(ULONG
, type
, D0
),
1130 AROS_LHA(APTR
, psdstruct
, A0
),
1131 AROS_LHA(struct TagItem
*, tags
, A1
),
1132 LIBBASETYPEPTR
, ps
, 22, psd
)
1137 ULONG
*packtab
= NULL
;
1139 KPRINTF(1, ("psdGetAttrsA(%ld, %p, %p)\n", type
, psdstruct
, tags
));
1141 if(type
<= PGA_LAST
)
1143 packtab
= (ULONG
*) PsdPTArray
[type
];
1150 if((ti
= FindTagItem(PA_HardwareList
, tags
)))
1152 *((struct List
**) ti
->ti_Data
) = &ps
->ps_Hardware
;
1155 if((ti
= FindTagItem(PA_ClassList
, tags
)))
1157 *((struct List
**) ti
->ti_Data
) = &ps
->ps_Classes
;
1160 if((ti
= FindTagItem(PA_ErrorMsgList
, tags
)))
1162 *((struct List
**) ti
->ti_Data
) = &ps
->ps_ErrorMsgs
;
1168 if((ti
= FindTagItem(HA_DeviceList
, tags
)))
1170 *((struct List
**) ti
->ti_Data
) = &(((struct PsdHardware
*) psdstruct
)->phw_Devices
);
1176 if((ti
= FindTagItem(DA_ConfigList
, tags
)))
1178 *((struct List
**) ti
->ti_Data
) = &(((struct PsdDevice
*) psdstruct
)->pd_Configs
);
1181 if((ti
= FindTagItem(DA_DescriptorList
, tags
)))
1183 *((struct List
**) ti
->ti_Data
) = &(((struct PsdDevice
*) psdstruct
)->pd_Descriptors
);
1189 if((ti
= FindTagItem(CA_InterfaceList
, tags
)))
1191 *((struct List
**) ti
->ti_Data
) = &(((struct PsdConfig
*) psdstruct
)->pc_Interfaces
);
1197 if((ti
= FindTagItem(IFA_EndpointList
, tags
)))
1199 *((struct List
**) ti
->ti_Data
) = &(((struct PsdInterface
*) psdstruct
)->pif_EPs
);
1202 if((ti
= FindTagItem(IFA_AlternateIfList
, tags
)))
1204 *((struct List
**) ti
->ti_Data
) = &(((struct PsdInterface
*) psdstruct
)->pif_AlterIfs
);
1210 if((ti
= FindTagItem(EMA_DateStamp
, tags
)))
1212 *((struct DateStamp
**) ti
->ti_Data
) = &(((struct PsdErrorMsg
*) psdstruct
)->pem_DateStamp
);
1218 if((ti
= FindTagItem(PPA_IORequest
, tags
)))
1220 *((struct IOUsbHWReq
**) ti
->ti_Data
) = &(((struct PsdPipe
*) psdstruct
)->pp_IOReq
);
1226 if((ti
= FindTagItem(GCA_InsertionSound
, tags
)))
1229 *((STRPTR
*) ti
->ti_Data
) = ps
->ps_PoPo
.po_InsertSndFile
;
1231 if((ti
= FindTagItem(GCA_RemovalSound
, tags
)))
1234 *((STRPTR
*) ti
->ti_Data
) = ps
->ps_PoPo
.po_RemoveSndFile
;
1240 return((LONG
) (UnpackStructureTags(psdstruct
, (ULONG
*) packtab
, tags
)+count
));
1248 /* /// "psdSetAttrsA()" */
1249 AROS_LH3(LONG
, psdSetAttrsA
,
1250 AROS_LHA(ULONG
, type
, D0
),
1251 AROS_LHA(APTR
, psdstruct
, A0
),
1252 AROS_LHA(struct TagItem
*, tags
, A1
),
1253 LIBBASETYPEPTR
, ps
, 23, psd
)
1258 ULONG
*packtab
= NULL
;
1259 BOOL savepopocfg
= FALSE
;
1260 BOOL checkcfgupdate
= FALSE
;
1261 BOOL powercalc
= FALSE
;
1264 KPRINTF(1, ("psdSetAttrsA(%ld, %p, %p)\n", type
, psdstruct
, tags
));
1266 if(type
<= PGA_LAST
)
1268 packtab
= (ULONG
*) PsdPTArray
[type
];
1274 if(FindTagItem(DA_InhibitPopup
, tags
) || FindTagItem(DA_InhibitClassBind
, tags
))
1278 if(FindTagItem(DA_OverridePowerInfo
, tags
))
1290 if((ti
= FindTagItem(GCA_InsertionSound
, tags
)))
1293 if(strcmp(ps
->ps_PoPo
.po_InsertSndFile
, (STRPTR
) ti
->ti_Data
))
1295 psdFreeVec(ps
->ps_PoPo
.po_InsertSndFile
);
1296 ps
->ps_PoPo
.po_InsertSndFile
= psdCopyStr((STRPTR
) ti
->ti_Data
);
1299 if((ti
= FindTagItem(GCA_RemovalSound
, tags
)))
1302 if(strcmp(ps
->ps_PoPo
.po_RemoveSndFile
, (STRPTR
) ti
->ti_Data
))
1304 psdFreeVec(ps
->ps_PoPo
.po_RemoveSndFile
);
1305 ps
->ps_PoPo
.po_RemoveSndFile
= psdCopyStr((STRPTR
) ti
->ti_Data
);
1308 checkcfgupdate
= TRUE
;
1311 case PGA_PIPESTREAM
:
1313 struct PsdPipeStream
*pps
= (struct PsdPipeStream
*) psdstruct
;
1315 ULONG oldbufsize
= pps
->pps_BufferSize
;
1316 ULONG oldnumpipes
= pps
->pps_NumPipes
;
1319 KPRINTF(1, ("SetAttrs PIPESTREAM\n"));
1320 ObtainSemaphore(&pps
->pps_AccessLock
);
1321 if((ti
= FindTagItem(PSA_MessagePort
, tags
)))
1324 if((pps
->pps_Flags
& PSFF_OWNMSGPORT
) && pps
->pps_MsgPort
)
1326 KPRINTF(1, ("Deleting old MsgPort\n"));
1327 DeleteMsgPort(pps
->pps_MsgPort
);
1328 pps
->pps_MsgPort
= NULL
;
1330 pps
->pps_Flags
&= ~PSFF_OWNMSGPORT
;
1332 count
+= PackStructureTags(psdstruct
, packtab
, tags
);
1333 KPRINTF(1, ("Pipes = %ld (old: %ld), BufferSize = %ld (old: %ld)\n",
1334 pps
->pps_NumPipes
, oldnumpipes
, pps
->pps_BufferSize
, oldbufsize
));
1335 if(pps
->pps_NumPipes
< 1)
1337 pps
->pps_NumPipes
= 1; /* minimal */
1339 if(pps
->pps_BufferSize
< pps
->pps_Endpoint
->pep_MaxPktSize
)
1341 pps
->pps_BufferSize
= pps
->pps_Endpoint
->pep_MaxPktSize
; /* minimal */
1343 if(!pps
->pps_MsgPort
)
1345 if((pps
->pps_MsgPort
= CreateMsgPort()))
1347 KPRINTF(1, ("Creating MsgPort\n"));
1348 pps
->pps_Flags
|= PSFF_OWNMSGPORT
;
1351 /* do we need to reallocate? */
1352 if((oldbufsize
!= pps
->pps_BufferSize
) ||
1353 (oldnumpipes
!= pps
->pps_NumPipes
) ||
1354 (!pps
->pps_Pipes
) ||
1359 KPRINTF(1, ("freeing %ld old pipes\n", oldnumpipes
));
1360 for(cnt
= 0; cnt
< oldnumpipes
; cnt
++)
1362 pp
= pps
->pps_Pipes
[cnt
];
1363 //if(pp->pp_IOReq.iouh_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
1365 KPRINTF(1, ("Abort %ld\n", cnt
));
1367 KPRINTF(1, ("Wait %ld\n", cnt
));
1370 KPRINTF(1, ("Free %ld\n", cnt
));
1373 psdFreeVec(pps
->pps_Pipes
);
1375 psdFreeVec(pps
->pps_Buffer
);
1377 NewList(&pps
->pps_FreePipes
);
1378 NewList(&pps
->pps_ReadyPipes
);
1379 pps
->pps_Offset
= 0;
1380 pps
->pps_BytesPending
= 0;
1381 pps
->pps_ReqBytes
= 0;
1382 pps
->pps_ActivePipe
= NULL
;
1383 pps
->pps_Buffer
= psdAllocVec(pps
->pps_NumPipes
* pps
->pps_BufferSize
);
1384 pps
->pps_Pipes
= psdAllocVec(pps
->pps_NumPipes
* sizeof(struct PsdPipe
*));
1385 if(pps
->pps_Pipes
&& pps
->pps_Buffer
)
1387 KPRINTF(1, ("allocating %ld new pipes\n", pps
->pps_NumPipes
));
1388 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
1390 pp
= psdAllocPipe(pps
->pps_Device
, pps
->pps_MsgPort
, pps
->pps_Endpoint
);
1391 if((pps
->pps_Pipes
[cnt
] = pp
))
1394 if(pps
->pps_Flags
& PSFF_NOSHORTPKT
) pp
->pp_IOReq
.iouh_Flags
|= UHFF_NOSHORTPKT
;
1395 if(pps
->pps_Flags
& PSFF_NAKTIMEOUT
) pp
->pp_IOReq
.iouh_Flags
|= UHFF_NAKTIMEOUT
;
1396 if(pps
->pps_Flags
& PSFF_ALLOWRUNT
) pp
->pp_IOReq
.iouh_Flags
|= UHFF_ALLOWRUNTPKTS
;
1397 pp
->pp_IOReq
.iouh_NakTimeout
= pps
->pps_NakTimeoutTime
;
1398 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
1400 KPRINTF(1, ("Allocating Pipe %ld failed!\n", cnt
));
1404 KPRINTF(1, ("Allocating Pipe array failed!\n"));
1405 psdFreeVec(pps
->pps_Buffer
);
1406 pps
->pps_Buffer
= NULL
;
1407 psdFreeVec(pps
->pps_Pipes
);
1408 pps
->pps_Pipes
= NULL
;
1411 ReleaseSemaphore(&pps
->pps_AccessLock
);
1412 return((LONG
) count
);
1418 res
= (LONG
) PackStructureTags(psdstruct
, packtab
, tags
);
1424 struct PsdDevice
*pd
= (struct PsdDevice
*) psdstruct
;
1425 struct PsdIFFContext
*pic
;
1427 pic
= psdGetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
);
1430 psdSetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
, NULL
);
1431 pic
= psdGetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
);
1435 pAddCfgChunk(ps
, pic
, &pd
->pd_PoPoCfg
);
1436 checkcfgupdate
= TRUE
;
1441 pUpdateGlobalCfg(ps
, (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
);
1442 pCheckCfgChanged(ps
);
1446 psdCalculatePower(((struct PsdDevice
*) psdstruct
)->pd_Hardware
);
1453 /* /// "psdSpawnSubTask()" */
1454 AROS_LH3(struct Task
*, psdSpawnSubTask
,
1455 AROS_LHA(STRPTR
, name
, A0
),
1456 AROS_LHA(APTR
, initpc
, A1
),
1457 AROS_LHA(APTR
, userdata
, A2
),
1458 LIBBASETYPEPTR
, ps
, 39, psd
)
1461 #define SUBTASKSTACKSIZE AROS_STACKSIZE
1464 struct MemList mrm_ml
;
1465 struct MemEntry mtm_me
[2];
1468 struct MemList
*newmemlist
;
1469 struct MemEntry
*me
;
1471 struct Process
*subtask
;
1473 if(!(name
&& initpc
))
1478 /* If there's dos available, create a process instead of a task */
1481 subtask
= CreateNewProcTags(NP_Entry
, initpc
,
1482 NP_StackSize
, SUBTASKSTACKSIZE
,
1483 NP_Priority
, ps
->ps_GlobalCfg
->pgc_SubTaskPri
,
1486 NP_UserData
, userdata
,
1488 return((struct Task
*) subtask
);
1491 /* Allocate memory of memlist */
1493 memlist
.mrm_ml
.ml_Node
.ln_Type
= NT_MEMORY
;
1494 memlist
.mrm_ml
.ml_Node
.ln_Pri
= 0;
1495 memlist
.mrm_ml
.ml_Node
.ln_Name
= NULL
;
1496 memlist
.mrm_ml
.ml_NumEntries
= 3;
1497 me
= &memlist
.mrm_ml
.ml_ME
[0];
1498 me
[1].me_Un
.meu_Reqs
= memlist
.mrm_ml
.ml_ME
[0].me_Un
.meu_Reqs
= MEMF_CLEAR
|MEMF_PUBLIC
;
1499 me
[0].me_Length
= sizeof(struct Task
);
1500 me
[1].me_Length
= SUBTASKSTACKSIZE
;
1501 me
[2].me_Un
.meu_Reqs
= MEMF_PUBLIC
;
1502 me
[2].me_Length
= strlen(name
) + 1;
1505 newmemlist
= NewAllocEntry(&memlist
.mrm_ml
, NULL
);
1508 newmemlist
= AllocEntry(&memlist
.mrm_ml
);
1509 if((IPTR
) newmemlist
& 0x80000000)
1514 me
= &newmemlist
->ml_ME
[0];
1515 nt
= me
[0].me_Un
.meu_Addr
;
1516 nt
->tc_Node
.ln_Name
= me
[2].me_Un
.meu_Addr
;
1517 strcpy(nt
->tc_Node
.ln_Name
, name
);
1518 nt
->tc_Node
.ln_Type
= NT_TASK
;
1519 nt
->tc_Node
.ln_Pri
= ps
->ps_GlobalCfg
->pgc_SubTaskPri
;
1520 nt
->tc_SPLower
= me
[1].me_Un
.meu_Addr
;
1521 nt
->tc_SPUpper
= nt
->tc_SPReg
= (APTR
) ((IPTR
) nt
->tc_SPLower
+ SUBTASKSTACKSIZE
);
1522 nt
->tc_UserData
= userdata
;
1523 NewList(&nt
->tc_MemEntry
);
1524 AddTail(&nt
->tc_MemEntry
, (struct Node
*) newmemlist
);
1525 #if !defined(__AROSEXEC_SMP__)
1526 KPRINTF(1, ("TDNestCnt=%ld\n", SysBase
->TDNestCnt
));
1528 if((nt
= AddTask(nt
, initpc
, NULL
)))
1530 XPRINTF(10, ("Started task %p (%s)\n", nt
, name
));
1533 FreeEntry(newmemlist
);
1539 /* /// "psdNumToStr()" */
1540 AROS_LH3(STRPTR
, psdNumToStr
,
1541 AROS_LHA(UWORD
, type
, D0
),
1542 AROS_LHA(LONG
, idx
, D1
),
1543 AROS_LHA(STRPTR
, defstr
, A0
),
1544 LIBBASETYPEPTR
, ps
, 38, psd
)
1551 const struct PsdWStringMap
*psm
= usbhwioerrstr
;
1554 if(psm
->psm_ID
== idx
)
1556 return(psm
->psm_String
);
1565 const struct PsdUWStringMap
*psm
= usblangids
;
1568 if(psm
->psm_ID
== idx
)
1570 return(psm
->psm_String
);
1582 case USEAF_ISOCHRONOUS
:
1583 return("isochronous");
1586 case USEAF_INTERRUPT
:
1587 return("interrupt");
1595 return("no synchronization");
1597 return("asynchronous");
1598 case USEAF_ADAPTIVE
:
1601 return("synchronous");
1610 case USEAF_FEEDBACK
:
1612 case USEAF_IMPLFEEDBACK
:
1613 return("implicit feedback data");
1619 const struct PsdUWStringMap
*psm
= usbvendorids
;
1622 if(psm
->psm_ID
== idx
)
1624 return(psm
->psm_String
);
1633 const struct PsdWStringMap
*psm
= usbclasscodestr
;
1636 if(psm
->psm_ID
== idx
)
1638 return(psm
->psm_String
);
1645 case NTS_DESCRIPTOR
:
1647 const struct PsdULStringMap
*psm
= usbdesctypestr
;
1650 if(psm
->psm_ID
== idx
)
1652 return(psm
->psm_String
);
1659 case NTS_COMBOCLASS
:
1661 const struct PsdULStringMap
*psm
= usbcomboclasscodestr
;
1662 if(idx
& (NTSCCF_CLASS
|NTSCCF_SUBCLASS
|NTSCCF_PROTO
))
1668 if(psm
->psm_ID
& NTSCCF_CLASS
)
1670 if((!(idx
& NTSCCF_CLASS
)) || ((idx
& 0x0000ff) != (psm
->psm_ID
& 0x0000ff)))
1675 if(psm
->psm_ID
& NTSCCF_SUBCLASS
)
1677 if((!(idx
& NTSCCF_SUBCLASS
)) || ((idx
& 0x00ff00) != (psm
->psm_ID
& 0x00ff00)))
1682 if(psm
->psm_ID
& NTSCCF_PROTO
)
1684 if((!(idx
& NTSCCF_PROTO
)) || ((idx
& 0xff0000) != (psm
->psm_ID
& 0xff0000)))
1691 return(psm
->psm_String
);
1704 /* *** Endpoint *** */
1706 /* /// "pFreeEndpoint()" */
1707 void pFreeEndpoint(struct PsdEndpoint
*pep
)
1709 LIBBASETYPEPTR ps
= pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Base
;
1710 KPRINTF(2, (" FreeEndpoint()\n"));
1711 Remove(&pep
->pep_Node
);
1716 /* /// "pAllocEndpoint()" */
1717 struct PsdEndpoint
* pAllocEndpoint(struct PsdInterface
*pif
)
1719 LIBBASETYPEPTR ps
= pif
->pif_Config
->pc_Device
->pd_Hardware
->phw_Base
;
1720 struct PsdEndpoint
*pep
;
1721 if((pep
= psdAllocVec(sizeof(struct PsdEndpoint
))))
1723 pep
->pep_Interface
= pif
;
1724 AddTail(&pif
->pif_EPs
, &pep
->pep_Node
);
1731 /* /// "psdFindEndpointA()" */
1732 AROS_LH3(struct PsdEndpoint
*, psdFindEndpointA
,
1733 AROS_LHA(struct PsdInterface
*, pif
, A0
),
1734 AROS_LHA(struct PsdEndpoint
*, pep
, A2
),
1735 AROS_LHA(struct TagItem
*, tags
, A1
),
1736 LIBBASETYPEPTR
, ps
, 67, psd
)
1742 KPRINTF(2, ("psdFindEndpointA(%p, %p, %p)\n", pif
, pep
, tags
));
1745 pep
= (struct PsdEndpoint
*) pif
->pif_EPs
.lh_Head
;
1747 pep
= (struct PsdEndpoint
*) pep
->pep_Node
.ln_Succ
;
1749 while(pep
->pep_Node
.ln_Succ
)
1752 if((ti
= FindTagItem(EA_IsIn
, tags
)))
1754 if((ti
->ti_Data
&& !pep
->pep_Direction
) || (!ti
->ti_Data
&& pep
->pep_Direction
))
1759 if((ti
= FindTagItem(EA_EndpointNum
, tags
)))
1761 if(ti
->ti_Data
!= pep
->pep_EPNum
)
1766 if((ti
= FindTagItem(EA_TransferType
, tags
)))
1768 if(ti
->ti_Data
!= pep
->pep_TransType
)
1773 if((ti
= FindTagItem(EA_MaxPktSize
, tags
)))
1775 if(ti
->ti_Data
!= pep
->pep_MaxPktSize
)
1780 if((ti
= FindTagItem(EA_Interval
, tags
)))
1782 if(ti
->ti_Data
!= pep
->pep_Interval
)
1792 pep
= (struct PsdEndpoint
*) pep
->pep_Node
.ln_Succ
;
1799 /* *** Interface *** */
1801 /* /// "pFreeInterface()" */
1802 void pFreeInterface(struct PsdInterface
*pif
)
1804 LIBBASETYPEPTR ps
= pif
->pif_Config
->pc_Device
->pd_Hardware
->phw_Base
;
1805 struct PsdEndpoint
*pep
= (struct PsdEndpoint
*) pif
->pif_EPs
.lh_Head
;
1806 struct PsdInterface
*altif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
1807 KPRINTF(2, (" FreeInterface()\n"));
1808 /* Remove alternate interfaces */
1809 while(altif
->pif_Node
.ln_Succ
)
1811 pFreeInterface(altif
);
1812 altif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
1814 /* Remove endpoints */
1815 while(pep
->pep_Node
.ln_Succ
)
1818 pep
= (struct PsdEndpoint
*) pif
->pif_EPs
.lh_Head
;
1820 psdFreeVec(pif
->pif_IfStr
);
1821 psdFreeVec(pif
->pif_IDString
);
1822 Remove(&pif
->pif_Node
);
1827 /* /// "pAllocInterface()" */
1828 struct PsdInterface
* pAllocInterface(struct PsdConfig
*pc
)
1830 LIBBASETYPEPTR ps
= pc
->pc_Device
->pd_Hardware
->phw_Base
;
1831 struct PsdInterface
*pif
;
1832 if((pif
= psdAllocVec(sizeof(struct PsdInterface
))))
1834 pif
->pif_Config
= pc
;
1835 NewList(&pif
->pif_EPs
);
1836 NewList(&pif
->pif_AlterIfs
);
1837 AddTail(&pc
->pc_Interfaces
, &pif
->pif_Node
);
1844 /* /// "psdFindInterfaceA()" */
1845 AROS_LH3(struct PsdInterface
*, psdFindInterfaceA
,
1846 AROS_LHA(struct PsdDevice
*, pd
, A0
),
1847 AROS_LHA(struct PsdInterface
*, pif
, A2
),
1848 AROS_LHA(struct TagItem
*, tags
, A1
),
1849 LIBBASETYPEPTR
, ps
, 66, psd
)
1852 struct PsdConfig
*pc
;
1855 BOOL searchalt
= FALSE
;
1857 struct PsdInterface
*oldpif
= NULL
;
1859 KPRINTF(2, ("psdFindInterfaceA(%p, %p, %p)\n", pd
, pif
, tags
));
1862 pc
= pd
->pd_CurrentConfig
;
1865 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
1872 if(FindTagItem(IFA_AlternateNum
, tags
))
1876 if(pif
->pif_ParentIf
)
1878 // special case: we are in an alternate interface right now
1880 if(pif
->pif_Node
.ln_Succ
)
1883 oldpif
= pif
->pif_ParentIf
;
1884 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
1886 pif
= (struct PsdInterface
*) pif
->pif_ParentIf
->pif_Node
.ln_Succ
;
1889 // go into alt interfaces
1890 if(searchalt
&& pif
->pif_AlterIfs
.lh_Head
->ln_Succ
)
1894 pif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
1896 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
1901 while(pif
->pif_Node
.ln_Succ
)
1904 if((ti
= FindTagItem(IFA_InterfaceNum
, tags
)))
1906 if(ti
->ti_Data
!= pif
->pif_IfNum
)
1911 if((ti
= FindTagItem(IFA_AlternateNum
, tags
)))
1914 if(ti
->ti_Data
<= 0xff) // if alternate number is greater than 0xff, don't check compliance, but just enable alternate interface searching
1916 if(ti
->ti_Data
!= pif
->pif_Alternate
)
1922 if((ti
= FindTagItem(IFA_NumEndpoints
, tags
)))
1924 if(ti
->ti_Data
!= pif
->pif_NumEPs
)
1929 if((ti
= FindTagItem(IFA_Class
, tags
)))
1931 if(ti
->ti_Data
!= pif
->pif_IfClass
)
1936 if((ti
= FindTagItem(IFA_SubClass
, tags
)))
1938 if(ti
->ti_Data
!= pif
->pif_IfSubClass
)
1943 if((ti
= FindTagItem(IFA_Protocol
, tags
)))
1945 if(ti
->ti_Data
!= pif
->pif_IfProto
)
1950 if((ti
= FindTagItem(IFA_Binding
, tags
)))
1952 if((APTR
) ti
->ti_Data
!= pif
->pif_IfBinding
)
1957 if((ti
= FindTagItem(IFA_InterfaceName
, tags
)))
1959 if(strcmp((STRPTR
) ti
->ti_Data
, pif
->pif_IfStr
))
1964 if((ti
= FindTagItem(IFA_IDString
, tags
)))
1966 if(strcmp((STRPTR
) ti
->ti_Data
, pif
->pif_IDString
))
1980 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
1981 if(!pif
->pif_Node
.ln_Succ
)
1983 pif
= (struct PsdInterface
*) oldpif
->pif_Node
.ln_Succ
;
1988 pif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
1989 if(!pif
->pif_Node
.ln_Succ
)
1991 pif
= (struct PsdInterface
*) oldpif
->pif_Node
.ln_Succ
;
1997 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
2005 /* *** Config *** */
2007 /* /// "pFreeConfig()" */
2008 void pFreeConfig(struct PsdConfig
*pc
)
2010 LIBBASETYPEPTR ps
= pc
->pc_Device
->pd_Hardware
->phw_Base
;
2011 struct PsdInterface
*pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2012 KPRINTF(2, (" FreeConfig()\n"));
2013 while(pif
->pif_Node
.ln_Succ
)
2015 psdReleaseIfBinding(pif
);
2016 pFreeInterface(pif
);
2017 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2019 psdFreeVec(pc
->pc_CfgStr
);
2020 Remove(&pc
->pc_Node
);
2025 /* /// "pAllocConfig()" */
2026 struct PsdConfig
* pAllocConfig(struct PsdDevice
*pd
)
2028 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
2029 struct PsdConfig
*pc
;
2030 KPRINTF(2, (" AllocConfig()\n"));
2031 if((pc
= psdAllocVec(sizeof(struct PsdConfig
))))
2034 NewList(&pc
->pc_Interfaces
);
2035 AddTail(&pd
->pd_Configs
, &pc
->pc_Node
);
2042 /* *** Descriptors *** */
2044 /* /// "pFreeDescriptor()" */
2045 void pFreeDescriptor(struct PsdDescriptor
*pdd
)
2047 LIBBASETYPEPTR ps
= pdd
->pdd_Device
->pd_Hardware
->phw_Base
;
2048 KPRINTF(2, (" FreeDescriptor()\n"));
2049 //psdFreeVec(pdd->pdd_Data); // part of the structure alloc
2050 Remove(&pdd
->pdd_Node
);
2055 /* /// "pAllocDescriptor()" */
2056 struct PsdDescriptor
* pAllocDescriptor(struct PsdDevice
*pd
, UBYTE
*buf
)
2058 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
2059 struct PsdDescriptor
*pdd
;
2061 KPRINTF(2, (" AllocDescriptor()\n"));
2062 if((pdd
= psdAllocVec(sizeof(struct PsdDescriptor
) + (ULONG
) buf
[0])))
2064 pdd
->pdd_Device
= pd
;
2065 pdd
->pdd_Data
= ((UBYTE
*) pdd
) + sizeof(struct PsdDescriptor
);
2066 pdd
->pdd_Length
= buf
[0];
2067 pdd
->pdd_Type
= buf
[1];
2068 if((pdd
->pdd_Type
>= UDT_CS_UNDEFINED
) && (pdd
->pdd_Type
<= UDT_CS_ENDPOINT
))
2070 pdd
->pdd_CSSubType
= buf
[2];
2072 pdd
->pdd_Name
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) pdd
->pdd_Type
, "<unknown>");
2073 CopyMem(buf
, pdd
->pdd_Data
, (ULONG
) buf
[0]);
2074 AddTail(&pd
->pd_Descriptors
, &pdd
->pdd_Node
);
2081 /* /// "psdFindDescriptorA()" */
2082 AROS_LH3(struct PsdDescriptor
*, psdFindDescriptorA
,
2083 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2084 AROS_LHA(struct PsdDescriptor
*, pdd
, A2
),
2085 AROS_LHA(struct TagItem
*, tags
, A1
),
2086 LIBBASETYPEPTR
, ps
, 91, psd
)
2089 struct PsdConfig
*pc
= pd
->pd_CurrentConfig
;
2093 KPRINTF(2, ("psdFindDescriptorA(%p, %p, %p)\n", pd
, pdd
, tags
));
2096 pdd
= (struct PsdDescriptor
*) pd
->pd_Descriptors
.lh_Head
;
2098 pdd
= (struct PsdDescriptor
*) pdd
->pdd_Node
.ln_Succ
;
2101 while(pdd
->pdd_Node
.ln_Succ
)
2105 if((ti
= FindTagItem(DDA_Config
, tags
)))
2107 // special case to workaround default: with NULL given, all configs are matched
2108 if(ti
->ti_Data
&& (((struct PsdConfig
*) ti
->ti_Data
) != pdd
->pdd_Config
))
2113 // only take descriptors from the current configuration by default
2114 if(pc
!= pdd
->pdd_Config
)
2119 if((ti
= FindTagItem(DDA_Interface
, tags
)))
2121 if(((struct PsdInterface
*) ti
->ti_Data
) != pdd
->pdd_Interface
)
2126 if((ti
= FindTagItem(DDA_Endpoint
, tags
)))
2128 if(((struct PsdEndpoint
*) ti
->ti_Data
) != pdd
->pdd_Endpoint
)
2133 if((ti
= FindTagItem(DDA_DescriptorType
, tags
)))
2135 if(ti
->ti_Data
!= pdd
->pdd_Type
)
2140 if((ti
= FindTagItem(DDA_CS_SubType
, tags
)))
2142 if(ti
->ti_Data
!= pdd
->pdd_CSSubType
)
2147 if((ti
= FindTagItem(DDA_DescriptorLength
, tags
)))
2149 if(ti
->ti_Data
!= pdd
->pdd_Length
)
2159 pdd
= (struct PsdDescriptor
*) pdd
->pdd_Node
.ln_Succ
;
2166 /* *** Device *** */
2168 /* /// "pFreeBindings()" */
2169 void pFreeBindings(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
2171 struct PsdHardware
*phw
= pd
->pd_Hardware
;
2172 struct PsdConfig
*pc
;
2173 struct PsdInterface
*pif
;
2174 KPRINTF(3, (" FreeBindings(%p)\n", pd
));
2176 /* move device to list of dead devices first
2177 This caused a lot of trouble as it could
2178 happen that a device got into class scan
2179 right after the bindings had been released. */
2180 psdLockWritePBase();
2181 Remove(&pd
->pd_Node
);
2182 AddTail(&phw
->phw_DeadDevices
, &pd
->pd_Node
);
2185 /* If there are bindings, get rid of them. */
2186 psdLockWriteDevice(pd
);
2187 psdReleaseDevBinding(pd
);
2189 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2190 while(pc
->pc_Node
.ln_Succ
)
2192 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2193 while(pif
->pif_Node
.ln_Succ
)
2195 psdReleaseIfBinding(pif
);
2196 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
2198 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
2200 psdUnlockDevice(pd
);
2204 /* /// "pFreeDevice()" */
2205 void pFreeDevice(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
2207 struct PsdHardware
*phw
= pd
->pd_Hardware
;
2208 struct PsdConfig
*pc
;
2209 struct PsdDescriptor
*pdd
;
2211 psdCalculatePower(phw
);
2212 psdLockWriteDevice(pd
);
2215 KPRINTF(20, ("Couldn't free device, use cnt %ld\n", pd
->pd_UseCnt
));
2216 pd
->pd_Flags
&= ~PDFF_CONNECTED
;
2217 pd
->pd_Flags
|= PDFF_DELEXPUNGE
;
2218 psdUnlockDevice(pd
);
2220 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2221 while(pc
->pc_Node
.ln_Succ
)
2224 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2227 pdd
= (struct PsdDescriptor
*) pd
->pd_Descriptors
.lh_Head
;
2228 while(pdd
->pdd_Node
.ln_Succ
)
2230 pFreeDescriptor(pdd
);
2231 pdd
= (struct PsdDescriptor
*) pd
->pd_Descriptors
.lh_Head
;
2234 psdFreeVec(pd
->pd_LangIDArray
);
2235 pd
->pd_LangIDArray
= NULL
;
2236 psdFreeVec(pd
->pd_MnfctrStr
);
2237 pd
->pd_MnfctrStr
= NULL
;
2238 /*if(!ps->ps_PoPo.po_Task) // keep name at least
2240 psdFreeVec(pd->pd_ProductStr);
2241 pd->pd_ProductStr = NULL;
2243 psdFreeVec(pd
->pd_OldProductStr
);
2244 pd
->pd_OldProductStr
= NULL
;
2245 psdFreeVec(pd
->pd_SerNumStr
);
2246 pd
->pd_SerNumStr
= NULL
;
2247 psdFreeVec(pd
->pd_IDString
);
2248 pd
->pd_IDString
= NULL
;
2251 KPRINTF(5,("Released DevAddr %ld\n", pd
->pd_DevAddr
));
2252 phw
->phw_DevArray
[pd
->pd_DevAddr
] = NULL
;
2254 psdUnlockDevice(pd
);
2255 psdLockWritePBase();
2256 Remove(&pd
->pd_Node
);
2258 pDeleteSem(ps
, &pd
->pd_Lock
);
2259 /* cannot free this vector -- tasks might still call LockDevice */
2262 KPRINTF(3, ("FreeDevice done\n"));
2266 /* /// "psdFreeDevice()" */
2267 AROS_LH1(void, psdFreeDevice
,
2268 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2269 LIBBASETYPEPTR
, ps
, 16, psd
)
2272 struct PsdHardware
*phw
= pd
->pd_Hardware
;
2273 struct PsdConfig
*pc
;
2274 struct PsdInterface
*pif
;
2275 struct PsdRTIsoHandler
*prt
;
2276 struct PsdRTIsoHandler
*nextprt
;
2278 KPRINTF(3, (" FreeDevice(%p)\n", pd
));
2280 /* move device to list of dead devices first
2281 This caused a lot of trouble as it could
2282 happen that a device got into class scan
2283 right after the bindings had been released. */
2284 psdLockWritePBase();
2285 Remove(&pd
->pd_Node
);
2286 AddTail(&phw
->phw_DeadDevices
, &pd
->pd_Node
);
2287 pd
->pd_Flags
&= ~PDFF_DELEXPUNGE
;
2290 psdLockWriteDevice(pd
);
2292 /* Inform all ISO handlers about the device going offline */
2293 prt
= (struct PsdRTIsoHandler
*) pd
->pd_RTIsoHandlers
.lh_Head
;
2294 while((nextprt
= (struct PsdRTIsoHandler
*) prt
->prt_Node
.ln_Succ
))
2296 if(prt
->prt_ReleaseHook
)
2298 CallHookPkt(prt
->prt_ReleaseHook
, prt
, NULL
);
2303 /* If there are bindings, get rid of them. */
2304 psdHubReleaseDevBinding(pd
);
2306 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2307 while(pc
->pc_Node
.ln_Succ
)
2309 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2310 while(pif
->pif_Node
.ln_Succ
)
2312 psdHubReleaseIfBinding(pif
);
2313 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
2315 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
2317 psdUnlockDevice(pd
);
2319 pFreeDevice(ps
, pd
);
2324 /* /// "psdAllocDevice()" */
2325 AROS_LH1(struct PsdDevice
*, psdAllocDevice
,
2326 AROS_LHA(struct PsdHardware
*, phw
, A0
),
2327 LIBBASETYPEPTR
, ps
, 15, psd
)
2330 struct PsdDevice
*pd
;
2331 KPRINTF(2, ("psdAllocDevice(%p)\n", phw
));
2332 if((pd
= psdAllocVec(sizeof(struct PsdDevice
))))
2334 pd
->pd_Hardware
= phw
;
2336 pd
->pd_MaxPktSize0
= 8;
2338 pInitSem(ps
, &pd
->pd_Lock
, "Device");
2340 NewList(&pd
->pd_Configs
);
2341 NewList(&pd
->pd_Descriptors
);
2342 NewList(&pd
->pd_RTIsoHandlers
);
2345 pd
->pd_PoPoCfg
.poc_ChunkID
= AROS_LONG2BE(IFFCHNK_POPUP
);
2346 pd
->pd_PoPoCfg
.poc_Length
= AROS_LONG2BE(sizeof(struct PsdPoPoCfg
) - 8);
2347 pd
->pd_PoPoCfg
.poc_InhibitPopup
= FALSE
;
2348 pd
->pd_PoPoCfg
.poc_NoClassBind
= FALSE
;
2349 pd
->pd_PoPoCfg
.poc_OverridePowerInfo
= POCP_TRUST_DEVICE
;
2351 psdLockWritePBase();
2352 AddTail(&phw
->phw_Devices
, &pd
->pd_Node
);
2356 KPRINTF(20, ("psdAllocDevice(): out of memory!\n"));
2363 /* /// "psdLockReadDevice()" */
2364 AROS_LH1(void, psdLockReadDevice
,
2365 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2366 LIBBASETYPEPTR
, ps
, 17, psd
)
2369 KPRINTF(2, ("psdLockReadDevice(%p, %p)\n", pd
, FindTask(NULL
)));
2370 pLockSemShared(ps
, &pd
->pd_Lock
);
2375 /* /// "psdLockWriteDevice()" */
2376 AROS_LH1(void, psdLockWriteDevice
,
2377 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2378 LIBBASETYPEPTR
, ps
, 18, psd
)
2381 KPRINTF(2, ("psdLockWriteDevice(%p, %p)\n", pd
, FindTask(NULL
)));
2382 pLockSemExcl(ps
, &pd
->pd_Lock
);
2387 /* /// "psdUnlockDevice()" */
2388 AROS_LH1(void, psdUnlockDevice
,
2389 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2390 LIBBASETYPEPTR
, ps
, 19, psd
)
2393 KPRINTF(2, ("psdUnlockDevice(%p, %p)\n", pd
, FindTask(NULL
)));
2394 pUnlockSem(ps
, &pd
->pd_Lock
);
2399 /* /// "pAllocDevAddr()" */
2400 UWORD
pAllocDevAddr(struct PsdDevice
*pd
)
2402 struct PsdHardware
*phw
= pd
->pd_Hardware
;
2406 return(pd
->pd_DevAddr
);
2408 for(da
= 1; da
< 128; da
++)
2410 if(!phw
->phw_DevArray
[da
])
2412 phw
->phw_DevArray
[da
] = pd
;
2413 pd
->pd_DevAddr
= da
;
2421 /* /// "psdGetStringDescriptor()" */
2422 AROS_LH2(STRPTR
, psdGetStringDescriptor
,
2423 AROS_LHA(struct PsdPipe
*, pp
, A1
),
2424 AROS_LHA(UWORD
, idx
, D0
),
2425 LIBBASETYPEPTR
, ps
, 33, psd
)
2428 struct PsdDevice
*pd
= pp
->pp_Device
;
2437 KPRINTF(1, ("psdGetStringDescriptor(%p, %ld)\n", pp
, idx
));
2440 if(!pd
->pd_LangIDArray
)
2442 KPRINTF(10,("Trying to get language array...\n"));
2443 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
2444 USR_GET_DESCRIPTOR
, UDT_STRING
<<8, 0);
2445 ioerr
= psdDoPipe(pp
, buf
, 2);
2446 if(ioerr
== UHIOERR_OVERFLOW
)
2449 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Language array overflow.");
2453 ioerr
= psdDoPipe(pp
, buf
, 256);
2454 if(ioerr
== UHIOERR_RUNTPACKET
)
2462 if((pd
->pd_LangIDArray
= psdAllocVec(max(len
, 4))))
2464 tmpbuf
= tmpptr
= pd
->pd_LangIDArray
;
2465 KPRINTF(1, ("Getting LangID Array length %ld\n", len
));
2466 // generate minimal sized array
2471 *tmpbuf
= AROS_WORD2LE(0x0409);
2472 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2473 "Language array descriptor too small (len %ld), using dummy.",
2477 ioerr
= psdDoPipe(pp
, tmpbuf
++, len
);
2484 KPRINTF(1, ("LangID: %04lx\n", AROS_WORD2LE(*tmpbuf
)));
2485 *tmpptr
++ = AROS_WORD2LE(*tmpbuf
);
2489 tmpptr
= pd
->pd_LangIDArray
;
2490 pd
->pd_CurrLangID
= *tmpptr
;
2493 if(*tmpptr
== 0x0409)
2495 pd
->pd_CurrLangID
= *tmpptr
;
2501 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2502 "Reading language array descriptor (len %ld) failed: %s (%ld)",
2503 len
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2504 KPRINTF(15, ("Error reading lang array descriptor (%ld) failed %ld\n", len
, ioerr
));
2508 KPRINTF(20, ("No langid array memory!\n"));
2511 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2512 "Reading language array descriptor (len %ld) failed: %s (%ld)",
2513 2, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2514 KPRINTF(15, ("Error reading lang array descriptor (2) failed %ld\n", ioerr
));
2515 /* Create empty array */
2516 if((pd
->pd_LangIDArray
= psdAllocVec(2)))
2518 *pd
->pd_LangIDArray
= 0;
2523 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
2524 USR_GET_DESCRIPTOR
, (UDT_STRING
<<8)|idx
, pd
->pd_CurrLangID
);
2525 ioerr
= psdDoPipe(pp
, buf
, 2);
2526 if(ioerr
== UHIOERR_OVERFLOW
)
2529 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "String %ld overflow.", idx
);
2533 ioerr
= psdDoPipe(pp
, buf
, 256);
2540 tmpptr
= (UWORD
*) buf
;
2541 KPRINTF(1, ("Getting String Descriptor %ld, length %ld\n", idx
, len
));
2542 ioerr
= psdDoPipe(pp
, tmpptr
++, len
);
2543 if(ioerr
== UHIOERR_RUNTPACKET
)
2545 len
= pp
->pp_IOReq
.iouh_Actual
;
2548 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2549 "String descriptor %ld truncated to %ld, requested %ld",
2556 ioerr
= psdDoPipe(pp
, buf
, 256);
2560 if((cbuf
= rs
= psdAllocVec(len
>>1)))
2565 widechar
= *tmpptr
++;
2566 widechar
= AROS_LE2WORD(widechar
);
2571 if((widechar
< 0x20) || (widechar
> 255))
2579 KPRINTF(1, ("String \"%s\"\n", rs
));
2588 KPRINTF(20, ("No memory for string!\n"));
2591 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2592 "Reading string descriptor %ld (len %ld) failed: %s (%ld)",
2593 idx
, len
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2594 KPRINTF(15, ("Error reading string descriptor %ld (%ld) failed %ld\n",
2598 KPRINTF(5, ("Empty string\n"));
2599 return(psdCopyStr(""));
2602 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2603 "Reading string descriptor %ld (len %ld) failed: %s (%ld)",
2604 idx
, 2, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2605 KPRINTF(15, ("Error reading string descriptor %ld (2) failed %ld\n", idx
, ioerr
));
2612 /* /// "psdSetDeviceConfig()" */
2613 AROS_LH2(BOOL
, psdSetDeviceConfig
,
2614 AROS_LHA(struct PsdPipe
*, pp
, A1
),
2615 AROS_LHA(UWORD
, cfgnum
, D0
),
2616 LIBBASETYPEPTR
, ps
, 34, psd
)
2619 struct PsdConfig
*pc
;
2620 struct PsdDevice
*pd
= pp
->pp_Device
;
2621 //UBYTE buf[8]; // VIA babble bug safety buffer (8 instead of 2)
2625 KPRINTF(2, ("Setting configuration to %ld...\n", cfgnum
));
2626 psdPipeSetup(pp
, URTF_STANDARD
|URTF_DEVICE
,
2627 USR_SET_CONFIGURATION
, cfgnum
, 0);
2628 ioerr
= psdDoPipe(pp
, NULL
, 0);
2631 #if 0 // MacOS X does not verify the configuration set. And as we don't check the results anyway, don't obtain current configuration to avoid bad devices breaking down
2632 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
2633 USR_GET_CONFIGURATION
, 0, 0);
2634 ioerr
= psdDoPipe(pp
, buf
, 1);
2637 pd
->pd_CurrCfg
= buf
[0];
2638 if(cfgnum
!= buf
[0])
2640 pd
->pd_CurrCfg
= cfgnum
;
2641 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2642 "Broken: SetConfig/GetConfig mismatch (%ld != %ld) for %s!",
2643 cfgnum
, buf
[0], pp
->pp_Device
->pd_ProductStr
);
2647 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2648 "GET_CONFIGURATION failed: %s (%ld)",
2649 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2650 pd
->pd_CurrCfg
= cfgnum
;
2651 KPRINTF(15, ("GET_CONFIGURATION failed %ld!\n", ioerr
));
2654 pd
->pd_CurrCfg
= cfgnum
;
2658 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2659 "SET_CONFIGURATION failed: %s (%ld)",
2660 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2661 KPRINTF(15, ("SET_CONFIGURATION failed %ld!\n", ioerr
));
2663 // update direct link
2665 pd
->pd_CurrentConfig
= NULL
;
2666 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2667 while(pc
->pc_Node
.ln_Succ
)
2669 if(pc
->pc_CfgNum
== pd
->pd_CurrCfg
)
2671 pd
->pd_CurrentConfig
= pc
;
2674 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
2677 if(!pd
->pd_CurrentConfig
)
2679 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "No current configuration, huh?");
2682 // power saving stuff
2683 if(ps
->ps_GlobalCfg
->pgc_PowerSaving
&& (pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
))
2685 psdPipeSetup(pp
, URTF_STANDARD
|URTF_DEVICE
,
2686 USR_SET_FEATURE
, UFS_DEVICE_REMOTE_WAKEUP
, 0);
2687 ioerr
= psdDoPipe(pp
, NULL
, 0);
2690 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2691 "SET_DEVICE_REMOTE_WAKEUP failed: %s (%ld)",
2692 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2693 KPRINTF(15, ("SET_DEVICE_REMOTE_WAKEUP failed %ld!\n", ioerr
));
2695 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_STATUS
, 0, 0);
2696 ioerr
= psdDoPipe(pp
, &status
, 2);
2699 if(status
& U_GSF_REMOTE_WAKEUP
)
2701 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2702 "Enabled remote wakeup feature for '%s'.",
2705 pd
->pd_CurrentConfig
->pc_Attr
&= ~USCAF_REMOTE_WAKEUP
;
2706 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2707 "Remote wakeup feature for '%s' could not be enabled.",
2711 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2712 "GET_STATUS failed: %s (%ld)",
2713 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);*/
2714 KPRINTF(15, ("GET_STATUS failed %ld!\n", ioerr
));
2717 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_STATUS
, 0, 0);
2718 ioerr
= psdDoPipe(pp
, &status
, 2);
2722 if((status
& U_GSF_SELF_POWERED
) && (!(pd
->pd_CurrentConfig
->pc_Attr
& USCAF_SELF_POWERED
)))
2724 pd
->pd_CurrentConfig
->pc_Attr
|= USCAF_SELF_POWERED
;
2725 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2726 "Device '%s' says it is currently self-powered. Fixing config.",
2729 else if((!(status
& U_GSF_SELF_POWERED
)) && (pd
->pd_CurrentConfig
->pc_Attr
& USCAF_SELF_POWERED
))
2731 pd
->pd_CurrentConfig
->pc_Attr
&= ~USCAF_SELF_POWERED
;
2732 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2733 "Device '%s' says it is currently bus-powered. Fixing config.",
2737 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2738 "GET_STATUS failed: %s (%ld)",
2739 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);*/
2740 KPRINTF(15, ("GET_STATUS failed %ld!\n", ioerr
));
2749 /* /// "psdSetAltInterface()" */
2750 AROS_LH2(BOOL
, psdSetAltInterface
,
2751 AROS_LHA(struct PsdPipe
*, pp
, A1
),
2752 AROS_LHA(struct PsdInterface
*, pif
, A0
),
2753 LIBBASETYPEPTR
, ps
, 43, psd
)
2756 struct PsdConfig
*pc
= pif
->pif_Config
;
2757 struct PsdInterface
*curif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2758 struct PsdInterface
*tmpif
;
2759 struct PsdDevice
*pd
= pc
->pc_Device
;
2760 UBYTE buf
[8]; // VIA babble bug safety buffer (8 instead of 2)
2762 UWORD ifnum
= pif
->pif_IfNum
;
2763 UWORD altnum
= pif
->pif_Alternate
;
2765 KPRINTF(2, ("Setting interface %ld to alt %ld...\n", ifnum
, altnum
));
2766 psdLockWriteDevice(pd
);
2768 /* Find root config structure */
2769 while(curif
->pif_Node
.ln_Succ
)
2771 if(curif
->pif_IfNum
== ifnum
)
2775 curif
= (struct PsdInterface
*) curif
->pif_Node
.ln_Succ
;
2777 if(!curif
->pif_Node
.ln_Succ
)
2779 KPRINTF(20, ("Where did you get that fucking interface from?!?"));
2780 psdUnlockDevice(pd
);
2783 if(curif
== pif
) /* Is already the current alternate setting */
2785 psdUnlockDevice(pd
);
2788 KPRINTF(1, ("really setting interface...\n"));
2791 psdPipeSetup(pp
, URTF_STANDARD
|URTF_INTERFACE
,
2792 USR_SET_INTERFACE
, altnum
, ifnum
);
2793 ioerr
= psdDoPipe(pp
, NULL
, 0);
2797 if((!ioerr
) || (ioerr
== UHIOERR_STALL
))
2801 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_INTERFACE
,
2802 USR_GET_INTERFACE
, 0, ifnum
);
2803 ioerr
= psdDoPipe(pp
, buf
, 1);
2809 if(altnum
== buf
[0])
2811 KPRINTF(1, ("resorting list..."));
2812 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2813 "Changed to alt %ld",
2816 /* Remove pif from alt list */
2817 Remove(&pif
->pif_Node
);
2818 pif
->pif_ParentIf
= NULL
;
2819 /* Now move bindings */
2820 pif
->pif_ClsBinding
= curif
->pif_ClsBinding
;
2821 pif
->pif_IfBinding
= curif
->pif_IfBinding
;
2822 curif
->pif_IfBinding
= NULL
;
2823 curif
->pif_ClsBinding
= NULL
;
2824 /* Insert it after root interface */
2825 Insert(&pc
->pc_Interfaces
, (struct Node
*) &pif
->pif_Node
, (struct Node
*) &curif
->pif_Node
);
2826 /* Unlink root interface */
2827 Remove(&curif
->pif_Node
);
2828 /* Now move all remaining alt interfaces to the new root interface */
2829 tmpif
= (struct PsdInterface
*) curif
->pif_AlterIfs
.lh_Head
;
2830 while(tmpif
->pif_Node
.ln_Succ
)
2832 Remove(&tmpif
->pif_Node
);
2833 AddTail(&pif
->pif_AlterIfs
, &tmpif
->pif_Node
);
2834 tmpif
->pif_ParentIf
= pif
;
2835 tmpif
= (struct PsdInterface
*) curif
->pif_AlterIfs
.lh_Head
;
2837 /* Add old root to the end of the alt list */
2838 AddTail(&pif
->pif_AlterIfs
, &curif
->pif_Node
);
2839 curif
->pif_ParentIf
= pif
;
2841 psdUnlockDevice(pd
);
2844 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2845 "Attempt to change interface %ld to alt %ld remained at alt %ld.",
2846 ifnum
, altnum
, buf
[0]);
2849 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2850 "GET_INTERFACE(%ld) failed: %s (%ld)",
2851 ifnum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2852 KPRINTF(15, ("GET_INTERFACE failed %ld!\n", ioerr
));
2855 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2856 "SET_INTERFACE(%ld)=%ld failed: %s (%ld)",
2858 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2859 KPRINTF(15, ("SET_INTERFACE failed %ld!\n", ioerr
));
2861 psdUnlockDevice(pd
);
2867 /* /// "psdEnumerateDevice()" */
2868 AROS_LH1(struct PsdDevice
*, psdEnumerateDevice
,
2869 AROS_LHA(struct PsdPipe
*, pp
, A1
),
2870 LIBBASETYPEPTR
, ps
, 20, psd
)
2874 struct PsdDevice
*pd
= pp
->pp_Device
;
2875 struct PsdDevice
*itpd
= pp
->pp_Device
;
2876 struct PsdConfig
*pc
;
2877 struct PsdInterface
*pif
;
2878 struct UsbStdDevDesc usdd
;
2881 ULONG oldnaktimeout
;
2893 BOOL haspopupinhibit
;
2897 struct PsdIFFContext
*pic
;
2901 #ifdef AROS_USB30_CODE
2902 struct UsbStdBOSDesc usbosd
;
2906 KPRINTF(2, ("psdEnumerateDevice(%p)\n", pp
));
2908 psdLockWriteDevice(pd
);
2909 if(pAllocDevAddr(pd
)) {
2911 oldflags
= pp
->pp_IOReq
.iouh_Flags
;
2912 oldnaktimeout
= pp
->pp_IOReq
.iouh_NakTimeout
;
2913 pp
->pp_IOReq
.iouh_Flags
|= UHFF_NAKTIMEOUT
;
2914 pp
->pp_IOReq
.iouh_NakTimeout
= 1000;
2915 pp
->pp_IOReq
.iouh_DevAddr
= 0;
2918 64 bytes is the maximum packet size for control transfers in fullspeed and highspeed devices
2920 psdGetAttrs(PGA_DEVICE
, pd
, DA_IsLowspeed
, &islowspeed
, TAG_END
);
2923 pp
->pp_IOReq
.iouh_MaxPktSize
= 8;
2925 pp
->pp_IOReq
.iouh_MaxPktSize
= 64;
2928 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_DESCRIPTOR
, UDT_DEVICE
<<8, 0);
2929 ioerr
= psdDoPipe(pp
, &usdd
, 8);
2930 if(ioerr
&& (ioerr
!= UHIOERR_RUNTPACKET
)) {
2931 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "GET_DESCRIPTOR (8) failed: %s (%ld)", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2932 KPRINTF(15, ("GET_DESCRIPTOR (8) failed %ld!\n", ioerr
));
2935 KPRINTF(1, ("Setting DevAddr %ld...\n", pd
->pd_DevAddr
));
2936 psdPipeSetup(pp
, URTF_STANDARD
|URTF_DEVICE
, USR_SET_ADDRESS
, pd
->pd_DevAddr
, 0);
2937 ioerr
= psdDoPipe(pp
, NULL
, 0);
2939 This is tricky: Maybe the device has accepted the command,
2940 but failed to send an ACK. Now, every resend trial will
2941 go to the wrong address!
2943 if((ioerr
== UHIOERR_TIMEOUT
) || (ioerr
== UHIOERR_STALL
)) {
2944 KPRINTF(1, ("First attempt failed, retrying new address\n"));
2945 /*pp->pp_IOReq.iouh_DevAddr = pd->pd_DevAddr;*/
2947 ioerr
= psdDoPipe(pp
, NULL
, 0);
2948 /*pp->pp_IOReq.iouh_DevAddr = 0;*/
2952 pd
->pd_Flags
|= PDFF_HASDEVADDR
|PDFF_CONNECTED
;
2953 pp
->pp_IOReq
.iouh_DevAddr
= pd
->pd_DevAddr
;
2955 psdDelayMS(50); /* Allowed time to settle */
2958 We have already received atleast the first 8 bytes from the descriptor, asking again may confuse some devices
2959 This is somewhat similar to how Windows enumerates USB devices
2961 KPRINTF(1, ("Getting MaxPktSize0...\n"));
2962 switch(usdd
.bMaxPacketSize0
)
2968 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
= usdd
.bMaxPacketSize0
;
2970 #ifdef AROS_USB30_CODE
2972 if((AROS_LE2WORD(usdd
.bcdUSB
) >= 0x0300)) {
2973 /* 9 is the only valid value for superspeed mode and it is the exponent of 2 =512 bytes */
2974 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
= (1<<9);
2979 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Illegal MaxPktSize0=%ld for endpoint 0", (ULONG
) usdd
.bMaxPacketSize0
);
2980 KPRINTF(2, ("Illegal MaxPktSize0=%ld!\n", usdd
.bMaxPacketSize0
));
2981 //pp->pp_IOReq.iouh_MaxPktSize = pd->pd_MaxPktSize0 = 8;
2982 ioerr
= UHIOERR_CRCERROR
;
2986 KPRINTF(1, (" MaxPktSize0 = %ld\n", pd
->pd_MaxPktSize0
));
2988 KPRINTF(1, ("Getting full descriptor...\n"));
2990 We have set a new address for the device so we need to setup the pipe again
2992 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_DESCRIPTOR
, UDT_DEVICE
<<8, 0);
2993 ioerr
= psdDoPipe(pp
, &usdd
, sizeof(struct UsbStdDevDesc
));
2996 pAllocDescriptor(pd
, (UBYTE
*) &usdd
);
2997 pd
->pd_Flags
|= PDFF_HASDEVDESC
;
2998 pd
->pd_USBVers
= AROS_WORD2LE(usdd
.bcdUSB
);
2999 pd
->pd_DevClass
= usdd
.bDeviceClass
;
3000 pd
->pd_DevSubClass
= usdd
.bDeviceSubClass
;
3001 pd
->pd_DevProto
= usdd
.bDeviceProtocol
;
3002 pd
->pd_VendorID
= AROS_WORD2LE(usdd
.idVendor
);
3003 pd
->pd_ProductID
= AROS_WORD2LE(usdd
.idProduct
);
3004 pd
->pd_DevVers
= AROS_WORD2LE(usdd
.bcdDevice
);
3005 vendorname
= psdNumToStr(NTS_VENDORID
, (LONG
) pd
->pd_VendorID
, NULL
);
3007 // patch to early determine highspeed roothubs
3008 if((!pd
->pd_Hub
) && (pd
->pd_USBVers
>= 0x200) && (pd
->pd_USBVers
< 0x300)) {
3009 pd
->pd_Flags
|= PDFF_HIGHSPEED
;
3012 #ifdef AROS_USB30_CODE
3013 if(((!pd
->pd_Hub
) && pd
->pd_USBVers
>= 0x300)) {
3014 pd
->pd_Flags
|= PDFF_SUPERSPEED
;
3018 The USB 3.0 and USB 2.0 LPM specifications define a new USB descriptor called the Binary Device Object Store (BOS)
3019 for a USB device, which reports a bcdUSB value greater than 0x0200 in their device descriptor
3021 if((pd
->pd_USBVers
> 0x200)) {
3022 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_DESCRIPTOR
, UDT_BOS
<<8, 0);
3023 ioerr_bos
= psdDoPipe(pp
, &usbosd
, sizeof(struct UsbStdBOSDesc
));
3025 XPRINTF(1, ("BOS descriptor received...\n"));
3028 BOS descriptor bLength = sizeof(struct UsbStdBOSDesc)
3029 BOS descriptor bNumDeviceCaps != 0
3030 BOS descriptor wTotalLength >= bLength + (bNumDeviceCaps * sizeof(protocol specific capability descriptor))
3032 if(usbosd
.bLength
!= sizeof(struct UsbStdBOSDesc
)) {
3033 XPRINTF(1, ("Invalid BOS descriptor bLength!\n"));
3036 if(usbosd
.bNumDeviceCaps
== 0) {
3037 XPRINTF(1, ("Invalid BOS descriptor bNumDeviceCaps!\n"));
3038 }else if(usbosd
.wTotalLength
< (usbosd
.bLength
+ (usbosd
.bNumDeviceCaps
* 2))) {
3039 XPRINTF(1, ("Invalid BOS descriptor wTotalLength!\n"));
3043 XPRINTF(1, ("GET_DESCRIPTOR (5) failed %ld!\n", ioerr_bos
));
3048 if(usdd
.iManufacturer
) {
3049 pd
->pd_MnfctrStr
= psdGetStringDescriptor(pp
, usdd
.iManufacturer
);
3053 pd
->pd_ProductStr
= psdGetStringDescriptor(pp
, usdd
.iProduct
);
3056 if(usdd
.iSerialNumber
) {
3057 pd
->pd_SerNumStr
= psdGetStringDescriptor(pp
, usdd
.iSerialNumber
);
3060 if(!pd
->pd_MnfctrStr
) {
3061 pd
->pd_MnfctrStr
= psdCopyStr(vendorname
? vendorname
: (STRPTR
) "n/a");
3064 if(!pd
->pd_ProductStr
) {
3065 hasprodname
= FALSE
;
3066 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) pd
->pd_DevClass
, NULL
);
3068 pd
->pd_ProductStr
= psdCopyStrFmt("%s: Vdr=%04lx/PID=%04lx", classname
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3070 pd
->pd_ProductStr
= psdCopyStrFmt("Cls=%ld/Vdr=%04lx/PID=%04lx", pd
->pd_DevClass
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3076 if(!pd
->pd_SerNumStr
) {
3077 pd
->pd_SerNumStr
= psdCopyStr("n/a");
3080 KPRINTF(2, ("Product : %s\n"
3081 "Manufacturer: %s\n"
3082 "SerialNumber: %s\n",
3083 pd
->pd_ProductStr
, pd
->pd_MnfctrStr
, pd
->pd_SerNumStr
));
3084 KPRINTF(2, ("USBVersion: %04lx\n"
3090 "DevVers : %04lx\n",
3091 pd
->pd_USBVers
, pd
->pd_DevClass
, pd
->pd_DevSubClass
, pd
->pd_DevProto
,
3092 pd
->pd_VendorID
, pd
->pd_ProductID
, pd
->pd_DevVers
));
3094 /* check for clones */
3096 while((itpd
= psdGetNextDevice(itpd
)))
3100 if((itpd
->pd_ProductID
== pd
->pd_ProductID
) &&
3101 (itpd
->pd_VendorID
== pd
->pd_VendorID
) &&
3102 (!strcmp(itpd
->pd_SerNumStr
, pd
->pd_SerNumStr
)) &&
3103 (itpd
->pd_CloneCount
== pd
->pd_CloneCount
))
3105 pd
->pd_CloneCount
++;
3111 pd
->pd_IDString
= psdCopyStrFmt("%s-%04lx-%04lx-%s-%02lx", pd
->pd_ProductStr
, pd
->pd_VendorID
, pd
->pd_ProductID
, pd
->pd_SerNumStr
, pd
->pd_CloneCount
);
3113 pStripString(ps
, pd
->pd_MnfctrStr
);
3114 pStripString(ps
, pd
->pd_ProductStr
);
3115 pStripString(ps
, pd
->pd_SerNumStr
);
3117 /* get custom name of device */
3118 pLockSemExcl(ps
, &ps
->ps_ConfigLock
); // Exclusive lock to avoid deadlock situation when promoting read to write
3119 pd
->pd_OldProductStr
= pd
->pd_ProductStr
;
3120 pd
->pd_ProductStr
= NULL
;
3121 haspopupinhibit
= FALSE
;
3122 pic
= psdGetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
);
3125 pd
->pd_IsNewToMe
= FALSE
;
3126 if((pd
->pd_ProductStr
= pGetStringChunk(ps
, pic
, IFFCHNK_NAME
)))
3130 if((chnk
= pFindCfgChunk(ps
, pic
, IFFCHNK_POPUP
)))
3132 struct PsdPoPoCfg
*poc
= (struct PsdPoPoCfg
*) chnk
;
3133 CopyMem(((UBYTE
*) poc
) + 8, ((UBYTE
*) &pd
->pd_PoPoCfg
) + 8, min(AROS_LONG2BE(poc
->poc_Length
), AROS_LONG2BE(pd
->pd_PoPoCfg
.poc_Length
)));
3134 haspopupinhibit
= TRUE
;
3137 pd
->pd_IsNewToMe
= TRUE
;
3138 psdSetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
, NULL
);
3140 if(!pd
->pd_ProductStr
)
3142 pd
->pd_ProductStr
= psdCopyStr(pd
->pd_OldProductStr
);
3144 if(!haspopupinhibit
)
3146 if(pd
->pd_DevClass
== HUB_CLASSCODE
) // hubs default to true
3148 pd
->pd_PoPoCfg
.poc_InhibitPopup
= TRUE
;
3151 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
3153 pd
->pd_NumCfgs
= usdd
.bNumConfigurations
;
3154 KPRINTF(10, ("Device has %ld different configurations\n", pd
->pd_NumCfgs
));
3156 if(pGetDevConfig(pp
))
3159 if(pd
->pd_Configs
.lh_Head
->ln_Succ
)
3161 cfgnum
= ((struct PsdConfig
*) pd
->pd_Configs
.lh_Head
)->pc_CfgNum
;
3163 psdSetDeviceConfig(pp
, cfgnum
); /* *** FIXME *** Workaround for USB2.0 devices */
3167 devclass
= pd
->pd_DevClass
;
3168 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
3169 while(pc
->pc_Node
.ln_Succ
)
3171 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3172 while(pif
->pif_Node
.ln_Succ
)
3174 if(pif
->pif_IfClass
)
3178 devclass
= pif
->pif_IfClass
;
3180 if(devclass
!= pif
->pif_IfClass
)
3187 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3189 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
3193 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) devclass
, NULL
);
3196 psdFreeVec(pd
->pd_ProductStr
);
3199 pd
->pd_ProductStr
= psdCopyStrFmt("%s (%s/%04lx)",
3200 classname
, vendorname
, pd
->pd_ProductID
);
3202 pd
->pd_ProductStr
= psdCopyStrFmt("%s (%04lx/%04lx)",
3203 classname
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3208 pFixBrokenConfig(pp
);
3209 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3210 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3211 psdUnlockDevice(pd
);
3212 psdCalculatePower(pd
->pd_Hardware
);
3215 KPRINTF(15, ("SetDeviceConfig(1) failed\n"));
3218 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3219 "Could not acquire device configuration for %s",
3220 pd
->pd_ProductStr
? pd
->pd_ProductStr
: (STRPTR
) "new device");
3221 KPRINTF(15, ("GetDevConfig() failed\n"));
3223 /* Although the device failed to configure fully, maybe
3224 some firmware will able to use this device anyway? */
3225 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3226 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3227 psdUnlockDevice(pd
);
3230 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3231 "GET_DESCRIPTOR (len 18) failed: %s (%ld)",
3232 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3233 KPRINTF(15, ("GET_DESCRIPTOR (18) failed %ld!\n", ioerr
));
3236 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
3237 "SET_ADDRESS failed: %s (%ld)",
3238 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3239 KPRINTF(15, ("SET_ADDRESS failed %ld!\n", ioerr
));
3241 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3242 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3244 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "This cannot happen! More than 127 devices on the bus???");
3245 KPRINTF(20, ("out of addresses???\n"));
3248 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Device enumeration failed, sorry.");
3249 psdUnlockDevice(pd
);
3255 /* /// "psdGetNextDevice()" */
3256 AROS_LH1(struct PsdDevice
*, psdGetNextDevice
,
3257 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3258 LIBBASETYPEPTR
, ps
, 21, psd
)
3261 struct PsdHardware
*phw
;
3263 KPRINTF(1, ("psdGetNextDevice(%p)\n", pd
));
3266 /* Is there another device node in the current hardware? */
3267 if(pd
->pd_Node
.ln_Succ
->ln_Succ
)
3269 return((struct PsdDevice
*) pd
->pd_Node
.ln_Succ
);
3271 /* No, then check if there's another hardware to scan */
3272 phw
= (struct PsdHardware
*) pd
->pd_Hardware
->phw_Node
.ln_Succ
;
3274 /* No context, start with first hardware */
3275 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
3277 while(phw
->phw_Node
.ln_Succ
)
3279 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3280 /* Is this an valid entry, or is the list empty? */
3281 if(pd
->pd_Node
.ln_Succ
)
3285 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
3287 /* End of list reached */
3293 /* /// "psdSuspendBindings()" */
3294 AROS_LH1(BOOL
, psdSuspendBindings
,
3295 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3296 LIBBASETYPEPTR
, ps
, 100, psd
)
3299 struct PsdUsbClass
*puc
;
3300 struct PsdConfig
*pc
;
3301 struct PsdInterface
*pif
;
3306 KPRINTF(5, ("psdSuspendBindings(%p)\n", pd
));
3309 if(ps
->ps_GlobalCfg
->pgc_ForceSuspend
&& (pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
))
3313 // ask existing bindings to go to suspend first -- if they don't support it, break off
3314 if(pd
->pd_DevBinding
)
3316 if(pd
->pd_Flags
& PDFF_APPBINDING
)
3320 // can't suspend application binding devices
3321 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3322 "Cannot suspend with application binding on '%s'.",
3326 psdReleaseDevBinding(pd
);
3328 if((puc
= pd
->pd_ClsBinding
))
3331 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
3334 res
= usbDoMethod(UCM_AttemptSuspendDevice
, pd
->pd_DevBinding
);
3337 // didn't want to suspend
3338 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3339 "Class '%s' failed to suspend device '%s'.",
3340 puc
->puc_Node
.ln_Name
, pd
->pd_ProductStr
);
3344 if(pd
->pd_IOBusyCount
)
3348 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3349 "Class '%s' does not support suspending.",
3350 puc
->puc_Node
.ln_Name
);
3353 psdReleaseDevBinding(pd
);
3356 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3357 "Class '%s' does not support suspending, but has no active IO. Suspending anyway.",
3358 puc
->puc_Node
.ln_Name
);
3363 pc
= pd
->pd_CurrentConfig
;
3364 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3365 while(pif
->pif_Node
.ln_Succ
)
3367 if(pif
->pif_IfBinding
)
3369 if((puc
= pif
->pif_ClsBinding
))
3372 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
3375 res
= usbDoMethod(UCM_AttemptSuspendDevice
, pif
->pif_IfBinding
);
3378 // didn't want to suspend
3379 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3380 "%s failed to suspend device '%s'.",
3381 puc
->puc_Node
.ln_Name
, pd
->pd_ProductStr
);
3385 if(pd
->pd_IOBusyCount
)
3390 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3391 "%s does not support suspending.",
3392 puc
->puc_Node
.ln_Name
);
3395 psdReleaseIfBinding(pif
);
3398 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3399 "%s does not support suspending, but has no active IO. Suspending anyway.",
3400 puc
->puc_Node
.ln_Name
);
3405 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3414 /* /// "psdSuspendDevice()" */
3415 AROS_LH1(BOOL
, psdSuspendDevice
,
3416 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3417 LIBBASETYPEPTR
, ps
, 98, psd
)
3420 struct PsdUsbClass
*puc
;
3421 struct PsdDevice
*hubpd
;
3425 KPRINTF(5, ("psdSuspendDevice(%p)\n", pd
));
3428 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
3433 if(!hubpd
) // suspend root hub
3435 // suspend whole USB, using the HCI UHCMD_USBSUSPEND command
3436 // FIXME currently unsupported!
3437 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Suspending of root hub currently not supported.");
3441 psdLockWriteDevice(pd
);
3442 res
= psdSuspendBindings(pd
);
3443 psdUnlockDevice(pd
);
3446 psdLockReadDevice(pd
);
3447 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
3449 res
= usbDoMethod(UCM_HubSuspendDevice
, binding
, pd
);
3451 psdUnlockDevice(pd
);
3456 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3457 "Suspending of device '%s' failed.",
3465 /* /// "psdResumeBindings()" */
3466 AROS_LH1(BOOL
, psdResumeBindings
,
3467 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3468 LIBBASETYPEPTR
, ps
, 101, psd
)
3471 struct PsdUsbClass
*puc
;
3472 struct PsdConfig
*pc
;
3473 struct PsdInterface
*pif
;
3475 BOOL rescan
= FALSE
;
3477 KPRINTF(5, ("psdResumeBindings(%p)\n", pd
));
3480 // ask existing bindings to resume -- if they don't support it, rebind
3481 if(pd
->pd_DevBinding
)
3483 if(!(pd
->pd_Flags
& PDFF_APPBINDING
))
3485 if((puc
= pd
->pd_ClsBinding
))
3487 res
= usbDoMethod(UCM_AttemptResumeDevice
, pd
->pd_DevBinding
);
3490 // if the device couldn't resume, better get rid of the binding
3491 psdReleaseDevBinding(pd
);
3497 pc
= pd
->pd_CurrentConfig
;
3498 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3499 while(pif
->pif_Node
.ln_Succ
)
3501 if(pif
->pif_IfBinding
)
3503 if((puc
= pif
->pif_ClsBinding
))
3505 res
= usbDoMethod(UCM_AttemptResumeDevice
, pif
->pif_IfBinding
);
3508 // didn't want to suspend
3509 psdReleaseIfBinding(pif
);
3515 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3527 /* /// "psdResumeDevice()" */
3528 AROS_LH1(BOOL
, psdResumeDevice
,
3529 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3530 LIBBASETYPEPTR
, ps
, 99, psd
)
3533 struct PsdUsbClass
*puc
;
3534 struct PsdDevice
*hubpd
;
3538 KPRINTF(5, ("psdResumeDevice(%p)\n", pd
));
3541 if(!(pd
->pd_Flags
& PDFF_SUSPENDED
))
3546 if(!hubpd
) // resume root hub
3548 // resume whole USB, using the HCI UHCMD_USBRESUME command
3549 // FIXME currently unsupported!
3552 psdLockWriteDevice(pd
);
3553 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
3555 res
= usbDoMethod(UCM_HubResumeDevice
, binding
, pd
);
3557 psdUnlockDevice(pd
);
3561 psdResumeBindings(pd
);
3570 /* /// "psdFindDeviceA()" */
3571 AROS_LH2(struct PsdDevice
*, psdFindDeviceA
,
3572 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3573 AROS_LHA(struct TagItem
*, tags
, A1
),
3574 LIBBASETYPEPTR
, ps
, 44, psd
)
3579 KPRINTF(2, ("psdFindDeviceA(%p, %p)\n", pd
, tags
));
3580 while((pd
= psdGetNextDevice(pd
)))
3583 if((ti
= FindTagItem(DA_ProductID
, tags
)))
3585 if(ti
->ti_Data
!= pd
->pd_ProductID
)
3590 if((ti
= FindTagItem(DA_VendorID
, tags
)))
3592 if(ti
->ti_Data
!= pd
->pd_VendorID
)
3597 if((ti
= FindTagItem(DA_Class
, tags
)))
3599 if(ti
->ti_Data
!= pd
->pd_DevClass
)
3604 if((ti
= FindTagItem(DA_SubClass
, tags
)))
3606 if(ti
->ti_Data
!= pd
->pd_DevSubClass
)
3611 if((ti
= FindTagItem(DA_Protocol
, tags
)))
3613 if(ti
->ti_Data
!= pd
->pd_DevProto
)
3618 if((ti
= FindTagItem(DA_Version
, tags
)))
3620 if(ti
->ti_Data
!= pd
->pd_DevVers
)
3625 if((ti
= FindTagItem(DA_SerialNumber
, tags
)))
3627 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_SerNumStr
))
3632 if((ti
= FindTagItem(DA_ProductName
, tags
)))
3634 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_ProductStr
))
3639 if((ti
= FindTagItem(DA_Manufacturer
, tags
)))
3641 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_MnfctrStr
))
3646 if((ti
= FindTagItem(DA_IDString
, tags
)))
3648 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_IDString
))
3653 if((ti
= FindTagItem(DA_Binding
, tags
)))
3655 if(ti
->ti_Data
!= (IPTR
) pd
->pd_DevBinding
)
3660 if((ti
= FindTagItem(DA_HubDevice
, tags
)))
3662 if(ti
->ti_Data
!= (IPTR
) pd
->pd_Hub
)
3678 /* *** Hardware *** */
3680 /* /// "pFindHardware()" */
3681 struct PsdHardware
* pFindHardware(LIBBASETYPEPTR ps
, STRPTR name
, ULONG unit
)
3683 struct PsdHardware
*phw
;
3687 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
3688 while(phw
->phw_Node
.ln_Succ
)
3690 if((phw
->phw_Unit
== unit
) && (!strcmp(phw
->phw_DevName
, name
)))
3695 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
3699 if((*name
== '/') || (*name
== ':'))
3711 /* /// "psdEnumerateHardware()" */
3712 AROS_LH1(struct PsdDevice
*, psdEnumerateHardware
,
3713 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3714 LIBBASETYPEPTR
, ps
, 14, psd
)
3717 struct PsdDevice
*pd
= NULL
;
3720 #ifdef AROS_USB30_CODE
3723 KPRINTF(2, ("psdEnumerateHardware(%p)\n", phw
));
3725 if((mp
= CreateMsgPort()))
3728 if((pd
= psdAllocDevice(phw
)))
3731 if((pp
= psdAllocPipe(pd
, mp
, NULL
)))
3733 //pp->pp_IOReq.iouh_Flags |= UHFF_NAKTIMEOUT;
3734 //pp->pp_IOReq.iouh_NakTimeout = 1000;
3735 pd
->pd_Flags
|= PDFF_CONNECTED
;
3737 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_USBRESET
;
3738 #ifdef AROS_USB30_CODE
3739 ioerr
= psdDoPipe(pp
, NULL
, 0);
3740 if(ioerr
== UHIOERR_HOSTERROR
) {
3741 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "UHCMD_USBRESET reset failed.");
3743 pFreeBindings(ps
, pd
);
3744 pFreeDevice(ps
, pd
);
3749 psdDoPipe(pp
, NULL
, 0);
3751 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
3752 psdDelayMS(100); // wait for root hub to settle
3753 if(psdEnumerateDevice(pp
))
3755 KPRINTF(1, ("Enumeration finished!\n"));
3756 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Root hub has been enumerated.");
3759 phw
->phw_RootDevice
= pd
;
3760 psdSendEvent(EHMB_ADDDEVICE
, pd
, NULL
);
3765 pFreeBindings(ps
, pd
);
3766 pFreeDevice(ps
, pd
);
3772 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Root hub enumeration failed. Blame your hardware driver programmer.");
3778 /* /// "psdRemHardware()" */
3779 AROS_LH1(void, psdRemHardware
,
3780 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3781 LIBBASETYPEPTR
, ps
, 13, psd
)
3784 struct PsdDevice
*pd
;
3787 KPRINTF(5, ("FreeHardware(%p)\n", phw
));
3789 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3790 while(pd
->pd_Node
.ln_Succ
)
3792 pFreeBindings(ps
, pd
);
3793 pFreeDevice(ps
, pd
);
3794 psdSendEvent(EHMB_REMDEVICE
, pd
, NULL
);
3795 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3798 pd
= (struct PsdDevice
*) phw
->phw_DeadDevices
.lh_Head
;
3799 while(pd
->pd_Node
.ln_Succ
)
3803 KPRINTF(20, ("Can't remove device, usecnt %ld\n", pd
->pd_UseCnt
));
3806 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3807 "Can't remove device '%s', there are still %ld pipes in use...",
3808 pd
->pd_ProductStr
, pd
->pd_UseCnt
);
3812 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3813 "Okay, going down with device '%s' anyway, maybe the driver crashed?",
3821 pFreeDevice(ps
, pd
);
3822 //psdSendEvent(EHMB_REMDEVICE, pd, NULL);
3824 pd
= (struct PsdDevice
*) phw
->phw_DeadDevices
.lh_Head
;
3828 /* Note that the subtask unlinks the hardware! */
3829 phw
->phw_ReadySignal
= SIGB_SINGLE
;
3830 phw
->phw_ReadySigTask
= FindTask(NULL
);
3833 Signal(phw
->phw_Task
, SIGBREAKF_CTRL_C
);
3836 while(phw
->phw_Task
)
3838 Wait(1L<<phw
->phw_ReadySignal
);
3840 //FreeSignal(phw->phw_ReadySignal);
3841 KPRINTF(1, ("FreeHardware(%p) freevec name\n", phw
));
3842 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3843 "Removed hardware %s/%ld. Bye bye!",
3844 phw
->phw_DevName
, phw
->phw_Unit
);
3845 psdFreeVec(phw
->phw_DevName
);
3846 psdFreeVec(phw
->phw_ProductName
);
3847 psdFreeVec(phw
->phw_Manufacturer
);
3848 psdFreeVec(phw
->phw_Description
);
3849 psdFreeVec(phw
->phw_Copyright
);
3851 psdSendEvent(EHMB_REMHARDWARE
, phw
, NULL
);
3852 KPRINTF(1, ("FreeHardware(%p) done\n", phw
));
3857 /* /// "psdAddHardware()" */
3858 AROS_LH2(struct PsdHardware
*,psdAddHardware
,
3859 AROS_LHA(STRPTR
, name
, A0
),
3860 AROS_LHA(ULONG
, unit
, D0
),
3861 LIBBASETYPEPTR
, ps
, 12, psd
)
3864 struct PsdHardware
*phw
;
3866 struct Task
*tmptask
;
3867 KPRINTF(5, ("psdAddHardware(%s, %ld)\n", name
, unit
));
3869 if((phw
= psdAllocVec(sizeof(struct PsdHardware
))))
3871 NewList(&phw
->phw_Devices
);
3872 NewList(&phw
->phw_DeadDevices
);
3873 phw
->phw_Unit
= unit
;
3875 if((phw
->phw_Node
.ln_Name
= phw
->phw_DevName
= psdCopyStr(name
)))
3877 psdSafeRawDoFmt(buf
, 64, "usbhw<%s/%ld>", name
, unit
);
3878 phw
->phw_ReadySignal
= SIGB_SINGLE
;
3879 phw
->phw_ReadySigTask
= FindTask(NULL
);
3880 SetSignal(0, SIGF_SINGLE
); // clear single bit
3881 if((tmptask
= psdSpawnSubTask(buf
, pDeviceTask
, phw
)))
3883 psdBorrowLocksWait(tmptask
, 1UL<<phw
->phw_ReadySignal
);
3886 phw
->phw_ReadySigTask
= NULL
;
3887 //FreeSignal(phw->phw_ReadySignal);
3888 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3889 "New hardware %s/%ld added (%s).",
3892 phw
->phw_ProductName
);
3893 psdSendEvent(EHMB_ADDHARDWARE
, phw
, NULL
);
3897 phw
->phw_ReadySigTask
= NULL
;
3898 //FreeSignal(phw->phw_ReadySignal);
3899 psdFreeVec(phw
->phw_DevName
);
3908 /* /// "psdCalculatePower()" */
3909 AROS_LH1(void, psdCalculatePower
,
3910 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3911 LIBBASETYPEPTR
, ps
, 78, psd
)
3914 struct PsdDevice
*roothub
= NULL
;
3915 struct PsdDevice
*pd
;
3919 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3920 while(pd
->pd_Node
.ln_Succ
)
3927 pd
= (struct PsdDevice
*) pd
->pd_Node
.ln_Succ
;
3934 roothub
->pd_PowerDrain
= 0;
3935 roothub
->pd_PowerSupply
= 500;
3937 /* calculate drain */
3938 pPowerRecurseDrain(ps
, roothub
);
3940 /* calculate supply */
3941 pPowerRecurseSupply(ps
, roothub
);
3949 /* /// "psdAllocPipe()" */
3950 AROS_LH3(struct PsdPipe
*, psdAllocPipe
,
3951 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3952 AROS_LHA(struct MsgPort
*, mp
, A1
),
3953 AROS_LHA(struct PsdEndpoint
*, pep
, A2
),
3954 LIBBASETYPEPTR
, ps
, 24, psd
)
3958 struct PsdDevice
*hubpd
;
3960 KPRINTF(2, ("psdAllocPipe(%p, %p, %p)\n", pd
, mp
, pep
));
3965 if(pep
&& (pep
->pep_TransType
== USEAF_ISOCHRONOUS
) && (!(pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Capabilities
& UHCF_ISO
)))
3967 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Your HW controller driver does not support iso transfers. Sorry.");
3971 if((pp
= psdAllocVec(sizeof(struct PsdPipe
))))
3973 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
3974 pp
->pp_MsgPort
= pp
->pp_Msg
.mn_ReplyPort
= mp
;
3975 pp
->pp_Msg
.mn_Length
= sizeof(struct PsdPipe
);
3977 pp
->pp_Endpoint
= pep
;
3978 pp
->pp_IOReq
= *(pd
->pd_Hardware
->phw_RootIOReq
);
3979 pp
->pp_IOReq
.iouh_DevAddr
= pd
->pd_DevAddr
;
3980 if(pd
->pd_Flags
& PDFF_LOWSPEED
)
3982 pp
->pp_IOReq
.iouh_Flags
|= UHFF_LOWSPEED
;
3984 if(pd
->pd_Flags
& PDFF_HIGHSPEED
)
3986 pp
->pp_IOReq
.iouh_Flags
|= UHFF_HIGHSPEED
;
3989 switch(pep
->pep_NumTransMuFr
)
3992 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_2
;
3995 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_3
;
3999 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_1
;
4002 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_1
;
4005 #ifdef AROS_USB30_CODE
4006 if(pd
->pd_Flags
& PDFF_SUPERSPEED
)
4008 pp
->pp_IOReq
.iouh_Flags
|= UHFF_SUPERSPEED
;
4011 if(pd
->pd_Flags
& PDFF_NEEDSSPLIT
)
4013 /* USB1.1 device connected to a USB2.0 hub */
4014 pp
->pp_IOReq
.iouh_Flags
|= UHFF_SPLITTRANS
;
4016 pp
->pp_IOReq
.iouh_SplitHubPort
= pd
->pd_HubPort
;
4017 // find the root USB 2.0 hub in the tree
4018 while(hubpd
&& !(hubpd
->pd_Flags
& PDFF_HIGHSPEED
))
4020 pp
->pp_IOReq
.iouh_SplitHubPort
= hubpd
->pd_HubPort
;
4021 hubpd
= hubpd
->pd_Hub
;
4025 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Internal error obtaining split transaction hub!");
4029 pp
->pp_IOReq
.iouh_Flags
|= (hubpd
->pd_HubThinkTime
<<UHFS_THINKTIME
);
4030 pp
->pp_IOReq
.iouh_SplitHubAddr
= hubpd
->pd_DevAddr
;
4034 switch(pep
->pep_TransType
)
4037 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
4039 case USEAF_ISOCHRONOUS
:
4040 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_ISOXFER
;
4043 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_BULKXFER
;
4045 case USEAF_INTERRUPT
:
4046 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_INTXFER
;
4049 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4050 "AllocPipe(): Illegal transfer type %ld",
4051 pep
->pep_TransType
);
4052 KPRINTF(20, ("Illegal transfer type for endpoint!"));
4057 pp
->pp_IOReq
.iouh_Dir
= (pep
->pep_Direction
? UHDIR_IN
: UHDIR_OUT
);
4058 pp
->pp_IOReq
.iouh_Endpoint
= pep
->pep_EPNum
;
4059 pp
->pp_IOReq
.iouh_MaxPktSize
= pep
->pep_MaxPktSize
;
4060 pp
->pp_IOReq
.iouh_Interval
= pep
->pep_Interval
;
4062 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
4063 pp
->pp_IOReq
.iouh_Dir
= UHDIR_SETUP
;
4064 pp
->pp_IOReq
.iouh_Endpoint
= 0;
4065 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
;
4075 /* /// "psdFreePipe()" */
4076 AROS_LH1(void, psdFreePipe
,
4077 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4078 LIBBASETYPEPTR
, ps
, 25, psd
)
4081 struct PsdDevice
*pd
;
4086 KPRINTF(2, ("psdFreePipe(%p)\n", pp
));
4089 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4091 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4092 "Tried to free pipe on %s that was still pending!", pd
->pd_ProductStr
);
4097 if(!(--pd
->pd_UseCnt
) && (pd
->pd_Flags
& PDFF_DELEXPUNGE
))
4099 KPRINTF(20, ("Finally getting rid of device %s\n", pd
->pd_ProductStr
));
4100 pFreeDevice(ps
, pd
);
4101 //psdSendEvent(EHMB_REMDEVICE, pd, NULL);
4109 /* /// "psdPipeSetup()" */
4110 AROS_LH5(void, psdPipeSetup
,
4111 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4112 AROS_LHA(UWORD
, rt
, D0
),
4113 AROS_LHA(UWORD
, rq
, D1
),
4114 AROS_LHA(UWORD
, val
, D2
),
4115 AROS_LHA(UWORD
, idx
, D3
),
4116 LIBBASETYPEPTR
, ps
, 26, psd
)
4119 struct UsbSetupData
*usd
= &pp
->pp_IOReq
.iouh_SetupData
;
4121 KPRINTF(1, ("psdSetupPipe(%p, (%02lx %02lx %04lx %04lx))\n",
4122 pp
, rt
, rq
, val
, idx
));
4123 usd
->bmRequestType
= rt
;
4125 usd
->wValue
= AROS_WORD2LE(val
);
4126 usd
->wIndex
= AROS_WORD2LE(idx
);
4131 /* /// "psdDoPipe()" */
4132 AROS_LH3(LONG
, psdDoPipe
,
4133 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4134 AROS_LHA(APTR
, data
, A0
),
4135 AROS_LHA(ULONG
, len
, D0
),
4136 LIBBASETYPEPTR
, ps
, 27, psd
)
4139 struct PsdDevice
*pd
= pp
->pp_Device
;
4140 KPRINTF(200, ("psdDoPipe(%p, %p, %ld)\n", pp
, data
, len
));
4142 if(pd
->pd_Flags
& PDFF_CONNECTED
)
4144 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
4146 // make sure the device is up and running before trying to send a new pipe
4147 psdResumeDevice(pd
);
4150 pp
->pp_IOReq
.iouh_Data
= data
;
4151 pp
->pp_IOReq
.iouh_Length
= len
;
4152 if(!pp
->pp_Endpoint
)
4154 pp
->pp_IOReq
.iouh_SetupData
.wLength
= AROS_WORD2LE(len
);
4156 PutMsg(&pd
->pd_Hardware
->phw_TaskMsgPort
, &pp
->pp_Msg
);
4157 ++pd
->pd_IOBusyCount
;
4158 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4159 return(psdWaitPipe(pp
));
4162 pp
->pp_IOReq
.iouh_Actual
= 0;
4163 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
4164 return(pp
->pp_IOReq
.iouh_Req
.io_Error
= UHIOERR_TIMEOUT
);
4170 /* /// "psdSendPipe()" */
4171 AROS_LH3(void, psdSendPipe
,
4172 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4173 AROS_LHA(APTR
, data
, A0
),
4174 AROS_LHA(ULONG
, len
, D0
),
4175 LIBBASETYPEPTR
, ps
, 28, psd
)
4178 struct PsdDevice
*pd
= pp
->pp_Device
;
4179 KPRINTF(200, ("psdSendPipe(%p, %p, %ld)\n", pp
, data
, len
));
4180 if(pd
->pd_Flags
& PDFF_CONNECTED
)
4182 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
4184 // make sure the device is up and running before trying to send a new pipe
4185 psdResumeDevice(pd
);
4188 pp
->pp_IOReq
.iouh_Data
= data
;
4189 pp
->pp_IOReq
.iouh_Length
= len
;
4190 if(!pp
->pp_Endpoint
)
4192 pp
->pp_IOReq
.iouh_SetupData
.wLength
= AROS_WORD2LE(len
);
4194 PutMsg(&pd
->pd_Hardware
->phw_TaskMsgPort
, &pp
->pp_Msg
);
4195 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4196 ++pd
->pd_IOBusyCount
;
4199 pp
->pp_IOReq
.iouh_Actual
= 0;
4200 //pp->pp_Msg.mn_Node.ln_Type = NT_REPLYMSG;
4201 pp
->pp_IOReq
.iouh_Req
.io_Error
= UHIOERR_TIMEOUT
;
4202 ReplyMsg(&pp
->pp_Msg
);
4203 ++pd
->pd_IOBusyCount
;
4209 /* /// "psdAbortPipe()" */
4210 AROS_LH1(void, psdAbortPipe
,
4211 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4212 LIBBASETYPEPTR
, ps
, 29, psd
)
4215 struct PsdPipe
*npp
;
4217 KPRINTF(5, ("psdAbortPipe(%p)\n", pp
));
4218 if(pp
->pp_Msg
.mn_Node
.ln_Type
!= NT_MESSAGE
)
4220 KPRINTF(5, ("Nothing to abort %02lx\n", pp
->pp_IOReq
.iouh_Req
.io_Message
.mn_Node
.ln_Type
));
4223 if((npp
= psdAllocVec(sizeof(struct PsdPipe
))))
4225 //npp->pp_Msg.mn_Node.ln_Type = NT_MESSAGE;
4226 npp
->pp_Device
= pp
->pp_Device
;
4227 npp
->pp_MsgPort
= npp
->pp_Msg
.mn_ReplyPort
= pp
->pp_MsgPort
;
4228 npp
->pp_Msg
.mn_Length
= sizeof(struct PsdPipe
);
4230 npp
->pp_AbortPipe
= pp
;
4231 PutMsg(&pp
->pp_Device
->pd_Hardware
->phw_TaskMsgPort
, &npp
->pp_Msg
);
4239 /* /// "psdWaitPipe()" */
4240 AROS_LH1(LONG
, psdWaitPipe
,
4241 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4242 LIBBASETYPEPTR
, ps
, 30, psd
)
4246 struct PsdDevice
*pd
= pp
->pp_Device
;
4248 KPRINTF(5, ("psdWaitPipe(%p)\n", pp
));
4249 while(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4251 KPRINTF(5, ("ln_Type = %02lx\n", pp
->pp_Msg
.mn_Node
.ln_Type
));
4252 sigs
|= Wait(1L<<pp
->pp_MsgPort
->mp_SigBit
);
4253 KPRINTF(5, ("sigs = %p\n", sigs
));
4257 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_REPLYMSG
)
4259 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
4260 Remove(&pp
->pp_Msg
.mn_Node
);
4262 //if(pp->pp_MsgPort->mp_MsgList.lh_Head->ln_Succ)
4264 // avoid signals getting lost for other messages arriving.
4265 SetSignal(sigs
, sigs
);
4270 Remove(&pp
->pp_Msg
.mn_Node
);
4273 ioerr
= pp
->pp_IOReq
.iouh_Req
.io_Error
;
4276 case UHIOERR_TIMEOUT
:
4279 case UHIOERR_NAKTIMEOUT
:
4281 case UHIOERR_CRCERROR
:
4284 case UHIOERR_RUNTPACKET
:
4286 if(pd
->pd_DeadCount
)
4288 pd
->pd_DeadCount
>>= 1;
4289 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4290 "Device %s starts recovering with %s (%ld)!",
4292 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);*/
4295 KPRINTF(200, ("psdWaitPipe(%p)=%ld\n", pp
, ioerr
));
4296 --pd
->pd_IOBusyCount
;
4297 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4299 if((pd
->pd_DeadCount
> 19) || ((pd
->pd_DeadCount
> 14) && (pd
->pd_Flags
& (PDFF_HASDEVADDR
|PDFF_HASDEVDESC
))))
4301 if(!(pd
->pd_Flags
& PDFF_DEAD
))
4303 pd
->pd_Flags
|= PDFF_DEAD
;
4304 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4305 "Device %s probably dropped dead!", pd
->pd_ProductStr
);
4307 psdSendEvent(EHMB_DEVICEDEAD
, pp
->pp_Device
, NULL
);
4310 if((!pd
->pd_DeadCount
) && ((pd
->pd_Flags
& (PDFF_DEAD
|PDFF_CONNECTED
)) == (PDFF_DEAD
|PDFF_CONNECTED
)))
4312 pd
->pd_Flags
&= ~PDFF_DEAD
;
4313 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4314 "Uuuhuuuhh, the zombie %s returned from the dead!", pd
->pd_ProductStr
);
4322 /* /// "psdCheckPipe()" */
4323 AROS_LH1(struct PsdPipe
*, psdCheckPipe
,
4324 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4325 LIBBASETYPEPTR
, ps
, 71, psd
)
4328 KPRINTF(5, ("psdCheckPipe(%p)\n", pp
));
4329 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4338 /* /// "psdGetPipeActual()" */
4339 AROS_LH1(ULONG
, psdGetPipeActual
,
4340 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4341 LIBBASETYPEPTR
, ps
, 31, psd
)
4344 KPRINTF(1, ("psdGetPipeActual(%p)\n", pp
));
4345 return(pp
->pp_IOReq
.iouh_Actual
);
4350 /* /// "psdGetPipeError()" */
4351 AROS_LH1(LONG
, psdGetPipeError
,
4352 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4353 LIBBASETYPEPTR
, ps
, 32, psd
)
4356 KPRINTF(1, ("psdGetPipeError(%p)\n", pp
));
4357 return((LONG
) pp
->pp_IOReq
.iouh_Req
.io_Error
);
4362 /* *** Streams *** */
4364 /* /// "psdOpenStreamA()" */
4365 AROS_LH2(struct PsdPipeStream
*, psdOpenStreamA
,
4366 AROS_LHA(struct PsdEndpoint
*, pep
, A0
),
4367 AROS_LHA(struct TagItem
*, tags
, A1
),
4368 LIBBASETYPEPTR
, ps
, 72, psd
)
4371 struct PsdPipeStream
*pps
;
4373 KPRINTF(2, ("psdOpenStream(%p, %p)\n", pep
, tags
));
4378 if((pps
= psdAllocVec(sizeof(struct PsdPipeStream
))))
4380 pps
->pps_Device
= pep
->pep_Interface
->pif_Config
->pc_Device
;
4381 pps
->pps_Endpoint
= pep
;
4382 NewList(&pps
->pps_FreePipes
);
4383 NewList(&pps
->pps_ReadyPipes
);
4384 InitSemaphore(&pps
->pps_AccessLock
);
4385 pps
->pps_NakTimeoutTime
= 5000;
4386 if(pep
->pep_Direction
)
4388 /* Defaults for IN */
4389 pps
->pps_NumPipes
= 4;
4390 pps
->pps_Flags
= PSFF_READAHEAD
|PSFF_BUFFERREAD
|PSFF_ALLOWRUNT
;
4391 pps
->pps_BufferSize
= 32*pps
->pps_Endpoint
->pep_MaxPktSize
;
4393 /* Defaults for OUT */
4394 pps
->pps_NumPipes
= 4;
4395 pps
->pps_Flags
= PSFF_NOSHORTPKT
;
4396 pps
->pps_BufferSize
= 4*pps
->pps_Endpoint
->pep_MaxPktSize
;
4399 psdSetAttrsA(PGA_PIPESTREAM
, pps
, tags
);
4402 psdCloseStream(pps
);
4412 /* /// "psdCloseStream()" */
4413 AROS_LH1(void, psdCloseStream
,
4414 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4415 LIBBASETYPEPTR
, ps
, 73, psd
)
4421 KPRINTF(2, ("psdCloseStream(%p)\n", pps
));
4426 psdStreamFlush(pps
);
4427 ObtainSemaphore(&pps
->pps_AccessLock
);
4430 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
4432 pp
= pps
->pps_Pipes
[cnt
];
4433 //if(pp->pp_IOReq.iouh_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
4435 KPRINTF(1, ("Abort %ld\n", cnt
));
4437 KPRINTF(1, ("Wait %ld\n", cnt
));
4440 KPRINTF(1, ("Free %ld\n", cnt
));
4443 psdFreeVec(pps
->pps_Pipes
);
4444 if((pps
->pps_Flags
& PSFF_OWNMSGPORT
) && pps
->pps_MsgPort
)
4446 DeleteMsgPort(pps
->pps_MsgPort
);
4449 psdFreeVec(pps
->pps_Buffer
);
4450 ReleaseSemaphore(&pps
->pps_AccessLock
);
4456 /* /// "psdStreamRead()" */
4457 AROS_LH3(LONG
, psdStreamRead
,
4458 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4459 AROS_LHA(UBYTE
*, buffer
, A0
),
4460 AROS_LHA(LONG
, length
, D0
),
4461 LIBBASETYPEPTR
, ps
, 74, psd
)
4478 KPRINTF(2, ("psdStreamRead(%p, %p, %ld)\n", pps
, buffer
, length
));
4483 ObtainSemaphore(&pps
->pps_AccessLock
);
4484 KPRINTF(2, ("Sema\n"));
4486 if((!pps
->pps_Pipes
) || (!pps
->pps_Endpoint
->pep_Direction
))
4488 KPRINTF(2, ("Wrong direction!\n"));
4489 pps
->pps_Error
= UHIOERR_BADPARAMS
;
4490 ReleaseSemaphore(&pps
->pps_AccessLock
);
4493 if(!(pps
->pps_Flags
& PSFF_ASYNCIO
))
4495 if(pps
->pps_Flags
& PSFF_BUFFERREAD
)
4497 /* buffered reading */
4500 /* check for incoming packets */
4501 while((pp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4503 KPRINTF(1, ("PktBack(%p, %p, %ld/%ld)=%ld\n",
4504 pp
, pp
->pp_IOReq
.iouh_Data
, pp
->pp_IOReq
.iouh_Actual
,
4505 pp
->pp_IOReq
.iouh_Length
, pp
->pp_IOReq
.iouh_Req
.io_Error
));
4507 pps
->pps_ReqBytes
-= pp
->pp_IOReq
.iouh_Length
;
4508 ioerr
= pp
->pp_IOReq
.iouh_Req
.io_Error
;
4509 if((ioerr
== UHIOERR_NAKTIMEOUT
) && pp
->pp_IOReq
.iouh_Actual
)
4516 pps
->pps_Error
= ioerr
;
4518 if(ioerr
!= UHIOERR_TIMEOUT
)
4520 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamRead",
4521 "Packet(%s) failed: %s (%ld)", (STRPTR
) "b",
4522 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4524 /* stop automatic queueing */
4525 pps
->pps_Flags
&= ~PSFF_READAHEAD
;
4526 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4528 /* successfully received packet */
4529 pps
->pps_BytesPending
+= pp
->pp_IOReq
.iouh_Actual
;
4530 AddTail(&pps
->pps_ReadyPipes
, &pp
->pp_Msg
.mn_Node
);
4533 if(length
== -1) /* get all that's there (STRONGLY DISCOURAGED! Might cause buffer overflows) */
4535 length
= pps
->pps_BytesPending
;
4537 /* check for buffered data */
4538 while(length
&& pps
->pps_BytesPending
)
4540 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
4541 if(!pp
->pp_Msg
.mn_Node
.ln_Succ
) /* debug */
4543 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) "StreamRead", "Readqueue empty!");
4544 ReleaseSemaphore(&pps
->pps_AccessLock
);
4547 if(pp
->pp_IOReq
.iouh_Actual
< pps
->pps_Offset
)
4549 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) "StreamRead",
4550 "Actual %ld < offset %ld!", pp
->pp_IOReq
.iouh_Actual
, pps
->pps_Offset
);
4551 ReleaseSemaphore(&pps
->pps_AccessLock
);
4554 remlen
= pp
->pp_IOReq
.iouh_Actual
- pps
->pps_Offset
;
4557 KPRINTF(1, ("PktBit(%p, %p, %ld)\n", pp
, buffer
, length
));
4560 KPRINTF(1, ("PktRem(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4563 if(pp
->pp_Flags
& PFF_INPLACE
)
4565 KPRINTF(1, ("PktRemIP(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4567 if(pps
->pps_TermArray
)
4570 KPRINTF(1, ("PktCpyEOF(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4572 srcptr
= &(((UBYTE
*) pp
->pp_IOReq
.iouh_Data
)[pps
->pps_Offset
]);
4573 tarrptr
= pps
->pps_TermArray
;
4580 cchar
= *bufptr
++ = *srcptr
++;
4585 if(cchar
< tarrptr
[tcnt
])
4589 else if(cchar
== tarrptr
[tcnt
])
4593 KPRINTF(2, ("EOF char %02lx found, length = %ld\n", cchar
, remlen
));
4598 if(tarrptr
[tcnt
] == tarrptr
[tcnt
+1])
4603 } while(++tcnt
< 8);
4607 KPRINTF(1, ("PktCpy(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4608 /* quick non-eof mode */
4609 CopyMem(&(((UBYTE
*) pp
->pp_IOReq
.iouh_Data
)[pps
->pps_Offset
]), buffer
, remlen
);
4615 pps
->pps_BytesPending
-= remlen
;
4616 pps
->pps_Offset
+= remlen
;
4617 /* end of packet reached? */
4618 if(pps
->pps_Offset
== pp
->pp_IOReq
.iouh_Actual
)
4620 pps
->pps_Offset
= 0;
4621 Remove(&pp
->pp_Msg
.mn_Node
);
4622 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4623 /* check for short packet */
4624 if((pps
->pps_Flags
& PSFF_SHORTTERM
) && (pp
->pp_IOReq
.iouh_Actual
% pp
->pp_IOReq
.iouh_MaxPktSize
))
4634 /* start sending out requests */
4636 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4637 if(!(pps
->pps_BytesPending
|| pps
->pps_ReqBytes
|| pps
->pps_TermArray
|| (length
< pps
->pps_BufferSize
)))
4639 /* faster non-buffered mode */
4640 if(pp
->pp_Msg
.mn_Node
.ln_Succ
)
4642 pp
->pp_Flags
|= PFF_INPLACE
;
4643 Remove(&pp
->pp_Msg
.mn_Node
);
4644 remlen
= length
- (length
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4645 KPRINTF(1, ("OutFast(%p, %p, %ld/%ld)\n",
4646 pp
, buffer
, remlen
, length
));
4647 psdSendPipe(pp
, buffer
, remlen
);
4648 pps
->pps_ReqBytes
+= remlen
;
4649 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4652 /* slower buffered mode */
4653 while(pp
->pp_Msg
.mn_Node
.ln_Succ
&& ((remlen
> pps
->pps_ReqBytes
) || (pps
->pps_Flags
& PSFF_READAHEAD
)))
4655 pp
->pp_Flags
&= ~PFF_INPLACE
;
4656 Remove(&pp
->pp_Msg
.mn_Node
);
4657 if((pps
->pps_Flags
& PSFF_READAHEAD
) || (remlen
% pp
->pp_IOReq
.iouh_MaxPktSize
))
4659 KPRINTF(1, ("OutSlow(%p, %p, %ld)\n",
4660 pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], pps
->pps_BufferSize
));
4661 remlen
= pps
->pps_BufferSize
;
4663 KPRINTF(1, ("OutExact(%p, %p, %ld)\n",
4664 pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], remlen
));
4666 psdSendPipe(pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], remlen
);
4667 pps
->pps_ReqBytes
+= remlen
;
4668 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4670 if((!length
) || (pps
->pps_Flags
& PSFF_DONOTWAIT
))
4676 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4677 KPRINTF(1, ("WaitPort (%p)\n", sigmask
));
4678 sigmask
= Wait(sigmask
);
4679 KPRINTF(1, ("Wait back (%p)\n", sigmask
));
4680 if(sigmask
& pps
->pps_AbortSigMask
)
4682 KPRINTF(1, ("Aborted!\n"));
4684 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4689 /* plain reading (might lose data) */
4690 if(pps
->pps_TermArray
|| (pps
->pps_Flags
& PSFF_READAHEAD
))
4692 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) "StreamRead", "This mode combination for the stream is not supported!");
4694 /* start sending out requests */
4695 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4696 if(pp
->pp_Msg
.mn_Node
.ln_Succ
&& length
)
4698 ioerr
= psdDoPipe(pp
, buffer
, length
);
4701 pps
->pps_Error
= ioerr
;
4702 if(ioerr
!= UHIOERR_TIMEOUT
)
4704 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamRead",
4705 "Packet(%s) failed: %s (%ld)", (STRPTR
) "u",
4706 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4709 actual
= pp
->pp_IOReq
.iouh_Actual
;
4713 ReleaseSemaphore(&pps
->pps_AccessLock
);
4719 /* /// "psdStreamWrite()" */
4720 AROS_LH3(LONG
, psdStreamWrite
,
4721 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4722 AROS_LHA(UBYTE
*, buffer
, A0
),
4723 AROS_LHA(LONG
, length
, D0
),
4724 LIBBASETYPEPTR
, ps
, 75, psd
)
4728 struct PsdPipe
*newpp
;
4741 KPRINTF(2, ("psdStreamWrite(%p, %p, %ld)\n", pps
, buffer
, length
));
4746 ObtainSemaphore(&pps
->pps_AccessLock
);
4748 if((!pps
->pps_Pipes
) || pps
->pps_Endpoint
->pep_Direction
)
4750 KPRINTF(2, ("Wrong direction!\n"));
4751 pps
->pps_Error
= UHIOERR_BADPARAMS
;
4752 ReleaseSemaphore(&pps
->pps_AccessLock
);
4755 if(length
== -1) /* null terminated string mode */
4757 KPRINTF(2, ("EOL mode!\n"));
4758 length
= strlen(buffer
);
4760 if((tarrptr
= pps
->pps_TermArray
)) /* EOF Mode */
4762 KPRINTF(1, ("EOFSearch(%p, %ld)\n", buffer
, length
));
4775 if(cchar
< tarrptr
[tcnt
])
4779 else if(cchar
== tarrptr
[tcnt
])
4782 KPRINTF(2, ("EOF char %02lx found, length = %ld\n", cchar
, length
));
4787 if(tarrptr
[tcnt
] == tarrptr
[tcnt
+1])
4792 } while(++tcnt
< 8);
4796 if(!(pps
->pps_Flags
& PSFF_ASYNCIO
))
4798 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4799 if(pp
->pp_Msg
.mn_Node
.ln_Succ
&& length
)
4801 if(pps
->pps_Flags
& PSFF_BUFFERWRITE
)
4803 /* buffered writing */
4804 if(pps
->pps_BytesPending
)
4806 remlen
= pps
->pps_BytesPending
% pp
->pp_IOReq
.iouh_MaxPktSize
;
4807 /* align to packet boundary */
4808 if(remlen
+ length
>= pp
->pp_IOReq
.iouh_MaxPktSize
)
4810 /* new data crosses at least on packet size */
4811 if(pps
->pps_BytesPending
+ length
<= pps
->pps_BufferSize
)
4813 /* copy everything up to the last (!) boundary */
4814 remlen
= pps
->pps_BytesPending
+ length
;
4815 remlen
= remlen
- (remlen
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4816 remlen
-= pps
->pps_BytesPending
;
4817 KPRINTF(1, ("PendOptCpy(%p, %ld+%ld/%ld)\n", buffer
, pps
->pps_BytesPending
, remlen
, length
));
4819 /* just calculate amount to copy to the next boundary */
4820 remlen
= pp
->pp_IOReq
.iouh_MaxPktSize
- remlen
;
4821 KPRINTF(1, ("PendOneCpy(%p, %ld+%ld/%ld)\n", buffer
, pps
->pps_BytesPending
, remlen
, length
));
4823 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], remlen
);
4824 pps
->pps_BytesPending
+= remlen
;
4829 KPRINTF(1, ("PendAdd(%p, %ld+%ld)\n", buffer
, pps
->pps_BytesPending
, length
));
4830 /* only a few bytes, see if we can fit them */
4831 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], length
);
4832 pps
->pps_BytesPending
+= length
;
4834 //buffer += length; /* not needed */
4837 /* flush some buffers */
4838 if((length
>= pp
->pp_IOReq
.iouh_MaxPktSize
) ||
4839 ((pps
->pps_BytesPending
>= (pps
->pps_BufferSize
>>1)) && (pps
->pps_BytesPending
>= pp
->pp_IOReq
.iouh_MaxPktSize
)))
4841 remlen
= pps
->pps_BytesPending
- (pps
->pps_BytesPending
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4842 KPRINTF(1, ("PendFlush(%ld/%ld)\n", remlen
, pps
->pps_BytesPending
));
4843 Remove(&pp
->pp_Msg
.mn_Node
);
4844 psdSendPipe(pp
, pps
->pps_Buffer
, remlen
);
4845 pps
->pps_ActivePipe
= pp
;
4846 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4848 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4849 sigmask
= Wait(sigmask
);
4850 if(sigmask
& pps
->pps_AbortSigMask
)
4852 KPRINTF(1, ("Kill signal detected!\n"));
4853 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4861 ioerr
= psdWaitPipe(pp
);
4862 pps
->pps_ActivePipe
= NULL
;
4863 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4865 /* move end of buffer */
4866 cnt
= pps
->pps_BytesPending
;
4867 tcnt
= pp
->pp_IOReq
.iouh_Actual
;
4868 pps
->pps_BytesPending
-= tcnt
;
4869 bufptr
= pps
->pps_Buffer
;
4870 srcptr
= bufptr
+ tcnt
;
4876 *bufptr
++ = *srcptr
++;
4881 pps
->pps_Error
= ioerr
;
4882 if(ioerr
!= UHIOERR_TIMEOUT
)
4884 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4885 "Packet(%s) failed: %s (%ld)", (STRPTR
) "b",
4886 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4888 ReleaseSemaphore(&pps
->pps_AccessLock
);
4893 /* send out large chunk (avoid copying) */
4894 if(length
>= pp
->pp_IOReq
.iouh_MaxPktSize
)
4896 remlen
= length
- (length
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4897 KPRINTF(1, ("BulkFlush(%p, %ld/%ld)\n", buffer
, remlen
, length
));
4898 Remove(&pp
->pp_Msg
.mn_Node
);
4899 psdSendPipe(pp
, buffer
, remlen
);
4900 pps
->pps_ActivePipe
= pp
;
4901 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4903 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4904 sigmask
= Wait(sigmask
);
4905 if(sigmask
& pps
->pps_AbortSigMask
)
4907 KPRINTF(1, ("Kill signal detected!\n"));
4908 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4916 ioerr
= psdWaitPipe(pp
);
4917 pps
->pps_ActivePipe
= NULL
;
4918 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4920 actual
+= pp
->pp_IOReq
.iouh_Actual
;
4921 buffer
+= pp
->pp_IOReq
.iouh_Actual
;
4922 length
-= pp
->pp_IOReq
.iouh_Actual
;
4925 pps
->pps_Error
= ioerr
;
4926 if(ioerr
!= UHIOERR_TIMEOUT
)
4928 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4929 "Packet(%s) failed: %s (%ld)", (STRPTR
) "c",
4930 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4932 ReleaseSemaphore(&pps
->pps_AccessLock
);
4936 /* buffer remaining bytes */
4939 KPRINTF(1, ("BufAdd(%p, %ld)\n", buffer
, length
));
4940 /* only a few bytes left, so lets buffer them */
4941 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], length
);
4942 pps
->pps_BytesPending
+= length
;
4947 /* start sending out requests */
4948 KPRINTF(1, ("PlainWrite(%p, %ld)\n", buffer
, length
));
4949 Remove(&pp
->pp_Msg
.mn_Node
);
4950 psdSendPipe(pp
, buffer
, length
);
4951 pps
->pps_ActivePipe
= pp
;
4952 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4954 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4955 sigmask
= Wait(sigmask
);
4956 if(sigmask
& pps
->pps_AbortSigMask
)
4958 KPRINTF(1, ("Kill signal detected!\n"));
4959 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4967 ioerr
= psdWaitPipe(pp
);
4968 pps
->pps_ActivePipe
= NULL
;
4969 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4972 pps
->pps_Error
= ioerr
;
4973 if(ioerr
!= UHIOERR_TIMEOUT
)
4975 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4976 "Packet(%s) failed: %s (%ld)", (STRPTR
) "u",
4977 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4980 actual
= pp
->pp_IOReq
.iouh_Actual
;
4983 KPRINTF(2, ("No free pipe!\n"));
4986 ReleaseSemaphore(&pps
->pps_AccessLock
);
4992 /* /// "psdStreamFlush()" */
4993 AROS_LH1(LONG
, psdStreamFlush
,
4994 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4995 LIBBASETYPEPTR
, ps
, 76, psd
)
5003 KPRINTF(2, ("psdStreamFlush(%p)\n", pps
));
5008 ObtainSemaphore(&pps
->pps_AccessLock
);
5010 if(pps
->pps_Endpoint
->pep_Direction
)
5013 KPRINTF(2, ("Flushing in...\n"));
5014 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
5016 psdAbortPipe(pps
->pps_Pipes
[cnt
]);
5018 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
5020 psdWaitPipe(pps
->pps_Pipes
[cnt
]);
5022 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
5023 while(pp
->pp_Msg
.mn_Node
.ln_Succ
)
5025 Remove(&pp
->pp_Msg
.mn_Node
);
5026 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
5027 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
5029 while((pp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
5031 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
5033 pps
->pps_ReqBytes
= 0;
5034 pps
->pps_BytesPending
= 0;
5035 pps
->pps_Offset
= 0;
5039 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
5040 if(pp
->pp_Msg
.mn_Node
.ln_Succ
)
5043 if(pps
->pps_BytesPending
)
5045 KPRINTF(2, ("Flushing out %ld...\n", pps
->pps_BytesPending
));
5046 Remove(&pp
->pp_Msg
.mn_Node
);
5047 ioerr
= psdDoPipe(pp
, pps
->pps_Buffer
, pps
->pps_BytesPending
);
5048 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
5049 pps
->pps_BytesPending
= 0;
5052 pps
->pps_Error
= ioerr
;
5053 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamFlush",
5054 "Packet(%s) failed: %s (%ld)", (STRPTR
) "f",
5055 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
5059 KPRINTF(2, ("Nothing to flush\n"));
5063 ReleaseSemaphore(&pps
->pps_AccessLock
);
5069 /* /// "psdGetStreamError()" */
5070 AROS_LH1(LONG
, psdGetStreamError
,
5071 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
5072 LIBBASETYPEPTR
, ps
, 77, psd
)
5075 KPRINTF(1, ("psdGetStreamError(%p)\n", pps
));
5078 return((LONG
) pps
->pps_Error
);
5086 /* *** Realtime Iso */
5088 /* /// "psdAllocRTIsoHandler()" */
5089 AROS_LH2(struct PsdRTIsoHandler
*, psdAllocRTIsoHandlerA
,
5090 AROS_LHA(struct PsdEndpoint
*, pep
, A0
),
5091 AROS_LHA(struct TagItem
*, tags
, A1
),
5092 LIBBASETYPEPTR
, ps
, 93, psd
)
5095 struct PsdRTIsoHandler
*prt
;
5099 KPRINTF(2, ("psdAllocRTIso(%p, %p)\n", pep
, tags
));
5104 if(pep
->pep_TransType
!= USEAF_ISOCHRONOUS
)
5108 if(!(pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Capabilities
& UHCF_RT_ISO
))
5110 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Your HW controller driver does not support realtime iso transfers. Sorry.");
5113 if((prt
= psdAllocVec(sizeof(struct PsdRTIsoHandler
))))
5115 prt
->prt_Device
= pep
->pep_Interface
->pif_Config
->pc_Device
;
5116 prt
->prt_Endpoint
= pep
;
5117 prt
->prt_RTIso
.urti_OutPrefetch
= 2048;
5118 if((pp
= prt
->prt_Pipe
= psdAllocPipe(prt
->prt_Device
, (struct MsgPort
*) 0xffffffff, pep
)))
5120 pp
->pp_MsgPort
= pp
->pp_Msg
.mn_ReplyPort
= NULL
;
5121 psdSetAttrsA(PGA_RTISO
, prt
, tags
);
5122 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_ADDISOHANDLER
;
5123 pp
->pp_IOReq
.iouh_Data
= &prt
->prt_RTIso
;
5124 // hardware must support quick IO for this to work!
5125 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5129 AddTail(&prt
->prt_Device
->pd_RTIsoHandlers
, &prt
->prt_Node
);
5133 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5134 "Adding RT Iso Handler failed: %s (%ld)",
5135 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
5137 psdFreePipe(prt
->prt_Pipe
);
5146 /* /// "psdFreeRTIsoHandler()" */
5147 AROS_LH1(void, psdFreeRTIsoHandler
,
5148 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5149 LIBBASETYPEPTR
, ps
, 94, psd
)
5159 Remove(&prt
->prt_Node
);
5162 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_REMISOHANDLER
;
5163 DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5170 /* /// "psdStartRTIso()" */
5171 AROS_LH1(LONG
, psdStartRTIso
,
5172 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5173 LIBBASETYPEPTR
, ps
, 95, psd
)
5181 return UHIOERR_BADPARAMS
;
5184 if(pp
->pp_Device
->pd_Flags
& PDFF_SUSPENDED
)
5186 // make sure the device is up and running before trying to send a new pipe
5187 psdResumeDevice(pp
->pp_Device
);
5189 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_STARTRTISO
;
5190 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5193 ++pp
->pp_Device
->pd_IOBusyCount
;
5200 /* /// "psdStopRTIso()" */
5201 AROS_LH1(LONG
, psdStopRTIso
,
5202 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5203 LIBBASETYPEPTR
, ps
, 96, psd
)
5211 return UHIOERR_BADPARAMS
;
5214 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_STOPRTISO
;
5215 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5218 --pp
->pp_Device
->pd_IOBusyCount
;
5225 /* *** Classes *** */
5227 /* /// "psdAddClass()" */
5228 AROS_LH2(struct PsdUsbClass
*, psdAddClass
,
5229 AROS_LHA(STRPTR
, name
, A1
),
5230 AROS_LHA(ULONG
, vers
, D0
),
5231 LIBBASETYPEPTR
, ps
, 35, psd
)
5234 struct Library
*cls
= NULL
;
5235 struct PsdUsbClass
*puc
;
5239 STRPTR origname
= name
;
5240 STRPTR evilmsg
[8] = { "Say hello to %s V%ld.%ld (%s).",
5241 "Whoah! %s V%ld.%ld surprised as %s.",
5242 "The door bell rang for %s V%ld.%ld (%s).",
5243 "Welcome %s V%ld.%ld (%s) to the party.",
5245 "Don't laugh at %s V%ld.%ld for %s.",
5246 "Time has come for %s V%ld.%ld (%s) to join the show.",
5247 "Start blaming %s V%ld.%ld for helping at %s.",
5248 "Ain't %s V%ld.%ld useful for %s?" };
5250 KPRINTF(5, ("psdAddClass(%s, %ld)\n", name
, vers
));
5254 if((cls
= OpenLibrary(name
, vers
)))
5260 if((*name
== '/') || (*name
== ':'))
5270 if(FindName(&ps
->ps_Classes
, cls
->lib_Node
.ln_Name
))
5273 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5274 "Attempted to add class %s twice. Nothing is good enough for people like you.",
5276 KPRINTF(20, ("attempt to add class twice!\n"));
5281 if((puc
= psdAllocVec(sizeof(struct PsdUsbClass
))))
5284 puc
->puc_ClassBase
= cls
;
5285 puc
->puc_Node
.ln_Name
= puc
->puc_ClassName
= psdCopyStr(cls
->lib_Node
.ln_Name
);
5286 puc
->puc_FullPath
= psdCopyStr(origname
);
5288 usbGetAttrs(UGA_CLASS
, NULL
,
5289 UCCA_Priority
, &pri
,
5290 UCCA_Description
, &desc
,
5293 puc
->puc_Node
.ln_Pri
= pri
;
5294 psdLockWritePBase();
5295 Enqueue(&ps
->ps_Classes
, &puc
->puc_Node
);
5297 msgoff
= ps
->ps_FunnyCount
++ & 7;
5299 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5301 cls
->lib_Node
.ln_Name
, cls
->lib_Version
, cls
->lib_Revision
, desc
);
5302 psdSendEvent(EHMB_ADDCLASS
, puc
, NULL
);
5312 /* /// "psdRemClass()" */
5313 AROS_LH1(void, psdRemClass
,
5314 AROS_LHA(struct PsdUsbClass
*, puc
, A1
),
5315 LIBBASETYPEPTR
, ps
, 36, psd
)
5318 KPRINTF(5, ("psdRemClass(%p)\n", puc
));
5319 psdLockWritePBase();
5320 Remove(&puc
->puc_Node
);
5323 /* Check if there are still bindings remaining */
5324 while(puc
->puc_UseCnt
)
5326 struct PsdDevice
*pd
;
5327 struct PsdConfig
*pc
;
5328 struct PsdInterface
*pif
;
5330 KPRINTF(20, ("This should never happen: Class %s still in use (%ld), can't close!\n",
5331 puc
->puc_ClassBase
->lib_Node
.ln_Name
, puc
->puc_UseCnt
));
5333 /* Well, try to release the open bindings in a best effort attempt */
5336 while((pd
= psdGetNextDevice(pd
)))
5338 if(pd
->pd_DevBinding
&& (pd
->pd_ClsBinding
== puc
) && (!(pd
->pd_Flags
& PDFF_APPBINDING
)))
5341 psdReleaseDevBinding(pd
);
5343 pd
= NULL
; /* restart */
5346 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5347 while(pc
->pc_Node
.ln_Succ
)
5349 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5350 while(pif
->pif_Node
.ln_Succ
)
5352 if(pif
->pif_IfBinding
&& (pif
->pif_ClsBinding
== puc
))
5355 psdReleaseIfBinding(pif
);
5357 pd
= NULL
; /* restart */
5360 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5362 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5368 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
5369 "This should never happen! Class %s still in use (cnt=%ld). Could not get rid of it! Sorry, we're broke.",
5370 puc
->puc_ClassBase
->lib_Node
.ln_Name
, puc
->puc_UseCnt
);
5372 /*psdDelayMS(2000);*/
5375 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5376 "I shot class %s, but I didn't kill the deputy.",
5377 puc
->puc_ClassBase
->lib_Node
.ln_Name
);
5378 CloseLibrary(puc
->puc_ClassBase
);
5379 psdFreeVec(puc
->puc_ClassName
);
5380 psdFreeVec(puc
->puc_FullPath
);
5382 psdSendEvent(EHMB_REMCLASS
, puc
, NULL
);
5387 /* *** Error Msgs *** */
5389 /* /// "psdAddErrorMsgA()" */
5390 AROS_LH4(struct PsdErrorMsg
*, psdAddErrorMsgA
,
5391 AROS_LHA(UWORD
, level
, D0
),
5392 AROS_LHA(STRPTR
, origin
, A0
),
5393 AROS_LHA(STRPTR
, fmtstr
, A1
),
5394 AROS_LHA(RAWARG
, fmtdata
, A2
),
5395 LIBBASETYPEPTR
, ps
, 40, psd
)
5398 struct PsdErrorMsg
*pem
;
5399 if(((!ps
->ps_GlobalCfg
->pgc_LogInfo
) && (level
< RETURN_WARN
)) ||
5400 ((!ps
->ps_GlobalCfg
->pgc_LogWarning
) && (level
>= RETURN_WARN
) && (level
< RETURN_ERROR
)) ||
5401 ((!ps
->ps_GlobalCfg
->pgc_LogError
) && (level
>= RETURN_ERROR
) && (level
< RETURN_FAIL
)) ||
5402 ((!ps
->ps_GlobalCfg
->pgc_LogFailure
) && (level
>= RETURN_FAIL
)))
5406 if((pem
= psdAllocVec(sizeof(struct PsdErrorMsg
))))
5409 pem
->pem_Level
= level
;
5410 if((pem
->pem_Origin
= psdCopyStr(origin
)))
5412 if((pem
->pem_Msg
= psdCopyStrFmtA(fmtstr
, fmtdata
)))
5414 if (ps
->ps_Flags
& PSF_KLOG
) {
5415 KPrintF("[%s] %s\n", origin
, pem
->pem_Msg
);
5420 DateStamp(&pem
->pem_DateStamp
);
5422 struct timerequest tr
= ps
->ps_TimerIOReq
;
5423 tr
.tr_node
.io_Command
= TR_GETSYSTIME
;
5424 DoIO((struct IORequest
*) &tr
);
5425 pem
->pem_DateStamp
.ds_Days
= tr
.tr_time
.tv_secs
/ (24*60*60);
5426 pem
->pem_DateStamp
.ds_Minute
= (tr
.tr_time
.tv_secs
/ 60) % 60;
5427 pem
->pem_DateStamp
.ds_Tick
= (tr
.tr_time
.tv_secs
% 60) * 50;
5430 AddTail(&ps
->ps_ErrorMsgs
, &pem
->pem_Node
);
5432 psdSendEvent(EHMB_ADDERRORMSG
, pem
, NULL
);
5435 psdFreeVec(pem
->pem_Origin
);
5444 /* /// "psdRemErrorMsg()" */
5445 AROS_LH1(void, psdRemErrorMsg
,
5446 AROS_LHA(struct PsdErrorMsg
*, pem
, A0
),
5447 LIBBASETYPEPTR
, ps
, 41, psd
)
5450 KPRINTF(1, ("psdRemErrorMsg()\n"));
5452 Remove(&pem
->pem_Node
);
5454 psdFreeVec(pem
->pem_Origin
);
5455 psdFreeVec(pem
->pem_Msg
);
5457 psdSendEvent(EHMB_REMERRORMSG
, pem
, NULL
);
5462 /* *** Bindings *** */
5464 /* /// "psdClassScan()" */
5465 AROS_LH0(void, psdClassScan
,
5466 LIBBASETYPEPTR
, ps
, 37, psd
)
5469 struct PsdHardware
*phw
;
5470 struct PsdDevice
*pd
;
5471 struct PsdUsbClass
*puc
;
5475 if((FindTask(NULL
)->tc_Node
.ln_Type
!= NT_PROCESS
) && (!ps
->ps_ConfigRead
))
5477 // it's the first time we were reading the config and DOS was not available
5478 ps
->ps_StartedAsTask
= TRUE
;
5481 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5482 if(!puc
->puc_Node
.ln_Succ
)
5484 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "ClassScan attempted with no classes installed!");
5489 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
5490 while(phw
->phw_Node
.ln_Succ
)
5492 if((pd
= phw
->phw_RootDevice
))
5494 // for the root, do it ourselves, the rest is done by each hub task
5495 psdHubClassScan(pd
);
5497 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
5500 //psdSendEvent(EHMB_CLSSCANRDY, NULL, NULL);
5501 KPRINTF(5, ("************ Scanning finished!\n"));
5506 /* /// "psdDoHubMethodA()" */
5507 AROS_LH3(LONG
, psdDoHubMethodA
,
5508 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5509 AROS_LHA(ULONG
, methodid
, D0
),
5510 AROS_LHA(APTR
, methoddata
, A1
),
5511 LIBBASETYPEPTR
, ps
, 92, psd
)
5514 struct PsdUsbClass
*puc
;
5515 KPRINTF(2, ("psdDoHubMethodA(%p)\n", pd
));
5521 if((pd
->pd_Hub
->pd_DevBinding
) && (puc
= pd
->pd_Hub
->pd_ClsBinding
))
5523 return(usbDoMethodA(methodid
, methoddata
));
5532 /* /// "psdClaimAppBindingA()" */
5533 AROS_LH1(struct PsdAppBinding
*, psdClaimAppBindingA
,
5534 AROS_LHA(struct TagItem
*, tags
, A1
),
5535 LIBBASETYPEPTR
, ps
, 45, psd
)
5538 struct PsdDevice
*pd
;
5539 struct PsdConfig
*pc
;
5540 struct PsdInterface
*pif
;
5541 struct PsdDevice
*hubpd
;
5542 struct PsdAppBinding tmppab
;
5543 struct PsdAppBinding
*pab
= NULL
;
5544 struct PsdUsbClass
*puc
;
5548 KPRINTF(2, ("psdClaimAppBindingA(%p)\n", tags
));
5550 tmppab
.pab_Device
= NULL
;
5551 tmppab
.pab_ReleaseHook
= NULL
;
5552 tmppab
.pab_Task
= NULL
;
5553 tmppab
.pab_ForceRelease
= FALSE
;
5554 psdSetAttrsA(PGA_APPBINDING
, &tmppab
, tags
);
5555 if(tmppab
.pab_Device
&& tmppab
.pab_ReleaseHook
)
5557 pd
= tmppab
.pab_Device
;
5559 // force release of other bindings first
5560 if(tmppab
.pab_ForceRelease
)
5562 /* If there are bindings, get rid of them. */
5563 if(pd
->pd_DevBinding
)
5565 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5566 "%s really wants to bind to %s, so I'm letting the old binding go.",
5567 FindTask(NULL
)->tc_Node
.ln_Name
,
5570 psdReleaseDevBinding(pd
);
5572 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5573 while(pc
->pc_Node
.ln_Succ
)
5575 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5576 while(pif
->pif_Node
.ln_Succ
)
5578 if(pif
->pif_IfBinding
)
5580 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5581 "%s really wants to bind to %s, so I'm letting the old binding go.",
5582 FindTask(NULL
)->tc_Node
.ln_Name
,
5584 psdReleaseIfBinding(pif
);
5586 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5588 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5593 if(!hubpd
) // claim app binding at the root hub -- improbable, but possible.
5595 pab
= psdHubClaimAppBindingA(tags
);
5597 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5599 pab
= (struct PsdAppBinding
*) usbDoMethod(UCM_HubClaimAppBinding
, binding
, tags
);
5604 // fill in task names
5605 pab
->pab_Task
= FindTask(NULL
);
5606 pab
->pab_Node
.ln_Name
= pab
->pab_Task
->tc_Node
.ln_Name
;
5607 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5616 /* /// "psdReleaseAppBinding()" */
5617 AROS_LH1(void, psdReleaseAppBinding
,
5618 AROS_LHA(struct PsdAppBinding
*, pab
, A0
),
5619 LIBBASETYPEPTR
, ps
, 46, psd
)
5622 struct PsdDevice
*pd
;
5623 struct PsdDevice
*hubpd
;
5624 struct PsdUsbClass
*puc
;
5627 KPRINTF(2, ("psdReleaseAppBinding(%p)\n", pab
));
5631 pd
= pab
->pab_Device
;
5633 if(!hubpd
) // release binding of hub (improbable)
5635 psdHubReleaseDevBinding(pd
);
5638 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5640 usbDoMethod(UCM_HubReleaseDevBinding
, binding
, pd
);
5647 /* /// "psdReleaseDevBinding()" */
5648 AROS_LH1(void, psdReleaseDevBinding
,
5649 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5650 LIBBASETYPEPTR
, ps
, 50, psd
)
5653 struct PsdUsbClass
*puc
;
5654 struct PsdDevice
*hubpd
;
5657 KPRINTF(5, ("psdReleaseDevBinding(%p)\n", pd
));
5658 if(pd
->pd_DevBinding
)
5661 if(!hubpd
) // release binding of hub
5663 psdHubReleaseDevBinding(pd
);
5666 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5668 usbDoMethod(UCM_HubReleaseDevBinding
, binding
, pd
);
5675 /* /// "psdReleaseIfBinding()" */
5676 AROS_LH1(void, psdReleaseIfBinding
,
5677 AROS_LHA(struct PsdInterface
*, pif
, A0
),
5678 LIBBASETYPEPTR
, ps
, 51, psd
)
5681 struct PsdUsbClass
*puc
;
5682 struct PsdDevice
*hubpd
;
5685 KPRINTF(5, ("psdReleaseIfBinding(%p)\n", pif
));
5686 if(pif
->pif_IfBinding
&& pif
->pif_ClsBinding
)
5688 hubpd
= pif
->pif_Config
->pc_Device
->pd_Hub
;
5689 if(!hubpd
) // release binding of hub (improbable)
5691 psdHubReleaseIfBinding(pif
);
5694 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5696 usbDoMethod(UCM_HubReleaseIfBinding
, binding
, pif
);
5703 /* /// "psdUnbindAll()" */
5704 AROS_LH0(void, psdUnbindAll
,
5705 LIBBASETYPEPTR
, ps
, 61, psd
)
5708 struct PsdHardware
*phw
;
5709 struct PsdDevice
*pd
;
5710 struct PsdConfig
*pc
;
5711 struct PsdInterface
*pif
;
5714 KPRINTF(10, ("pUnbindAll()\n"));
5715 /* FIXME What happens if devices or hardware gets removed during the process? Need notify semaphore */
5720 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
5721 while(phw
->phw_Node
.ln_Succ
)
5723 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
5724 while(pd
->pd_Node
.ln_Succ
)
5726 /* If there are bindings, get rid of them. */
5727 if(pd
->pd_DevBinding
)
5730 psdReleaseDevBinding(pd
);
5735 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5736 while(pc
->pc_Node
.ln_Succ
)
5738 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5739 while(pif
->pif_Node
.ln_Succ
)
5741 if(pif
->pif_IfBinding
)
5744 psdReleaseIfBinding(pif
);
5749 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5755 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5761 pd
= (struct PsdDevice
*) pd
->pd_Node
.ln_Succ
;
5767 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
5775 /* /// "psdHubClassScan()" */
5776 AROS_LH1(void, psdHubClassScan
,
5777 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5778 LIBBASETYPEPTR
, ps
, 82, psd
)
5781 struct PsdUsbClass
*puc
;
5782 struct PsdConfig
*pc
;
5783 struct PsdInterface
*pif
;
5784 struct PsdInterface
*firstpif
;
5785 struct PsdPipe
*pp
= NULL
;
5792 KPRINTF(5, ("psdClassScan()\n"));
5794 if(!(mp
= CreateMsgPort()))
5799 psdLockWriteDevice(pd
);
5800 while(!(pd
->pd_PoPoCfg
.poc_NoClassBind
|| pd
->pd_DevBinding
))
5802 if(!(pp
= psdAllocPipe(pd
, mp
, NULL
)))
5806 KPRINTF(5, ("Doing ClassScan on Device: %s\n", pd
->pd_ProductStr
));
5808 /* First look if there is any interface binding. We may not change
5809 the current config in this case! */
5810 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5811 while(pc
->pc_Node
.ln_Succ
)
5813 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5815 while(pif
->pif_Node
.ln_Succ
)
5817 if(pif
->pif_IfBinding
)
5819 hasifbinding
= pc
->pc_CfgNum
;
5822 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5824 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5827 owner
= psdGetForcedBinding(pd
->pd_IDString
, NULL
);
5828 if((!hasifbinding
) && owner
)
5830 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5831 while(puc
->puc_Node
.ln_Succ
)
5833 if(!strcmp(owner
, puc
->puc_ClassName
))
5835 if((pd
->pd_DevBinding
= (APTR
) usbDoMethod(UCM_ForceDeviceBinding
, pd
)))
5837 pd
->pd_ClsBinding
= puc
;
5839 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5841 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5842 "Forced device binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5846 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5848 /* no more scanning required, abort here */
5852 /* Second attempt */
5853 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5854 while(pc
->pc_Node
.ln_Succ
)
5856 if((!hasifbinding
) || (hasifbinding
== pc
->pc_CfgNum
))
5858 /* If the current config is not the one selected, change it */
5859 if(pd
->pd_CurrCfg
!= pc
->pc_CfgNum
)
5861 psdSetDeviceConfig(pp
, pc
->pc_CfgNum
);
5863 KPRINTF(5, (" Config %ld\n", pc
->pc_CfgNum
));
5864 /* If something went wrong above, we must exclude this config */
5865 if(pd
->pd_CurrCfg
== pc
->pc_CfgNum
)
5867 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5868 while(pif
->pif_Node
.ln_Succ
)
5870 KPRINTF(5, (" Interface %ld\n", pif
->pif_IfNum
));
5873 if(!pif
->pif_IfBinding
)
5878 if(!psdSetAltInterface(pp
, pif
))
5880 pif
->pif_IfBinding
= NULL
;
5881 /* Okay, this alternate setting failed. Try to get next one */
5884 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5885 if(pif
->pif_Node
.ln_Succ
)
5887 KPRINTF(5, ("CONT!\n"));
5890 KPRINTF(5, ("BREAK!\n"));
5896 owner
= psdGetForcedBinding(pd
->pd_IDString
, pif
->pif_IDString
);
5897 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5898 while(puc
->puc_Node
.ln_Succ
)
5900 KPRINTF(5, (">>>PING %s!\n", puc
->puc_ClassName
));
5903 if(!strcmp(owner
, puc
->puc_ClassName
))
5905 binding
= (APTR
) usbDoMethod(UCM_ForceInterfaceBinding
, pif
);
5908 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5909 "Forced interface binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5914 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5918 binding
= (APTR
) usbDoMethod(UCM_AttemptInterfaceBinding
, pif
);
5921 KPRINTF(5, ("<<<PONG!!\n"));
5924 KPRINTF(5, ("Got binding!\n"));
5925 /* Find root config structure */
5926 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5927 while(pif
->pif_Node
.ln_Succ
)
5929 if(pif
->pif_IfNum
== firstpif
->pif_IfNum
)
5933 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5935 if(!pif
->pif_Node
.ln_Succ
)
5937 KPRINTF(5, ("Fucked it up!\n"));
5938 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Something incredibly stupid happend. I've given up.");
5942 pif
->pif_IfBinding
= binding
;
5943 pif
->pif_ClsBinding
= puc
;
5944 hasifbinding
= pc
->pc_CfgNum
;
5946 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5951 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5957 //break; /* FIXME: DISABLED ALTSCANNING */
5958 /* Check alternate setting */
5959 if(pif
->pif_AlterIfs
.lh_Head
->ln_Succ
)
5961 /* There are some alternative interfaces, start at top */
5962 pif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
5965 } while(pif
!= firstpif
);
5966 //pif->pif_IfBinding = binding;
5969 psdSetAltInterface(pp
, pif
);
5971 /* Hohum, search current main interface then */
5972 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5973 while(pif
->pif_Node
.ln_Succ
)
5975 if(pif
->pif_IfNum
== firstpif
->pif_IfNum
)
5979 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5982 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5986 KPRINTF(5, ("End, next ConfigCheck!\n"));
5987 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5989 /* Could not establish interface binding, try device binding then */
5993 //pd->pd_DevBinding = (APTR) ~0UL;
5995 owner
= psdGetForcedBinding(pd
->pd_IDString
, NULL
);
5996 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5997 while(puc
->puc_Node
.ln_Succ
)
6002 if(!strcmp(owner
, puc
->puc_ClassName
))
6004 binding
= (APTR
) usbDoMethod(UCM_ForceDeviceBinding
, pd
, TAG_END
);
6007 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6008 "Forced device binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
6013 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6017 binding
= (APTR
) usbDoMethod(UCM_AttemptDeviceBinding
, pd
);
6021 pd
->pd_DevBinding
= binding
;
6022 pd
->pd_ClsBinding
= puc
;
6024 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
6027 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6029 pd
->pd_DevBinding
= binding
;
6037 // call hub class scan code
6038 if((binding
= pd
->pd_DevBinding
) && (puc
= pd
->pd_ClsBinding
))
6040 usbDoMethod(UCM_HubClassScan
, binding
);
6042 psdUnlockDevice(pd
);
6049 /* /// "psdHubClaimAppBindingA()" */
6050 AROS_LH1(struct PsdAppBinding
*, psdHubClaimAppBindingA
,
6051 AROS_LHA(struct TagItem
*, tags
, A1
),
6052 LIBBASETYPEPTR
, ps
, 83, psd
)
6055 struct PsdDevice
*pd
;
6056 struct PsdAppBinding
*pab
;
6057 struct PsdConfig
*pc
;
6058 struct PsdInterface
*pif
;
6060 BOOL hasbinding
= FALSE
;
6061 KPRINTF(2, ("psdHubClaimAppBindingA(%p)\n", tags
));
6063 if((pab
= psdAllocVec(sizeof(struct PsdAppBinding
))))
6065 psdSetAttrsA(PGA_APPBINDING
, pab
, tags
);
6066 if(pab
->pab_Device
&& pab
->pab_ReleaseHook
)
6068 pd
= pab
->pab_Device
;
6069 if(pd
->pd_DevBinding
)
6073 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
6074 while(pc
->pc_Node
.ln_Succ
)
6076 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
6078 while(pif
->pif_Node
.ln_Succ
)
6080 if(pif
->pif_IfBinding
)
6085 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
6087 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
6092 pd
->pd_Flags
|= PDFF_APPBINDING
;
6093 pd
->pd_DevBinding
= pab
;
6094 pd
->pd_ClsBinding
= NULL
;
6105 /* /// "psdHubReleaseDevBinding()" */
6106 AROS_LH1(void, psdHubReleaseDevBinding
,
6107 AROS_LHA(struct PsdDevice
*, pd
, A0
),
6108 LIBBASETYPEPTR
, ps
, 84, psd
)
6111 struct PsdUsbClass
*puc
;
6113 struct PsdAppBinding
*pab
;
6115 KPRINTF(5, ("psdHubReleaseDevBinding(%p)\n", pd
));
6118 psdLockWriteDevice(pd
);
6119 if((binding
= pd
->pd_DevBinding
))
6121 pd
->pd_DevBinding
= NULL
;
6122 if(pd
->pd_Flags
& PDFF_APPBINDING
)
6124 pab
= (struct PsdAppBinding
*) binding
;
6125 CallHookPkt(pab
->pab_ReleaseHook
, pab
, (APTR
) pab
->pab_UserData
);
6126 pd
->pd_ClsBinding
= NULL
;
6127 pd
->pd_Flags
&= ~PDFF_APPBINDING
;
6129 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6131 puc
= pd
->pd_ClsBinding
;
6134 pd
->pd_ClsBinding
= NULL
;
6135 usbDoMethod(UCM_ReleaseDeviceBinding
, binding
);
6137 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6141 psdUnlockDevice(pd
);
6147 /* /// "psdHubReleaseIfBinding()" */
6148 AROS_LH1(void, psdHubReleaseIfBinding
,
6149 AROS_LHA(struct PsdInterface
*, pif
, A0
),
6150 LIBBASETYPEPTR
, ps
, 85, psd
)
6153 struct PsdUsbClass
*puc
;
6154 struct PsdDevice
*pd
;
6157 KPRINTF(5, ("psdHubReleaseIfBinding(%p)\n", pif
));
6161 pd
= pif
->pif_Config
->pc_Device
;
6162 psdLockWriteDevice(pd
);
6163 if((binding
= pif
->pif_IfBinding
))
6165 pif
->pif_IfBinding
= NULL
;
6166 puc
= pif
->pif_ClsBinding
;
6169 pif
->pif_ClsBinding
= NULL
;
6170 usbDoMethod(UCM_ReleaseInterfaceBinding
, binding
);
6173 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6175 psdUnlockDevice(pd
);
6181 /* *** Events *** */
6183 /* /// "psdAddEventHandler()" */
6184 AROS_LH2(struct PsdEventHook
*, psdAddEventHandler
,
6185 AROS_LHA(struct MsgPort
*, mp
, A1
),
6186 AROS_LHA(ULONG
, msgmask
, D0
),
6187 LIBBASETYPEPTR
, ps
, 47, psd
)
6190 struct PsdEventHook
*peh
= NULL
;
6192 KPRINTF(5, ("psdAddEventHandler(%p, %p)\n", mp
, msgmask
));
6196 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6197 if((peh
= psdAllocVec(sizeof(struct PsdEventHook
))))
6199 peh
->peh_MsgPort
= mp
;
6200 peh
->peh_MsgMask
= msgmask
;
6201 AddTail(&ps
->ps_EventHooks
, &peh
->peh_Node
);
6203 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6210 /* /// "psdRemEventHandler()" */
6211 AROS_LH1(void, psdRemEventHandler
,
6212 AROS_LHA(struct PsdEventHook
*, peh
, A0
),
6213 LIBBASETYPEPTR
, ps
, 48, psd
)
6216 struct Message
*msg
;
6218 KPRINTF(5, ("psdRemEventHandler(%p)\n", peh
));
6223 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6224 Remove(&peh
->peh_Node
);
6225 while((msg
= GetMsg(peh
->peh_MsgPort
)))
6229 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6230 pGarbageCollectEvents(ps
);
6236 /* /// "psdSendEvent()" */
6237 AROS_LH3(void, psdSendEvent
,
6238 AROS_LHA(ULONG
, ehmt
, D0
),
6239 AROS_LHA(APTR
, param1
, A0
),
6240 AROS_LHA(APTR
, param2
, A1
),
6241 LIBBASETYPEPTR
, ps
, 49, psd
)
6244 struct PsdEventNote
*pen
;
6245 struct PsdEventHook
*peh
;
6246 ULONG msgmask
= (1L<<ehmt
);
6248 KPRINTF(1, ("psdSendEvent(%p, %p, %p)\n", ehmt
, param1
, param2
));
6250 pGarbageCollectEvents(ps
);
6251 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6252 peh
= (struct PsdEventHook
*) ps
->ps_EventHooks
.lh_Head
;
6253 while(peh
->peh_Node
.ln_Succ
)
6255 if(peh
->peh_MsgMask
& msgmask
)
6257 if((pen
= psdAllocVec(sizeof(struct PsdEventNote
))))
6259 pen
->pen_Msg
.mn_ReplyPort
= &ps
->ps_EventReplyPort
;
6260 pen
->pen_Msg
.mn_Length
= sizeof(struct PsdEventNote
);
6261 pen
->pen_Event
= ehmt
;
6262 pen
->pen_Param1
= param1
;
6263 pen
->pen_Param2
= param2
;
6264 PutMsg(peh
->peh_MsgPort
, &pen
->pen_Msg
);
6267 peh
= (struct PsdEventHook
*) peh
->peh_Node
.ln_Succ
;
6269 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6274 /* *** Configuration *** */
6276 /* /// "psdReadCfg()" */
6277 AROS_LH2(BOOL
, psdReadCfg
,
6278 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6279 AROS_LHA(APTR
, formdata
, A1
),
6280 LIBBASETYPEPTR
, ps
, 52, psd
)
6283 struct PsdIFFContext
*subpic
;
6286 ULONG
*buf
= formdata
;
6288 KPRINTF(10, ("psdReadCfg(%p, %p)\n", pic
, formdata
));
6290 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6293 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6294 if(!(pic
->pic_Node
.ln_Succ
))
6296 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6300 if((AROS_LONG2BE(*buf
) != ID_FORM
) || (AROS_LONG2BE(buf
[2]) != pic
->pic_FormID
))
6302 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to replace a cfg form with a chunk or with an alien form!");
6303 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6306 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6307 while(subpic
->pic_Node
.ln_Succ
)
6309 pFreeForm(ps
, subpic
);
6310 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6312 pic
->pic_ChunksLen
= 0;
6313 len
= (AROS_LONG2BE(buf
[1]) - 3) & ~1UL;
6317 if(!(pAddCfgChunk(ps
, pic
, buf
)))
6321 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
6323 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
6327 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to add a nasty corrupted FORM chunk! Configuration is probably b0rken!");
6331 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6332 ps
->ps_CheckConfigReq
= TRUE
;
6338 /* /// "psdLoadCfgFromDisk()" */
6339 AROS_LH1(BOOL
, psdLoadCfgFromDisk
,
6340 AROS_LHA(STRPTR
, filename
, A1
),
6341 LIBBASETYPEPTR
, ps
, 79, psd
)
6345 BOOL loaded
= FALSE
;
6350 XPRINTF(10, ("Loading config file: %s\n", filename
));
6354 loaded
= psdLoadCfgFromDisk("ENV:Sys/poseidon.prefs");
6360 loaded
= psdLoadCfgFromDisk("ENVARC:Sys/poseidon.prefs");
6367 KPRINTF(1, ("dos.library not available yet\n"));
6371 filehandle
= Open(filename
, MODE_OLDFILE
);
6372 KPRINTF(1, ("File handle 0x%p\n", filehandle
));
6375 if(Read(filehandle
, formhead
, 12) == 12)
6377 KPRINTF(1, ("Read header\n"));
6378 if((AROS_LONG2BE(formhead
[0]) == ID_FORM
) && (AROS_LONG2BE(formhead
[2]) == IFFFORM_PSDCFG
))
6380 formlen
= AROS_LONG2BE(formhead
[1]);
6381 KPRINTF(1, ("Header OK, %lu bytes\n", formlen
));
6383 buf
= (ULONG
*) psdAllocVec(formlen
+ 8);
6386 buf
[0] = formhead
[0];
6387 buf
[1] = formhead
[1];
6388 buf
[2] = formhead
[2];
6389 if(Read(filehandle
, &buf
[3], formlen
- 4) == formlen
- 4)
6391 KPRINTF(1, ("Data read OK\n"));
6393 psdReadCfg(NULL
, buf
);
6396 KPRINTF(1, ("All done\n"));
6405 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6406 "Failed to load config from '%s'!",
6411 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
;
6418 /* /// "psdSaveCfgToDisk()" */
6419 AROS_LH2(BOOL
, psdSaveCfgToDisk
,
6420 AROS_LHA(STRPTR
, filename
, A1
),
6421 AROS_LHA(BOOL
, executable
, D0
),
6422 LIBBASETYPEPTR
, ps
, 80, psd
)
6431 saved
= psdSaveCfgToDisk("ENVARC:Sys/poseidon.prefs", FALSE
);
6432 saved
&= psdSaveCfgToDisk("ENV:Sys/poseidon.prefs", FALSE
);
6440 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6442 buf
= (ULONG
*) psdWriteCfg(NULL
);
6446 filehandle
= Open(filename
, MODE_NEWFILE
);
6449 Write(filehandle
, buf
, (AROS_LONG2BE(buf
[1])+9) & ~1UL);
6453 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6454 "Failed to write config to '%s'!",
6459 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6462 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
;
6469 /* /// "psdWriteCfg()" */
6470 AROS_LH1(APTR
, psdWriteCfg
,
6471 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6472 LIBBASETYPEPTR
, ps
, 53, psd
)
6478 KPRINTF(10, ("psdWriteCfg(%p)\n", pic
));
6480 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6483 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6484 if(!(pic
->pic_Node
.ln_Succ
))
6486 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6490 pUpdateGlobalCfg(ps
, pic
);
6491 ps
->ps_CheckConfigReq
= TRUE
;
6492 len
= pGetFormLength(pic
);
6493 if((buf
= psdAllocVec(len
)))
6495 pInternalWriteForm(pic
, buf
);
6497 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6503 /* /// "psdFindCfgForm()" */
6504 AROS_LH2(struct PsdIFFContext
*, psdFindCfgForm
,
6505 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6506 AROS_LHA(ULONG
, formid
, D0
),
6507 LIBBASETYPEPTR
, ps
, 54, psd
)
6510 struct PsdIFFContext
*subpic
;
6512 KPRINTF(160, ("psdFindCfgForm(0x%p, 0x%08lx)\n", pic
, formid
));
6513 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6516 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6517 if(!(pic
->pic_Node
.ln_Succ
))
6519 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6523 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6524 while(subpic
->pic_Node
.ln_Succ
)
6526 if(subpic
->pic_FormID
== formid
)
6528 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6531 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
6533 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6539 /* /// "psdNextCfgForm()" */
6540 AROS_LH1(struct PsdIFFContext
*, psdNextCfgForm
,
6541 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6542 LIBBASETYPEPTR
, ps
, 55, psd
)
6546 KPRINTF(160, ("psdNextCfgForm(%p)\n", pic
));
6552 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6553 formid
= pic
->pic_FormID
;
6554 pic
= (struct PsdIFFContext
*) pic
->pic_Node
.ln_Succ
;
6555 while(pic
->pic_Node
.ln_Succ
)
6557 if(pic
->pic_FormID
== formid
)
6559 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6561 KPRINTF(1, ("Found context 0x%p\n", pic
));
6564 pic
= (struct PsdIFFContext
*) pic
->pic_Node
.ln_Succ
;
6566 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6572 /* /// "psdAllocCfgForm()" */
6573 AROS_LH1(struct PsdIFFContext
*, psdAllocCfgForm
,
6574 AROS_LHA(ULONG
, formid
, D0
),
6575 LIBBASETYPEPTR
, ps
, 86, psd
)
6578 struct PsdIFFContext
*pic
;
6579 KPRINTF(10, ("psdAllocCfgForm(%p)\n", formid
));
6580 if((pic
= psdAllocVec(sizeof(struct PsdIFFContext
))))
6582 NewList(&pic
->pic_SubForms
);
6583 //pic->pic_Parent = parent;
6584 pic
->pic_FormID
= formid
;
6585 pic
->pic_FormLength
= 4;
6586 pic
->pic_Chunks
= NULL
;
6587 pic
->pic_ChunksLen
= 0;
6588 pic
->pic_BufferLen
= 0;
6590 AddTail(&ps
->ps_AlienConfigs
, &pic
->pic_Node
);
6598 /* /// "psdRemCfgForm()" */
6599 AROS_LH1(void, psdRemCfgForm
,
6600 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6601 LIBBASETYPEPTR
, ps
, 56, psd
)
6604 KPRINTF(10, ("psdRemCfgForm(%p)\n", pic
));
6606 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6609 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6610 if(!(pic
->pic_Node
.ln_Succ
))
6612 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6617 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6618 ps
->ps_CheckConfigReq
= TRUE
;
6623 /* /// "psdAddCfgEntry()" */
6624 AROS_LH2(struct PsdIFFContext
*, psdAddCfgEntry
,
6625 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6626 AROS_LHA(APTR
, formdata
, A1
),
6627 LIBBASETYPEPTR
, ps
, 57, psd
)
6630 struct PsdIFFContext
*res
;
6632 KPRINTF(10, ("psdAddCfgEntry(%p, %p)\n", pic
, formdata
));
6633 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6636 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6637 if(!(pic
->pic_Node
.ln_Succ
))
6639 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6643 res
= pAddCfgChunk(ps
, pic
, formdata
);
6644 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6645 ps
->ps_CheckConfigReq
= TRUE
;
6651 /* /// "psdRemCfgChunk()" */
6652 AROS_LH2(BOOL
, psdRemCfgChunk
,
6653 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6654 AROS_LHA(ULONG
, chnkid
, D0
),
6655 LIBBASETYPEPTR
, ps
, 58, psd
)
6660 KPRINTF(10, ("psdRemCfgChunk(%p, %p)\n", pic
, chnkid
));
6661 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6664 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6665 if(!(pic
->pic_Node
.ln_Succ
))
6667 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6673 res
= pRemCfgChunk(ps
, pic
, chnkid
);
6675 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6676 while(subpic
->pic_Node
.ln_Succ
)
6678 pFreeForm(ps
, subpic
);
6680 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6682 if(pic
->pic_ChunksLen
)
6686 pic
->pic_ChunksLen
= 0;
6687 pic
->pic_FormLength
= 4;
6690 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6691 ps
->ps_CheckConfigReq
= TRUE
;
6697 /* /// "psdGetCfgChunk()" */
6698 AROS_LH2(APTR
, psdGetCfgChunk
,
6699 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6700 AROS_LHA(ULONG
, chnkid
, D0
),
6701 LIBBASETYPEPTR
, ps
, 59, psd
)
6707 KPRINTF(10, ("psdGetCfgChunk(%p, 0x%08lx)\n", pic
, chnkid
));
6709 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6712 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6713 if(!(pic
->pic_Node
.ln_Succ
))
6715 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6719 pUpdateGlobalCfg(ps
, pic
);
6720 chnk
= pFindCfgChunk(ps
, pic
, chnkid
);
6723 res
= psdAllocVec(AROS_LONG2BE(chnk
[1])+8);
6726 memcpy(res
, chnk
, AROS_LONG2BE(chnk
[1])+8);
6729 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6735 /* /// "psdParseCfg()" */
6736 AROS_LH0(void, psdParseCfg
,
6737 LIBBASETYPEPTR
, ps
, 60, psd
)
6740 struct PsdIFFContext
*pic
;
6741 struct PsdIFFContext
*subpic
;
6745 struct PsdHardware
*phw
;
6746 struct PsdUsbClass
*puc
;
6747 BOOL removeall
= TRUE
;
6748 BOOL nodos
= (FindTask(NULL
)->tc_Node
.ln_Type
!= NT_PROCESS
);
6751 XPRINTF(10, ("psdParseCfg()\n"));
6753 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6754 pCheckCfgChanged(ps
);
6755 pic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
);
6758 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6762 // if no config for hardware is found, we don't remove the devices,
6763 // because this could render the system useless (no USB mice or
6764 // keyboards to configure the hardware!)
6765 if(!psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
))
6767 XPRINTF(10, ("No hardware data present\n"));
6773 /* select all hardware devices for removal */
6774 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6775 while(phw
->phw_Node
.ln_Succ
)
6777 phw
->phw_RemoveMe
= removeall
;
6778 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
6781 /* select all classes for removal */
6782 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6783 while(puc
->puc_Node
.ln_Succ
)
6786 * For kickstart-resident classes we check usage count, and
6787 * remove them only if it's zero.
6788 * These classes can be responsible for devices which we can use
6789 * at boot time. If we happen to remove them, we can end up with
6790 * no input or storage devices at all.
6792 if (FindResident(puc
->puc_ClassName
))
6793 puc
->puc_RemoveMe
= (puc
->puc_UseCnt
== 0);
6795 puc
->puc_RemoveMe
= TRUE
;
6797 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6802 /* Get Hardware config */
6803 subpic
= psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
);
6806 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6809 name
= (STRPTR
) &chnk
[2];
6811 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_UNIT
);
6816 if(!pFindCfgChunk(ps
, subpic
, IFFCHNK_OFFLINE
))
6818 phw
= pFindHardware(ps
, name
, unit
);
6819 XPRINTF(5, ("Have configuration for device 0x%p (%s unit %u)\n", phw
, name
, unit
));
6822 phw
->phw_RemoveMe
= FALSE
;
6826 subpic
= psdNextCfgForm(subpic
);
6829 /* Get Class config */
6830 subpic
= psdFindCfgForm(pic
, IFFFORM_USBCLASS
);
6833 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6836 name
= (STRPTR
) &chnk
[2];
6837 puc
= (struct PsdUsbClass
*) pFindName(ps
, &ps
->ps_Classes
, name
);
6838 XPRINTF(5, ("Have configuration for class 0x%p (%s)\n", puc
, name
));
6841 puc
->puc_RemoveMe
= FALSE
;
6844 subpic
= psdNextCfgForm(subpic
);
6847 // unlock config while removing to avoid deadlocks.
6848 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6850 /* now remove remaining classes not found in the config */
6851 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6852 while(puc
->puc_Node
.ln_Succ
)
6854 if(puc
->puc_RemoveMe
)
6856 XPRINTF(5, ("Removing class %s\n", puc
->puc_ClassName
));
6858 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6860 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6864 /* now remove all remaining hardware not found in the config */
6865 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6866 while(phw
->phw_Node
.ln_Succ
)
6868 if(phw
->phw_RemoveMe
)
6870 XPRINTF(5, ("Removing device %s unit %u\n", phw
->phw_DevName
, phw
->phw_Unit
));
6871 psdRemHardware(phw
);
6872 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6874 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
6878 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6879 pic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
);
6882 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6887 /* Add missing Classes */
6888 subpic
= psdFindCfgForm(pic
, IFFFORM_USBCLASS
);
6891 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6894 /* *** FIXME *** POSSIBLE DEADLOCK WHEN CLASS TRIES TO DO CONFIG STUFF IN
6895 AN EXTERNAL TASK INSIDE LIBOPEN CODE */
6896 name
= (STRPTR
) &chnk
[2];
6897 puc
= (struct PsdUsbClass
*) pFindName(ps
, &ps
->ps_Classes
, name
);
6900 psdAddClass(name
, 0);
6903 subpic
= psdNextCfgForm(subpic
);
6906 /* Now really mount Hardware found in config */
6907 subpic
= psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
);
6910 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6913 name
= (STRPTR
) &chnk
[2];
6915 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_UNIT
);
6920 if(!pFindCfgChunk(ps
, subpic
, IFFCHNK_OFFLINE
))
6922 phw
= pFindHardware(ps
, name
, unit
);
6925 phw
= psdAddHardware(name
, unit
);
6928 #ifdef AROS_USB30_CODE
6929 if(psdEnumerateHardware(phw
) == NULL
) {
6930 psdRemHardware(phw
);
6933 psdEnumerateHardware(phw
);
6939 subpic
= psdNextCfgForm(subpic
);
6941 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6943 if(!nodos
&& ps
->ps_StartedAsTask
)
6945 // last time we were reading the config before DOS, so maybe we need to
6946 // unbind some classes that need to be overruled by newly available classes,
6947 // such as hid.class overruling bootmouse & bootkeyboard.
6948 // so unbind those classes that promote themselves as AfterDOS
6951 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Checking AfterDOS...");
6952 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6953 while(puc
->puc_Node
.ln_Succ
)
6956 usbGetAttrs(UGA_CLASS
, NULL
,
6957 UCCA_AfterDOSRestart
, &restartme
,
6960 if(restartme
&& puc
->puc_UseCnt
)
6962 struct PsdDevice
*pd
;
6963 struct PsdConfig
*pc
;
6964 struct PsdInterface
*pif
;
6966 /* Well, try to release the open bindings in a best effort attempt */
6968 while((pd
= psdGetNextDevice(pd
)))
6970 if(pd
->pd_DevBinding
&& (pd
->pd_ClsBinding
== puc
) && (!(pd
->pd_Flags
& PDFF_APPBINDING
)))
6973 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6974 "AfterDOS: Temporarily releasing %s %s binding to %s.",
6975 puc
->puc_ClassName
, "device", pd
->pd_ProductStr
);
6976 psdReleaseDevBinding(pd
);
6978 pd
= NULL
; /* restart */
6981 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
6982 while(pc
->pc_Node
.ln_Succ
)
6984 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
6985 while(pif
->pif_Node
.ln_Succ
)
6987 if(pif
->pif_IfBinding
&& (pif
->pif_ClsBinding
== puc
))
6990 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6991 "AfterDOS: Temporarily releasing %s %s binding to %s.",
6992 puc
->puc_ClassName
, "interface", pd
->pd_ProductStr
);
6993 psdReleaseIfBinding(pif
);
6995 pd
= NULL
; /* restart */
6998 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
7000 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
7004 usbDoMethodA(UCM_DOSAvailableEvent
, NULL
);
7005 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
7007 ps
->ps_StartedAsTask
= FALSE
;
7011 if(nodos
&& (!ps
->ps_ConfigRead
))
7013 // it's the first time we were reading the config and DOS was not available
7014 ps
->ps_StartedAsTask
= TRUE
;
7016 ps
->ps_ConfigRead
= TRUE
;
7017 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
; // update saved hash
7019 /* do a class scan */
7022 if(nodos
&& ps
->ps_GlobalCfg
->pgc_BootDelay
)
7024 // wait for hubs to settle
7026 puc
= (struct PsdUsbClass
*) FindName(&ps
->ps_Classes
, "massstorage.class");
7027 if(puc
&& puc
->puc_UseCnt
)
7029 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
7030 "Delaying further execution by %ld second(s) (boot delay).",
7031 ps
->ps_GlobalCfg
->pgc_BootDelay
);
7032 if(ps
->ps_GlobalCfg
->pgc_BootDelay
>= 1)
7034 psdDelayMS((ps
->ps_GlobalCfg
->pgc_BootDelay
-1)*1000);
7037 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Boot delay skipped, no mass storage devices found.");
7044 /* /// "psdSetClsCfg()" */
7045 AROS_LH2(BOOL
, psdSetClsCfg
,
7046 AROS_LHA(STRPTR
, owner
, A0
),
7047 AROS_LHA(APTR
, form
, A1
),
7048 LIBBASETYPEPTR
, ps
, 62, psd
)
7051 struct PsdIFFContext
*pic
;
7052 BOOL result
= FALSE
;
7054 KPRINTF(10, ("psdSetClsCfg(%s, %p)\n", owner
, form
));
7055 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7056 pic
= psdFindCfgForm(NULL
, IFFFORM_CLASSCFG
);
7059 if(pMatchStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7061 pic
= psdFindCfgForm(pic
, IFFFORM_CLASSDATA
);
7066 result
= psdReadCfg(pic
, form
);
7068 psdRemCfgChunk(pic
, 0);
7076 pic
= psdNextCfgForm(pic
);
7080 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7081 pCheckCfgChanged(ps
);
7084 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7085 if(pic
->pic_Node
.ln_Succ
)
7087 pic
= pAllocForm(ps
, pic
, IFFFORM_CLASSCFG
);
7090 if(pAddStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7094 if(pAddCfgChunk(ps
, pic
, form
))
7096 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7097 pCheckCfgChanged(ps
);
7102 buf
[0] = AROS_LONG2BE(ID_FORM
);
7103 buf
[1] = AROS_LONG2BE(4);
7104 buf
[2] = AROS_LONG2BE(IFFFORM_CLASSDATA
);
7105 if(pAddCfgChunk(ps
, pic
, buf
))
7107 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7108 pCheckCfgChanged(ps
);
7115 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7116 pCheckCfgChanged(ps
);
7122 /* /// "psdGetClsCfg()" */
7123 AROS_LH1(struct PsdIFFContext
*, psdGetClsCfg
,
7124 AROS_LHA(STRPTR
, owner
, A0
),
7125 LIBBASETYPEPTR
, ps
, 63, psd
)
7128 struct PsdIFFContext
*pic
;
7130 KPRINTF(10, ("psdGetClsCfg(%s)\n", owner
));
7131 pic
= psdFindCfgForm(NULL
, IFFFORM_CLASSCFG
);
7134 if(pMatchStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7136 return(psdFindCfgForm(pic
, IFFFORM_CLASSDATA
));
7138 pic
= psdNextCfgForm(pic
);
7145 /* /// "psdSetUsbDevCfg()" */
7146 AROS_LH4(BOOL
, psdSetUsbDevCfg
,
7147 AROS_LHA(STRPTR
, owner
, A0
),
7148 AROS_LHA(STRPTR
, devid
, A2
),
7149 AROS_LHA(STRPTR
, ifid
, A3
),
7150 AROS_LHA(APTR
, form
, A1
),
7151 LIBBASETYPEPTR
, ps
, 64, psd
)
7154 struct PsdIFFContext
*pic
;
7155 struct PsdIFFContext
*cpic
= NULL
;
7156 struct PsdIFFContext
*mpic
= NULL
;
7157 BOOL result
= FALSE
;
7159 KPRINTF(10, ("psdSetUsbDevCfg(%s, %s, %s, %p)\n", owner
, devid
, ifid
, form
));
7160 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7161 /* Find device config form. It contains all device config data */
7162 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7165 /* Find DEVID-Chunk. Check if it matches our device id */
7166 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7169 /* We found the correct device. Now if we need to store interface data, find the interface first */
7172 /* Search interface config form */
7173 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7176 /* Found the form. Find the the ID String for the interface */
7177 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7179 /* ID did match, now check for owner */
7180 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7182 /* found it! So there is already a config saved in there. Search for dev config data form */
7183 cpic
= psdFindCfgForm(mpic
, IFFFORM_IFCLSDATA
);
7186 /* not found, generate it */
7187 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7192 mpic
= psdNextCfgForm(mpic
);
7196 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7198 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7200 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7202 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7208 /* Search for device config */
7209 mpic
= psdFindCfgForm(pic
, IFFFORM_DEVCFGDATA
);
7212 /* search for the right owner */
7213 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7215 /* found it! So there is already a config saved in there. Search for dev config data form */
7216 cpic
= psdFindCfgForm(mpic
, IFFFORM_DEVCLSDATA
);
7219 /* not found, generate it */
7220 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7224 mpic
= psdNextCfgForm(mpic
);
7226 if(!cpic
) /* no device config form */
7228 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_DEVCFGDATA
)))
7230 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7232 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7241 result
= psdReadCfg(cpic
, form
);
7243 psdRemCfgChunk(cpic
, 0);
7249 pic
= psdNextCfgForm(pic
);
7253 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7254 pCheckCfgChanged(ps
);
7258 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7259 if(pic
->pic_Node
.ln_Succ
)
7261 pic
= pAllocForm(ps
, pic
, IFFFORM_DEVICECFG
);
7264 if(pAddStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7268 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7270 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7272 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7274 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7279 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_DEVCFGDATA
)))
7281 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7283 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7291 result
= psdReadCfg(cpic
, form
);
7293 psdRemCfgChunk(cpic
, 0);
7300 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7301 pCheckCfgChanged(ps
);
7307 /* /// "psdGetUsbDevCfg()" */
7308 AROS_LH3(struct PsdIFFContext
*, psdGetUsbDevCfg
,
7309 AROS_LHA(STRPTR
, owner
, A0
),
7310 AROS_LHA(STRPTR
, devid
, A2
),
7311 AROS_LHA(STRPTR
, ifid
, A3
),
7312 LIBBASETYPEPTR
, ps
, 65, psd
)
7315 struct PsdIFFContext
*pic
;
7316 struct PsdIFFContext
*cpic
= NULL
;
7317 struct PsdIFFContext
*mpic
= NULL
;
7319 KPRINTF(10, ("psdGetUsbDevCfg(%s, %s, %s)\n", owner
, devid
, ifid
));
7320 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7321 /* Find device config form. It contains all device config data */
7322 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7325 /* Find DEVID-Chunk. Check if it matches our device id */
7326 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7329 /* We found the correct device. Now if we need to store interface data, find the interface first */
7332 /* Search interface config form */
7333 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7336 /* Found the form. Find the the ID String for the interface */
7337 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7339 /* ID did match, now check for owner */
7340 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7342 /* found it! So there is already a config saved in there. Search for dev config data form */
7343 cpic
= psdFindCfgForm(mpic
, IFFFORM_IFCLSDATA
);
7347 mpic
= psdNextCfgForm(mpic
);
7350 /* Search for device config */
7351 mpic
= psdFindCfgForm(pic
, IFFFORM_DEVCFGDATA
);
7354 /* search for the right owner */
7355 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7357 /* found it! So there is already a config saved in there. Search for dev config data form */
7358 cpic
= psdFindCfgForm(mpic
, IFFFORM_DEVCLSDATA
);
7361 mpic
= psdNextCfgForm(mpic
);
7366 pic
= psdNextCfgForm(pic
);
7368 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7369 KPRINTF(1, ("Result %p\n", cpic
));
7375 /* /// "psdSetForcedBinding()" */
7376 AROS_LH3(BOOL
, psdSetForcedBinding
,
7377 AROS_LHA(STRPTR
, owner
, A2
),
7378 AROS_LHA(STRPTR
, devid
, A0
),
7379 AROS_LHA(STRPTR
, ifid
, A1
),
7380 LIBBASETYPEPTR
, ps
, 69, psd
)
7383 struct PsdIFFContext
*pic
;
7384 struct PsdIFFContext
*mpic
= NULL
;
7386 BOOL result
= FALSE
;
7390 olen
= strlen(owner
);
7392 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7393 /* Find device config form. It contains all device config data */
7394 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7397 /* Find DEVID-Chunk. Check if it matches our device id */
7398 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7400 /* We found the correct device. Now if we need to store interface data, find the interface first */
7403 /* Search interface config form */
7404 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7407 /* Found the form. Find the the ID String for the interface */
7408 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7410 /* ID did match, insert/replace forced binding */
7413 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7418 pRemCfgChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
);
7422 mpic
= psdNextCfgForm(mpic
);
7428 if((!result
) && olen
)
7430 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7432 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7434 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7436 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7445 /* Add FBND chunk */
7448 if(pAddStringChunk(ps
, pic
, IFFCHNK_FORCEDBIND
, owner
))
7453 pRemCfgChunk(ps
, pic
, IFFCHNK_FORCEDBIND
);
7459 pic
= psdNextCfgForm(pic
);
7467 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7468 pCheckCfgChanged(ps
);
7471 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7472 if(pic
->pic_Node
.ln_Succ
)
7474 pic
= pAllocForm(ps
, pic
, IFFFORM_DEVICECFG
);
7477 if(pAddStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7481 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7483 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7485 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7487 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7495 /* Add FBND chunk */
7496 if(pAddStringChunk(ps
, pic
, IFFCHNK_FORCEDBIND
, owner
))
7504 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7505 pCheckCfgChanged(ps
);
7511 /* /// "psdGetForcedBinding()" */
7512 AROS_LH2(STRPTR
, psdGetForcedBinding
,
7513 AROS_LHA(STRPTR
, devid
, A0
),
7514 AROS_LHA(STRPTR
, ifid
, A1
),
7515 LIBBASETYPEPTR
, ps
, 70, psd
)
7518 struct PsdIFFContext
*pic
;
7519 struct PsdIFFContext
*mpic
= NULL
;
7521 STRPTR owner
= NULL
;
7523 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7524 /* Find device config form. It contains all device config data */
7525 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7528 /* Find DEVID-Chunk. Check if it matches our device id */
7529 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7531 /* We found the correct device. Now if we need to store interface data, find the interface first */
7534 /* Search interface config form */
7535 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7538 /* Found the form. Find the the ID String for the interface */
7539 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7541 /* ID did match, now check for forced binding */
7542 chunk
= pFindCfgChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
);
7545 owner
= (STRPTR
) &chunk
[2];
7549 mpic
= psdNextCfgForm(mpic
);
7552 /* Search for device forced binding */
7553 chunk
= pFindCfgChunk(ps
, pic
, IFFCHNK_FORCEDBIND
);
7556 owner
= (STRPTR
) &chunk
[2];
7562 pic
= psdNextCfgForm(pic
);
7564 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7570 /* /// "psdAddStringChunk()" */
7571 AROS_LH3(BOOL
, psdAddStringChunk
,
7572 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7573 AROS_LHA(ULONG
, chunkid
, D0
),
7574 AROS_LHA(CONST_STRPTR
, str
, A1
),
7575 LIBBASETYPEPTR
, ps
, 87, psd
)
7579 KPRINTF(10, ("psdAddStringChunk(%p, %p, %s)\n", pic
, chunkid
, str
));
7580 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7581 res
= pAddStringChunk(ps
, pic
, chunkid
, str
);
7582 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7588 /* /// "psdMatchStringChunk()" */
7589 AROS_LH3(BOOL
, psdMatchStringChunk
,
7590 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7591 AROS_LHA(ULONG
, chunkid
, D0
),
7592 AROS_LHA(CONST_STRPTR
, str
, A1
),
7593 LIBBASETYPEPTR
, ps
, 88, psd
)
7597 KPRINTF(10, ("psdMatchStringChunk(%p, %p, %s)\n", pic
, chunkid
, str
));
7598 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7599 res
= pMatchStringChunk(ps
, pic
, chunkid
, str
);
7600 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7606 /* /// "psdGetStringChunk()" */
7607 AROS_LH2(STRPTR
, psdGetStringChunk
,
7608 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7609 AROS_LHA(ULONG
, chunkid
, D0
),
7610 LIBBASETYPEPTR
, ps
, 89, psd
)
7614 KPRINTF(10, ("psdGetStringChunk(%p, %p)\n", pic
, chunkid
));
7615 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7616 str
= pGetStringChunk(ps
, pic
, chunkid
);
7617 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7623 /* *** Configuration (non-library subroutines) *** */
7625 /* /// "pAllocForm()" */
7626 struct PsdIFFContext
* pAllocForm(LIBBASETYPEPTR ps
, struct PsdIFFContext
*parent
, ULONG formid
)
7628 struct PsdIFFContext
*pic
;
7629 KPRINTF(10, ("pAllocForm(%p, %p)\n", parent
, formid
));
7630 if((pic
= psdAllocVec(sizeof(struct PsdIFFContext
))))
7632 NewList(&pic
->pic_SubForms
);
7633 //pic->pic_Parent = parent;
7634 pic
->pic_FormID
= formid
;
7635 pic
->pic_FormLength
= 4;
7636 pic
->pic_Chunks
= NULL
;
7637 pic
->pic_ChunksLen
= 0;
7638 pic
->pic_BufferLen
= 0;
7642 AddTail(&parent
->pic_SubForms
, &pic
->pic_Node
);
7644 AddTail(&ps
->ps_ConfigRoot
, &pic
->pic_Node
);
7652 /* /// "pFreeForm()" */
7653 void pFreeForm(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
)
7655 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7656 KPRINTF(10, ("pFreeForm(%p)\n", pic
));
7657 Remove(&pic
->pic_Node
);
7658 while(subpic
->pic_Node
.ln_Succ
)
7660 pFreeForm(ps
, subpic
);
7661 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7663 psdFreeVec(pic
->pic_Chunks
);
7668 /* /// "pGetFormLength()" */
7669 ULONG
pGetFormLength(struct PsdIFFContext
*pic
)
7671 ULONG len
= (5 + pic
->pic_ChunksLen
) & ~1UL;
7672 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7673 //KPRINTF(10, ("pGetFormLength(%p)\n", pic));
7674 while(subpic
->pic_Node
.ln_Succ
)
7676 len
+= pGetFormLength(subpic
);
7677 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7679 pic
->pic_FormLength
= len
;
7680 //KPRINTF(10, ("FormLen=%ld\n", len+8));
7685 /* /// "pFindCfgChunk()" */
7686 APTR
pFindCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chnkid
)
7688 ULONG
*buf
= pic
->pic_Chunks
;
7689 ULONG len
= pic
->pic_ChunksLen
;
7691 KPRINTF(10, ("pFindCfgChunk(%p, %p)\n", pic
, chnkid
));
7695 if(AROS_LONG2BE(*buf
) == chnkid
)
7697 KPRINTF(10, ("Found at %p\n", buf
));
7700 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7702 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7704 KPRINTF(10, ("Not found!\n"));
7709 /* /// "pRemCfgChunk()" */
7710 BOOL
pRemCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chnkid
)
7712 ULONG
*buf
= pic
->pic_Chunks
;
7713 ULONG len
= pic
->pic_ChunksLen
;
7715 KPRINTF(10, ("pRemCfgChunk(%p, %p)\n", pic
, chnkid
));
7719 chlen
= ((AROS_LONG2BE(buf
[1])) + 9) & ~1UL;
7720 if(AROS_LONG2BE(*buf
) == chnkid
)
7725 memcpy(buf
, &((UBYTE
*) buf
)[chlen
], (size_t) len
);
7727 pic
->pic_ChunksLen
-= chlen
;
7728 KPRINTF(10, ("Deleted %ld bytes to %ld chunk len\n", chlen
, pic
->pic_ChunksLen
));
7732 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7734 KPRINTF(10, ("Not found!\n"));
7739 /* /// "pAddCfgChunk()" */
7740 struct PsdIFFContext
* pAddCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, APTR chunk
)
7746 struct PsdIFFContext
*subpic
;
7747 KPRINTF(10, ("pAddCfgChunk(%p, %p)\n", pic
, chunk
));
7748 if(AROS_LONG2BE(*buf
) == ID_FORM
)
7751 len
= ((AROS_LONG2BE(*buf
)) - 3) & ~1UL;
7753 if((subpic
= pAllocForm(ps
, pic
, AROS_LONG2BE(*buf
))))
7758 if(!(pAddCfgChunk(ps
, subpic
, buf
)))
7762 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7764 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7768 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to add a nasty corrupted FORM chunk! Configuration is probably b0rken!");
7776 pRemCfgChunk(ps
, pic
, AROS_LONG2BE(*buf
));
7777 len
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7778 if(pic
->pic_ChunksLen
+len
> pic
->pic_BufferLen
)
7780 KPRINTF(10, ("expanding buffer from %ld to %ld to fit %ld bytes\n", pic
->pic_BufferLen
, (pic
->pic_ChunksLen
+len
)<<1, pic
->pic_ChunksLen
+len
));
7783 if((newbuf
= psdAllocVec((pic
->pic_ChunksLen
+len
)<<1)))
7785 if(pic
->pic_ChunksLen
)
7787 memcpy(newbuf
, pic
->pic_Chunks
, (size_t) pic
->pic_ChunksLen
);
7788 psdFreeVec(pic
->pic_Chunks
);
7790 pic
->pic_Chunks
= newbuf
;
7791 pic
->pic_BufferLen
= (pic
->pic_ChunksLen
+len
)<<1;
7796 memcpy(&(((UBYTE
*) pic
->pic_Chunks
)[pic
->pic_ChunksLen
]), chunk
, (size_t) len
);
7797 pic
->pic_ChunksLen
+= len
;
7803 /* /// "pInternalWriteForm()" */
7804 ULONG
* pInternalWriteForm(struct PsdIFFContext
*pic
, ULONG
*buf
)
7806 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7807 //KPRINTF(10, ("pInternalWriteForm(%p, %p)", pic, buf));
7808 *buf
++ = AROS_LONG2BE(ID_FORM
);
7809 *buf
++ = AROS_LONG2BE(pic
->pic_FormLength
);
7810 *buf
++ = AROS_LONG2BE(pic
->pic_FormID
);
7811 if(pic
->pic_ChunksLen
)
7813 memcpy(buf
, pic
->pic_Chunks
, (size_t) pic
->pic_ChunksLen
);
7814 buf
= (ULONG
*) (((UBYTE
*) buf
) + pic
->pic_ChunksLen
);
7816 while(subpic
->pic_Node
.ln_Succ
)
7818 buf
= pInternalWriteForm(subpic
, buf
);
7819 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7825 /* /// "pCalcCfgCRC()" */
7826 ULONG
pCalcCfgCRC(struct PsdIFFContext
*pic
)
7828 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7830 ULONG crc
= pic
->pic_FormID
;
7833 //KPRINTF(10, ("pInternalWriteForm(%p, %p)", pic, buf));
7834 if(pic
->pic_ChunksLen
)
7836 len
= pic
->pic_ChunksLen
>>1;
7839 ptr
= (UWORD
*) pic
->pic_Chunks
;
7842 crc
= ((crc
<<1)|(crc
>>31))^(*ptr
++);
7846 while(subpic
->pic_Node
.ln_Succ
)
7848 crc
^= pCalcCfgCRC(subpic
);
7849 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7855 /* /// "pCheckCfgChanged()" */
7856 BOOL
pCheckCfgChanged(LIBBASETYPEPTR ps
)
7859 struct PsdIFFContext
*pic
;
7860 struct PsdIFFContext
*subpic
;
7863 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7864 ps
->ps_CheckConfigReq
= FALSE
;
7865 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7866 if(!(pic
->pic_Node
.ln_Succ
))
7868 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7871 crc
= pCalcCfgCRC(pic
);
7872 if(crc
!= ps
->ps_ConfigHash
)
7875 ps
->ps_ConfigHash
= crc
;
7876 /* Get Global config */
7877 if((subpic
= psdFindCfgForm(pic
, IFFFORM_STACKCFG
)))
7879 if((chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_GLOBALCFG
)))
7881 CopyMem(&chnk
[2], ((UBYTE
*) ps
->ps_GlobalCfg
) + 8, min(AROS_LONG2BE(chnk
[1]), AROS_LONG2BE(ps
->ps_GlobalCfg
->pgc_Length
)));
7883 if(!pMatchStringChunk(ps
, subpic
, IFFCHNK_INSERTSND
, ps
->ps_PoPo
.po_InsertSndFile
))
7885 if((tmpstr
= pGetStringChunk(ps
, subpic
, IFFCHNK_INSERTSND
)))
7887 psdFreeVec(ps
->ps_PoPo
.po_InsertSndFile
);
7888 ps
->ps_PoPo
.po_InsertSndFile
= tmpstr
;
7891 if(!pMatchStringChunk(ps
, subpic
, IFFCHNK_REMOVESND
, ps
->ps_PoPo
.po_RemoveSndFile
))
7893 if((tmpstr
= pGetStringChunk(ps
, subpic
, IFFCHNK_REMOVESND
)))
7895 psdFreeVec(ps
->ps_PoPo
.po_RemoveSndFile
);
7896 ps
->ps_PoPo
.po_RemoveSndFile
= tmpstr
;
7900 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7901 psdSendEvent(EHMB_CONFIGCHG
, NULL
, NULL
);
7904 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7909 /* /// "pAddStringChunk()" */
7910 BOOL
pAddStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
, CONST_STRPTR str
)
7913 ULONG len
= strlen(str
);
7914 ULONG
*chnk
= (ULONG
*) psdAllocVec((ULONG
) len
+8+2);
7917 chnk
[0] = AROS_LONG2BE(chunkid
);
7918 chnk
[1] = AROS_LONG2BE(len
+1);
7919 strcpy((STRPTR
) &chnk
[2], str
);
7920 if(pAddCfgChunk(ps
, pic
, chnk
))
7930 /* /// "pMatchStringChunk()" */
7931 BOOL
pMatchStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
, CONST_STRPTR str
)
7936 if((chunk
= pFindCfgChunk(ps
, pic
, chunkid
)))
7938 srcptr
= (STRPTR
) &chunk
[2];
7939 len
= AROS_LONG2BE(chunk
[1]);
7940 while(len
-- && *srcptr
)
7942 if(*str
++ != *srcptr
++)
7956 /* /// "pGetStringChunk()" */
7957 STRPTR
pGetStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
)
7961 if((chunk
= pFindCfgChunk(ps
, pic
, chunkid
)))
7963 if((str
= (STRPTR
) psdAllocVec(AROS_LONG2BE(chunk
[1]) + 1)))
7965 memcpy(str
, &chunk
[2], (size_t) AROS_LONG2BE(chunk
[1]));
7973 /* /// "pUpdateGlobalCfg()" */
7974 void pUpdateGlobalCfg(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
)
7976 struct PsdIFFContext
*tmppic
;
7977 /* Set Global config */
7978 if(pic
== (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
)
7980 if((tmppic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
)))
7982 pAddCfgChunk(ps
, tmppic
, ps
->ps_GlobalCfg
);
7983 pAddStringChunk(ps
, tmppic
, IFFCHNK_INSERTSND
, ps
->ps_PoPo
.po_InsertSndFile
);
7984 pAddStringChunk(ps
, tmppic
, IFFCHNK_REMOVESND
, ps
->ps_PoPo
.po_RemoveSndFile
);
7990 /* *** Misc (non library functions) ***/
7992 /* /// "pGetDevConfig()" */
7993 BOOL
pGetDevConfig(struct PsdPipe
*pp
)
7995 struct PsdDevice
*pd
= pp
->pp_Device
;
7996 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
7998 struct UsbStdCfgDesc uscd
;
8004 KPRINTF(1, ("Getting configuration descriptor...\n"));
8005 psdLockWriteDevice(pd
);
8006 while(curcfg
< pd
->pd_NumCfgs
)
8008 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
8009 USR_GET_DESCRIPTOR
, (UDT_CONFIGURATION
<<8)|curcfg
, 0);
8011 /*tempbuf = psdAllocVec(256);
8012 ioerr = psdDoPipe(pp, tempbuf, 34);
8013 if(ioerr == UHIOERR_RUNTPACKET)
8017 memcpy(&uscd, tempbuf, 9);*/
8018 ioerr
= psdDoPipe(pp
, &uscd
, 9);//sizeof(struct UsbStdCfgDesc));
8021 KPRINTF(1, ("Config type: %ld\n", (ULONG
) uscd
.bDescriptorType
));
8022 len
= (ULONG
) AROS_WORD2LE(uscd
.wTotalLength
);
8023 KPRINTF(1, ("Configsize %ld, total size %ld\n", (ULONG
) uscd
.bLength
, len
));
8024 if((tempbuf
= psdAllocVec(len
)))
8027 KPRINTF(1, ("Getting whole configuration descriptor...\n"));
8028 ioerr
= psdDoPipe(pp
, tempbuf
, len
);
8031 struct PsdConfig
*pc
= NULL
;
8032 struct PsdInterface
*pif
= NULL
;
8033 struct PsdInterface
*altif
= NULL
;
8034 struct PsdEndpoint
*pep
= NULL
;
8035 struct PsdDescriptor
*pdd
= NULL
;
8036 UBYTE
*dbuf
= tempbuf
;
8039 bufend
= &dbuf
[len
];
8040 while(dbuf
< bufend
)
8042 dlen
= dbuf
[0]; /* bLength */
8047 if(&dbuf
[dlen
] > bufend
)
8049 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "End of descriptor past buffer!");
8051 switch(dbuf
[1]) /* bDescriptorType */
8053 case UDT_CONFIGURATION
:
8055 struct UsbStdCfgDesc
*usc
= (struct UsbStdCfgDesc
*) dbuf
;
8059 if((pc
= pAllocConfig(pd
)))
8061 pd
->pd_Flags
|= PDFF_CONFIGURED
;
8062 pc
->pc_NumIfs
= usc
->bNumInterfaces
;
8063 pc
->pc_CfgNum
= usc
->bConfigurationValue
;
8064 pc
->pc_Attr
= usc
->bmAttributes
;
8065 pc
->pc_MaxPower
= usc
->bMaxPower
<<1;
8067 KPRINTF(1, (" Config %ld\n", pc
->pc_CfgNum
));
8068 if(usc
->iConfiguration
)
8070 pc
->pc_CfgStr
= psdGetStringDescriptor(pp
, usc
->iConfiguration
);
8074 pc
->pc_CfgStr
= psdCopyStrFmt("Configuration %ld", pc
->pc_CfgNum
);
8077 KPRINTF(20, (" Config allocation failed\n"));
8084 struct UsbStdIfDesc
*usif
= (struct UsbStdIfDesc
*) dbuf
;
8088 if((altif
= pAllocInterface(pc
)))
8090 altif
->pif_IfNum
= usif
->bInterfaceNumber
;
8091 altif
->pif_Alternate
= usif
->bAlternateSetting
;
8092 altif
->pif_NumEPs
= usif
->bNumEndpoints
;
8093 altif
->pif_IfClass
= usif
->bInterfaceClass
;
8094 altif
->pif_IfSubClass
= usif
->bInterfaceSubClass
;
8095 altif
->pif_IfProto
= usif
->bInterfaceProtocol
;
8096 KPRINTF(2, (" Interface %ld\n", altif
->pif_IfNum
));
8097 if(usif
->iInterface
)
8099 altif
->pif_IfStr
= psdGetStringDescriptor(pp
, usif
->iInterface
);
8101 if(!altif
->pif_IfStr
)
8103 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) altif
->pif_IfClass
, NULL
);
8106 altif
->pif_IfStr
= psdCopyStrFmt("%s interface (%ld)", classname
, altif
->pif_IfNum
);
8108 altif
->pif_IfStr
= psdCopyStrFmt("Interface %ld", altif
->pif_IfNum
);
8111 KPRINTF(2, (" IfName : %s\n"
8112 " Alternate : %ld\n"
8115 " IfSubClass: %ld\n"
8117 altif
->pif_IfStr
, altif
->pif_Alternate
,
8120 altif
->pif_IfSubClass
, altif
->pif_IfProto
));
8121 if(pc
->pc_CfgNum
== 1)
8123 altif
->pif_IDString
= psdCopyStrFmt("%02lx-%02lx-%02lx-%02lx-%02lx",
8124 altif
->pif_IfNum
, altif
->pif_Alternate
,
8125 altif
->pif_IfClass
, altif
->pif_IfSubClass
,
8126 altif
->pif_IfProto
);
8128 // for more than one config, add config number (retain backwards compatibility with most devices)
8129 altif
->pif_IDString
= psdCopyStrFmt("%02lx-%02lx-%02lx-%02lx-%02lx-%02lx",
8131 altif
->pif_IfNum
, altif
->pif_Alternate
,
8132 altif
->pif_IfClass
, altif
->pif_IfSubClass
,
8133 altif
->pif_IfProto
);
8136 /* Move the interface to the alternatives if possible */
8137 if(altif
->pif_Alternate
)
8141 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Alternate interface without prior main interface!");
8142 KPRINTF(20, (" Alternate interface without prior main interface\n"));
8145 Remove(&altif
->pif_Node
);
8146 AddTail(&pif
->pif_AlterIfs
, &altif
->pif_Node
);
8147 altif
->pif_ParentIf
= pif
;
8150 altif
->pif_ParentIf
= NULL
;
8154 KPRINTF(20, (" Interface allocation failed\n"));
8157 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Interface without prior config descriptor!");
8158 KPRINTF(20, (" Interface descriptor without Config\n"));
8165 struct UsbStdEPDesc
*usep
= (struct UsbStdEPDesc
*) dbuf
;
8168 if((pep
= pAllocEndpoint(altif
)))
8171 pep
->pep_EPNum
= usep
->bEndpointAddress
& 0x0f;
8172 pep
->pep_Direction
= usep
->bEndpointAddress
>>7;
8173 pep
->pep_TransType
= usep
->bmAttributes
& 0x03;
8174 pep
->pep_SyncType
= (usep
->bmAttributes
>>2) & 0x03;
8175 pep
->pep_UsageType
= (usep
->bmAttributes
>>4) & 0x03;
8176 eptype
= (pep
->pep_TransType
== USEAF_INTERRUPT
) ? "int" : "iso";
8178 pep
->pep_MaxPktSize
= AROS_WORD2LE(usep
->wMaxPacketSize
) & 0x07ff;
8179 pep
->pep_NumTransMuFr
= ((AROS_WORD2LE(usep
->wMaxPacketSize
)>>11) & 3) + 1;
8180 if(pep
->pep_NumTransMuFr
== 4)
8182 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint contains illegal Num Trans �Frame value!");
8183 pep
->pep_NumTransMuFr
= 1;
8186 pep
->pep_Interval
= usep
->bInterval
;
8187 if(pd
->pd_Flags
& PDFF_HIGHSPEED
)
8189 switch(pep
->pep_TransType
)
8193 //pep->pep_Interval = 0; // no use here, NAK rate not of interest
8196 case USEAF_ISOCHRONOUS
:
8197 if(pep
->pep_MaxPktSize
> 1024)
8199 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8200 "Endpoint contains %s (%ld) MaxPktSize value!",
8201 (STRPTR
) "too high", pep
->pep_MaxPktSize
);
8202 pep
->pep_MaxPktSize
= 1024;
8205 case USEAF_INTERRUPT
:
8206 if(!pep
->pep_Interval
)
8208 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8209 "%sspeed %s endpoint contains %s interval value! Fixing.",
8210 (STRPTR
) "High", eptype
, (STRPTR
) "zero");
8211 pep
->pep_Interval
= 1;
8213 else if(pep
->pep_Interval
> 16)
8215 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8216 "%sspeed %s endpoint contains %s interval value! Fixing.",
8217 (STRPTR
) "High", eptype
, (STRPTR
) "too high");
8218 pep
->pep_Interval
= 16;
8220 pep
->pep_Interval
= 1<<(pep
->pep_Interval
-1);
8224 else if(pd
->pd_Flags
& PDFF_LOWSPEED
)
8226 switch(pep
->pep_TransType
)
8228 case USEAF_INTERRUPT
:
8229 if(pep
->pep_Interval
< 8)
8231 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8232 (STRPTR
) "Low", eptype
, (STRPTR
) "too low");
8233 pep
->pep_Interval
= 8;
8239 pep
->pep_Interval
= 0; // no use here
8242 case USEAF_ISOCHRONOUS
:
8243 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Lowspeed devices cannot have isochronous endpoints!");
8247 switch(pep
->pep_TransType
)
8249 case USEAF_INTERRUPT
:
8250 if(!pep
->pep_Interval
)
8252 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8253 (STRPTR
) "Full", eptype
, (STRPTR
) "zero");
8254 pep
->pep_Interval
= 1;
8260 pep
->pep_Interval
= 0; // no use here
8263 case USEAF_ISOCHRONOUS
:
8264 if(pep
->pep_MaxPktSize
> 1023)
8266 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint contains too high (%ld) MaxPktSize value! Fixing.", pep
->pep_MaxPktSize
);
8267 pep
->pep_MaxPktSize
= 1023;
8269 if(!pep
->pep_Interval
)
8271 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8272 (STRPTR
) "Full", eptype
, (STRPTR
) "zero");
8273 pep
->pep_Interval
= 1;
8275 else if(pep
->pep_Interval
> 16)
8277 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8278 (STRPTR
) "Full", eptype
, (STRPTR
) "too high");
8279 pep
->pep_Interval
= 16;
8281 pep
->pep_Interval
= 1<<(pep
->pep_Interval
-1);
8286 KPRINTF(2, (" Endpoint %ld\n", pep
->pep_EPNum
));
8287 KPRINTF(2, (" Direction : %s\n"
8288 " TransType : %ld\n"
8289 " MaxPktSize: %ld\n"
8290 " Interval : %ld\n",
8291 (pep
->pep_Direction
? "IN" : "OUT"),
8292 pep
->pep_TransType
, pep
->pep_MaxPktSize
,
8293 pep
->pep_Interval
));
8296 KPRINTF(20, (" Endpoint allocation failed\n"));
8299 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint without prior interface descriptor!");
8300 KPRINTF(20, (" Endpoint descriptor without Interface\n"));
8310 case UDT_CS_INTERFACE
:
8311 case UDT_CS_ENDPOINT
:
8312 case UDT_DEVICE_QUALIFIER
:
8313 case UDT_OTHERSPEED_QUALIFIER
:
8314 case UDT_INTERFACE_POWER
:
8316 //psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Skipping descriptor %02lx (pc=%p, pif=%p altpif=%p).", dbuf[1], pc, pif, altif);
8317 KPRINTF(1, ("Skipping unknown descriptor %ld.\n", dbuf
[1]));
8321 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Skipping unknown descriptor %02lx.", dbuf
[1]);
8322 KPRINTF(1, ("Skipping unknown descriptor %ld.\n", dbuf
[1]));
8325 // add descriptor to device
8326 pdd
= pAllocDescriptor(pd
, dbuf
);
8329 STRPTR descname
= NULL
;
8331 pdd
->pdd_Config
= pc
;
8332 pdd
->pdd_Interface
= altif
;
8333 pdd
->pdd_Endpoint
= pep
;
8334 if(pdd
->pdd_Interface
)
8336 if((pdd
->pdd_Type
>= UDT_CS_UNDEFINED
) && (pdd
->pdd_Type
<= UDT_CS_ENDPOINT
))
8338 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pdd
->pdd_CSSubType
<<24)|(pif
->pif_IfSubClass
<<16)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8341 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pdd
->pdd_CSSubType
<<24)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8346 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pif
->pif_IfSubClass
<<16)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8350 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8355 pdd
->pdd_Name
= descname
;
8360 KPRINTF(1, ("Configuration acquired!\n"));
8361 psdFreeVec(tempbuf
);
8364 //psdUnlockDevice(pd);
8367 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8368 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
8369 len
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8370 KPRINTF(15, ("GET_DESCRIPTOR failed %ld!\n", ioerr
));
8372 psdFreeVec(tempbuf
);
8374 KPRINTF(20, ("No memory for %ld bytes config temp buffer!\n", len
));
8377 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8378 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
8379 9, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8380 KPRINTF(15, ("GET_DESCRIPTOR (9) failed %ld!\n", ioerr
));
8382 psdUnlockDevice(pd
);
8385 psdUnlockDevice(pd
);
8390 /* /// "pPowerRecurseDrain()" */
8391 ULONG
pPowerRecurseDrain(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
8393 struct PsdDevice
*nextpd
;
8394 struct PsdConfig
*pc
;
8395 UWORD maxdrain
= 666;
8397 BOOL selfpwd
= TRUE
;
8398 pd
->pd_PowerDrain
= 0;
8400 /* look at config */
8401 if((pc
= pd
->pd_CurrentConfig
))
8404 /* if suspended, no more than 500�A are drained */
8405 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
8407 pd
->pd_PowerDrain
= (pc
->pc_MaxPower
>= 100) ? 3 : 1;
8408 return(pd
->pd_PowerDrain
);
8410 selfpwd
= ((pc
->pc_Attr
& USCAF_SELF_POWERED
) && (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
!= POCP_BUS_POWERED
)) ||
8411 (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
== POCP_SELF_POWERED
);
8412 maxdrain
= selfpwd
? 500 : 100;
8415 /* examine children */
8416 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8417 while(nextpd
->pd_Node
.ln_Succ
)
8419 if(nextpd
->pd_Hub
== pd
)
8421 childdrain
= pPowerRecurseDrain(ps
, nextpd
);
8422 // limit the drain to the maximum power suckage
8423 pd
->pd_PowerDrain
+= (childdrain
> maxdrain
) ? maxdrain
: childdrain
;
8425 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8428 /* look at config */
8431 pd
->pd_PowerDrain
= 0;
8433 pd
->pd_PowerDrain
+= pc
->pc_MaxPower
;
8435 return(pd
->pd_PowerDrain
);
8439 /* /// "pPowerRecurseSupply()" */
8440 void pPowerRecurseSupply(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
8442 struct PsdDevice
*nextpd
;
8443 struct PsdConfig
*pc
;
8446 BOOL selfpwd
= TRUE
;
8448 /* look at config */
8449 if((pc
= pd
->pd_CurrentConfig
))
8451 selfpwd
= ((pc
->pc_Attr
& USCAF_SELF_POWERED
) && (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
!= POCP_BUS_POWERED
)) ||
8452 (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
== POCP_SELF_POWERED
);
8455 /* count children */
8456 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8457 while(nextpd
->pd_Node
.ln_Succ
)
8459 if(nextpd
->pd_Hub
== pd
) // this device is a child of us (we're a hub!)
8463 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8466 /* look at config */
8471 pd
->pd_PowerSupply
= ports
? 500*ports
+ pc
->pc_MaxPower
: pc
->pc_MaxPower
;
8473 supply
= 500; // each downstream port gets the full monty
8475 // the parent hub has already set the amount of supply for this port
8476 if(pd
->pd_PowerSupply
>= pc
->pc_MaxPower
)
8478 // the downstream ports get the remaining divided attention
8481 // avoid division by zero
8482 supply
= (pd
->pd_PowerSupply
- pc
->pc_MaxPower
) / ports
;
8485 // limit to 100 mA per port
8490 supply
= 1; // bad luck, out of power
8495 if(ports
) /* needs to be a hub */
8497 // propagate supply down to the children
8498 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8499 while(nextpd
->pd_Node
.ln_Succ
)
8501 if(nextpd
->pd_Hub
== pd
)
8503 nextpd
->pd_PowerSupply
= supply
;
8504 pPowerRecurseSupply(ps
, nextpd
);
8506 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8509 if(pd
->pd_PowerDrain
> pd
->pd_PowerSupply
)
8511 if(!(pd
->pd_Flags
& PDFF_LOWPOWER
))
8513 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8514 "Detected low power condition for '%s'.", pd
->pd_ProductStr
);
8515 pd
->pd_Flags
|= PDFF_LOWPOWER
;
8516 psdSendEvent(EHMB_DEVICELOWPW
, pd
, NULL
);
8519 if(pd
->pd_Flags
& PDFF_LOWPOWER
)
8521 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
8522 "Low power condition resolved for '%s'.", pd
->pd_ProductStr
);
8523 pd
->pd_Flags
&= ~PDFF_LOWPOWER
;
8529 /* /// "pGarbageCollectEvents()" */
8530 void pGarbageCollectEvents(LIBBASETYPEPTR ps
)
8532 struct PsdEventNote
*pen
;
8533 while((pen
= (struct PsdEventNote
*) GetMsg(&ps
->ps_EventReplyPort
)))
8540 /* /// "pFindName()" */
8541 struct Node
* pFindName(LIBBASETYPEPTR ps
, struct List
*list
, STRPTR name
)
8543 struct Node
*res
= NULL
;
8548 res
= FindName(list
, name
);
8555 if((*name
== '/') || (*name
== ':'))
8567 /* /// "pStripString()" */
8568 void pStripString(LIBBASETYPEPTR ps
, STRPTR str
)
8570 STRPTR srcptr
= str
;
8571 STRPTR tarptr
= str
;
8572 STRPTR lastgoodchar
= str
;
8573 BOOL leadingspaces
= TRUE
;
8577 while((ch
= *srcptr
++))
8588 lastgoodchar
= tarptr
;
8589 leadingspaces
= FALSE
;
8594 if((str
== lastgoodchar
) && (len
> 6))
8596 strcpy(str
, "<empty>");
8601 /* /// "pFixBrokenConfig()" */
8602 BOOL
pFixBrokenConfig(struct PsdPipe
*pp
)
8604 struct PsdDevice
*pd
= pp
->pp_Device
;
8605 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
8606 struct PsdConfig
*pc
;
8607 struct PsdInterface
*pif
;
8610 switch(pd
->pd_VendorID
)
8612 case 0x03eb: /* Atmel */
8613 if(pd
->pd_ProductID
== 0x3312)
8615 psdFreeVec(pd
->pd_ProductStr
);
8616 pd
->pd_ProductStr
= psdCopyStr("Highway/Subway Root Hub");
8620 case 0x04e6: /* E-Shuttle */
8621 if(pd
->pd_ProductID
== 0x0001) /* LS120 */
8623 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8624 /* Get msd interface and fix it */
8625 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8626 if(pif
->pif_IfClass
!= MASSSTORE_CLASSCODE
)
8629 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "E-Shuttle LS120");
8630 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8631 pif
->pif_IfSubClass
= MS_ATAPI_SUBCLASS
;
8632 pif
->pif_IfProto
= MS_PROTO_CB
;
8637 case 0x054C: /* Sony */
8638 if((pd
->pd_ProductID
== 0x002E) || (pd
->pd_ProductID
== 0x0010)) /* Handycam */
8641 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Sony MSD");
8642 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8643 /* Get msd interface and fix it */
8644 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8645 pif
->pif_IfSubClass
= MS_RBC_SUBCLASS
;
8649 case 0x057b: /* Y-E Data */
8650 if(pd
->pd_ProductID
== 0x0000) /* Flashbuster U */
8652 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8653 /* Get msd interface and fix it */
8654 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8655 if(pif
->pif_IfClass
!= MASSSTORE_CLASSCODE
)
8658 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Y-E Data USB Floppy");
8659 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8660 pif
->pif_IfSubClass
= MS_UFI_SUBCLASS
;
8661 pif
->pif_IfProto
= (pd
->pd_DevVers
< 0x0300) ? MS_PROTO_CB
: MS_PROTO_CBI
;
8666 case 0x04ce: /* ScanLogic */
8667 if(pd
->pd_ProductID
== 0x0002)
8669 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "ScanLogic");
8670 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8671 /* Get msd interface and fix it */
8672 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8674 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8678 case 0x0584: /* Ratoc cardreader */
8679 if(pd
->pd_ProductID
== 0x0008)
8681 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "RATOC");
8682 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8683 /* Get msd interface and fix it */
8684 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8686 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8687 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8688 pif
->pif_IfProto
= MS_PROTO_BULK
;
8692 case 0x04b8: /* Epson */
8693 if(pd
->pd_ProductID
== 0x0602) /* EPX Storage device (Card slot in Printer) */
8695 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Epson storage");
8696 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8697 /* Get msd interface and fix it */
8698 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8700 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8701 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8702 pif
->pif_IfProto
= MS_PROTO_BULK
;
8713 /* /// "pOpenDOS()" */
8714 BOOL
pOpenDOS(LIBBASETYPEPTR ps
)
8720 if((DOSBase
= OpenLibrary("dos.library", 39)))
8728 /* *** Class Scan Task *** */
8730 /* /// "pStartEventHandler()" */
8731 BOOL
pStartEventHandler(LIBBASETYPEPTR ps
)
8733 struct PsdHandlerTask
*ph
= &ps
->ps_EventHandler
;
8735 ObtainSemaphore(&ps
->ps_PoPoLock
);
8738 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8741 ph
->ph_ReadySignal
= SIGB_SINGLE
;
8742 ph
->ph_ReadySigTask
= FindTask(NULL
);
8743 SetSignal(0, SIGF_SINGLE
); // clear single bit
8744 if(psdSpawnSubTask("Poseidon Event Broadcast", pEventHandlerTask
, ps
))
8746 Wait(1UL<<ph
->ph_ReadySignal
);
8748 ph
->ph_ReadySigTask
= NULL
;
8749 //FreeSignal(ph->ph_ReadySignal);
8752 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8753 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Event broadcaster started.");
8756 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8761 /* *** Hardware Driver Task *** */
8763 /* /// "pQuickForwardRequest()" */
8764 AROS_UFH1(void, pQuickForwardRequest
,
8765 AROS_UFHA(struct MsgPort
*, msgport
, A1
))
8768 struct PsdHardware
*phw
= (struct PsdHardware
*) msgport
->mp_Node
.ln_Name
;
8771 while((pp
= (struct PsdPipe
*) RemHead(&msgport
->mp_MsgList
)))
8773 if(pp
->pp_AbortPipe
)
8775 KPRINTF(2, ("Abort pipe %p\n", pp
->pp_AbortPipe
));
8776 AbortIO((struct IORequest
*) &pp
->pp_AbortPipe
->pp_IOReq
);
8777 ReplyMsg(&pp
->pp_Msg
);
8778 KPRINTF(2, ("Replying evil pipe %p\n", pp
));
8780 KPRINTF(1, ("Forwarding pipe %p\n", pp
));
8781 pp
->pp_IOReq
.iouh_UserData
= pp
;
8782 SendIO((struct IORequest
*) &pp
->pp_IOReq
);
8783 ++phw
->phw_MsgCount
;
8790 /* /// "pQuickReplyRequest()" */
8791 AROS_UFH1(void, pQuickReplyRequest
,
8792 AROS_UFHA(struct MsgPort
*, msgport
, A1
))
8795 struct PsdHardware
*phw
= (struct PsdHardware
*) msgport
->mp_Node
.ln_Name
;
8796 struct IOUsbHWReq
*ioreq
;
8798 while((ioreq
= (struct IOUsbHWReq
*) RemHead(&msgport
->mp_MsgList
)))
8800 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8801 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8802 --phw
->phw_MsgCount
;
8808 /* /// "pDeviceTask()" */
8809 AROS_UFH0(void, pDeviceTask
)
8813 struct PsdHardware
*phw
;
8814 struct Task
*thistask
;
8818 struct TagItem taglist
[11];
8819 struct TagItem
*tag
;
8821 struct IOUsbHWReq
*ioreq
;
8823 STRPTR prodname
= NULL
;
8824 STRPTR manufacturer
= NULL
;
8825 STRPTR description
= NULL
;
8826 STRPTR copyright
= NULL
;
8829 ULONG driververs
= 0x0100;
8830 ULONG caps
= UHCF_ISO
;
8834 if(!(ps
= (LIBBASETYPEPTR
) OpenLibrary("poseidon.library", 4)))
8839 thistask
= FindTask(NULL
);
8840 SetTaskPri(thistask
, 21);
8841 phw
= thistask
->tc_UserData
;
8843 #ifndef PA_CALLBACK // undocumented exec feature
8844 #define PA_CALLBACK 3
8847 memset(&phw
->phw_TaskMsgPort
, 0, sizeof(phw
->phw_TaskMsgPort
));
8848 phw
->phw_TaskMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
8849 phw
->phw_TaskMsgPort
.mp_Node
.ln_Name
= (APTR
) phw
;
8850 phw
->phw_TaskMsgPort
.mp_Flags
= PA_SIGNAL
;
8851 phw
->phw_TaskMsgPort
.mp_SigTask
= thistask
;
8852 phw
->phw_TaskMsgPort
.mp_SigBit
= AllocSignal(-1L);
8853 NewList(&phw
->phw_TaskMsgPort
.mp_MsgList
);
8855 memset(&phw
->phw_DevMsgPort
, 0, sizeof(phw
->phw_DevMsgPort
));
8856 phw
->phw_DevMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
8857 phw
->phw_DevMsgPort
.mp_Node
.ln_Name
= (APTR
) phw
;
8858 phw
->phw_DevMsgPort
.mp_Flags
= PA_SIGNAL
;
8859 phw
->phw_DevMsgPort
.mp_SigTask
= thistask
;
8860 phw
->phw_DevMsgPort
.mp_SigBit
= AllocSignal(-1L);
8861 NewList(&phw
->phw_DevMsgPort
.mp_MsgList
);
8863 if((phw
->phw_RootIOReq
= (struct IOUsbHWReq
*) CreateIORequest(&phw
->phw_DevMsgPort
, sizeof(struct IOUsbHWReq
))))
8865 devname
= phw
->phw_DevName
;
8869 if(!(ioerr
= OpenDevice(devname
, phw
->phw_Unit
, (struct IORequest
*) phw
->phw_RootIOReq
, 0)))
8875 if((*devname
== '/') || (*devname
== ':'))
8880 } while(*(++devname
));
8885 phw
->phw_Node
.ln_Name
= phw
->phw_RootIOReq
->iouh_Req
.io_Device
->dd_Library
.lib_Node
.ln_Name
;
8887 tag
->ti_Tag
= UHA_ProductName
;
8888 tag
->ti_Data
= (IPTR
) &prodname
;
8890 tag
->ti_Tag
= UHA_Manufacturer
;
8891 tag
->ti_Data
= (IPTR
) &manufacturer
;
8893 tag
->ti_Tag
= UHA_Description
;
8894 tag
->ti_Data
= (IPTR
) &description
;
8896 tag
->ti_Tag
= UHA_Version
;
8897 tag
->ti_Data
= (IPTR
) &version
;
8899 tag
->ti_Tag
= UHA_Revision
;
8900 tag
->ti_Data
= (IPTR
) &revision
;
8902 tag
->ti_Tag
= UHA_Copyright
;
8903 tag
->ti_Data
= (IPTR
) ©right
;
8905 tag
->ti_Tag
= UHA_DriverVersion
;
8906 tag
->ti_Data
= (IPTR
) &driververs
;
8908 tag
->ti_Tag
= UHA_Capabilities
;
8909 tag
->ti_Data
= (IPTR
) &caps
;
8911 tag
->ti_Tag
= TAG_END
;
8912 phw
->phw_RootIOReq
->iouh_Data
= taglist
;
8913 phw
->phw_RootIOReq
->iouh_Req
.io_Command
= UHCMD_QUERYDEVICE
;
8914 DoIO((struct IORequest
*) phw
->phw_RootIOReq
);
8916 phw
->phw_ProductName
= psdCopyStr(prodname
? prodname
: (STRPTR
) "n/a");
8917 phw
->phw_Manufacturer
= psdCopyStr(manufacturer
? manufacturer
: (STRPTR
) "n/a");
8918 phw
->phw_Description
= psdCopyStr(description
? description
: (STRPTR
) "n/a");
8919 phw
->phw_Copyright
= psdCopyStr(copyright
? copyright
: (STRPTR
) "n/a");
8920 phw
->phw_Version
= version
;
8921 phw
->phw_Revision
= revision
;
8922 phw
->phw_DriverVers
= driververs
;
8923 phw
->phw_Capabilities
= caps
;
8925 sigmask
= SIGBREAKF_CTRL_C
;
8926 if(caps
& UHCF_QUICKIO
)
8928 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Enabling QuickIO for %s.", prodname
);
8929 phw
->phw_TaskMsgPort
.mp_Flags
= PA_CALLBACK
;
8930 phw
->phw_TaskMsgPort
.mp_SigTask
= (APTR
) pQuickForwardRequest
;
8932 phw
->phw_DevMsgPort
.mp_Flags
= PA_CALLBACK
;
8933 phw
->phw_DevMsgPort
.mp_SigTask
= (APTR
) pQuickReplyRequest
;
8935 sigmask
|= (1UL<<phw
->phw_DevMsgPort
.mp_SigBit
)|(1UL<<phw
->phw_TaskMsgPort
.mp_SigBit
);
8938 KPRINTF(10, ("%s ready!\n", thistask
->tc_Node
.ln_Name
));
8939 phw
->phw_Task
= thistask
;
8941 psdLockWritePBase();
8942 AddTail(&ps
->ps_Hardware
, &phw
->phw_Node
);
8946 if(phw
->phw_ReadySigTask
)
8948 Signal(phw
->phw_ReadySigTask
, 1L<<phw
->phw_ReadySignal
);
8953 KPRINTF(1, ("Main loop wait.\n"));
8954 while((pp
= (struct PsdPipe
*) GetMsg(&phw
->phw_TaskMsgPort
)))
8956 if(pp
->pp_AbortPipe
)
8958 KPRINTF(2, ("Abort pipe %p\n", pp
->pp_AbortPipe
));
8959 AbortIO((struct IORequest
*) &pp
->pp_AbortPipe
->pp_IOReq
);
8960 ReplyMsg(&pp
->pp_Msg
);
8961 KPRINTF(2, ("Replying evil pipe %p\n", pp
));
8963 KPRINTF(1, ("Forwarding pipe %p\n", pp
));
8964 pp
->pp_IOReq
.iouh_UserData
= pp
;
8965 SendIO((struct IORequest
*) &pp
->pp_IOReq
);
8966 ++phw
->phw_MsgCount
;
8969 while((ioreq
= (struct IOUsbHWReq
*) GetMsg(&phw
->phw_DevMsgPort
)))
8971 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8972 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8973 --phw
->phw_MsgCount
;
8975 sigs
= Wait(sigmask
);
8976 } while(!(sigs
& SIGBREAKF_CTRL_C
));
8977 /* Flush all pending IO Requests */
8978 phw
->phw_RootIOReq
->iouh_Req
.io_Command
= CMD_FLUSH
;
8979 DoIO((struct IORequest
*) phw
->phw_RootIOReq
);
8981 while(phw
->phw_MsgCount
)
8983 KPRINTF(20, ("Still %ld iorequests pending!\n", phw
->phw_MsgCount
));
8987 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8988 "There are still %ld IORequests pending, before unit can go down. Driver buggy?",
8993 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8994 "Okay, I've waited long enough, sod these %ld IORequests.",
8996 phw
->phw_MsgCount
= 0;
8999 while((ioreq
= (struct IOUsbHWReq
*) GetMsg(&phw
->phw_DevMsgPort
)))
9001 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
9002 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
9003 --phw
->phw_MsgCount
;
9006 psdLockWritePBase();
9007 Remove(&phw
->phw_Node
);
9009 CloseDevice((struct IORequest
*) phw
->phw_RootIOReq
);
9011 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
9012 "Opening %s unit %ld failed %s (%ld).",
9013 phw
->phw_DevName
, phw
->phw_Unit
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
9015 DeleteIORequest((struct IORequest
*) phw
->phw_RootIOReq
);
9016 phw
->phw_RootIOReq
= NULL
;
9018 FreeSignal((LONG
) phw
->phw_TaskMsgPort
.mp_SigBit
);
9019 FreeSignal((LONG
) phw
->phw_DevMsgPort
.mp_SigBit
);
9021 CloseLibrary((struct Library
*) ps
);
9022 phw
->phw_Task
= NULL
;
9025 if(phw
->phw_ReadySigTask
)
9027 Signal(phw
->phw_ReadySigTask
, 1L<<phw
->phw_ReadySignal
);
9033 /* /// "pEventHandlerTask()" */
9034 AROS_UFH0(void, pEventHandlerTask
)
9038 struct Task
*thistask
;
9039 struct timeval currtime
;
9042 struct PsdUsbClass
*puc
;
9043 struct PsdHandlerTask
*ph
;
9044 struct PsdEventNote
*pen
;
9048 thistask
= FindTask(NULL
);
9049 ps
= thistask
->tc_UserData
;
9050 ph
= &ps
->ps_EventHandler
;
9051 SetTaskPri(thistask
, 0);
9053 if((ph
->ph_MsgPort
= CreateMsgPort()))
9055 if((ph
->ph_TimerMsgPort
= CreateMsgPort()))
9057 if((ph
->ph_TimerIOReq
= (struct timerequest
*) CreateIORequest(ph
->ph_TimerMsgPort
, sizeof(struct timerequest
))))
9059 if(!(OpenDevice("timer.device", UNIT_VBLANK
, (struct IORequest
*) ph
->ph_TimerIOReq
, 0)))
9061 ph
->ph_TimerIOReq
->tr_node
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
9062 ph
->ph_TimerIOReq
->tr_node
.io_Message
.mn_Node
.ln_Name
= "EventHandler";
9063 ph
->ph_TimerIOReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
9065 ph
->ph_EventHandler
= psdAddEventHandler(ph
->ph_MsgPort
, EHMF_CONFIGCHG
);
9066 if(ph
->ph_EventHandler
)
9068 ph
->ph_Task
= thistask
;
9070 if(ph
->ph_ReadySigTask
)
9072 Signal(ph
->ph_ReadySigTask
, 1L<<ph
->ph_ReadySignal
);
9076 ph
->ph_TimerIOReq
->tr_time
.tv_micro
= 500*1000;
9077 SendIO(&ph
->ph_TimerIOReq
->tr_node
);
9078 sigmask
= (1UL<<ph
->ph_MsgPort
->mp_SigBit
)|(1UL<<ph
->ph_TimerMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
9083 if(ps
->ps_CheckConfigReq
)
9085 pCheckCfgChanged(ps
);
9087 while((pen
= (struct PsdEventNote
*) GetMsg(ph
->ph_MsgPort
)))
9089 switch(pen
->pen_Event
)
9091 case EHMB_CONFIGCHG
:
9094 cfgchanged
= counter
;
9099 ReplyMsg(&pen
->pen_Msg
);
9101 if(CheckIO(&ph
->ph_TimerIOReq
->tr_node
))
9104 WaitIO(&ph
->ph_TimerIOReq
->tr_node
);
9105 ph
->ph_TimerIOReq
->tr_time
.tv_micro
= 500*1000;
9106 SendIO(&ph
->ph_TimerIOReq
->tr_node
);
9108 startpopo
= !((counter
& 3) || ps
->ps_PoPo
.po_Task
);
9109 if((ps
->ps_GlobalCfg
->pgc_PopupDeviceNew
== PGCP_NEVER
) &&
9110 (!ps
->ps_GlobalCfg
->pgc_PopupDeviceDeath
) &&
9111 (!ps
->ps_GlobalCfg
->pgc_PopupDeviceGone
))
9113 startpopo
= FALSE
; // no need to start popo, no windows wanted
9117 struct PsdPoPo
*po
= &ps
->ps_PoPo
;
9119 po
->po_ReadySignal
= SIGB_SINGLE
;
9120 po
->po_ReadySigTask
= FindTask(NULL
);
9121 SetSignal(0, SIGF_SINGLE
); // clear single bit
9122 if(psdSpawnSubTask("PoPo (Poseidon Popups)", pPoPoGUITask
, ps
))
9124 Wait(1UL<<po
->po_ReadySignal
);
9126 po
->po_ReadySigTask
= NULL
;
9127 //FreeSignal(po->po_ReadySignal);
9130 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "PoPo kicks ass.");
9133 if((cfgchanged
+ 2) == counter
)
9135 KPRINTF(10, ("Sending information about config changed to all classes.\n"));
9136 /* Inform all classes */
9138 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
9139 while(puc
->puc_Node
.ln_Succ
)
9141 usbDoMethod(UCM_ConfigChangedEvent
);
9142 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
9147 // power saving stuff, check every second
9148 if((counter
& 1) && ps
->ps_GlobalCfg
->pgc_PowerSaving
)
9150 struct PsdDevice
*pd
= NULL
;
9151 struct PsdInterface
*pif
;
9152 GetSysTime((APTR
) &currtime
);
9153 while((pd
= psdGetNextDevice(pd
)))
9155 if((pd
->pd_DevClass
!= HUB_CLASSCODE
) &&
9156 ((pd
->pd_Flags
& (PDFF_CONFIGURED
|PDFF_DEAD
|PDFF_SUSPENDED
|PDFF_APPBINDING
|PDFF_DELEXPUNGE
)) == PDFF_CONFIGURED
))
9158 if(pd
->pd_LastActivity
.tv_secs
&& ((currtime
.tv_secs
- pd
->pd_LastActivity
.tv_secs
) > ps
->ps_GlobalCfg
->pgc_SuspendTimeout
))
9162 if(!((pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
) && ps
->ps_GlobalCfg
->pgc_ForceSuspend
))
9164 if(pd
->pd_DevBinding
&& ((puc
= pd
->pd_ClsBinding
)))
9167 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
9173 pif
= (struct PsdInterface
*) pd
->pd_CurrentConfig
->pc_Interfaces
.lh_Head
;
9174 while(pif
->pif_Node
.ln_Succ
)
9176 if(pif
->pif_IfBinding
&& ((puc
= pif
->pif_ClsBinding
)))
9179 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
9186 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
9191 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Suspending '%s'.", pd
->pd_ProductStr
);
9192 psdSuspendDevice(pd
);
9194 pd
->pd_LastActivity
.tv_secs
= 0;
9200 sigs
= Wait(sigmask
);
9201 } while(!(sigs
& SIGBREAKF_CTRL_C
));
9202 psdRemEventHandler(ph
->ph_EventHandler
);
9203 ph
->ph_EventHandler
= NULL
;
9204 AbortIO(&ph
->ph_TimerIOReq
->tr_node
);
9205 WaitIO(&ph
->ph_TimerIOReq
->tr_node
);
9207 CloseDevice((struct IORequest
*) ph
->ph_TimerIOReq
);
9209 DeleteIORequest((struct IORequest
*) ph
->ph_TimerIOReq
);
9211 DeleteMsgPort(ph
->ph_TimerMsgPort
);
9213 DeleteMsgPort(ph
->ph_MsgPort
);
9214 ph
->ph_MsgPort
= NULL
;
9218 if(ph
->ph_ReadySigTask
)
9220 Signal(ph
->ph_ReadySigTask
, 1L<<ph
->ph_ReadySignal
);
9226 /*****************************************************************/
9228 /* /// "Packtables for psdGetAttrs() and psdSetAttrs() " */
9229 /* Pack table for PsdBase */
9230 static const ULONG PsdBasePT
[] =
9232 PACK_STARTTABLE(PA_Dummy
),
9233 PACK_ENTRY(PA_Dummy
, PA_ConfigRead
, PsdBase
, ps_ConfigRead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9234 PACK_ENTRY(PA_Dummy
, PA_GlobalConfig
, PsdBase
, ps_GlobalCfg
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9235 PACK_ENTRY(PA_Dummy
, PA_MemPoolUsage
, PsdBase
, ps_MemAllocated
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9236 PACK_ENTRY(PA_Dummy
, PA_CurrConfigHash
, PsdBase
, ps_ConfigHash
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9237 PACK_ENTRY(PA_Dummy
, PA_SavedConfigHash
, PsdBase
, ps_SavedConfigHash
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9238 PACK_ENTRY(PA_Dummy
, PA_ReleaseVersion
, PsdBase
, ps_ReleaseVersion
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9239 PACK_ENTRY(PA_Dummy
, PA_OSVersion
, PsdBase
, ps_OSVersion
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9243 /* Pack table for PsdErrorMsg */
9244 static const ULONG PsdErrorMsgPT
[] =
9246 PACK_STARTTABLE(EMA_Dummy
),
9247 PACK_ENTRY(EMA_Dummy
, EMA_Level
, PsdErrorMsg
, pem_Level
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9248 PACK_ENTRY(EMA_Dummy
, EMA_Origin
, PsdErrorMsg
, pem_Origin
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9249 PACK_ENTRY(EMA_Dummy
, EMA_Msg
, PsdErrorMsg
, pem_Msg
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9253 /* Pack table for PsdUsbClass */
9254 static const ULONG PsdUsbClassPT
[] =
9256 PACK_STARTTABLE(UCA_Dummy
),
9257 PACK_ENTRY(UCA_Dummy
, UCA_ClassBase
, PsdUsbClass
, puc_ClassBase
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9258 PACK_ENTRY(UCA_Dummy
, UCA_ClassName
, PsdUsbClass
, puc_ClassName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9259 PACK_ENTRY(UCA_Dummy
, UCA_FullPath
, PsdUsbClass
, puc_FullPath
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9260 PACK_ENTRY(UCA_Dummy
, UCA_UseCount
, PsdUsbClass
, puc_UseCnt
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9264 /* Pack table for PsdHardware */
9265 static const ULONG PsdHardwarePT
[] =
9267 PACK_STARTTABLE(HA_Dummy
),
9268 PACK_ENTRY(HA_Dummy
, HA_DeviceName
, PsdHardware
, phw_DevName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9269 PACK_ENTRY(HA_Dummy
, HA_DeviceUnit
, PsdHardware
, phw_Unit
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9270 PACK_ENTRY(HA_Dummy
, HA_ProductName
, PsdHardware
, phw_ProductName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9271 PACK_ENTRY(HA_Dummy
, HA_Manufacturer
, PsdHardware
, phw_Manufacturer
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9272 PACK_ENTRY(HA_Dummy
, HA_Description
, PsdHardware
, phw_Description
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9273 PACK_ENTRY(HA_Dummy
, HA_Copyright
, PsdHardware
, phw_Copyright
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9274 PACK_ENTRY(HA_Dummy
, HA_Version
, PsdHardware
, phw_Version
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9275 PACK_ENTRY(HA_Dummy
, HA_Revision
, PsdHardware
, phw_Revision
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9276 PACK_ENTRY(HA_Dummy
, HA_DriverVersion
, PsdHardware
, phw_DriverVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9280 /* Pack table for PsdDevice */
9281 static const ULONG PsdDevicePT
[] =
9283 PACK_STARTTABLE(DA_Dummy
),
9284 PACK_ENTRY(DA_Dummy
, DA_Address
, PsdDevice
, pd_DevAddr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9285 PACK_ENTRY(DA_Dummy
, DA_NumConfigs
, PsdDevice
, pd_NumCfgs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9286 PACK_ENTRY(DA_Dummy
, DA_CurrConfig
, PsdDevice
, pd_CurrCfg
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9287 PACK_ENTRY(DA_Dummy
, DA_Config
, PsdDevice
, pd_CurrentConfig
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9288 PACK_ENTRY(DA_Dummy
, DA_HubDevice
, PsdDevice
, pd_Hub
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9289 PACK_ENTRY(DA_Dummy
, DA_UsbVersion
, PsdDevice
, pd_USBVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9290 PACK_ENTRY(DA_Dummy
, DA_Class
, PsdDevice
, pd_DevClass
, PKCTRL_WORD
|PKCTRL_UNPACKONLY
),
9291 PACK_ENTRY(DA_Dummy
, DA_SubClass
, PsdDevice
, pd_DevSubClass
, PKCTRL_WORD
|PKCTRL_UNPACKONLY
),
9292 PACK_ENTRY(DA_Dummy
, DA_Protocol
, PsdDevice
, pd_DevProto
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9293 PACK_ENTRY(DA_Dummy
, DA_VendorID
, PsdDevice
, pd_VendorID
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9294 PACK_ENTRY(DA_Dummy
, DA_MaxPktSize0
, PsdDevice
, pd_MaxPktSize0
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9295 PACK_ENTRY(DA_Dummy
, DA_ProductID
, PsdDevice
, pd_ProductID
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9296 PACK_ENTRY(DA_Dummy
, DA_Version
, PsdDevice
, pd_DevVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9297 PACK_ENTRY(DA_Dummy
, DA_Manufacturer
, PsdDevice
, pd_MnfctrStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9298 PACK_ENTRY(DA_Dummy
, DA_ProductName
, PsdDevice
, pd_ProductStr
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9299 PACK_ENTRY(DA_Dummy
, DA_OrigProductName
, PsdDevice
, pd_OldProductStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9300 PACK_ENTRY(DA_Dummy
, DA_SerialNumber
, PsdDevice
, pd_SerNumStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9301 PACK_ENTRY(DA_Dummy
, DA_Hardware
, PsdDevice
, pd_Hardware
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9302 PACK_ENTRY(DA_Dummy
, DA_Binding
, PsdDevice
, pd_DevBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9303 PACK_ENTRY(DA_Dummy
, DA_BindingClass
, PsdDevice
, pd_ClsBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9304 PACK_ENTRY(DA_Dummy
, DA_LangIDArray
, PsdDevice
, pd_LangIDArray
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9305 PACK_ENTRY(DA_Dummy
, DA_CurrLangID
, PsdDevice
, pd_CurrLangID
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9306 PACK_ENTRY(DA_Dummy
, DA_IDString
, PsdDevice
, pd_IDString
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9307 PACK_ENTRY(DA_Dummy
, DA_CloneCount
, PsdDevice
, pd_CloneCount
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9308 PACK_ENTRY(DA_Dummy
, DA_AtHubPortNumber
, PsdDevice
, pd_HubPort
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9309 PACK_ENTRY(DA_Dummy
, DA_PowerDrained
, PsdDevice
, pd_PowerDrain
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9310 PACK_ENTRY(DA_Dummy
, DA_PowerSupply
, PsdDevice
, pd_PowerSupply
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9311 PACK_ENTRY(DA_Dummy
, DA_IsNewToMe
, PsdDevice
, pd_IsNewToMe
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9312 PACK_ENTRY(DA_Dummy
, DA_InhibitPopup
, PsdDevice
, pd_PoPoCfg
.poc_InhibitPopup
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9313 PACK_ENTRY(DA_Dummy
, DA_InhibitClassBind
, PsdDevice
, pd_PoPoCfg
.poc_NoClassBind
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9314 PACK_ENTRY(DA_Dummy
, DA_OverridePowerInfo
, PsdDevice
, pd_PoPoCfg
.poc_OverridePowerInfo
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9315 PACK_ENTRY(DA_Dummy
, DA_HubThinkTime
, PsdDevice
, pd_HubThinkTime
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9316 PACK_WORDBIT(DA_Dummy
, DA_IsLowspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_LOWSPEED
),
9317 PACK_WORDBIT(DA_Dummy
, DA_IsHighspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HIGHSPEED
),
9318 PACK_WORDBIT(DA_Dummy
, DA_IsConnected
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_CONNECTED
),
9319 PACK_WORDBIT(DA_Dummy
, DA_HasAddress
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HASDEVADDR
),
9320 PACK_WORDBIT(DA_Dummy
, DA_HasDevDesc
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HASDEVDESC
),
9321 PACK_WORDBIT(DA_Dummy
, DA_IsConfigured
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_CONFIGURED
),
9322 PACK_WORDBIT(DA_Dummy
, DA_IsDead
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_DEAD
),
9323 PACK_WORDBIT(DA_Dummy
, DA_IsSuspended
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_SUSPENDED
),
9324 PACK_WORDBIT(DA_Dummy
, DA_HasAppBinding
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_APPBINDING
),
9325 PACK_WORDBIT(DA_Dummy
, DA_NeedsSplitTrans
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_NEEDSSPLIT
),
9326 PACK_WORDBIT(DA_Dummy
, DA_LowPower
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_LOWPOWER
),
9327 #ifdef AROS_USB30_CODE
9328 PACK_WORDBIT(DA_Dummy
, DA_IsSuperspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_SUPERSPEED
),
9333 /* Pack table for PsdConfig */
9334 static const ULONG PsdConfigPT
[] =
9336 PACK_STARTTABLE(CA_Dummy
),
9337 PACK_ENTRY(CA_Dummy
, CA_ConfigNum
, PsdConfig
, pc_CfgNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9338 PACK_ENTRY(CA_Dummy
, CA_MaxPower
, PsdConfig
, pc_MaxPower
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9339 PACK_ENTRY(CA_Dummy
, CA_ConfigName
, PsdConfig
, pc_CfgStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9340 PACK_ENTRY(CA_Dummy
, CA_NumInterfaces
, PsdConfig
, pc_NumIfs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9341 PACK_ENTRY(CA_Dummy
, CA_Attrs
, PsdConfig
, pc_Attr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9342 PACK_ENTRY(CA_Dummy
, CA_Device
, PsdConfig
, pc_Device
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9343 PACK_WORDBIT(CA_Dummy
, CA_SelfPowered
, PsdConfig
, pc_Attr
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, USCAF_SELF_POWERED
),
9344 PACK_WORDBIT(CA_Dummy
, CA_RemoteWakeup
, PsdConfig
, pc_Attr
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, USCAF_REMOTE_WAKEUP
),
9348 /* Pack table for PsdDescriptor */
9349 static const ULONG PsdDescriptorPT
[] =
9351 PACK_STARTTABLE(DDA_Dummy
),
9352 PACK_ENTRY(DDA_Dummy
, DDA_Device
, PsdDescriptor
, pdd_Device
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9353 PACK_ENTRY(DDA_Dummy
, DDA_Config
, PsdDescriptor
, pdd_Config
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9354 PACK_ENTRY(DDA_Dummy
, DDA_Interface
, PsdDescriptor
, pdd_Interface
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9355 PACK_ENTRY(DDA_Dummy
, DDA_Endpoint
, PsdDescriptor
, pdd_Endpoint
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9356 PACK_ENTRY(DDA_Dummy
, DDA_Name
, PsdDescriptor
, pdd_Name
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9357 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorType
, PsdDescriptor
, pdd_Type
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9358 PACK_ENTRY(DDA_Dummy
, DDA_CS_SubType
, PsdDescriptor
, pdd_CSSubType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9359 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorData
, PsdDescriptor
, pdd_Data
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9360 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorLength
, PsdDescriptor
, pdd_Length
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9364 /* Pack table for PsdInterface */
9365 static const ULONG PsdInterfacePT
[] =
9367 PACK_STARTTABLE(IFA_Dummy
),
9368 PACK_ENTRY(IFA_Dummy
, IFA_InterfaceNum
, PsdInterface
, pif_IfNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9369 PACK_ENTRY(IFA_Dummy
, IFA_AlternateNum
, PsdInterface
, pif_Alternate
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9370 PACK_ENTRY(IFA_Dummy
, IFA_NumEndpoints
, PsdInterface
, pif_NumEPs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9371 PACK_ENTRY(IFA_Dummy
, IFA_Class
, PsdInterface
, pif_IfClass
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9372 PACK_ENTRY(IFA_Dummy
, IFA_SubClass
, PsdInterface
, pif_IfSubClass
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9373 PACK_ENTRY(IFA_Dummy
, IFA_Protocol
, PsdInterface
, pif_IfProto
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9374 PACK_ENTRY(IFA_Dummy
, IFA_InterfaceName
, PsdInterface
, pif_IfStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9375 PACK_ENTRY(IFA_Dummy
, IFA_Config
, PsdInterface
, pif_Config
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9376 PACK_ENTRY(IFA_Dummy
, IFA_Binding
, PsdInterface
, pif_IfBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9377 PACK_ENTRY(IFA_Dummy
, IFA_BindingClass
, PsdInterface
, pif_ClsBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9378 PACK_ENTRY(IFA_Dummy
, IFA_IDString
, PsdInterface
, pif_IDString
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9382 /* Pack table for PsdEndpoint */
9383 static const ULONG PsdEndpointPT
[] =
9385 PACK_STARTTABLE(EA_Dummy
),
9386 PACK_ENTRY(EA_Dummy
, EA_EndpointNum
, PsdEndpoint
, pep_EPNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9387 PACK_ENTRY(EA_Dummy
, EA_TransferType
, PsdEndpoint
, pep_TransType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9388 PACK_ENTRY(EA_Dummy
, EA_MaxPktSize
, PsdEndpoint
, pep_MaxPktSize
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9389 PACK_ENTRY(EA_Dummy
, EA_Interval
, PsdEndpoint
, pep_Interval
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9390 PACK_ENTRY(EA_Dummy
, EA_NumTransMuFrame
, PsdEndpoint
, pep_NumTransMuFr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9391 PACK_ENTRY(EA_Dummy
, EA_SyncType
, PsdEndpoint
, pep_SyncType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9392 PACK_ENTRY(EA_Dummy
, EA_UsageType
, PsdEndpoint
, pep_UsageType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9393 PACK_ENTRY(EA_Dummy
, EA_Interface
, PsdEndpoint
, pep_Interface
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9394 PACK_WORDBIT(EA_Dummy
, EA_IsIn
, PsdEndpoint
, pep_Direction
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, 1),
9398 /* Pack table for PsdPipe */
9399 static const ULONG PsdPipePT
[] =
9401 PACK_STARTTABLE(PPA_Dummy
),
9402 PACK_ENTRY(PPA_Dummy
, PPA_Endpoint
, PsdPipe
, pp_Endpoint
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9403 PACK_ENTRY(PPA_Dummy
, PPA_Error
, PsdPipe
, pp_IOReq
.iouh_Req
.io_Error
, PKCTRL_BYTE
|PKCTRL_UNPACKONLY
),
9404 PACK_ENTRY(PPA_Dummy
, PPA_Actual
, PsdPipe
, pp_IOReq
.iouh_Actual
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9405 PACK_ENTRY(PPA_Dummy
, PPA_EndpointNum
, PsdPipe
, pp_IOReq
.iouh_Endpoint
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9406 PACK_ENTRY(PPA_Dummy
, PPA_DeviceAddress
, PsdPipe
, pp_IOReq
.iouh_DevAddr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9407 PACK_ENTRY(PPA_Dummy
, PPA_MaxPktSize
, PsdPipe
, pp_IOReq
.iouh_MaxPktSize
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9408 PACK_ENTRY(PPA_Dummy
, PPA_NakTimeoutTime
, PsdPipe
, pp_IOReq
.iouh_NakTimeout
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9409 PACK_ENTRY(PPA_Dummy
, PPA_Interval
, PsdPipe
, pp_IOReq
.iouh_Interval
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9410 PACK_WORDBIT(PPA_Dummy
, PPA_NoShortPackets
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_NOSHORTPKT
),
9411 PACK_WORDBIT(PPA_Dummy
, PPA_NakTimeout
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_NAKTIMEOUT
),
9412 PACK_WORDBIT(PPA_Dummy
, PPA_AllowRuntPackets
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_ALLOWRUNTPKTS
),
9416 /* Pack table for PsdAppBinding */
9417 static const ULONG PsdAppBindingPT
[] =
9419 PACK_STARTTABLE(ABA_Dummy
),
9420 PACK_ENTRY(ABA_Dummy
, ABA_ReleaseHook
, PsdAppBinding
, pab_ReleaseHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9421 PACK_ENTRY(ABA_Dummy
, ABA_Device
, PsdAppBinding
, pab_Device
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9422 PACK_ENTRY(ABA_Dummy
, ABA_UserData
, PsdAppBinding
, pab_UserData
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9423 PACK_ENTRY(ABA_Dummy
, ABA_Task
, PsdAppBinding
, pab_Task
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9424 PACK_ENTRY(ABA_Dummy
, ABA_ForceRelease
, PsdAppBinding
, pab_ForceRelease
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9428 /* Pack table for PsdAppBinding */
9429 static const ULONG PsdEventNotePT
[] =
9431 PACK_STARTTABLE(ENA_Dummy
),
9432 PACK_ENTRY(ENA_Dummy
, ENA_EventID
, PsdEventNote
, pen_Event
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9433 PACK_ENTRY(ENA_Dummy
, ENA_Param1
, PsdEventNote
, pen_Param1
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9434 PACK_ENTRY(ENA_Dummy
, ENA_Param2
, PsdEventNote
, pen_Param2
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9438 /* Pack table for PsdGlobalCfg */
9439 static const ULONG PsdGlobalCfgPT
[] =
9441 PACK_STARTTABLE(GCA_Dummy
),
9442 PACK_ENTRY(GCA_Dummy
, GCA_LogInfo
, PsdGlobalCfg
, pgc_LogInfo
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9443 PACK_ENTRY(GCA_Dummy
, GCA_LogWarning
, PsdGlobalCfg
, pgc_LogWarning
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9444 PACK_ENTRY(GCA_Dummy
, GCA_LogError
, PsdGlobalCfg
, pgc_LogError
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9445 PACK_ENTRY(GCA_Dummy
, GCA_LogFailure
, PsdGlobalCfg
, pgc_LogFailure
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9446 PACK_ENTRY(GCA_Dummy
, GCA_BootDelay
, PsdGlobalCfg
, pgc_BootDelay
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9447 PACK_ENTRY(GCA_Dummy
, GCA_SubTaskPri
, PsdGlobalCfg
, pgc_SubTaskPri
, PKCTRL_WORD
|PKCTRL_PACKUNPACK
),
9448 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceNew
, PsdGlobalCfg
, pgc_PopupDeviceNew
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9449 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceGone
, PsdGlobalCfg
, pgc_PopupDeviceGone
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9450 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceDeath
, PsdGlobalCfg
, pgc_PopupDeviceDeath
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9451 PACK_ENTRY(GCA_Dummy
, GCA_PopupCloseDelay
, PsdGlobalCfg
, pgc_PopupCloseDelay
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9452 PACK_ENTRY(GCA_Dummy
, GCA_PopupActivateWin
, PsdGlobalCfg
, pgc_PopupActivateWin
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9453 PACK_ENTRY(GCA_Dummy
, GCA_PopupWinToFront
, PsdGlobalCfg
, pgc_PopupWinToFront
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9454 PACK_ENTRY(GCA_Dummy
, GCA_AutoDisableLP
, PsdGlobalCfg
, pgc_AutoDisableLP
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9455 PACK_ENTRY(GCA_Dummy
, GCA_AutoDisableDead
, PsdGlobalCfg
, pgc_AutoDisableDead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9456 PACK_ENTRY(GCA_Dummy
, GCA_AutoRestartDead
, PsdGlobalCfg
, pgc_AutoRestartDead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9457 PACK_ENTRY(GCA_Dummy
, GCA_PowerSaving
, PsdGlobalCfg
, pgc_PowerSaving
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9458 PACK_ENTRY(GCA_Dummy
, GCA_ForceSuspend
, PsdGlobalCfg
, pgc_ForceSuspend
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9459 PACK_ENTRY(GCA_Dummy
, GCA_SuspendTimeout
, PsdGlobalCfg
, pgc_SuspendTimeout
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9460 PACK_ENTRY(GCA_Dummy
, GCA_PrefsVersion
, PsdGlobalCfg
, pgc_PrefsVersion
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9464 /* Pack table for PsdPipeStream */
9465 static const ULONG PsdPipeStreamPT
[] =
9467 PACK_STARTTABLE(PSA_Dummy
),
9468 PACK_ENTRY(PSA_Dummy
, PSA_MessagePort
, PsdPipeStream
, pps_MsgPort
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9469 PACK_ENTRY(PSA_Dummy
, PSA_NumPipes
, PsdPipeStream
, pps_NumPipes
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9470 PACK_ENTRY(PSA_Dummy
, PSA_BufferSize
, PsdPipeStream
, pps_BufferSize
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9471 PACK_ENTRY(PSA_Dummy
, PSA_NakTimeoutTime
, PsdPipeStream
, pps_NakTimeoutTime
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9472 PACK_ENTRY(PSA_Dummy
, PSA_BytesPending
, PsdPipeStream
, pps_BytesPending
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9473 PACK_ENTRY(PSA_Dummy
, PSA_Error
, PsdPipeStream
, pps_Error
, PKCTRL_LONG
|PKCTRL_PACKUNPACK
),
9474 PACK_ENTRY(PSA_Dummy
, PSA_TermArray
, PsdPipeStream
, pps_TermArray
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9475 PACK_ENTRY(PSA_Dummy
, PSA_AbortSigMask
, PsdPipeStream
, pps_AbortSigMask
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9476 PACK_ENTRY(PSA_Dummy
, PSA_ActivePipe
, PsdPipeStream
, pps_ActivePipe
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9477 PACK_WORDBIT(PSA_Dummy
, PSA_AsyncIO
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_ASYNCIO
),
9478 PACK_WORDBIT(PSA_Dummy
, PSA_ShortPktTerm
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_SHORTTERM
),
9479 PACK_WORDBIT(PSA_Dummy
, PSA_ReadAhead
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_READAHEAD
),
9480 PACK_WORDBIT(PSA_Dummy
, PSA_BufferedRead
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_BUFFERREAD
),
9481 PACK_WORDBIT(PSA_Dummy
, PSA_BufferedWrite
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_BUFFERWRITE
),
9482 PACK_WORDBIT(PSA_Dummy
, PSA_NoZeroPktTerm
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_NOSHORTPKT
),
9483 PACK_WORDBIT(PSA_Dummy
, PSA_NakTimeout
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_NAKTIMEOUT
),
9484 PACK_WORDBIT(PSA_Dummy
, PSA_AllowRuntPackets
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_ALLOWRUNT
),
9485 PACK_WORDBIT(PSA_Dummy
, PSA_DoNotWait
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_DONOTWAIT
),
9489 /* Pack table for PsdRTIsoHandler */
9490 static const ULONG PsdRTIsoHandlerPT
[] =
9492 PACK_STARTTABLE(RTA_Dummy
),
9493 PACK_ENTRY(RTA_Dummy
, RTA_InRequestHook
, PsdRTIsoHandler
, prt_RTIso
.urti_InReqHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9494 PACK_ENTRY(RTA_Dummy
, RTA_OutRequestHook
, PsdRTIsoHandler
, prt_RTIso
.urti_OutReqHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9495 PACK_ENTRY(RTA_Dummy
, RTA_InDoneHook
, PsdRTIsoHandler
, prt_RTIso
.urti_InDoneHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9496 PACK_ENTRY(RTA_Dummy
, RTA_OutDoneHook
, PsdRTIsoHandler
, prt_RTIso
.urti_OutDoneHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9497 PACK_ENTRY(RTA_Dummy
, RTA_ReleaseHook
, PsdRTIsoHandler
, prt_ReleaseHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9498 PACK_ENTRY(RTA_Dummy
, RTA_OutPrefetchSize
, PsdRTIsoHandler
, prt_RTIso
.urti_OutPrefetch
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9502 /* PGA assignment table */
9503 static const ULONG
*PsdPTArray
[] =