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>
44 #include <aros/bootloader.h>
45 #include <proto/bootloader.h>
48 #define NewList(list) NEWLIST(list)
50 #define min(x,y) (((x) < (y)) ? (x) : (y))
51 #define max(x,y) (((x) > (y)) ? (x) : (y))
53 extern const struct PsdWStringMap usbclasscodestr
[];
54 extern const struct PsdULStringMap usbcomboclasscodestr
[];
55 extern const struct PsdULStringMap usbdesctypestr
[];
56 extern const struct PsdWStringMap usbhwioerrstr
[];
57 extern const struct PsdUWStringMap usblangids
[];
58 extern const struct PsdUWStringMap usbvendorids
[];
60 extern struct ExecBase
*SysBase
;
63 const char GM_UNIQUENAME(libname
)[] = MOD_NAME_STRING
;
65 #define UsbClsBase puc->puc_ClassBase
66 #define DOSBase ps->ps_DosBase
67 #define TimerBase ps->ps_TimerIOReq.tr_node.io_Device
70 static int GM_UNIQUENAME(libInit
)(LIBBASETYPEPTR ps
)
72 KPRINTF(10, ("libInit ps: 0x%p SysBase: 0x%p\n",
75 ps
->ps_StackInit
= FALSE
;
76 ps
->ps_UtilityBase
= (struct UtilityBase
*) OpenLibrary("utility.library", 39);
78 #define UtilityBase ps->ps_UtilityBase
83 APTR BootLoaderBase
= OpenResource("bootloader.resource");
87 struct List
*args
= GetBootInfo(BL_Args
);
93 for (node
= args
->lh_Head
; node
->ln_Succ
; node
= node
->ln_Succ
)
95 if (stricmp(node
->ln_Name
, "usbdebug") == 0)
97 ps
->ps_Flags
= PSF_KLOG
;
105 NewList(&ps
->ps_Hardware
);
106 NewList(&ps
->ps_Classes
);
107 NewList(&ps
->ps_ErrorMsgs
);
108 NewList(&ps
->ps_EventHooks
);
109 ps
->ps_EventReplyPort
.mp_Flags
= PA_IGNORE
;
110 NewList(&ps
->ps_EventReplyPort
.mp_MsgList
);
111 NewList(&ps
->ps_ConfigRoot
);
112 NewList(&ps
->ps_AlienConfigs
);
114 NewList(&ps
->ps_DeadlockDebug
);
116 InitSemaphore(&ps
->ps_ReentrantLock
);
117 InitSemaphore(&ps
->ps_PoPoLock
);
119 if((ps
->ps_MemPool
= CreatePool(MEMF_CLEAR
|MEMF_PUBLIC
|MEMF_SEM_PROTECTED
, 16384, 1024)))
121 if((ps
->ps_SemaMemPool
= CreatePool(MEMF_CLEAR
|MEMF_PUBLIC
, 16*sizeof(struct PsdReadLock
), sizeof(struct PsdBorrowLock
))))
123 pInitSem(ps
, &ps
->ps_Lock
, "PBase");
124 pInitSem(ps
, &ps
->ps_ConfigLock
, "ConfigLock");
125 KPRINTF(20, ("libInit: Done!\n"));
128 DeletePool(ps
->ps_MemPool
);
130 KPRINTF(20, ("libInit: CreatePool() failed!\n"));
132 CloseLibrary((struct Library
*) UtilityBase
);
134 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
140 static int GM_UNIQUENAME(libOpen
)(LIBBASETYPEPTR ps
)
142 struct PsdIFFContext
*pic
;
144 KPRINTF(10, ("libOpen ps: 0x%p\n", ps
));
145 ObtainSemaphore(&ps
->ps_ReentrantLock
);
146 if(!ps
->ps_StackInit
)
148 ps
->ps_TimerIOReq
.tr_node
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
149 ps
->ps_TimerIOReq
.tr_node
.io_Message
.mn_ReplyPort
= NULL
;
150 ps
->ps_TimerIOReq
.tr_node
.io_Message
.mn_Length
= sizeof(struct timerequest
);
151 if(!OpenDevice("timer.device", UNIT_MICROHZ
, (struct IORequest
*) &ps
->ps_TimerIOReq
, 0))
153 ps
->ps_TimerIOReq
.tr_node
.io_Message
.mn_Node
.ln_Name
= "Poseidon";
154 ps
->ps_TimerIOReq
.tr_node
.io_Command
= TR_ADDREQUEST
;
156 ps
->ps_ReleaseVersion
= RELEASEVERSION
;
157 ps
->ps_OSVersion
= MAKE_ID('A','R','O','S');
159 pic
= pAllocForm(ps
, NULL
, IFFFORM_PSDCFG
);
160 if((ps
->ps_GlobalCfg
= psdAllocVec(sizeof(struct PsdGlobalCfg
))))
162 ps
->ps_GlobalCfg
->pgc_ChunkID
= AROS_LONG2BE(IFFCHNK_GLOBALCFG
);
163 ps
->ps_GlobalCfg
->pgc_Length
= AROS_LONG2BE(sizeof(struct PsdGlobalCfg
)-8);
164 ps
->ps_GlobalCfg
->pgc_LogInfo
= TRUE
;
165 ps
->ps_GlobalCfg
->pgc_LogWarning
= TRUE
;
166 ps
->ps_GlobalCfg
->pgc_LogError
= TRUE
;
167 ps
->ps_GlobalCfg
->pgc_LogFailure
= TRUE
;
168 ps
->ps_GlobalCfg
->pgc_BootDelay
= 2;
169 ps
->ps_GlobalCfg
->pgc_SubTaskPri
= 5;
170 ps
->ps_GlobalCfg
->pgc_PopupDeviceNew
= PGCP_ISNEW
;
171 ps
->ps_GlobalCfg
->pgc_PopupDeviceGone
= TRUE
;
172 ps
->ps_GlobalCfg
->pgc_PopupDeviceDeath
= TRUE
;
173 ps
->ps_GlobalCfg
->pgc_PopupCloseDelay
= 5;
174 ps
->ps_GlobalCfg
->pgc_PopupActivateWin
= FALSE
;
175 ps
->ps_GlobalCfg
->pgc_PopupWinToFront
= TRUE
;
176 ps
->ps_GlobalCfg
->pgc_AutoDisableLP
= FALSE
;
177 ps
->ps_GlobalCfg
->pgc_AutoDisableDead
= FALSE
;
178 ps
->ps_GlobalCfg
->pgc_AutoRestartDead
= TRUE
;
179 ps
->ps_GlobalCfg
->pgc_PowerSaving
= FALSE
;
180 ps
->ps_GlobalCfg
->pgc_ForceSuspend
= FALSE
;
181 ps
->ps_GlobalCfg
->pgc_SuspendTimeout
= 30;
183 ps
->ps_GlobalCfg
->pgc_PrefsVersion
= 0; // is updated on writing
184 ps
->ps_ConfigRead
= FALSE
;
187 pic
= pAllocForm(ps
, pic
, IFFFORM_STACKCFG
);
190 pAddCfgChunk(ps
, pic
, ps
->ps_GlobalCfg
);
193 ps
->ps_PoPo
.po_InsertSndFile
= psdCopyStr("SYS:Prefs/Presets/Poseidon/Connect.iff");
194 ps
->ps_PoPo
.po_RemoveSndFile
= psdCopyStr("SYS:Prefs/Presets/Poseidon/Disconnect.iff");
198 tmpstr
= psdCopyStr((STRPTR
) VERSION_STRING
);
201 tmpstr
[strlen(tmpstr
)-2] = 0;
202 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Welcome to %s (%p)!", tmpstr
, ps
->ps_ReleaseVersion
);
205 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Welcome to %s", VERSION_STRING
);
209 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "This is the AROS port.");
211 KPRINTF(10, ("libOpen: Ok\n"));
212 ps
->ps_StackInit
= TRUE
;
213 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
214 pStartEventHandler(ps
);
218 KPRINTF(20, ("libOpen: No memory for cfg!\n"));
221 KPRINTF(20, ("libOpen: OpenDevice(timer.device) failed!\n"));
223 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
226 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
227 KPRINTF(5, ("libOpen: openCnt = %ld\n", ps
->ps_Library
.lib_OpenCnt
));
231 int GM_UNIQUENAME(libExpunge
)(LIBBASETYPEPTR ps
)
233 struct PsdHardware
*phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
234 struct PsdUsbClass
*puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
235 struct PsdErrorMsg
*pem
= (struct PsdErrorMsg
*) ps
->ps_ErrorMsgs
.lh_Head
;
236 struct PsdIFFContext
*pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
237 KPRINTF(10, ("libExpunge ps: 0x%p\n", ps
));
238 while(phw
->phw_Node
.ln_Succ
)
241 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
243 while(puc
->puc_Node
.ln_Succ
)
246 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
248 while(pem
->pem_Node
.ln_Succ
)
251 pem
= (struct PsdErrorMsg
*) ps
->ps_ErrorMsgs
.lh_Head
;
254 while(pic
->pic_Node
.ln_Succ
)
257 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
260 if(ps
->ps_PoPo
.po_Task
)
262 ps
->ps_PoPo
.po_ReadySignal
= SIGB_SINGLE
;
263 ps
->ps_PoPo
.po_ReadySigTask
= FindTask(NULL
);
264 Signal(ps
->ps_PoPo
.po_Task
, SIGBREAKF_CTRL_C
);
265 while(ps
->ps_PoPo
.po_Task
)
267 Wait(1L<<ps
->ps_PoPo
.po_ReadySignal
);
269 ps
->ps_PoPo
.po_ReadySigTask
= NULL
;
270 //FreeSignal(ps->ps_PoPo.po_ReadySignal);
272 if(ps
->ps_EventHandler
.ph_Task
)
274 ps
->ps_EventHandler
.ph_ReadySignal
= SIGB_SINGLE
;
275 ps
->ps_EventHandler
.ph_ReadySigTask
= FindTask(NULL
);
276 Signal(ps
->ps_EventHandler
.ph_Task
, SIGBREAKF_CTRL_C
);
277 while(ps
->ps_EventHandler
.ph_Task
)
279 Wait(1L<<ps
->ps_EventHandler
.ph_ReadySignal
);
281 ps
->ps_EventHandler
.ph_ReadySigTask
= NULL
;
282 //FreeSignal(ps->ps_EventHandler.ph_ReadySignal);
284 psdFreeVec(ps
->ps_PoPo
.po_InsertSndFile
);
285 psdFreeVec(ps
->ps_PoPo
.po_RemoveSndFile
);
286 pGarbageCollectEvents(ps
);
288 CloseDevice((struct IORequest
*) &ps
->ps_TimerIOReq
);
289 DeletePool(ps
->ps_SemaMemPool
);
290 DeletePool(ps
->ps_MemPool
);
292 KPRINTF(1, ("libExpunge: closelibrary utilitybase 0x%p\n",
294 CloseLibrary((struct Library
*) UtilityBase
);
296 CloseLibrary(DOSBase
);
298 KPRINTF(1, ("libExpunge: removing library node 0x%p\n",
299 &ps
->ps_Library
.lib_Node
));
300 Remove(&ps
->ps_Library
.lib_Node
);
306 ADD2INITLIB(GM_UNIQUENAME(libInit
), 0)
307 ADD2OPENLIB(GM_UNIQUENAME(libOpen
), 0)
308 ADD2EXPUNGELIB(GM_UNIQUENAME(libExpunge
), 0);
311 * ***********************************************************************
312 * * Library functions *
313 * ***********************************************************************
316 static const ULONG
*PsdPTArray
[PGA_LAST
+1];
320 /* /// "psdAllocVec()" */
321 AROS_LH1(APTR
, psdAllocVec
,
322 AROS_LHA(ULONG
, size
, D0
),
323 LIBBASETYPEPTR
, ps
, 5, psd
)
327 KPRINTF(1, ("psdAllocVec(%ld)\n", size
));
329 if((pmem
= AllocPooled(ps
->ps_MemPool
, size
+ (1*sizeof(ULONG
)))))
332 if((pmem
= AllocPooled(ps
->ps_MemPool
, size
+ (1*sizeof(ULONG
)) + 1024)))
334 ULONG upos
= size
+ (1*sizeof(ULONG
));
336 UBYTE
*dbptr
= (UBYTE
*) pmem
;
344 ps
->ps_MemAllocated
+= size
;
352 /* /// "psdFreeVec()" */
353 AROS_LH1(void, psdFreeVec
,
354 AROS_LHA(APTR
, pmem
, A1
),
355 LIBBASETYPEPTR
, ps
, 6, psd
)
360 KPRINTF(1, ("psdFreeVec(%p)\n", pmem
));
363 size
= ((ULONG
*) pmem
)[-1];
364 ps
->ps_MemAllocated
-= size
;
367 FreePooled(ps
->ps_MemPool
, &((ULONG
*) pmem
)[-1], size
+ (1*sizeof(ULONG
)) + 1024);
369 FreePooled(ps
->ps_MemPool
, &((ULONG
*) pmem
)[-1], size
+ (1*sizeof(ULONG
)));
378 /* /// "pDebugSemaInfo()" */
379 void pDebugSemaInfo(LIBBASETYPEPTR ps
, struct PsdSemaInfo
*psi
)
381 struct PsdReadLock
*prl
;
382 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
383 "Semaphore %p %s (Excl/SharedLockCount %ld/%ld) (Owner: %s):",
385 psi
->psi_LockSem
->pls_Node
.ln_Name
,
386 psi
->psi_LockSem
->pls_ExclLockCount
,
387 psi
->psi_LockSem
->pls_SharedLockCount
,
388 psi
->psi_LockSem
->pls_Owner
? (const char *)psi
->psi_LockSem
->pls_Owner
->tc_Node
.ln_Name
: "None");
390 prl
= (struct PsdReadLock
*) psi
->psi_LockSem
->pls_WaitQueue
.lh_Head
;
391 while(prl
->prl_Node
.ln_Succ
)
393 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
394 " Waiting Task: %p (%s) %s",
395 prl
->prl_Task
, prl
->prl_Task
->tc_Node
.ln_Name
,
396 prl
->prl_IsExcl
? "Excl" : "Shared");
397 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
399 prl
= (struct PsdReadLock
*) psi
->psi_LockSem
->pls_ReadLocks
.lh_Head
;
400 while(prl
->prl_Node
.ln_Succ
)
402 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
403 " Readlock Task: %p (%s), Count %ld",
404 prl
->prl_Task
, prl
->prl_Task
->tc_Node
.ln_Name
,
406 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
411 /* /// "pInitSem()" */
412 void pInitSem(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
, STRPTR name
)
414 struct PsdSemaInfo
*psi
= NULL
;
415 NewList(&pls
->pls_WaitQueue
);
416 NewList(&pls
->pls_ReadLocks
);
417 pls
->pls_Node
.ln_Name
= name
;
418 // struct should be nulled anyway
419 pls
->pls_Owner
= NULL
;
420 pls
->pls_ExclLockCount
= 0;
421 pls
->pls_SharedLockCount
= 0;
422 pls
->pls_Dead
= FALSE
;
425 psi
= (struct PsdSemaInfo
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdSemaInfo
));
431 psi
->psi_LockSem
= pls
;
432 AddTail(&ps
->ps_DeadlockDebug
, &psi
->psi_Node
);
437 /* /// "pDeleteSem()" */
438 void pDeleteSem(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
)
440 struct PsdSemaInfo
*psi
;
442 pls
->pls_Dead
= TRUE
;
443 psi
= (struct PsdSemaInfo
*) ps
->ps_DeadlockDebug
.lh_Head
;
444 while(psi
->psi_Node
.ln_Succ
)
446 if(psi
->psi_LockSem
== pls
)
448 if(pls
->pls_SharedLockCount
+ pls
->pls_ExclLockCount
)
450 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Semaphore still locked when attempting to delete it!\n");
451 pDebugSemaInfo(ps
, psi
);
453 Remove(&psi
->psi_Node
);
454 FreePooled(ps
->ps_SemaMemPool
, psi
, sizeof(struct PsdSemaInfo
));
458 psi
= (struct PsdSemaInfo
*) psi
->psi_Node
.ln_Succ
;
464 /* /// "pLockSemExcl()" */
465 void pLockSemExcl(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
)
467 struct PsdReadLock waitprl
;
468 struct Task
*thistask
= FindTask(NULL
);
470 waitprl
.prl_Task
= thistask
;
471 waitprl
.prl_IsExcl
= TRUE
;
476 // it's already mine!!
477 if(thistask
== pls
->pls_Owner
)
481 if(!pls
->pls_ExclLockCount
)
483 // easy case: no shared locks, no exclusive locker
484 if(!pls
->pls_SharedLockCount
)
488 // sole readlock promotion case
489 if((pls
->pls_SharedLockCount
== 1) && ((struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
)->prl_Task
== thistask
)
491 KPRINTF(1, ("Promoting read lock (%p) to write lock!\n", thistask
));
496 // okay, bad luck, we've got to wait somehow
497 AddHead(&pls
->pls_WaitQueue
, &waitprl
.prl_Node
);
498 thistask
->tc_SigRecvd
&= ~SIGF_SINGLE
;
502 Remove(&waitprl
.prl_Node
);
504 pls
->pls_Owner
= thistask
;
505 pls
->pls_ExclLockCount
++;
510 /* /// "pLockSemShared()" */
511 void pLockSemShared(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
)
513 struct PsdReadLock
*prl
;
514 struct Task
*thistask
= FindTask(NULL
);
517 // is this already locked exclusively by me?
518 if(thistask
== pls
->pls_Owner
)
520 // yes? then just increase exclusive lock count
521 pls
->pls_ExclLockCount
++;
526 // find existing readlock
527 prl
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
528 while(prl
->prl_Node
.ln_Succ
)
530 if(prl
->prl_Task
== thistask
)
532 KPRINTF(1, ("Increasing ReadLock (%p) count to %ld\n", thistask
, prl
->prl_Count
));
537 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
540 // this is a new readlock, generate context
541 if(!(prl
= (struct PsdReadLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdReadLock
))))
543 KPRINTF(20, ("No mem for shared lock! context (%p) on %p\n", thistask
, pls
));
544 // try exclusive lock as fallback (needs no memory)
546 pLockSemExcl(ps
, pls
);
550 KPRINTF(1, ("New ReadLockShared context (%p) on %p\n", thistask
, pls
));
551 prl
->prl_Task
= thistask
;
553 prl
->prl_IsExcl
= FALSE
;
555 // if it's exclusively locked, wait for this lock to vanish
556 while(pls
->pls_Owner
)
558 AddTail(&pls
->pls_WaitQueue
, &prl
->prl_Node
);
559 thistask
->tc_SigRecvd
&= ~SIGF_SINGLE
;
563 Remove(&prl
->prl_Node
);
568 // we got promoted by BorrowLocks during the process! So we don't need the shared stuff anymore
569 FreePooled(ps
->ps_SemaMemPool
, prl
, sizeof(struct PsdReadLock
));
570 pls
->pls_Owner
= thistask
;
571 pls
->pls_ExclLockCount
++;
574 AddHead(&pls
->pls_ReadLocks
, &prl
->prl_Node
);
576 pls
->pls_SharedLockCount
++;
583 /* /// "pUnlockSem()" */
584 void pUnlockSem(LIBBASETYPEPTR ps
, struct PsdLockSem
*pls
)
586 struct PsdReadLock
*prl
;
587 struct Task
*thistask
= FindTask(NULL
);
593 // exclusively locked, this means unlocking task must be owner
594 if(pls
->pls_Owner
!= thistask
)
597 psdDebugSemaphores();
598 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
599 "Attempt to unlock exclusive semaphore %p not owned by task %s!",
600 pls
, thistask
->tc_Node
.ln_Name
);
604 if(--pls
->pls_ExclLockCount
)
610 pls
->pls_Owner
= NULL
;
611 // otherwise drop through and notify
613 if(!pls
->pls_SharedLockCount
)
616 psdDebugSemaphores();
617 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
618 "Attempt to unlock (free) semaphore %p once too often by task %s!",
619 pls
, thistask
->tc_Node
.ln_Name
);
623 prl
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
624 while(prl
->prl_Node
.ln_Succ
)
626 if(prl
->prl_Task
== thistask
)
630 // can't be the last lock, so just reduce count and return
634 // remove read lock, it's no longer needed
635 KPRINTF(1, ("Removing read lock context (%p) on %p!\n", thistask
, pls
));
636 Remove(&prl
->prl_Node
);
637 FreePooled(ps
->ps_SemaMemPool
, prl
, sizeof(struct PsdReadLock
));
639 // losing a designated lock
640 pls
->pls_SharedLockCount
--;
643 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
648 psdDebugSemaphores();
649 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
650 "Attempt to unlock (shared) semaphore %p once too often by task %s!",
651 pls
, thistask
->tc_Node
.ln_Name
);
655 // we need to notify anyway, because the waiter could already have a shared lock
656 // on the same semaphore, and if we only notified on LockCount reaching zero,
657 // the locker would wait forever.
660 // notify waiting tasks
661 prl
= (struct PsdReadLock
*) pls
->pls_WaitQueue
.lh_Head
;
662 while(prl
->prl_Node
.ln_Succ
)
664 Signal(prl
->prl_Task
, SIGF_SINGLE
);
665 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
671 /* /// "psdDebugSemaphores()" */
672 AROS_LH0(void, psdDebugSemaphores
,
673 LIBBASETYPEPTR
, ps
, 81, psd
)
676 struct Task
*thistask
= FindTask(NULL
);
677 struct PsdSemaInfo
*psi
;
679 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
680 "Debug Semaphores (%p)", thistask
);
683 // search for context
684 psi
= (struct PsdSemaInfo
*) ps
->ps_DeadlockDebug
.lh_Head
;
685 while(psi
->psi_Node
.ln_Succ
)
687 pDebugSemaInfo(ps
, psi
);
688 psi
= (struct PsdSemaInfo
*) psi
->psi_Node
.ln_Succ
;
695 /* /// "psdLockReadPBase()" */
696 AROS_LH0(void, psdLockReadPBase
,
697 LIBBASETYPEPTR
, ps
, 8, psd
)
700 KPRINTF(2, ("psdLockReadPBase(%p)\n", FindTask(NULL
)));
701 pLockSemShared(ps
, &ps
->ps_Lock
);
706 /* /// "psdLockWritePBase()" */
707 AROS_LH0(void, psdLockWritePBase
,
708 LIBBASETYPEPTR
, ps
, 7, psd
)
711 KPRINTF(2, ("psdLockWritePBase(%p)\n", FindTask(NULL
)));
712 pLockSemExcl(ps
, &ps
->ps_Lock
);
717 /* /// "psdUnlockPBase()" */
718 AROS_LH0(void, psdUnlockPBase
,
719 LIBBASETYPEPTR
, ps
, 9, psd
)
722 KPRINTF(2, ("psdUnlockPBase(%p)\n", FindTask(NULL
)));
723 pUnlockSem(ps
, &ps
->ps_Lock
);
728 /* /// "psdBorrowLocksWait()" */
729 AROS_LH2(ULONG
, psdBorrowLocksWait
,
730 AROS_LHA(struct Task
*, task
, A1
),
731 AROS_LHA(ULONG
, signals
, D0
),
732 LIBBASETYPEPTR
, ps
, 97, psd
)
735 struct Task
*thistask
= FindTask(NULL
);
738 struct PsdSemaInfo
*psi
;
739 struct PsdLockSem
*pls
;
740 struct PsdReadLock
*prl
;
741 struct PsdBorrowLock
*pbl
;
743 struct List reclaims
;
746 XPRINTF(10, ("Borrowing locks from %p (%s) to %p (%s)!\n",
747 thistask
, thistask
->tc_Node
.ln_Name
, task
, task
->tc_Node
.ln_Name
));
750 psi
= (struct PsdSemaInfo
*) ps
->ps_DeadlockDebug
.lh_Head
;
751 while(psi
->psi_Node
.ln_Succ
)
753 pls
= psi
->psi_LockSem
;
754 if(pls
->pls_Owner
== thistask
)
758 if(pls
->pls_SharedLockCount
)
760 struct PsdReadLock
*prl
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
763 if(prl
->prl_Task
== thistask
)
768 } while((prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
)->prl_Node
.ln_Succ
);
770 psi
= (struct PsdSemaInfo
*) psi
->psi_Node
.ln_Succ
;
775 XPRINTF(10, ("Nothing to borrow!\n"));
776 return(Wait(signals
));
781 XPRINTF(10, ("Borrowing %ld locks\n", cnt
));
783 psi
= (struct PsdSemaInfo
*) ps
->ps_DeadlockDebug
.lh_Head
;
784 while(psi
->psi_Node
.ln_Succ
)
787 pls
= psi
->psi_LockSem
;
788 if(pls
->pls_Owner
== thistask
)
790 // check if the target task is already waiting for that lock
791 // in this case, we simply remove our exclusive lock and let
792 // the other task catch it
793 prl
= (struct PsdReadLock
*) pls
->pls_WaitQueue
.lh_Head
;
794 while(prl
->prl_Node
.ln_Succ
)
796 if(prl
->prl_Task
== task
)
800 // if we hand over the excl lock, we have to make sure that the exclusiveness is kept
801 // and no other thread may catch it while it is shared.
802 // hence we will need set this lock exclusive aswell
803 // this no optimal solution, but it guarantees the same
804 // behaviour with pending lock and no pending lock
805 prl
->prl_IsExcl
= TRUE
;
806 XPRINTF(10, ("Promo waiting lock to excl\n"));
808 // move shared lock to top of the list
809 Remove(&prl
->prl_Node
);
810 AddHead(&pls
->pls_WaitQueue
, &prl
->prl_Node
);
811 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
813 pbl
->pbl_LockSem
= pls
;
814 pbl
->pbl_ExclLockCount
= pls
->pls_ExclLockCount
;
815 AddTail(&reclaims
, &pbl
->pbl_Node
);
817 // unlock exclusive lock
818 pls
->pls_ExclLockCount
= 0;
819 pls
->pls_Owner
= NULL
;
820 Signal(task
, SIGF_SINGLE
);
821 XPRINTF(10, ("Waiting lock %p transfer\n", pls
));
826 prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
;
830 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
832 pbl
->pbl_LockSem
= pls
;
833 pbl
->pbl_ExclLockCount
= pls
->pls_ExclLockCount
;
834 AddTail(&borrows
, &pbl
->pbl_Node
);
835 pls
->pls_Owner
= task
;
836 XPRINTF(10, ("Lock %p transfer\n", pls
));
840 if(pls
->pls_SharedLockCount
)
842 prl
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
845 if(prl
->prl_Task
== thistask
)
847 // check if target task is waiting for this task
848 struct PsdReadLock
*prl2
= (struct PsdReadLock
*) pls
->pls_WaitQueue
.lh_Head
;
849 while(prl2
->prl_Node
.ln_Succ
)
851 if(prl2
->prl_Task
== task
)
853 // move lock to top of the list
854 Remove(&prl2
->prl_Node
);
855 AddHead(&pls
->pls_WaitQueue
, &prl2
->prl_Node
);
856 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
858 pbl
->pbl_LockSem
= pls
;
859 pbl
->pbl_ReadLock
= prl
;
860 pbl
->pbl_Count
= prl
->prl_Count
;
861 AddHead(&reclaims
, &pbl
->pbl_Node
);
863 // unlock shared lock
864 Remove(&prl
->prl_Node
);
865 FreePooled(ps
->ps_SemaMemPool
, prl
, sizeof(struct PsdReadLock
));
866 pls
->pls_SharedLockCount
--;
867 Signal(task
, SIGF_SINGLE
);
870 XPRINTF(10, ("Waiting shared lock %p transfer\n", pls
));
873 prl2
= (struct PsdReadLock
*) prl2
->prl_Node
.ln_Succ
;
877 // check if target task already has a shared lock on this
878 prl2
= (struct PsdReadLock
*) pls
->pls_ReadLocks
.lh_Head
;
881 if(prl2
->prl_Task
== task
)
883 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
885 // we redirect to this other lock
886 pbl
->pbl_LockSem
= pls
;
887 pbl
->pbl_ReadLock
= prl2
;
888 pbl
->pbl_Count
= prl
->prl_Count
; // save the old lock count
889 AddTail(&borrows
, &pbl
->pbl_Node
);
891 // unlock shared lock
892 Remove(&prl
->prl_Node
);
893 FreePooled(ps
->ps_SemaMemPool
, prl
, sizeof(struct PsdReadLock
));
894 pls
->pls_SharedLockCount
--;
895 // just increase lockcount, so a split occurs automatically
896 prl2
->prl_Count
+= pbl
->pbl_Count
;
898 XPRINTF(10, ("Already locked %p transfer\n", pls
));
902 } while((prl2
= (struct PsdReadLock
*) prl2
->prl_Node
.ln_Succ
)->prl_Node
.ln_Succ
);
906 if((pbl
= (struct PsdBorrowLock
*) AllocPooled(ps
->ps_SemaMemPool
, sizeof(struct PsdBorrowLock
))))
908 pbl
->pbl_LockSem
= pls
;
909 pbl
->pbl_ReadLock
= prl
;
910 pbl
->pbl_Count
= prl
->prl_Count
;
911 AddTail(&borrows
, &pbl
->pbl_Node
);
912 prl
->prl_Task
= task
;
913 XPRINTF(10, ("Std lock %p transfer\n", pls
));
918 } while((prl
= (struct PsdReadLock
*) prl
->prl_Node
.ln_Succ
)->prl_Node
.ln_Succ
);
920 psi
= (struct PsdSemaInfo
*) psi
->psi_Node
.ln_Succ
;
923 sigmask
= Wait(signals
);
925 // try to get moved locks back first
926 pbl
= (struct PsdBorrowLock
*) borrows
.lh_Head
;
927 while(pbl
->pbl_Node
.ln_Succ
)
929 Remove(&pbl
->pbl_Node
);
930 pls
= pbl
->pbl_LockSem
;
931 if(pbl
->pbl_ExclLockCount
)
933 if(pbl
->pbl_ExclLockCount
== pls
->pls_ExclLockCount
)
935 // all fine, other task didn't use the locks or returned them already
936 pls
->pls_Owner
= thistask
;
937 FreePooled(ps
->ps_SemaMemPool
, pbl
, sizeof(struct PsdBorrowLock
));
939 // okay, bad thing, release lock and try to obtain it again -- eventually the other task should free the lock again
940 pls
->pls_ExclLockCount
-= pbl
->pbl_ExclLockCount
;
941 AddTail(&reclaims
, &pbl
->pbl_Node
);
944 if(pls
->pls_Owner
== task
)
946 // oh, damn. The other task converted our shared lock into an exclusive lock --
947 // we cannot claim this back right now. This gets tricky now.
948 if(pbl
->pbl_Count
== pbl
->pbl_ReadLock
->prl_Count
)
950 // luckily, the count didn't change, so we just release the shared lock and requeue us into the reclaim list
951 Remove(&pbl
->pbl_ReadLock
->prl_Node
);
952 FreePooled(ps
->ps_SemaMemPool
, pbl
->pbl_ReadLock
, sizeof(struct PsdReadLock
));
953 pbl
->pbl_ReadLock
= NULL
;
954 pls
->pls_SharedLockCount
--; // should turn to 0
956 // can it get worse? obviously, the alien task also has added some read locks
957 // this means we need to split up!
958 // therefore we leave a few lock counts and requeue
959 pbl
->pbl_ReadLock
->prl_Count
-= pbl
->pbl_Count
;
960 pbl
->pbl_ReadLock
= NULL
;
962 AddHead(&reclaims
, &pbl
->pbl_Node
);
964 if(pbl
->pbl_Count
== pbl
->pbl_ReadLock
->prl_Count
)
966 // the count didn't change, just so just change owner
967 pbl
->pbl_ReadLock
->prl_Task
= thistask
;
968 FreePooled(ps
->ps_SemaMemPool
, pbl
, sizeof(struct PsdBorrowLock
));
970 // the alien task still has some read locks
971 // this means we need to split up!
972 // therefore we leave a few lock counts and requeue
973 pbl
->pbl_ReadLock
->prl_Count
-= pbl
->pbl_Count
;
974 pbl
->pbl_ReadLock
= NULL
;
975 AddHead(&reclaims
, &pbl
->pbl_Node
);
979 pbl
= (struct PsdBorrowLock
*) borrows
.lh_Head
;
982 // try to reclaim released locks
983 pbl
= (struct PsdBorrowLock
*) reclaims
.lh_Head
;
984 while(pbl
->pbl_Node
.ln_Succ
)
986 Remove(&pbl
->pbl_Node
);
987 pls
= pbl
->pbl_LockSem
;
988 while(pbl
->pbl_Count
)
990 pLockSemShared(ps
, pls
);
993 while(pbl
->pbl_ExclLockCount
)
995 pLockSemExcl(ps
, pls
);
996 --pbl
->pbl_ExclLockCount
;
998 FreePooled(ps
->ps_SemaMemPool
, pbl
, sizeof(struct PsdBorrowLock
));
999 pbl
= (struct PsdBorrowLock
*) reclaims
.lh_Head
;
1008 /* *** Support *** */
1010 /* /// "psdCopyStr()" */
1011 AROS_LH1(STRPTR
, psdCopyStr
,
1012 AROS_LHA(CONST_STRPTR
, name
, A0
),
1013 LIBBASETYPEPTR
, ps
, 10, psd
)
1016 STRPTR rs
= psdAllocVec((ULONG
) strlen(name
)+1);
1017 KPRINTF(1, ("psdCopyStr(%s)\n", name
));
1027 /* /// "psdSafeRawDoFmtA()" */
1028 AROS_LH4(void, psdSafeRawDoFmtA
,
1029 AROS_LHA(STRPTR
, buf
, A0
),
1030 AROS_LHA(ULONG
, len
, D0
),
1031 AROS_LHA(CONST_STRPTR
, fmtstr
, A1
),
1032 AROS_LHA(RAWARG
, fmtdata
, A2
),
1033 LIBBASETYPEPTR
, ps
, 42, psd
)
1036 struct PsdRawDoFmt rdf
;
1042 RawDoFmt(fmtstr
, fmtdata
, (void (*)()) pPutChar
, &rdf
);
1049 /* /// "pPutChar()" */
1050 AROS_UFH2(void, pPutChar
,
1051 AROS_UFHA(char, ch
, D0
),
1052 AROS_UFHA(struct PsdRawDoFmt
*, rdf
, A3
))
1058 *rdf
->rdf_Buf
++ = ch
;
1064 /* /// "psdCopyStrFmtA()" */
1065 AROS_LH2(STRPTR
, psdCopyStrFmtA
,
1066 AROS_LHA(CONST_STRPTR
, fmtstr
, A0
),
1067 AROS_LHA(RAWARG
, fmtdata
, A1
),
1068 LIBBASETYPEPTR
, ps
, 68, psd
)
1074 RawDoFmt(fmtstr
, fmtdata
, (void (*)()) pRawFmtLength
, &len
);
1075 buf
= psdAllocVec(len
+1);
1078 psdSafeRawDoFmtA(buf
, len
+1, fmtstr
, fmtdata
);
1085 /* /// "pRawFmtLength()" */
1086 AROS_UFH2(void, pRawFmtLength
,
1087 AROS_UFHA(char, ch
, D0
),
1088 AROS_UFHA(ULONG
*, len
, A3
))
1096 /* /// "psdDelayMS()" */
1097 AROS_LH1(void, psdDelayMS
,
1098 AROS_LHA(ULONG
, milli
, D0
),
1099 LIBBASETYPEPTR
, ps
, 11, psd
)
1103 struct timerequest tr
;
1105 KPRINTF(1, ("psdDelayMS(%ld)\n", milli
));
1106 mp
.mp_Flags
= PA_SIGNAL
;
1107 mp
.mp_SigBit
= SIGB_SINGLE
;
1108 mp
.mp_SigTask
= FindTask(NULL
);
1109 NewList(&mp
.mp_MsgList
);
1110 CopyMem(&ps
->ps_TimerIOReq
, &tr
, sizeof(tr
));
1111 tr
.tr_node
.io_Message
.mn_ReplyPort
= &mp
;
1112 tr
.tr_time
.tv_secs
= 0;
1113 tr
.tr_time
.tv_micro
= milli
* 1000;
1114 DoIO((struct IORequest
*) &tr
);
1119 /* /// "psdGetAttrsA()" */
1120 AROS_LH3(LONG
, psdGetAttrsA
,
1121 AROS_LHA(ULONG
, type
, D0
),
1122 AROS_LHA(APTR
, psdstruct
, A0
),
1123 AROS_LHA(struct TagItem
*, tags
, A1
),
1124 LIBBASETYPEPTR
, ps
, 22, psd
)
1129 ULONG
*packtab
= NULL
;
1131 KPRINTF(1, ("psdGetAttrsA(%ld, %p, %p)\n", type
, psdstruct
, tags
));
1133 if(type
<= PGA_LAST
)
1135 packtab
= (ULONG
*) PsdPTArray
[type
];
1142 if((ti
= FindTagItem(PA_HardwareList
, tags
)))
1144 *((struct List
**) ti
->ti_Data
) = &ps
->ps_Hardware
;
1147 if((ti
= FindTagItem(PA_ClassList
, tags
)))
1149 *((struct List
**) ti
->ti_Data
) = &ps
->ps_Classes
;
1152 if((ti
= FindTagItem(PA_ErrorMsgList
, tags
)))
1154 *((struct List
**) ti
->ti_Data
) = &ps
->ps_ErrorMsgs
;
1160 if((ti
= FindTagItem(HA_DeviceList
, tags
)))
1162 *((struct List
**) ti
->ti_Data
) = &(((struct PsdHardware
*) psdstruct
)->phw_Devices
);
1168 if((ti
= FindTagItem(DA_ConfigList
, tags
)))
1170 *((struct List
**) ti
->ti_Data
) = &(((struct PsdDevice
*) psdstruct
)->pd_Configs
);
1173 if((ti
= FindTagItem(DA_DescriptorList
, tags
)))
1175 *((struct List
**) ti
->ti_Data
) = &(((struct PsdDevice
*) psdstruct
)->pd_Descriptors
);
1181 if((ti
= FindTagItem(CA_InterfaceList
, tags
)))
1183 *((struct List
**) ti
->ti_Data
) = &(((struct PsdConfig
*) psdstruct
)->pc_Interfaces
);
1189 if((ti
= FindTagItem(IFA_EndpointList
, tags
)))
1191 *((struct List
**) ti
->ti_Data
) = &(((struct PsdInterface
*) psdstruct
)->pif_EPs
);
1194 if((ti
= FindTagItem(IFA_AlternateIfList
, tags
)))
1196 *((struct List
**) ti
->ti_Data
) = &(((struct PsdInterface
*) psdstruct
)->pif_AlterIfs
);
1202 if((ti
= FindTagItem(EMA_DateStamp
, tags
)))
1204 *((struct DateStamp
**) ti
->ti_Data
) = &(((struct PsdErrorMsg
*) psdstruct
)->pem_DateStamp
);
1210 if((ti
= FindTagItem(PPA_IORequest
, tags
)))
1212 *((struct IOUsbHWReq
**) ti
->ti_Data
) = &(((struct PsdPipe
*) psdstruct
)->pp_IOReq
);
1218 if((ti
= FindTagItem(GCA_InsertionSound
, tags
)))
1221 *((STRPTR
*) ti
->ti_Data
) = ps
->ps_PoPo
.po_InsertSndFile
;
1223 if((ti
= FindTagItem(GCA_RemovalSound
, tags
)))
1226 *((STRPTR
*) ti
->ti_Data
) = ps
->ps_PoPo
.po_RemoveSndFile
;
1232 return((LONG
) (UnpackStructureTags(psdstruct
, (ULONG
*) packtab
, tags
)+count
));
1240 /* /// "psdSetAttrsA()" */
1241 AROS_LH3(LONG
, psdSetAttrsA
,
1242 AROS_LHA(ULONG
, type
, D0
),
1243 AROS_LHA(APTR
, psdstruct
, A0
),
1244 AROS_LHA(struct TagItem
*, tags
, A1
),
1245 LIBBASETYPEPTR
, ps
, 23, psd
)
1250 ULONG
*packtab
= NULL
;
1251 BOOL savepopocfg
= FALSE
;
1252 BOOL checkcfgupdate
= FALSE
;
1253 BOOL powercalc
= FALSE
;
1256 KPRINTF(1, ("psdSetAttrsA(%ld, %p, %p)\n", type
, psdstruct
, tags
));
1258 if(type
<= PGA_LAST
)
1260 packtab
= (ULONG
*) PsdPTArray
[type
];
1266 if(FindTagItem(DA_InhibitPopup
, tags
) || FindTagItem(DA_InhibitClassBind
, tags
))
1270 if(FindTagItem(DA_OverridePowerInfo
, tags
))
1282 if((ti
= FindTagItem(GCA_InsertionSound
, tags
)))
1285 if(strcmp(ps
->ps_PoPo
.po_InsertSndFile
, (STRPTR
) ti
->ti_Data
))
1287 psdFreeVec(ps
->ps_PoPo
.po_InsertSndFile
);
1288 ps
->ps_PoPo
.po_InsertSndFile
= psdCopyStr((STRPTR
) ti
->ti_Data
);
1291 if((ti
= FindTagItem(GCA_RemovalSound
, tags
)))
1294 if(strcmp(ps
->ps_PoPo
.po_RemoveSndFile
, (STRPTR
) ti
->ti_Data
))
1296 psdFreeVec(ps
->ps_PoPo
.po_RemoveSndFile
);
1297 ps
->ps_PoPo
.po_RemoveSndFile
= psdCopyStr((STRPTR
) ti
->ti_Data
);
1300 checkcfgupdate
= TRUE
;
1303 case PGA_PIPESTREAM
:
1305 struct PsdPipeStream
*pps
= (struct PsdPipeStream
*) psdstruct
;
1307 ULONG oldbufsize
= pps
->pps_BufferSize
;
1308 ULONG oldnumpipes
= pps
->pps_NumPipes
;
1311 KPRINTF(1, ("SetAttrs PIPESTREAM\n"));
1312 ObtainSemaphore(&pps
->pps_AccessLock
);
1313 if((ti
= FindTagItem(PSA_MessagePort
, tags
)))
1316 if((pps
->pps_Flags
& PSFF_OWNMSGPORT
) && pps
->pps_MsgPort
)
1318 KPRINTF(1, ("Deleting old MsgPort\n"));
1319 DeleteMsgPort(pps
->pps_MsgPort
);
1320 pps
->pps_MsgPort
= NULL
;
1322 pps
->pps_Flags
&= ~PSFF_OWNMSGPORT
;
1324 count
+= PackStructureTags(psdstruct
, packtab
, tags
);
1325 KPRINTF(1, ("Pipes = %ld (old: %ld), BufferSize = %ld (old: %ld)\n",
1326 pps
->pps_NumPipes
, oldnumpipes
, pps
->pps_BufferSize
, oldbufsize
));
1327 if(pps
->pps_NumPipes
< 1)
1329 pps
->pps_NumPipes
= 1; /* minimal */
1331 if(pps
->pps_BufferSize
< pps
->pps_Endpoint
->pep_MaxPktSize
)
1333 pps
->pps_BufferSize
= pps
->pps_Endpoint
->pep_MaxPktSize
; /* minimal */
1335 if(!pps
->pps_MsgPort
)
1337 if((pps
->pps_MsgPort
= CreateMsgPort()))
1339 KPRINTF(1, ("Creating MsgPort\n"));
1340 pps
->pps_Flags
|= PSFF_OWNMSGPORT
;
1343 /* do we need to reallocate? */
1344 if((oldbufsize
!= pps
->pps_BufferSize
) ||
1345 (oldnumpipes
!= pps
->pps_NumPipes
) ||
1346 (!pps
->pps_Pipes
) ||
1351 KPRINTF(1, ("freeing %ld old pipes\n", oldnumpipes
));
1352 for(cnt
= 0; cnt
< oldnumpipes
; cnt
++)
1354 pp
= pps
->pps_Pipes
[cnt
];
1355 //if(pp->pp_IOReq.iouh_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
1357 KPRINTF(1, ("Abort %ld\n", cnt
));
1359 KPRINTF(1, ("Wait %ld\n", cnt
));
1362 KPRINTF(1, ("Free %ld\n", cnt
));
1365 psdFreeVec(pps
->pps_Pipes
);
1367 psdFreeVec(pps
->pps_Buffer
);
1369 NewList(&pps
->pps_FreePipes
);
1370 NewList(&pps
->pps_ReadyPipes
);
1371 pps
->pps_Offset
= 0;
1372 pps
->pps_BytesPending
= 0;
1373 pps
->pps_ReqBytes
= 0;
1374 pps
->pps_ActivePipe
= NULL
;
1375 pps
->pps_Buffer
= psdAllocVec(pps
->pps_NumPipes
* pps
->pps_BufferSize
);
1376 pps
->pps_Pipes
= psdAllocVec(pps
->pps_NumPipes
* sizeof(struct PsdPipe
*));
1377 if(pps
->pps_Pipes
&& pps
->pps_Buffer
)
1379 KPRINTF(1, ("allocating %ld new pipes\n", pps
->pps_NumPipes
));
1380 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
1382 pp
= psdAllocPipe(pps
->pps_Device
, pps
->pps_MsgPort
, pps
->pps_Endpoint
);
1383 if((pps
->pps_Pipes
[cnt
] = pp
))
1386 if(pps
->pps_Flags
& PSFF_NOSHORTPKT
) pp
->pp_IOReq
.iouh_Flags
|= UHFF_NOSHORTPKT
;
1387 if(pps
->pps_Flags
& PSFF_NAKTIMEOUT
) pp
->pp_IOReq
.iouh_Flags
|= UHFF_NAKTIMEOUT
;
1388 if(pps
->pps_Flags
& PSFF_ALLOWRUNT
) pp
->pp_IOReq
.iouh_Flags
|= UHFF_ALLOWRUNTPKTS
;
1389 pp
->pp_IOReq
.iouh_NakTimeout
= pps
->pps_NakTimeoutTime
;
1390 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
1392 KPRINTF(1, ("Allocating Pipe %ld failed!\n", cnt
));
1396 KPRINTF(1, ("Allocating Pipe array failed!\n"));
1397 psdFreeVec(pps
->pps_Buffer
);
1398 pps
->pps_Buffer
= NULL
;
1399 psdFreeVec(pps
->pps_Pipes
);
1400 pps
->pps_Pipes
= NULL
;
1403 ReleaseSemaphore(&pps
->pps_AccessLock
);
1404 return((LONG
) count
);
1410 res
= (LONG
) PackStructureTags(psdstruct
, packtab
, tags
);
1416 struct PsdDevice
*pd
= (struct PsdDevice
*) psdstruct
;
1417 struct PsdIFFContext
*pic
;
1419 pic
= psdGetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
);
1422 psdSetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
, NULL
);
1423 pic
= psdGetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
);
1427 pAddCfgChunk(ps
, pic
, &pd
->pd_PoPoCfg
);
1428 checkcfgupdate
= TRUE
;
1433 pUpdateGlobalCfg(ps
, (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
);
1434 pCheckCfgChanged(ps
);
1438 psdCalculatePower(((struct PsdDevice
*) psdstruct
)->pd_Hardware
);
1445 /* /// "psdSpawnSubTask()" */
1446 AROS_LH3(struct Task
*, psdSpawnSubTask
,
1447 AROS_LHA(STRPTR
, name
, A0
),
1448 AROS_LHA(APTR
, initpc
, A1
),
1449 AROS_LHA(APTR
, userdata
, A2
),
1450 LIBBASETYPEPTR
, ps
, 39, psd
)
1453 #define SUBTASKSTACKSIZE 8192
1456 struct MemList mrm_ml
;
1457 struct MemEntry mtm_me
[2];
1460 struct MemList
*newmemlist
;
1461 struct MemEntry
*me
;
1463 struct Process
*subtask
;
1465 if(!(name
&& initpc
))
1470 /* If there's dos available, create a process instead of a task */
1473 subtask
= CreateNewProcTags(NP_Entry
, initpc
,
1474 NP_StackSize
, SUBTASKSTACKSIZE
,
1475 NP_Priority
, ps
->ps_GlobalCfg
->pgc_SubTaskPri
,
1478 NP_UserData
, userdata
,
1480 return((struct Task
*) subtask
);
1483 /* Allocate memory of memlist */
1485 memlist
.mrm_ml
.ml_Node
.ln_Type
= NT_MEMORY
;
1486 memlist
.mrm_ml
.ml_Node
.ln_Pri
= 0;
1487 memlist
.mrm_ml
.ml_Node
.ln_Name
= NULL
;
1488 memlist
.mrm_ml
.ml_NumEntries
= 3;
1489 me
= &memlist
.mrm_ml
.ml_ME
[0];
1490 me
[1].me_Un
.meu_Reqs
= memlist
.mrm_ml
.ml_ME
[0].me_Un
.meu_Reqs
= MEMF_CLEAR
|MEMF_PUBLIC
;
1491 me
[0].me_Length
= sizeof(struct Task
);
1492 me
[1].me_Length
= SUBTASKSTACKSIZE
;
1493 me
[2].me_Un
.meu_Reqs
= MEMF_PUBLIC
;
1494 me
[2].me_Length
= strlen(name
) + 1;
1497 newmemlist
= NewAllocEntry(&memlist
.mrm_ml
, NULL
);
1500 newmemlist
= AllocEntry(&memlist
.mrm_ml
);
1501 if((IPTR
) newmemlist
& 0x80000000)
1506 me
= &newmemlist
->ml_ME
[0];
1507 nt
= me
[0].me_Un
.meu_Addr
;
1508 nt
->tc_Node
.ln_Name
= me
[2].me_Un
.meu_Addr
;
1509 strcpy(nt
->tc_Node
.ln_Name
, name
);
1510 nt
->tc_Node
.ln_Type
= NT_TASK
;
1511 nt
->tc_Node
.ln_Pri
= ps
->ps_GlobalCfg
->pgc_SubTaskPri
;
1512 nt
->tc_SPLower
= me
[1].me_Un
.meu_Addr
;
1513 nt
->tc_SPUpper
= nt
->tc_SPReg
= (APTR
) ((IPTR
) nt
->tc_SPLower
+ SUBTASKSTACKSIZE
);
1514 nt
->tc_UserData
= userdata
;
1515 NewList(&nt
->tc_MemEntry
);
1516 AddTail(&nt
->tc_MemEntry
, (struct Node
*) newmemlist
);
1517 KPRINTF(1, ("TDNestCnt=%ld\n", SysBase
->TDNestCnt
));
1518 if((nt
= AddTask(nt
, initpc
, NULL
)))
1520 XPRINTF(10, ("Started task %p (%s)\n", nt
, name
));
1523 FreeEntry(newmemlist
);
1529 /* /// "psdNumToStr()" */
1530 AROS_LH3(STRPTR
, psdNumToStr
,
1531 AROS_LHA(UWORD
, type
, D0
),
1532 AROS_LHA(LONG
, idx
, D1
),
1533 AROS_LHA(STRPTR
, defstr
, A0
),
1534 LIBBASETYPEPTR
, ps
, 38, psd
)
1541 const struct PsdWStringMap
*psm
= usbhwioerrstr
;
1544 if(psm
->psm_ID
== idx
)
1546 return(psm
->psm_String
);
1555 const struct PsdUWStringMap
*psm
= usblangids
;
1558 if(psm
->psm_ID
== idx
)
1560 return(psm
->psm_String
);
1572 case USEAF_ISOCHRONOUS
:
1573 return("isochronous");
1576 case USEAF_INTERRUPT
:
1577 return("interrupt");
1585 return("no synchronization");
1587 return("asynchronous");
1588 case USEAF_ADAPTIVE
:
1591 return("synchronous");
1600 case USEAF_FEEDBACK
:
1602 case USEAF_IMPLFEEDBACK
:
1603 return("implicit feedback data");
1609 const struct PsdUWStringMap
*psm
= usbvendorids
;
1612 if(psm
->psm_ID
== idx
)
1614 return(psm
->psm_String
);
1623 const struct PsdWStringMap
*psm
= usbclasscodestr
;
1626 if(psm
->psm_ID
== idx
)
1628 return(psm
->psm_String
);
1635 case NTS_DESCRIPTOR
:
1637 const struct PsdULStringMap
*psm
= usbdesctypestr
;
1640 if(psm
->psm_ID
== idx
)
1642 return(psm
->psm_String
);
1649 case NTS_COMBOCLASS
:
1651 const struct PsdULStringMap
*psm
= usbcomboclasscodestr
;
1652 if(idx
& (NTSCCF_CLASS
|NTSCCF_SUBCLASS
|NTSCCF_PROTO
))
1658 if(psm
->psm_ID
& NTSCCF_CLASS
)
1660 if((!(idx
& NTSCCF_CLASS
)) || ((idx
& 0x0000ff) != (psm
->psm_ID
& 0x0000ff)))
1665 if(psm
->psm_ID
& NTSCCF_SUBCLASS
)
1667 if((!(idx
& NTSCCF_SUBCLASS
)) || ((idx
& 0x00ff00) != (psm
->psm_ID
& 0x00ff00)))
1672 if(psm
->psm_ID
& NTSCCF_PROTO
)
1674 if((!(idx
& NTSCCF_PROTO
)) || ((idx
& 0xff0000) != (psm
->psm_ID
& 0xff0000)))
1681 return(psm
->psm_String
);
1694 /* *** Endpoint *** */
1696 /* /// "pFreeEndpoint()" */
1697 void pFreeEndpoint(struct PsdEndpoint
*pep
)
1699 LIBBASETYPEPTR ps
= pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Base
;
1700 KPRINTF(2, (" FreeEndpoint()\n"));
1701 Remove(&pep
->pep_Node
);
1706 /* /// "pAllocEndpoint()" */
1707 struct PsdEndpoint
* pAllocEndpoint(struct PsdInterface
*pif
)
1709 LIBBASETYPEPTR ps
= pif
->pif_Config
->pc_Device
->pd_Hardware
->phw_Base
;
1710 struct PsdEndpoint
*pep
;
1711 if((pep
= psdAllocVec(sizeof(struct PsdEndpoint
))))
1713 pep
->pep_Interface
= pif
;
1714 AddTail(&pif
->pif_EPs
, &pep
->pep_Node
);
1721 /* /// "psdFindEndpointA()" */
1722 AROS_LH3(struct PsdEndpoint
*, psdFindEndpointA
,
1723 AROS_LHA(struct PsdInterface
*, pif
, A0
),
1724 AROS_LHA(struct PsdEndpoint
*, pep
, A2
),
1725 AROS_LHA(struct TagItem
*, tags
, A1
),
1726 LIBBASETYPEPTR
, ps
, 67, psd
)
1732 KPRINTF(2, ("psdFindEndpointA(%p, %p, %p)\n", pif
, pep
, tags
));
1735 pep
= (struct PsdEndpoint
*) pif
->pif_EPs
.lh_Head
;
1737 pep
= (struct PsdEndpoint
*) pep
->pep_Node
.ln_Succ
;
1739 while(pep
->pep_Node
.ln_Succ
)
1742 if((ti
= FindTagItem(EA_IsIn
, tags
)))
1744 if((ti
->ti_Data
&& !pep
->pep_Direction
) || (!ti
->ti_Data
&& pep
->pep_Direction
))
1749 if((ti
= FindTagItem(EA_EndpointNum
, tags
)))
1751 if(ti
->ti_Data
!= pep
->pep_EPNum
)
1756 if((ti
= FindTagItem(EA_TransferType
, tags
)))
1758 if(ti
->ti_Data
!= pep
->pep_TransType
)
1763 if((ti
= FindTagItem(EA_MaxPktSize
, tags
)))
1765 if(ti
->ti_Data
!= pep
->pep_MaxPktSize
)
1770 if((ti
= FindTagItem(EA_Interval
, tags
)))
1772 if(ti
->ti_Data
!= pep
->pep_Interval
)
1782 pep
= (struct PsdEndpoint
*) pep
->pep_Node
.ln_Succ
;
1789 /* *** Interface *** */
1791 /* /// "pFreeInterface()" */
1792 void pFreeInterface(struct PsdInterface
*pif
)
1794 LIBBASETYPEPTR ps
= pif
->pif_Config
->pc_Device
->pd_Hardware
->phw_Base
;
1795 struct PsdEndpoint
*pep
= (struct PsdEndpoint
*) pif
->pif_EPs
.lh_Head
;
1796 struct PsdInterface
*altif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
1797 KPRINTF(2, (" FreeInterface()\n"));
1798 /* Remove alternate interfaces */
1799 while(altif
->pif_Node
.ln_Succ
)
1801 pFreeInterface(altif
);
1802 altif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
1804 /* Remove endpoints */
1805 while(pep
->pep_Node
.ln_Succ
)
1808 pep
= (struct PsdEndpoint
*) pif
->pif_EPs
.lh_Head
;
1810 psdFreeVec(pif
->pif_IfStr
);
1811 psdFreeVec(pif
->pif_IDString
);
1812 Remove(&pif
->pif_Node
);
1817 /* /// "pAllocInterface()" */
1818 struct PsdInterface
* pAllocInterface(struct PsdConfig
*pc
)
1820 LIBBASETYPEPTR ps
= pc
->pc_Device
->pd_Hardware
->phw_Base
;
1821 struct PsdInterface
*pif
;
1822 if((pif
= psdAllocVec(sizeof(struct PsdInterface
))))
1824 pif
->pif_Config
= pc
;
1825 NewList(&pif
->pif_EPs
);
1826 NewList(&pif
->pif_AlterIfs
);
1827 AddTail(&pc
->pc_Interfaces
, &pif
->pif_Node
);
1834 /* /// "psdFindInterfaceA()" */
1835 AROS_LH3(struct PsdInterface
*, psdFindInterfaceA
,
1836 AROS_LHA(struct PsdDevice
*, pd
, A0
),
1837 AROS_LHA(struct PsdInterface
*, pif
, A2
),
1838 AROS_LHA(struct TagItem
*, tags
, A1
),
1839 LIBBASETYPEPTR
, ps
, 66, psd
)
1842 struct PsdConfig
*pc
;
1845 BOOL searchalt
= FALSE
;
1847 struct PsdInterface
*oldpif
= NULL
;
1849 KPRINTF(2, ("psdFindInterfaceA(%p, %p, %p)\n", pd
, pif
, tags
));
1852 pc
= pd
->pd_CurrentConfig
;
1855 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
1862 if(FindTagItem(IFA_AlternateNum
, tags
))
1866 if(pif
->pif_ParentIf
)
1868 // special case: we are in an alternate interface right now
1870 if(pif
->pif_Node
.ln_Succ
)
1873 oldpif
= pif
->pif_ParentIf
;
1874 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
1876 pif
= (struct PsdInterface
*) pif
->pif_ParentIf
->pif_Node
.ln_Succ
;
1879 // go into alt interfaces
1880 if(searchalt
&& pif
->pif_AlterIfs
.lh_Head
->ln_Succ
)
1884 pif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
1886 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
1891 while(pif
->pif_Node
.ln_Succ
)
1894 if((ti
= FindTagItem(IFA_InterfaceNum
, tags
)))
1896 if(ti
->ti_Data
!= pif
->pif_IfNum
)
1901 if((ti
= FindTagItem(IFA_AlternateNum
, tags
)))
1904 if(ti
->ti_Data
<= 0xff) // if alternate number is greater than 0xff, don't check compliance, but just enable alternate interface searching
1906 if(ti
->ti_Data
!= pif
->pif_Alternate
)
1912 if((ti
= FindTagItem(IFA_NumEndpoints
, tags
)))
1914 if(ti
->ti_Data
!= pif
->pif_NumEPs
)
1919 if((ti
= FindTagItem(IFA_Class
, tags
)))
1921 if(ti
->ti_Data
!= pif
->pif_IfClass
)
1926 if((ti
= FindTagItem(IFA_SubClass
, tags
)))
1928 if(ti
->ti_Data
!= pif
->pif_IfSubClass
)
1933 if((ti
= FindTagItem(IFA_Protocol
, tags
)))
1935 if(ti
->ti_Data
!= pif
->pif_IfProto
)
1940 if((ti
= FindTagItem(IFA_Binding
, tags
)))
1942 if((APTR
) ti
->ti_Data
!= pif
->pif_IfBinding
)
1947 if((ti
= FindTagItem(IFA_InterfaceName
, tags
)))
1949 if(strcmp((STRPTR
) ti
->ti_Data
, pif
->pif_IfStr
))
1954 if((ti
= FindTagItem(IFA_IDString
, tags
)))
1956 if(strcmp((STRPTR
) ti
->ti_Data
, pif
->pif_IDString
))
1970 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
1971 if(!pif
->pif_Node
.ln_Succ
)
1973 pif
= (struct PsdInterface
*) oldpif
->pif_Node
.ln_Succ
;
1978 pif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
1979 if(!pif
->pif_Node
.ln_Succ
)
1981 pif
= (struct PsdInterface
*) oldpif
->pif_Node
.ln_Succ
;
1987 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
1995 /* *** Config *** */
1997 /* /// "pFreeConfig()" */
1998 void pFreeConfig(struct PsdConfig
*pc
)
2000 LIBBASETYPEPTR ps
= pc
->pc_Device
->pd_Hardware
->phw_Base
;
2001 struct PsdInterface
*pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2002 KPRINTF(2, (" FreeConfig()\n"));
2003 while(pif
->pif_Node
.ln_Succ
)
2005 psdReleaseIfBinding(pif
);
2006 pFreeInterface(pif
);
2007 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2009 psdFreeVec(pc
->pc_CfgStr
);
2010 Remove(&pc
->pc_Node
);
2015 /* /// "pAllocConfig()" */
2016 struct PsdConfig
* pAllocConfig(struct PsdDevice
*pd
)
2018 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
2019 struct PsdConfig
*pc
;
2020 KPRINTF(2, (" AllocConfig()\n"));
2021 if((pc
= psdAllocVec(sizeof(struct PsdConfig
))))
2024 NewList(&pc
->pc_Interfaces
);
2025 AddTail(&pd
->pd_Configs
, &pc
->pc_Node
);
2032 /* *** Descriptors *** */
2034 /* /// "pFreeDescriptor()" */
2035 void pFreeDescriptor(struct PsdDescriptor
*pdd
)
2037 LIBBASETYPEPTR ps
= pdd
->pdd_Device
->pd_Hardware
->phw_Base
;
2038 KPRINTF(2, (" FreeDescriptor()\n"));
2039 //psdFreeVec(pdd->pdd_Data); // part of the structure alloc
2040 Remove(&pdd
->pdd_Node
);
2045 /* /// "pAllocDescriptor()" */
2046 struct PsdDescriptor
* pAllocDescriptor(struct PsdDevice
*pd
, UBYTE
*buf
)
2048 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
2049 struct PsdDescriptor
*pdd
;
2051 KPRINTF(2, (" AllocDescriptor()\n"));
2052 if((pdd
= psdAllocVec(sizeof(struct PsdDescriptor
) + (ULONG
) buf
[0])))
2054 pdd
->pdd_Device
= pd
;
2055 pdd
->pdd_Data
= ((UBYTE
*) pdd
) + sizeof(struct PsdDescriptor
);
2056 pdd
->pdd_Length
= buf
[0];
2057 pdd
->pdd_Type
= buf
[1];
2058 if((pdd
->pdd_Type
>= UDT_CS_UNDEFINED
) && (pdd
->pdd_Type
<= UDT_CS_ENDPOINT
))
2060 pdd
->pdd_CSSubType
= buf
[2];
2062 pdd
->pdd_Name
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) pdd
->pdd_Type
, "<unknown>");
2063 CopyMem(buf
, pdd
->pdd_Data
, (ULONG
) buf
[0]);
2064 AddTail(&pd
->pd_Descriptors
, &pdd
->pdd_Node
);
2071 /* /// "psdFindDescriptorA()" */
2072 AROS_LH3(struct PsdDescriptor
*, psdFindDescriptorA
,
2073 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2074 AROS_LHA(struct PsdDescriptor
*, pdd
, A2
),
2075 AROS_LHA(struct TagItem
*, tags
, A1
),
2076 LIBBASETYPEPTR
, ps
, 91, psd
)
2079 struct PsdConfig
*pc
= pd
->pd_CurrentConfig
;
2083 KPRINTF(2, ("psdFindDescriptorA(%p, %p, %p)\n", pd
, pdd
, tags
));
2086 pdd
= (struct PsdDescriptor
*) pd
->pd_Descriptors
.lh_Head
;
2088 pdd
= (struct PsdDescriptor
*) pdd
->pdd_Node
.ln_Succ
;
2091 while(pdd
->pdd_Node
.ln_Succ
)
2095 if((ti
= FindTagItem(DDA_Config
, tags
)))
2097 // special case to workaround default: with NULL given, all configs are matched
2098 if(ti
->ti_Data
&& (((struct PsdConfig
*) ti
->ti_Data
) != pdd
->pdd_Config
))
2103 // only take descriptors from the current configuration by default
2104 if(pc
!= pdd
->pdd_Config
)
2109 if((ti
= FindTagItem(DDA_Interface
, tags
)))
2111 if(((struct PsdInterface
*) ti
->ti_Data
) != pdd
->pdd_Interface
)
2116 if((ti
= FindTagItem(DDA_Endpoint
, tags
)))
2118 if(((struct PsdEndpoint
*) ti
->ti_Data
) != pdd
->pdd_Endpoint
)
2123 if((ti
= FindTagItem(DDA_DescriptorType
, tags
)))
2125 if(ti
->ti_Data
!= pdd
->pdd_Type
)
2130 if((ti
= FindTagItem(DDA_CS_SubType
, tags
)))
2132 if(ti
->ti_Data
!= pdd
->pdd_CSSubType
)
2137 if((ti
= FindTagItem(DDA_DescriptorLength
, tags
)))
2139 if(ti
->ti_Data
!= pdd
->pdd_Length
)
2149 pdd
= (struct PsdDescriptor
*) pdd
->pdd_Node
.ln_Succ
;
2156 /* *** Device *** */
2158 /* /// "pFreeBindings()" */
2159 void pFreeBindings(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
2161 struct PsdHardware
*phw
= pd
->pd_Hardware
;
2162 struct PsdConfig
*pc
;
2163 struct PsdInterface
*pif
;
2164 KPRINTF(3, (" FreeBindings(%p)\n", pd
));
2166 /* move device to list of dead devices first
2167 This caused a lot of trouble as it could
2168 happen that a device got into class scan
2169 right after the bindings had been released. */
2170 psdLockWritePBase();
2171 Remove(&pd
->pd_Node
);
2172 AddTail(&phw
->phw_DeadDevices
, &pd
->pd_Node
);
2175 /* If there are bindings, get rid of them. */
2176 psdLockWriteDevice(pd
);
2177 psdReleaseDevBinding(pd
);
2179 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2180 while(pc
->pc_Node
.ln_Succ
)
2182 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2183 while(pif
->pif_Node
.ln_Succ
)
2185 psdReleaseIfBinding(pif
);
2186 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
2188 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
2190 psdUnlockDevice(pd
);
2194 /* /// "pFreeDevice()" */
2195 void pFreeDevice(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
2197 struct PsdHardware
*phw
= pd
->pd_Hardware
;
2198 struct PsdConfig
*pc
;
2199 struct PsdDescriptor
*pdd
;
2201 psdCalculatePower(phw
);
2202 psdLockWriteDevice(pd
);
2205 KPRINTF(20, ("Couldn't free device, use cnt %ld\n", pd
->pd_UseCnt
));
2206 pd
->pd_Flags
&= ~PDFF_CONNECTED
;
2207 pd
->pd_Flags
|= PDFF_DELEXPUNGE
;
2208 psdUnlockDevice(pd
);
2210 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2211 while(pc
->pc_Node
.ln_Succ
)
2214 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2217 pdd
= (struct PsdDescriptor
*) pd
->pd_Descriptors
.lh_Head
;
2218 while(pdd
->pdd_Node
.ln_Succ
)
2220 pFreeDescriptor(pdd
);
2221 pdd
= (struct PsdDescriptor
*) pd
->pd_Descriptors
.lh_Head
;
2224 psdFreeVec(pd
->pd_LangIDArray
);
2225 pd
->pd_LangIDArray
= NULL
;
2226 psdFreeVec(pd
->pd_MnfctrStr
);
2227 pd
->pd_MnfctrStr
= NULL
;
2228 /*if(!ps->ps_PoPo.po_Task) // keep name at least
2230 psdFreeVec(pd->pd_ProductStr);
2231 pd->pd_ProductStr = NULL;
2233 psdFreeVec(pd
->pd_OldProductStr
);
2234 pd
->pd_OldProductStr
= NULL
;
2235 psdFreeVec(pd
->pd_SerNumStr
);
2236 pd
->pd_SerNumStr
= NULL
;
2237 psdFreeVec(pd
->pd_IDString
);
2238 pd
->pd_IDString
= NULL
;
2241 KPRINTF(5,("Released DevAddr %ld\n", pd
->pd_DevAddr
));
2242 phw
->phw_DevArray
[pd
->pd_DevAddr
] = NULL
;
2244 psdUnlockDevice(pd
);
2245 psdLockWritePBase();
2246 Remove(&pd
->pd_Node
);
2248 pDeleteSem(ps
, &pd
->pd_Lock
);
2249 /* cannot free this vector -- tasks might still call LockDevice */
2252 KPRINTF(3, ("FreeDevice done\n"));
2256 /* /// "psdFreeDevice()" */
2257 AROS_LH1(void, psdFreeDevice
,
2258 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2259 LIBBASETYPEPTR
, ps
, 16, psd
)
2262 struct PsdHardware
*phw
= pd
->pd_Hardware
;
2263 struct PsdConfig
*pc
;
2264 struct PsdInterface
*pif
;
2265 struct PsdRTIsoHandler
*prt
;
2266 struct PsdRTIsoHandler
*nextprt
;
2268 KPRINTF(3, (" FreeDevice(%p)\n", pd
));
2270 /* move device to list of dead devices first
2271 This caused a lot of trouble as it could
2272 happen that a device got into class scan
2273 right after the bindings had been released. */
2274 psdLockWritePBase();
2275 Remove(&pd
->pd_Node
);
2276 AddTail(&phw
->phw_DeadDevices
, &pd
->pd_Node
);
2277 pd
->pd_Flags
&= ~PDFF_DELEXPUNGE
;
2280 psdLockWriteDevice(pd
);
2282 /* Inform all ISO handlers about the device going offline */
2283 prt
= (struct PsdRTIsoHandler
*) pd
->pd_RTIsoHandlers
.lh_Head
;
2284 while((nextprt
= (struct PsdRTIsoHandler
*) prt
->prt_Node
.ln_Succ
))
2286 if(prt
->prt_ReleaseHook
)
2288 CallHookPkt(prt
->prt_ReleaseHook
, prt
, NULL
);
2293 /* If there are bindings, get rid of them. */
2294 psdHubReleaseDevBinding(pd
);
2296 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2297 while(pc
->pc_Node
.ln_Succ
)
2299 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2300 while(pif
->pif_Node
.ln_Succ
)
2302 psdHubReleaseIfBinding(pif
);
2303 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
2305 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
2307 psdUnlockDevice(pd
);
2309 pFreeDevice(ps
, pd
);
2314 /* /// "psdAllocDevice()" */
2315 AROS_LH1(struct PsdDevice
*, psdAllocDevice
,
2316 AROS_LHA(struct PsdHardware
*, phw
, A0
),
2317 LIBBASETYPEPTR
, ps
, 15, psd
)
2320 struct PsdDevice
*pd
;
2321 KPRINTF(2, ("psdAllocDevice(%p)\n", phw
));
2322 if((pd
= psdAllocVec(sizeof(struct PsdDevice
))))
2324 pd
->pd_Hardware
= phw
;
2326 pd
->pd_MaxPktSize0
= 8;
2328 pInitSem(ps
, &pd
->pd_Lock
, "Device");
2330 NewList(&pd
->pd_Configs
);
2331 NewList(&pd
->pd_Descriptors
);
2332 NewList(&pd
->pd_RTIsoHandlers
);
2335 pd
->pd_PoPoCfg
.poc_ChunkID
= AROS_LONG2BE(IFFCHNK_POPUP
);
2336 pd
->pd_PoPoCfg
.poc_Length
= AROS_LONG2BE(sizeof(struct PsdPoPoCfg
) - 8);
2337 pd
->pd_PoPoCfg
.poc_InhibitPopup
= FALSE
;
2338 pd
->pd_PoPoCfg
.poc_NoClassBind
= FALSE
;
2339 pd
->pd_PoPoCfg
.poc_OverridePowerInfo
= POCP_TRUST_DEVICE
;
2341 psdLockWritePBase();
2342 AddTail(&phw
->phw_Devices
, &pd
->pd_Node
);
2346 KPRINTF(20, ("psdAllocDevice(): out of memory!\n"));
2353 /* /// "psdLockReadDevice()" */
2354 AROS_LH1(void, psdLockReadDevice
,
2355 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2356 LIBBASETYPEPTR
, ps
, 17, psd
)
2359 KPRINTF(2, ("psdLockReadDevice(%p, %p)\n", pd
, FindTask(NULL
)));
2360 pLockSemShared(ps
, &pd
->pd_Lock
);
2365 /* /// "psdLockWriteDevice()" */
2366 AROS_LH1(void, psdLockWriteDevice
,
2367 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2368 LIBBASETYPEPTR
, ps
, 18, psd
)
2371 KPRINTF(2, ("psdLockWriteDevice(%p, %p)\n", pd
, FindTask(NULL
)));
2372 pLockSemExcl(ps
, &pd
->pd_Lock
);
2377 /* /// "psdUnlockDevice()" */
2378 AROS_LH1(void, psdUnlockDevice
,
2379 AROS_LHA(struct PsdDevice
*, pd
, A0
),
2380 LIBBASETYPEPTR
, ps
, 19, psd
)
2383 KPRINTF(2, ("psdUnlockDevice(%p, %p)\n", pd
, FindTask(NULL
)));
2384 pUnlockSem(ps
, &pd
->pd_Lock
);
2389 /* /// "pAllocDevAddr()" */
2390 UWORD
pAllocDevAddr(struct PsdDevice
*pd
)
2392 struct PsdHardware
*phw
= pd
->pd_Hardware
;
2396 return(pd
->pd_DevAddr
);
2398 for(da
= 1; da
< 128; da
++)
2400 if(!phw
->phw_DevArray
[da
])
2402 phw
->phw_DevArray
[da
] = pd
;
2403 pd
->pd_DevAddr
= da
;
2411 /* /// "psdGetStringDescriptor()" */
2412 AROS_LH2(STRPTR
, psdGetStringDescriptor
,
2413 AROS_LHA(struct PsdPipe
*, pp
, A1
),
2414 AROS_LHA(UWORD
, idx
, D0
),
2415 LIBBASETYPEPTR
, ps
, 33, psd
)
2418 struct PsdDevice
*pd
= pp
->pp_Device
;
2427 KPRINTF(1, ("psdGetStringDescriptor(%p, %ld)\n", pp
, idx
));
2430 if(!pd
->pd_LangIDArray
)
2432 KPRINTF(10,("Trying to get language array...\n"));
2433 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
2434 USR_GET_DESCRIPTOR
, UDT_STRING
<<8, 0);
2435 ioerr
= psdDoPipe(pp
, buf
, 2);
2436 if(ioerr
== UHIOERR_OVERFLOW
)
2439 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Language array overflow.");
2443 ioerr
= psdDoPipe(pp
, buf
, 256);
2444 if(ioerr
== UHIOERR_RUNTPACKET
)
2452 if((pd
->pd_LangIDArray
= psdAllocVec(max(len
, 4))))
2454 tmpbuf
= tmpptr
= pd
->pd_LangIDArray
;
2455 KPRINTF(1, ("Getting LangID Array length %ld\n", len
));
2456 // generate minimal sized array
2461 *tmpbuf
= AROS_WORD2LE(0x0409);
2462 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2463 "Language array descriptor too small (len %ld), using dummy.",
2467 ioerr
= psdDoPipe(pp
, tmpbuf
++, len
);
2474 KPRINTF(1, ("LangID: %04lx\n", AROS_WORD2LE(*tmpbuf
)));
2475 *tmpptr
++ = AROS_WORD2LE(*tmpbuf
);
2479 tmpptr
= pd
->pd_LangIDArray
;
2480 pd
->pd_CurrLangID
= *tmpptr
;
2483 if(*tmpptr
== 0x0409)
2485 pd
->pd_CurrLangID
= *tmpptr
;
2491 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2492 "Reading language array descriptor (len %ld) failed: %s (%ld)",
2493 len
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2494 KPRINTF(15, ("Error reading lang array descriptor (%ld) failed %ld\n", len
, ioerr
));
2498 KPRINTF(20, ("No langid array memory!\n"));
2501 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2502 "Reading language array descriptor (len %ld) failed: %s (%ld)",
2503 2, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2504 KPRINTF(15, ("Error reading lang array descriptor (2) failed %ld\n", ioerr
));
2505 /* Create empty array */
2506 if((pd
->pd_LangIDArray
= psdAllocVec(2)))
2508 *pd
->pd_LangIDArray
= 0;
2513 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
2514 USR_GET_DESCRIPTOR
, (UDT_STRING
<<8)|idx
, pd
->pd_CurrLangID
);
2515 ioerr
= psdDoPipe(pp
, buf
, 2);
2516 if(ioerr
== UHIOERR_OVERFLOW
)
2519 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "String %ld overflow.", idx
);
2523 ioerr
= psdDoPipe(pp
, buf
, 256);
2530 tmpptr
= (UWORD
*) buf
;
2531 KPRINTF(1, ("Getting String Descriptor %ld, length %ld\n", idx
, len
));
2532 ioerr
= psdDoPipe(pp
, tmpptr
++, len
);
2533 if(ioerr
== UHIOERR_RUNTPACKET
)
2535 len
= pp
->pp_IOReq
.iouh_Actual
;
2538 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2539 "String descriptor %ld truncated to %ld, requested %ld",
2546 ioerr
= psdDoPipe(pp
, buf
, 256);
2550 if((cbuf
= rs
= psdAllocVec(len
>>1)))
2555 widechar
= *tmpptr
++;
2556 widechar
= AROS_LE2WORD(widechar
);
2561 if((widechar
< 0x20) || (widechar
> 255))
2569 KPRINTF(1, ("String \"%s\"\n", rs
));
2578 KPRINTF(20, ("No memory for string!\n"));
2581 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2582 "Reading string descriptor %ld (len %ld) failed: %s (%ld)",
2583 idx
, len
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2584 KPRINTF(15, ("Error reading string descriptor %ld (%ld) failed %ld\n",
2588 KPRINTF(5, ("Empty string\n"));
2589 return(psdCopyStr(""));
2592 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2593 "Reading string descriptor %ld (len %ld) failed: %s (%ld)",
2594 idx
, 2, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2595 KPRINTF(15, ("Error reading string descriptor %ld (2) failed %ld\n", idx
, ioerr
));
2602 /* /// "psdSetDeviceConfig()" */
2603 AROS_LH2(BOOL
, psdSetDeviceConfig
,
2604 AROS_LHA(struct PsdPipe
*, pp
, A1
),
2605 AROS_LHA(UWORD
, cfgnum
, D0
),
2606 LIBBASETYPEPTR
, ps
, 34, psd
)
2609 struct PsdConfig
*pc
;
2610 struct PsdDevice
*pd
= pp
->pp_Device
;
2611 //UBYTE buf[8]; // VIA babble bug safety buffer (8 instead of 2)
2615 KPRINTF(2, ("Setting configuration to %ld...\n", cfgnum
));
2616 psdPipeSetup(pp
, URTF_STANDARD
|URTF_DEVICE
,
2617 USR_SET_CONFIGURATION
, cfgnum
, 0);
2618 ioerr
= psdDoPipe(pp
, NULL
, 0);
2621 #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
2622 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
2623 USR_GET_CONFIGURATION
, 0, 0);
2624 ioerr
= psdDoPipe(pp
, buf
, 1);
2627 pd
->pd_CurrCfg
= buf
[0];
2628 if(cfgnum
!= buf
[0])
2630 pd
->pd_CurrCfg
= cfgnum
;
2631 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2632 "Broken: SetConfig/GetConfig mismatch (%ld != %ld) for %s!",
2633 cfgnum
, buf
[0], pp
->pp_Device
->pd_ProductStr
);
2637 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2638 "GET_CONFIGURATION failed: %s (%ld)",
2639 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2640 pd
->pd_CurrCfg
= cfgnum
;
2641 KPRINTF(15, ("GET_CONFIGURATION failed %ld!\n", ioerr
));
2644 pd
->pd_CurrCfg
= cfgnum
;
2648 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2649 "SET_CONFIGURATION failed: %s (%ld)",
2650 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2651 KPRINTF(15, ("SET_CONFIGURATION failed %ld!\n", ioerr
));
2653 // update direct link
2655 pd
->pd_CurrentConfig
= NULL
;
2656 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
2657 while(pc
->pc_Node
.ln_Succ
)
2659 if(pc
->pc_CfgNum
== pd
->pd_CurrCfg
)
2661 pd
->pd_CurrentConfig
= pc
;
2664 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
2667 if(!pd
->pd_CurrentConfig
)
2669 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "No current configuration, huh?");
2672 // power saving stuff
2673 if(ps
->ps_GlobalCfg
->pgc_PowerSaving
&& (pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
))
2675 psdPipeSetup(pp
, URTF_STANDARD
|URTF_DEVICE
,
2676 USR_SET_FEATURE
, UFS_DEVICE_REMOTE_WAKEUP
, 0);
2677 ioerr
= psdDoPipe(pp
, NULL
, 0);
2680 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2681 "SET_DEVICE_REMOTE_WAKEUP failed: %s (%ld)",
2682 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2683 KPRINTF(15, ("SET_DEVICE_REMOTE_WAKEUP failed %ld!\n", ioerr
));
2685 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_STATUS
, 0, 0);
2686 ioerr
= psdDoPipe(pp
, &status
, 2);
2689 if(status
& U_GSF_REMOTE_WAKEUP
)
2691 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2692 "Enabled remote wakeup feature for '%s'.",
2695 pd
->pd_CurrentConfig
->pc_Attr
&= ~USCAF_REMOTE_WAKEUP
;
2696 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2697 "Remote wakeup feature for '%s' could not be enabled.",
2701 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2702 "GET_STATUS failed: %s (%ld)",
2703 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);*/
2704 KPRINTF(15, ("GET_STATUS failed %ld!\n", ioerr
));
2707 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_STATUS
, 0, 0);
2708 ioerr
= psdDoPipe(pp
, &status
, 2);
2712 if((status
& U_GSF_SELF_POWERED
) && (!(pd
->pd_CurrentConfig
->pc_Attr
& USCAF_SELF_POWERED
)))
2714 pd
->pd_CurrentConfig
->pc_Attr
|= USCAF_SELF_POWERED
;
2715 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2716 "Device '%s' says it is currently self-powered. Fixing config.",
2719 else if((!(status
& U_GSF_SELF_POWERED
)) && (pd
->pd_CurrentConfig
->pc_Attr
& USCAF_SELF_POWERED
))
2721 pd
->pd_CurrentConfig
->pc_Attr
&= ~USCAF_SELF_POWERED
;
2722 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2723 "Device '%s' says it is currently bus-powered. Fixing config.",
2727 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2728 "GET_STATUS failed: %s (%ld)",
2729 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);*/
2730 KPRINTF(15, ("GET_STATUS failed %ld!\n", ioerr
));
2739 /* /// "psdSetAltInterface()" */
2740 AROS_LH2(BOOL
, psdSetAltInterface
,
2741 AROS_LHA(struct PsdPipe
*, pp
, A1
),
2742 AROS_LHA(struct PsdInterface
*, pif
, A0
),
2743 LIBBASETYPEPTR
, ps
, 43, psd
)
2746 struct PsdConfig
*pc
= pif
->pif_Config
;
2747 struct PsdInterface
*curif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
2748 struct PsdInterface
*tmpif
;
2749 struct PsdDevice
*pd
= pc
->pc_Device
;
2750 UBYTE buf
[8]; // VIA babble bug safety buffer (8 instead of 2)
2752 UWORD ifnum
= pif
->pif_IfNum
;
2753 UWORD altnum
= pif
->pif_Alternate
;
2755 KPRINTF(2, ("Setting interface %ld to alt %ld...\n", ifnum
, altnum
));
2756 psdLockWriteDevice(pd
);
2758 /* Find root config structure */
2759 while(curif
->pif_Node
.ln_Succ
)
2761 if(curif
->pif_IfNum
== ifnum
)
2765 curif
= (struct PsdInterface
*) curif
->pif_Node
.ln_Succ
;
2767 if(!curif
->pif_Node
.ln_Succ
)
2769 KPRINTF(20, ("Where did you get that fucking interface from?!?"));
2770 psdUnlockDevice(pd
);
2773 if(curif
== pif
) /* Is already the current alternate setting */
2775 psdUnlockDevice(pd
);
2778 KPRINTF(1, ("really setting interface...\n"));
2781 psdPipeSetup(pp
, URTF_STANDARD
|URTF_INTERFACE
,
2782 USR_SET_INTERFACE
, altnum
, ifnum
);
2783 ioerr
= psdDoPipe(pp
, NULL
, 0);
2787 if((!ioerr
) || (ioerr
== UHIOERR_STALL
))
2791 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_INTERFACE
,
2792 USR_GET_INTERFACE
, 0, ifnum
);
2793 ioerr
= psdDoPipe(pp
, buf
, 1);
2799 if(altnum
== buf
[0])
2801 KPRINTF(1, ("resorting list..."));
2802 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2803 "Changed to alt %ld",
2806 /* Remove pif from alt list */
2807 Remove(&pif
->pif_Node
);
2808 pif
->pif_ParentIf
= NULL
;
2809 /* Now move bindings */
2810 pif
->pif_ClsBinding
= curif
->pif_ClsBinding
;
2811 pif
->pif_IfBinding
= curif
->pif_IfBinding
;
2812 curif
->pif_IfBinding
= NULL
;
2813 curif
->pif_ClsBinding
= NULL
;
2814 /* Insert it after root interface */
2815 Insert(&pc
->pc_Interfaces
, (struct Node
*) &pif
->pif_Node
, (struct Node
*) &curif
->pif_Node
);
2816 /* Unlink root interface */
2817 Remove(&curif
->pif_Node
);
2818 /* Now move all remaining alt interfaces to the new root interface */
2819 tmpif
= (struct PsdInterface
*) curif
->pif_AlterIfs
.lh_Head
;
2820 while(tmpif
->pif_Node
.ln_Succ
)
2822 Remove(&tmpif
->pif_Node
);
2823 AddTail(&pif
->pif_AlterIfs
, &tmpif
->pif_Node
);
2824 tmpif
->pif_ParentIf
= pif
;
2825 tmpif
= (struct PsdInterface
*) curif
->pif_AlterIfs
.lh_Head
;
2827 /* Add old root to the end of the alt list */
2828 AddTail(&pif
->pif_AlterIfs
, &curif
->pif_Node
);
2829 curif
->pif_ParentIf
= pif
;
2831 psdUnlockDevice(pd
);
2834 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2835 "Attempt to change interface %ld to alt %ld remained at alt %ld.",
2836 ifnum
, altnum
, buf
[0]);
2839 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2840 "GET_INTERFACE(%ld) failed: %s (%ld)",
2841 ifnum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2842 KPRINTF(15, ("GET_INTERFACE failed %ld!\n", ioerr
));
2845 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2846 "SET_INTERFACE(%ld)=%ld failed: %s (%ld)",
2848 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2849 KPRINTF(15, ("SET_INTERFACE failed %ld!\n", ioerr
));
2851 psdUnlockDevice(pd
);
2857 /* /// "psdEnumerateDevice()" */
2858 AROS_LH1(struct PsdDevice
*, psdEnumerateDevice
,
2859 AROS_LHA(struct PsdPipe
*, pp
, A1
),
2860 LIBBASETYPEPTR
, ps
, 20, psd
)
2864 struct PsdDevice
*pd
= pp
->pp_Device
;
2865 struct PsdDevice
*itpd
= pp
->pp_Device
;
2866 struct PsdConfig
*pc
;
2867 struct PsdInterface
*pif
;
2868 struct UsbStdDevDesc usdd
;
2871 ULONG oldnaktimeout
;
2883 BOOL haspopupinhibit
;
2887 struct PsdIFFContext
*pic
;
2891 #ifdef AROS_USB30_CODE
2892 struct UsbStdBOSDesc usbosd
;
2896 KPRINTF(2, ("psdEnumerateDevice(%p)\n", pp
));
2898 psdLockWriteDevice(pd
);
2899 if(pAllocDevAddr(pd
)) {
2901 oldflags
= pp
->pp_IOReq
.iouh_Flags
;
2902 oldnaktimeout
= pp
->pp_IOReq
.iouh_NakTimeout
;
2903 pp
->pp_IOReq
.iouh_Flags
|= UHFF_NAKTIMEOUT
;
2904 pp
->pp_IOReq
.iouh_NakTimeout
= 1000;
2905 pp
->pp_IOReq
.iouh_DevAddr
= 0;
2908 64 bytes is the maximum packet size for control transfers in fullspeed and highspeed devices
2910 psdGetAttrs(PGA_DEVICE
, pd
, DA_IsLowspeed
, &islowspeed
, TAG_END
);
2913 pp
->pp_IOReq
.iouh_MaxPktSize
= 8;
2915 pp
->pp_IOReq
.iouh_MaxPktSize
= 64;
2918 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_DESCRIPTOR
, UDT_DEVICE
<<8, 0);
2919 ioerr
= psdDoPipe(pp
, &usdd
, 8);
2920 if(ioerr
&& (ioerr
!= UHIOERR_RUNTPACKET
)) {
2921 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "GET_DESCRIPTOR (8) failed: %s (%ld)", psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2922 KPRINTF(15, ("GET_DESCRIPTOR (8) failed %ld!\n", ioerr
));
2925 KPRINTF(1, ("Setting DevAddr %ld...\n", pd
->pd_DevAddr
));
2926 psdPipeSetup(pp
, URTF_STANDARD
|URTF_DEVICE
, USR_SET_ADDRESS
, pd
->pd_DevAddr
, 0);
2927 ioerr
= psdDoPipe(pp
, NULL
, 0);
2929 This is tricky: Maybe the device has accepted the command,
2930 but failed to send an ACK. Now, every resend trial will
2931 go to the wrong address!
2933 if((ioerr
== UHIOERR_TIMEOUT
) || (ioerr
== UHIOERR_STALL
)) {
2934 KPRINTF(1, ("First attempt failed, retrying new address\n"));
2935 /*pp->pp_IOReq.iouh_DevAddr = pd->pd_DevAddr;*/
2937 ioerr
= psdDoPipe(pp
, NULL
, 0);
2938 /*pp->pp_IOReq.iouh_DevAddr = 0;*/
2942 pd
->pd_Flags
|= PDFF_HASDEVADDR
|PDFF_CONNECTED
;
2943 pp
->pp_IOReq
.iouh_DevAddr
= pd
->pd_DevAddr
;
2945 psdDelayMS(50); /* Allowed time to settle */
2948 We have already received atleast the first 8 bytes from the descriptor, asking again may confuse some devices
2949 This is somewhat similar to how Windows enumerates USB devices
2951 KPRINTF(1, ("Getting MaxPktSize0...\n"));
2952 switch(usdd
.bMaxPacketSize0
)
2958 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
= usdd
.bMaxPacketSize0
;
2960 #ifdef AROS_USB30_CODE
2962 if((AROS_LE2WORD(usdd
.bcdUSB
) >= 0x0300)) {
2963 /* 9 is the only valid value for superspeed mode and it is the exponent of 2 =512 bytes */
2964 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
= (1<<9);
2969 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Illegal MaxPktSize0=%ld for endpoint 0", (ULONG
) usdd
.bMaxPacketSize0
);
2970 KPRINTF(2, ("Illegal MaxPktSize0=%ld!\n", usdd
.bMaxPacketSize0
));
2971 //pp->pp_IOReq.iouh_MaxPktSize = pd->pd_MaxPktSize0 = 8;
2972 ioerr
= UHIOERR_CRCERROR
;
2976 KPRINTF(1, (" MaxPktSize0 = %ld\n", pd
->pd_MaxPktSize0
));
2978 KPRINTF(1, ("Getting full descriptor...\n"));
2980 We have set a new address for the device so we need to setup the pipe again
2982 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_DESCRIPTOR
, UDT_DEVICE
<<8, 0);
2983 ioerr
= psdDoPipe(pp
, &usdd
, sizeof(struct UsbStdDevDesc
));
2986 pAllocDescriptor(pd
, (UBYTE
*) &usdd
);
2987 pd
->pd_Flags
|= PDFF_HASDEVDESC
;
2988 pd
->pd_USBVers
= AROS_WORD2LE(usdd
.bcdUSB
);
2989 pd
->pd_DevClass
= usdd
.bDeviceClass
;
2990 pd
->pd_DevSubClass
= usdd
.bDeviceSubClass
;
2991 pd
->pd_DevProto
= usdd
.bDeviceProtocol
;
2992 pd
->pd_VendorID
= AROS_WORD2LE(usdd
.idVendor
);
2993 pd
->pd_ProductID
= AROS_WORD2LE(usdd
.idProduct
);
2994 pd
->pd_DevVers
= AROS_WORD2LE(usdd
.bcdDevice
);
2995 vendorname
= psdNumToStr(NTS_VENDORID
, (LONG
) pd
->pd_VendorID
, NULL
);
2997 // patch to early determine highspeed roothubs
2998 if((!pd
->pd_Hub
) && (pd
->pd_USBVers
>= 0x200) && (pd
->pd_USBVers
< 0x300)) {
2999 pd
->pd_Flags
|= PDFF_HIGHSPEED
;
3002 #ifdef AROS_USB30_CODE
3003 if(((!pd
->pd_Hub
) && pd
->pd_USBVers
>= 0x300)) {
3004 pd
->pd_Flags
|= PDFF_SUPERSPEED
;
3008 The USB 3.0 and USB 2.0 LPM specifications define a new USB descriptor called the Binary Device Object Store (BOS)
3009 for a USB device, which reports a bcdUSB value greater than 0x0200 in their device descriptor
3011 if((pd
->pd_USBVers
> 0x200)) {
3012 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_DESCRIPTOR
, UDT_BOS
<<8, 0);
3013 ioerr_bos
= psdDoPipe(pp
, &usbosd
, sizeof(struct UsbStdBOSDesc
));
3015 XPRINTF(1, ("BOS descriptor received...\n"));
3018 BOS descriptor bLength = sizeof(struct UsbStdBOSDesc)
3019 BOS descriptor bNumDeviceCaps != 0
3020 BOS descriptor wTotalLength >= bLength + (bNumDeviceCaps * sizeof(protocol specific capability descriptor))
3022 if(usbosd
.bLength
!= sizeof(struct UsbStdBOSDesc
)) {
3023 XPRINTF(1, ("Invalid BOS descriptor bLength!\n"));
3026 if(usbosd
.bNumDeviceCaps
== 0) {
3027 XPRINTF(1, ("Invalid BOS descriptor bNumDeviceCaps!\n"));
3028 }else if(usbosd
.wTotalLength
< (usbosd
.bLength
+ (usbosd
.bNumDeviceCaps
* 2))) {
3029 XPRINTF(1, ("Invalid BOS descriptor wTotalLength!\n"));
3033 XPRINTF(1, ("GET_DESCRIPTOR (5) failed %ld!\n", ioerr_bos
));
3038 if(usdd
.iManufacturer
) {
3039 pd
->pd_MnfctrStr
= psdGetStringDescriptor(pp
, usdd
.iManufacturer
);
3043 pd
->pd_ProductStr
= psdGetStringDescriptor(pp
, usdd
.iProduct
);
3046 if(usdd
.iSerialNumber
) {
3047 pd
->pd_SerNumStr
= psdGetStringDescriptor(pp
, usdd
.iSerialNumber
);
3050 if(!pd
->pd_MnfctrStr
) {
3051 pd
->pd_MnfctrStr
= psdCopyStr(vendorname
? vendorname
: (STRPTR
) "n/a");
3054 if(!pd
->pd_ProductStr
) {
3055 hasprodname
= FALSE
;
3056 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) pd
->pd_DevClass
, NULL
);
3058 pd
->pd_ProductStr
= psdCopyStrFmt("%s: Vdr=%04lx/PID=%04lx", classname
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3060 pd
->pd_ProductStr
= psdCopyStrFmt("Cls=%ld/Vdr=%04lx/PID=%04lx", pd
->pd_DevClass
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3066 if(!pd
->pd_SerNumStr
) {
3067 pd
->pd_SerNumStr
= psdCopyStr("n/a");
3070 KPRINTF(2, ("Product : %s\n"
3071 "Manufacturer: %s\n"
3072 "SerialNumber: %s\n",
3073 pd
->pd_ProductStr
, pd
->pd_MnfctrStr
, pd
->pd_SerNumStr
));
3074 KPRINTF(2, ("USBVersion: %04lx\n"
3080 "DevVers : %04lx\n",
3081 pd
->pd_USBVers
, pd
->pd_DevClass
, pd
->pd_DevSubClass
, pd
->pd_DevProto
,
3082 pd
->pd_VendorID
, pd
->pd_ProductID
, pd
->pd_DevVers
));
3084 /* check for clones */
3086 while((itpd
= psdGetNextDevice(itpd
)))
3090 if((itpd
->pd_ProductID
== pd
->pd_ProductID
) &&
3091 (itpd
->pd_VendorID
== pd
->pd_VendorID
) &&
3092 (!strcmp(itpd
->pd_SerNumStr
, pd
->pd_SerNumStr
)) &&
3093 (itpd
->pd_CloneCount
== pd
->pd_CloneCount
))
3095 pd
->pd_CloneCount
++;
3101 pd
->pd_IDString
= psdCopyStrFmt("%s-%04lx-%04lx-%s-%02lx", pd
->pd_ProductStr
, pd
->pd_VendorID
, pd
->pd_ProductID
, pd
->pd_SerNumStr
, pd
->pd_CloneCount
);
3103 pStripString(ps
, pd
->pd_MnfctrStr
);
3104 pStripString(ps
, pd
->pd_ProductStr
);
3105 pStripString(ps
, pd
->pd_SerNumStr
);
3107 /* get custom name of device */
3108 pLockSemExcl(ps
, &ps
->ps_ConfigLock
); // Exclusive lock to avoid deadlock situation when promoting read to write
3109 pd
->pd_OldProductStr
= pd
->pd_ProductStr
;
3110 pd
->pd_ProductStr
= NULL
;
3111 haspopupinhibit
= FALSE
;
3112 pic
= psdGetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
);
3115 pd
->pd_IsNewToMe
= FALSE
;
3116 if((pd
->pd_ProductStr
= pGetStringChunk(ps
, pic
, IFFCHNK_NAME
)))
3120 if((chnk
= pFindCfgChunk(ps
, pic
, IFFCHNK_POPUP
)))
3122 struct PsdPoPoCfg
*poc
= (struct PsdPoPoCfg
*) chnk
;
3123 CopyMem(((UBYTE
*) poc
) + 8, ((UBYTE
*) &pd
->pd_PoPoCfg
) + 8, min(AROS_LONG2BE(poc
->poc_Length
), AROS_LONG2BE(pd
->pd_PoPoCfg
.poc_Length
)));
3124 haspopupinhibit
= TRUE
;
3127 pd
->pd_IsNewToMe
= TRUE
;
3128 psdSetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
, NULL
);
3130 if(!pd
->pd_ProductStr
)
3132 pd
->pd_ProductStr
= psdCopyStr(pd
->pd_OldProductStr
);
3134 if(!haspopupinhibit
)
3136 if(pd
->pd_DevClass
== HUB_CLASSCODE
) // hubs default to true
3138 pd
->pd_PoPoCfg
.poc_InhibitPopup
= TRUE
;
3141 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
3143 pd
->pd_NumCfgs
= usdd
.bNumConfigurations
;
3144 KPRINTF(10, ("Device has %ld different configurations\n", pd
->pd_NumCfgs
));
3146 if(pGetDevConfig(pp
))
3149 if(pd
->pd_Configs
.lh_Head
->ln_Succ
)
3151 cfgnum
= ((struct PsdConfig
*) pd
->pd_Configs
.lh_Head
)->pc_CfgNum
;
3153 psdSetDeviceConfig(pp
, cfgnum
); /* *** FIXME *** Workaround for USB2.0 devices */
3157 devclass
= pd
->pd_DevClass
;
3158 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
3159 while(pc
->pc_Node
.ln_Succ
)
3161 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3162 while(pif
->pif_Node
.ln_Succ
)
3164 if(pif
->pif_IfClass
)
3168 devclass
= pif
->pif_IfClass
;
3170 if(devclass
!= pif
->pif_IfClass
)
3177 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3179 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
3183 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) devclass
, NULL
);
3186 psdFreeVec(pd
->pd_ProductStr
);
3189 pd
->pd_ProductStr
= psdCopyStrFmt("%s (%s/%04lx)",
3190 classname
, vendorname
, pd
->pd_ProductID
);
3192 pd
->pd_ProductStr
= psdCopyStrFmt("%s (%04lx/%04lx)",
3193 classname
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3198 pFixBrokenConfig(pp
);
3199 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3200 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3201 psdUnlockDevice(pd
);
3202 psdCalculatePower(pd
->pd_Hardware
);
3205 KPRINTF(15, ("SetDeviceConfig(1) failed\n"));
3208 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3209 "Could not acquire device configuration for %s",
3210 pd
->pd_ProductStr
? pd
->pd_ProductStr
: (STRPTR
) "new device");
3211 KPRINTF(15, ("GetDevConfig() failed\n"));
3213 /* Although the device failed to configure fully, maybe
3214 some firmware will able to use this device anyway? */
3215 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3216 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3217 psdUnlockDevice(pd
);
3220 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3221 "GET_DESCRIPTOR (len 18) failed: %s (%ld)",
3222 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3223 KPRINTF(15, ("GET_DESCRIPTOR (18) failed %ld!\n", ioerr
));
3226 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
3227 "SET_ADDRESS failed: %s (%ld)",
3228 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3229 KPRINTF(15, ("SET_ADDRESS failed %ld!\n", ioerr
));
3231 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3232 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3234 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "This cannot happen! More than 127 devices on the bus???");
3235 KPRINTF(20, ("out of addresses???\n"));
3238 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Device enumeration failed, sorry.");
3239 psdUnlockDevice(pd
);
3245 /* /// "psdGetNextDevice()" */
3246 AROS_LH1(struct PsdDevice
*, psdGetNextDevice
,
3247 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3248 LIBBASETYPEPTR
, ps
, 21, psd
)
3251 struct PsdHardware
*phw
;
3253 KPRINTF(1, ("psdGetNextDevice(%p)\n", pd
));
3256 /* Is there another device node in the current hardware? */
3257 if(pd
->pd_Node
.ln_Succ
->ln_Succ
)
3259 return((struct PsdDevice
*) pd
->pd_Node
.ln_Succ
);
3261 /* No, then check if there's another hardware to scan */
3262 phw
= (struct PsdHardware
*) pd
->pd_Hardware
->phw_Node
.ln_Succ
;
3264 /* No context, start with first hardware */
3265 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
3267 while(phw
->phw_Node
.ln_Succ
)
3269 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3270 /* Is this an valid entry, or is the list empty? */
3271 if(pd
->pd_Node
.ln_Succ
)
3275 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
3277 /* End of list reached */
3283 /* /// "psdSuspendBindings()" */
3284 AROS_LH1(BOOL
, psdSuspendBindings
,
3285 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3286 LIBBASETYPEPTR
, ps
, 100, psd
)
3289 struct PsdUsbClass
*puc
;
3290 struct PsdConfig
*pc
;
3291 struct PsdInterface
*pif
;
3296 KPRINTF(5, ("psdSuspendBindings(%p)\n", pd
));
3299 if(ps
->ps_GlobalCfg
->pgc_ForceSuspend
&& (pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
))
3303 // ask existing bindings to go to suspend first -- if they don't support it, break off
3304 if(pd
->pd_DevBinding
)
3306 if(pd
->pd_Flags
& PDFF_APPBINDING
)
3310 // can't suspend application binding devices
3311 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3312 "Cannot suspend with application binding on '%s'.",
3316 psdReleaseDevBinding(pd
);
3318 if((puc
= pd
->pd_ClsBinding
))
3321 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
3324 res
= usbDoMethod(UCM_AttemptSuspendDevice
, pd
->pd_DevBinding
);
3327 // didn't want to suspend
3328 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3329 "Class '%s' failed to suspend device '%s'.",
3330 puc
->puc_Node
.ln_Name
, pd
->pd_ProductStr
);
3334 if(pd
->pd_IOBusyCount
)
3338 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3339 "Class '%s' does not support suspending.",
3340 puc
->puc_Node
.ln_Name
);
3343 psdReleaseDevBinding(pd
);
3346 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3347 "Class '%s' does not support suspending, but has no active IO. Suspending anyway.",
3348 puc
->puc_Node
.ln_Name
);
3353 pc
= pd
->pd_CurrentConfig
;
3354 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3355 while(pif
->pif_Node
.ln_Succ
)
3357 if(pif
->pif_IfBinding
)
3359 if((puc
= pif
->pif_ClsBinding
))
3362 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
3365 res
= usbDoMethod(UCM_AttemptSuspendDevice
, pif
->pif_IfBinding
);
3368 // didn't want to suspend
3369 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3370 "%s failed to suspend device '%s'.",
3371 puc
->puc_Node
.ln_Name
, pd
->pd_ProductStr
);
3375 if(pd
->pd_IOBusyCount
)
3380 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3381 "%s does not support suspending.",
3382 puc
->puc_Node
.ln_Name
);
3385 psdReleaseIfBinding(pif
);
3388 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3389 "%s does not support suspending, but has no active IO. Suspending anyway.",
3390 puc
->puc_Node
.ln_Name
);
3395 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3404 /* /// "psdSuspendDevice()" */
3405 AROS_LH1(BOOL
, psdSuspendDevice
,
3406 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3407 LIBBASETYPEPTR
, ps
, 98, psd
)
3410 struct PsdUsbClass
*puc
;
3411 struct PsdDevice
*hubpd
;
3415 KPRINTF(5, ("psdSuspendDevice(%p)\n", pd
));
3418 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
3423 if(!hubpd
) // suspend root hub
3425 // suspend whole USB, using the HCI UHCMD_USBSUSPEND command
3426 // FIXME currently unsupported!
3427 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Suspending of root hub currently not supported.");
3431 psdLockWriteDevice(pd
);
3432 res
= psdSuspendBindings(pd
);
3433 psdUnlockDevice(pd
);
3436 psdLockReadDevice(pd
);
3437 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
3439 res
= usbDoMethod(UCM_HubSuspendDevice
, binding
, pd
);
3441 psdUnlockDevice(pd
);
3446 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3447 "Suspending of device '%s' failed.",
3455 /* /// "psdResumeBindings()" */
3456 AROS_LH1(BOOL
, psdResumeBindings
,
3457 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3458 LIBBASETYPEPTR
, ps
, 101, psd
)
3461 struct PsdUsbClass
*puc
;
3462 struct PsdConfig
*pc
;
3463 struct PsdInterface
*pif
;
3465 BOOL rescan
= FALSE
;
3467 KPRINTF(5, ("psdResumeBindings(%p)\n", pd
));
3470 // ask existing bindings to resume -- if they don't support it, rebind
3471 if(pd
->pd_DevBinding
)
3473 if(!(pd
->pd_Flags
& PDFF_APPBINDING
))
3475 if((puc
= pd
->pd_ClsBinding
))
3477 res
= usbDoMethod(UCM_AttemptResumeDevice
, pd
->pd_DevBinding
);
3480 // if the device couldn't resume, better get rid of the binding
3481 psdReleaseDevBinding(pd
);
3487 pc
= pd
->pd_CurrentConfig
;
3488 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3489 while(pif
->pif_Node
.ln_Succ
)
3491 if(pif
->pif_IfBinding
)
3493 if((puc
= pif
->pif_ClsBinding
))
3495 res
= usbDoMethod(UCM_AttemptResumeDevice
, pif
->pif_IfBinding
);
3498 // didn't want to suspend
3499 psdReleaseIfBinding(pif
);
3505 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3517 /* /// "psdResumeDevice()" */
3518 AROS_LH1(BOOL
, psdResumeDevice
,
3519 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3520 LIBBASETYPEPTR
, ps
, 99, psd
)
3523 struct PsdUsbClass
*puc
;
3524 struct PsdDevice
*hubpd
;
3528 KPRINTF(5, ("psdResumeDevice(%p)\n", pd
));
3531 if(!(pd
->pd_Flags
& PDFF_SUSPENDED
))
3536 if(!hubpd
) // resume root hub
3538 // resume whole USB, using the HCI UHCMD_USBRESUME command
3539 // FIXME currently unsupported!
3542 psdLockWriteDevice(pd
);
3543 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
3545 res
= usbDoMethod(UCM_HubResumeDevice
, binding
, pd
);
3547 psdUnlockDevice(pd
);
3551 psdResumeBindings(pd
);
3560 /* /// "psdFindDeviceA()" */
3561 AROS_LH2(struct PsdDevice
*, psdFindDeviceA
,
3562 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3563 AROS_LHA(struct TagItem
*, tags
, A1
),
3564 LIBBASETYPEPTR
, ps
, 44, psd
)
3569 KPRINTF(2, ("psdFindDeviceA(%p, %p)\n", pd
, tags
));
3570 while((pd
= psdGetNextDevice(pd
)))
3573 if((ti
= FindTagItem(DA_ProductID
, tags
)))
3575 if(ti
->ti_Data
!= pd
->pd_ProductID
)
3580 if((ti
= FindTagItem(DA_VendorID
, tags
)))
3582 if(ti
->ti_Data
!= pd
->pd_VendorID
)
3587 if((ti
= FindTagItem(DA_Class
, tags
)))
3589 if(ti
->ti_Data
!= pd
->pd_DevClass
)
3594 if((ti
= FindTagItem(DA_SubClass
, tags
)))
3596 if(ti
->ti_Data
!= pd
->pd_DevSubClass
)
3601 if((ti
= FindTagItem(DA_Protocol
, tags
)))
3603 if(ti
->ti_Data
!= pd
->pd_DevProto
)
3608 if((ti
= FindTagItem(DA_Version
, tags
)))
3610 if(ti
->ti_Data
!= pd
->pd_DevVers
)
3615 if((ti
= FindTagItem(DA_SerialNumber
, tags
)))
3617 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_SerNumStr
))
3622 if((ti
= FindTagItem(DA_ProductName
, tags
)))
3624 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_ProductStr
))
3629 if((ti
= FindTagItem(DA_Manufacturer
, tags
)))
3631 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_MnfctrStr
))
3636 if((ti
= FindTagItem(DA_IDString
, tags
)))
3638 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_IDString
))
3643 if((ti
= FindTagItem(DA_Binding
, tags
)))
3645 if(ti
->ti_Data
!= (IPTR
) pd
->pd_DevBinding
)
3650 if((ti
= FindTagItem(DA_HubDevice
, tags
)))
3652 if(ti
->ti_Data
!= (IPTR
) pd
->pd_Hub
)
3668 /* *** Hardware *** */
3670 /* /// "pFindHardware()" */
3671 struct PsdHardware
* pFindHardware(LIBBASETYPEPTR ps
, STRPTR name
, ULONG unit
)
3673 struct PsdHardware
*phw
;
3677 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
3678 while(phw
->phw_Node
.ln_Succ
)
3680 if((phw
->phw_Unit
== unit
) && (!strcmp(phw
->phw_DevName
, name
)))
3685 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
3689 if((*name
== '/') || (*name
== ':'))
3701 /* /// "psdEnumerateHardware()" */
3702 AROS_LH1(struct PsdDevice
*, psdEnumerateHardware
,
3703 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3704 LIBBASETYPEPTR
, ps
, 14, psd
)
3707 struct PsdDevice
*pd
= NULL
;
3710 #ifdef AROS_USB30_CODE
3713 KPRINTF(2, ("psdEnumerateHardware(%p)\n", phw
));
3715 if((mp
= CreateMsgPort()))
3718 if((pd
= psdAllocDevice(phw
)))
3721 if((pp
= psdAllocPipe(pd
, mp
, NULL
)))
3723 //pp->pp_IOReq.iouh_Flags |= UHFF_NAKTIMEOUT;
3724 //pp->pp_IOReq.iouh_NakTimeout = 1000;
3725 pd
->pd_Flags
|= PDFF_CONNECTED
;
3727 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_USBRESET
;
3728 #ifdef AROS_USB30_CODE
3729 ioerr
= psdDoPipe(pp
, NULL
, 0);
3730 if(ioerr
== UHIOERR_HOSTERROR
) {
3731 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "UHCMD_USBRESET reset failed.");
3733 pFreeBindings(ps
, pd
);
3734 pFreeDevice(ps
, pd
);
3739 psdDoPipe(pp
, NULL
, 0);
3741 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
3742 psdDelayMS(100); // wait for root hub to settle
3743 if(psdEnumerateDevice(pp
))
3745 KPRINTF(1, ("Enumeration finished!\n"));
3746 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Root hub has been enumerated.");
3749 phw
->phw_RootDevice
= pd
;
3750 psdSendEvent(EHMB_ADDDEVICE
, pd
, NULL
);
3755 pFreeBindings(ps
, pd
);
3756 pFreeDevice(ps
, pd
);
3762 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Root hub enumeration failed. Blame your hardware driver programmer.");
3768 /* /// "psdRemHardware()" */
3769 AROS_LH1(void, psdRemHardware
,
3770 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3771 LIBBASETYPEPTR
, ps
, 13, psd
)
3774 struct PsdDevice
*pd
;
3777 KPRINTF(5, ("FreeHardware(%p)\n", phw
));
3779 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3780 while(pd
->pd_Node
.ln_Succ
)
3782 pFreeBindings(ps
, pd
);
3783 pFreeDevice(ps
, pd
);
3784 psdSendEvent(EHMB_REMDEVICE
, pd
, NULL
);
3785 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3788 pd
= (struct PsdDevice
*) phw
->phw_DeadDevices
.lh_Head
;
3789 while(pd
->pd_Node
.ln_Succ
)
3793 KPRINTF(20, ("Can't remove device, usecnt %ld\n", pd
->pd_UseCnt
));
3796 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3797 "Can't remove device '%s', there are still %ld pipes in use...",
3798 pd
->pd_ProductStr
, pd
->pd_UseCnt
);
3802 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3803 "Okay, going down with device '%s' anyway, maybe the driver crashed?",
3811 pFreeDevice(ps
, pd
);
3812 //psdSendEvent(EHMB_REMDEVICE, pd, NULL);
3814 pd
= (struct PsdDevice
*) phw
->phw_DeadDevices
.lh_Head
;
3818 /* Note that the subtask unlinks the hardware! */
3819 phw
->phw_ReadySignal
= SIGB_SINGLE
;
3820 phw
->phw_ReadySigTask
= FindTask(NULL
);
3823 Signal(phw
->phw_Task
, SIGBREAKF_CTRL_C
);
3826 while(phw
->phw_Task
)
3828 Wait(1L<<phw
->phw_ReadySignal
);
3830 //FreeSignal(phw->phw_ReadySignal);
3831 KPRINTF(1, ("FreeHardware(%p) freevec name\n", phw
));
3832 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3833 "Removed hardware %s/%ld. Bye bye!",
3834 phw
->phw_DevName
, phw
->phw_Unit
);
3835 psdFreeVec(phw
->phw_DevName
);
3836 psdFreeVec(phw
->phw_ProductName
);
3837 psdFreeVec(phw
->phw_Manufacturer
);
3838 psdFreeVec(phw
->phw_Description
);
3839 psdFreeVec(phw
->phw_Copyright
);
3841 psdSendEvent(EHMB_REMHARDWARE
, phw
, NULL
);
3842 KPRINTF(1, ("FreeHardware(%p) done\n", phw
));
3847 /* /// "psdAddHardware()" */
3848 AROS_LH2(struct PsdHardware
*,psdAddHardware
,
3849 AROS_LHA(STRPTR
, name
, A0
),
3850 AROS_LHA(ULONG
, unit
, D0
),
3851 LIBBASETYPEPTR
, ps
, 12, psd
)
3854 struct PsdHardware
*phw
;
3856 struct Task
*tmptask
;
3857 KPRINTF(5, ("psdAddHardware(%s, %ld)\n", name
, unit
));
3859 if((phw
= psdAllocVec(sizeof(struct PsdHardware
))))
3861 NewList(&phw
->phw_Devices
);
3862 NewList(&phw
->phw_DeadDevices
);
3863 phw
->phw_Unit
= unit
;
3865 if((phw
->phw_Node
.ln_Name
= phw
->phw_DevName
= psdCopyStr(name
)))
3867 psdSafeRawDoFmt(buf
, 64, "usbhw<%s/%ld>", name
, unit
);
3868 phw
->phw_ReadySignal
= SIGB_SINGLE
;
3869 phw
->phw_ReadySigTask
= FindTask(NULL
);
3870 SetSignal(0, SIGF_SINGLE
); // clear single bit
3871 if((tmptask
= psdSpawnSubTask(buf
, pDeviceTask
, phw
)))
3873 psdBorrowLocksWait(tmptask
, 1UL<<phw
->phw_ReadySignal
);
3876 phw
->phw_ReadySigTask
= NULL
;
3877 //FreeSignal(phw->phw_ReadySignal);
3878 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3879 "New hardware %s/%ld added (%s).",
3882 phw
->phw_ProductName
);
3883 psdSendEvent(EHMB_ADDHARDWARE
, phw
, NULL
);
3887 phw
->phw_ReadySigTask
= NULL
;
3888 //FreeSignal(phw->phw_ReadySignal);
3889 psdFreeVec(phw
->phw_DevName
);
3898 /* /// "psdCalculatePower()" */
3899 AROS_LH1(void, psdCalculatePower
,
3900 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3901 LIBBASETYPEPTR
, ps
, 78, psd
)
3904 struct PsdDevice
*roothub
= NULL
;
3905 struct PsdDevice
*pd
;
3909 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3910 while(pd
->pd_Node
.ln_Succ
)
3917 pd
= (struct PsdDevice
*) pd
->pd_Node
.ln_Succ
;
3924 roothub
->pd_PowerDrain
= 0;
3925 roothub
->pd_PowerSupply
= 500;
3927 /* calculate drain */
3928 pPowerRecurseDrain(ps
, roothub
);
3930 /* calculate supply */
3931 pPowerRecurseSupply(ps
, roothub
);
3939 /* /// "psdAllocPipe()" */
3940 AROS_LH3(struct PsdPipe
*, psdAllocPipe
,
3941 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3942 AROS_LHA(struct MsgPort
*, mp
, A1
),
3943 AROS_LHA(struct PsdEndpoint
*, pep
, A2
),
3944 LIBBASETYPEPTR
, ps
, 24, psd
)
3948 struct PsdDevice
*hubpd
;
3950 KPRINTF(2, ("psdAllocPipe(%p, %p, %p)\n", pd
, mp
, pep
));
3955 if(pep
&& (pep
->pep_TransType
== USEAF_ISOCHRONOUS
) && (!(pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Capabilities
& UHCF_ISO
)))
3957 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Your HW controller driver does not support iso transfers. Sorry.");
3961 if((pp
= psdAllocVec(sizeof(struct PsdPipe
))))
3963 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
3964 pp
->pp_MsgPort
= pp
->pp_Msg
.mn_ReplyPort
= mp
;
3965 pp
->pp_Msg
.mn_Length
= sizeof(struct PsdPipe
);
3967 pp
->pp_Endpoint
= pep
;
3968 pp
->pp_IOReq
= *(pd
->pd_Hardware
->phw_RootIOReq
);
3969 pp
->pp_IOReq
.iouh_DevAddr
= pd
->pd_DevAddr
;
3970 if(pd
->pd_Flags
& PDFF_LOWSPEED
)
3972 pp
->pp_IOReq
.iouh_Flags
|= UHFF_LOWSPEED
;
3974 if(pd
->pd_Flags
& PDFF_HIGHSPEED
)
3976 pp
->pp_IOReq
.iouh_Flags
|= UHFF_HIGHSPEED
;
3979 switch(pep
->pep_NumTransMuFr
)
3982 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_2
;
3985 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_3
;
3989 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_1
;
3992 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_1
;
3995 #ifdef AROS_USB30_CODE
3996 if(pd
->pd_Flags
& PDFF_SUPERSPEED
)
3998 pp
->pp_IOReq
.iouh_Flags
|= UHFF_SUPERSPEED
;
4001 if(pd
->pd_Flags
& PDFF_NEEDSSPLIT
)
4003 /* USB1.1 device connected to a USB2.0 hub */
4004 pp
->pp_IOReq
.iouh_Flags
|= UHFF_SPLITTRANS
;
4006 pp
->pp_IOReq
.iouh_SplitHubPort
= pd
->pd_HubPort
;
4007 // find the root USB 2.0 hub in the tree
4008 while(hubpd
&& !(hubpd
->pd_Flags
& PDFF_HIGHSPEED
))
4010 pp
->pp_IOReq
.iouh_SplitHubPort
= hubpd
->pd_HubPort
;
4011 hubpd
= hubpd
->pd_Hub
;
4015 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Internal error obtaining split transaction hub!");
4019 pp
->pp_IOReq
.iouh_Flags
|= (hubpd
->pd_HubThinkTime
<<UHFS_THINKTIME
);
4020 pp
->pp_IOReq
.iouh_SplitHubAddr
= hubpd
->pd_DevAddr
;
4024 switch(pep
->pep_TransType
)
4027 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
4029 case USEAF_ISOCHRONOUS
:
4030 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_ISOXFER
;
4033 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_BULKXFER
;
4035 case USEAF_INTERRUPT
:
4036 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_INTXFER
;
4039 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4040 "AllocPipe(): Illegal transfer type %ld",
4041 pep
->pep_TransType
);
4042 KPRINTF(20, ("Illegal transfer type for endpoint!"));
4047 pp
->pp_IOReq
.iouh_Dir
= (pep
->pep_Direction
? UHDIR_IN
: UHDIR_OUT
);
4048 pp
->pp_IOReq
.iouh_Endpoint
= pep
->pep_EPNum
;
4049 pp
->pp_IOReq
.iouh_MaxPktSize
= pep
->pep_MaxPktSize
;
4050 pp
->pp_IOReq
.iouh_Interval
= pep
->pep_Interval
;
4052 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
4053 pp
->pp_IOReq
.iouh_Dir
= UHDIR_SETUP
;
4054 pp
->pp_IOReq
.iouh_Endpoint
= 0;
4055 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
;
4065 /* /// "psdFreePipe()" */
4066 AROS_LH1(void, psdFreePipe
,
4067 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4068 LIBBASETYPEPTR
, ps
, 25, psd
)
4071 struct PsdDevice
*pd
;
4076 KPRINTF(2, ("psdFreePipe(%p)\n", pp
));
4079 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4081 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4082 "Tried to free pipe on %s that was still pending!", pd
->pd_ProductStr
);
4087 if(!(--pd
->pd_UseCnt
) && (pd
->pd_Flags
& PDFF_DELEXPUNGE
))
4089 KPRINTF(20, ("Finally getting rid of device %s\n", pd
->pd_ProductStr
));
4090 pFreeDevice(ps
, pd
);
4091 //psdSendEvent(EHMB_REMDEVICE, pd, NULL);
4099 /* /// "psdPipeSetup()" */
4100 AROS_LH5(void, psdPipeSetup
,
4101 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4102 AROS_LHA(UWORD
, rt
, D0
),
4103 AROS_LHA(UWORD
, rq
, D1
),
4104 AROS_LHA(UWORD
, val
, D2
),
4105 AROS_LHA(UWORD
, idx
, D3
),
4106 LIBBASETYPEPTR
, ps
, 26, psd
)
4109 struct UsbSetupData
*usd
= &pp
->pp_IOReq
.iouh_SetupData
;
4111 KPRINTF(1, ("psdSetupPipe(%p, (%02lx %02lx %04lx %04lx))\n",
4112 pp
, rt
, rq
, val
, idx
));
4113 usd
->bmRequestType
= rt
;
4115 usd
->wValue
= AROS_WORD2LE(val
);
4116 usd
->wIndex
= AROS_WORD2LE(idx
);
4121 /* /// "psdDoPipe()" */
4122 AROS_LH3(LONG
, psdDoPipe
,
4123 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4124 AROS_LHA(APTR
, data
, A0
),
4125 AROS_LHA(ULONG
, len
, D0
),
4126 LIBBASETYPEPTR
, ps
, 27, psd
)
4129 struct PsdDevice
*pd
= pp
->pp_Device
;
4130 KPRINTF(200, ("psdDoPipe(%p, %p, %ld)\n", pp
, data
, len
));
4132 if(pd
->pd_Flags
& PDFF_CONNECTED
)
4134 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
4136 // make sure the device is up and running before trying to send a new pipe
4137 psdResumeDevice(pd
);
4140 pp
->pp_IOReq
.iouh_Data
= data
;
4141 pp
->pp_IOReq
.iouh_Length
= len
;
4142 if(!pp
->pp_Endpoint
)
4144 pp
->pp_IOReq
.iouh_SetupData
.wLength
= AROS_WORD2LE(len
);
4146 PutMsg(&pd
->pd_Hardware
->phw_TaskMsgPort
, &pp
->pp_Msg
);
4147 ++pd
->pd_IOBusyCount
;
4148 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4149 return(psdWaitPipe(pp
));
4152 pp
->pp_IOReq
.iouh_Actual
= 0;
4153 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
4154 return(pp
->pp_IOReq
.iouh_Req
.io_Error
= UHIOERR_TIMEOUT
);
4160 /* /// "psdSendPipe()" */
4161 AROS_LH3(void, psdSendPipe
,
4162 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4163 AROS_LHA(APTR
, data
, A0
),
4164 AROS_LHA(ULONG
, len
, D0
),
4165 LIBBASETYPEPTR
, ps
, 28, psd
)
4168 struct PsdDevice
*pd
= pp
->pp_Device
;
4169 KPRINTF(200, ("psdSendPipe(%p, %p, %ld)\n", pp
, data
, len
));
4170 if(pd
->pd_Flags
& PDFF_CONNECTED
)
4172 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
4174 // make sure the device is up and running before trying to send a new pipe
4175 psdResumeDevice(pd
);
4178 pp
->pp_IOReq
.iouh_Data
= data
;
4179 pp
->pp_IOReq
.iouh_Length
= len
;
4180 if(!pp
->pp_Endpoint
)
4182 pp
->pp_IOReq
.iouh_SetupData
.wLength
= AROS_WORD2LE(len
);
4184 PutMsg(&pd
->pd_Hardware
->phw_TaskMsgPort
, &pp
->pp_Msg
);
4185 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4186 ++pd
->pd_IOBusyCount
;
4189 pp
->pp_IOReq
.iouh_Actual
= 0;
4190 //pp->pp_Msg.mn_Node.ln_Type = NT_REPLYMSG;
4191 pp
->pp_IOReq
.iouh_Req
.io_Error
= UHIOERR_TIMEOUT
;
4192 ReplyMsg(&pp
->pp_Msg
);
4193 ++pd
->pd_IOBusyCount
;
4199 /* /// "psdAbortPipe()" */
4200 AROS_LH1(void, psdAbortPipe
,
4201 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4202 LIBBASETYPEPTR
, ps
, 29, psd
)
4205 struct PsdPipe
*npp
;
4207 KPRINTF(5, ("psdAbortPipe(%p)\n", pp
));
4208 if(pp
->pp_Msg
.mn_Node
.ln_Type
!= NT_MESSAGE
)
4210 KPRINTF(5, ("Nothing to abort %02lx\n", pp
->pp_IOReq
.iouh_Req
.io_Message
.mn_Node
.ln_Type
));
4213 if((npp
= psdAllocVec(sizeof(struct PsdPipe
))))
4215 //npp->pp_Msg.mn_Node.ln_Type = NT_MESSAGE;
4216 npp
->pp_Device
= pp
->pp_Device
;
4217 npp
->pp_MsgPort
= npp
->pp_Msg
.mn_ReplyPort
= pp
->pp_MsgPort
;
4218 npp
->pp_Msg
.mn_Length
= sizeof(struct PsdPipe
);
4220 npp
->pp_AbortPipe
= pp
;
4221 PutMsg(&pp
->pp_Device
->pd_Hardware
->phw_TaskMsgPort
, &npp
->pp_Msg
);
4229 /* /// "psdWaitPipe()" */
4230 AROS_LH1(LONG
, psdWaitPipe
,
4231 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4232 LIBBASETYPEPTR
, ps
, 30, psd
)
4236 struct PsdDevice
*pd
= pp
->pp_Device
;
4238 KPRINTF(5, ("psdWaitPipe(%p)\n", pp
));
4239 while(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4241 KPRINTF(5, ("ln_Type = %02lx\n", pp
->pp_Msg
.mn_Node
.ln_Type
));
4242 sigs
|= Wait(1L<<pp
->pp_MsgPort
->mp_SigBit
);
4243 KPRINTF(5, ("sigs = %p\n", sigs
));
4247 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_REPLYMSG
)
4249 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
4250 Remove(&pp
->pp_Msg
.mn_Node
);
4252 //if(pp->pp_MsgPort->mp_MsgList.lh_Head->ln_Succ)
4254 // avoid signals getting lost for other messages arriving.
4255 SetSignal(sigs
, sigs
);
4260 Remove(&pp
->pp_Msg
.mn_Node
);
4263 ioerr
= pp
->pp_IOReq
.iouh_Req
.io_Error
;
4266 case UHIOERR_TIMEOUT
:
4269 case UHIOERR_NAKTIMEOUT
:
4271 case UHIOERR_CRCERROR
:
4274 case UHIOERR_RUNTPACKET
:
4276 if(pd
->pd_DeadCount
)
4278 pd
->pd_DeadCount
>>= 1;
4279 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4280 "Device %s starts recovering with %s (%ld)!",
4282 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);*/
4285 KPRINTF(200, ("psdWaitPipe(%p)=%ld\n", pp
, ioerr
));
4286 --pd
->pd_IOBusyCount
;
4287 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4289 if((pd
->pd_DeadCount
> 19) || ((pd
->pd_DeadCount
> 14) && (pd
->pd_Flags
& (PDFF_HASDEVADDR
|PDFF_HASDEVDESC
))))
4291 if(!(pd
->pd_Flags
& PDFF_DEAD
))
4293 pd
->pd_Flags
|= PDFF_DEAD
;
4294 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4295 "Device %s probably dropped dead!", pd
->pd_ProductStr
);
4297 psdSendEvent(EHMB_DEVICEDEAD
, pp
->pp_Device
, NULL
);
4300 if((!pd
->pd_DeadCount
) && ((pd
->pd_Flags
& (PDFF_DEAD
|PDFF_CONNECTED
)) == (PDFF_DEAD
|PDFF_CONNECTED
)))
4302 pd
->pd_Flags
&= ~PDFF_DEAD
;
4303 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4304 "Uuuhuuuhh, the zombie %s returned from the dead!", pd
->pd_ProductStr
);
4312 /* /// "psdCheckPipe()" */
4313 AROS_LH1(struct PsdPipe
*, psdCheckPipe
,
4314 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4315 LIBBASETYPEPTR
, ps
, 71, psd
)
4318 KPRINTF(5, ("psdCheckPipe(%p)\n", pp
));
4319 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4328 /* /// "psdGetPipeActual()" */
4329 AROS_LH1(ULONG
, psdGetPipeActual
,
4330 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4331 LIBBASETYPEPTR
, ps
, 31, psd
)
4334 KPRINTF(1, ("psdGetPipeActual(%p)\n", pp
));
4335 return(pp
->pp_IOReq
.iouh_Actual
);
4340 /* /// "psdGetPipeError()" */
4341 AROS_LH1(LONG
, psdGetPipeError
,
4342 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4343 LIBBASETYPEPTR
, ps
, 32, psd
)
4346 KPRINTF(1, ("psdGetPipeError(%p)\n", pp
));
4347 return((LONG
) pp
->pp_IOReq
.iouh_Req
.io_Error
);
4352 /* *** Streams *** */
4354 /* /// "psdOpenStreamA()" */
4355 AROS_LH2(struct PsdPipeStream
*, psdOpenStreamA
,
4356 AROS_LHA(struct PsdEndpoint
*, pep
, A0
),
4357 AROS_LHA(struct TagItem
*, tags
, A1
),
4358 LIBBASETYPEPTR
, ps
, 72, psd
)
4361 struct PsdPipeStream
*pps
;
4363 KPRINTF(2, ("psdOpenStream(%p, %p)\n", pep
, tags
));
4368 if((pps
= psdAllocVec(sizeof(struct PsdPipeStream
))))
4370 pps
->pps_Device
= pep
->pep_Interface
->pif_Config
->pc_Device
;
4371 pps
->pps_Endpoint
= pep
;
4372 NewList(&pps
->pps_FreePipes
);
4373 NewList(&pps
->pps_ReadyPipes
);
4374 InitSemaphore(&pps
->pps_AccessLock
);
4375 pps
->pps_NakTimeoutTime
= 5000;
4376 if(pep
->pep_Direction
)
4378 /* Defaults for IN */
4379 pps
->pps_NumPipes
= 4;
4380 pps
->pps_Flags
= PSFF_READAHEAD
|PSFF_BUFFERREAD
|PSFF_ALLOWRUNT
;
4381 pps
->pps_BufferSize
= 32*pps
->pps_Endpoint
->pep_MaxPktSize
;
4383 /* Defaults for OUT */
4384 pps
->pps_NumPipes
= 4;
4385 pps
->pps_Flags
= PSFF_NOSHORTPKT
;
4386 pps
->pps_BufferSize
= 4*pps
->pps_Endpoint
->pep_MaxPktSize
;
4389 psdSetAttrsA(PGA_PIPESTREAM
, pps
, tags
);
4392 psdCloseStream(pps
);
4402 /* /// "psdCloseStream()" */
4403 AROS_LH1(void, psdCloseStream
,
4404 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4405 LIBBASETYPEPTR
, ps
, 73, psd
)
4411 KPRINTF(2, ("psdCloseStream(%p)\n", pps
));
4416 psdStreamFlush(pps
);
4417 ObtainSemaphore(&pps
->pps_AccessLock
);
4420 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
4422 pp
= pps
->pps_Pipes
[cnt
];
4423 //if(pp->pp_IOReq.iouh_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
4425 KPRINTF(1, ("Abort %ld\n", cnt
));
4427 KPRINTF(1, ("Wait %ld\n", cnt
));
4430 KPRINTF(1, ("Free %ld\n", cnt
));
4433 psdFreeVec(pps
->pps_Pipes
);
4434 if((pps
->pps_Flags
& PSFF_OWNMSGPORT
) && pps
->pps_MsgPort
)
4436 DeleteMsgPort(pps
->pps_MsgPort
);
4439 psdFreeVec(pps
->pps_Buffer
);
4440 ReleaseSemaphore(&pps
->pps_AccessLock
);
4446 /* /// "psdStreamRead()" */
4447 AROS_LH3(LONG
, psdStreamRead
,
4448 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4449 AROS_LHA(UBYTE
*, buffer
, A0
),
4450 AROS_LHA(LONG
, length
, D0
),
4451 LIBBASETYPEPTR
, ps
, 74, psd
)
4468 KPRINTF(2, ("psdStreamRead(%p, %p, %ld)\n", pps
, buffer
, length
));
4473 ObtainSemaphore(&pps
->pps_AccessLock
);
4474 KPRINTF(2, ("Sema\n"));
4476 if((!pps
->pps_Pipes
) || (!pps
->pps_Endpoint
->pep_Direction
))
4478 KPRINTF(2, ("Wrong direction!\n"));
4479 pps
->pps_Error
= UHIOERR_BADPARAMS
;
4480 ReleaseSemaphore(&pps
->pps_AccessLock
);
4483 if(!(pps
->pps_Flags
& PSFF_ASYNCIO
))
4485 if(pps
->pps_Flags
& PSFF_BUFFERREAD
)
4487 /* buffered reading */
4490 /* check for incoming packets */
4491 while((pp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4493 KPRINTF(1, ("PktBack(%p, %p, %ld/%ld)=%ld\n",
4494 pp
, pp
->pp_IOReq
.iouh_Data
, pp
->pp_IOReq
.iouh_Actual
,
4495 pp
->pp_IOReq
.iouh_Length
, pp
->pp_IOReq
.iouh_Req
.io_Error
));
4497 pps
->pps_ReqBytes
-= pp
->pp_IOReq
.iouh_Length
;
4498 ioerr
= pp
->pp_IOReq
.iouh_Req
.io_Error
;
4499 if((ioerr
== UHIOERR_NAKTIMEOUT
) && pp
->pp_IOReq
.iouh_Actual
)
4506 pps
->pps_Error
= ioerr
;
4508 if(ioerr
!= UHIOERR_TIMEOUT
)
4510 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamRead",
4511 "Packet(%s) failed: %s (%ld)", (STRPTR
) "b",
4512 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4514 /* stop automatic queueing */
4515 pps
->pps_Flags
&= ~PSFF_READAHEAD
;
4516 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4518 /* successfully received packet */
4519 pps
->pps_BytesPending
+= pp
->pp_IOReq
.iouh_Actual
;
4520 AddTail(&pps
->pps_ReadyPipes
, &pp
->pp_Msg
.mn_Node
);
4523 if(length
== -1) /* get all that's there (STRONGLY DISCOURAGED! Might cause buffer overflows) */
4525 length
= pps
->pps_BytesPending
;
4527 /* check for buffered data */
4528 while(length
&& pps
->pps_BytesPending
)
4530 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
4531 if(!pp
->pp_Msg
.mn_Node
.ln_Succ
) /* debug */
4533 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) "StreamRead", "Readqueue empty!");
4534 ReleaseSemaphore(&pps
->pps_AccessLock
);
4537 if(pp
->pp_IOReq
.iouh_Actual
< pps
->pps_Offset
)
4539 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) "StreamRead",
4540 "Actual %ld < offset %ld!", pp
->pp_IOReq
.iouh_Actual
, pps
->pps_Offset
);
4541 ReleaseSemaphore(&pps
->pps_AccessLock
);
4544 remlen
= pp
->pp_IOReq
.iouh_Actual
- pps
->pps_Offset
;
4547 KPRINTF(1, ("PktBit(%p, %p, %ld)\n", pp
, buffer
, length
));
4550 KPRINTF(1, ("PktRem(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4553 if(pp
->pp_Flags
& PFF_INPLACE
)
4555 KPRINTF(1, ("PktRemIP(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4557 if(pps
->pps_TermArray
)
4560 KPRINTF(1, ("PktCpyEOF(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4562 srcptr
= &(((UBYTE
*) pp
->pp_IOReq
.iouh_Data
)[pps
->pps_Offset
]);
4563 tarrptr
= pps
->pps_TermArray
;
4570 cchar
= *bufptr
++ = *srcptr
++;
4575 if(cchar
< tarrptr
[tcnt
])
4579 else if(cchar
== tarrptr
[tcnt
])
4583 KPRINTF(2, ("EOF char %02lx found, length = %ld\n", cchar
, remlen
));
4588 if(tarrptr
[tcnt
] == tarrptr
[tcnt
+1])
4593 } while(++tcnt
< 8);
4597 KPRINTF(1, ("PktCpy(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4598 /* quick non-eof mode */
4599 CopyMem(&(((UBYTE
*) pp
->pp_IOReq
.iouh_Data
)[pps
->pps_Offset
]), buffer
, remlen
);
4605 pps
->pps_BytesPending
-= remlen
;
4606 pps
->pps_Offset
+= remlen
;
4607 /* end of packet reached? */
4608 if(pps
->pps_Offset
== pp
->pp_IOReq
.iouh_Actual
)
4610 pps
->pps_Offset
= 0;
4611 Remove(&pp
->pp_Msg
.mn_Node
);
4612 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4613 /* check for short packet */
4614 if((pps
->pps_Flags
& PSFF_SHORTTERM
) && (pp
->pp_IOReq
.iouh_Actual
% pp
->pp_IOReq
.iouh_MaxPktSize
))
4624 /* start sending out requests */
4626 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4627 if(!(pps
->pps_BytesPending
|| pps
->pps_ReqBytes
|| pps
->pps_TermArray
|| (length
< pps
->pps_BufferSize
)))
4629 /* faster non-buffered mode */
4630 if(pp
->pp_Msg
.mn_Node
.ln_Succ
)
4632 pp
->pp_Flags
|= PFF_INPLACE
;
4633 Remove(&pp
->pp_Msg
.mn_Node
);
4634 remlen
= length
- (length
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4635 KPRINTF(1, ("OutFast(%p, %p, %ld/%ld)\n",
4636 pp
, buffer
, remlen
, length
));
4637 psdSendPipe(pp
, buffer
, remlen
);
4638 pps
->pps_ReqBytes
+= remlen
;
4639 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4642 /* slower buffered mode */
4643 while(pp
->pp_Msg
.mn_Node
.ln_Succ
&& ((remlen
> pps
->pps_ReqBytes
) || (pps
->pps_Flags
& PSFF_READAHEAD
)))
4645 pp
->pp_Flags
&= ~PFF_INPLACE
;
4646 Remove(&pp
->pp_Msg
.mn_Node
);
4647 if((pps
->pps_Flags
& PSFF_READAHEAD
) || (remlen
% pp
->pp_IOReq
.iouh_MaxPktSize
))
4649 KPRINTF(1, ("OutSlow(%p, %p, %ld)\n",
4650 pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], pps
->pps_BufferSize
));
4651 remlen
= pps
->pps_BufferSize
;
4653 KPRINTF(1, ("OutExact(%p, %p, %ld)\n",
4654 pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], remlen
));
4656 psdSendPipe(pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], remlen
);
4657 pps
->pps_ReqBytes
+= remlen
;
4658 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4660 if((!length
) || (pps
->pps_Flags
& PSFF_DONOTWAIT
))
4666 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4667 KPRINTF(1, ("WaitPort (%p)\n", sigmask
));
4668 sigmask
= Wait(sigmask
);
4669 KPRINTF(1, ("Wait back (%p)\n", sigmask
));
4670 if(sigmask
& pps
->pps_AbortSigMask
)
4672 KPRINTF(1, ("Aborted!\n"));
4674 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4679 /* plain reading (might lose data) */
4680 if(pps
->pps_TermArray
|| (pps
->pps_Flags
& PSFF_READAHEAD
))
4682 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) "StreamRead", "This mode combination for the stream is not supported!");
4684 /* start sending out requests */
4685 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4686 if(pp
->pp_Msg
.mn_Node
.ln_Succ
&& length
)
4688 ioerr
= psdDoPipe(pp
, buffer
, length
);
4691 pps
->pps_Error
= ioerr
;
4692 if(ioerr
!= UHIOERR_TIMEOUT
)
4694 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamRead",
4695 "Packet(%s) failed: %s (%ld)", (STRPTR
) "u",
4696 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4699 actual
= pp
->pp_IOReq
.iouh_Actual
;
4703 ReleaseSemaphore(&pps
->pps_AccessLock
);
4709 /* /// "psdStreamWrite()" */
4710 AROS_LH3(LONG
, psdStreamWrite
,
4711 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4712 AROS_LHA(UBYTE
*, buffer
, A0
),
4713 AROS_LHA(LONG
, length
, D0
),
4714 LIBBASETYPEPTR
, ps
, 75, psd
)
4718 struct PsdPipe
*newpp
;
4731 KPRINTF(2, ("psdStreamWrite(%p, %p, %ld)\n", pps
, buffer
, length
));
4736 ObtainSemaphore(&pps
->pps_AccessLock
);
4738 if((!pps
->pps_Pipes
) || pps
->pps_Endpoint
->pep_Direction
)
4740 KPRINTF(2, ("Wrong direction!\n"));
4741 pps
->pps_Error
= UHIOERR_BADPARAMS
;
4742 ReleaseSemaphore(&pps
->pps_AccessLock
);
4745 if(length
== -1) /* null terminated string mode */
4747 KPRINTF(2, ("EOL mode!\n"));
4748 length
= strlen(buffer
);
4750 if((tarrptr
= pps
->pps_TermArray
)) /* EOF Mode */
4752 KPRINTF(1, ("EOFSearch(%p, %ld)\n", buffer
, length
));
4765 if(cchar
< tarrptr
[tcnt
])
4769 else if(cchar
== tarrptr
[tcnt
])
4772 KPRINTF(2, ("EOF char %02lx found, length = %ld\n", cchar
, length
));
4777 if(tarrptr
[tcnt
] == tarrptr
[tcnt
+1])
4782 } while(++tcnt
< 8);
4786 if(!(pps
->pps_Flags
& PSFF_ASYNCIO
))
4788 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4789 if(pp
->pp_Msg
.mn_Node
.ln_Succ
&& length
)
4791 if(pps
->pps_Flags
& PSFF_BUFFERWRITE
)
4793 /* buffered writing */
4794 if(pps
->pps_BytesPending
)
4796 remlen
= pps
->pps_BytesPending
% pp
->pp_IOReq
.iouh_MaxPktSize
;
4797 /* align to packet boundary */
4798 if(remlen
+ length
>= pp
->pp_IOReq
.iouh_MaxPktSize
)
4800 /* new data crosses at least on packet size */
4801 if(pps
->pps_BytesPending
+ length
<= pps
->pps_BufferSize
)
4803 /* copy everything up to the last (!) boundary */
4804 remlen
= pps
->pps_BytesPending
+ length
;
4805 remlen
= remlen
- (remlen
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4806 remlen
-= pps
->pps_BytesPending
;
4807 KPRINTF(1, ("PendOptCpy(%p, %ld+%ld/%ld)\n", buffer
, pps
->pps_BytesPending
, remlen
, length
));
4809 /* just calculate amount to copy to the next boundary */
4810 remlen
= pp
->pp_IOReq
.iouh_MaxPktSize
- remlen
;
4811 KPRINTF(1, ("PendOneCpy(%p, %ld+%ld/%ld)\n", buffer
, pps
->pps_BytesPending
, remlen
, length
));
4813 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], remlen
);
4814 pps
->pps_BytesPending
+= remlen
;
4819 KPRINTF(1, ("PendAdd(%p, %ld+%ld)\n", buffer
, pps
->pps_BytesPending
, length
));
4820 /* only a few bytes, see if we can fit them */
4821 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], length
);
4822 pps
->pps_BytesPending
+= length
;
4824 //buffer += length; /* not needed */
4827 /* flush some buffers */
4828 if((length
>= pp
->pp_IOReq
.iouh_MaxPktSize
) ||
4829 ((pps
->pps_BytesPending
>= (pps
->pps_BufferSize
>>1)) && (pps
->pps_BytesPending
>= pp
->pp_IOReq
.iouh_MaxPktSize
)))
4831 remlen
= pps
->pps_BytesPending
- (pps
->pps_BytesPending
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4832 KPRINTF(1, ("PendFlush(%ld/%ld)\n", remlen
, pps
->pps_BytesPending
));
4833 Remove(&pp
->pp_Msg
.mn_Node
);
4834 psdSendPipe(pp
, pps
->pps_Buffer
, remlen
);
4835 pps
->pps_ActivePipe
= pp
;
4836 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4838 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4839 sigmask
= Wait(sigmask
);
4840 if(sigmask
& pps
->pps_AbortSigMask
)
4842 KPRINTF(1, ("Kill signal detected!\n"));
4843 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4851 ioerr
= psdWaitPipe(pp
);
4852 pps
->pps_ActivePipe
= NULL
;
4853 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4855 /* move end of buffer */
4856 cnt
= pps
->pps_BytesPending
;
4857 tcnt
= pp
->pp_IOReq
.iouh_Actual
;
4858 pps
->pps_BytesPending
-= tcnt
;
4859 bufptr
= pps
->pps_Buffer
;
4860 srcptr
= bufptr
+ tcnt
;
4866 *bufptr
++ = *srcptr
++;
4871 pps
->pps_Error
= ioerr
;
4872 if(ioerr
!= UHIOERR_TIMEOUT
)
4874 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4875 "Packet(%s) failed: %s (%ld)", (STRPTR
) "b",
4876 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4878 ReleaseSemaphore(&pps
->pps_AccessLock
);
4883 /* send out large chunk (avoid copying) */
4884 if(length
>= pp
->pp_IOReq
.iouh_MaxPktSize
)
4886 remlen
= length
- (length
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4887 KPRINTF(1, ("BulkFlush(%p, %ld/%ld)\n", buffer
, remlen
, length
));
4888 Remove(&pp
->pp_Msg
.mn_Node
);
4889 psdSendPipe(pp
, buffer
, remlen
);
4890 pps
->pps_ActivePipe
= pp
;
4891 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4893 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4894 sigmask
= Wait(sigmask
);
4895 if(sigmask
& pps
->pps_AbortSigMask
)
4897 KPRINTF(1, ("Kill signal detected!\n"));
4898 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4906 ioerr
= psdWaitPipe(pp
);
4907 pps
->pps_ActivePipe
= NULL
;
4908 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4910 actual
+= pp
->pp_IOReq
.iouh_Actual
;
4911 buffer
+= pp
->pp_IOReq
.iouh_Actual
;
4912 length
-= pp
->pp_IOReq
.iouh_Actual
;
4915 pps
->pps_Error
= ioerr
;
4916 if(ioerr
!= UHIOERR_TIMEOUT
)
4918 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4919 "Packet(%s) failed: %s (%ld)", (STRPTR
) "c",
4920 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4922 ReleaseSemaphore(&pps
->pps_AccessLock
);
4926 /* buffer remaining bytes */
4929 KPRINTF(1, ("BufAdd(%p, %ld)\n", buffer
, length
));
4930 /* only a few bytes left, so lets buffer them */
4931 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], length
);
4932 pps
->pps_BytesPending
+= length
;
4937 /* start sending out requests */
4938 KPRINTF(1, ("PlainWrite(%p, %ld)\n", buffer
, length
));
4939 Remove(&pp
->pp_Msg
.mn_Node
);
4940 psdSendPipe(pp
, buffer
, length
);
4941 pps
->pps_ActivePipe
= pp
;
4942 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4944 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4945 sigmask
= Wait(sigmask
);
4946 if(sigmask
& pps
->pps_AbortSigMask
)
4948 KPRINTF(1, ("Kill signal detected!\n"));
4949 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4957 ioerr
= psdWaitPipe(pp
);
4958 pps
->pps_ActivePipe
= NULL
;
4959 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4962 pps
->pps_Error
= ioerr
;
4963 if(ioerr
!= UHIOERR_TIMEOUT
)
4965 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4966 "Packet(%s) failed: %s (%ld)", (STRPTR
) "u",
4967 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4970 actual
= pp
->pp_IOReq
.iouh_Actual
;
4973 KPRINTF(2, ("No free pipe!\n"));
4976 ReleaseSemaphore(&pps
->pps_AccessLock
);
4982 /* /// "psdStreamFlush()" */
4983 AROS_LH1(LONG
, psdStreamFlush
,
4984 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4985 LIBBASETYPEPTR
, ps
, 76, psd
)
4993 KPRINTF(2, ("psdStreamFlush(%p)\n", pps
));
4998 ObtainSemaphore(&pps
->pps_AccessLock
);
5000 if(pps
->pps_Endpoint
->pep_Direction
)
5003 KPRINTF(2, ("Flushing in...\n"));
5004 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
5006 psdAbortPipe(pps
->pps_Pipes
[cnt
]);
5008 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
5010 psdWaitPipe(pps
->pps_Pipes
[cnt
]);
5012 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
5013 while(pp
->pp_Msg
.mn_Node
.ln_Succ
)
5015 Remove(&pp
->pp_Msg
.mn_Node
);
5016 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
5017 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
5019 while((pp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
5021 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
5023 pps
->pps_ReqBytes
= 0;
5024 pps
->pps_BytesPending
= 0;
5025 pps
->pps_Offset
= 0;
5029 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
5030 if(pp
->pp_Msg
.mn_Node
.ln_Succ
)
5033 if(pps
->pps_BytesPending
)
5035 KPRINTF(2, ("Flushing out %ld...\n", pps
->pps_BytesPending
));
5036 Remove(&pp
->pp_Msg
.mn_Node
);
5037 ioerr
= psdDoPipe(pp
, pps
->pps_Buffer
, pps
->pps_BytesPending
);
5038 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
5039 pps
->pps_BytesPending
= 0;
5042 pps
->pps_Error
= ioerr
;
5043 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamFlush",
5044 "Packet(%s) failed: %s (%ld)", (STRPTR
) "f",
5045 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
5049 KPRINTF(2, ("Nothing to flush\n"));
5053 ReleaseSemaphore(&pps
->pps_AccessLock
);
5059 /* /// "psdGetStreamError()" */
5060 AROS_LH1(LONG
, psdGetStreamError
,
5061 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
5062 LIBBASETYPEPTR
, ps
, 77, psd
)
5065 KPRINTF(1, ("psdGetStreamError(%p)\n", pps
));
5068 return((LONG
) pps
->pps_Error
);
5076 /* *** Realtime Iso */
5078 /* /// "psdAllocRTIsoHandler()" */
5079 AROS_LH2(struct PsdRTIsoHandler
*, psdAllocRTIsoHandlerA
,
5080 AROS_LHA(struct PsdEndpoint
*, pep
, A0
),
5081 AROS_LHA(struct TagItem
*, tags
, A1
),
5082 LIBBASETYPEPTR
, ps
, 93, psd
)
5085 struct PsdRTIsoHandler
*prt
;
5089 KPRINTF(2, ("psdAllocRTIso(%p, %p)\n", pep
, tags
));
5094 if(pep
->pep_TransType
!= USEAF_ISOCHRONOUS
)
5098 if(!(pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Capabilities
& UHCF_RT_ISO
))
5100 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Your HW controller driver does not support realtime iso transfers. Sorry.");
5103 if((prt
= psdAllocVec(sizeof(struct PsdRTIsoHandler
))))
5105 prt
->prt_Device
= pep
->pep_Interface
->pif_Config
->pc_Device
;
5106 prt
->prt_Endpoint
= pep
;
5107 prt
->prt_RTIso
.urti_OutPrefetch
= 2048;
5108 if((pp
= prt
->prt_Pipe
= psdAllocPipe(prt
->prt_Device
, (struct MsgPort
*) 0xffffffff, pep
)))
5110 pp
->pp_MsgPort
= pp
->pp_Msg
.mn_ReplyPort
= NULL
;
5111 psdSetAttrsA(PGA_RTISO
, prt
, tags
);
5112 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_ADDISOHANDLER
;
5113 pp
->pp_IOReq
.iouh_Data
= &prt
->prt_RTIso
;
5114 // hardware must support quick IO for this to work!
5115 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5119 AddTail(&prt
->prt_Device
->pd_RTIsoHandlers
, &prt
->prt_Node
);
5123 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5124 "Adding RT Iso Handler failed: %s (%ld)",
5125 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
5127 psdFreePipe(prt
->prt_Pipe
);
5136 /* /// "psdFreeRTIsoHandler()" */
5137 AROS_LH1(void, psdFreeRTIsoHandler
,
5138 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5139 LIBBASETYPEPTR
, ps
, 94, psd
)
5149 Remove(&prt
->prt_Node
);
5152 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_REMISOHANDLER
;
5153 DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5160 /* /// "psdStartRTIso()" */
5161 AROS_LH1(LONG
, psdStartRTIso
,
5162 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5163 LIBBASETYPEPTR
, ps
, 95, psd
)
5171 return UHIOERR_BADPARAMS
;
5174 if(pp
->pp_Device
->pd_Flags
& PDFF_SUSPENDED
)
5176 // make sure the device is up and running before trying to send a new pipe
5177 psdResumeDevice(pp
->pp_Device
);
5179 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_STARTRTISO
;
5180 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5183 ++pp
->pp_Device
->pd_IOBusyCount
;
5190 /* /// "psdStopRTIso()" */
5191 AROS_LH1(LONG
, psdStopRTIso
,
5192 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5193 LIBBASETYPEPTR
, ps
, 96, psd
)
5201 return UHIOERR_BADPARAMS
;
5204 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_STOPRTISO
;
5205 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5208 --pp
->pp_Device
->pd_IOBusyCount
;
5215 /* *** Classes *** */
5217 /* /// "psdAddClass()" */
5218 AROS_LH2(struct PsdUsbClass
*, psdAddClass
,
5219 AROS_LHA(STRPTR
, name
, A1
),
5220 AROS_LHA(ULONG
, vers
, D0
),
5221 LIBBASETYPEPTR
, ps
, 35, psd
)
5224 struct Library
*cls
= NULL
;
5225 struct PsdUsbClass
*puc
;
5229 STRPTR origname
= name
;
5230 STRPTR evilmsg
[8] = { "Say hello to %s V%ld.%ld (%s).",
5231 "Whoah! %s V%ld.%ld surprised as %s.",
5232 "The door bell rang for %s V%ld.%ld (%s).",
5233 "Welcome %s V%ld.%ld (%s) to the party.",
5235 "Don't laugh at %s V%ld.%ld for %s.",
5236 "Time has come for %s V%ld.%ld (%s) to join the show.",
5237 "Start blaming %s V%ld.%ld for helping at %s.",
5238 "Ain't %s V%ld.%ld useful for %s?" };
5240 KPRINTF(5, ("psdAddClass(%s, %ld)\n", name
, vers
));
5244 if((cls
= OpenLibrary(name
, vers
)))
5250 if((*name
== '/') || (*name
== ':'))
5260 if(FindName(&ps
->ps_Classes
, cls
->lib_Node
.ln_Name
))
5263 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5264 "Attempted to add class %s twice. Nothing is good enough for people like you.",
5266 KPRINTF(20, ("attempt to add class twice!\n"));
5271 if((puc
= psdAllocVec(sizeof(struct PsdUsbClass
))))
5274 puc
->puc_ClassBase
= cls
;
5275 puc
->puc_Node
.ln_Name
= puc
->puc_ClassName
= psdCopyStr(cls
->lib_Node
.ln_Name
);
5276 puc
->puc_FullPath
= psdCopyStr(origname
);
5278 usbGetAttrs(UGA_CLASS
, NULL
,
5279 UCCA_Priority
, &pri
,
5280 UCCA_Description
, &desc
,
5283 puc
->puc_Node
.ln_Pri
= pri
;
5284 psdLockWritePBase();
5285 Enqueue(&ps
->ps_Classes
, &puc
->puc_Node
);
5287 msgoff
= ps
->ps_FunnyCount
++ & 7;
5289 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5291 cls
->lib_Node
.ln_Name
, cls
->lib_Version
, cls
->lib_Revision
, desc
);
5292 psdSendEvent(EHMB_ADDCLASS
, puc
, NULL
);
5302 /* /// "psdRemClass()" */
5303 AROS_LH1(void, psdRemClass
,
5304 AROS_LHA(struct PsdUsbClass
*, puc
, A1
),
5305 LIBBASETYPEPTR
, ps
, 36, psd
)
5308 KPRINTF(5, ("psdRemClass(%p)\n", puc
));
5309 psdLockWritePBase();
5310 Remove(&puc
->puc_Node
);
5313 /* Check if there are still bindings remaining */
5314 while(puc
->puc_UseCnt
)
5316 struct PsdDevice
*pd
;
5317 struct PsdConfig
*pc
;
5318 struct PsdInterface
*pif
;
5320 KPRINTF(20, ("This should never happen: Class %s still in use (%ld), can't close!\n",
5321 puc
->puc_ClassBase
->lib_Node
.ln_Name
, puc
->puc_UseCnt
));
5323 /* Well, try to release the open bindings in a best effort attempt */
5326 while((pd
= psdGetNextDevice(pd
)))
5328 if(pd
->pd_DevBinding
&& (pd
->pd_ClsBinding
== puc
) && (!(pd
->pd_Flags
& PDFF_APPBINDING
)))
5331 psdReleaseDevBinding(pd
);
5333 pd
= NULL
; /* restart */
5336 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5337 while(pc
->pc_Node
.ln_Succ
)
5339 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5340 while(pif
->pif_Node
.ln_Succ
)
5342 if(pif
->pif_IfBinding
&& (pif
->pif_ClsBinding
== puc
))
5345 psdReleaseIfBinding(pif
);
5347 pd
= NULL
; /* restart */
5350 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5352 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5358 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
5359 "This should never happen! Class %s still in use (cnt=%ld). Could not get rid of it! Sorry, we're broke.",
5360 puc
->puc_ClassBase
->lib_Node
.ln_Name
, puc
->puc_UseCnt
);
5362 /*psdDelayMS(2000);*/
5365 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5366 "I shot class %s, but I didn't kill the deputy.",
5367 puc
->puc_ClassBase
->lib_Node
.ln_Name
);
5368 CloseLibrary(puc
->puc_ClassBase
);
5369 psdFreeVec(puc
->puc_ClassName
);
5370 psdFreeVec(puc
->puc_FullPath
);
5372 psdSendEvent(EHMB_REMCLASS
, puc
, NULL
);
5377 /* *** Error Msgs *** */
5379 /* /// "psdAddErrorMsgA()" */
5380 AROS_LH4(struct PsdErrorMsg
*, psdAddErrorMsgA
,
5381 AROS_LHA(UWORD
, level
, D0
),
5382 AROS_LHA(STRPTR
, origin
, A0
),
5383 AROS_LHA(STRPTR
, fmtstr
, A1
),
5384 AROS_LHA(RAWARG
, fmtdata
, A2
),
5385 LIBBASETYPEPTR
, ps
, 40, psd
)
5388 struct PsdErrorMsg
*pem
;
5389 if(((!ps
->ps_GlobalCfg
->pgc_LogInfo
) && (level
< RETURN_WARN
)) ||
5390 ((!ps
->ps_GlobalCfg
->pgc_LogWarning
) && (level
>= RETURN_WARN
) && (level
< RETURN_ERROR
)) ||
5391 ((!ps
->ps_GlobalCfg
->pgc_LogError
) && (level
>= RETURN_ERROR
) && (level
< RETURN_FAIL
)) ||
5392 ((!ps
->ps_GlobalCfg
->pgc_LogFailure
) && (level
>= RETURN_FAIL
)))
5396 if((pem
= psdAllocVec(sizeof(struct PsdErrorMsg
))))
5399 pem
->pem_Level
= level
;
5400 if((pem
->pem_Origin
= psdCopyStr(origin
)))
5402 if((pem
->pem_Msg
= psdCopyStrFmtA(fmtstr
, fmtdata
)))
5404 if (ps
->ps_Flags
& PSF_KLOG
) {
5405 KPrintF("[%s] %s\n", origin
, pem
->pem_Msg
);
5410 DateStamp(&pem
->pem_DateStamp
);
5412 struct timerequest tr
= ps
->ps_TimerIOReq
;
5413 tr
.tr_node
.io_Command
= TR_GETSYSTIME
;
5414 DoIO((struct IORequest
*) &tr
);
5415 pem
->pem_DateStamp
.ds_Days
= tr
.tr_time
.tv_secs
/ (24*60*60);
5416 pem
->pem_DateStamp
.ds_Minute
= (tr
.tr_time
.tv_secs
/ 60) % 60;
5417 pem
->pem_DateStamp
.ds_Tick
= (tr
.tr_time
.tv_secs
% 60) * 50;
5420 AddTail(&ps
->ps_ErrorMsgs
, &pem
->pem_Node
);
5422 psdSendEvent(EHMB_ADDERRORMSG
, pem
, NULL
);
5425 psdFreeVec(pem
->pem_Origin
);
5434 /* /// "psdRemErrorMsg()" */
5435 AROS_LH1(void, psdRemErrorMsg
,
5436 AROS_LHA(struct PsdErrorMsg
*, pem
, A0
),
5437 LIBBASETYPEPTR
, ps
, 41, psd
)
5440 KPRINTF(1, ("psdRemErrorMsg()\n"));
5442 Remove(&pem
->pem_Node
);
5444 psdFreeVec(pem
->pem_Origin
);
5445 psdFreeVec(pem
->pem_Msg
);
5447 psdSendEvent(EHMB_REMERRORMSG
, pem
, NULL
);
5452 /* *** Bindings *** */
5454 /* /// "psdClassScan()" */
5455 AROS_LH0(void, psdClassScan
,
5456 LIBBASETYPEPTR
, ps
, 37, psd
)
5459 struct PsdHardware
*phw
;
5460 struct PsdDevice
*pd
;
5461 struct PsdUsbClass
*puc
;
5465 if((FindTask(NULL
)->tc_Node
.ln_Type
!= NT_PROCESS
) && (!ps
->ps_ConfigRead
))
5467 // it's the first time we were reading the config and DOS was not available
5468 ps
->ps_StartedAsTask
= TRUE
;
5471 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5472 if(!puc
->puc_Node
.ln_Succ
)
5474 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "ClassScan attempted with no classes installed!");
5479 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
5480 while(phw
->phw_Node
.ln_Succ
)
5482 if((pd
= phw
->phw_RootDevice
))
5484 // for the root, do it ourselves, the rest is done by each hub task
5485 psdHubClassScan(pd
);
5487 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
5490 //psdSendEvent(EHMB_CLSSCANRDY, NULL, NULL);
5491 KPRINTF(5, ("************ Scanning finished!\n"));
5496 /* /// "psdDoHubMethodA()" */
5497 AROS_LH3(LONG
, psdDoHubMethodA
,
5498 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5499 AROS_LHA(ULONG
, methodid
, D0
),
5500 AROS_LHA(APTR
, methoddata
, A1
),
5501 LIBBASETYPEPTR
, ps
, 92, psd
)
5504 struct PsdUsbClass
*puc
;
5505 KPRINTF(2, ("psdDoHubMethodA(%p)\n", pd
));
5511 if((pd
->pd_Hub
->pd_DevBinding
) && (puc
= pd
->pd_Hub
->pd_ClsBinding
))
5513 return(usbDoMethodA(methodid
, methoddata
));
5522 /* /// "psdClaimAppBindingA()" */
5523 AROS_LH1(struct PsdAppBinding
*, psdClaimAppBindingA
,
5524 AROS_LHA(struct TagItem
*, tags
, A1
),
5525 LIBBASETYPEPTR
, ps
, 45, psd
)
5528 struct PsdDevice
*pd
;
5529 struct PsdConfig
*pc
;
5530 struct PsdInterface
*pif
;
5531 struct PsdDevice
*hubpd
;
5532 struct PsdAppBinding tmppab
;
5533 struct PsdAppBinding
*pab
= NULL
;
5534 struct PsdUsbClass
*puc
;
5538 KPRINTF(2, ("psdClaimAppBindingA(%p)\n", tags
));
5540 tmppab
.pab_Device
= NULL
;
5541 tmppab
.pab_ReleaseHook
= NULL
;
5542 tmppab
.pab_Task
= NULL
;
5543 tmppab
.pab_ForceRelease
= FALSE
;
5544 psdSetAttrsA(PGA_APPBINDING
, &tmppab
, tags
);
5545 if(tmppab
.pab_Device
&& tmppab
.pab_ReleaseHook
)
5547 pd
= tmppab
.pab_Device
;
5549 // force release of other bindings first
5550 if(tmppab
.pab_ForceRelease
)
5552 /* If there are bindings, get rid of them. */
5553 if(pd
->pd_DevBinding
)
5555 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5556 "%s really wants to bind to %s, so I'm letting the old binding go.",
5557 FindTask(NULL
)->tc_Node
.ln_Name
,
5560 psdReleaseDevBinding(pd
);
5562 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5563 while(pc
->pc_Node
.ln_Succ
)
5565 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5566 while(pif
->pif_Node
.ln_Succ
)
5568 if(pif
->pif_IfBinding
)
5570 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5571 "%s really wants to bind to %s, so I'm letting the old binding go.",
5572 FindTask(NULL
)->tc_Node
.ln_Name
,
5574 psdReleaseIfBinding(pif
);
5576 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5578 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5583 if(!hubpd
) // claim app binding at the root hub -- improbable, but possible.
5585 pab
= psdHubClaimAppBindingA(tags
);
5587 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5589 pab
= (struct PsdAppBinding
*) usbDoMethod(UCM_HubClaimAppBinding
, binding
, tags
);
5594 // fill in task names
5595 pab
->pab_Task
= FindTask(NULL
);
5596 pab
->pab_Node
.ln_Name
= pab
->pab_Task
->tc_Node
.ln_Name
;
5597 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5606 /* /// "psdReleaseAppBinding()" */
5607 AROS_LH1(void, psdReleaseAppBinding
,
5608 AROS_LHA(struct PsdAppBinding
*, pab
, A0
),
5609 LIBBASETYPEPTR
, ps
, 46, psd
)
5612 struct PsdDevice
*pd
;
5613 struct PsdDevice
*hubpd
;
5614 struct PsdUsbClass
*puc
;
5617 KPRINTF(2, ("psdReleaseAppBinding(%p)\n", pab
));
5621 pd
= pab
->pab_Device
;
5623 if(!hubpd
) // release binding of hub (improbable)
5625 psdHubReleaseDevBinding(pd
);
5628 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5630 usbDoMethod(UCM_HubReleaseDevBinding
, binding
, pd
);
5637 /* /// "psdReleaseDevBinding()" */
5638 AROS_LH1(void, psdReleaseDevBinding
,
5639 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5640 LIBBASETYPEPTR
, ps
, 50, psd
)
5643 struct PsdUsbClass
*puc
;
5644 struct PsdDevice
*hubpd
;
5647 KPRINTF(5, ("psdReleaseDevBinding(%p)\n", pd
));
5648 if(pd
->pd_DevBinding
)
5651 if(!hubpd
) // release binding of hub
5653 psdHubReleaseDevBinding(pd
);
5656 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5658 usbDoMethod(UCM_HubReleaseDevBinding
, binding
, pd
);
5665 /* /// "psdReleaseIfBinding()" */
5666 AROS_LH1(void, psdReleaseIfBinding
,
5667 AROS_LHA(struct PsdInterface
*, pif
, A0
),
5668 LIBBASETYPEPTR
, ps
, 51, psd
)
5671 struct PsdUsbClass
*puc
;
5672 struct PsdDevice
*hubpd
;
5675 KPRINTF(5, ("psdReleaseIfBinding(%p)\n", pif
));
5676 if(pif
->pif_IfBinding
&& pif
->pif_ClsBinding
)
5678 hubpd
= pif
->pif_Config
->pc_Device
->pd_Hub
;
5679 if(!hubpd
) // release binding of hub (improbable)
5681 psdHubReleaseIfBinding(pif
);
5684 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5686 usbDoMethod(UCM_HubReleaseIfBinding
, binding
, pif
);
5693 /* /// "psdUnbindAll()" */
5694 AROS_LH0(void, psdUnbindAll
,
5695 LIBBASETYPEPTR
, ps
, 61, psd
)
5698 struct PsdHardware
*phw
;
5699 struct PsdDevice
*pd
;
5700 struct PsdConfig
*pc
;
5701 struct PsdInterface
*pif
;
5704 KPRINTF(10, ("pUnbindAll()\n"));
5705 /* FIXME What happens if devices or hardware gets removed during the process? Need notify semaphore */
5710 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
5711 while(phw
->phw_Node
.ln_Succ
)
5713 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
5714 while(pd
->pd_Node
.ln_Succ
)
5716 /* If there are bindings, get rid of them. */
5717 if(pd
->pd_DevBinding
)
5720 psdReleaseDevBinding(pd
);
5725 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5726 while(pc
->pc_Node
.ln_Succ
)
5728 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5729 while(pif
->pif_Node
.ln_Succ
)
5731 if(pif
->pif_IfBinding
)
5734 psdReleaseIfBinding(pif
);
5739 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5745 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5751 pd
= (struct PsdDevice
*) pd
->pd_Node
.ln_Succ
;
5757 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
5765 /* /// "psdHubClassScan()" */
5766 AROS_LH1(void, psdHubClassScan
,
5767 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5768 LIBBASETYPEPTR
, ps
, 82, psd
)
5771 struct PsdUsbClass
*puc
;
5772 struct PsdConfig
*pc
;
5773 struct PsdInterface
*pif
;
5774 struct PsdInterface
*firstpif
;
5775 struct PsdPipe
*pp
= NULL
;
5782 KPRINTF(5, ("psdClassScan()\n"));
5784 if(!(mp
= CreateMsgPort()))
5789 psdLockWriteDevice(pd
);
5790 while(!(pd
->pd_PoPoCfg
.poc_NoClassBind
|| pd
->pd_DevBinding
))
5792 if(!(pp
= psdAllocPipe(pd
, mp
, NULL
)))
5796 KPRINTF(5, ("Doing ClassScan on Device: %s\n", pd
->pd_ProductStr
));
5798 /* First look if there is any interface binding. We may not change
5799 the current config in this case! */
5800 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5801 while(pc
->pc_Node
.ln_Succ
)
5803 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5805 while(pif
->pif_Node
.ln_Succ
)
5807 if(pif
->pif_IfBinding
)
5809 hasifbinding
= pc
->pc_CfgNum
;
5812 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5814 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5817 owner
= psdGetForcedBinding(pd
->pd_IDString
, NULL
);
5818 if((!hasifbinding
) && owner
)
5820 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5821 while(puc
->puc_Node
.ln_Succ
)
5823 if(!strcmp(owner
, puc
->puc_ClassName
))
5825 if((pd
->pd_DevBinding
= (APTR
) usbDoMethod(UCM_ForceDeviceBinding
, pd
)))
5827 pd
->pd_ClsBinding
= puc
;
5829 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5831 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5832 "Forced device binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5836 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5838 /* no more scanning required, abort here */
5842 /* Second attempt */
5843 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5844 while(pc
->pc_Node
.ln_Succ
)
5846 if((!hasifbinding
) || (hasifbinding
== pc
->pc_CfgNum
))
5848 /* If the current config is not the one selected, change it */
5849 if(pd
->pd_CurrCfg
!= pc
->pc_CfgNum
)
5851 psdSetDeviceConfig(pp
, pc
->pc_CfgNum
);
5853 KPRINTF(5, (" Config %ld\n", pc
->pc_CfgNum
));
5854 /* If something went wrong above, we must exclude this config */
5855 if(pd
->pd_CurrCfg
== pc
->pc_CfgNum
)
5857 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5858 while(pif
->pif_Node
.ln_Succ
)
5860 KPRINTF(5, (" Interface %ld\n", pif
->pif_IfNum
));
5863 if(!pif
->pif_IfBinding
)
5868 if(!psdSetAltInterface(pp
, pif
))
5870 pif
->pif_IfBinding
= NULL
;
5871 /* Okay, this alternate setting failed. Try to get next one */
5874 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5875 if(pif
->pif_Node
.ln_Succ
)
5877 KPRINTF(5, ("CONT!\n"));
5880 KPRINTF(5, ("BREAK!\n"));
5886 owner
= psdGetForcedBinding(pd
->pd_IDString
, pif
->pif_IDString
);
5887 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5888 while(puc
->puc_Node
.ln_Succ
)
5890 KPRINTF(5, (">>>PING %s!\n", puc
->puc_ClassName
));
5893 if(!strcmp(owner
, puc
->puc_ClassName
))
5895 binding
= (APTR
) usbDoMethod(UCM_ForceInterfaceBinding
, pif
);
5898 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5899 "Forced interface binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5904 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5908 binding
= (APTR
) usbDoMethod(UCM_AttemptInterfaceBinding
, pif
);
5911 KPRINTF(5, ("<<<PONG!!\n"));
5914 KPRINTF(5, ("Got binding!\n"));
5915 /* Find root config structure */
5916 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5917 while(pif
->pif_Node
.ln_Succ
)
5919 if(pif
->pif_IfNum
== firstpif
->pif_IfNum
)
5923 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5925 if(!pif
->pif_Node
.ln_Succ
)
5927 KPRINTF(5, ("Fucked it up!\n"));
5928 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Something incredibly stupid happend. I've given up.");
5932 pif
->pif_IfBinding
= binding
;
5933 pif
->pif_ClsBinding
= puc
;
5934 hasifbinding
= pc
->pc_CfgNum
;
5936 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5941 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5947 //break; /* FIXME: DISABLED ALTSCANNING */
5948 /* Check alternate setting */
5949 if(pif
->pif_AlterIfs
.lh_Head
->ln_Succ
)
5951 /* There are some alternative interfaces, start at top */
5952 pif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
5955 } while(pif
!= firstpif
);
5956 //pif->pif_IfBinding = binding;
5959 psdSetAltInterface(pp
, pif
);
5961 /* Hohum, search current main interface then */
5962 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5963 while(pif
->pif_Node
.ln_Succ
)
5965 if(pif
->pif_IfNum
== firstpif
->pif_IfNum
)
5969 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5972 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5976 KPRINTF(5, ("End, next ConfigCheck!\n"));
5977 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5979 /* Could not establish interface binding, try device binding then */
5983 //pd->pd_DevBinding = (APTR) ~0UL;
5985 owner
= psdGetForcedBinding(pd
->pd_IDString
, NULL
);
5986 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5987 while(puc
->puc_Node
.ln_Succ
)
5992 if(!strcmp(owner
, puc
->puc_ClassName
))
5994 binding
= (APTR
) usbDoMethod(UCM_ForceDeviceBinding
, pd
, TAG_END
);
5997 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5998 "Forced device binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
6003 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6007 binding
= (APTR
) usbDoMethod(UCM_AttemptDeviceBinding
, pd
);
6011 pd
->pd_DevBinding
= binding
;
6012 pd
->pd_ClsBinding
= puc
;
6014 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
6017 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6019 pd
->pd_DevBinding
= binding
;
6027 // call hub class scan code
6028 if((binding
= pd
->pd_DevBinding
) && (puc
= pd
->pd_ClsBinding
))
6030 usbDoMethod(UCM_HubClassScan
, binding
);
6032 psdUnlockDevice(pd
);
6039 /* /// "psdHubClaimAppBindingA()" */
6040 AROS_LH1(struct PsdAppBinding
*, psdHubClaimAppBindingA
,
6041 AROS_LHA(struct TagItem
*, tags
, A1
),
6042 LIBBASETYPEPTR
, ps
, 83, psd
)
6045 struct PsdDevice
*pd
;
6046 struct PsdAppBinding
*pab
;
6047 struct PsdConfig
*pc
;
6048 struct PsdInterface
*pif
;
6050 BOOL hasbinding
= FALSE
;
6051 KPRINTF(2, ("psdHubClaimAppBindingA(%p)\n", tags
));
6053 if((pab
= psdAllocVec(sizeof(struct PsdAppBinding
))))
6055 psdSetAttrsA(PGA_APPBINDING
, pab
, tags
);
6056 if(pab
->pab_Device
&& pab
->pab_ReleaseHook
)
6058 pd
= pab
->pab_Device
;
6059 if(pd
->pd_DevBinding
)
6063 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
6064 while(pc
->pc_Node
.ln_Succ
)
6066 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
6068 while(pif
->pif_Node
.ln_Succ
)
6070 if(pif
->pif_IfBinding
)
6075 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
6077 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
6082 pd
->pd_Flags
|= PDFF_APPBINDING
;
6083 pd
->pd_DevBinding
= pab
;
6084 pd
->pd_ClsBinding
= NULL
;
6095 /* /// "psdHubReleaseDevBinding()" */
6096 AROS_LH1(void, psdHubReleaseDevBinding
,
6097 AROS_LHA(struct PsdDevice
*, pd
, A0
),
6098 LIBBASETYPEPTR
, ps
, 84, psd
)
6101 struct PsdUsbClass
*puc
;
6103 struct PsdAppBinding
*pab
;
6105 KPRINTF(5, ("psdHubReleaseDevBinding(%p)\n", pd
));
6108 psdLockWriteDevice(pd
);
6109 if((binding
= pd
->pd_DevBinding
))
6111 pd
->pd_DevBinding
= NULL
;
6112 if(pd
->pd_Flags
& PDFF_APPBINDING
)
6114 pab
= (struct PsdAppBinding
*) binding
;
6115 CallHookPkt(pab
->pab_ReleaseHook
, pab
, (APTR
) pab
->pab_UserData
);
6116 pd
->pd_ClsBinding
= NULL
;
6117 pd
->pd_Flags
&= ~PDFF_APPBINDING
;
6119 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6121 puc
= pd
->pd_ClsBinding
;
6124 pd
->pd_ClsBinding
= NULL
;
6125 usbDoMethod(UCM_ReleaseDeviceBinding
, binding
);
6127 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6131 psdUnlockDevice(pd
);
6137 /* /// "psdHubReleaseIfBinding()" */
6138 AROS_LH1(void, psdHubReleaseIfBinding
,
6139 AROS_LHA(struct PsdInterface
*, pif
, A0
),
6140 LIBBASETYPEPTR
, ps
, 85, psd
)
6143 struct PsdUsbClass
*puc
;
6144 struct PsdDevice
*pd
;
6147 KPRINTF(5, ("psdHubReleaseIfBinding(%p)\n", pif
));
6151 pd
= pif
->pif_Config
->pc_Device
;
6152 psdLockWriteDevice(pd
);
6153 if((binding
= pif
->pif_IfBinding
))
6155 pif
->pif_IfBinding
= NULL
;
6156 puc
= pif
->pif_ClsBinding
;
6159 pif
->pif_ClsBinding
= NULL
;
6160 usbDoMethod(UCM_ReleaseInterfaceBinding
, binding
);
6163 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6165 psdUnlockDevice(pd
);
6171 /* *** Events *** */
6173 /* /// "psdAddEventHandler()" */
6174 AROS_LH2(struct PsdEventHook
*, psdAddEventHandler
,
6175 AROS_LHA(struct MsgPort
*, mp
, A1
),
6176 AROS_LHA(ULONG
, msgmask
, D0
),
6177 LIBBASETYPEPTR
, ps
, 47, psd
)
6180 struct PsdEventHook
*peh
= NULL
;
6182 KPRINTF(5, ("psdAddEventHandler(%p, %p)\n", mp
, msgmask
));
6186 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6187 if((peh
= psdAllocVec(sizeof(struct PsdEventHook
))))
6189 peh
->peh_MsgPort
= mp
;
6190 peh
->peh_MsgMask
= msgmask
;
6191 AddTail(&ps
->ps_EventHooks
, &peh
->peh_Node
);
6193 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6200 /* /// "psdRemEventHandler()" */
6201 AROS_LH1(void, psdRemEventHandler
,
6202 AROS_LHA(struct PsdEventHook
*, peh
, A0
),
6203 LIBBASETYPEPTR
, ps
, 48, psd
)
6206 struct Message
*msg
;
6208 KPRINTF(5, ("psdRemEventHandler(%p)\n", peh
));
6213 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6214 Remove(&peh
->peh_Node
);
6215 while((msg
= GetMsg(peh
->peh_MsgPort
)))
6219 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6220 pGarbageCollectEvents(ps
);
6226 /* /// "psdSendEvent()" */
6227 AROS_LH3(void, psdSendEvent
,
6228 AROS_LHA(ULONG
, ehmt
, D0
),
6229 AROS_LHA(APTR
, param1
, A0
),
6230 AROS_LHA(APTR
, param2
, A1
),
6231 LIBBASETYPEPTR
, ps
, 49, psd
)
6234 struct PsdEventNote
*pen
;
6235 struct PsdEventHook
*peh
;
6236 ULONG msgmask
= (1L<<ehmt
);
6238 KPRINTF(1, ("psdSendEvent(%p, %p, %p)\n", ehmt
, param1
, param2
));
6240 pGarbageCollectEvents(ps
);
6241 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6242 peh
= (struct PsdEventHook
*) ps
->ps_EventHooks
.lh_Head
;
6243 while(peh
->peh_Node
.ln_Succ
)
6245 if(peh
->peh_MsgMask
& msgmask
)
6247 if((pen
= psdAllocVec(sizeof(struct PsdEventNote
))))
6249 pen
->pen_Msg
.mn_ReplyPort
= &ps
->ps_EventReplyPort
;
6250 pen
->pen_Msg
.mn_Length
= sizeof(struct PsdEventNote
);
6251 pen
->pen_Event
= ehmt
;
6252 pen
->pen_Param1
= param1
;
6253 pen
->pen_Param2
= param2
;
6254 PutMsg(peh
->peh_MsgPort
, &pen
->pen_Msg
);
6257 peh
= (struct PsdEventHook
*) peh
->peh_Node
.ln_Succ
;
6259 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6264 /* *** Configuration *** */
6266 /* /// "psdReadCfg()" */
6267 AROS_LH2(BOOL
, psdReadCfg
,
6268 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6269 AROS_LHA(APTR
, formdata
, A1
),
6270 LIBBASETYPEPTR
, ps
, 52, psd
)
6273 struct PsdIFFContext
*subpic
;
6276 ULONG
*buf
= formdata
;
6278 KPRINTF(10, ("psdReadCfg(%p, %p)\n", pic
, formdata
));
6280 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6283 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6284 if(!(pic
->pic_Node
.ln_Succ
))
6286 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6290 if((AROS_LONG2BE(*buf
) != ID_FORM
) || (AROS_LONG2BE(buf
[2]) != pic
->pic_FormID
))
6292 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to replace a cfg form with a chunk or with an alien form!");
6293 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6296 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6297 while(subpic
->pic_Node
.ln_Succ
)
6299 pFreeForm(ps
, subpic
);
6300 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6302 pic
->pic_ChunksLen
= 0;
6303 len
= (AROS_LONG2BE(buf
[1]) - 3) & ~1UL;
6307 if(!(pAddCfgChunk(ps
, pic
, buf
)))
6311 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
6313 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
6317 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to add a nasty corrupted FORM chunk! Configuration is probably b0rken!");
6321 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6322 ps
->ps_CheckConfigReq
= TRUE
;
6328 /* /// "psdLoadCfgFromDisk()" */
6329 AROS_LH1(BOOL
, psdLoadCfgFromDisk
,
6330 AROS_LHA(STRPTR
, filename
, A1
),
6331 LIBBASETYPEPTR
, ps
, 79, psd
)
6335 BOOL loaded
= FALSE
;
6340 XPRINTF(10, ("Loading config file: %s\n", filename
));
6344 loaded
= psdLoadCfgFromDisk("ENV:Sys/poseidon.prefs");
6350 loaded
= psdLoadCfgFromDisk("ENVARC:Sys/poseidon.prefs");
6357 KPRINTF(1, ("dos.library not available yet\n"));
6361 filehandle
= Open(filename
, MODE_OLDFILE
);
6362 KPRINTF(1, ("File handle 0x%p\n", filehandle
));
6365 if(Read(filehandle
, formhead
, 12) == 12)
6367 KPRINTF(1, ("Read header\n"));
6368 if((AROS_LONG2BE(formhead
[0]) == ID_FORM
) && (AROS_LONG2BE(formhead
[2]) == IFFFORM_PSDCFG
))
6370 formlen
= AROS_LONG2BE(formhead
[1]);
6371 KPRINTF(1, ("Header OK, %lu bytes\n", formlen
));
6373 buf
= (ULONG
*) psdAllocVec(formlen
+ 8);
6376 buf
[0] = formhead
[0];
6377 buf
[1] = formhead
[1];
6378 buf
[2] = formhead
[2];
6379 if(Read(filehandle
, &buf
[3], formlen
- 4) == formlen
- 4)
6381 KPRINTF(1, ("Data read OK\n"));
6383 psdReadCfg(NULL
, buf
);
6386 KPRINTF(1, ("All done\n"));
6395 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6396 "Failed to load config from '%s'!",
6401 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
;
6408 /* /// "psdSaveCfgToDisk()" */
6409 AROS_LH2(BOOL
, psdSaveCfgToDisk
,
6410 AROS_LHA(STRPTR
, filename
, A1
),
6411 AROS_LHA(BOOL
, executable
, D0
),
6412 LIBBASETYPEPTR
, ps
, 80, psd
)
6421 saved
= psdSaveCfgToDisk("ENVARC:Sys/poseidon.prefs", FALSE
);
6422 saved
&= psdSaveCfgToDisk("ENV:Sys/poseidon.prefs", FALSE
);
6430 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6432 buf
= (ULONG
*) psdWriteCfg(NULL
);
6436 filehandle
= Open(filename
, MODE_NEWFILE
);
6439 Write(filehandle
, buf
, (AROS_LONG2BE(buf
[1])+9) & ~1UL);
6443 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6444 "Failed to write config to '%s'!",
6449 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6452 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
;
6459 /* /// "psdWriteCfg()" */
6460 AROS_LH1(APTR
, psdWriteCfg
,
6461 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6462 LIBBASETYPEPTR
, ps
, 53, psd
)
6468 KPRINTF(10, ("psdWriteCfg(%p)\n", pic
));
6470 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6473 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6474 if(!(pic
->pic_Node
.ln_Succ
))
6476 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6480 pUpdateGlobalCfg(ps
, pic
);
6481 ps
->ps_CheckConfigReq
= TRUE
;
6482 len
= pGetFormLength(pic
);
6483 if((buf
= psdAllocVec(len
)))
6485 pInternalWriteForm(pic
, buf
);
6487 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6493 /* /// "psdFindCfgForm()" */
6494 AROS_LH2(struct PsdIFFContext
*, psdFindCfgForm
,
6495 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6496 AROS_LHA(ULONG
, formid
, D0
),
6497 LIBBASETYPEPTR
, ps
, 54, psd
)
6500 struct PsdIFFContext
*subpic
;
6502 KPRINTF(160, ("psdFindCfgForm(0x%p, 0x%08lx)\n", pic
, formid
));
6503 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6506 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6507 if(!(pic
->pic_Node
.ln_Succ
))
6509 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6513 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6514 while(subpic
->pic_Node
.ln_Succ
)
6516 if(subpic
->pic_FormID
== formid
)
6518 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6521 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
6523 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6529 /* /// "psdNextCfgForm()" */
6530 AROS_LH1(struct PsdIFFContext
*, psdNextCfgForm
,
6531 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6532 LIBBASETYPEPTR
, ps
, 55, psd
)
6536 KPRINTF(160, ("psdNextCfgForm(%p)\n", pic
));
6542 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6543 formid
= pic
->pic_FormID
;
6544 pic
= (struct PsdIFFContext
*) pic
->pic_Node
.ln_Succ
;
6545 while(pic
->pic_Node
.ln_Succ
)
6547 if(pic
->pic_FormID
== formid
)
6549 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6551 KPRINTF(1, ("Found context 0x%p\n", pic
));
6554 pic
= (struct PsdIFFContext
*) pic
->pic_Node
.ln_Succ
;
6556 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6562 /* /// "psdAllocCfgForm()" */
6563 AROS_LH1(struct PsdIFFContext
*, psdAllocCfgForm
,
6564 AROS_LHA(ULONG
, formid
, D0
),
6565 LIBBASETYPEPTR
, ps
, 86, psd
)
6568 struct PsdIFFContext
*pic
;
6569 KPRINTF(10, ("psdAllocCfgForm(%p)\n", formid
));
6570 if((pic
= psdAllocVec(sizeof(struct PsdIFFContext
))))
6572 NewList(&pic
->pic_SubForms
);
6573 //pic->pic_Parent = parent;
6574 pic
->pic_FormID
= formid
;
6575 pic
->pic_FormLength
= 4;
6576 pic
->pic_Chunks
= NULL
;
6577 pic
->pic_ChunksLen
= 0;
6578 pic
->pic_BufferLen
= 0;
6580 AddTail(&ps
->ps_AlienConfigs
, &pic
->pic_Node
);
6588 /* /// "psdRemCfgForm()" */
6589 AROS_LH1(void, psdRemCfgForm
,
6590 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6591 LIBBASETYPEPTR
, ps
, 56, psd
)
6594 KPRINTF(10, ("psdRemCfgForm(%p)\n", pic
));
6596 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6599 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6600 if(!(pic
->pic_Node
.ln_Succ
))
6602 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6607 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6608 ps
->ps_CheckConfigReq
= TRUE
;
6613 /* /// "psdAddCfgEntry()" */
6614 AROS_LH2(struct PsdIFFContext
*, psdAddCfgEntry
,
6615 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6616 AROS_LHA(APTR
, formdata
, A1
),
6617 LIBBASETYPEPTR
, ps
, 57, psd
)
6620 struct PsdIFFContext
*res
;
6622 KPRINTF(10, ("psdAddCfgEntry(%p, %p)\n", pic
, formdata
));
6623 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6626 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6627 if(!(pic
->pic_Node
.ln_Succ
))
6629 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6633 res
= pAddCfgChunk(ps
, pic
, formdata
);
6634 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6635 ps
->ps_CheckConfigReq
= TRUE
;
6641 /* /// "psdRemCfgChunk()" */
6642 AROS_LH2(BOOL
, psdRemCfgChunk
,
6643 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6644 AROS_LHA(ULONG
, chnkid
, D0
),
6645 LIBBASETYPEPTR
, ps
, 58, psd
)
6650 KPRINTF(10, ("psdRemCfgChunk(%p, %p)\n", pic
, chnkid
));
6651 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6654 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6655 if(!(pic
->pic_Node
.ln_Succ
))
6657 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6663 res
= pRemCfgChunk(ps
, pic
, chnkid
);
6665 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6666 while(subpic
->pic_Node
.ln_Succ
)
6668 pFreeForm(ps
, subpic
);
6670 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6672 if(pic
->pic_ChunksLen
)
6676 pic
->pic_ChunksLen
= 0;
6677 pic
->pic_FormLength
= 4;
6680 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6681 ps
->ps_CheckConfigReq
= TRUE
;
6687 /* /// "psdGetCfgChunk()" */
6688 AROS_LH2(APTR
, psdGetCfgChunk
,
6689 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6690 AROS_LHA(ULONG
, chnkid
, D0
),
6691 LIBBASETYPEPTR
, ps
, 59, psd
)
6697 KPRINTF(10, ("psdGetCfgChunk(%p, 0x%08lx)\n", pic
, chnkid
));
6699 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6702 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6703 if(!(pic
->pic_Node
.ln_Succ
))
6705 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6709 pUpdateGlobalCfg(ps
, pic
);
6710 chnk
= pFindCfgChunk(ps
, pic
, chnkid
);
6713 res
= psdAllocVec(AROS_LONG2BE(chnk
[1])+8);
6716 memcpy(res
, chnk
, AROS_LONG2BE(chnk
[1])+8);
6719 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6725 /* /// "psdParseCfg()" */
6726 AROS_LH0(void, psdParseCfg
,
6727 LIBBASETYPEPTR
, ps
, 60, psd
)
6730 struct PsdIFFContext
*pic
;
6731 struct PsdIFFContext
*subpic
;
6735 struct PsdHardware
*phw
;
6736 struct PsdUsbClass
*puc
;
6737 BOOL removeall
= TRUE
;
6738 BOOL nodos
= (FindTask(NULL
)->tc_Node
.ln_Type
!= NT_PROCESS
);
6741 XPRINTF(10, ("psdParseCfg()\n"));
6743 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6744 pCheckCfgChanged(ps
);
6745 pic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
);
6748 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6752 // if no config for hardware is found, we don't remove the devices,
6753 // because this could render the system useless (no USB mice or
6754 // keyboards to configure the hardware!)
6755 if(!psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
))
6757 XPRINTF(10, ("No hardware data present\n"));
6763 /* select all hardware devices for removal */
6764 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6765 while(phw
->phw_Node
.ln_Succ
)
6767 phw
->phw_RemoveMe
= removeall
;
6768 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
6771 /* select all classes for removal */
6772 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6773 while(puc
->puc_Node
.ln_Succ
)
6776 * For kickstart-resident classes we check usage count, and
6777 * remove them only if it's zero.
6778 * These classes can be responsible for devices which we can use
6779 * at boot time. If we happen to remove them, we can end up with
6780 * no input or storage devices at all.
6782 if (FindResident(puc
->puc_ClassName
))
6783 puc
->puc_RemoveMe
= (puc
->puc_UseCnt
== 0);
6785 puc
->puc_RemoveMe
= TRUE
;
6787 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6792 /* Get Hardware config */
6793 subpic
= psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
);
6796 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6799 name
= (STRPTR
) &chnk
[2];
6801 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_UNIT
);
6806 if(!pFindCfgChunk(ps
, subpic
, IFFCHNK_OFFLINE
))
6808 phw
= pFindHardware(ps
, name
, unit
);
6809 XPRINTF(5, ("Have configuration for device 0x%p (%s unit %u)\n", phw
, name
, unit
));
6812 phw
->phw_RemoveMe
= FALSE
;
6816 subpic
= psdNextCfgForm(subpic
);
6819 /* Get Class config */
6820 subpic
= psdFindCfgForm(pic
, IFFFORM_USBCLASS
);
6823 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6826 name
= (STRPTR
) &chnk
[2];
6827 puc
= (struct PsdUsbClass
*) pFindName(ps
, &ps
->ps_Classes
, name
);
6828 XPRINTF(5, ("Have configuration for class 0x%p (%s)\n", puc
, name
));
6831 puc
->puc_RemoveMe
= FALSE
;
6834 subpic
= psdNextCfgForm(subpic
);
6837 // unlock config while removing to avoid deadlocks.
6838 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6840 /* now remove remaining classes not found in the config */
6841 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6842 while(puc
->puc_Node
.ln_Succ
)
6844 if(puc
->puc_RemoveMe
)
6846 XPRINTF(5, ("Removing class %s\n", puc
->puc_ClassName
));
6848 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6850 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6854 /* now remove all remaining hardware not found in the config */
6855 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6856 while(phw
->phw_Node
.ln_Succ
)
6858 if(phw
->phw_RemoveMe
)
6860 XPRINTF(5, ("Removing device %s unit %u\n", phw
->phw_DevName
, phw
->phw_Unit
));
6861 psdRemHardware(phw
);
6862 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6864 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
6868 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6869 pic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
);
6872 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6877 /* Add missing Classes */
6878 subpic
= psdFindCfgForm(pic
, IFFFORM_USBCLASS
);
6881 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6884 /* *** FIXME *** POSSIBLE DEADLOCK WHEN CLASS TRIES TO DO CONFIG STUFF IN
6885 AN EXTERNAL TASK INSIDE LIBOPEN CODE */
6886 name
= (STRPTR
) &chnk
[2];
6887 puc
= (struct PsdUsbClass
*) pFindName(ps
, &ps
->ps_Classes
, name
);
6890 psdAddClass(name
, 0);
6893 subpic
= psdNextCfgForm(subpic
);
6896 /* Now really mount Hardware found in config */
6897 subpic
= psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
);
6900 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6903 name
= (STRPTR
) &chnk
[2];
6905 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_UNIT
);
6910 if(!pFindCfgChunk(ps
, subpic
, IFFCHNK_OFFLINE
))
6912 phw
= pFindHardware(ps
, name
, unit
);
6915 phw
= psdAddHardware(name
, unit
);
6918 #ifdef AROS_USB30_CODE
6919 if(psdEnumerateHardware(phw
) == NULL
) {
6920 psdRemHardware(phw
);
6923 psdEnumerateHardware(phw
);
6929 subpic
= psdNextCfgForm(subpic
);
6931 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6933 if(!nodos
&& ps
->ps_StartedAsTask
)
6935 // last time we were reading the config before DOS, so maybe we need to
6936 // unbind some classes that need to be overruled by newly available classes,
6937 // such as hid.class overruling bootmouse & bootkeyboard.
6938 // so unbind those classes that promote themselves as AfterDOS
6941 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Checking AfterDOS...");
6942 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6943 while(puc
->puc_Node
.ln_Succ
)
6946 usbGetAttrs(UGA_CLASS
, NULL
,
6947 UCCA_AfterDOSRestart
, &restartme
,
6950 if(restartme
&& puc
->puc_UseCnt
)
6952 struct PsdDevice
*pd
;
6953 struct PsdConfig
*pc
;
6954 struct PsdInterface
*pif
;
6956 /* Well, try to release the open bindings in a best effort attempt */
6958 while((pd
= psdGetNextDevice(pd
)))
6960 if(pd
->pd_DevBinding
&& (pd
->pd_ClsBinding
== puc
) && (!(pd
->pd_Flags
& PDFF_APPBINDING
)))
6963 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6964 "AfterDOS: Temporarily releasing %s %s binding to %s.",
6965 puc
->puc_ClassName
, "device", pd
->pd_ProductStr
);
6966 psdReleaseDevBinding(pd
);
6968 pd
= NULL
; /* restart */
6971 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
6972 while(pc
->pc_Node
.ln_Succ
)
6974 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
6975 while(pif
->pif_Node
.ln_Succ
)
6977 if(pif
->pif_IfBinding
&& (pif
->pif_ClsBinding
== puc
))
6980 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6981 "AfterDOS: Temporarily releasing %s %s binding to %s.",
6982 puc
->puc_ClassName
, "interface", pd
->pd_ProductStr
);
6983 psdReleaseIfBinding(pif
);
6985 pd
= NULL
; /* restart */
6988 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
6990 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
6994 usbDoMethodA(UCM_DOSAvailableEvent
, NULL
);
6995 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6997 ps
->ps_StartedAsTask
= FALSE
;
7001 if(nodos
&& (!ps
->ps_ConfigRead
))
7003 // it's the first time we were reading the config and DOS was not available
7004 ps
->ps_StartedAsTask
= TRUE
;
7006 ps
->ps_ConfigRead
= TRUE
;
7007 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
; // update saved hash
7009 /* do a class scan */
7012 if(nodos
&& ps
->ps_GlobalCfg
->pgc_BootDelay
)
7014 // wait for hubs to settle
7016 puc
= (struct PsdUsbClass
*) FindName(&ps
->ps_Classes
, "massstorage.class");
7017 if(puc
&& puc
->puc_UseCnt
)
7019 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
7020 "Delaying further execution by %ld second(s) (boot delay).",
7021 ps
->ps_GlobalCfg
->pgc_BootDelay
);
7022 if(ps
->ps_GlobalCfg
->pgc_BootDelay
>= 1)
7024 psdDelayMS((ps
->ps_GlobalCfg
->pgc_BootDelay
-1)*1000);
7027 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Boot delay skipped, no mass storage devices found.");
7034 /* /// "psdSetClsCfg()" */
7035 AROS_LH2(BOOL
, psdSetClsCfg
,
7036 AROS_LHA(STRPTR
, owner
, A0
),
7037 AROS_LHA(APTR
, form
, A1
),
7038 LIBBASETYPEPTR
, ps
, 62, psd
)
7041 struct PsdIFFContext
*pic
;
7042 BOOL result
= FALSE
;
7044 KPRINTF(10, ("psdSetClsCfg(%s, %p)\n", owner
, form
));
7045 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7046 pic
= psdFindCfgForm(NULL
, IFFFORM_CLASSCFG
);
7049 if(pMatchStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7051 pic
= psdFindCfgForm(pic
, IFFFORM_CLASSDATA
);
7056 result
= psdReadCfg(pic
, form
);
7058 psdRemCfgChunk(pic
, 0);
7066 pic
= psdNextCfgForm(pic
);
7070 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7071 pCheckCfgChanged(ps
);
7074 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7075 if(pic
->pic_Node
.ln_Succ
)
7077 pic
= pAllocForm(ps
, pic
, IFFFORM_CLASSCFG
);
7080 if(pAddStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7084 if(pAddCfgChunk(ps
, pic
, form
))
7086 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7087 pCheckCfgChanged(ps
);
7092 buf
[0] = AROS_LONG2BE(ID_FORM
);
7093 buf
[1] = AROS_LONG2BE(4);
7094 buf
[2] = AROS_LONG2BE(IFFFORM_CLASSDATA
);
7095 if(pAddCfgChunk(ps
, pic
, buf
))
7097 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7098 pCheckCfgChanged(ps
);
7105 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7106 pCheckCfgChanged(ps
);
7112 /* /// "psdGetClsCfg()" */
7113 AROS_LH1(struct PsdIFFContext
*, psdGetClsCfg
,
7114 AROS_LHA(STRPTR
, owner
, A0
),
7115 LIBBASETYPEPTR
, ps
, 63, psd
)
7118 struct PsdIFFContext
*pic
;
7120 KPRINTF(10, ("psdGetClsCfg(%s)\n", owner
));
7121 pic
= psdFindCfgForm(NULL
, IFFFORM_CLASSCFG
);
7124 if(pMatchStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7126 return(psdFindCfgForm(pic
, IFFFORM_CLASSDATA
));
7128 pic
= psdNextCfgForm(pic
);
7135 /* /// "psdSetUsbDevCfg()" */
7136 AROS_LH4(BOOL
, psdSetUsbDevCfg
,
7137 AROS_LHA(STRPTR
, owner
, A0
),
7138 AROS_LHA(STRPTR
, devid
, A2
),
7139 AROS_LHA(STRPTR
, ifid
, A3
),
7140 AROS_LHA(APTR
, form
, A1
),
7141 LIBBASETYPEPTR
, ps
, 64, psd
)
7144 struct PsdIFFContext
*pic
;
7145 struct PsdIFFContext
*cpic
= NULL
;
7146 struct PsdIFFContext
*mpic
= NULL
;
7147 BOOL result
= FALSE
;
7149 KPRINTF(10, ("psdSetUsbDevCfg(%s, %s, %s, %p)\n", owner
, devid
, ifid
, form
));
7150 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7151 /* Find device config form. It contains all device config data */
7152 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7155 /* Find DEVID-Chunk. Check if it matches our device id */
7156 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7159 /* We found the correct device. Now if we need to store interface data, find the interface first */
7162 /* Search interface config form */
7163 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7166 /* Found the form. Find the the ID String for the interface */
7167 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7169 /* ID did match, now check for owner */
7170 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7172 /* found it! So there is already a config saved in there. Search for dev config data form */
7173 cpic
= psdFindCfgForm(mpic
, IFFFORM_IFCLSDATA
);
7176 /* not found, generate it */
7177 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7182 mpic
= psdNextCfgForm(mpic
);
7186 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7188 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7190 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7192 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7198 /* Search for device config */
7199 mpic
= psdFindCfgForm(pic
, IFFFORM_DEVCFGDATA
);
7202 /* search for the right owner */
7203 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7205 /* found it! So there is already a config saved in there. Search for dev config data form */
7206 cpic
= psdFindCfgForm(mpic
, IFFFORM_DEVCLSDATA
);
7209 /* not found, generate it */
7210 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7214 mpic
= psdNextCfgForm(mpic
);
7216 if(!cpic
) /* no device config form */
7218 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_DEVCFGDATA
)))
7220 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7222 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7231 result
= psdReadCfg(cpic
, form
);
7233 psdRemCfgChunk(cpic
, 0);
7239 pic
= psdNextCfgForm(pic
);
7243 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7244 pCheckCfgChanged(ps
);
7248 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7249 if(pic
->pic_Node
.ln_Succ
)
7251 pic
= pAllocForm(ps
, pic
, IFFFORM_DEVICECFG
);
7254 if(pAddStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7258 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7260 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7262 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7264 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7269 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_DEVCFGDATA
)))
7271 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7273 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7281 result
= psdReadCfg(cpic
, form
);
7283 psdRemCfgChunk(cpic
, 0);
7290 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7291 pCheckCfgChanged(ps
);
7297 /* /// "psdGetUsbDevCfg()" */
7298 AROS_LH3(struct PsdIFFContext
*, psdGetUsbDevCfg
,
7299 AROS_LHA(STRPTR
, owner
, A0
),
7300 AROS_LHA(STRPTR
, devid
, A2
),
7301 AROS_LHA(STRPTR
, ifid
, A3
),
7302 LIBBASETYPEPTR
, ps
, 65, psd
)
7305 struct PsdIFFContext
*pic
;
7306 struct PsdIFFContext
*cpic
= NULL
;
7307 struct PsdIFFContext
*mpic
= NULL
;
7309 KPRINTF(10, ("psdGetUsbDevCfg(%s, %s, %s)\n", owner
, devid
, ifid
));
7310 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7311 /* Find device config form. It contains all device config data */
7312 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7315 /* Find DEVID-Chunk. Check if it matches our device id */
7316 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7319 /* We found the correct device. Now if we need to store interface data, find the interface first */
7322 /* Search interface config form */
7323 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7326 /* Found the form. Find the the ID String for the interface */
7327 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7329 /* ID did match, now check for owner */
7330 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7332 /* found it! So there is already a config saved in there. Search for dev config data form */
7333 cpic
= psdFindCfgForm(mpic
, IFFFORM_IFCLSDATA
);
7337 mpic
= psdNextCfgForm(mpic
);
7340 /* Search for device config */
7341 mpic
= psdFindCfgForm(pic
, IFFFORM_DEVCFGDATA
);
7344 /* search for the right owner */
7345 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7347 /* found it! So there is already a config saved in there. Search for dev config data form */
7348 cpic
= psdFindCfgForm(mpic
, IFFFORM_DEVCLSDATA
);
7351 mpic
= psdNextCfgForm(mpic
);
7356 pic
= psdNextCfgForm(pic
);
7358 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7359 KPRINTF(1, ("Result %p\n", cpic
));
7365 /* /// "psdSetForcedBinding()" */
7366 AROS_LH3(BOOL
, psdSetForcedBinding
,
7367 AROS_LHA(STRPTR
, owner
, A2
),
7368 AROS_LHA(STRPTR
, devid
, A0
),
7369 AROS_LHA(STRPTR
, ifid
, A1
),
7370 LIBBASETYPEPTR
, ps
, 69, psd
)
7373 struct PsdIFFContext
*pic
;
7374 struct PsdIFFContext
*mpic
= NULL
;
7376 BOOL result
= FALSE
;
7380 olen
= strlen(owner
);
7382 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7383 /* Find device config form. It contains all device config data */
7384 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7387 /* Find DEVID-Chunk. Check if it matches our device id */
7388 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7390 /* We found the correct device. Now if we need to store interface data, find the interface first */
7393 /* Search interface config form */
7394 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7397 /* Found the form. Find the the ID String for the interface */
7398 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7400 /* ID did match, insert/replace forced binding */
7403 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7408 pRemCfgChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
);
7412 mpic
= psdNextCfgForm(mpic
);
7418 if((!result
) && olen
)
7420 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7422 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7424 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7426 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7435 /* Add FBND chunk */
7438 if(pAddStringChunk(ps
, pic
, IFFCHNK_FORCEDBIND
, owner
))
7443 pRemCfgChunk(ps
, pic
, IFFCHNK_FORCEDBIND
);
7449 pic
= psdNextCfgForm(pic
);
7457 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7458 pCheckCfgChanged(ps
);
7461 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7462 if(pic
->pic_Node
.ln_Succ
)
7464 pic
= pAllocForm(ps
, pic
, IFFFORM_DEVICECFG
);
7467 if(pAddStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7471 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7473 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7475 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7477 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7485 /* Add FBND chunk */
7486 if(pAddStringChunk(ps
, pic
, IFFCHNK_FORCEDBIND
, owner
))
7494 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7495 pCheckCfgChanged(ps
);
7501 /* /// "psdGetForcedBinding()" */
7502 AROS_LH2(STRPTR
, psdGetForcedBinding
,
7503 AROS_LHA(STRPTR
, devid
, A0
),
7504 AROS_LHA(STRPTR
, ifid
, A1
),
7505 LIBBASETYPEPTR
, ps
, 70, psd
)
7508 struct PsdIFFContext
*pic
;
7509 struct PsdIFFContext
*mpic
= NULL
;
7511 STRPTR owner
= NULL
;
7513 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7514 /* Find device config form. It contains all device config data */
7515 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7518 /* Find DEVID-Chunk. Check if it matches our device id */
7519 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7521 /* We found the correct device. Now if we need to store interface data, find the interface first */
7524 /* Search interface config form */
7525 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7528 /* Found the form. Find the the ID String for the interface */
7529 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7531 /* ID did match, now check for forced binding */
7532 chunk
= pFindCfgChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
);
7535 owner
= (STRPTR
) &chunk
[2];
7539 mpic
= psdNextCfgForm(mpic
);
7542 /* Search for device forced binding */
7543 chunk
= pFindCfgChunk(ps
, pic
, IFFCHNK_FORCEDBIND
);
7546 owner
= (STRPTR
) &chunk
[2];
7552 pic
= psdNextCfgForm(pic
);
7554 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7560 /* /// "psdAddStringChunk()" */
7561 AROS_LH3(BOOL
, psdAddStringChunk
,
7562 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7563 AROS_LHA(ULONG
, chunkid
, D0
),
7564 AROS_LHA(CONST_STRPTR
, str
, A1
),
7565 LIBBASETYPEPTR
, ps
, 87, psd
)
7569 KPRINTF(10, ("psdAddStringChunk(%p, %p, %s)\n", pic
, chunkid
, str
));
7570 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7571 res
= pAddStringChunk(ps
, pic
, chunkid
, str
);
7572 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7578 /* /// "psdMatchStringChunk()" */
7579 AROS_LH3(BOOL
, psdMatchStringChunk
,
7580 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7581 AROS_LHA(ULONG
, chunkid
, D0
),
7582 AROS_LHA(CONST_STRPTR
, str
, A1
),
7583 LIBBASETYPEPTR
, ps
, 88, psd
)
7587 KPRINTF(10, ("psdMatchStringChunk(%p, %p, %s)\n", pic
, chunkid
, str
));
7588 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7589 res
= pMatchStringChunk(ps
, pic
, chunkid
, str
);
7590 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7596 /* /// "psdGetStringChunk()" */
7597 AROS_LH2(STRPTR
, psdGetStringChunk
,
7598 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7599 AROS_LHA(ULONG
, chunkid
, D0
),
7600 LIBBASETYPEPTR
, ps
, 89, psd
)
7604 KPRINTF(10, ("psdGetStringChunk(%p, %p)\n", pic
, chunkid
));
7605 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7606 str
= pGetStringChunk(ps
, pic
, chunkid
);
7607 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7613 /* *** Configuration (non-library subroutines) *** */
7615 /* /// "pAllocForm()" */
7616 struct PsdIFFContext
* pAllocForm(LIBBASETYPEPTR ps
, struct PsdIFFContext
*parent
, ULONG formid
)
7618 struct PsdIFFContext
*pic
;
7619 KPRINTF(10, ("pAllocForm(%p, %p)\n", parent
, formid
));
7620 if((pic
= psdAllocVec(sizeof(struct PsdIFFContext
))))
7622 NewList(&pic
->pic_SubForms
);
7623 //pic->pic_Parent = parent;
7624 pic
->pic_FormID
= formid
;
7625 pic
->pic_FormLength
= 4;
7626 pic
->pic_Chunks
= NULL
;
7627 pic
->pic_ChunksLen
= 0;
7628 pic
->pic_BufferLen
= 0;
7632 AddTail(&parent
->pic_SubForms
, &pic
->pic_Node
);
7634 AddTail(&ps
->ps_ConfigRoot
, &pic
->pic_Node
);
7642 /* /// "pFreeForm()" */
7643 void pFreeForm(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
)
7645 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7646 KPRINTF(10, ("pFreeForm(%p)\n", pic
));
7647 Remove(&pic
->pic_Node
);
7648 while(subpic
->pic_Node
.ln_Succ
)
7650 pFreeForm(ps
, subpic
);
7651 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7653 psdFreeVec(pic
->pic_Chunks
);
7658 /* /// "pGetFormLength()" */
7659 ULONG
pGetFormLength(struct PsdIFFContext
*pic
)
7661 ULONG len
= (5 + pic
->pic_ChunksLen
) & ~1UL;
7662 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7663 //KPRINTF(10, ("pGetFormLength(%p)\n", pic));
7664 while(subpic
->pic_Node
.ln_Succ
)
7666 len
+= pGetFormLength(subpic
);
7667 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7669 pic
->pic_FormLength
= len
;
7670 //KPRINTF(10, ("FormLen=%ld\n", len+8));
7675 /* /// "pFindCfgChunk()" */
7676 APTR
pFindCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chnkid
)
7678 ULONG
*buf
= pic
->pic_Chunks
;
7679 ULONG len
= pic
->pic_ChunksLen
;
7681 KPRINTF(10, ("pFindCfgChunk(%p, %p)\n", pic
, chnkid
));
7685 if(AROS_LONG2BE(*buf
) == chnkid
)
7687 KPRINTF(10, ("Found at %p\n", buf
));
7690 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7692 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7694 KPRINTF(10, ("Not found!\n"));
7699 /* /// "pRemCfgChunk()" */
7700 BOOL
pRemCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chnkid
)
7702 ULONG
*buf
= pic
->pic_Chunks
;
7703 ULONG len
= pic
->pic_ChunksLen
;
7705 KPRINTF(10, ("pRemCfgChunk(%p, %p)\n", pic
, chnkid
));
7709 chlen
= ((AROS_LONG2BE(buf
[1])) + 9) & ~1UL;
7710 if(AROS_LONG2BE(*buf
) == chnkid
)
7715 memcpy(buf
, &((UBYTE
*) buf
)[chlen
], (size_t) len
);
7717 pic
->pic_ChunksLen
-= chlen
;
7718 KPRINTF(10, ("Deleted %ld bytes to %ld chunk len\n", chlen
, pic
->pic_ChunksLen
));
7722 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7724 KPRINTF(10, ("Not found!\n"));
7729 /* /// "pAddCfgChunk()" */
7730 struct PsdIFFContext
* pAddCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, APTR chunk
)
7736 struct PsdIFFContext
*subpic
;
7737 KPRINTF(10, ("pAddCfgChunk(%p, %p)\n", pic
, chunk
));
7738 if(AROS_LONG2BE(*buf
) == ID_FORM
)
7741 len
= ((AROS_LONG2BE(*buf
)) - 3) & ~1UL;
7743 if((subpic
= pAllocForm(ps
, pic
, AROS_LONG2BE(*buf
))))
7748 if(!(pAddCfgChunk(ps
, subpic
, buf
)))
7752 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7754 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7758 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to add a nasty corrupted FORM chunk! Configuration is probably b0rken!");
7766 pRemCfgChunk(ps
, pic
, AROS_LONG2BE(*buf
));
7767 len
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7768 if(pic
->pic_ChunksLen
+len
> pic
->pic_BufferLen
)
7770 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
));
7773 if((newbuf
= psdAllocVec((pic
->pic_ChunksLen
+len
)<<1)))
7775 if(pic
->pic_ChunksLen
)
7777 memcpy(newbuf
, pic
->pic_Chunks
, (size_t) pic
->pic_ChunksLen
);
7778 psdFreeVec(pic
->pic_Chunks
);
7780 pic
->pic_Chunks
= newbuf
;
7781 pic
->pic_BufferLen
= (pic
->pic_ChunksLen
+len
)<<1;
7786 memcpy(&(((UBYTE
*) pic
->pic_Chunks
)[pic
->pic_ChunksLen
]), chunk
, (size_t) len
);
7787 pic
->pic_ChunksLen
+= len
;
7793 /* /// "pInternalWriteForm()" */
7794 ULONG
* pInternalWriteForm(struct PsdIFFContext
*pic
, ULONG
*buf
)
7796 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7797 //KPRINTF(10, ("pInternalWriteForm(%p, %p)", pic, buf));
7798 *buf
++ = AROS_LONG2BE(ID_FORM
);
7799 *buf
++ = AROS_LONG2BE(pic
->pic_FormLength
);
7800 *buf
++ = AROS_LONG2BE(pic
->pic_FormID
);
7801 if(pic
->pic_ChunksLen
)
7803 memcpy(buf
, pic
->pic_Chunks
, (size_t) pic
->pic_ChunksLen
);
7804 buf
= (ULONG
*) (((UBYTE
*) buf
) + pic
->pic_ChunksLen
);
7806 while(subpic
->pic_Node
.ln_Succ
)
7808 buf
= pInternalWriteForm(subpic
, buf
);
7809 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7815 /* /// "pCalcCfgCRC()" */
7816 ULONG
pCalcCfgCRC(struct PsdIFFContext
*pic
)
7818 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7820 ULONG crc
= pic
->pic_FormID
;
7823 //KPRINTF(10, ("pInternalWriteForm(%p, %p)", pic, buf));
7824 if(pic
->pic_ChunksLen
)
7826 len
= pic
->pic_ChunksLen
>>1;
7829 ptr
= (UWORD
*) pic
->pic_Chunks
;
7832 crc
= ((crc
<<1)|(crc
>>31))^(*ptr
++);
7836 while(subpic
->pic_Node
.ln_Succ
)
7838 crc
^= pCalcCfgCRC(subpic
);
7839 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7845 /* /// "pCheckCfgChanged()" */
7846 BOOL
pCheckCfgChanged(LIBBASETYPEPTR ps
)
7849 struct PsdIFFContext
*pic
;
7850 struct PsdIFFContext
*subpic
;
7853 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7854 ps
->ps_CheckConfigReq
= FALSE
;
7855 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7856 if(!(pic
->pic_Node
.ln_Succ
))
7858 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7861 crc
= pCalcCfgCRC(pic
);
7862 if(crc
!= ps
->ps_ConfigHash
)
7865 ps
->ps_ConfigHash
= crc
;
7866 /* Get Global config */
7867 if((subpic
= psdFindCfgForm(pic
, IFFFORM_STACKCFG
)))
7869 if((chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_GLOBALCFG
)))
7871 CopyMem(&chnk
[2], ((UBYTE
*) ps
->ps_GlobalCfg
) + 8, min(AROS_LONG2BE(chnk
[1]), AROS_LONG2BE(ps
->ps_GlobalCfg
->pgc_Length
)));
7873 if(!pMatchStringChunk(ps
, subpic
, IFFCHNK_INSERTSND
, ps
->ps_PoPo
.po_InsertSndFile
))
7875 if((tmpstr
= pGetStringChunk(ps
, subpic
, IFFCHNK_INSERTSND
)))
7877 psdFreeVec(ps
->ps_PoPo
.po_InsertSndFile
);
7878 ps
->ps_PoPo
.po_InsertSndFile
= tmpstr
;
7881 if(!pMatchStringChunk(ps
, subpic
, IFFCHNK_REMOVESND
, ps
->ps_PoPo
.po_RemoveSndFile
))
7883 if((tmpstr
= pGetStringChunk(ps
, subpic
, IFFCHNK_REMOVESND
)))
7885 psdFreeVec(ps
->ps_PoPo
.po_RemoveSndFile
);
7886 ps
->ps_PoPo
.po_RemoveSndFile
= tmpstr
;
7890 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7891 psdSendEvent(EHMB_CONFIGCHG
, NULL
, NULL
);
7894 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7899 /* /// "pAddStringChunk()" */
7900 BOOL
pAddStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
, CONST_STRPTR str
)
7903 ULONG len
= strlen(str
);
7904 ULONG
*chnk
= (ULONG
*) psdAllocVec((ULONG
) len
+8+2);
7907 chnk
[0] = AROS_LONG2BE(chunkid
);
7908 chnk
[1] = AROS_LONG2BE(len
+1);
7909 strcpy((STRPTR
) &chnk
[2], str
);
7910 if(pAddCfgChunk(ps
, pic
, chnk
))
7920 /* /// "pMatchStringChunk()" */
7921 BOOL
pMatchStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
, CONST_STRPTR str
)
7926 if((chunk
= pFindCfgChunk(ps
, pic
, chunkid
)))
7928 srcptr
= (STRPTR
) &chunk
[2];
7929 len
= AROS_LONG2BE(chunk
[1]);
7930 while(len
-- && *srcptr
)
7932 if(*str
++ != *srcptr
++)
7946 /* /// "pGetStringChunk()" */
7947 STRPTR
pGetStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
)
7951 if((chunk
= pFindCfgChunk(ps
, pic
, chunkid
)))
7953 if((str
= (STRPTR
) psdAllocVec(AROS_LONG2BE(chunk
[1]) + 1)))
7955 memcpy(str
, &chunk
[2], (size_t) AROS_LONG2BE(chunk
[1]));
7963 /* /// "pUpdateGlobalCfg()" */
7964 void pUpdateGlobalCfg(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
)
7966 struct PsdIFFContext
*tmppic
;
7967 /* Set Global config */
7968 if(pic
== (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
)
7970 if((tmppic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
)))
7972 pAddCfgChunk(ps
, tmppic
, ps
->ps_GlobalCfg
);
7973 pAddStringChunk(ps
, tmppic
, IFFCHNK_INSERTSND
, ps
->ps_PoPo
.po_InsertSndFile
);
7974 pAddStringChunk(ps
, tmppic
, IFFCHNK_REMOVESND
, ps
->ps_PoPo
.po_RemoveSndFile
);
7980 /* *** Misc (non library functions) ***/
7982 /* /// "pGetDevConfig()" */
7983 BOOL
pGetDevConfig(struct PsdPipe
*pp
)
7985 struct PsdDevice
*pd
= pp
->pp_Device
;
7986 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
7988 struct UsbStdCfgDesc uscd
;
7994 KPRINTF(1, ("Getting configuration descriptor...\n"));
7995 psdLockWriteDevice(pd
);
7996 while(curcfg
< pd
->pd_NumCfgs
)
7998 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
7999 USR_GET_DESCRIPTOR
, (UDT_CONFIGURATION
<<8)|curcfg
, 0);
8001 /*tempbuf = psdAllocVec(256);
8002 ioerr = psdDoPipe(pp, tempbuf, 34);
8003 if(ioerr == UHIOERR_RUNTPACKET)
8007 memcpy(&uscd, tempbuf, 9);*/
8008 ioerr
= psdDoPipe(pp
, &uscd
, 9);//sizeof(struct UsbStdCfgDesc));
8011 KPRINTF(1, ("Config type: %ld\n", (ULONG
) uscd
.bDescriptorType
));
8012 len
= (ULONG
) AROS_WORD2LE(uscd
.wTotalLength
);
8013 KPRINTF(1, ("Configsize %ld, total size %ld\n", (ULONG
) uscd
.bLength
, len
));
8014 if((tempbuf
= psdAllocVec(len
)))
8017 KPRINTF(1, ("Getting whole configuration descriptor...\n"));
8018 ioerr
= psdDoPipe(pp
, tempbuf
, len
);
8021 struct PsdConfig
*pc
= NULL
;
8022 struct PsdInterface
*pif
= NULL
;
8023 struct PsdInterface
*altif
= NULL
;
8024 struct PsdEndpoint
*pep
= NULL
;
8025 struct PsdDescriptor
*pdd
= NULL
;
8026 UBYTE
*dbuf
= tempbuf
;
8029 bufend
= &dbuf
[len
];
8030 while(dbuf
< bufend
)
8032 dlen
= dbuf
[0]; /* bLength */
8037 if(&dbuf
[dlen
] > bufend
)
8039 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "End of descriptor past buffer!");
8041 switch(dbuf
[1]) /* bDescriptorType */
8043 case UDT_CONFIGURATION
:
8045 struct UsbStdCfgDesc
*usc
= (struct UsbStdCfgDesc
*) dbuf
;
8049 if((pc
= pAllocConfig(pd
)))
8051 pd
->pd_Flags
|= PDFF_CONFIGURED
;
8052 pc
->pc_NumIfs
= usc
->bNumInterfaces
;
8053 pc
->pc_CfgNum
= usc
->bConfigurationValue
;
8054 pc
->pc_Attr
= usc
->bmAttributes
;
8055 pc
->pc_MaxPower
= usc
->bMaxPower
<<1;
8057 KPRINTF(1, (" Config %ld\n", pc
->pc_CfgNum
));
8058 if(usc
->iConfiguration
)
8060 pc
->pc_CfgStr
= psdGetStringDescriptor(pp
, usc
->iConfiguration
);
8064 pc
->pc_CfgStr
= psdCopyStrFmt("Configuration %ld", pc
->pc_CfgNum
);
8067 KPRINTF(20, (" Config allocation failed\n"));
8074 struct UsbStdIfDesc
*usif
= (struct UsbStdIfDesc
*) dbuf
;
8078 if((altif
= pAllocInterface(pc
)))
8080 altif
->pif_IfNum
= usif
->bInterfaceNumber
;
8081 altif
->pif_Alternate
= usif
->bAlternateSetting
;
8082 altif
->pif_NumEPs
= usif
->bNumEndpoints
;
8083 altif
->pif_IfClass
= usif
->bInterfaceClass
;
8084 altif
->pif_IfSubClass
= usif
->bInterfaceSubClass
;
8085 altif
->pif_IfProto
= usif
->bInterfaceProtocol
;
8086 KPRINTF(2, (" Interface %ld\n", altif
->pif_IfNum
));
8087 if(usif
->iInterface
)
8089 altif
->pif_IfStr
= psdGetStringDescriptor(pp
, usif
->iInterface
);
8091 if(!altif
->pif_IfStr
)
8093 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) altif
->pif_IfClass
, NULL
);
8096 altif
->pif_IfStr
= psdCopyStrFmt("%s interface (%ld)", classname
, altif
->pif_IfNum
);
8098 altif
->pif_IfStr
= psdCopyStrFmt("Interface %ld", altif
->pif_IfNum
);
8101 KPRINTF(2, (" IfName : %s\n"
8102 " Alternate : %ld\n"
8105 " IfSubClass: %ld\n"
8107 altif
->pif_IfStr
, altif
->pif_Alternate
,
8110 altif
->pif_IfSubClass
, altif
->pif_IfProto
));
8111 if(pc
->pc_CfgNum
== 1)
8113 altif
->pif_IDString
= psdCopyStrFmt("%02lx-%02lx-%02lx-%02lx-%02lx",
8114 altif
->pif_IfNum
, altif
->pif_Alternate
,
8115 altif
->pif_IfClass
, altif
->pif_IfSubClass
,
8116 altif
->pif_IfProto
);
8118 // for more than one config, add config number (retain backwards compatibility with most devices)
8119 altif
->pif_IDString
= psdCopyStrFmt("%02lx-%02lx-%02lx-%02lx-%02lx-%02lx",
8121 altif
->pif_IfNum
, altif
->pif_Alternate
,
8122 altif
->pif_IfClass
, altif
->pif_IfSubClass
,
8123 altif
->pif_IfProto
);
8126 /* Move the interface to the alternatives if possible */
8127 if(altif
->pif_Alternate
)
8131 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Alternate interface without prior main interface!");
8132 KPRINTF(20, (" Alternate interface without prior main interface\n"));
8135 Remove(&altif
->pif_Node
);
8136 AddTail(&pif
->pif_AlterIfs
, &altif
->pif_Node
);
8137 altif
->pif_ParentIf
= pif
;
8140 altif
->pif_ParentIf
= NULL
;
8144 KPRINTF(20, (" Interface allocation failed\n"));
8147 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Interface without prior config descriptor!");
8148 KPRINTF(20, (" Interface descriptor without Config\n"));
8155 struct UsbStdEPDesc
*usep
= (struct UsbStdEPDesc
*) dbuf
;
8158 if((pep
= pAllocEndpoint(altif
)))
8161 pep
->pep_EPNum
= usep
->bEndpointAddress
& 0x0f;
8162 pep
->pep_Direction
= usep
->bEndpointAddress
>>7;
8163 pep
->pep_TransType
= usep
->bmAttributes
& 0x03;
8164 pep
->pep_SyncType
= (usep
->bmAttributes
>>2) & 0x03;
8165 pep
->pep_UsageType
= (usep
->bmAttributes
>>4) & 0x03;
8166 eptype
= (pep
->pep_TransType
== USEAF_INTERRUPT
) ? "int" : "iso";
8168 pep
->pep_MaxPktSize
= AROS_WORD2LE(usep
->wMaxPacketSize
) & 0x07ff;
8169 pep
->pep_NumTransMuFr
= ((AROS_WORD2LE(usep
->wMaxPacketSize
)>>11) & 3) + 1;
8170 if(pep
->pep_NumTransMuFr
== 4)
8172 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint contains illegal Num Trans µFrame value!");
8173 pep
->pep_NumTransMuFr
= 1;
8176 pep
->pep_Interval
= usep
->bInterval
;
8177 if(pd
->pd_Flags
& PDFF_HIGHSPEED
)
8179 switch(pep
->pep_TransType
)
8183 //pep->pep_Interval = 0; // no use here, NAK rate not of interest
8186 case USEAF_ISOCHRONOUS
:
8187 if(pep
->pep_MaxPktSize
> 1024)
8189 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8190 "Endpoint contains %s (%ld) MaxPktSize value!",
8191 (STRPTR
) "too high", pep
->pep_MaxPktSize
);
8192 pep
->pep_MaxPktSize
= 1024;
8195 case USEAF_INTERRUPT
:
8196 if(!pep
->pep_Interval
)
8198 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8199 "%sspeed %s endpoint contains %s interval value! Fixing.",
8200 (STRPTR
) "High", eptype
, (STRPTR
) "zero");
8201 pep
->pep_Interval
= 1;
8203 else if(pep
->pep_Interval
> 16)
8205 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8206 "%sspeed %s endpoint contains %s interval value! Fixing.",
8207 (STRPTR
) "High", eptype
, (STRPTR
) "too high");
8208 pep
->pep_Interval
= 16;
8210 pep
->pep_Interval
= 1<<(pep
->pep_Interval
-1);
8214 else if(pd
->pd_Flags
& PDFF_LOWSPEED
)
8216 switch(pep
->pep_TransType
)
8218 case USEAF_INTERRUPT
:
8219 if(pep
->pep_Interval
< 8)
8221 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8222 (STRPTR
) "Low", eptype
, (STRPTR
) "too low");
8223 pep
->pep_Interval
= 8;
8229 pep
->pep_Interval
= 0; // no use here
8232 case USEAF_ISOCHRONOUS
:
8233 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Lowspeed devices cannot have isochronous endpoints!");
8237 switch(pep
->pep_TransType
)
8239 case USEAF_INTERRUPT
:
8240 if(!pep
->pep_Interval
)
8242 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8243 (STRPTR
) "Full", eptype
, (STRPTR
) "zero");
8244 pep
->pep_Interval
= 1;
8250 pep
->pep_Interval
= 0; // no use here
8253 case USEAF_ISOCHRONOUS
:
8254 if(pep
->pep_MaxPktSize
> 1023)
8256 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint contains too high (%ld) MaxPktSize value! Fixing.", pep
->pep_MaxPktSize
);
8257 pep
->pep_MaxPktSize
= 1023;
8259 if(!pep
->pep_Interval
)
8261 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8262 (STRPTR
) "Full", eptype
, (STRPTR
) "zero");
8263 pep
->pep_Interval
= 1;
8265 else if(pep
->pep_Interval
> 16)
8267 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8268 (STRPTR
) "Full", eptype
, (STRPTR
) "too high");
8269 pep
->pep_Interval
= 16;
8271 pep
->pep_Interval
= 1<<(pep
->pep_Interval
-1);
8276 KPRINTF(2, (" Endpoint %ld\n", pep
->pep_EPNum
));
8277 KPRINTF(2, (" Direction : %s\n"
8278 " TransType : %ld\n"
8279 " MaxPktSize: %ld\n"
8280 " Interval : %ld\n",
8281 (pep
->pep_Direction
? "IN" : "OUT"),
8282 pep
->pep_TransType
, pep
->pep_MaxPktSize
,
8283 pep
->pep_Interval
));
8286 KPRINTF(20, (" Endpoint allocation failed\n"));
8289 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint without prior interface descriptor!");
8290 KPRINTF(20, (" Endpoint descriptor without Interface\n"));
8300 case UDT_CS_INTERFACE
:
8301 case UDT_CS_ENDPOINT
:
8302 case UDT_DEVICE_QUALIFIER
:
8303 case UDT_OTHERSPEED_QUALIFIER
:
8304 case UDT_INTERFACE_POWER
:
8306 //psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Skipping descriptor %02lx (pc=%p, pif=%p altpif=%p).", dbuf[1], pc, pif, altif);
8307 KPRINTF(1, ("Skipping unknown descriptor %ld.\n", dbuf
[1]));
8311 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Skipping unknown descriptor %02lx.", dbuf
[1]);
8312 KPRINTF(1, ("Skipping unknown descriptor %ld.\n", dbuf
[1]));
8315 // add descriptor to device
8316 pdd
= pAllocDescriptor(pd
, dbuf
);
8319 STRPTR descname
= NULL
;
8321 pdd
->pdd_Config
= pc
;
8322 pdd
->pdd_Interface
= altif
;
8323 pdd
->pdd_Endpoint
= pep
;
8324 if(pdd
->pdd_Interface
)
8326 if((pdd
->pdd_Type
>= UDT_CS_UNDEFINED
) && (pdd
->pdd_Type
<= UDT_CS_ENDPOINT
))
8328 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pdd
->pdd_CSSubType
<<24)|(pif
->pif_IfSubClass
<<16)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8331 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pdd
->pdd_CSSubType
<<24)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8336 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pif
->pif_IfSubClass
<<16)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8340 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8345 pdd
->pdd_Name
= descname
;
8350 KPRINTF(1, ("Configuration acquired!\n"));
8351 psdFreeVec(tempbuf
);
8354 //psdUnlockDevice(pd);
8357 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8358 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
8359 len
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8360 KPRINTF(15, ("GET_DESCRIPTOR failed %ld!\n", ioerr
));
8362 psdFreeVec(tempbuf
);
8364 KPRINTF(20, ("No memory for %ld bytes config temp buffer!\n", len
));
8367 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8368 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
8369 9, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8370 KPRINTF(15, ("GET_DESCRIPTOR (9) failed %ld!\n", ioerr
));
8372 psdUnlockDevice(pd
);
8375 psdUnlockDevice(pd
);
8380 /* /// "pPowerRecurseDrain()" */
8381 ULONG
pPowerRecurseDrain(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
8383 struct PsdDevice
*nextpd
;
8384 struct PsdConfig
*pc
;
8385 UWORD maxdrain
= 666;
8387 BOOL selfpwd
= TRUE
;
8388 pd
->pd_PowerDrain
= 0;
8390 /* look at config */
8391 if((pc
= pd
->pd_CurrentConfig
))
8394 /* if suspended, no more than 500µA are drained */
8395 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
8397 pd
->pd_PowerDrain
= (pc
->pc_MaxPower
>= 100) ? 3 : 1;
8398 return(pd
->pd_PowerDrain
);
8400 selfpwd
= ((pc
->pc_Attr
& USCAF_SELF_POWERED
) && (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
!= POCP_BUS_POWERED
)) ||
8401 (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
== POCP_SELF_POWERED
);
8402 maxdrain
= selfpwd
? 500 : 100;
8405 /* examine children */
8406 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8407 while(nextpd
->pd_Node
.ln_Succ
)
8409 if(nextpd
->pd_Hub
== pd
)
8411 childdrain
= pPowerRecurseDrain(ps
, nextpd
);
8412 // limit the drain to the maximum power suckage
8413 pd
->pd_PowerDrain
+= (childdrain
> maxdrain
) ? maxdrain
: childdrain
;
8415 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8418 /* look at config */
8421 pd
->pd_PowerDrain
= 0;
8423 pd
->pd_PowerDrain
+= pc
->pc_MaxPower
;
8425 return(pd
->pd_PowerDrain
);
8429 /* /// "pPowerRecurseSupply()" */
8430 void pPowerRecurseSupply(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
8432 struct PsdDevice
*nextpd
;
8433 struct PsdConfig
*pc
;
8436 BOOL selfpwd
= TRUE
;
8438 /* look at config */
8439 if((pc
= pd
->pd_CurrentConfig
))
8441 selfpwd
= ((pc
->pc_Attr
& USCAF_SELF_POWERED
) && (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
!= POCP_BUS_POWERED
)) ||
8442 (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
== POCP_SELF_POWERED
);
8445 /* count children */
8446 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8447 while(nextpd
->pd_Node
.ln_Succ
)
8449 if(nextpd
->pd_Hub
== pd
) // this device is a child of us (we're a hub!)
8453 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8456 /* look at config */
8461 pd
->pd_PowerSupply
= ports
? 500*ports
+ pc
->pc_MaxPower
: pc
->pc_MaxPower
;
8463 supply
= 500; // each downstream port gets the full monty
8465 // the parent hub has already set the amount of supply for this port
8466 if(pd
->pd_PowerSupply
>= pc
->pc_MaxPower
)
8468 // the downstream ports get the remaining divided attention
8471 // avoid division by zero
8472 supply
= (pd
->pd_PowerSupply
- pc
->pc_MaxPower
) / ports
;
8475 // limit to 100 mA per port
8480 supply
= 1; // bad luck, out of power
8485 if(ports
) /* needs to be a hub */
8487 // propagate supply down to the children
8488 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8489 while(nextpd
->pd_Node
.ln_Succ
)
8491 if(nextpd
->pd_Hub
== pd
)
8493 nextpd
->pd_PowerSupply
= supply
;
8494 pPowerRecurseSupply(ps
, nextpd
);
8496 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8499 if(pd
->pd_PowerDrain
> pd
->pd_PowerSupply
)
8501 if(!(pd
->pd_Flags
& PDFF_LOWPOWER
))
8503 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8504 "Detected low power condition for '%s'.", pd
->pd_ProductStr
);
8505 pd
->pd_Flags
|= PDFF_LOWPOWER
;
8506 psdSendEvent(EHMB_DEVICELOWPW
, pd
, NULL
);
8509 if(pd
->pd_Flags
& PDFF_LOWPOWER
)
8511 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
8512 "Low power condition resolved for '%s'.", pd
->pd_ProductStr
);
8513 pd
->pd_Flags
&= ~PDFF_LOWPOWER
;
8519 /* /// "pGarbageCollectEvents()" */
8520 void pGarbageCollectEvents(LIBBASETYPEPTR ps
)
8522 struct PsdEventNote
*pen
;
8523 while((pen
= (struct PsdEventNote
*) GetMsg(&ps
->ps_EventReplyPort
)))
8530 /* /// "pFindName()" */
8531 struct Node
* pFindName(LIBBASETYPEPTR ps
, struct List
*list
, STRPTR name
)
8533 struct Node
*res
= NULL
;
8538 res
= FindName(list
, name
);
8545 if((*name
== '/') || (*name
== ':'))
8557 /* /// "pStripString()" */
8558 void pStripString(LIBBASETYPEPTR ps
, STRPTR str
)
8560 STRPTR srcptr
= str
;
8561 STRPTR tarptr
= str
;
8562 STRPTR lastgoodchar
= str
;
8563 BOOL leadingspaces
= TRUE
;
8567 while((ch
= *srcptr
++))
8578 lastgoodchar
= tarptr
;
8579 leadingspaces
= FALSE
;
8584 if((str
== lastgoodchar
) && (len
> 6))
8586 strcpy(str
, "<empty>");
8591 /* /// "pFixBrokenConfig()" */
8592 BOOL
pFixBrokenConfig(struct PsdPipe
*pp
)
8594 struct PsdDevice
*pd
= pp
->pp_Device
;
8595 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
8596 struct PsdConfig
*pc
;
8597 struct PsdInterface
*pif
;
8600 switch(pd
->pd_VendorID
)
8602 case 0x03eb: /* Atmel */
8603 if(pd
->pd_ProductID
== 0x3312)
8605 psdFreeVec(pd
->pd_ProductStr
);
8606 pd
->pd_ProductStr
= psdCopyStr("Highway/Subway Root Hub");
8610 case 0x04e6: /* E-Shuttle */
8611 if(pd
->pd_ProductID
== 0x0001) /* LS120 */
8613 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8614 /* Get msd interface and fix it */
8615 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8616 if(pif
->pif_IfClass
!= MASSSTORE_CLASSCODE
)
8619 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "E-Shuttle LS120");
8620 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8621 pif
->pif_IfSubClass
= MS_ATAPI_SUBCLASS
;
8622 pif
->pif_IfProto
= MS_PROTO_CB
;
8627 case 0x054C: /* Sony */
8628 if((pd
->pd_ProductID
== 0x002E) || (pd
->pd_ProductID
== 0x0010)) /* Handycam */
8631 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Sony MSD");
8632 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8633 /* Get msd interface and fix it */
8634 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8635 pif
->pif_IfSubClass
= MS_RBC_SUBCLASS
;
8639 case 0x057b: /* Y-E Data */
8640 if(pd
->pd_ProductID
== 0x0000) /* Flashbuster U */
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 if(pif
->pif_IfClass
!= MASSSTORE_CLASSCODE
)
8648 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Y-E Data USB Floppy");
8649 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8650 pif
->pif_IfSubClass
= MS_UFI_SUBCLASS
;
8651 pif
->pif_IfProto
= (pd
->pd_DevVers
< 0x0300) ? MS_PROTO_CB
: MS_PROTO_CBI
;
8656 case 0x04ce: /* ScanLogic */
8657 if(pd
->pd_ProductID
== 0x0002)
8659 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "ScanLogic");
8660 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8661 /* Get msd interface and fix it */
8662 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8664 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8668 case 0x0584: /* Ratoc cardreader */
8669 if(pd
->pd_ProductID
== 0x0008)
8671 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "RATOC");
8672 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8673 /* Get msd interface and fix it */
8674 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8676 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8677 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8678 pif
->pif_IfProto
= MS_PROTO_BULK
;
8682 case 0x04b8: /* Epson */
8683 if(pd
->pd_ProductID
== 0x0602) /* EPX Storage device (Card slot in Printer) */
8685 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Epson storage");
8686 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8687 /* Get msd interface and fix it */
8688 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8690 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8691 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8692 pif
->pif_IfProto
= MS_PROTO_BULK
;
8703 /* /// "pOpenDOS()" */
8704 BOOL
pOpenDOS(LIBBASETYPEPTR ps
)
8710 if((DOSBase
= OpenLibrary("dos.library", 39)))
8718 /* *** Class Scan Task *** */
8720 /* /// "pStartEventHandler()" */
8721 BOOL
pStartEventHandler(LIBBASETYPEPTR ps
)
8723 struct PsdHandlerTask
*ph
= &ps
->ps_EventHandler
;
8725 ObtainSemaphore(&ps
->ps_PoPoLock
);
8728 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8731 ph
->ph_ReadySignal
= SIGB_SINGLE
;
8732 ph
->ph_ReadySigTask
= FindTask(NULL
);
8733 SetSignal(0, SIGF_SINGLE
); // clear single bit
8734 if(psdSpawnSubTask("Poseidon Event Broadcast", pEventHandlerTask
, ps
))
8736 Wait(1UL<<ph
->ph_ReadySignal
);
8738 ph
->ph_ReadySigTask
= NULL
;
8739 //FreeSignal(ph->ph_ReadySignal);
8742 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8743 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Event broadcaster started.");
8746 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8751 /* *** Hardware Driver Task *** */
8753 /* /// "pQuickForwardRequest()" */
8754 AROS_UFH1(void, pQuickForwardRequest
,
8755 AROS_UFHA(struct MsgPort
*, msgport
, A1
))
8758 struct PsdHardware
*phw
= (struct PsdHardware
*) msgport
->mp_Node
.ln_Name
;
8761 while((pp
= (struct PsdPipe
*) RemHead(&msgport
->mp_MsgList
)))
8763 if(pp
->pp_AbortPipe
)
8765 KPRINTF(2, ("Abort pipe %p\n", pp
->pp_AbortPipe
));
8766 AbortIO((struct IORequest
*) &pp
->pp_AbortPipe
->pp_IOReq
);
8767 ReplyMsg(&pp
->pp_Msg
);
8768 KPRINTF(2, ("Replying evil pipe %p\n", pp
));
8770 KPRINTF(1, ("Forwarding pipe %p\n", pp
));
8771 pp
->pp_IOReq
.iouh_UserData
= pp
;
8772 SendIO((struct IORequest
*) &pp
->pp_IOReq
);
8773 ++phw
->phw_MsgCount
;
8780 /* /// "pQuickReplyRequest()" */
8781 AROS_UFH1(void, pQuickReplyRequest
,
8782 AROS_UFHA(struct MsgPort
*, msgport
, A1
))
8785 struct PsdHardware
*phw
= (struct PsdHardware
*) msgport
->mp_Node
.ln_Name
;
8786 struct IOUsbHWReq
*ioreq
;
8788 while((ioreq
= (struct IOUsbHWReq
*) RemHead(&msgport
->mp_MsgList
)))
8790 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8791 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8792 --phw
->phw_MsgCount
;
8798 /* /// "pDeviceTask()" */
8799 AROS_UFH0(void, pDeviceTask
)
8803 struct PsdHardware
*phw
;
8804 struct Task
*thistask
;
8808 struct TagItem taglist
[11];
8809 struct TagItem
*tag
;
8811 struct IOUsbHWReq
*ioreq
;
8813 STRPTR prodname
= NULL
;
8814 STRPTR manufacturer
= NULL
;
8815 STRPTR description
= NULL
;
8816 STRPTR copyright
= NULL
;
8819 ULONG driververs
= 0x0100;
8820 ULONG caps
= UHCF_ISO
;
8824 if(!(ps
= (LIBBASETYPEPTR
) OpenLibrary("poseidon.library", 4)))
8829 thistask
= FindTask(NULL
);
8830 SetTaskPri(thistask
, 21);
8831 phw
= thistask
->tc_UserData
;
8833 #ifndef PA_CALLBACK // undocumented exec feature
8834 #define PA_CALLBACK 3
8837 phw
->phw_TaskMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
8838 phw
->phw_TaskMsgPort
.mp_Node
.ln_Name
= (APTR
) phw
;
8839 phw
->phw_TaskMsgPort
.mp_Flags
= PA_SIGNAL
;
8840 phw
->phw_TaskMsgPort
.mp_SigTask
= thistask
;
8841 phw
->phw_TaskMsgPort
.mp_SigBit
= AllocSignal(-1L);
8842 NewList(&phw
->phw_TaskMsgPort
.mp_MsgList
);
8844 phw
->phw_DevMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
8845 phw
->phw_DevMsgPort
.mp_Node
.ln_Name
= (APTR
) phw
;
8846 phw
->phw_DevMsgPort
.mp_Flags
= PA_SIGNAL
;
8847 phw
->phw_DevMsgPort
.mp_SigTask
= thistask
;
8848 phw
->phw_DevMsgPort
.mp_SigBit
= AllocSignal(-1L);
8849 NewList(&phw
->phw_DevMsgPort
.mp_MsgList
);
8851 if((phw
->phw_RootIOReq
= (struct IOUsbHWReq
*) CreateIORequest(&phw
->phw_DevMsgPort
, sizeof(struct IOUsbHWReq
))))
8853 devname
= phw
->phw_DevName
;
8857 if(!(ioerr
= OpenDevice(devname
, phw
->phw_Unit
, (struct IORequest
*) phw
->phw_RootIOReq
, 0)))
8863 if((*devname
== '/') || (*devname
== ':'))
8868 } while(*(++devname
));
8873 phw
->phw_Node
.ln_Name
= phw
->phw_RootIOReq
->iouh_Req
.io_Device
->dd_Library
.lib_Node
.ln_Name
;
8875 tag
->ti_Tag
= UHA_ProductName
;
8876 tag
->ti_Data
= (IPTR
) &prodname
;
8878 tag
->ti_Tag
= UHA_Manufacturer
;
8879 tag
->ti_Data
= (IPTR
) &manufacturer
;
8881 tag
->ti_Tag
= UHA_Description
;
8882 tag
->ti_Data
= (IPTR
) &description
;
8884 tag
->ti_Tag
= UHA_Version
;
8885 tag
->ti_Data
= (IPTR
) &version
;
8887 tag
->ti_Tag
= UHA_Revision
;
8888 tag
->ti_Data
= (IPTR
) &revision
;
8890 tag
->ti_Tag
= UHA_Copyright
;
8891 tag
->ti_Data
= (IPTR
) ©right
;
8893 tag
->ti_Tag
= UHA_DriverVersion
;
8894 tag
->ti_Data
= (IPTR
) &driververs
;
8896 tag
->ti_Tag
= UHA_Capabilities
;
8897 tag
->ti_Data
= (IPTR
) &caps
;
8899 tag
->ti_Tag
= TAG_END
;
8900 phw
->phw_RootIOReq
->iouh_Data
= taglist
;
8901 phw
->phw_RootIOReq
->iouh_Req
.io_Command
= UHCMD_QUERYDEVICE
;
8902 DoIO((struct IORequest
*) phw
->phw_RootIOReq
);
8904 phw
->phw_ProductName
= psdCopyStr(prodname
? prodname
: (STRPTR
) "n/a");
8905 phw
->phw_Manufacturer
= psdCopyStr(manufacturer
? manufacturer
: (STRPTR
) "n/a");
8906 phw
->phw_Description
= psdCopyStr(description
? description
: (STRPTR
) "n/a");
8907 phw
->phw_Copyright
= psdCopyStr(copyright
? copyright
: (STRPTR
) "n/a");
8908 phw
->phw_Version
= version
;
8909 phw
->phw_Revision
= revision
;
8910 phw
->phw_DriverVers
= driververs
;
8911 phw
->phw_Capabilities
= caps
;
8913 sigmask
= SIGBREAKF_CTRL_C
;
8914 if(caps
& UHCF_QUICKIO
)
8916 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Enabling QuickIO for %s.", prodname
);
8917 phw
->phw_TaskMsgPort
.mp_Flags
= PA_CALLBACK
;
8918 phw
->phw_TaskMsgPort
.mp_SigTask
= (APTR
) pQuickForwardRequest
;
8920 phw
->phw_DevMsgPort
.mp_Flags
= PA_CALLBACK
;
8921 phw
->phw_DevMsgPort
.mp_SigTask
= (APTR
) pQuickReplyRequest
;
8923 sigmask
|= (1UL<<phw
->phw_DevMsgPort
.mp_SigBit
)|(1UL<<phw
->phw_TaskMsgPort
.mp_SigBit
);
8926 KPRINTF(10, ("%s ready!\n", thistask
->tc_Node
.ln_Name
));
8927 phw
->phw_Task
= thistask
;
8929 psdLockWritePBase();
8930 AddTail(&ps
->ps_Hardware
, &phw
->phw_Node
);
8934 if(phw
->phw_ReadySigTask
)
8936 Signal(phw
->phw_ReadySigTask
, 1L<<phw
->phw_ReadySignal
);
8941 KPRINTF(1, ("Main loop wait.\n"));
8942 while((pp
= (struct PsdPipe
*) GetMsg(&phw
->phw_TaskMsgPort
)))
8944 if(pp
->pp_AbortPipe
)
8946 KPRINTF(2, ("Abort pipe %p\n", pp
->pp_AbortPipe
));
8947 AbortIO((struct IORequest
*) &pp
->pp_AbortPipe
->pp_IOReq
);
8948 ReplyMsg(&pp
->pp_Msg
);
8949 KPRINTF(2, ("Replying evil pipe %p\n", pp
));
8951 KPRINTF(1, ("Forwarding pipe %p\n", pp
));
8952 pp
->pp_IOReq
.iouh_UserData
= pp
;
8953 SendIO((struct IORequest
*) &pp
->pp_IOReq
);
8954 ++phw
->phw_MsgCount
;
8957 while((ioreq
= (struct IOUsbHWReq
*) GetMsg(&phw
->phw_DevMsgPort
)))
8959 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8960 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8961 --phw
->phw_MsgCount
;
8963 sigs
= Wait(sigmask
);
8964 } while(!(sigs
& SIGBREAKF_CTRL_C
));
8965 /* Flush all pending IO Requests */
8966 phw
->phw_RootIOReq
->iouh_Req
.io_Command
= CMD_FLUSH
;
8967 DoIO((struct IORequest
*) phw
->phw_RootIOReq
);
8969 while(phw
->phw_MsgCount
)
8971 KPRINTF(20, ("Still %ld iorequests pending!\n", phw
->phw_MsgCount
));
8975 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8976 "There are still %ld IORequests pending, before unit can go down. Driver buggy?",
8981 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8982 "Okay, I've waited long enough, sod these %ld IORequests.",
8984 phw
->phw_MsgCount
= 0;
8987 while((ioreq
= (struct IOUsbHWReq
*) GetMsg(&phw
->phw_DevMsgPort
)))
8989 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8990 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8991 --phw
->phw_MsgCount
;
8994 psdLockWritePBase();
8995 Remove(&phw
->phw_Node
);
8997 CloseDevice((struct IORequest
*) phw
->phw_RootIOReq
);
8999 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
9000 "Opening %s unit %ld failed %s (%ld).",
9001 phw
->phw_DevName
, phw
->phw_Unit
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
9003 DeleteIORequest((struct IORequest
*) phw
->phw_RootIOReq
);
9004 phw
->phw_RootIOReq
= NULL
;
9006 FreeSignal((LONG
) phw
->phw_TaskMsgPort
.mp_SigBit
);
9007 FreeSignal((LONG
) phw
->phw_DevMsgPort
.mp_SigBit
);
9009 CloseLibrary((struct Library
*) ps
);
9010 phw
->phw_Task
= NULL
;
9013 if(phw
->phw_ReadySigTask
)
9015 Signal(phw
->phw_ReadySigTask
, 1L<<phw
->phw_ReadySignal
);
9021 /* /// "pEventHandlerTask()" */
9022 AROS_UFH0(void, pEventHandlerTask
)
9026 struct Task
*thistask
;
9027 struct timeval currtime
;
9030 struct PsdUsbClass
*puc
;
9031 struct PsdHandlerTask
*ph
;
9032 struct PsdEventNote
*pen
;
9036 thistask
= FindTask(NULL
);
9037 ps
= thistask
->tc_UserData
;
9038 ph
= &ps
->ps_EventHandler
;
9039 SetTaskPri(thistask
, 0);
9041 if((ph
->ph_MsgPort
= CreateMsgPort()))
9043 if((ph
->ph_TimerMsgPort
= CreateMsgPort()))
9045 if((ph
->ph_TimerIOReq
= (struct timerequest
*) CreateIORequest(ph
->ph_TimerMsgPort
, sizeof(struct timerequest
))))
9047 if(!(OpenDevice("timer.device", UNIT_VBLANK
, (struct IORequest
*) ph
->ph_TimerIOReq
, 0)))
9049 ph
->ph_TimerIOReq
->tr_node
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
9050 ph
->ph_TimerIOReq
->tr_node
.io_Message
.mn_Node
.ln_Name
= "EventHandler";
9051 ph
->ph_TimerIOReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
9053 ph
->ph_EventHandler
= psdAddEventHandler(ph
->ph_MsgPort
, EHMF_CONFIGCHG
);
9054 if(ph
->ph_EventHandler
)
9056 ph
->ph_Task
= thistask
;
9058 if(ph
->ph_ReadySigTask
)
9060 Signal(ph
->ph_ReadySigTask
, 1L<<ph
->ph_ReadySignal
);
9064 ph
->ph_TimerIOReq
->tr_time
.tv_micro
= 500*1000;
9065 SendIO(&ph
->ph_TimerIOReq
->tr_node
);
9066 sigmask
= (1UL<<ph
->ph_MsgPort
->mp_SigBit
)|(1UL<<ph
->ph_TimerMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
9071 if(ps
->ps_CheckConfigReq
)
9073 pCheckCfgChanged(ps
);
9075 while((pen
= (struct PsdEventNote
*) GetMsg(ph
->ph_MsgPort
)))
9077 switch(pen
->pen_Event
)
9079 case EHMB_CONFIGCHG
:
9082 cfgchanged
= counter
;
9087 ReplyMsg(&pen
->pen_Msg
);
9089 if(CheckIO(&ph
->ph_TimerIOReq
->tr_node
))
9092 WaitIO(&ph
->ph_TimerIOReq
->tr_node
);
9093 ph
->ph_TimerIOReq
->tr_time
.tv_micro
= 500*1000;
9094 SendIO(&ph
->ph_TimerIOReq
->tr_node
);
9096 startpopo
= !((counter
& 3) || ps
->ps_PoPo
.po_Task
);
9097 if((ps
->ps_GlobalCfg
->pgc_PopupDeviceNew
== PGCP_NEVER
) &&
9098 (!ps
->ps_GlobalCfg
->pgc_PopupDeviceDeath
) &&
9099 (!ps
->ps_GlobalCfg
->pgc_PopupDeviceGone
))
9101 startpopo
= FALSE
; // no need to start popo, no windows wanted
9105 struct PsdPoPo
*po
= &ps
->ps_PoPo
;
9107 po
->po_ReadySignal
= SIGB_SINGLE
;
9108 po
->po_ReadySigTask
= FindTask(NULL
);
9109 SetSignal(0, SIGF_SINGLE
); // clear single bit
9110 if(psdSpawnSubTask("PoPo (Poseidon Popups)", pPoPoGUITask
, ps
))
9112 Wait(1UL<<po
->po_ReadySignal
);
9114 po
->po_ReadySigTask
= NULL
;
9115 //FreeSignal(po->po_ReadySignal);
9118 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "PoPo kicks ass.");
9121 if((cfgchanged
+ 2) == counter
)
9123 KPRINTF(10, ("Sending information about config changed to all classes.\n"));
9124 /* Inform all classes */
9126 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
9127 while(puc
->puc_Node
.ln_Succ
)
9129 usbDoMethod(UCM_ConfigChangedEvent
);
9130 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
9135 // power saving stuff, check every second
9136 if((counter
& 1) && ps
->ps_GlobalCfg
->pgc_PowerSaving
)
9138 struct PsdDevice
*pd
= NULL
;
9139 struct PsdInterface
*pif
;
9140 GetSysTime((APTR
) &currtime
);
9141 while((pd
= psdGetNextDevice(pd
)))
9143 if((pd
->pd_DevClass
!= HUB_CLASSCODE
) &&
9144 ((pd
->pd_Flags
& (PDFF_CONFIGURED
|PDFF_DEAD
|PDFF_SUSPENDED
|PDFF_APPBINDING
|PDFF_DELEXPUNGE
)) == PDFF_CONFIGURED
))
9146 if(pd
->pd_LastActivity
.tv_secs
&& ((currtime
.tv_secs
- pd
->pd_LastActivity
.tv_secs
) > ps
->ps_GlobalCfg
->pgc_SuspendTimeout
))
9150 if(!((pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
) && ps
->ps_GlobalCfg
->pgc_ForceSuspend
))
9152 if(pd
->pd_DevBinding
&& ((puc
= pd
->pd_ClsBinding
)))
9155 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
9161 pif
= (struct PsdInterface
*) pd
->pd_CurrentConfig
->pc_Interfaces
.lh_Head
;
9162 while(pif
->pif_Node
.ln_Succ
)
9164 if(pif
->pif_IfBinding
&& ((puc
= pif
->pif_ClsBinding
)))
9167 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
9174 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
9179 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Suspending '%s'.", pd
->pd_ProductStr
);
9180 psdSuspendDevice(pd
);
9182 pd
->pd_LastActivity
.tv_secs
= 0;
9188 sigs
= Wait(sigmask
);
9189 } while(!(sigs
& SIGBREAKF_CTRL_C
));
9190 psdRemEventHandler(ph
->ph_EventHandler
);
9191 ph
->ph_EventHandler
= NULL
;
9192 AbortIO(&ph
->ph_TimerIOReq
->tr_node
);
9193 WaitIO(&ph
->ph_TimerIOReq
->tr_node
);
9195 CloseDevice((struct IORequest
*) ph
->ph_TimerIOReq
);
9197 DeleteIORequest((struct IORequest
*) ph
->ph_TimerIOReq
);
9199 DeleteMsgPort(ph
->ph_TimerMsgPort
);
9201 DeleteMsgPort(ph
->ph_MsgPort
);
9202 ph
->ph_MsgPort
= NULL
;
9206 if(ph
->ph_ReadySigTask
)
9208 Signal(ph
->ph_ReadySigTask
, 1L<<ph
->ph_ReadySignal
);
9214 /*****************************************************************/
9216 /* /// "Packtables for psdGetAttrs() and psdSetAttrs() " */
9217 /* Pack table for PsdBase */
9218 static const ULONG PsdBasePT
[] =
9220 PACK_STARTTABLE(PA_Dummy
),
9221 PACK_ENTRY(PA_Dummy
, PA_ConfigRead
, PsdBase
, ps_ConfigRead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9222 PACK_ENTRY(PA_Dummy
, PA_GlobalConfig
, PsdBase
, ps_GlobalCfg
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9223 PACK_ENTRY(PA_Dummy
, PA_MemPoolUsage
, PsdBase
, ps_MemAllocated
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9224 PACK_ENTRY(PA_Dummy
, PA_CurrConfigHash
, PsdBase
, ps_ConfigHash
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9225 PACK_ENTRY(PA_Dummy
, PA_SavedConfigHash
, PsdBase
, ps_SavedConfigHash
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9226 PACK_ENTRY(PA_Dummy
, PA_ReleaseVersion
, PsdBase
, ps_ReleaseVersion
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9227 PACK_ENTRY(PA_Dummy
, PA_OSVersion
, PsdBase
, ps_OSVersion
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9231 /* Pack table for PsdErrorMsg */
9232 static const ULONG PsdErrorMsgPT
[] =
9234 PACK_STARTTABLE(EMA_Dummy
),
9235 PACK_ENTRY(EMA_Dummy
, EMA_Level
, PsdErrorMsg
, pem_Level
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9236 PACK_ENTRY(EMA_Dummy
, EMA_Origin
, PsdErrorMsg
, pem_Origin
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9237 PACK_ENTRY(EMA_Dummy
, EMA_Msg
, PsdErrorMsg
, pem_Msg
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9241 /* Pack table for PsdUsbClass */
9242 static const ULONG PsdUsbClassPT
[] =
9244 PACK_STARTTABLE(UCA_Dummy
),
9245 PACK_ENTRY(UCA_Dummy
, UCA_ClassBase
, PsdUsbClass
, puc_ClassBase
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9246 PACK_ENTRY(UCA_Dummy
, UCA_ClassName
, PsdUsbClass
, puc_ClassName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9247 PACK_ENTRY(UCA_Dummy
, UCA_FullPath
, PsdUsbClass
, puc_FullPath
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9248 PACK_ENTRY(UCA_Dummy
, UCA_UseCount
, PsdUsbClass
, puc_UseCnt
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9252 /* Pack table for PsdHardware */
9253 static const ULONG PsdHardwarePT
[] =
9255 PACK_STARTTABLE(HA_Dummy
),
9256 PACK_ENTRY(HA_Dummy
, HA_DeviceName
, PsdHardware
, phw_DevName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9257 PACK_ENTRY(HA_Dummy
, HA_DeviceUnit
, PsdHardware
, phw_Unit
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9258 PACK_ENTRY(HA_Dummy
, HA_ProductName
, PsdHardware
, phw_ProductName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9259 PACK_ENTRY(HA_Dummy
, HA_Manufacturer
, PsdHardware
, phw_Manufacturer
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9260 PACK_ENTRY(HA_Dummy
, HA_Description
, PsdHardware
, phw_Description
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9261 PACK_ENTRY(HA_Dummy
, HA_Copyright
, PsdHardware
, phw_Copyright
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9262 PACK_ENTRY(HA_Dummy
, HA_Version
, PsdHardware
, phw_Version
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9263 PACK_ENTRY(HA_Dummy
, HA_Revision
, PsdHardware
, phw_Revision
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9264 PACK_ENTRY(HA_Dummy
, HA_DriverVersion
, PsdHardware
, phw_DriverVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9268 /* Pack table for PsdDevice */
9269 static const ULONG PsdDevicePT
[] =
9271 PACK_STARTTABLE(DA_Dummy
),
9272 PACK_ENTRY(DA_Dummy
, DA_Address
, PsdDevice
, pd_DevAddr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9273 PACK_ENTRY(DA_Dummy
, DA_NumConfigs
, PsdDevice
, pd_NumCfgs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9274 PACK_ENTRY(DA_Dummy
, DA_CurrConfig
, PsdDevice
, pd_CurrCfg
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9275 PACK_ENTRY(DA_Dummy
, DA_Config
, PsdDevice
, pd_CurrentConfig
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9276 PACK_ENTRY(DA_Dummy
, DA_HubDevice
, PsdDevice
, pd_Hub
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9277 PACK_ENTRY(DA_Dummy
, DA_UsbVersion
, PsdDevice
, pd_USBVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9278 PACK_ENTRY(DA_Dummy
, DA_Class
, PsdDevice
, pd_DevClass
, PKCTRL_WORD
|PKCTRL_UNPACKONLY
),
9279 PACK_ENTRY(DA_Dummy
, DA_SubClass
, PsdDevice
, pd_DevSubClass
, PKCTRL_WORD
|PKCTRL_UNPACKONLY
),
9280 PACK_ENTRY(DA_Dummy
, DA_Protocol
, PsdDevice
, pd_DevProto
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9281 PACK_ENTRY(DA_Dummy
, DA_VendorID
, PsdDevice
, pd_VendorID
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9282 PACK_ENTRY(DA_Dummy
, DA_MaxPktSize0
, PsdDevice
, pd_MaxPktSize0
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9283 PACK_ENTRY(DA_Dummy
, DA_ProductID
, PsdDevice
, pd_ProductID
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9284 PACK_ENTRY(DA_Dummy
, DA_Version
, PsdDevice
, pd_DevVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9285 PACK_ENTRY(DA_Dummy
, DA_Manufacturer
, PsdDevice
, pd_MnfctrStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9286 PACK_ENTRY(DA_Dummy
, DA_ProductName
, PsdDevice
, pd_ProductStr
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9287 PACK_ENTRY(DA_Dummy
, DA_OrigProductName
, PsdDevice
, pd_OldProductStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9288 PACK_ENTRY(DA_Dummy
, DA_SerialNumber
, PsdDevice
, pd_SerNumStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9289 PACK_ENTRY(DA_Dummy
, DA_Hardware
, PsdDevice
, pd_Hardware
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9290 PACK_ENTRY(DA_Dummy
, DA_Binding
, PsdDevice
, pd_DevBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9291 PACK_ENTRY(DA_Dummy
, DA_BindingClass
, PsdDevice
, pd_ClsBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9292 PACK_ENTRY(DA_Dummy
, DA_LangIDArray
, PsdDevice
, pd_LangIDArray
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9293 PACK_ENTRY(DA_Dummy
, DA_CurrLangID
, PsdDevice
, pd_CurrLangID
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9294 PACK_ENTRY(DA_Dummy
, DA_IDString
, PsdDevice
, pd_IDString
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9295 PACK_ENTRY(DA_Dummy
, DA_CloneCount
, PsdDevice
, pd_CloneCount
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9296 PACK_ENTRY(DA_Dummy
, DA_AtHubPortNumber
, PsdDevice
, pd_HubPort
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9297 PACK_ENTRY(DA_Dummy
, DA_PowerDrained
, PsdDevice
, pd_PowerDrain
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9298 PACK_ENTRY(DA_Dummy
, DA_PowerSupply
, PsdDevice
, pd_PowerSupply
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9299 PACK_ENTRY(DA_Dummy
, DA_IsNewToMe
, PsdDevice
, pd_IsNewToMe
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9300 PACK_ENTRY(DA_Dummy
, DA_InhibitPopup
, PsdDevice
, pd_PoPoCfg
.poc_InhibitPopup
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9301 PACK_ENTRY(DA_Dummy
, DA_InhibitClassBind
, PsdDevice
, pd_PoPoCfg
.poc_NoClassBind
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9302 PACK_ENTRY(DA_Dummy
, DA_OverridePowerInfo
, PsdDevice
, pd_PoPoCfg
.poc_OverridePowerInfo
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9303 PACK_ENTRY(DA_Dummy
, DA_HubThinkTime
, PsdDevice
, pd_HubThinkTime
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9304 PACK_WORDBIT(DA_Dummy
, DA_IsLowspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_LOWSPEED
),
9305 PACK_WORDBIT(DA_Dummy
, DA_IsHighspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HIGHSPEED
),
9306 PACK_WORDBIT(DA_Dummy
, DA_IsConnected
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_CONNECTED
),
9307 PACK_WORDBIT(DA_Dummy
, DA_HasAddress
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HASDEVADDR
),
9308 PACK_WORDBIT(DA_Dummy
, DA_HasDevDesc
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HASDEVDESC
),
9309 PACK_WORDBIT(DA_Dummy
, DA_IsConfigured
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_CONFIGURED
),
9310 PACK_WORDBIT(DA_Dummy
, DA_IsDead
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_DEAD
),
9311 PACK_WORDBIT(DA_Dummy
, DA_IsSuspended
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_SUSPENDED
),
9312 PACK_WORDBIT(DA_Dummy
, DA_HasAppBinding
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_APPBINDING
),
9313 PACK_WORDBIT(DA_Dummy
, DA_NeedsSplitTrans
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_NEEDSSPLIT
),
9314 PACK_WORDBIT(DA_Dummy
, DA_LowPower
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_LOWPOWER
),
9315 #ifdef AROS_USB30_CODE
9316 PACK_WORDBIT(DA_Dummy
, DA_IsSuperspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_SUPERSPEED
),
9321 /* Pack table for PsdConfig */
9322 static const ULONG PsdConfigPT
[] =
9324 PACK_STARTTABLE(CA_Dummy
),
9325 PACK_ENTRY(CA_Dummy
, CA_ConfigNum
, PsdConfig
, pc_CfgNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9326 PACK_ENTRY(CA_Dummy
, CA_MaxPower
, PsdConfig
, pc_MaxPower
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9327 PACK_ENTRY(CA_Dummy
, CA_ConfigName
, PsdConfig
, pc_CfgStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9328 PACK_ENTRY(CA_Dummy
, CA_NumInterfaces
, PsdConfig
, pc_NumIfs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9329 PACK_ENTRY(CA_Dummy
, CA_Attrs
, PsdConfig
, pc_Attr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9330 PACK_ENTRY(CA_Dummy
, CA_Device
, PsdConfig
, pc_Device
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9331 PACK_WORDBIT(CA_Dummy
, CA_SelfPowered
, PsdConfig
, pc_Attr
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, USCAF_SELF_POWERED
),
9332 PACK_WORDBIT(CA_Dummy
, CA_RemoteWakeup
, PsdConfig
, pc_Attr
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, USCAF_REMOTE_WAKEUP
),
9336 /* Pack table for PsdDescriptor */
9337 static const ULONG PsdDescriptorPT
[] =
9339 PACK_STARTTABLE(DDA_Dummy
),
9340 PACK_ENTRY(DDA_Dummy
, DDA_Device
, PsdDescriptor
, pdd_Device
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9341 PACK_ENTRY(DDA_Dummy
, DDA_Config
, PsdDescriptor
, pdd_Config
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9342 PACK_ENTRY(DDA_Dummy
, DDA_Interface
, PsdDescriptor
, pdd_Interface
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9343 PACK_ENTRY(DDA_Dummy
, DDA_Endpoint
, PsdDescriptor
, pdd_Endpoint
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9344 PACK_ENTRY(DDA_Dummy
, DDA_Name
, PsdDescriptor
, pdd_Name
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9345 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorType
, PsdDescriptor
, pdd_Type
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9346 PACK_ENTRY(DDA_Dummy
, DDA_CS_SubType
, PsdDescriptor
, pdd_CSSubType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9347 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorData
, PsdDescriptor
, pdd_Data
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9348 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorLength
, PsdDescriptor
, pdd_Length
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9352 /* Pack table for PsdInterface */
9353 static const ULONG PsdInterfacePT
[] =
9355 PACK_STARTTABLE(IFA_Dummy
),
9356 PACK_ENTRY(IFA_Dummy
, IFA_InterfaceNum
, PsdInterface
, pif_IfNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9357 PACK_ENTRY(IFA_Dummy
, IFA_AlternateNum
, PsdInterface
, pif_Alternate
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9358 PACK_ENTRY(IFA_Dummy
, IFA_NumEndpoints
, PsdInterface
, pif_NumEPs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9359 PACK_ENTRY(IFA_Dummy
, IFA_Class
, PsdInterface
, pif_IfClass
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9360 PACK_ENTRY(IFA_Dummy
, IFA_SubClass
, PsdInterface
, pif_IfSubClass
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9361 PACK_ENTRY(IFA_Dummy
, IFA_Protocol
, PsdInterface
, pif_IfProto
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9362 PACK_ENTRY(IFA_Dummy
, IFA_InterfaceName
, PsdInterface
, pif_IfStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9363 PACK_ENTRY(IFA_Dummy
, IFA_Config
, PsdInterface
, pif_Config
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9364 PACK_ENTRY(IFA_Dummy
, IFA_Binding
, PsdInterface
, pif_IfBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9365 PACK_ENTRY(IFA_Dummy
, IFA_BindingClass
, PsdInterface
, pif_ClsBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9366 PACK_ENTRY(IFA_Dummy
, IFA_IDString
, PsdInterface
, pif_IDString
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9370 /* Pack table for PsdEndpoint */
9371 static const ULONG PsdEndpointPT
[] =
9373 PACK_STARTTABLE(EA_Dummy
),
9374 PACK_ENTRY(EA_Dummy
, EA_EndpointNum
, PsdEndpoint
, pep_EPNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9375 PACK_ENTRY(EA_Dummy
, EA_TransferType
, PsdEndpoint
, pep_TransType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9376 PACK_ENTRY(EA_Dummy
, EA_MaxPktSize
, PsdEndpoint
, pep_MaxPktSize
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9377 PACK_ENTRY(EA_Dummy
, EA_Interval
, PsdEndpoint
, pep_Interval
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9378 PACK_ENTRY(EA_Dummy
, EA_NumTransMuFrame
, PsdEndpoint
, pep_NumTransMuFr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9379 PACK_ENTRY(EA_Dummy
, EA_SyncType
, PsdEndpoint
, pep_SyncType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9380 PACK_ENTRY(EA_Dummy
, EA_UsageType
, PsdEndpoint
, pep_UsageType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9381 PACK_ENTRY(EA_Dummy
, EA_Interface
, PsdEndpoint
, pep_Interface
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9382 PACK_WORDBIT(EA_Dummy
, EA_IsIn
, PsdEndpoint
, pep_Direction
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, 1),
9386 /* Pack table for PsdPipe */
9387 static const ULONG PsdPipePT
[] =
9389 PACK_STARTTABLE(PPA_Dummy
),
9390 PACK_ENTRY(PPA_Dummy
, PPA_Endpoint
, PsdPipe
, pp_Endpoint
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9391 PACK_ENTRY(PPA_Dummy
, PPA_Error
, PsdPipe
, pp_IOReq
.iouh_Req
.io_Error
, PKCTRL_BYTE
|PKCTRL_UNPACKONLY
),
9392 PACK_ENTRY(PPA_Dummy
, PPA_Actual
, PsdPipe
, pp_IOReq
.iouh_Actual
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9393 PACK_ENTRY(PPA_Dummy
, PPA_EndpointNum
, PsdPipe
, pp_IOReq
.iouh_Endpoint
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9394 PACK_ENTRY(PPA_Dummy
, PPA_DeviceAddress
, PsdPipe
, pp_IOReq
.iouh_DevAddr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9395 PACK_ENTRY(PPA_Dummy
, PPA_MaxPktSize
, PsdPipe
, pp_IOReq
.iouh_MaxPktSize
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9396 PACK_ENTRY(PPA_Dummy
, PPA_NakTimeoutTime
, PsdPipe
, pp_IOReq
.iouh_NakTimeout
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9397 PACK_ENTRY(PPA_Dummy
, PPA_Interval
, PsdPipe
, pp_IOReq
.iouh_Interval
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9398 PACK_WORDBIT(PPA_Dummy
, PPA_NoShortPackets
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_NOSHORTPKT
),
9399 PACK_WORDBIT(PPA_Dummy
, PPA_NakTimeout
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_NAKTIMEOUT
),
9400 PACK_WORDBIT(PPA_Dummy
, PPA_AllowRuntPackets
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_ALLOWRUNTPKTS
),
9404 /* Pack table for PsdAppBinding */
9405 static const ULONG PsdAppBindingPT
[] =
9407 PACK_STARTTABLE(ABA_Dummy
),
9408 PACK_ENTRY(ABA_Dummy
, ABA_ReleaseHook
, PsdAppBinding
, pab_ReleaseHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9409 PACK_ENTRY(ABA_Dummy
, ABA_Device
, PsdAppBinding
, pab_Device
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9410 PACK_ENTRY(ABA_Dummy
, ABA_UserData
, PsdAppBinding
, pab_UserData
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9411 PACK_ENTRY(ABA_Dummy
, ABA_Task
, PsdAppBinding
, pab_Task
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9412 PACK_ENTRY(ABA_Dummy
, ABA_ForceRelease
, PsdAppBinding
, pab_ForceRelease
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9416 /* Pack table for PsdAppBinding */
9417 static const ULONG PsdEventNotePT
[] =
9419 PACK_STARTTABLE(ENA_Dummy
),
9420 PACK_ENTRY(ENA_Dummy
, ENA_EventID
, PsdEventNote
, pen_Event
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9421 PACK_ENTRY(ENA_Dummy
, ENA_Param1
, PsdEventNote
, pen_Param1
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9422 PACK_ENTRY(ENA_Dummy
, ENA_Param2
, PsdEventNote
, pen_Param2
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9426 /* Pack table for PsdGlobalCfg */
9427 static const ULONG PsdGlobalCfgPT
[] =
9429 PACK_STARTTABLE(GCA_Dummy
),
9430 PACK_ENTRY(GCA_Dummy
, GCA_LogInfo
, PsdGlobalCfg
, pgc_LogInfo
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9431 PACK_ENTRY(GCA_Dummy
, GCA_LogWarning
, PsdGlobalCfg
, pgc_LogWarning
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9432 PACK_ENTRY(GCA_Dummy
, GCA_LogError
, PsdGlobalCfg
, pgc_LogError
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9433 PACK_ENTRY(GCA_Dummy
, GCA_LogFailure
, PsdGlobalCfg
, pgc_LogFailure
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9434 PACK_ENTRY(GCA_Dummy
, GCA_BootDelay
, PsdGlobalCfg
, pgc_BootDelay
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9435 PACK_ENTRY(GCA_Dummy
, GCA_SubTaskPri
, PsdGlobalCfg
, pgc_SubTaskPri
, PKCTRL_WORD
|PKCTRL_PACKUNPACK
),
9436 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceNew
, PsdGlobalCfg
, pgc_PopupDeviceNew
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9437 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceGone
, PsdGlobalCfg
, pgc_PopupDeviceGone
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9438 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceDeath
, PsdGlobalCfg
, pgc_PopupDeviceDeath
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9439 PACK_ENTRY(GCA_Dummy
, GCA_PopupCloseDelay
, PsdGlobalCfg
, pgc_PopupCloseDelay
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9440 PACK_ENTRY(GCA_Dummy
, GCA_PopupActivateWin
, PsdGlobalCfg
, pgc_PopupActivateWin
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9441 PACK_ENTRY(GCA_Dummy
, GCA_PopupWinToFront
, PsdGlobalCfg
, pgc_PopupWinToFront
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9442 PACK_ENTRY(GCA_Dummy
, GCA_AutoDisableLP
, PsdGlobalCfg
, pgc_AutoDisableLP
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9443 PACK_ENTRY(GCA_Dummy
, GCA_AutoDisableDead
, PsdGlobalCfg
, pgc_AutoDisableDead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9444 PACK_ENTRY(GCA_Dummy
, GCA_AutoRestartDead
, PsdGlobalCfg
, pgc_AutoRestartDead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9445 PACK_ENTRY(GCA_Dummy
, GCA_PowerSaving
, PsdGlobalCfg
, pgc_PowerSaving
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9446 PACK_ENTRY(GCA_Dummy
, GCA_ForceSuspend
, PsdGlobalCfg
, pgc_ForceSuspend
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9447 PACK_ENTRY(GCA_Dummy
, GCA_SuspendTimeout
, PsdGlobalCfg
, pgc_SuspendTimeout
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9448 PACK_ENTRY(GCA_Dummy
, GCA_PrefsVersion
, PsdGlobalCfg
, pgc_PrefsVersion
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9452 /* Pack table for PsdPipeStream */
9453 static const ULONG PsdPipeStreamPT
[] =
9455 PACK_STARTTABLE(PSA_Dummy
),
9456 PACK_ENTRY(PSA_Dummy
, PSA_MessagePort
, PsdPipeStream
, pps_MsgPort
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9457 PACK_ENTRY(PSA_Dummy
, PSA_NumPipes
, PsdPipeStream
, pps_NumPipes
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9458 PACK_ENTRY(PSA_Dummy
, PSA_BufferSize
, PsdPipeStream
, pps_BufferSize
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9459 PACK_ENTRY(PSA_Dummy
, PSA_NakTimeoutTime
, PsdPipeStream
, pps_NakTimeoutTime
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9460 PACK_ENTRY(PSA_Dummy
, PSA_BytesPending
, PsdPipeStream
, pps_BytesPending
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9461 PACK_ENTRY(PSA_Dummy
, PSA_Error
, PsdPipeStream
, pps_Error
, PKCTRL_LONG
|PKCTRL_PACKUNPACK
),
9462 PACK_ENTRY(PSA_Dummy
, PSA_TermArray
, PsdPipeStream
, pps_TermArray
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9463 PACK_ENTRY(PSA_Dummy
, PSA_AbortSigMask
, PsdPipeStream
, pps_AbortSigMask
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9464 PACK_ENTRY(PSA_Dummy
, PSA_ActivePipe
, PsdPipeStream
, pps_ActivePipe
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9465 PACK_WORDBIT(PSA_Dummy
, PSA_AsyncIO
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_ASYNCIO
),
9466 PACK_WORDBIT(PSA_Dummy
, PSA_ShortPktTerm
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_SHORTTERM
),
9467 PACK_WORDBIT(PSA_Dummy
, PSA_ReadAhead
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_READAHEAD
),
9468 PACK_WORDBIT(PSA_Dummy
, PSA_BufferedRead
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_BUFFERREAD
),
9469 PACK_WORDBIT(PSA_Dummy
, PSA_BufferedWrite
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_BUFFERWRITE
),
9470 PACK_WORDBIT(PSA_Dummy
, PSA_NoZeroPktTerm
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_NOSHORTPKT
),
9471 PACK_WORDBIT(PSA_Dummy
, PSA_NakTimeout
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_NAKTIMEOUT
),
9472 PACK_WORDBIT(PSA_Dummy
, PSA_AllowRuntPackets
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_ALLOWRUNT
),
9473 PACK_WORDBIT(PSA_Dummy
, PSA_DoNotWait
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_DONOTWAIT
),
9477 /* Pack table for PsdRTIsoHandler */
9478 static const ULONG PsdRTIsoHandlerPT
[] =
9480 PACK_STARTTABLE(RTA_Dummy
),
9481 PACK_ENTRY(RTA_Dummy
, RTA_InRequestHook
, PsdRTIsoHandler
, prt_RTIso
.urti_InReqHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9482 PACK_ENTRY(RTA_Dummy
, RTA_OutRequestHook
, PsdRTIsoHandler
, prt_RTIso
.urti_OutReqHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9483 PACK_ENTRY(RTA_Dummy
, RTA_InDoneHook
, PsdRTIsoHandler
, prt_RTIso
.urti_InDoneHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9484 PACK_ENTRY(RTA_Dummy
, RTA_OutDoneHook
, PsdRTIsoHandler
, prt_RTIso
.urti_OutDoneHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9485 PACK_ENTRY(RTA_Dummy
, RTA_ReleaseHook
, PsdRTIsoHandler
, prt_ReleaseHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9486 PACK_ENTRY(RTA_Dummy
, RTA_OutPrefetchSize
, PsdRTIsoHandler
, prt_RTIso
.urti_OutPrefetch
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9490 /* PGA assignment table */
9491 static const ULONG
*PsdPTArray
[] =