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
? 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(IPTR
*, 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(IPTR
*, 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
)
2863 struct PsdDevice
*pd
= pp
->pp_Device
;
2864 struct PsdDevice
*itpd
= pp
->pp_Device
;
2865 struct PsdConfig
*pc
;
2866 struct PsdInterface
*pif
;
2867 struct UsbStdDevDesc usdd
;
2869 ULONG oldnaktimeout
;
2875 BOOL haspopupinhibit
;
2877 struct PsdIFFContext
*pic
;
2881 KPRINTF(2, ("psdEnumerateDevice(%p)\n", pp
));
2883 psdLockWriteDevice(pd
);
2884 if(pAllocDevAddr(pd
))
2886 oldflags
= pp
->pp_IOReq
.iouh_Flags
;
2887 oldnaktimeout
= pp
->pp_IOReq
.iouh_NakTimeout
;
2888 pp
->pp_IOReq
.iouh_Flags
|= UHFF_NAKTIMEOUT
;
2889 pp
->pp_IOReq
.iouh_NakTimeout
= 1000;
2890 pp
->pp_IOReq
.iouh_DevAddr
= 0;
2892 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
2893 USR_GET_DESCRIPTOR
, UDT_DEVICE
<<8, 0);
2894 ioerr
= psdDoPipe(pp
, dummybuf
, 8);
2895 if(ioerr
&& (ioerr
!= UHIOERR_RUNTPACKET
))
2897 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2898 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
2899 8, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2900 KPRINTF(15, ("GET_DESCRIPTOR (8) failed %ld!\n", ioerr
));
2902 KPRINTF(1, ("Setting DevAddr %ld...\n", pd
->pd_DevAddr
));
2903 psdPipeSetup(pp
, URTF_STANDARD
|URTF_DEVICE
,
2904 USR_SET_ADDRESS
, pd
->pd_DevAddr
, 0);
2905 ioerr
= psdDoPipe(pp
, NULL
, 0);
2906 /* This is tricky: Maybe the device has accepted the command,
2907 but failed to send an ACK. Now, every resend trial will
2908 go to the wrong address! */
2909 if((ioerr
== UHIOERR_TIMEOUT
) || (ioerr
== UHIOERR_STALL
))
2911 KPRINTF(1, ("First attempt failed, retrying new address\n"));
2912 /*pp->pp_IOReq.iouh_DevAddr = pd->pd_DevAddr;*/
2914 ioerr
= psdDoPipe(pp
, NULL
, 0);
2915 /*pp->pp_IOReq.iouh_DevAddr = 0;*/
2919 pd
->pd_Flags
|= PDFF_HASDEVADDR
|PDFF_CONNECTED
;
2920 pp
->pp_IOReq
.iouh_DevAddr
= pd
->pd_DevAddr
;
2922 psdDelayMS(50); /* Allowed time to settle */
2924 KPRINTF(1, ("Getting MaxPktSize0...\n"));
2925 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
2926 USR_GET_DESCRIPTOR
, UDT_DEVICE
<<8, 0);
2927 ioerr
= psdDoPipe(pp
, &usdd
, 8);
2930 switch(usdd
.bMaxPacketSize0
)
2936 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
= usdd
.bMaxPacketSize0
;
2939 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2940 "Illegal MaxPktSize0=%ld for endpoint 0",
2941 (ULONG
) usdd
.bMaxPacketSize0
);
2942 KPRINTF(2, ("Illegal MaxPktSize0=%ld!\n", usdd
.bMaxPacketSize0
));
2943 //pp->pp_IOReq.iouh_MaxPktSize = pd->pd_MaxPktSize0 = 8;
2944 ioerr
= UHIOERR_CRCERROR
;
2950 KPRINTF(1, (" MaxPktSize0 = %ld\n", pd
->pd_MaxPktSize0
));
2951 KPRINTF(1, ("Getting full descriptor...\n"));
2952 ioerr
= psdDoPipe(pp
, &usdd
, sizeof(struct UsbStdDevDesc
));
2955 pAllocDescriptor(pd
, (UBYTE
*) &usdd
);
2956 pd
->pd_Flags
|= PDFF_HASDEVDESC
;
2957 pd
->pd_USBVers
= AROS_WORD2LE(usdd
.bcdUSB
);
2958 pd
->pd_DevClass
= usdd
.bDeviceClass
;
2959 pd
->pd_DevSubClass
= usdd
.bDeviceSubClass
;
2960 pd
->pd_DevProto
= usdd
.bDeviceProtocol
;
2961 pd
->pd_VendorID
= AROS_WORD2LE(usdd
.idVendor
);
2962 pd
->pd_ProductID
= AROS_WORD2LE(usdd
.idProduct
);
2963 pd
->pd_DevVers
= AROS_WORD2LE(usdd
.bcdDevice
);
2964 vendorname
= psdNumToStr(NTS_VENDORID
, (LONG
) pd
->pd_VendorID
, NULL
);
2966 // patch to early determine highspeed roothubs
2967 if((!pd
->pd_Hub
) && (pd
->pd_USBVers
>= 0x200) && (pd
->pd_USBVers
< 0x300))
2969 pd
->pd_Flags
|= PDFF_HIGHSPEED
;
2971 #ifdef AROS_USB30_CODE
2972 if((!pd
->pd_Hub
) && (pd
->pd_USBVers
>= 0x300))
2974 pd
->pd_Flags
|= PDFF_SUPERSPEED
;
2978 if(usdd
.iManufacturer
)
2980 pd
->pd_MnfctrStr
= psdGetStringDescriptor(pp
, usdd
.iManufacturer
);
2984 pd
->pd_ProductStr
= psdGetStringDescriptor(pp
, usdd
.iProduct
);
2986 if(usdd
.iSerialNumber
)
2988 pd
->pd_SerNumStr
= psdGetStringDescriptor(pp
, usdd
.iSerialNumber
);
2990 if(!pd
->pd_MnfctrStr
)
2992 pd
->pd_MnfctrStr
= psdCopyStr(vendorname
? vendorname
: (STRPTR
) "n/a");
2994 if(!pd
->pd_ProductStr
)
2996 hasprodname
= FALSE
;
2997 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) pd
->pd_DevClass
, NULL
);
3000 pd
->pd_ProductStr
= psdCopyStrFmt("%s: Vdr=%04lx/PID=%04lx",
3001 classname
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3003 pd
->pd_ProductStr
= psdCopyStrFmt("Cls=%ld/Vdr=%04lx/PID=%04lx",
3004 pd
->pd_DevClass
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3009 if(!pd
->pd_SerNumStr
)
3011 pd
->pd_SerNumStr
= psdCopyStr("n/a");
3014 KPRINTF(2, ("Product : %s\n"
3015 "Manufacturer: %s\n"
3016 "SerialNumber: %s\n",
3017 pd
->pd_ProductStr
, pd
->pd_MnfctrStr
, pd
->pd_SerNumStr
));
3018 KPRINTF(2, ("USBVersion: %04lx\n"
3024 "DevVers : %04lx\n",
3025 pd
->pd_USBVers
, pd
->pd_DevClass
, pd
->pd_DevSubClass
, pd
->pd_DevProto
,
3026 pd
->pd_VendorID
, pd
->pd_ProductID
, pd
->pd_DevVers
));
3028 /* check for clones */
3030 while((itpd
= psdGetNextDevice(itpd
)))
3034 if((itpd
->pd_ProductID
== pd
->pd_ProductID
) &&
3035 (itpd
->pd_VendorID
== pd
->pd_VendorID
) &&
3036 (!strcmp(itpd
->pd_SerNumStr
, pd
->pd_SerNumStr
)) &&
3037 (itpd
->pd_CloneCount
== pd
->pd_CloneCount
))
3039 pd
->pd_CloneCount
++;
3045 pd
->pd_IDString
= psdCopyStrFmt("%s-%04lx-%04lx-%s-%02lx", pd
->pd_ProductStr
, pd
->pd_VendorID
, pd
->pd_ProductID
, pd
->pd_SerNumStr
, pd
->pd_CloneCount
);
3047 pStripString(ps
, pd
->pd_MnfctrStr
);
3048 pStripString(ps
, pd
->pd_ProductStr
);
3049 pStripString(ps
, pd
->pd_SerNumStr
);
3051 /* get custom name of device */
3052 pLockSemExcl(ps
, &ps
->ps_ConfigLock
); // Exclusive lock to avoid deadlock situation when promoting read to write
3053 pd
->pd_OldProductStr
= pd
->pd_ProductStr
;
3054 pd
->pd_ProductStr
= NULL
;
3055 haspopupinhibit
= FALSE
;
3056 pic
= psdGetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
);
3059 pd
->pd_IsNewToMe
= FALSE
;
3060 if((pd
->pd_ProductStr
= pGetStringChunk(ps
, pic
, IFFCHNK_NAME
)))
3064 if((chnk
= pFindCfgChunk(ps
, pic
, IFFCHNK_POPUP
)))
3066 struct PsdPoPoCfg
*poc
= (struct PsdPoPoCfg
*) chnk
;
3067 CopyMem(((UBYTE
*) poc
) + 8, ((UBYTE
*) &pd
->pd_PoPoCfg
) + 8, min(AROS_LONG2BE(poc
->poc_Length
), AROS_LONG2BE(pd
->pd_PoPoCfg
.poc_Length
)));
3068 haspopupinhibit
= TRUE
;
3071 pd
->pd_IsNewToMe
= TRUE
;
3072 psdSetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
, NULL
);
3074 if(!pd
->pd_ProductStr
)
3076 pd
->pd_ProductStr
= psdCopyStr(pd
->pd_OldProductStr
);
3078 if(!haspopupinhibit
)
3080 if(pd
->pd_DevClass
== HUB_CLASSCODE
) // hubs default to true
3082 pd
->pd_PoPoCfg
.poc_InhibitPopup
= TRUE
;
3085 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
3087 pd
->pd_NumCfgs
= usdd
.bNumConfigurations
;
3088 KPRINTF(10, ("Device has %ld different configurations\n", pd
->pd_NumCfgs
));
3090 if(pGetDevConfig(pp
))
3093 if(pd
->pd_Configs
.lh_Head
->ln_Succ
)
3095 cfgnum
= ((struct PsdConfig
*) pd
->pd_Configs
.lh_Head
)->pc_CfgNum
;
3097 psdSetDeviceConfig(pp
, cfgnum
); /* *** FIXME *** Workaround for USB2.0 devices */
3101 devclass
= pd
->pd_DevClass
;
3102 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
3103 while(pc
->pc_Node
.ln_Succ
)
3105 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3106 while(pif
->pif_Node
.ln_Succ
)
3108 if(pif
->pif_IfClass
)
3112 devclass
= pif
->pif_IfClass
;
3114 if(devclass
!= pif
->pif_IfClass
)
3121 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3123 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
3127 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) devclass
, NULL
);
3130 psdFreeVec(pd
->pd_ProductStr
);
3133 pd
->pd_ProductStr
= psdCopyStrFmt("%s (%s/%04lx)",
3134 classname
, vendorname
, pd
->pd_ProductID
);
3136 pd
->pd_ProductStr
= psdCopyStrFmt("%s (%04lx/%04lx)",
3137 classname
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3142 pFixBrokenConfig(pp
);
3143 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3144 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3145 psdUnlockDevice(pd
);
3146 psdCalculatePower(pd
->pd_Hardware
);
3149 KPRINTF(15, ("SetDeviceConfig(1) failed\n"));
3152 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3153 "Could not acquire device configuration for %s",
3154 pd
->pd_ProductStr
? pd
->pd_ProductStr
: (STRPTR
) "new device");
3155 KPRINTF(15, ("GetDevConfig() failed\n"));
3157 /* Although the device failed to configure fully, maybe
3158 some firmware will able to use this device anyway? */
3159 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3160 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3162 psdUnlockDevice(pd
);
3165 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3166 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
3167 18, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3168 KPRINTF(15, ("GET_DESCRIPTOR (18) failed %ld!\n", ioerr
));
3171 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3172 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
3173 8, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3174 KPRINTF(15, ("GET_DESCRIPTOR (8) failed %ld!\n", ioerr
));
3177 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
3178 "SET_ADDRESS failed: %s (%ld)",
3179 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3180 KPRINTF(15, ("SET_ADDRESS failed %ld!\n", ioerr
));
3183 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3184 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3186 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "This cannot happen! More than 127 devices on the bus???");
3187 KPRINTF(20, ("out of addresses???\n"));
3189 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Device enumeration failed, sorry.");
3190 psdUnlockDevice(pd
);
3196 /* /// "psdGetNextDevice()" */
3197 AROS_LH1(struct PsdDevice
*, psdGetNextDevice
,
3198 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3199 LIBBASETYPEPTR
, ps
, 21, psd
)
3202 struct PsdHardware
*phw
;
3204 KPRINTF(1, ("psdGetNextDevice(%p)\n", pd
));
3207 /* Is there another device node in the current hardware? */
3208 if(pd
->pd_Node
.ln_Succ
->ln_Succ
)
3210 return((struct PsdDevice
*) pd
->pd_Node
.ln_Succ
);
3212 /* No, then check if there's another hardware to scan */
3213 phw
= (struct PsdHardware
*) pd
->pd_Hardware
->phw_Node
.ln_Succ
;
3215 /* No context, start with first hardware */
3216 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
3218 while(phw
->phw_Node
.ln_Succ
)
3220 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3221 /* Is this an valid entry, or is the list empty? */
3222 if(pd
->pd_Node
.ln_Succ
)
3226 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
3228 /* End of list reached */
3234 /* /// "psdSuspendBindings()" */
3235 AROS_LH1(BOOL
, psdSuspendBindings
,
3236 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3237 LIBBASETYPEPTR
, ps
, 100, psd
)
3240 struct PsdUsbClass
*puc
;
3241 struct PsdConfig
*pc
;
3242 struct PsdInterface
*pif
;
3247 KPRINTF(5, ("psdSuspendBindings(%p)\n", pd
));
3250 if(ps
->ps_GlobalCfg
->pgc_ForceSuspend
&& (pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
))
3254 // ask existing bindings to go to suspend first -- if they don't support it, break off
3255 if(pd
->pd_DevBinding
)
3257 if(pd
->pd_Flags
& PDFF_APPBINDING
)
3261 // can't suspend application binding devices
3262 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3263 "Cannot suspend with application binding on '%s'.",
3267 psdReleaseDevBinding(pd
);
3269 if((puc
= pd
->pd_ClsBinding
))
3272 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
3275 res
= usbDoMethod(UCM_AttemptSuspendDevice
, pd
->pd_DevBinding
);
3278 // didn't want to suspend
3279 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3280 "Class '%s' failed to suspend device '%s'.",
3281 puc
->puc_Node
.ln_Name
, pd
->pd_ProductStr
);
3285 if(pd
->pd_IOBusyCount
)
3289 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3290 "Class '%s' does not support suspending.",
3291 puc
->puc_Node
.ln_Name
);
3294 psdReleaseDevBinding(pd
);
3297 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3298 "Class '%s' does not support suspending, but has no active IO. Suspending anyway.",
3299 puc
->puc_Node
.ln_Name
);
3304 pc
= pd
->pd_CurrentConfig
;
3305 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3306 while(pif
->pif_Node
.ln_Succ
)
3308 if(pif
->pif_IfBinding
)
3310 if((puc
= pif
->pif_ClsBinding
))
3313 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
3316 res
= usbDoMethod(UCM_AttemptSuspendDevice
, pif
->pif_IfBinding
);
3319 // didn't want to suspend
3320 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3321 "%s failed to suspend device '%s'.",
3322 puc
->puc_Node
.ln_Name
, pd
->pd_ProductStr
);
3326 if(pd
->pd_IOBusyCount
)
3331 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3332 "%s does not support suspending.",
3333 puc
->puc_Node
.ln_Name
);
3336 psdReleaseIfBinding(pif
);
3339 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3340 "%s does not support suspending, but has no active IO. Suspending anyway.",
3341 puc
->puc_Node
.ln_Name
);
3346 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3355 /* /// "psdSuspendDevice()" */
3356 AROS_LH1(BOOL
, psdSuspendDevice
,
3357 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3358 LIBBASETYPEPTR
, ps
, 98, psd
)
3361 struct PsdUsbClass
*puc
;
3362 struct PsdDevice
*hubpd
;
3366 KPRINTF(5, ("psdSuspendDevice(%p)\n", pd
));
3369 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
3374 if(!hubpd
) // suspend root hub
3376 // suspend whole USB, using the HCI UHCMD_USBSUSPEND command
3377 // FIXME currently unsupported!
3378 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Suspending of root hub currently not supported.");
3382 psdLockWriteDevice(pd
);
3383 res
= psdSuspendBindings(pd
);
3384 psdUnlockDevice(pd
);
3387 psdLockReadDevice(pd
);
3388 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
3390 res
= usbDoMethod(UCM_HubSuspendDevice
, binding
, pd
);
3392 psdUnlockDevice(pd
);
3397 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3398 "Suspending of device '%s' failed.",
3406 /* /// "psdResumeBindings()" */
3407 AROS_LH1(BOOL
, psdResumeBindings
,
3408 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3409 LIBBASETYPEPTR
, ps
, 101, psd
)
3412 struct PsdUsbClass
*puc
;
3413 struct PsdConfig
*pc
;
3414 struct PsdInterface
*pif
;
3416 BOOL rescan
= FALSE
;
3418 KPRINTF(5, ("psdResumeBindings(%p)\n", pd
));
3421 // ask existing bindings to resume -- if they don't support it, rebind
3422 if(pd
->pd_DevBinding
)
3424 if(!(pd
->pd_Flags
& PDFF_APPBINDING
))
3426 if((puc
= pd
->pd_ClsBinding
))
3428 res
= usbDoMethod(UCM_AttemptResumeDevice
, pd
->pd_DevBinding
);
3431 // if the device couldn't resume, better get rid of the binding
3432 psdReleaseDevBinding(pd
);
3438 pc
= pd
->pd_CurrentConfig
;
3439 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3440 while(pif
->pif_Node
.ln_Succ
)
3442 if(pif
->pif_IfBinding
)
3444 if((puc
= pif
->pif_ClsBinding
))
3446 res
= usbDoMethod(UCM_AttemptResumeDevice
, pif
->pif_IfBinding
);
3449 // didn't want to suspend
3450 psdReleaseIfBinding(pif
);
3456 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3468 /* /// "psdResumeDevice()" */
3469 AROS_LH1(BOOL
, psdResumeDevice
,
3470 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3471 LIBBASETYPEPTR
, ps
, 99, psd
)
3474 struct PsdUsbClass
*puc
;
3475 struct PsdDevice
*hubpd
;
3479 KPRINTF(5, ("psdResumeDevice(%p)\n", pd
));
3482 if(!(pd
->pd_Flags
& PDFF_SUSPENDED
))
3487 if(!hubpd
) // resume root hub
3489 // resume whole USB, using the HCI UHCMD_USBRESUME command
3490 // FIXME currently unsupported!
3493 psdLockWriteDevice(pd
);
3494 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
3496 res
= usbDoMethod(UCM_HubResumeDevice
, binding
, pd
);
3498 psdUnlockDevice(pd
);
3502 psdResumeBindings(pd
);
3511 /* /// "psdFindDeviceA()" */
3512 AROS_LH2(struct PsdDevice
*, psdFindDeviceA
,
3513 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3514 AROS_LHA(struct TagItem
*, tags
, A1
),
3515 LIBBASETYPEPTR
, ps
, 44, psd
)
3520 KPRINTF(2, ("psdFindDeviceA(%p, %p)\n", pd
, tags
));
3521 while((pd
= psdGetNextDevice(pd
)))
3524 if((ti
= FindTagItem(DA_ProductID
, tags
)))
3526 if(ti
->ti_Data
!= pd
->pd_ProductID
)
3531 if((ti
= FindTagItem(DA_VendorID
, tags
)))
3533 if(ti
->ti_Data
!= pd
->pd_VendorID
)
3538 if((ti
= FindTagItem(DA_Class
, tags
)))
3540 if(ti
->ti_Data
!= pd
->pd_DevClass
)
3545 if((ti
= FindTagItem(DA_SubClass
, tags
)))
3547 if(ti
->ti_Data
!= pd
->pd_DevSubClass
)
3552 if((ti
= FindTagItem(DA_Protocol
, tags
)))
3554 if(ti
->ti_Data
!= pd
->pd_DevProto
)
3559 if((ti
= FindTagItem(DA_Version
, tags
)))
3561 if(ti
->ti_Data
!= pd
->pd_DevVers
)
3566 if((ti
= FindTagItem(DA_SerialNumber
, tags
)))
3568 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_SerNumStr
))
3573 if((ti
= FindTagItem(DA_ProductName
, tags
)))
3575 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_ProductStr
))
3580 if((ti
= FindTagItem(DA_Manufacturer
, tags
)))
3582 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_MnfctrStr
))
3587 if((ti
= FindTagItem(DA_IDString
, tags
)))
3589 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_IDString
))
3594 if((ti
= FindTagItem(DA_Binding
, tags
)))
3596 if(ti
->ti_Data
!= (IPTR
) pd
->pd_DevBinding
)
3601 if((ti
= FindTagItem(DA_HubDevice
, tags
)))
3603 if(ti
->ti_Data
!= (IPTR
) pd
->pd_Hub
)
3619 /* *** Hardware *** */
3621 /* /// "pFindHardware()" */
3622 struct PsdHardware
* pFindHardware(LIBBASETYPEPTR ps
, STRPTR name
, ULONG unit
)
3624 struct PsdHardware
*phw
;
3628 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
3629 while(phw
->phw_Node
.ln_Succ
)
3631 if((phw
->phw_Unit
== unit
) && (!strcmp(phw
->phw_DevName
, name
)))
3636 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
3640 if((*name
== '/') || (*name
== ':'))
3652 /* /// "psdEnumerateHardware()" */
3653 AROS_LH1(struct PsdDevice
*, psdEnumerateHardware
,
3654 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3655 LIBBASETYPEPTR
, ps
, 14, psd
)
3658 struct PsdDevice
*pd
= NULL
;
3661 KPRINTF(2, ("psdEnumerateHardware(%p)\n", phw
));
3663 if((mp
= CreateMsgPort()))
3666 if((pd
= psdAllocDevice(phw
)))
3669 if((pp
= psdAllocPipe(pd
, mp
, NULL
)))
3671 //pp->pp_IOReq.iouh_Flags |= UHFF_NAKTIMEOUT;
3672 //pp->pp_IOReq.iouh_NakTimeout = 1000;
3673 pd
->pd_Flags
|= PDFF_CONNECTED
;
3674 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_USBRESET
;
3675 psdDoPipe(pp
, NULL
, 0);
3676 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
3677 psdDelayMS(100); // wait for root hub to settle
3678 if(psdEnumerateDevice(pp
))
3680 KPRINTF(1, ("Enumeration finished!\n"));
3681 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Root hub has been enumerated.");
3684 phw
->phw_RootDevice
= pd
;
3685 psdSendEvent(EHMB_ADDDEVICE
, pd
, NULL
);
3690 pFreeBindings(ps
, pd
);
3691 pFreeDevice(ps
, pd
);
3697 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Root hub enumeration failed. Blame your hardware driver programmer.");
3703 /* /// "psdRemHardware()" */
3704 AROS_LH1(void, psdRemHardware
,
3705 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3706 LIBBASETYPEPTR
, ps
, 13, psd
)
3709 struct PsdDevice
*pd
;
3712 KPRINTF(5, ("FreeHardware(%p)\n", phw
));
3714 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3715 while(pd
->pd_Node
.ln_Succ
)
3717 pFreeBindings(ps
, pd
);
3718 pFreeDevice(ps
, pd
);
3719 psdSendEvent(EHMB_REMDEVICE
, pd
, NULL
);
3720 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3723 pd
= (struct PsdDevice
*) phw
->phw_DeadDevices
.lh_Head
;
3724 while(pd
->pd_Node
.ln_Succ
)
3728 KPRINTF(20, ("Can't remove device, usecnt %ld\n", pd
->pd_UseCnt
));
3731 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3732 "Can't remove device '%s', there are still %ld pipes in use...",
3733 pd
->pd_ProductStr
, pd
->pd_UseCnt
);
3737 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3738 "Okay, going down with device '%s' anyway, maybe the driver crashed?",
3746 pFreeDevice(ps
, pd
);
3747 //psdSendEvent(EHMB_REMDEVICE, pd, NULL);
3749 pd
= (struct PsdDevice
*) phw
->phw_DeadDevices
.lh_Head
;
3753 /* Note that the subtask unlinks the hardware! */
3754 phw
->phw_ReadySignal
= SIGB_SINGLE
;
3755 phw
->phw_ReadySigTask
= FindTask(NULL
);
3758 Signal(phw
->phw_Task
, SIGBREAKF_CTRL_C
);
3761 while(phw
->phw_Task
)
3763 Wait(1L<<phw
->phw_ReadySignal
);
3765 //FreeSignal(phw->phw_ReadySignal);
3766 KPRINTF(1, ("FreeHardware(%p) freevec name\n", phw
));
3767 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3768 "Removed hardware %s/%ld. Bye bye!",
3769 phw
->phw_DevName
, phw
->phw_Unit
);
3770 psdFreeVec(phw
->phw_DevName
);
3771 psdFreeVec(phw
->phw_ProductName
);
3772 psdFreeVec(phw
->phw_Manufacturer
);
3773 psdFreeVec(phw
->phw_Description
);
3774 psdFreeVec(phw
->phw_Copyright
);
3776 psdSendEvent(EHMB_REMHARDWARE
, phw
, NULL
);
3777 KPRINTF(1, ("FreeHardware(%p) done\n", phw
));
3782 /* /// "psdAddHardware()" */
3783 AROS_LH2(struct PsdHardware
*,psdAddHardware
,
3784 AROS_LHA(STRPTR
, name
, A0
),
3785 AROS_LHA(ULONG
, unit
, D0
),
3786 LIBBASETYPEPTR
, ps
, 12, psd
)
3789 struct PsdHardware
*phw
;
3791 struct Task
*tmptask
;
3792 KPRINTF(5, ("psdAddHardware(%s, %ld)\n", name
, unit
));
3794 if((phw
= psdAllocVec(sizeof(struct PsdHardware
))))
3796 NewList(&phw
->phw_Devices
);
3797 NewList(&phw
->phw_DeadDevices
);
3798 phw
->phw_Unit
= unit
;
3800 if((phw
->phw_Node
.ln_Name
= phw
->phw_DevName
= psdCopyStr(name
)))
3802 psdSafeRawDoFmt(buf
, 64, "usbhw<%s/%ld>", name
, unit
);
3803 phw
->phw_ReadySignal
= SIGB_SINGLE
;
3804 phw
->phw_ReadySigTask
= FindTask(NULL
);
3805 SetSignal(0, SIGF_SINGLE
); // clear single bit
3806 if((tmptask
= psdSpawnSubTask(buf
, pDeviceTask
, phw
)))
3808 psdBorrowLocksWait(tmptask
, 1UL<<phw
->phw_ReadySignal
);
3811 phw
->phw_ReadySigTask
= NULL
;
3812 //FreeSignal(phw->phw_ReadySignal);
3813 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3814 "New hardware %s/%ld added (%s).",
3817 phw
->phw_ProductName
);
3818 psdSendEvent(EHMB_ADDHARDWARE
, phw
, NULL
);
3822 phw
->phw_ReadySigTask
= NULL
;
3823 //FreeSignal(phw->phw_ReadySignal);
3824 psdFreeVec(phw
->phw_DevName
);
3833 /* /// "psdCalculatePower()" */
3834 AROS_LH1(void, psdCalculatePower
,
3835 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3836 LIBBASETYPEPTR
, ps
, 78, psd
)
3839 struct PsdDevice
*roothub
= NULL
;
3840 struct PsdDevice
*pd
;
3844 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3845 while(pd
->pd_Node
.ln_Succ
)
3852 pd
= (struct PsdDevice
*) pd
->pd_Node
.ln_Succ
;
3859 roothub
->pd_PowerDrain
= 0;
3860 roothub
->pd_PowerSupply
= 500;
3862 /* calculate drain */
3863 pPowerRecurseDrain(ps
, roothub
);
3865 /* calculate supply */
3866 pPowerRecurseSupply(ps
, roothub
);
3874 /* /// "psdAllocPipe()" */
3875 AROS_LH3(struct PsdPipe
*, psdAllocPipe
,
3876 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3877 AROS_LHA(struct MsgPort
*, mp
, A1
),
3878 AROS_LHA(struct PsdEndpoint
*, pep
, A2
),
3879 LIBBASETYPEPTR
, ps
, 24, psd
)
3883 struct PsdDevice
*hubpd
;
3885 KPRINTF(2, ("psdAllocPipe(%p, %p, %p)\n", pd
, mp
, pep
));
3890 if(pep
&& (pep
->pep_TransType
== USEAF_ISOCHRONOUS
) && (!(pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Capabilities
& UHCF_ISO
)))
3892 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Your HW controller driver does not support iso transfers. Sorry.");
3896 if((pp
= psdAllocVec(sizeof(struct PsdPipe
))))
3898 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
3899 pp
->pp_MsgPort
= pp
->pp_Msg
.mn_ReplyPort
= mp
;
3900 pp
->pp_Msg
.mn_Length
= sizeof(struct PsdPipe
);
3902 pp
->pp_Endpoint
= pep
;
3903 pp
->pp_IOReq
= *(pd
->pd_Hardware
->phw_RootIOReq
);
3904 pp
->pp_IOReq
.iouh_DevAddr
= pd
->pd_DevAddr
;
3905 if(pd
->pd_Flags
& PDFF_LOWSPEED
)
3907 pp
->pp_IOReq
.iouh_Flags
|= UHFF_LOWSPEED
;
3909 if(pd
->pd_Flags
& PDFF_HIGHSPEED
)
3911 pp
->pp_IOReq
.iouh_Flags
|= UHFF_HIGHSPEED
;
3914 switch(pep
->pep_NumTransMuFr
)
3917 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_2
;
3920 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_3
;
3924 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_1
;
3927 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_1
;
3930 #ifdef AROS_USB30_CODE
3931 if(pd
->pd_Flags
& PDFF_SUPERSPEED
)
3933 pp
->pp_IOReq
.iouh_Flags
|= UHFF_SUPERSPEED
;
3936 if(pd
->pd_Flags
& PDFF_NEEDSSPLIT
)
3938 /* USB1.1 device connected to a USB2.0 hub */
3939 pp
->pp_IOReq
.iouh_Flags
|= UHFF_SPLITTRANS
;
3941 pp
->pp_IOReq
.iouh_SplitHubPort
= pd
->pd_HubPort
;
3942 // find the root USB 2.0 hub in the tree
3943 while(hubpd
&& !(hubpd
->pd_Flags
& PDFF_HIGHSPEED
))
3945 pp
->pp_IOReq
.iouh_SplitHubPort
= hubpd
->pd_HubPort
;
3946 hubpd
= hubpd
->pd_Hub
;
3950 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Internal error obtaining split transaction hub!");
3954 pp
->pp_IOReq
.iouh_Flags
|= (hubpd
->pd_HubThinkTime
<<UHFS_THINKTIME
);
3955 pp
->pp_IOReq
.iouh_SplitHubAddr
= hubpd
->pd_DevAddr
;
3959 switch(pep
->pep_TransType
)
3962 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
3964 case USEAF_ISOCHRONOUS
:
3965 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_ISOXFER
;
3968 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_BULKXFER
;
3970 case USEAF_INTERRUPT
:
3971 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_INTXFER
;
3974 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3975 "AllocPipe(): Illegal transfer type %ld",
3976 pep
->pep_TransType
);
3977 KPRINTF(20, ("Illegal transfer type for endpoint!"));
3982 pp
->pp_IOReq
.iouh_Dir
= (pep
->pep_Direction
? UHDIR_IN
: UHDIR_OUT
);
3983 pp
->pp_IOReq
.iouh_Endpoint
= pep
->pep_EPNum
;
3984 pp
->pp_IOReq
.iouh_MaxPktSize
= pep
->pep_MaxPktSize
;
3985 pp
->pp_IOReq
.iouh_Interval
= pep
->pep_Interval
;
3987 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
3988 pp
->pp_IOReq
.iouh_Dir
= UHDIR_SETUP
;
3989 pp
->pp_IOReq
.iouh_Endpoint
= 0;
3990 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
;
4000 /* /// "psdFreePipe()" */
4001 AROS_LH1(void, psdFreePipe
,
4002 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4003 LIBBASETYPEPTR
, ps
, 25, psd
)
4006 struct PsdDevice
*pd
;
4011 KPRINTF(2, ("psdFreePipe(%p)\n", pp
));
4014 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4016 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4017 "Tried to free pipe on %s that was still pending!", pd
->pd_ProductStr
);
4022 if(!(--pd
->pd_UseCnt
) && (pd
->pd_Flags
& PDFF_DELEXPUNGE
))
4024 KPRINTF(20, ("Finally getting rid of device %s\n", pd
->pd_ProductStr
));
4025 pFreeDevice(ps
, pd
);
4026 //psdSendEvent(EHMB_REMDEVICE, pd, NULL);
4034 /* /// "psdPipeSetup()" */
4035 AROS_LH5(void, psdPipeSetup
,
4036 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4037 AROS_LHA(UWORD
, rt
, D0
),
4038 AROS_LHA(UWORD
, rq
, D1
),
4039 AROS_LHA(UWORD
, val
, D2
),
4040 AROS_LHA(UWORD
, idx
, D3
),
4041 LIBBASETYPEPTR
, ps
, 26, psd
)
4044 struct UsbSetupData
*usd
= &pp
->pp_IOReq
.iouh_SetupData
;
4046 KPRINTF(1, ("psdSetupPipe(%p, (%02lx %02lx %04lx %04lx))\n",
4047 pp
, rt
, rq
, val
, idx
));
4048 usd
->bmRequestType
= rt
;
4050 usd
->wValue
= AROS_WORD2LE(val
);
4051 usd
->wIndex
= AROS_WORD2LE(idx
);
4056 /* /// "psdDoPipe()" */
4057 AROS_LH3(LONG
, psdDoPipe
,
4058 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4059 AROS_LHA(APTR
, data
, A0
),
4060 AROS_LHA(ULONG
, len
, D0
),
4061 LIBBASETYPEPTR
, ps
, 27, psd
)
4064 struct PsdDevice
*pd
= pp
->pp_Device
;
4065 KPRINTF(200, ("psdDoPipe(%p, %p, %ld)\n", pp
, data
, len
));
4067 if(pd
->pd_Flags
& PDFF_CONNECTED
)
4069 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
4071 // make sure the device is up and running before trying to send a new pipe
4072 psdResumeDevice(pd
);
4075 pp
->pp_IOReq
.iouh_Data
= data
;
4076 pp
->pp_IOReq
.iouh_Length
= len
;
4077 if(!pp
->pp_Endpoint
)
4079 pp
->pp_IOReq
.iouh_SetupData
.wLength
= AROS_WORD2LE(len
);
4081 PutMsg(&pd
->pd_Hardware
->phw_TaskMsgPort
, &pp
->pp_Msg
);
4082 ++pd
->pd_IOBusyCount
;
4083 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4084 return(psdWaitPipe(pp
));
4087 pp
->pp_IOReq
.iouh_Actual
= 0;
4088 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
4089 return(pp
->pp_IOReq
.iouh_Req
.io_Error
= UHIOERR_TIMEOUT
);
4095 /* /// "psdSendPipe()" */
4096 AROS_LH3(void, psdSendPipe
,
4097 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4098 AROS_LHA(APTR
, data
, A0
),
4099 AROS_LHA(ULONG
, len
, D0
),
4100 LIBBASETYPEPTR
, ps
, 28, psd
)
4103 struct PsdDevice
*pd
= pp
->pp_Device
;
4104 KPRINTF(200, ("psdSendPipe(%p, %p, %ld)\n", pp
, data
, len
));
4105 if(pd
->pd_Flags
& PDFF_CONNECTED
)
4107 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
4109 // make sure the device is up and running before trying to send a new pipe
4110 psdResumeDevice(pd
);
4113 pp
->pp_IOReq
.iouh_Data
= data
;
4114 pp
->pp_IOReq
.iouh_Length
= len
;
4115 if(!pp
->pp_Endpoint
)
4117 pp
->pp_IOReq
.iouh_SetupData
.wLength
= AROS_WORD2LE(len
);
4119 PutMsg(&pd
->pd_Hardware
->phw_TaskMsgPort
, &pp
->pp_Msg
);
4120 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4121 ++pd
->pd_IOBusyCount
;
4124 pp
->pp_IOReq
.iouh_Actual
= 0;
4125 //pp->pp_Msg.mn_Node.ln_Type = NT_REPLYMSG;
4126 pp
->pp_IOReq
.iouh_Req
.io_Error
= UHIOERR_TIMEOUT
;
4127 ReplyMsg(&pp
->pp_Msg
);
4128 ++pd
->pd_IOBusyCount
;
4134 /* /// "psdAbortPipe()" */
4135 AROS_LH1(void, psdAbortPipe
,
4136 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4137 LIBBASETYPEPTR
, ps
, 29, psd
)
4140 struct PsdPipe
*npp
;
4142 KPRINTF(5, ("psdAbortPipe(%p)\n", pp
));
4143 if(pp
->pp_Msg
.mn_Node
.ln_Type
!= NT_MESSAGE
)
4145 KPRINTF(5, ("Nothing to abort %02lx\n", pp
->pp_IOReq
.iouh_Req
.io_Message
.mn_Node
.ln_Type
));
4148 if((npp
= psdAllocVec(sizeof(struct PsdPipe
))))
4150 //npp->pp_Msg.mn_Node.ln_Type = NT_MESSAGE;
4151 npp
->pp_Device
= pp
->pp_Device
;
4152 npp
->pp_MsgPort
= npp
->pp_Msg
.mn_ReplyPort
= pp
->pp_MsgPort
;
4153 npp
->pp_Msg
.mn_Length
= sizeof(struct PsdPipe
);
4155 npp
->pp_AbortPipe
= pp
;
4156 PutMsg(&pp
->pp_Device
->pd_Hardware
->phw_TaskMsgPort
, &npp
->pp_Msg
);
4164 /* /// "psdWaitPipe()" */
4165 AROS_LH1(LONG
, psdWaitPipe
,
4166 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4167 LIBBASETYPEPTR
, ps
, 30, psd
)
4171 struct PsdDevice
*pd
= pp
->pp_Device
;
4173 KPRINTF(5, ("psdWaitPipe(%p)\n", pp
));
4174 while(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4176 KPRINTF(5, ("ln_Type = %02lx\n", pp
->pp_Msg
.mn_Node
.ln_Type
));
4177 sigs
|= Wait(1L<<pp
->pp_MsgPort
->mp_SigBit
);
4178 KPRINTF(5, ("sigs = %p\n", sigs
));
4182 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_REPLYMSG
)
4184 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
4185 Remove(&pp
->pp_Msg
.mn_Node
);
4187 //if(pp->pp_MsgPort->mp_MsgList.lh_Head->ln_Succ)
4189 // avoid signals getting lost for other messages arriving.
4190 SetSignal(sigs
, sigs
);
4195 Remove(&pp
->pp_Msg
.mn_Node
);
4198 ioerr
= pp
->pp_IOReq
.iouh_Req
.io_Error
;
4201 case UHIOERR_TIMEOUT
:
4204 case UHIOERR_NAKTIMEOUT
:
4206 case UHIOERR_CRCERROR
:
4209 case UHIOERR_RUNTPACKET
:
4211 if(pd
->pd_DeadCount
)
4213 pd
->pd_DeadCount
>>= 1;
4214 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4215 "Device %s starts recovering with %s (%ld)!",
4217 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);*/
4220 KPRINTF(200, ("psdWaitPipe(%p)=%ld\n", pp
, ioerr
));
4221 --pd
->pd_IOBusyCount
;
4222 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4224 if((pd
->pd_DeadCount
> 19) || ((pd
->pd_DeadCount
> 14) && (pd
->pd_Flags
& (PDFF_HASDEVADDR
|PDFF_HASDEVDESC
))))
4226 if(!(pd
->pd_Flags
& PDFF_DEAD
))
4228 pd
->pd_Flags
|= PDFF_DEAD
;
4229 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4230 "Device %s probably dropped dead!", pd
->pd_ProductStr
);
4232 psdSendEvent(EHMB_DEVICEDEAD
, pp
->pp_Device
, NULL
);
4235 if((!pd
->pd_DeadCount
) && ((pd
->pd_Flags
& (PDFF_DEAD
|PDFF_CONNECTED
)) == (PDFF_DEAD
|PDFF_CONNECTED
)))
4237 pd
->pd_Flags
&= ~PDFF_DEAD
;
4238 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4239 "Uuuhuuuhh, the zombie %s returned from the dead!", pd
->pd_ProductStr
);
4247 /* /// "psdCheckPipe()" */
4248 AROS_LH1(struct PsdPipe
*, psdCheckPipe
,
4249 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4250 LIBBASETYPEPTR
, ps
, 71, psd
)
4253 KPRINTF(5, ("psdCheckPipe(%p)\n", pp
));
4254 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4263 /* /// "psdGetPipeActual()" */
4264 AROS_LH1(ULONG
, psdGetPipeActual
,
4265 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4266 LIBBASETYPEPTR
, ps
, 31, psd
)
4269 KPRINTF(1, ("psdGetPipeActual(%p)\n", pp
));
4270 return(pp
->pp_IOReq
.iouh_Actual
);
4275 /* /// "psdGetPipeError()" */
4276 AROS_LH1(LONG
, psdGetPipeError
,
4277 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4278 LIBBASETYPEPTR
, ps
, 32, psd
)
4281 KPRINTF(1, ("psdGetPipeError(%p)\n", pp
));
4282 return((LONG
) pp
->pp_IOReq
.iouh_Req
.io_Error
);
4287 /* *** Streams *** */
4289 /* /// "psdOpenStreamA()" */
4290 AROS_LH2(struct PsdPipeStream
*, psdOpenStreamA
,
4291 AROS_LHA(struct PsdEndpoint
*, pep
, A0
),
4292 AROS_LHA(struct TagItem
*, tags
, A1
),
4293 LIBBASETYPEPTR
, ps
, 72, psd
)
4296 struct PsdPipeStream
*pps
;
4298 KPRINTF(2, ("psdOpenStream(%p, %p)\n", pep
, tags
));
4303 if((pps
= psdAllocVec(sizeof(struct PsdPipeStream
))))
4305 pps
->pps_Device
= pep
->pep_Interface
->pif_Config
->pc_Device
;
4306 pps
->pps_Endpoint
= pep
;
4307 NewList(&pps
->pps_FreePipes
);
4308 NewList(&pps
->pps_ReadyPipes
);
4309 InitSemaphore(&pps
->pps_AccessLock
);
4310 pps
->pps_NakTimeoutTime
= 5000;
4311 if(pep
->pep_Direction
)
4313 /* Defaults for IN */
4314 pps
->pps_NumPipes
= 4;
4315 pps
->pps_Flags
= PSFF_READAHEAD
|PSFF_BUFFERREAD
|PSFF_ALLOWRUNT
;
4316 pps
->pps_BufferSize
= 32*pps
->pps_Endpoint
->pep_MaxPktSize
;
4318 /* Defaults for OUT */
4319 pps
->pps_NumPipes
= 4;
4320 pps
->pps_Flags
= PSFF_NOSHORTPKT
;
4321 pps
->pps_BufferSize
= 4*pps
->pps_Endpoint
->pep_MaxPktSize
;
4324 psdSetAttrsA(PGA_PIPESTREAM
, pps
, tags
);
4327 psdCloseStream(pps
);
4337 /* /// "psdCloseStream()" */
4338 AROS_LH1(void, psdCloseStream
,
4339 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4340 LIBBASETYPEPTR
, ps
, 73, psd
)
4346 KPRINTF(2, ("psdCloseStream(%p)\n", pps
));
4351 psdStreamFlush(pps
);
4352 ObtainSemaphore(&pps
->pps_AccessLock
);
4355 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
4357 pp
= pps
->pps_Pipes
[cnt
];
4358 //if(pp->pp_IOReq.iouh_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
4360 KPRINTF(1, ("Abort %ld\n", cnt
));
4362 KPRINTF(1, ("Wait %ld\n", cnt
));
4365 KPRINTF(1, ("Free %ld\n", cnt
));
4368 psdFreeVec(pps
->pps_Pipes
);
4369 if((pps
->pps_Flags
& PSFF_OWNMSGPORT
) && pps
->pps_MsgPort
)
4371 DeleteMsgPort(pps
->pps_MsgPort
);
4374 psdFreeVec(pps
->pps_Buffer
);
4375 ReleaseSemaphore(&pps
->pps_AccessLock
);
4381 /* /// "psdStreamRead()" */
4382 AROS_LH3(LONG
, psdStreamRead
,
4383 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4384 AROS_LHA(UBYTE
*, buffer
, A0
),
4385 AROS_LHA(LONG
, length
, D0
),
4386 LIBBASETYPEPTR
, ps
, 74, psd
)
4403 KPRINTF(2, ("psdStreamRead(%p, %p, %ld)\n", pps
, buffer
, length
));
4408 ObtainSemaphore(&pps
->pps_AccessLock
);
4409 KPRINTF(2, ("Sema\n"));
4411 if((!pps
->pps_Pipes
) || (!pps
->pps_Endpoint
->pep_Direction
))
4413 KPRINTF(2, ("Wrong direction!\n"));
4414 pps
->pps_Error
= UHIOERR_BADPARAMS
;
4415 ReleaseSemaphore(&pps
->pps_AccessLock
);
4418 if(!(pps
->pps_Flags
& PSFF_ASYNCIO
))
4420 if(pps
->pps_Flags
& PSFF_BUFFERREAD
)
4422 /* buffered reading */
4425 /* check for incoming packets */
4426 while((pp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4428 KPRINTF(1, ("PktBack(%p, %p, %ld/%ld)=%ld\n",
4429 pp
, pp
->pp_IOReq
.iouh_Data
, pp
->pp_IOReq
.iouh_Actual
,
4430 pp
->pp_IOReq
.iouh_Length
, pp
->pp_IOReq
.iouh_Req
.io_Error
));
4432 pps
->pps_ReqBytes
-= pp
->pp_IOReq
.iouh_Length
;
4433 ioerr
= pp
->pp_IOReq
.iouh_Req
.io_Error
;
4434 if((ioerr
== UHIOERR_NAKTIMEOUT
) && pp
->pp_IOReq
.iouh_Actual
)
4441 pps
->pps_Error
= ioerr
;
4443 if(ioerr
!= UHIOERR_TIMEOUT
)
4445 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamRead",
4446 "Packet(%s) failed: %s (%ld)", (STRPTR
) "b",
4447 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4449 /* stop automatic queueing */
4450 pps
->pps_Flags
&= ~PSFF_READAHEAD
;
4451 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4453 /* successfully received packet */
4454 pps
->pps_BytesPending
+= pp
->pp_IOReq
.iouh_Actual
;
4455 AddTail(&pps
->pps_ReadyPipes
, &pp
->pp_Msg
.mn_Node
);
4458 if(length
== -1) /* get all that's there (STRONGLY DISCOURAGED! Might cause buffer overflows) */
4460 length
= pps
->pps_BytesPending
;
4462 /* check for buffered data */
4463 while(length
&& pps
->pps_BytesPending
)
4465 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
4466 if(!pp
->pp_Msg
.mn_Node
.ln_Succ
) /* debug */
4468 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) "StreamRead", "Readqueue empty!");
4469 ReleaseSemaphore(&pps
->pps_AccessLock
);
4472 if(pp
->pp_IOReq
.iouh_Actual
< pps
->pps_Offset
)
4474 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) "StreamRead",
4475 "Actual %ld < offset %ld!", pp
->pp_IOReq
.iouh_Actual
, pps
->pps_Offset
);
4476 ReleaseSemaphore(&pps
->pps_AccessLock
);
4479 remlen
= pp
->pp_IOReq
.iouh_Actual
- pps
->pps_Offset
;
4482 KPRINTF(1, ("PktBit(%p, %p, %ld)\n", pp
, buffer
, length
));
4485 KPRINTF(1, ("PktRem(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4488 if(pp
->pp_Flags
& PFF_INPLACE
)
4490 KPRINTF(1, ("PktRemIP(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4492 if(pps
->pps_TermArray
)
4495 KPRINTF(1, ("PktCpyEOF(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4497 srcptr
= &(((UBYTE
*) pp
->pp_IOReq
.iouh_Data
)[pps
->pps_Offset
]);
4498 tarrptr
= pps
->pps_TermArray
;
4505 cchar
= *bufptr
++ = *srcptr
++;
4510 if(cchar
< tarrptr
[tcnt
])
4514 else if(cchar
== tarrptr
[tcnt
])
4518 KPRINTF(2, ("EOF char %02lx found, length = %ld\n", cchar
, remlen
));
4523 if(tarrptr
[tcnt
] == tarrptr
[tcnt
+1])
4528 } while(++tcnt
< 8);
4532 KPRINTF(1, ("PktCpy(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4533 /* quick non-eof mode */
4534 CopyMem(&(((UBYTE
*) pp
->pp_IOReq
.iouh_Data
)[pps
->pps_Offset
]), buffer
, remlen
);
4540 pps
->pps_BytesPending
-= remlen
;
4541 pps
->pps_Offset
+= remlen
;
4542 /* end of packet reached? */
4543 if(pps
->pps_Offset
== pp
->pp_IOReq
.iouh_Actual
)
4545 pps
->pps_Offset
= 0;
4546 Remove(&pp
->pp_Msg
.mn_Node
);
4547 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4548 /* check for short packet */
4549 if((pps
->pps_Flags
& PSFF_SHORTTERM
) && (pp
->pp_IOReq
.iouh_Actual
% pp
->pp_IOReq
.iouh_MaxPktSize
))
4559 /* start sending out requests */
4561 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4562 if(!(pps
->pps_BytesPending
|| pps
->pps_ReqBytes
|| pps
->pps_TermArray
|| (length
< pps
->pps_BufferSize
)))
4564 /* faster non-buffered mode */
4565 if(pp
->pp_Msg
.mn_Node
.ln_Succ
)
4567 pp
->pp_Flags
|= PFF_INPLACE
;
4568 Remove(&pp
->pp_Msg
.mn_Node
);
4569 remlen
= length
- (length
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4570 KPRINTF(1, ("OutFast(%p, %p, %ld/%ld)\n",
4571 pp
, buffer
, remlen
, length
));
4572 psdSendPipe(pp
, buffer
, remlen
);
4573 pps
->pps_ReqBytes
+= remlen
;
4574 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4577 /* slower buffered mode */
4578 while(pp
->pp_Msg
.mn_Node
.ln_Succ
&& ((remlen
> pps
->pps_ReqBytes
) || (pps
->pps_Flags
& PSFF_READAHEAD
)))
4580 pp
->pp_Flags
&= ~PFF_INPLACE
;
4581 Remove(&pp
->pp_Msg
.mn_Node
);
4582 if((pps
->pps_Flags
& PSFF_READAHEAD
) || (remlen
% pp
->pp_IOReq
.iouh_MaxPktSize
))
4584 KPRINTF(1, ("OutSlow(%p, %p, %ld)\n",
4585 pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], pps
->pps_BufferSize
));
4586 remlen
= pps
->pps_BufferSize
;
4588 KPRINTF(1, ("OutExact(%p, %p, %ld)\n",
4589 pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], remlen
));
4591 psdSendPipe(pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], remlen
);
4592 pps
->pps_ReqBytes
+= remlen
;
4593 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4595 if((!length
) || (pps
->pps_Flags
& PSFF_DONOTWAIT
))
4601 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4602 KPRINTF(1, ("WaitPort (%p)\n", sigmask
));
4603 sigmask
= Wait(sigmask
);
4604 KPRINTF(1, ("Wait back (%p)\n", sigmask
));
4605 if(sigmask
& pps
->pps_AbortSigMask
)
4607 KPRINTF(1, ("Aborted!\n"));
4609 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4614 /* plain reading (might lose data) */
4615 if(pps
->pps_TermArray
|| (pps
->pps_Flags
& PSFF_READAHEAD
))
4617 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) "StreamRead", "This mode combination for the stream is not supported!");
4619 /* start sending out requests */
4620 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4621 if(pp
->pp_Msg
.mn_Node
.ln_Succ
&& length
)
4623 ioerr
= psdDoPipe(pp
, buffer
, length
);
4626 pps
->pps_Error
= ioerr
;
4627 if(ioerr
!= UHIOERR_TIMEOUT
)
4629 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamRead",
4630 "Packet(%s) failed: %s (%ld)", (STRPTR
) "u",
4631 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4634 actual
= pp
->pp_IOReq
.iouh_Actual
;
4638 ReleaseSemaphore(&pps
->pps_AccessLock
);
4644 /* /// "psdStreamWrite()" */
4645 AROS_LH3(LONG
, psdStreamWrite
,
4646 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4647 AROS_LHA(UBYTE
*, buffer
, A0
),
4648 AROS_LHA(LONG
, length
, D0
),
4649 LIBBASETYPEPTR
, ps
, 75, psd
)
4653 struct PsdPipe
*newpp
;
4666 KPRINTF(2, ("psdStreamWrite(%p, %p, %ld)\n", pps
, buffer
, length
));
4671 ObtainSemaphore(&pps
->pps_AccessLock
);
4673 if((!pps
->pps_Pipes
) || pps
->pps_Endpoint
->pep_Direction
)
4675 KPRINTF(2, ("Wrong direction!\n"));
4676 pps
->pps_Error
= UHIOERR_BADPARAMS
;
4677 ReleaseSemaphore(&pps
->pps_AccessLock
);
4680 if(length
== -1) /* null terminated string mode */
4682 KPRINTF(2, ("EOL mode!\n"));
4683 length
= strlen(buffer
);
4685 if((tarrptr
= pps
->pps_TermArray
)) /* EOF Mode */
4687 KPRINTF(1, ("EOFSearch(%p, %ld)\n", buffer
, length
));
4700 if(cchar
< tarrptr
[tcnt
])
4704 else if(cchar
== tarrptr
[tcnt
])
4707 KPRINTF(2, ("EOF char %02lx found, length = %ld\n", cchar
, length
));
4712 if(tarrptr
[tcnt
] == tarrptr
[tcnt
+1])
4717 } while(++tcnt
< 8);
4721 if(!(pps
->pps_Flags
& PSFF_ASYNCIO
))
4723 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4724 if(pp
->pp_Msg
.mn_Node
.ln_Succ
&& length
)
4726 if(pps
->pps_Flags
& PSFF_BUFFERWRITE
)
4728 /* buffered writing */
4729 if(pps
->pps_BytesPending
)
4731 remlen
= pps
->pps_BytesPending
% pp
->pp_IOReq
.iouh_MaxPktSize
;
4732 /* align to packet boundary */
4733 if(remlen
+ length
>= pp
->pp_IOReq
.iouh_MaxPktSize
)
4735 /* new data crosses at least on packet size */
4736 if(pps
->pps_BytesPending
+ length
<= pps
->pps_BufferSize
)
4738 /* copy everything up to the last (!) boundary */
4739 remlen
= pps
->pps_BytesPending
+ length
;
4740 remlen
= remlen
- (remlen
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4741 remlen
-= pps
->pps_BytesPending
;
4742 KPRINTF(1, ("PendOptCpy(%p, %ld+%ld/%ld)\n", buffer
, pps
->pps_BytesPending
, remlen
, length
));
4744 /* just calculate amount to copy to the next boundary */
4745 remlen
= pp
->pp_IOReq
.iouh_MaxPktSize
- remlen
;
4746 KPRINTF(1, ("PendOneCpy(%p, %ld+%ld/%ld)\n", buffer
, pps
->pps_BytesPending
, remlen
, length
));
4748 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], remlen
);
4749 pps
->pps_BytesPending
+= remlen
;
4754 KPRINTF(1, ("PendAdd(%p, %ld+%ld)\n", buffer
, pps
->pps_BytesPending
, length
));
4755 /* only a few bytes, see if we can fit them */
4756 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], length
);
4757 pps
->pps_BytesPending
+= length
;
4759 //buffer += length; /* not needed */
4762 /* flush some buffers */
4763 if((length
>= pp
->pp_IOReq
.iouh_MaxPktSize
) ||
4764 ((pps
->pps_BytesPending
>= (pps
->pps_BufferSize
>>1)) && (pps
->pps_BytesPending
>= pp
->pp_IOReq
.iouh_MaxPktSize
)))
4766 remlen
= pps
->pps_BytesPending
- (pps
->pps_BytesPending
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4767 KPRINTF(1, ("PendFlush(%ld/%ld)\n", remlen
, pps
->pps_BytesPending
));
4768 Remove(&pp
->pp_Msg
.mn_Node
);
4769 psdSendPipe(pp
, pps
->pps_Buffer
, remlen
);
4770 pps
->pps_ActivePipe
= pp
;
4771 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4773 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4774 sigmask
= Wait(sigmask
);
4775 if(sigmask
& pps
->pps_AbortSigMask
)
4777 KPRINTF(1, ("Kill signal detected!\n"));
4778 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4786 ioerr
= psdWaitPipe(pp
);
4787 pps
->pps_ActivePipe
= NULL
;
4788 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4790 /* move end of buffer */
4791 cnt
= pps
->pps_BytesPending
;
4792 tcnt
= pp
->pp_IOReq
.iouh_Actual
;
4793 pps
->pps_BytesPending
-= tcnt
;
4794 bufptr
= pps
->pps_Buffer
;
4795 srcptr
= bufptr
+ tcnt
;
4801 *bufptr
++ = *srcptr
++;
4806 pps
->pps_Error
= ioerr
;
4807 if(ioerr
!= UHIOERR_TIMEOUT
)
4809 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4810 "Packet(%s) failed: %s (%ld)", (STRPTR
) "b",
4811 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4813 ReleaseSemaphore(&pps
->pps_AccessLock
);
4818 /* send out large chunk (avoid copying) */
4819 if(length
>= pp
->pp_IOReq
.iouh_MaxPktSize
)
4821 remlen
= length
- (length
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4822 KPRINTF(1, ("BulkFlush(%p, %ld/%ld)\n", buffer
, remlen
, length
));
4823 Remove(&pp
->pp_Msg
.mn_Node
);
4824 psdSendPipe(pp
, buffer
, remlen
);
4825 pps
->pps_ActivePipe
= pp
;
4826 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4828 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4829 sigmask
= Wait(sigmask
);
4830 if(sigmask
& pps
->pps_AbortSigMask
)
4832 KPRINTF(1, ("Kill signal detected!\n"));
4833 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4841 ioerr
= psdWaitPipe(pp
);
4842 pps
->pps_ActivePipe
= NULL
;
4843 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4845 actual
+= pp
->pp_IOReq
.iouh_Actual
;
4846 buffer
+= pp
->pp_IOReq
.iouh_Actual
;
4847 length
-= pp
->pp_IOReq
.iouh_Actual
;
4850 pps
->pps_Error
= ioerr
;
4851 if(ioerr
!= UHIOERR_TIMEOUT
)
4853 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4854 "Packet(%s) failed: %s (%ld)", (STRPTR
) "c",
4855 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4857 ReleaseSemaphore(&pps
->pps_AccessLock
);
4861 /* buffer remaining bytes */
4864 KPRINTF(1, ("BufAdd(%p, %ld)\n", buffer
, length
));
4865 /* only a few bytes left, so lets buffer them */
4866 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], length
);
4867 pps
->pps_BytesPending
+= length
;
4872 /* start sending out requests */
4873 KPRINTF(1, ("PlainWrite(%p, %ld)\n", buffer
, length
));
4874 Remove(&pp
->pp_Msg
.mn_Node
);
4875 psdSendPipe(pp
, buffer
, length
);
4876 pps
->pps_ActivePipe
= pp
;
4877 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4879 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4880 sigmask
= Wait(sigmask
);
4881 if(sigmask
& pps
->pps_AbortSigMask
)
4883 KPRINTF(1, ("Kill signal detected!\n"));
4884 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4892 ioerr
= psdWaitPipe(pp
);
4893 pps
->pps_ActivePipe
= NULL
;
4894 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4897 pps
->pps_Error
= ioerr
;
4898 if(ioerr
!= UHIOERR_TIMEOUT
)
4900 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4901 "Packet(%s) failed: %s (%ld)", (STRPTR
) "u",
4902 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4905 actual
= pp
->pp_IOReq
.iouh_Actual
;
4908 KPRINTF(2, ("No free pipe!\n"));
4911 ReleaseSemaphore(&pps
->pps_AccessLock
);
4917 /* /// "psdStreamFlush()" */
4918 AROS_LH1(LONG
, psdStreamFlush
,
4919 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4920 LIBBASETYPEPTR
, ps
, 76, psd
)
4928 KPRINTF(2, ("psdStreamFlush(%p)\n", pps
));
4933 ObtainSemaphore(&pps
->pps_AccessLock
);
4935 if(pps
->pps_Endpoint
->pep_Direction
)
4938 KPRINTF(2, ("Flushing in...\n"));
4939 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
4941 psdAbortPipe(pps
->pps_Pipes
[cnt
]);
4943 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
4945 psdWaitPipe(pps
->pps_Pipes
[cnt
]);
4947 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
4948 while(pp
->pp_Msg
.mn_Node
.ln_Succ
)
4950 Remove(&pp
->pp_Msg
.mn_Node
);
4951 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4952 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
4954 while((pp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4956 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4958 pps
->pps_ReqBytes
= 0;
4959 pps
->pps_BytesPending
= 0;
4960 pps
->pps_Offset
= 0;
4964 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4965 if(pp
->pp_Msg
.mn_Node
.ln_Succ
)
4968 if(pps
->pps_BytesPending
)
4970 KPRINTF(2, ("Flushing out %ld...\n", pps
->pps_BytesPending
));
4971 Remove(&pp
->pp_Msg
.mn_Node
);
4972 ioerr
= psdDoPipe(pp
, pps
->pps_Buffer
, pps
->pps_BytesPending
);
4973 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4974 pps
->pps_BytesPending
= 0;
4977 pps
->pps_Error
= ioerr
;
4978 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamFlush",
4979 "Packet(%s) failed: %s (%ld)", (STRPTR
) "f",
4980 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4984 KPRINTF(2, ("Nothing to flush\n"));
4988 ReleaseSemaphore(&pps
->pps_AccessLock
);
4994 /* /// "psdGetStreamError()" */
4995 AROS_LH1(LONG
, psdGetStreamError
,
4996 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4997 LIBBASETYPEPTR
, ps
, 77, psd
)
5000 KPRINTF(1, ("psdGetStreamError(%p)\n", pps
));
5003 return((LONG
) pps
->pps_Error
);
5011 /* *** Realtime Iso */
5013 /* /// "psdAllocRTIsoHandler()" */
5014 AROS_LH2(struct PsdRTIsoHandler
*, psdAllocRTIsoHandlerA
,
5015 AROS_LHA(struct PsdEndpoint
*, pep
, A0
),
5016 AROS_LHA(struct TagItem
*, tags
, A1
),
5017 LIBBASETYPEPTR
, ps
, 93, psd
)
5020 struct PsdRTIsoHandler
*prt
;
5024 KPRINTF(2, ("psdAllocRTIso(%p, %p)\n", pep
, tags
));
5029 if(pep
->pep_TransType
!= USEAF_ISOCHRONOUS
)
5033 if(!(pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Capabilities
& UHCF_RT_ISO
))
5035 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Your HW controller driver does not support realtime iso transfers. Sorry.");
5038 if((prt
= psdAllocVec(sizeof(struct PsdRTIsoHandler
))))
5040 prt
->prt_Device
= pep
->pep_Interface
->pif_Config
->pc_Device
;
5041 prt
->prt_Endpoint
= pep
;
5042 prt
->prt_RTIso
.urti_OutPrefetch
= 2048;
5043 if((pp
= prt
->prt_Pipe
= psdAllocPipe(prt
->prt_Device
, (struct MsgPort
*) 0xffffffff, pep
)))
5045 pp
->pp_MsgPort
= pp
->pp_Msg
.mn_ReplyPort
= NULL
;
5046 psdSetAttrsA(PGA_RTISO
, prt
, tags
);
5047 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_ADDISOHANDLER
;
5048 pp
->pp_IOReq
.iouh_Data
= &prt
->prt_RTIso
;
5049 // hardware must support quick IO for this to work!
5050 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5054 AddTail(&prt
->prt_Device
->pd_RTIsoHandlers
, &prt
->prt_Node
);
5058 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5059 "Adding RT Iso Handler failed: %s (%ld)",
5060 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
5062 psdFreePipe(prt
->prt_Pipe
);
5071 /* /// "psdFreeRTIsoHandler()" */
5072 AROS_LH1(void, psdFreeRTIsoHandler
,
5073 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5074 LIBBASETYPEPTR
, ps
, 94, psd
)
5084 Remove(&prt
->prt_Node
);
5087 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_REMISOHANDLER
;
5088 DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5095 /* /// "psdStartRTIso()" */
5096 AROS_LH1(LONG
, psdStartRTIso
,
5097 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5098 LIBBASETYPEPTR
, ps
, 95, psd
)
5106 return UHIOERR_BADPARAMS
;
5109 if(pp
->pp_Device
->pd_Flags
& PDFF_SUSPENDED
)
5111 // make sure the device is up and running before trying to send a new pipe
5112 psdResumeDevice(pp
->pp_Device
);
5114 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_STARTRTISO
;
5115 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5118 ++pp
->pp_Device
->pd_IOBusyCount
;
5125 /* /// "psdStopRTIso()" */
5126 AROS_LH1(LONG
, psdStopRTIso
,
5127 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5128 LIBBASETYPEPTR
, ps
, 96, psd
)
5136 return UHIOERR_BADPARAMS
;
5139 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_STOPRTISO
;
5140 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5143 --pp
->pp_Device
->pd_IOBusyCount
;
5150 /* *** Classes *** */
5152 /* /// "psdAddClass()" */
5153 AROS_LH2(struct PsdUsbClass
*, psdAddClass
,
5154 AROS_LHA(STRPTR
, name
, A1
),
5155 AROS_LHA(ULONG
, vers
, D0
),
5156 LIBBASETYPEPTR
, ps
, 35, psd
)
5159 struct Library
*cls
= NULL
;
5160 struct PsdUsbClass
*puc
;
5164 STRPTR origname
= name
;
5165 STRPTR evilmsg
[8] = { "Say hello to %s V%ld.%ld (%s).",
5166 "Whoah! %s V%ld.%ld surprised as %s.",
5167 "The door bell rang for %s V%ld.%ld (%s).",
5168 "Welcome %s V%ld.%ld (%s) to the party.",
5170 "Don't laugh at %s V%ld.%ld for %s.",
5171 "Time has come for %s V%ld.%ld (%s) to join the show.",
5172 "Start blaming %s V%ld.%ld for helping at %s.",
5173 "Ain't %s V%ld.%ld useful for %s?" };
5175 KPRINTF(5, ("psdAddClass(%s, %ld)\n", name
, vers
));
5179 if((cls
= OpenLibrary(name
, vers
)))
5185 if((*name
== '/') || (*name
== ':'))
5195 if(FindName(&ps
->ps_Classes
, cls
->lib_Node
.ln_Name
))
5198 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5199 "Attempted to add class %s twice. Nothing is good enough for people like you.",
5201 KPRINTF(20, ("attempt to add class twice!\n"));
5206 if((puc
= psdAllocVec(sizeof(struct PsdUsbClass
))))
5209 puc
->puc_ClassBase
= cls
;
5210 puc
->puc_Node
.ln_Name
= puc
->puc_ClassName
= psdCopyStr(cls
->lib_Node
.ln_Name
);
5211 puc
->puc_FullPath
= psdCopyStr(origname
);
5213 usbGetAttrs(UGA_CLASS
, NULL
,
5214 UCCA_Priority
, &pri
,
5215 UCCA_Description
, &desc
,
5218 puc
->puc_Node
.ln_Pri
= pri
;
5219 psdLockWritePBase();
5220 Enqueue(&ps
->ps_Classes
, &puc
->puc_Node
);
5222 msgoff
= ps
->ps_FunnyCount
++ & 7;
5224 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5226 cls
->lib_Node
.ln_Name
, cls
->lib_Version
, cls
->lib_Revision
, desc
);
5227 psdSendEvent(EHMB_ADDCLASS
, puc
, NULL
);
5237 /* /// "psdRemClass()" */
5238 AROS_LH1(void, psdRemClass
,
5239 AROS_LHA(struct PsdUsbClass
*, puc
, A1
),
5240 LIBBASETYPEPTR
, ps
, 36, psd
)
5243 KPRINTF(5, ("psdRemClass(%p)\n", puc
));
5244 psdLockWritePBase();
5245 Remove(&puc
->puc_Node
);
5248 /* Check if there are still bindings remaining */
5249 while(puc
->puc_UseCnt
)
5251 struct PsdDevice
*pd
;
5252 struct PsdConfig
*pc
;
5253 struct PsdInterface
*pif
;
5255 KPRINTF(20, ("This should never happen: Class %s still in use (%ld), can't close!\n",
5256 puc
->puc_ClassBase
->lib_Node
.ln_Name
, puc
->puc_UseCnt
));
5258 /* Well, try to release the open bindings in a best effort attempt */
5261 while((pd
= psdGetNextDevice(pd
)))
5263 if(pd
->pd_DevBinding
&& (pd
->pd_ClsBinding
== puc
) && (!(pd
->pd_Flags
& PDFF_APPBINDING
)))
5266 psdReleaseDevBinding(pd
);
5268 pd
= NULL
; /* restart */
5271 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5272 while(pc
->pc_Node
.ln_Succ
)
5274 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5275 while(pif
->pif_Node
.ln_Succ
)
5277 if(pif
->pif_IfBinding
&& (pif
->pif_ClsBinding
== puc
))
5280 psdReleaseIfBinding(pif
);
5282 pd
= NULL
; /* restart */
5285 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5287 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5293 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
5294 "This should never happen! Class %s still in use (cnt=%ld). Could not get rid of it! Sorry, we're broke.",
5295 puc
->puc_ClassBase
->lib_Node
.ln_Name
, puc
->puc_UseCnt
);
5297 /*psdDelayMS(2000);*/
5300 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5301 "I shot class %s, but I didn't kill the deputy.",
5302 puc
->puc_ClassBase
->lib_Node
.ln_Name
);
5303 CloseLibrary(puc
->puc_ClassBase
);
5304 psdFreeVec(puc
->puc_ClassName
);
5305 psdFreeVec(puc
->puc_FullPath
);
5307 psdSendEvent(EHMB_REMCLASS
, puc
, NULL
);
5312 /* *** Error Msgs *** */
5314 /* /// "psdAddErrorMsgA()" */
5315 AROS_LH4(struct PsdErrorMsg
*, psdAddErrorMsgA
,
5316 AROS_LHA(UWORD
, level
, D0
),
5317 AROS_LHA(STRPTR
, origin
, A0
),
5318 AROS_LHA(STRPTR
, fmtstr
, A1
),
5319 AROS_LHA(IPTR
*, fmtdata
, A2
),
5320 LIBBASETYPEPTR
, ps
, 40, psd
)
5323 struct PsdErrorMsg
*pem
;
5324 if(((!ps
->ps_GlobalCfg
->pgc_LogInfo
) && (level
< RETURN_WARN
)) ||
5325 ((!ps
->ps_GlobalCfg
->pgc_LogWarning
) && (level
>= RETURN_WARN
) && (level
< RETURN_ERROR
)) ||
5326 ((!ps
->ps_GlobalCfg
->pgc_LogError
) && (level
>= RETURN_ERROR
) && (level
< RETURN_FAIL
)) ||
5327 ((!ps
->ps_GlobalCfg
->pgc_LogFailure
) && (level
>= RETURN_FAIL
)))
5331 if((pem
= psdAllocVec(sizeof(struct PsdErrorMsg
))))
5334 pem
->pem_Level
= level
;
5335 if((pem
->pem_Origin
= psdCopyStr(origin
)))
5337 if((pem
->pem_Msg
= psdCopyStrFmtA(fmtstr
, fmtdata
)))
5339 if (ps
->ps_Flags
& PSF_KLOG
) {
5340 KPrintF("[%s] %s\n", origin
, pem
->pem_Msg
);
5345 DateStamp(&pem
->pem_DateStamp
);
5347 struct timerequest tr
= ps
->ps_TimerIOReq
;
5348 tr
.tr_node
.io_Command
= TR_GETSYSTIME
;
5349 DoIO((struct IORequest
*) &tr
);
5350 pem
->pem_DateStamp
.ds_Days
= tr
.tr_time
.tv_secs
/ (24*60*60);
5351 pem
->pem_DateStamp
.ds_Minute
= (tr
.tr_time
.tv_secs
/ 60) % 60;
5352 pem
->pem_DateStamp
.ds_Tick
= (tr
.tr_time
.tv_secs
% 60) * 50;
5355 AddTail(&ps
->ps_ErrorMsgs
, &pem
->pem_Node
);
5357 psdSendEvent(EHMB_ADDERRORMSG
, pem
, NULL
);
5360 psdFreeVec(pem
->pem_Origin
);
5369 /* /// "psdRemErrorMsg()" */
5370 AROS_LH1(void, psdRemErrorMsg
,
5371 AROS_LHA(struct PsdErrorMsg
*, pem
, A0
),
5372 LIBBASETYPEPTR
, ps
, 41, psd
)
5375 KPRINTF(1, ("psdRemErrorMsg()\n"));
5377 Remove(&pem
->pem_Node
);
5379 psdFreeVec(pem
->pem_Origin
);
5380 psdFreeVec(pem
->pem_Msg
);
5382 psdSendEvent(EHMB_REMERRORMSG
, pem
, NULL
);
5387 /* *** Bindings *** */
5389 /* /// "psdClassScan()" */
5390 AROS_LH0(void, psdClassScan
,
5391 LIBBASETYPEPTR
, ps
, 37, psd
)
5394 struct PsdHardware
*phw
;
5395 struct PsdDevice
*pd
;
5396 struct PsdUsbClass
*puc
;
5400 if((FindTask(NULL
)->tc_Node
.ln_Type
!= NT_PROCESS
) && (!ps
->ps_ConfigRead
))
5402 // it's the first time we were reading the config and DOS was not available
5403 ps
->ps_StartedAsTask
= TRUE
;
5406 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5407 if(!puc
->puc_Node
.ln_Succ
)
5409 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "ClassScan attempted with no classes installed!");
5414 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
5415 while(phw
->phw_Node
.ln_Succ
)
5417 if((pd
= phw
->phw_RootDevice
))
5419 // for the root, do it ourselves, the rest is done by each hub task
5420 psdHubClassScan(pd
);
5422 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
5425 //psdSendEvent(EHMB_CLSSCANRDY, NULL, NULL);
5426 KPRINTF(5, ("************ Scanning finished!\n"));
5431 /* /// "psdDoHubMethodA()" */
5432 AROS_LH3(LONG
, psdDoHubMethodA
,
5433 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5434 AROS_LHA(ULONG
, methodid
, D0
),
5435 AROS_LHA(APTR
, methoddata
, A1
),
5436 LIBBASETYPEPTR
, ps
, 92, psd
)
5439 struct PsdUsbClass
*puc
;
5440 KPRINTF(2, ("psdDoHubMethodA(%p)\n", pd
));
5446 if((pd
->pd_Hub
->pd_DevBinding
) && (puc
= pd
->pd_Hub
->pd_ClsBinding
))
5448 return(usbDoMethodA(methodid
, methoddata
));
5457 /* /// "psdClaimAppBindingA()" */
5458 AROS_LH1(struct PsdAppBinding
*, psdClaimAppBindingA
,
5459 AROS_LHA(struct TagItem
*, tags
, A1
),
5460 LIBBASETYPEPTR
, ps
, 45, psd
)
5463 struct PsdDevice
*pd
;
5464 struct PsdConfig
*pc
;
5465 struct PsdInterface
*pif
;
5466 struct PsdDevice
*hubpd
;
5467 struct PsdAppBinding tmppab
;
5468 struct PsdAppBinding
*pab
= NULL
;
5469 struct PsdUsbClass
*puc
;
5473 KPRINTF(2, ("psdClaimAppBindingA(%p)\n", tags
));
5475 tmppab
.pab_Device
= NULL
;
5476 tmppab
.pab_ReleaseHook
= NULL
;
5477 tmppab
.pab_Task
= NULL
;
5478 tmppab
.pab_ForceRelease
= FALSE
;
5479 psdSetAttrsA(PGA_APPBINDING
, &tmppab
, tags
);
5480 if(tmppab
.pab_Device
&& tmppab
.pab_ReleaseHook
)
5482 pd
= tmppab
.pab_Device
;
5484 // force release of other bindings first
5485 if(tmppab
.pab_ForceRelease
)
5487 /* If there are bindings, get rid of them. */
5488 if(pd
->pd_DevBinding
)
5490 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5491 "%s really wants to bind to %s, so I'm letting the old binding go.",
5492 FindTask(NULL
)->tc_Node
.ln_Name
,
5495 psdReleaseDevBinding(pd
);
5497 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5498 while(pc
->pc_Node
.ln_Succ
)
5500 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5501 while(pif
->pif_Node
.ln_Succ
)
5503 if(pif
->pif_IfBinding
)
5505 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5506 "%s really wants to bind to %s, so I'm letting the old binding go.",
5507 FindTask(NULL
)->tc_Node
.ln_Name
,
5509 psdReleaseIfBinding(pif
);
5511 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5513 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5518 if(!hubpd
) // claim app binding at the root hub -- improbable, but possible.
5520 pab
= psdHubClaimAppBindingA(tags
);
5522 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5524 pab
= (struct PsdAppBinding
*) usbDoMethod(UCM_HubClaimAppBinding
, binding
, tags
);
5529 // fill in task names
5530 pab
->pab_Task
= FindTask(NULL
);
5531 pab
->pab_Node
.ln_Name
= pab
->pab_Task
->tc_Node
.ln_Name
;
5532 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5541 /* /// "psdReleaseAppBinding()" */
5542 AROS_LH1(void, psdReleaseAppBinding
,
5543 AROS_LHA(struct PsdAppBinding
*, pab
, A0
),
5544 LIBBASETYPEPTR
, ps
, 46, psd
)
5547 struct PsdDevice
*pd
;
5548 struct PsdDevice
*hubpd
;
5549 struct PsdUsbClass
*puc
;
5552 KPRINTF(2, ("psdReleaseAppBinding(%p)\n", pab
));
5556 pd
= pab
->pab_Device
;
5558 if(!hubpd
) // release binding of hub (improbable)
5560 psdHubReleaseDevBinding(pd
);
5563 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5565 usbDoMethod(UCM_HubReleaseDevBinding
, binding
, pd
);
5572 /* /// "psdReleaseDevBinding()" */
5573 AROS_LH1(void, psdReleaseDevBinding
,
5574 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5575 LIBBASETYPEPTR
, ps
, 50, psd
)
5578 struct PsdUsbClass
*puc
;
5579 struct PsdDevice
*hubpd
;
5582 KPRINTF(5, ("psdReleaseDevBinding(%p)\n", pd
));
5583 if(pd
->pd_DevBinding
)
5586 if(!hubpd
) // release binding of hub
5588 psdHubReleaseDevBinding(pd
);
5591 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5593 usbDoMethod(UCM_HubReleaseDevBinding
, binding
, pd
);
5600 /* /// "psdReleaseIfBinding()" */
5601 AROS_LH1(void, psdReleaseIfBinding
,
5602 AROS_LHA(struct PsdInterface
*, pif
, A0
),
5603 LIBBASETYPEPTR
, ps
, 51, psd
)
5606 struct PsdUsbClass
*puc
;
5607 struct PsdDevice
*hubpd
;
5610 KPRINTF(5, ("psdReleaseIfBinding(%p)\n", pif
));
5611 if(pif
->pif_IfBinding
&& pif
->pif_ClsBinding
)
5613 hubpd
= pif
->pif_Config
->pc_Device
->pd_Hub
;
5614 if(!hubpd
) // release binding of hub (improbable)
5616 psdHubReleaseIfBinding(pif
);
5619 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5621 usbDoMethod(UCM_HubReleaseIfBinding
, binding
, pif
);
5628 /* /// "psdUnbindAll()" */
5629 AROS_LH0(void, psdUnbindAll
,
5630 LIBBASETYPEPTR
, ps
, 61, psd
)
5633 struct PsdHardware
*phw
;
5634 struct PsdDevice
*pd
;
5635 struct PsdConfig
*pc
;
5636 struct PsdInterface
*pif
;
5639 KPRINTF(10, ("pUnbindAll()\n"));
5640 /* FIXME What happens if devices or hardware gets removed during the process? Need notify semaphore */
5645 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
5646 while(phw
->phw_Node
.ln_Succ
)
5648 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
5649 while(pd
->pd_Node
.ln_Succ
)
5651 /* If there are bindings, get rid of them. */
5652 if(pd
->pd_DevBinding
)
5655 psdReleaseDevBinding(pd
);
5660 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5661 while(pc
->pc_Node
.ln_Succ
)
5663 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5664 while(pif
->pif_Node
.ln_Succ
)
5666 if(pif
->pif_IfBinding
)
5669 psdReleaseIfBinding(pif
);
5674 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5680 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5686 pd
= (struct PsdDevice
*) pd
->pd_Node
.ln_Succ
;
5692 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
5700 /* /// "psdHubClassScan()" */
5701 AROS_LH1(void, psdHubClassScan
,
5702 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5703 LIBBASETYPEPTR
, ps
, 82, psd
)
5706 struct PsdUsbClass
*puc
;
5707 struct PsdConfig
*pc
;
5708 struct PsdInterface
*pif
;
5709 struct PsdInterface
*firstpif
;
5710 struct PsdPipe
*pp
= NULL
;
5717 KPRINTF(5, ("psdClassScan()\n"));
5719 if(!(mp
= CreateMsgPort()))
5724 psdLockWriteDevice(pd
);
5725 while(!(pd
->pd_PoPoCfg
.poc_NoClassBind
|| pd
->pd_DevBinding
))
5727 if(!(pp
= psdAllocPipe(pd
, mp
, NULL
)))
5731 KPRINTF(5, ("Doing ClassScan on Device: %s\n", pd
->pd_ProductStr
));
5733 /* First look if there is any interface binding. We may not change
5734 the current config in this case! */
5735 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5736 while(pc
->pc_Node
.ln_Succ
)
5738 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5740 while(pif
->pif_Node
.ln_Succ
)
5742 if(pif
->pif_IfBinding
)
5744 hasifbinding
= pc
->pc_CfgNum
;
5747 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5749 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5752 owner
= psdGetForcedBinding(pd
->pd_IDString
, NULL
);
5753 if((!hasifbinding
) && owner
)
5755 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5756 while(puc
->puc_Node
.ln_Succ
)
5758 if(!strcmp(owner
, puc
->puc_ClassName
))
5760 if((pd
->pd_DevBinding
= (APTR
) usbDoMethod(UCM_ForceDeviceBinding
, pd
)))
5762 pd
->pd_ClsBinding
= puc
;
5764 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5766 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5767 "Forced device binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5771 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5773 /* no more scanning required, abort here */
5777 /* Second attempt */
5778 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5779 while(pc
->pc_Node
.ln_Succ
)
5781 if((!hasifbinding
) || (hasifbinding
== pc
->pc_CfgNum
))
5783 /* If the current config is not the one selected, change it */
5784 if(pd
->pd_CurrCfg
!= pc
->pc_CfgNum
)
5786 psdSetDeviceConfig(pp
, pc
->pc_CfgNum
);
5788 KPRINTF(5, (" Config %ld\n", pc
->pc_CfgNum
));
5789 /* If something went wrong above, we must exclude this config */
5790 if(pd
->pd_CurrCfg
== pc
->pc_CfgNum
)
5792 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5793 while(pif
->pif_Node
.ln_Succ
)
5795 KPRINTF(5, (" Interface %ld\n", pif
->pif_IfNum
));
5798 if(!pif
->pif_IfBinding
)
5803 if(!psdSetAltInterface(pp
, pif
))
5805 pif
->pif_IfBinding
= NULL
;
5806 /* Okay, this alternate setting failed. Try to get next one */
5809 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5810 if(pif
->pif_Node
.ln_Succ
)
5812 KPRINTF(5, ("CONT!\n"));
5815 KPRINTF(5, ("BREAK!\n"));
5821 owner
= psdGetForcedBinding(pd
->pd_IDString
, pif
->pif_IDString
);
5822 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5823 while(puc
->puc_Node
.ln_Succ
)
5825 KPRINTF(5, (">>>PING %s!\n", puc
->puc_ClassName
));
5828 if(!strcmp(owner
, puc
->puc_ClassName
))
5830 binding
= (APTR
) usbDoMethod(UCM_ForceInterfaceBinding
, pif
);
5833 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5834 "Forced interface binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5839 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5843 binding
= (APTR
) usbDoMethod(UCM_AttemptInterfaceBinding
, pif
);
5846 KPRINTF(5, ("<<<PONG!!\n"));
5849 KPRINTF(5, ("Got binding!\n"));
5850 /* Find root config structure */
5851 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5852 while(pif
->pif_Node
.ln_Succ
)
5854 if(pif
->pif_IfNum
== firstpif
->pif_IfNum
)
5858 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5860 if(!pif
->pif_Node
.ln_Succ
)
5862 KPRINTF(5, ("Fucked it up!\n"));
5863 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Something incredibly stupid happend. I've given up.");
5867 pif
->pif_IfBinding
= binding
;
5868 pif
->pif_ClsBinding
= puc
;
5869 hasifbinding
= pc
->pc_CfgNum
;
5871 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5876 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5882 //break; /* FIXME: DISABLED ALTSCANNING */
5883 /* Check alternate setting */
5884 if(pif
->pif_AlterIfs
.lh_Head
->ln_Succ
)
5886 /* There are some alternative interfaces, start at top */
5887 pif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
5890 } while(pif
!= firstpif
);
5891 //pif->pif_IfBinding = binding;
5894 psdSetAltInterface(pp
, pif
);
5896 /* Hohum, search current main interface then */
5897 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5898 while(pif
->pif_Node
.ln_Succ
)
5900 if(pif
->pif_IfNum
== firstpif
->pif_IfNum
)
5904 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5907 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5911 KPRINTF(5, ("End, next ConfigCheck!\n"));
5912 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5914 /* Could not establish interface binding, try device binding then */
5918 //pd->pd_DevBinding = (APTR) ~0UL;
5920 owner
= psdGetForcedBinding(pd
->pd_IDString
, NULL
);
5921 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5922 while(puc
->puc_Node
.ln_Succ
)
5927 if(!strcmp(owner
, puc
->puc_ClassName
))
5929 binding
= (APTR
) usbDoMethod(UCM_ForceDeviceBinding
, pd
, TAG_END
);
5932 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5933 "Forced device binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5938 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5942 binding
= (APTR
) usbDoMethod(UCM_AttemptDeviceBinding
, pd
);
5946 pd
->pd_DevBinding
= binding
;
5947 pd
->pd_ClsBinding
= puc
;
5949 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5952 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5954 pd
->pd_DevBinding
= binding
;
5962 // call hub class scan code
5963 if((binding
= pd
->pd_DevBinding
) && (puc
= pd
->pd_ClsBinding
))
5965 usbDoMethod(UCM_HubClassScan
, binding
);
5967 psdUnlockDevice(pd
);
5974 /* /// "psdHubClaimAppBindingA()" */
5975 AROS_LH1(struct PsdAppBinding
*, psdHubClaimAppBindingA
,
5976 AROS_LHA(struct TagItem
*, tags
, A1
),
5977 LIBBASETYPEPTR
, ps
, 83, psd
)
5980 struct PsdDevice
*pd
;
5981 struct PsdAppBinding
*pab
;
5982 struct PsdConfig
*pc
;
5983 struct PsdInterface
*pif
;
5985 BOOL hasbinding
= FALSE
;
5986 KPRINTF(2, ("psdHubClaimAppBindingA(%p)\n", tags
));
5988 if((pab
= psdAllocVec(sizeof(struct PsdAppBinding
))))
5990 psdSetAttrsA(PGA_APPBINDING
, pab
, tags
);
5991 if(pab
->pab_Device
&& pab
->pab_ReleaseHook
)
5993 pd
= pab
->pab_Device
;
5994 if(pd
->pd_DevBinding
)
5998 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5999 while(pc
->pc_Node
.ln_Succ
)
6001 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
6003 while(pif
->pif_Node
.ln_Succ
)
6005 if(pif
->pif_IfBinding
)
6010 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
6012 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
6017 pd
->pd_Flags
|= PDFF_APPBINDING
;
6018 pd
->pd_DevBinding
= pab
;
6019 pd
->pd_ClsBinding
= NULL
;
6030 /* /// "psdHubReleaseDevBinding()" */
6031 AROS_LH1(void, psdHubReleaseDevBinding
,
6032 AROS_LHA(struct PsdDevice
*, pd
, A0
),
6033 LIBBASETYPEPTR
, ps
, 84, psd
)
6036 struct PsdUsbClass
*puc
;
6038 struct PsdAppBinding
*pab
;
6040 KPRINTF(5, ("psdHubReleaseDevBinding(%p)\n", pd
));
6043 psdLockWriteDevice(pd
);
6044 if((binding
= pd
->pd_DevBinding
))
6046 pd
->pd_DevBinding
= NULL
;
6047 if(pd
->pd_Flags
& PDFF_APPBINDING
)
6049 pab
= (struct PsdAppBinding
*) binding
;
6050 CallHookPkt(pab
->pab_ReleaseHook
, pab
, (APTR
) pab
->pab_UserData
);
6051 pd
->pd_ClsBinding
= NULL
;
6052 pd
->pd_Flags
&= ~PDFF_APPBINDING
;
6054 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6056 puc
= pd
->pd_ClsBinding
;
6059 pd
->pd_ClsBinding
= NULL
;
6060 usbDoMethod(UCM_ReleaseDeviceBinding
, binding
);
6062 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6066 psdUnlockDevice(pd
);
6072 /* /// "psdHubReleaseIfBinding()" */
6073 AROS_LH1(void, psdHubReleaseIfBinding
,
6074 AROS_LHA(struct PsdInterface
*, pif
, A0
),
6075 LIBBASETYPEPTR
, ps
, 85, psd
)
6078 struct PsdUsbClass
*puc
;
6079 struct PsdDevice
*pd
;
6082 KPRINTF(5, ("psdHubReleaseIfBinding(%p)\n", pif
));
6086 pd
= pif
->pif_Config
->pc_Device
;
6087 psdLockWriteDevice(pd
);
6088 if((binding
= pif
->pif_IfBinding
))
6090 pif
->pif_IfBinding
= NULL
;
6091 puc
= pif
->pif_ClsBinding
;
6094 pif
->pif_ClsBinding
= NULL
;
6095 usbDoMethod(UCM_ReleaseInterfaceBinding
, binding
);
6098 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6100 psdUnlockDevice(pd
);
6106 /* *** Events *** */
6108 /* /// "psdAddEventHandler()" */
6109 AROS_LH2(struct PsdEventHook
*, psdAddEventHandler
,
6110 AROS_LHA(struct MsgPort
*, mp
, A1
),
6111 AROS_LHA(ULONG
, msgmask
, D0
),
6112 LIBBASETYPEPTR
, ps
, 47, psd
)
6115 struct PsdEventHook
*peh
= NULL
;
6117 KPRINTF(5, ("psdAddEventHandler(%p, %p)\n", mp
, msgmask
));
6121 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6122 if((peh
= psdAllocVec(sizeof(struct PsdEventHook
))))
6124 peh
->peh_MsgPort
= mp
;
6125 peh
->peh_MsgMask
= msgmask
;
6126 AddTail(&ps
->ps_EventHooks
, &peh
->peh_Node
);
6128 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6135 /* /// "psdRemEventHandler()" */
6136 AROS_LH1(void, psdRemEventHandler
,
6137 AROS_LHA(struct PsdEventHook
*, peh
, A0
),
6138 LIBBASETYPEPTR
, ps
, 48, psd
)
6141 struct Message
*msg
;
6143 KPRINTF(5, ("psdRemEventHandler(%p)\n", peh
));
6148 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6149 Remove(&peh
->peh_Node
);
6150 while((msg
= GetMsg(peh
->peh_MsgPort
)))
6154 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6155 pGarbageCollectEvents(ps
);
6161 /* /// "psdSendEvent()" */
6162 AROS_LH3(void, psdSendEvent
,
6163 AROS_LHA(ULONG
, ehmt
, D0
),
6164 AROS_LHA(APTR
, param1
, A0
),
6165 AROS_LHA(APTR
, param2
, A1
),
6166 LIBBASETYPEPTR
, ps
, 49, psd
)
6169 struct PsdEventNote
*pen
;
6170 struct PsdEventHook
*peh
;
6171 ULONG msgmask
= (1L<<ehmt
);
6173 KPRINTF(1, ("psdSendEvent(%p, %p, %p)\n", ehmt
, param1
, param2
));
6175 pGarbageCollectEvents(ps
);
6176 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6177 peh
= (struct PsdEventHook
*) ps
->ps_EventHooks
.lh_Head
;
6178 while(peh
->peh_Node
.ln_Succ
)
6180 if(peh
->peh_MsgMask
& msgmask
)
6182 if((pen
= psdAllocVec(sizeof(struct PsdEventNote
))))
6184 pen
->pen_Msg
.mn_ReplyPort
= &ps
->ps_EventReplyPort
;
6185 pen
->pen_Msg
.mn_Length
= sizeof(struct PsdEventNote
);
6186 pen
->pen_Event
= ehmt
;
6187 pen
->pen_Param1
= param1
;
6188 pen
->pen_Param2
= param2
;
6189 PutMsg(peh
->peh_MsgPort
, &pen
->pen_Msg
);
6192 peh
= (struct PsdEventHook
*) peh
->peh_Node
.ln_Succ
;
6194 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6199 /* *** Configuration *** */
6201 /* /// "psdReadCfg()" */
6202 AROS_LH2(BOOL
, psdReadCfg
,
6203 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6204 AROS_LHA(APTR
, formdata
, A1
),
6205 LIBBASETYPEPTR
, ps
, 52, psd
)
6208 struct PsdIFFContext
*subpic
;
6211 ULONG
*buf
= formdata
;
6213 KPRINTF(10, ("psdReadCfg(%p, %p)\n", pic
, formdata
));
6215 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6218 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6219 if(!(pic
->pic_Node
.ln_Succ
))
6221 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6225 if((AROS_LONG2BE(*buf
) != ID_FORM
) || (AROS_LONG2BE(buf
[2]) != pic
->pic_FormID
))
6227 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to replace a cfg form with a chunk or with an alien form!");
6228 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6231 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6232 while(subpic
->pic_Node
.ln_Succ
)
6234 pFreeForm(ps
, subpic
);
6235 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6237 pic
->pic_ChunksLen
= 0;
6238 len
= (AROS_LONG2BE(buf
[1]) - 3) & ~1UL;
6242 if(!(pAddCfgChunk(ps
, pic
, buf
)))
6246 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
6248 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
6252 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to add a nasty corrupted FORM chunk! Configuration is probably b0rken!");
6256 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6257 ps
->ps_CheckConfigReq
= TRUE
;
6263 /* /// "psdLoadCfgFromDisk()" */
6264 AROS_LH1(BOOL
, psdLoadCfgFromDisk
,
6265 AROS_LHA(STRPTR
, filename
, A1
),
6266 LIBBASETYPEPTR
, ps
, 79, psd
)
6270 BOOL loaded
= FALSE
;
6275 XPRINTF(10, ("Loading config file: %s\n", filename
));
6279 loaded
= psdLoadCfgFromDisk("ENV:Sys/poseidon.prefs");
6285 loaded
= psdLoadCfgFromDisk("ENVARC:Sys/poseidon.prefs");
6292 KPRINTF(1, ("dos.library not available yet\n"));
6296 filehandle
= Open(filename
, MODE_OLDFILE
);
6297 KPRINTF(1, ("File handle 0x%p\n", filehandle
));
6300 if(Read(filehandle
, formhead
, 12) == 12)
6302 KPRINTF(1, ("Read header\n"));
6303 if((AROS_LONG2BE(formhead
[0]) == ID_FORM
) && (AROS_LONG2BE(formhead
[2]) == IFFFORM_PSDCFG
))
6305 formlen
= AROS_LONG2BE(formhead
[1]);
6306 KPRINTF(1, ("Header OK, %lu bytes\n", formlen
));
6308 buf
= (ULONG
*) psdAllocVec(formlen
+ 8);
6311 buf
[0] = formhead
[0];
6312 buf
[1] = formhead
[1];
6313 buf
[2] = formhead
[2];
6314 if(Read(filehandle
, &buf
[3], formlen
- 4) == formlen
- 4)
6316 KPRINTF(1, ("Data read OK\n"));
6318 psdReadCfg(NULL
, buf
);
6321 KPRINTF(1, ("All done\n"));
6330 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6331 "Failed to load config from '%s'!",
6336 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
;
6343 /* /// "psdSaveCfgToDisk()" */
6344 AROS_LH2(BOOL
, psdSaveCfgToDisk
,
6345 AROS_LHA(STRPTR
, filename
, A1
),
6346 AROS_LHA(BOOL
, executable
, D0
),
6347 LIBBASETYPEPTR
, ps
, 80, psd
)
6356 saved
= psdSaveCfgToDisk("ENVARC:Sys/poseidon.prefs", FALSE
);
6357 saved
&= psdSaveCfgToDisk("ENV:Sys/poseidon.prefs", FALSE
);
6365 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6367 buf
= (ULONG
*) psdWriteCfg(NULL
);
6371 filehandle
= Open(filename
, MODE_NEWFILE
);
6374 Write(filehandle
, buf
, (AROS_LONG2BE(buf
[1])+9) & ~1UL);
6378 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6379 "Failed to write config to '%s'!",
6384 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6387 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
;
6394 /* /// "psdWriteCfg()" */
6395 AROS_LH1(APTR
, psdWriteCfg
,
6396 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6397 LIBBASETYPEPTR
, ps
, 53, psd
)
6403 KPRINTF(10, ("psdWriteCfg(%p)\n", pic
));
6405 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6408 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6409 if(!(pic
->pic_Node
.ln_Succ
))
6411 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6415 pUpdateGlobalCfg(ps
, pic
);
6416 ps
->ps_CheckConfigReq
= TRUE
;
6417 len
= pGetFormLength(pic
);
6418 if((buf
= psdAllocVec(len
)))
6420 pInternalWriteForm(pic
, buf
);
6422 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6428 /* /// "psdFindCfgForm()" */
6429 AROS_LH2(struct PsdIFFContext
*, psdFindCfgForm
,
6430 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6431 AROS_LHA(ULONG
, formid
, D0
),
6432 LIBBASETYPEPTR
, ps
, 54, psd
)
6435 struct PsdIFFContext
*subpic
;
6437 KPRINTF(160, ("psdFindCfgForm(0x%p, 0x%08lx)\n", pic
, formid
));
6438 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6441 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6442 if(!(pic
->pic_Node
.ln_Succ
))
6444 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6448 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6449 while(subpic
->pic_Node
.ln_Succ
)
6451 if(subpic
->pic_FormID
== formid
)
6453 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6456 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
6458 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6464 /* /// "psdNextCfgForm()" */
6465 AROS_LH1(struct PsdIFFContext
*, psdNextCfgForm
,
6466 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6467 LIBBASETYPEPTR
, ps
, 55, psd
)
6471 KPRINTF(160, ("psdNextCfgForm(%p)\n", pic
));
6477 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6478 formid
= pic
->pic_FormID
;
6479 pic
= (struct PsdIFFContext
*) pic
->pic_Node
.ln_Succ
;
6480 while(pic
->pic_Node
.ln_Succ
)
6482 if(pic
->pic_FormID
== formid
)
6484 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6486 KPRINTF(1, ("Found context 0x%p\n", pic
));
6489 pic
= (struct PsdIFFContext
*) pic
->pic_Node
.ln_Succ
;
6491 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6497 /* /// "psdAllocCfgForm()" */
6498 AROS_LH1(struct PsdIFFContext
*, psdAllocCfgForm
,
6499 AROS_LHA(ULONG
, formid
, D0
),
6500 LIBBASETYPEPTR
, ps
, 86, psd
)
6503 struct PsdIFFContext
*pic
;
6504 KPRINTF(10, ("psdAllocCfgForm(%p)\n", formid
));
6505 if((pic
= psdAllocVec(sizeof(struct PsdIFFContext
))))
6507 NewList(&pic
->pic_SubForms
);
6508 //pic->pic_Parent = parent;
6509 pic
->pic_FormID
= formid
;
6510 pic
->pic_FormLength
= 4;
6511 pic
->pic_Chunks
= NULL
;
6512 pic
->pic_ChunksLen
= 0;
6513 pic
->pic_BufferLen
= 0;
6515 AddTail(&ps
->ps_AlienConfigs
, &pic
->pic_Node
);
6523 /* /// "psdRemCfgForm()" */
6524 AROS_LH1(void, psdRemCfgForm
,
6525 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6526 LIBBASETYPEPTR
, ps
, 56, psd
)
6529 KPRINTF(10, ("psdRemCfgForm(%p)\n", pic
));
6531 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6534 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6535 if(!(pic
->pic_Node
.ln_Succ
))
6537 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6542 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6543 ps
->ps_CheckConfigReq
= TRUE
;
6548 /* /// "psdAddCfgEntry()" */
6549 AROS_LH2(struct PsdIFFContext
*, psdAddCfgEntry
,
6550 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6551 AROS_LHA(APTR
, formdata
, A1
),
6552 LIBBASETYPEPTR
, ps
, 57, psd
)
6555 struct PsdIFFContext
*res
;
6557 KPRINTF(10, ("psdAddCfgEntry(%p, %p)\n", pic
, formdata
));
6558 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6561 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6562 if(!(pic
->pic_Node
.ln_Succ
))
6564 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6568 res
= pAddCfgChunk(ps
, pic
, formdata
);
6569 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6570 ps
->ps_CheckConfigReq
= TRUE
;
6576 /* /// "psdRemCfgChunk()" */
6577 AROS_LH2(BOOL
, psdRemCfgChunk
,
6578 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6579 AROS_LHA(ULONG
, chnkid
, D0
),
6580 LIBBASETYPEPTR
, ps
, 58, psd
)
6585 KPRINTF(10, ("psdRemCfgChunk(%p, %p)\n", pic
, chnkid
));
6586 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6589 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6590 if(!(pic
->pic_Node
.ln_Succ
))
6592 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6598 res
= pRemCfgChunk(ps
, pic
, chnkid
);
6600 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6601 while(subpic
->pic_Node
.ln_Succ
)
6603 pFreeForm(ps
, subpic
);
6605 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6607 if(pic
->pic_ChunksLen
)
6611 pic
->pic_ChunksLen
= 0;
6612 pic
->pic_FormLength
= 4;
6615 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6616 ps
->ps_CheckConfigReq
= TRUE
;
6622 /* /// "psdGetCfgChunk()" */
6623 AROS_LH2(APTR
, psdGetCfgChunk
,
6624 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6625 AROS_LHA(ULONG
, chnkid
, D0
),
6626 LIBBASETYPEPTR
, ps
, 59, psd
)
6632 KPRINTF(10, ("psdGetCfgChunk(%p, 0x%08lx)\n", pic
, chnkid
));
6634 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6637 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6638 if(!(pic
->pic_Node
.ln_Succ
))
6640 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6644 pUpdateGlobalCfg(ps
, pic
);
6645 chnk
= pFindCfgChunk(ps
, pic
, chnkid
);
6648 res
= psdAllocVec(AROS_LONG2BE(chnk
[1])+8);
6651 memcpy(res
, chnk
, AROS_LONG2BE(chnk
[1])+8);
6654 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6660 /* /// "psdParseCfg()" */
6661 AROS_LH0(void, psdParseCfg
,
6662 LIBBASETYPEPTR
, ps
, 60, psd
)
6665 struct PsdIFFContext
*pic
;
6666 struct PsdIFFContext
*subpic
;
6670 struct PsdHardware
*phw
;
6671 struct PsdUsbClass
*puc
;
6672 BOOL removeall
= TRUE
;
6673 BOOL nodos
= (FindTask(NULL
)->tc_Node
.ln_Type
!= NT_PROCESS
);
6676 XPRINTF(10, ("psdParseCfg()\n"));
6678 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6679 pCheckCfgChanged(ps
);
6680 pic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
);
6683 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6687 // if no config for hardware is found, we don't remove the devices,
6688 // because this could render the system useless (no USB mice or
6689 // keyboards to configure the hardware!)
6690 if(!psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
))
6692 XPRINTF(10, ("No hardware data present\n"));
6698 /* select all hardware devices for removal */
6699 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6700 while(phw
->phw_Node
.ln_Succ
)
6702 phw
->phw_RemoveMe
= removeall
;
6703 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
6706 /* select all classes for removal */
6707 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6708 while(puc
->puc_Node
.ln_Succ
)
6711 * For kickstart-resident classes we check usage count, and
6712 * remove them only if it's zero.
6713 * These classes can be responsible for devices which we can use
6714 * at boot time. If we happen to remove them, we can end up with
6715 * no input or storage devices at all.
6717 if (FindResident(puc
->puc_ClassName
))
6718 puc
->puc_RemoveMe
= (puc
->puc_UseCnt
== 0);
6720 puc
->puc_RemoveMe
= TRUE
;
6722 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6727 /* Get Hardware config */
6728 subpic
= psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
);
6731 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6734 name
= (STRPTR
) &chnk
[2];
6736 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_UNIT
);
6741 if(!pFindCfgChunk(ps
, subpic
, IFFCHNK_OFFLINE
))
6743 phw
= pFindHardware(ps
, name
, unit
);
6744 XPRINTF(5, ("Have configuration for device 0x%p (%s unit %u)\n", phw
, name
, unit
));
6747 phw
->phw_RemoveMe
= FALSE
;
6751 subpic
= psdNextCfgForm(subpic
);
6754 /* Get Class config */
6755 subpic
= psdFindCfgForm(pic
, IFFFORM_USBCLASS
);
6758 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6761 name
= (STRPTR
) &chnk
[2];
6762 puc
= (struct PsdUsbClass
*) pFindName(ps
, &ps
->ps_Classes
, name
);
6763 XPRINTF(5, ("Have configuration for class 0x%p (%s)\n", puc
, name
));
6766 puc
->puc_RemoveMe
= FALSE
;
6769 subpic
= psdNextCfgForm(subpic
);
6772 // unlock config while removing to avoid deadlocks.
6773 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6775 /* now remove remaining classes not found in the config */
6776 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6777 while(puc
->puc_Node
.ln_Succ
)
6779 if(puc
->puc_RemoveMe
)
6781 XPRINTF(5, ("Removing class %s\n", puc
->puc_ClassName
));
6783 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6785 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6789 /* now remove all remaining hardware not found in the config */
6790 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6791 while(phw
->phw_Node
.ln_Succ
)
6793 if(phw
->phw_RemoveMe
)
6795 XPRINTF(5, ("Removing device %s unit %u\n", phw
->phw_DevName
, phw
->phw_Unit
));
6796 psdRemHardware(phw
);
6797 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6799 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
6803 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6804 pic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
);
6807 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6812 /* Add missing Classes */
6813 subpic
= psdFindCfgForm(pic
, IFFFORM_USBCLASS
);
6816 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6819 /* *** FIXME *** POSSIBLE DEADLOCK WHEN CLASS TRIES TO DO CONFIG STUFF IN
6820 AN EXTERNAL TASK INSIDE LIBOPEN CODE */
6821 name
= (STRPTR
) &chnk
[2];
6822 puc
= (struct PsdUsbClass
*) pFindName(ps
, &ps
->ps_Classes
, name
);
6825 psdAddClass(name
, 0);
6828 subpic
= psdNextCfgForm(subpic
);
6831 /* Now really mount Hardware found in config */
6832 subpic
= psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
);
6835 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6838 name
= (STRPTR
) &chnk
[2];
6840 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_UNIT
);
6845 if(!pFindCfgChunk(ps
, subpic
, IFFCHNK_OFFLINE
))
6847 phw
= pFindHardware(ps
, name
, unit
);
6850 phw
= psdAddHardware(name
, unit
);
6853 psdEnumerateHardware(phw
);
6858 subpic
= psdNextCfgForm(subpic
);
6860 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6862 if(!nodos
&& ps
->ps_StartedAsTask
)
6864 // last time we were reading the config before DOS, so maybe we need to
6865 // unbind some classes that need to be overruled by newly available classes,
6866 // such as hid.class overruling bootmouse & bootkeyboard.
6867 // so unbind those classes that promote themselves as AfterDOS
6870 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Checking AfterDOS...");
6871 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6872 while(puc
->puc_Node
.ln_Succ
)
6875 usbGetAttrs(UGA_CLASS
, NULL
,
6876 UCCA_AfterDOSRestart
, &restartme
,
6879 if(restartme
&& puc
->puc_UseCnt
)
6881 struct PsdDevice
*pd
;
6882 struct PsdConfig
*pc
;
6883 struct PsdInterface
*pif
;
6885 /* Well, try to release the open bindings in a best effort attempt */
6887 while((pd
= psdGetNextDevice(pd
)))
6889 if(pd
->pd_DevBinding
&& (pd
->pd_ClsBinding
== puc
) && (!(pd
->pd_Flags
& PDFF_APPBINDING
)))
6892 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6893 "AfterDOS: Temporarily releasing %s %s binding to %s.",
6894 puc
->puc_ClassName
, "device", pd
->pd_ProductStr
);
6895 psdReleaseDevBinding(pd
);
6897 pd
= NULL
; /* restart */
6900 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
6901 while(pc
->pc_Node
.ln_Succ
)
6903 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
6904 while(pif
->pif_Node
.ln_Succ
)
6906 if(pif
->pif_IfBinding
&& (pif
->pif_ClsBinding
== puc
))
6909 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6910 "AfterDOS: Temporarily releasing %s %s binding to %s.",
6911 puc
->puc_ClassName
, "interface", pd
->pd_ProductStr
);
6912 psdReleaseIfBinding(pif
);
6914 pd
= NULL
; /* restart */
6917 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
6919 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
6923 usbDoMethodA(UCM_DOSAvailableEvent
, NULL
);
6924 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6926 ps
->ps_StartedAsTask
= FALSE
;
6930 if(nodos
&& (!ps
->ps_ConfigRead
))
6932 // it's the first time we were reading the config and DOS was not available
6933 ps
->ps_StartedAsTask
= TRUE
;
6935 ps
->ps_ConfigRead
= TRUE
;
6936 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
; // update saved hash
6938 /* do a class scan */
6941 if(nodos
&& ps
->ps_GlobalCfg
->pgc_BootDelay
)
6943 // wait for hubs to settle
6945 puc
= (struct PsdUsbClass
*) FindName(&ps
->ps_Classes
, "massstorage.class");
6946 if(puc
&& puc
->puc_UseCnt
)
6948 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6949 "Delaying further execution by %ld second(s) (boot delay).",
6950 ps
->ps_GlobalCfg
->pgc_BootDelay
);
6951 if(ps
->ps_GlobalCfg
->pgc_BootDelay
>= 1);
6953 psdDelayMS((ps
->ps_GlobalCfg
->pgc_BootDelay
-1)*1000);
6956 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Boot delay skipped, no mass storage devices found.");
6963 /* /// "psdSetClsCfg()" */
6964 AROS_LH2(BOOL
, psdSetClsCfg
,
6965 AROS_LHA(STRPTR
, owner
, A0
),
6966 AROS_LHA(APTR
, form
, A1
),
6967 LIBBASETYPEPTR
, ps
, 62, psd
)
6970 struct PsdIFFContext
*pic
;
6971 BOOL result
= FALSE
;
6973 KPRINTF(10, ("psdSetClsCfg(%s, %p)\n", owner
, form
));
6974 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6975 pic
= psdFindCfgForm(NULL
, IFFFORM_CLASSCFG
);
6978 if(pMatchStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
6980 pic
= psdFindCfgForm(pic
, IFFFORM_CLASSDATA
);
6985 result
= psdReadCfg(pic
, form
);
6987 psdRemCfgChunk(pic
, 0);
6995 pic
= psdNextCfgForm(pic
);
6999 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7000 pCheckCfgChanged(ps
);
7003 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7004 if(pic
->pic_Node
.ln_Succ
)
7006 pic
= pAllocForm(ps
, pic
, IFFFORM_CLASSCFG
);
7009 if(pAddStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7013 if(pAddCfgChunk(ps
, pic
, form
))
7015 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7016 pCheckCfgChanged(ps
);
7021 buf
[0] = AROS_LONG2BE(ID_FORM
);
7022 buf
[1] = AROS_LONG2BE(4);
7023 buf
[2] = AROS_LONG2BE(IFFFORM_CLASSDATA
);
7024 if(pAddCfgChunk(ps
, pic
, buf
))
7026 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7027 pCheckCfgChanged(ps
);
7034 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7035 pCheckCfgChanged(ps
);
7041 /* /// "psdGetClsCfg()" */
7042 AROS_LH1(struct PsdIFFContext
*, psdGetClsCfg
,
7043 AROS_LHA(STRPTR
, owner
, A0
),
7044 LIBBASETYPEPTR
, ps
, 63, psd
)
7047 struct PsdIFFContext
*pic
;
7049 KPRINTF(10, ("psdGetClsCfg(%s)\n", owner
));
7050 pic
= psdFindCfgForm(NULL
, IFFFORM_CLASSCFG
);
7053 if(pMatchStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7055 return(psdFindCfgForm(pic
, IFFFORM_CLASSDATA
));
7057 pic
= psdNextCfgForm(pic
);
7064 /* /// "psdSetUsbDevCfg()" */
7065 AROS_LH4(BOOL
, psdSetUsbDevCfg
,
7066 AROS_LHA(STRPTR
, owner
, A0
),
7067 AROS_LHA(STRPTR
, devid
, A2
),
7068 AROS_LHA(STRPTR
, ifid
, A3
),
7069 AROS_LHA(APTR
, form
, A1
),
7070 LIBBASETYPEPTR
, ps
, 64, psd
)
7073 struct PsdIFFContext
*pic
;
7074 struct PsdIFFContext
*cpic
= NULL
;
7075 struct PsdIFFContext
*mpic
= NULL
;
7076 BOOL result
= FALSE
;
7078 KPRINTF(10, ("psdSetUsbDevCfg(%s, %s, %s, %p)\n", owner
, devid
, ifid
, form
));
7079 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7080 /* Find device config form. It contains all device config data */
7081 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7084 /* Find DEVID-Chunk. Check if it matches our device id */
7085 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7088 /* We found the correct device. Now if we need to store interface data, find the interface first */
7091 /* Search interface config form */
7092 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7095 /* Found the form. Find the the ID String for the interface */
7096 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7098 /* ID did match, now check for owner */
7099 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7101 /* found it! So there is already a config saved in there. Search for dev config data form */
7102 cpic
= psdFindCfgForm(mpic
, IFFFORM_IFCLSDATA
);
7105 /* not found, generate it */
7106 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7111 mpic
= psdNextCfgForm(mpic
);
7115 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7117 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7119 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7121 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7127 /* Search for device config */
7128 mpic
= psdFindCfgForm(pic
, IFFFORM_DEVCFGDATA
);
7131 /* search for the right owner */
7132 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7134 /* found it! So there is already a config saved in there. Search for dev config data form */
7135 cpic
= psdFindCfgForm(mpic
, IFFFORM_DEVCLSDATA
);
7138 /* not found, generate it */
7139 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7143 mpic
= psdNextCfgForm(mpic
);
7145 if(!cpic
) /* no device config form */
7147 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_DEVCFGDATA
)))
7149 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7151 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7160 result
= psdReadCfg(cpic
, form
);
7162 psdRemCfgChunk(cpic
, 0);
7168 pic
= psdNextCfgForm(pic
);
7172 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7173 pCheckCfgChanged(ps
);
7177 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7178 if(pic
->pic_Node
.ln_Succ
)
7180 pic
= pAllocForm(ps
, pic
, IFFFORM_DEVICECFG
);
7183 if(pAddStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7187 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7189 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7191 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7193 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7198 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_DEVCFGDATA
)))
7200 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7202 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7210 result
= psdReadCfg(cpic
, form
);
7212 psdRemCfgChunk(cpic
, 0);
7219 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7220 pCheckCfgChanged(ps
);
7226 /* /// "psdGetUsbDevCfg()" */
7227 AROS_LH3(struct PsdIFFContext
*, psdGetUsbDevCfg
,
7228 AROS_LHA(STRPTR
, owner
, A0
),
7229 AROS_LHA(STRPTR
, devid
, A2
),
7230 AROS_LHA(STRPTR
, ifid
, A3
),
7231 LIBBASETYPEPTR
, ps
, 65, psd
)
7234 struct PsdIFFContext
*pic
;
7235 struct PsdIFFContext
*cpic
= NULL
;
7236 struct PsdIFFContext
*mpic
= NULL
;
7238 KPRINTF(10, ("psdGetUsbDevCfg(%s, %s, %s)\n", owner
, devid
, ifid
));
7239 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7240 /* Find device config form. It contains all device config data */
7241 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7244 /* Find DEVID-Chunk. Check if it matches our device id */
7245 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7248 /* We found the correct device. Now if we need to store interface data, find the interface first */
7251 /* Search interface config form */
7252 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7255 /* Found the form. Find the the ID String for the interface */
7256 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7258 /* ID did match, now check for owner */
7259 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7261 /* found it! So there is already a config saved in there. Search for dev config data form */
7262 cpic
= psdFindCfgForm(mpic
, IFFFORM_IFCLSDATA
);
7266 mpic
= psdNextCfgForm(mpic
);
7269 /* Search for device config */
7270 mpic
= psdFindCfgForm(pic
, IFFFORM_DEVCFGDATA
);
7273 /* search for the right owner */
7274 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7276 /* found it! So there is already a config saved in there. Search for dev config data form */
7277 cpic
= psdFindCfgForm(mpic
, IFFFORM_DEVCLSDATA
);
7280 mpic
= psdNextCfgForm(mpic
);
7285 pic
= psdNextCfgForm(pic
);
7287 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7288 KPRINTF(1, ("Result %p\n", cpic
));
7294 /* /// "psdSetForcedBinding()" */
7295 AROS_LH3(BOOL
, psdSetForcedBinding
,
7296 AROS_LHA(STRPTR
, owner
, A2
),
7297 AROS_LHA(STRPTR
, devid
, A0
),
7298 AROS_LHA(STRPTR
, ifid
, A1
),
7299 LIBBASETYPEPTR
, ps
, 69, psd
)
7302 struct PsdIFFContext
*pic
;
7303 struct PsdIFFContext
*mpic
= NULL
;
7305 BOOL result
= FALSE
;
7309 olen
= strlen(owner
);
7311 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7312 /* Find device config form. It contains all device config data */
7313 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7316 /* Find DEVID-Chunk. Check if it matches our device id */
7317 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, insert/replace forced binding */
7332 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7337 pRemCfgChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
);
7341 mpic
= psdNextCfgForm(mpic
);
7347 if((!result
) && olen
)
7349 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7351 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7353 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7355 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7364 /* Add FBND chunk */
7367 if(pAddStringChunk(ps
, pic
, IFFCHNK_FORCEDBIND
, owner
))
7372 pRemCfgChunk(ps
, pic
, IFFCHNK_FORCEDBIND
);
7378 pic
= psdNextCfgForm(pic
);
7386 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7387 pCheckCfgChanged(ps
);
7390 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7391 if(pic
->pic_Node
.ln_Succ
)
7393 pic
= pAllocForm(ps
, pic
, IFFFORM_DEVICECFG
);
7396 if(pAddStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7400 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7402 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7404 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7406 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7414 /* Add FBND chunk */
7415 if(pAddStringChunk(ps
, pic
, IFFCHNK_FORCEDBIND
, owner
))
7423 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7424 pCheckCfgChanged(ps
);
7430 /* /// "psdGetForcedBinding()" */
7431 AROS_LH2(STRPTR
, psdGetForcedBinding
,
7432 AROS_LHA(STRPTR
, devid
, A0
),
7433 AROS_LHA(STRPTR
, ifid
, A1
),
7434 LIBBASETYPEPTR
, ps
, 70, psd
)
7437 struct PsdIFFContext
*pic
;
7438 struct PsdIFFContext
*mpic
= NULL
;
7440 STRPTR owner
= NULL
;
7442 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7443 /* Find device config form. It contains all device config data */
7444 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7447 /* Find DEVID-Chunk. Check if it matches our device id */
7448 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7450 /* We found the correct device. Now if we need to store interface data, find the interface first */
7453 /* Search interface config form */
7454 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7457 /* Found the form. Find the the ID String for the interface */
7458 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7460 /* ID did match, now check for forced binding */
7461 chunk
= pFindCfgChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
);
7464 owner
= (STRPTR
) &chunk
[2];
7468 mpic
= psdNextCfgForm(mpic
);
7471 /* Search for device forced binding */
7472 chunk
= pFindCfgChunk(ps
, pic
, IFFCHNK_FORCEDBIND
);
7475 owner
= (STRPTR
) &chunk
[2];
7481 pic
= psdNextCfgForm(pic
);
7483 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7489 /* /// "psdAddStringChunk()" */
7490 AROS_LH3(BOOL
, psdAddStringChunk
,
7491 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7492 AROS_LHA(ULONG
, chunkid
, D0
),
7493 AROS_LHA(CONST_STRPTR
, str
, A1
),
7494 LIBBASETYPEPTR
, ps
, 87, psd
)
7498 KPRINTF(10, ("psdAddStringChunk(%p, %p, %s)\n", pic
, chunkid
, str
));
7499 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7500 res
= pAddStringChunk(ps
, pic
, chunkid
, str
);
7501 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7507 /* /// "psdMatchStringChunk()" */
7508 AROS_LH3(BOOL
, psdMatchStringChunk
,
7509 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7510 AROS_LHA(ULONG
, chunkid
, D0
),
7511 AROS_LHA(CONST_STRPTR
, str
, A1
),
7512 LIBBASETYPEPTR
, ps
, 88, psd
)
7516 KPRINTF(10, ("psdMatchStringChunk(%p, %p, %s)\n", pic
, chunkid
, str
));
7517 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7518 res
= pMatchStringChunk(ps
, pic
, chunkid
, str
);
7519 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7525 /* /// "psdGetStringChunk()" */
7526 AROS_LH2(STRPTR
, psdGetStringChunk
,
7527 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7528 AROS_LHA(ULONG
, chunkid
, D0
),
7529 LIBBASETYPEPTR
, ps
, 89, psd
)
7533 KPRINTF(10, ("psdGetStringChunk(%p, %p)\n", pic
, chunkid
));
7534 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7535 str
= pGetStringChunk(ps
, pic
, chunkid
);
7536 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7542 /* *** Configuration (non-library subroutines) *** */
7544 /* /// "pAllocForm()" */
7545 struct PsdIFFContext
* pAllocForm(LIBBASETYPEPTR ps
, struct PsdIFFContext
*parent
, ULONG formid
)
7547 struct PsdIFFContext
*pic
;
7548 KPRINTF(10, ("pAllocForm(%p, %p)\n", parent
, formid
));
7549 if((pic
= psdAllocVec(sizeof(struct PsdIFFContext
))))
7551 NewList(&pic
->pic_SubForms
);
7552 //pic->pic_Parent = parent;
7553 pic
->pic_FormID
= formid
;
7554 pic
->pic_FormLength
= 4;
7555 pic
->pic_Chunks
= NULL
;
7556 pic
->pic_ChunksLen
= 0;
7557 pic
->pic_BufferLen
= 0;
7561 AddTail(&parent
->pic_SubForms
, &pic
->pic_Node
);
7563 AddTail(&ps
->ps_ConfigRoot
, &pic
->pic_Node
);
7571 /* /// "pFreeForm()" */
7572 void pFreeForm(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
)
7574 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7575 KPRINTF(10, ("pFreeForm(%p)\n", pic
));
7576 Remove(&pic
->pic_Node
);
7577 while(subpic
->pic_Node
.ln_Succ
)
7579 pFreeForm(ps
, subpic
);
7580 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7582 psdFreeVec(pic
->pic_Chunks
);
7587 /* /// "pGetFormLength()" */
7588 ULONG
pGetFormLength(struct PsdIFFContext
*pic
)
7590 ULONG len
= (5 + pic
->pic_ChunksLen
) & ~1UL;
7591 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7592 //KPRINTF(10, ("pGetFormLength(%p)\n", pic));
7593 while(subpic
->pic_Node
.ln_Succ
)
7595 len
+= pGetFormLength(subpic
);
7596 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7598 pic
->pic_FormLength
= len
;
7599 //KPRINTF(10, ("FormLen=%ld\n", len+8));
7604 /* /// "pFindCfgChunk()" */
7605 APTR
pFindCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chnkid
)
7607 ULONG
*buf
= pic
->pic_Chunks
;
7608 ULONG len
= pic
->pic_ChunksLen
;
7610 KPRINTF(10, ("pFindCfgChunk(%p, %p)\n", pic
, chnkid
));
7614 if(AROS_LONG2BE(*buf
) == chnkid
)
7616 KPRINTF(10, ("Found at %p\n", buf
));
7619 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7621 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7623 KPRINTF(10, ("Not found!\n"));
7628 /* /// "pRemCfgChunk()" */
7629 BOOL
pRemCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chnkid
)
7631 ULONG
*buf
= pic
->pic_Chunks
;
7632 ULONG len
= pic
->pic_ChunksLen
;
7634 KPRINTF(10, ("pRemCfgChunk(%p, %p)\n", pic
, chnkid
));
7638 chlen
= ((AROS_LONG2BE(buf
[1])) + 9) & ~1UL;
7639 if(AROS_LONG2BE(*buf
) == chnkid
)
7644 memcpy(buf
, &((UBYTE
*) buf
)[chlen
], (size_t) len
);
7646 pic
->pic_ChunksLen
-= chlen
;
7647 KPRINTF(10, ("Deleted %ld bytes to %ld chunk len\n", chlen
, pic
->pic_ChunksLen
));
7651 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7653 KPRINTF(10, ("Not found!\n"));
7658 /* /// "pAddCfgChunk()" */
7659 struct PsdIFFContext
* pAddCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, APTR chunk
)
7665 struct PsdIFFContext
*subpic
;
7666 KPRINTF(10, ("pAddCfgChunk(%p, %p)\n", pic
, chunk
));
7667 if(AROS_LONG2BE(*buf
) == ID_FORM
)
7670 len
= ((AROS_LONG2BE(*buf
)) - 3) & ~1UL;
7672 if((subpic
= pAllocForm(ps
, pic
, AROS_LONG2BE(*buf
))))
7677 if(!(pAddCfgChunk(ps
, subpic
, buf
)))
7681 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7683 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7687 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to add a nasty corrupted FORM chunk! Configuration is probably b0rken!");
7695 pRemCfgChunk(ps
, pic
, AROS_LONG2BE(*buf
));
7696 len
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7697 if(pic
->pic_ChunksLen
+len
> pic
->pic_BufferLen
)
7699 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
));
7702 if((newbuf
= psdAllocVec((pic
->pic_ChunksLen
+len
)<<1)))
7704 if(pic
->pic_ChunksLen
)
7706 memcpy(newbuf
, pic
->pic_Chunks
, (size_t) pic
->pic_ChunksLen
);
7707 psdFreeVec(pic
->pic_Chunks
);
7709 pic
->pic_Chunks
= newbuf
;
7710 pic
->pic_BufferLen
= (pic
->pic_ChunksLen
+len
)<<1;
7715 memcpy(&(((UBYTE
*) pic
->pic_Chunks
)[pic
->pic_ChunksLen
]), chunk
, (size_t) len
);
7716 pic
->pic_ChunksLen
+= len
;
7722 /* /// "pInternalWriteForm()" */
7723 ULONG
* pInternalWriteForm(struct PsdIFFContext
*pic
, ULONG
*buf
)
7725 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7726 //KPRINTF(10, ("pInternalWriteForm(%p, %p)", pic, buf));
7727 *buf
++ = AROS_LONG2BE(ID_FORM
);
7728 *buf
++ = AROS_LONG2BE(pic
->pic_FormLength
);
7729 *buf
++ = AROS_LONG2BE(pic
->pic_FormID
);
7730 if(pic
->pic_ChunksLen
)
7732 memcpy(buf
, pic
->pic_Chunks
, (size_t) pic
->pic_ChunksLen
);
7733 buf
= (ULONG
*) (((UBYTE
*) buf
) + pic
->pic_ChunksLen
);
7735 while(subpic
->pic_Node
.ln_Succ
)
7737 buf
= pInternalWriteForm(subpic
, buf
);
7738 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7744 /* /// "pCalcCfgCRC()" */
7745 ULONG
pCalcCfgCRC(struct PsdIFFContext
*pic
)
7747 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7749 ULONG crc
= pic
->pic_FormID
;
7752 //KPRINTF(10, ("pInternalWriteForm(%p, %p)", pic, buf));
7753 if(pic
->pic_ChunksLen
)
7755 len
= pic
->pic_ChunksLen
>>1;
7758 ptr
= (UWORD
*) pic
->pic_Chunks
;
7761 crc
= ((crc
<<1)|(crc
>>31))^(*ptr
++);
7765 while(subpic
->pic_Node
.ln_Succ
)
7767 crc
^= pCalcCfgCRC(subpic
);
7768 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7774 /* /// "pCheckCfgChanged()" */
7775 BOOL
pCheckCfgChanged(LIBBASETYPEPTR ps
)
7778 struct PsdIFFContext
*pic
;
7779 struct PsdIFFContext
*subpic
;
7782 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7783 ps
->ps_CheckConfigReq
= FALSE
;
7784 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7785 if(!(pic
->pic_Node
.ln_Succ
))
7787 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7790 crc
= pCalcCfgCRC(pic
);
7791 if(crc
!= ps
->ps_ConfigHash
)
7794 ps
->ps_ConfigHash
= crc
;
7795 /* Get Global config */
7796 if((subpic
= psdFindCfgForm(pic
, IFFFORM_STACKCFG
)))
7798 if((chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_GLOBALCFG
)))
7800 CopyMem(&chnk
[2], ((UBYTE
*) ps
->ps_GlobalCfg
) + 8, min(AROS_LONG2BE(chnk
[1]), AROS_LONG2BE(ps
->ps_GlobalCfg
->pgc_Length
)));
7802 if(!pMatchStringChunk(ps
, subpic
, IFFCHNK_INSERTSND
, ps
->ps_PoPo
.po_InsertSndFile
))
7804 if((tmpstr
= pGetStringChunk(ps
, subpic
, IFFCHNK_INSERTSND
)))
7806 psdFreeVec(ps
->ps_PoPo
.po_InsertSndFile
);
7807 ps
->ps_PoPo
.po_InsertSndFile
= tmpstr
;
7810 if(!pMatchStringChunk(ps
, subpic
, IFFCHNK_REMOVESND
, ps
->ps_PoPo
.po_RemoveSndFile
))
7812 if((tmpstr
= pGetStringChunk(ps
, subpic
, IFFCHNK_REMOVESND
)))
7814 psdFreeVec(ps
->ps_PoPo
.po_RemoveSndFile
);
7815 ps
->ps_PoPo
.po_RemoveSndFile
= tmpstr
;
7819 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7820 psdSendEvent(EHMB_CONFIGCHG
, NULL
, NULL
);
7823 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7828 /* /// "pAddStringChunk()" */
7829 BOOL
pAddStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
, CONST_STRPTR str
)
7832 ULONG len
= strlen(str
);
7833 ULONG
*chnk
= (ULONG
*) psdAllocVec((ULONG
) len
+8+2);
7836 chnk
[0] = AROS_LONG2BE(chunkid
);
7837 chnk
[1] = AROS_LONG2BE(len
+1);
7838 strcpy((STRPTR
) &chnk
[2], str
);
7839 if(pAddCfgChunk(ps
, pic
, chnk
))
7849 /* /// "pMatchStringChunk()" */
7850 BOOL
pMatchStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
, CONST_STRPTR str
)
7855 if((chunk
= pFindCfgChunk(ps
, pic
, chunkid
)))
7857 srcptr
= (STRPTR
) &chunk
[2];
7858 len
= AROS_LONG2BE(chunk
[1]);
7859 while(len
-- && *srcptr
)
7861 if(*str
++ != *srcptr
++)
7875 /* /// "pGetStringChunk()" */
7876 STRPTR
pGetStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
)
7880 if((chunk
= pFindCfgChunk(ps
, pic
, chunkid
)))
7882 if((str
= (STRPTR
) psdAllocVec(AROS_LONG2BE(chunk
[1]) + 1)))
7884 memcpy(str
, &chunk
[2], (size_t) AROS_LONG2BE(chunk
[1]));
7892 /* /// "pUpdateGlobalCfg()" */
7893 void pUpdateGlobalCfg(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
)
7895 struct PsdIFFContext
*tmppic
;
7896 /* Set Global config */
7897 if(pic
== (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
)
7899 if((tmppic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
)))
7901 pAddCfgChunk(ps
, tmppic
, ps
->ps_GlobalCfg
);
7902 pAddStringChunk(ps
, tmppic
, IFFCHNK_INSERTSND
, ps
->ps_PoPo
.po_InsertSndFile
);
7903 pAddStringChunk(ps
, tmppic
, IFFCHNK_REMOVESND
, ps
->ps_PoPo
.po_RemoveSndFile
);
7909 /* *** Misc (non library functions) ***/
7911 /* /// "pGetDevConfig()" */
7912 BOOL
pGetDevConfig(struct PsdPipe
*pp
)
7914 struct PsdDevice
*pd
= pp
->pp_Device
;
7915 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
7917 struct UsbStdCfgDesc uscd
;
7923 KPRINTF(1, ("Getting configuration descriptor...\n"));
7924 psdLockWriteDevice(pd
);
7925 while(curcfg
< pd
->pd_NumCfgs
)
7927 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
7928 USR_GET_DESCRIPTOR
, (UDT_CONFIGURATION
<<8)|curcfg
, 0);
7930 /*tempbuf = psdAllocVec(256);
7931 ioerr = psdDoPipe(pp, tempbuf, 34);
7932 if(ioerr == UHIOERR_RUNTPACKET)
7936 memcpy(&uscd, tempbuf, 9);*/
7937 ioerr
= psdDoPipe(pp
, &uscd
, 9);//sizeof(struct UsbStdCfgDesc));
7940 KPRINTF(1, ("Config type: %ld\n", (ULONG
) uscd
.bDescriptorType
));
7941 len
= (ULONG
) AROS_WORD2LE(uscd
.wTotalLength
);
7942 KPRINTF(1, ("Configsize %ld, total size %ld\n", (ULONG
) uscd
.bLength
, len
));
7943 if((tempbuf
= psdAllocVec(len
)))
7946 KPRINTF(1, ("Getting whole configuration descriptor...\n"));
7947 ioerr
= psdDoPipe(pp
, tempbuf
, len
);
7950 struct PsdConfig
*pc
= NULL
;
7951 struct PsdInterface
*pif
= NULL
;
7952 struct PsdInterface
*altif
= NULL
;
7953 struct PsdEndpoint
*pep
= NULL
;
7954 struct PsdDescriptor
*pdd
= NULL
;
7955 UBYTE
*dbuf
= tempbuf
;
7958 bufend
= &dbuf
[len
];
7959 while(dbuf
< bufend
)
7961 dlen
= dbuf
[0]; /* bLength */
7966 if(&dbuf
[dlen
] > bufend
)
7968 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "End of descriptor past buffer!");
7970 switch(dbuf
[1]) /* bDescriptorType */
7972 case UDT_CONFIGURATION
:
7974 struct UsbStdCfgDesc
*usc
= (struct UsbStdCfgDesc
*) dbuf
;
7978 if((pc
= pAllocConfig(pd
)))
7980 pd
->pd_Flags
|= PDFF_CONFIGURED
;
7981 pc
->pc_NumIfs
= usc
->bNumInterfaces
;
7982 pc
->pc_CfgNum
= usc
->bConfigurationValue
;
7983 pc
->pc_Attr
= usc
->bmAttributes
;
7984 pc
->pc_MaxPower
= usc
->bMaxPower
<<1;
7986 KPRINTF(1, (" Config %ld\n", pc
->pc_CfgNum
));
7987 if(usc
->iConfiguration
)
7989 pc
->pc_CfgStr
= psdGetStringDescriptor(pp
, usc
->iConfiguration
);
7993 pc
->pc_CfgStr
= psdCopyStrFmt("Configuration %ld", pc
->pc_CfgNum
);
7996 KPRINTF(20, (" Config allocation failed\n"));
8003 struct UsbStdIfDesc
*usif
= (struct UsbStdIfDesc
*) dbuf
;
8007 if((altif
= pAllocInterface(pc
)))
8009 altif
->pif_IfNum
= usif
->bInterfaceNumber
;
8010 altif
->pif_Alternate
= usif
->bAlternateSetting
;
8011 altif
->pif_NumEPs
= usif
->bNumEndpoints
;
8012 altif
->pif_IfClass
= usif
->bInterfaceClass
;
8013 altif
->pif_IfSubClass
= usif
->bInterfaceSubClass
;
8014 altif
->pif_IfProto
= usif
->bInterfaceProtocol
;
8015 KPRINTF(2, (" Interface %ld\n", altif
->pif_IfNum
));
8016 if(usif
->iInterface
)
8018 altif
->pif_IfStr
= psdGetStringDescriptor(pp
, usif
->iInterface
);
8020 if(!altif
->pif_IfStr
)
8022 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) altif
->pif_IfClass
, NULL
);
8025 altif
->pif_IfStr
= psdCopyStrFmt("%s interface (%ld)", classname
, altif
->pif_IfNum
);
8027 altif
->pif_IfStr
= psdCopyStrFmt("Interface %ld", altif
->pif_IfNum
);
8030 KPRINTF(2, (" IfName : %s\n"
8031 " Alternate : %ld\n"
8034 " IfSubClass: %ld\n"
8036 altif
->pif_IfStr
, altif
->pif_Alternate
,
8039 altif
->pif_IfSubClass
, altif
->pif_IfProto
));
8040 if(pc
->pc_CfgNum
== 1)
8042 altif
->pif_IDString
= psdCopyStrFmt("%02lx-%02lx-%02lx-%02lx-%02lx",
8043 altif
->pif_IfNum
, altif
->pif_Alternate
,
8044 altif
->pif_IfClass
, altif
->pif_IfSubClass
,
8045 altif
->pif_IfProto
);
8047 // for more than one config, add config number (retain backwards compatibility with most devices)
8048 altif
->pif_IDString
= psdCopyStrFmt("%02lx-%02lx-%02lx-%02lx-%02lx-%02lx",
8050 altif
->pif_IfNum
, altif
->pif_Alternate
,
8051 altif
->pif_IfClass
, altif
->pif_IfSubClass
,
8052 altif
->pif_IfProto
);
8055 /* Move the interface to the alternatives if possible */
8056 if(altif
->pif_Alternate
)
8060 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Alternate interface without prior main interface!");
8061 KPRINTF(20, (" Alternate interface without prior main interface\n"));
8064 Remove(&altif
->pif_Node
);
8065 AddTail(&pif
->pif_AlterIfs
, &altif
->pif_Node
);
8066 altif
->pif_ParentIf
= pif
;
8069 altif
->pif_ParentIf
= NULL
;
8073 KPRINTF(20, (" Interface allocation failed\n"));
8076 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Interface without prior config descriptor!");
8077 KPRINTF(20, (" Interface descriptor without Config\n"));
8084 struct UsbStdEPDesc
*usep
= (struct UsbStdEPDesc
*) dbuf
;
8087 if((pep
= pAllocEndpoint(altif
)))
8090 pep
->pep_EPNum
= usep
->bEndpointAddress
& 0x0f;
8091 pep
->pep_Direction
= usep
->bEndpointAddress
>>7;
8092 pep
->pep_TransType
= usep
->bmAttributes
& 0x03;
8093 pep
->pep_SyncType
= (usep
->bmAttributes
>>2) & 0x03;
8094 pep
->pep_UsageType
= (usep
->bmAttributes
>>4) & 0x03;
8095 eptype
= (pep
->pep_TransType
== USEAF_INTERRUPT
) ? "int" : "iso";
8097 pep
->pep_MaxPktSize
= AROS_WORD2LE(usep
->wMaxPacketSize
) & 0x07ff;
8098 pep
->pep_NumTransMuFr
= ((AROS_WORD2LE(usep
->wMaxPacketSize
)>>11) & 3) + 1;
8099 if(pep
->pep_NumTransMuFr
== 4)
8101 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint contains illegal Num Trans µFrame value!");
8102 pep
->pep_NumTransMuFr
= 1;
8105 pep
->pep_Interval
= usep
->bInterval
;
8106 if(pd
->pd_Flags
& PDFF_HIGHSPEED
)
8108 switch(pep
->pep_TransType
)
8112 //pep->pep_Interval = 0; // no use here, NAK rate not of interest
8115 case USEAF_ISOCHRONOUS
:
8116 if(pep
->pep_MaxPktSize
> 1024)
8118 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8119 "Endpoint contains %s (%ld) MaxPktSize value!",
8120 (STRPTR
) "too high", pep
->pep_MaxPktSize
);
8121 pep
->pep_MaxPktSize
= 1024;
8124 case USEAF_INTERRUPT
:
8125 if(!pep
->pep_Interval
)
8127 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8128 "%sspeed %s endpoint contains %s interval value! Fixing.",
8129 (STRPTR
) "High", eptype
, (STRPTR
) "zero");
8130 pep
->pep_Interval
= 1;
8132 else if(pep
->pep_Interval
> 16)
8134 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8135 "%sspeed %s endpoint contains %s interval value! Fixing.",
8136 (STRPTR
) "High", eptype
, (STRPTR
) "too high");
8137 pep
->pep_Interval
= 16;
8139 pep
->pep_Interval
= 1<<(pep
->pep_Interval
-1);
8143 else if(pd
->pd_Flags
& PDFF_LOWSPEED
)
8145 switch(pep
->pep_TransType
)
8147 case USEAF_INTERRUPT
:
8148 if(pep
->pep_Interval
< 8)
8150 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8151 (STRPTR
) "Low", eptype
, (STRPTR
) "too low");
8152 pep
->pep_Interval
= 8;
8158 pep
->pep_Interval
= 0; // no use here
8161 case USEAF_ISOCHRONOUS
:
8162 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Lowspeed devices cannot have isochronous endpoints!");
8166 switch(pep
->pep_TransType
)
8168 case USEAF_INTERRUPT
:
8169 if(!pep
->pep_Interval
)
8171 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8172 (STRPTR
) "Full", eptype
, (STRPTR
) "zero");
8173 pep
->pep_Interval
= 1;
8179 pep
->pep_Interval
= 0; // no use here
8182 case USEAF_ISOCHRONOUS
:
8183 if(pep
->pep_MaxPktSize
> 1023)
8185 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint contains too high (%ld) MaxPktSize value! Fixing.", pep
->pep_MaxPktSize
);
8186 pep
->pep_MaxPktSize
= 1023;
8188 if(!pep
->pep_Interval
)
8190 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8191 (STRPTR
) "Full", eptype
, (STRPTR
) "zero");
8192 pep
->pep_Interval
= 1;
8194 else if(pep
->pep_Interval
> 16)
8196 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8197 (STRPTR
) "Full", eptype
, (STRPTR
) "too high");
8198 pep
->pep_Interval
= 16;
8200 pep
->pep_Interval
= 1<<(pep
->pep_Interval
-1);
8205 KPRINTF(2, (" Endpoint %ld\n", pep
->pep_EPNum
));
8206 KPRINTF(2, (" Direction : %s\n"
8207 " TransType : %ld\n"
8208 " MaxPktSize: %ld\n"
8209 " Interval : %ld\n",
8210 (pep
->pep_Direction
? "IN" : "OUT"),
8211 pep
->pep_TransType
, pep
->pep_MaxPktSize
,
8212 pep
->pep_Interval
));
8215 KPRINTF(20, (" Endpoint allocation failed\n"));
8218 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint without prior interface descriptor!");
8219 KPRINTF(20, (" Endpoint descriptor without Interface\n"));
8229 case UDT_CS_INTERFACE
:
8230 case UDT_CS_ENDPOINT
:
8231 case UDT_DEVICE_QUALIFIER
:
8232 case UDT_OTHERSPEED_QUALIFIER
:
8233 case UDT_INTERFACE_POWER
:
8235 //psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Skipping descriptor %02lx (pc=%p, pif=%p altpif=%p).", dbuf[1], pc, pif, altif);
8236 KPRINTF(1, ("Skipping unknown descriptor %ld.\n", dbuf
[1]));
8240 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Skipping unknown descriptor %02lx.", dbuf
[1]);
8241 KPRINTF(1, ("Skipping unknown descriptor %ld.\n", dbuf
[1]));
8244 // add descriptor to device
8245 pdd
= pAllocDescriptor(pd
, dbuf
);
8248 STRPTR descname
= NULL
;
8250 pdd
->pdd_Config
= pc
;
8251 pdd
->pdd_Interface
= altif
;
8252 pdd
->pdd_Endpoint
= pep
;
8253 if(pdd
->pdd_Interface
)
8255 if((pdd
->pdd_Type
>= UDT_CS_UNDEFINED
) && (pdd
->pdd_Type
<= UDT_CS_ENDPOINT
))
8257 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pdd
->pdd_CSSubType
<<24)|(pif
->pif_IfSubClass
<<16)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8260 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pdd
->pdd_CSSubType
<<24)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8265 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pif
->pif_IfSubClass
<<16)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8269 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8274 pdd
->pdd_Name
= descname
;
8279 KPRINTF(1, ("Configuration acquired!\n"));
8280 psdFreeVec(tempbuf
);
8283 //psdUnlockDevice(pd);
8286 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8287 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
8288 len
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8289 KPRINTF(15, ("GET_DESCRIPTOR failed %ld!\n", ioerr
));
8291 psdFreeVec(tempbuf
);
8293 KPRINTF(20, ("No memory for %ld bytes config temp buffer!\n", len
));
8296 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8297 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
8298 9, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8299 KPRINTF(15, ("GET_DESCRIPTOR (9) failed %ld!\n", ioerr
));
8301 psdUnlockDevice(pd
);
8304 psdUnlockDevice(pd
);
8309 /* /// "pPowerRecurseDrain()" */
8310 ULONG
pPowerRecurseDrain(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
8312 struct PsdDevice
*nextpd
;
8313 struct PsdConfig
*pc
;
8314 UWORD maxdrain
= 666;
8316 BOOL selfpwd
= TRUE
;
8317 pd
->pd_PowerDrain
= 0;
8319 /* look at config */
8320 if((pc
= pd
->pd_CurrentConfig
))
8323 /* if suspended, no more than 500µA are drained */
8324 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
8326 pd
->pd_PowerDrain
= (pc
->pc_MaxPower
>= 100) ? 3 : 1;
8327 return(pd
->pd_PowerDrain
);
8329 selfpwd
= ((pc
->pc_Attr
& USCAF_SELF_POWERED
) && (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
!= POCP_BUS_POWERED
)) ||
8330 (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
== POCP_SELF_POWERED
);
8331 maxdrain
= selfpwd
? 500 : 100;
8334 /* examine children */
8335 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8336 while(nextpd
->pd_Node
.ln_Succ
)
8338 if(nextpd
->pd_Hub
== pd
)
8340 childdrain
= pPowerRecurseDrain(ps
, nextpd
);
8341 // limit the drain to the maximum power suckage
8342 pd
->pd_PowerDrain
+= (childdrain
> maxdrain
) ? maxdrain
: childdrain
;
8344 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8347 /* look at config */
8350 pd
->pd_PowerDrain
= 0;
8352 pd
->pd_PowerDrain
+= pc
->pc_MaxPower
;
8354 return(pd
->pd_PowerDrain
);
8358 /* /// "pPowerRecurseSupply()" */
8359 void pPowerRecurseSupply(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
8361 struct PsdDevice
*nextpd
;
8362 struct PsdConfig
*pc
;
8365 BOOL selfpwd
= TRUE
;
8367 /* look at config */
8368 if((pc
= pd
->pd_CurrentConfig
))
8370 selfpwd
= ((pc
->pc_Attr
& USCAF_SELF_POWERED
) && (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
!= POCP_BUS_POWERED
)) ||
8371 (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
== POCP_SELF_POWERED
);
8374 /* count children */
8375 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8376 while(nextpd
->pd_Node
.ln_Succ
)
8378 if(nextpd
->pd_Hub
== pd
) // this device is a child of us (we're a hub!)
8382 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8385 /* look at config */
8390 pd
->pd_PowerSupply
= ports
? 500*ports
+ pc
->pc_MaxPower
: pc
->pc_MaxPower
;
8392 supply
= 500; // each downstream port gets the full monty
8394 // the parent hub has already set the amount of supply for this port
8395 if(pd
->pd_PowerSupply
>= pc
->pc_MaxPower
)
8397 // the downstream ports get the remaining divided attention
8400 // avoid division by zero
8401 supply
= (pd
->pd_PowerSupply
- pc
->pc_MaxPower
) / ports
;
8404 // limit to 100 mA per port
8409 supply
= 1; // bad luck, out of power
8414 if(ports
) /* needs to be a hub */
8416 // propagate supply down to the children
8417 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8418 while(nextpd
->pd_Node
.ln_Succ
)
8420 if(nextpd
->pd_Hub
== pd
)
8422 nextpd
->pd_PowerSupply
= supply
;
8423 pPowerRecurseSupply(ps
, nextpd
);
8425 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8428 if(pd
->pd_PowerDrain
> pd
->pd_PowerSupply
)
8430 if(!(pd
->pd_Flags
& PDFF_LOWPOWER
))
8432 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8433 "Detected low power condition for '%s'.", pd
->pd_ProductStr
);
8434 pd
->pd_Flags
|= PDFF_LOWPOWER
;
8435 psdSendEvent(EHMB_DEVICELOWPW
, pd
, NULL
);
8438 if(pd
->pd_Flags
& PDFF_LOWPOWER
)
8440 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
8441 "Low power condition resolved for '%s'.", pd
->pd_ProductStr
);
8442 pd
->pd_Flags
&= ~PDFF_LOWPOWER
;
8448 /* /// "pGarbageCollectEvents()" */
8449 void pGarbageCollectEvents(LIBBASETYPEPTR ps
)
8451 struct PsdEventNote
*pen
;
8452 while((pen
= (struct PsdEventNote
*) GetMsg(&ps
->ps_EventReplyPort
)))
8459 /* /// "pFindName()" */
8460 struct Node
* pFindName(LIBBASETYPEPTR ps
, struct List
*list
, STRPTR name
)
8462 struct Node
*res
= NULL
;
8467 res
= FindName(list
, name
);
8474 if((*name
== '/') || (*name
== ':'))
8486 /* /// "pStripString()" */
8487 void pStripString(LIBBASETYPEPTR ps
, STRPTR str
)
8489 STRPTR srcptr
= str
;
8490 STRPTR tarptr
= str
;
8491 STRPTR lastgoodchar
= str
;
8492 BOOL leadingspaces
= TRUE
;
8496 while((ch
= *srcptr
++))
8507 lastgoodchar
= tarptr
;
8508 leadingspaces
= FALSE
;
8513 if((str
== lastgoodchar
) && (len
> 6))
8515 strcpy(str
, "<empty>");
8520 /* /// "pFixBrokenConfig()" */
8521 BOOL
pFixBrokenConfig(struct PsdPipe
*pp
)
8523 struct PsdDevice
*pd
= pp
->pp_Device
;
8524 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
8525 struct PsdConfig
*pc
;
8526 struct PsdInterface
*pif
;
8529 switch(pd
->pd_VendorID
)
8531 case 0x03eb: /* Atmel */
8532 if(pd
->pd_ProductID
== 0x3312)
8534 psdFreeVec(pd
->pd_ProductStr
);
8535 pd
->pd_ProductStr
= psdCopyStr("Highway/Subway Root Hub");
8539 case 0x04e6: /* E-Shuttle */
8540 if(pd
->pd_ProductID
== 0x0001) /* LS120 */
8542 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8543 /* Get msd interface and fix it */
8544 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8545 if(pif
->pif_IfClass
!= MASSSTORE_CLASSCODE
)
8548 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "E-Shuttle LS120");
8549 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8550 pif
->pif_IfSubClass
= MS_ATAPI_SUBCLASS
;
8551 pif
->pif_IfProto
= MS_PROTO_CB
;
8556 case 0x054C: /* Sony */
8557 if((pd
->pd_ProductID
== 0x002E) || (pd
->pd_ProductID
== 0x0010)) /* Handycam */
8560 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Sony MSD");
8561 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8562 /* Get msd interface and fix it */
8563 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8564 pif
->pif_IfSubClass
= MS_RBC_SUBCLASS
;
8568 case 0x057b: /* Y-E Data */
8569 if(pd
->pd_ProductID
== 0x0000) /* Flashbuster U */
8571 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8572 /* Get msd interface and fix it */
8573 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8574 if(pif
->pif_IfClass
!= MASSSTORE_CLASSCODE
)
8577 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Y-E Data USB Floppy");
8578 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8579 pif
->pif_IfSubClass
= MS_UFI_SUBCLASS
;
8580 pif
->pif_IfProto
= (pd
->pd_DevVers
< 0x0300) ? MS_PROTO_CB
: MS_PROTO_CBI
;
8585 case 0x04ce: /* ScanLogic */
8586 if(pd
->pd_ProductID
== 0x0002)
8588 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "ScanLogic");
8589 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8590 /* Get msd interface and fix it */
8591 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8593 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8597 case 0x0584: /* Ratoc cardreader */
8598 if(pd
->pd_ProductID
== 0x0008)
8600 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "RATOC");
8601 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8602 /* Get msd interface and fix it */
8603 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8605 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8606 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8607 pif
->pif_IfProto
= MS_PROTO_BULK
;
8611 case 0x04b8: /* Epson */
8612 if(pd
->pd_ProductID
== 0x0602) /* EPX Storage device (Card slot in Printer) */
8614 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Epson storage");
8615 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8616 /* Get msd interface and fix it */
8617 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8619 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8620 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8621 pif
->pif_IfProto
= MS_PROTO_BULK
;
8632 /* /// "pOpenDOS()" */
8633 BOOL
pOpenDOS(LIBBASETYPEPTR ps
)
8639 if((DOSBase
= OpenLibrary("dos.library", 39)))
8647 /* *** Class Scan Task *** */
8649 /* /// "pStartEventHandler()" */
8650 BOOL
pStartEventHandler(LIBBASETYPEPTR ps
)
8652 struct PsdHandlerTask
*ph
= &ps
->ps_EventHandler
;
8654 ObtainSemaphore(&ps
->ps_PoPoLock
);
8657 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8660 ph
->ph_ReadySignal
= SIGB_SINGLE
;
8661 ph
->ph_ReadySigTask
= FindTask(NULL
);
8662 SetSignal(0, SIGF_SINGLE
); // clear single bit
8663 if(psdSpawnSubTask("Poseidon Event Broadcast", pEventHandlerTask
, ps
))
8665 Wait(1UL<<ph
->ph_ReadySignal
);
8667 ph
->ph_ReadySigTask
= NULL
;
8668 //FreeSignal(ph->ph_ReadySignal);
8671 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8672 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Event broadcaster started.");
8675 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8680 /* *** Hardware Driver Task *** */
8682 /* /// "pQuickForwardRequest()" */
8683 AROS_UFH1(void, pQuickForwardRequest
,
8684 AROS_UFHA(struct MsgPort
*, msgport
, A1
))
8687 struct PsdHardware
*phw
= (struct PsdHardware
*) msgport
->mp_Node
.ln_Name
;
8690 while((pp
= (struct PsdPipe
*) RemHead(&msgport
->mp_MsgList
)))
8692 if(pp
->pp_AbortPipe
)
8694 KPRINTF(2, ("Abort pipe %p\n", pp
->pp_AbortPipe
));
8695 AbortIO((struct IORequest
*) &pp
->pp_AbortPipe
->pp_IOReq
);
8696 ReplyMsg(&pp
->pp_Msg
);
8697 KPRINTF(2, ("Replying evil pipe %p\n", pp
));
8699 KPRINTF(1, ("Forwarding pipe %p\n", pp
));
8700 pp
->pp_IOReq
.iouh_UserData
= pp
;
8701 SendIO((struct IORequest
*) &pp
->pp_IOReq
);
8702 ++phw
->phw_MsgCount
;
8709 /* /// "pQuickReplyRequest()" */
8710 AROS_UFH1(void, pQuickReplyRequest
,
8711 AROS_UFHA(struct MsgPort
*, msgport
, A1
))
8714 struct PsdHardware
*phw
= (struct PsdHardware
*) msgport
->mp_Node
.ln_Name
;
8715 struct IOUsbHWReq
*ioreq
;
8717 while((ioreq
= (struct IOUsbHWReq
*) RemHead(&msgport
->mp_MsgList
)))
8719 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8720 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8721 --phw
->phw_MsgCount
;
8727 /* /// "pDeviceTask()" */
8728 AROS_UFH0(void, pDeviceTask
)
8732 struct PsdHardware
*phw
;
8733 struct Task
*thistask
;
8737 struct TagItem taglist
[11];
8738 struct TagItem
*tag
;
8740 struct IOUsbHWReq
*ioreq
;
8742 STRPTR prodname
= NULL
;
8743 STRPTR manufacturer
= NULL
;
8744 STRPTR description
= NULL
;
8745 STRPTR copyright
= NULL
;
8748 ULONG driververs
= 0x0100;
8749 ULONG caps
= UHCF_ISO
;
8753 if(!(ps
= (LIBBASETYPEPTR
) OpenLibrary("poseidon.library", 4)))
8758 thistask
= FindTask(NULL
);
8759 SetTaskPri(thistask
, 21);
8760 phw
= thistask
->tc_UserData
;
8762 #ifndef PA_CALLBACK // undocumented exec feature
8763 #define PA_CALLBACK 3
8766 phw
->phw_TaskMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
8767 phw
->phw_TaskMsgPort
.mp_Node
.ln_Name
= (APTR
) phw
;
8768 phw
->phw_TaskMsgPort
.mp_Flags
= PA_SIGNAL
;
8769 phw
->phw_TaskMsgPort
.mp_SigTask
= thistask
;
8770 phw
->phw_TaskMsgPort
.mp_SigBit
= AllocSignal(-1L);
8771 NewList(&phw
->phw_TaskMsgPort
.mp_MsgList
);
8773 phw
->phw_DevMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
8774 phw
->phw_DevMsgPort
.mp_Node
.ln_Name
= (APTR
) phw
;
8775 phw
->phw_DevMsgPort
.mp_Flags
= PA_SIGNAL
;
8776 phw
->phw_DevMsgPort
.mp_SigTask
= thistask
;
8777 phw
->phw_DevMsgPort
.mp_SigBit
= AllocSignal(-1L);
8778 NewList(&phw
->phw_DevMsgPort
.mp_MsgList
);
8780 if((phw
->phw_RootIOReq
= (struct IOUsbHWReq
*) CreateIORequest(&phw
->phw_DevMsgPort
, sizeof(struct IOUsbHWReq
))))
8782 devname
= phw
->phw_DevName
;
8786 if(!(ioerr
= OpenDevice(devname
, phw
->phw_Unit
, (struct IORequest
*) phw
->phw_RootIOReq
, 0)))
8792 if((*devname
== '/') || (*devname
== ':'))
8797 } while(*(++devname
));
8802 phw
->phw_Node
.ln_Name
= phw
->phw_RootIOReq
->iouh_Req
.io_Device
->dd_Library
.lib_Node
.ln_Name
;
8804 tag
->ti_Tag
= UHA_ProductName
;
8805 tag
->ti_Data
= (IPTR
) &prodname
;
8807 tag
->ti_Tag
= UHA_Manufacturer
;
8808 tag
->ti_Data
= (IPTR
) &manufacturer
;
8810 tag
->ti_Tag
= UHA_Description
;
8811 tag
->ti_Data
= (IPTR
) &description
;
8813 tag
->ti_Tag
= UHA_Version
;
8814 tag
->ti_Data
= (IPTR
) &version
;
8816 tag
->ti_Tag
= UHA_Revision
;
8817 tag
->ti_Data
= (IPTR
) &revision
;
8819 tag
->ti_Tag
= UHA_Copyright
;
8820 tag
->ti_Data
= (IPTR
) ©right
;
8822 tag
->ti_Tag
= UHA_DriverVersion
;
8823 tag
->ti_Data
= (IPTR
) &driververs
;
8825 tag
->ti_Tag
= UHA_Capabilities
;
8826 tag
->ti_Data
= (IPTR
) &caps
;
8828 tag
->ti_Tag
= TAG_END
;
8829 phw
->phw_RootIOReq
->iouh_Data
= taglist
;
8830 phw
->phw_RootIOReq
->iouh_Req
.io_Command
= UHCMD_QUERYDEVICE
;
8831 DoIO((struct IORequest
*) phw
->phw_RootIOReq
);
8833 phw
->phw_ProductName
= psdCopyStr(prodname
? prodname
: (STRPTR
) "n/a");
8834 phw
->phw_Manufacturer
= psdCopyStr(manufacturer
? manufacturer
: (STRPTR
) "n/a");
8835 phw
->phw_Description
= psdCopyStr(description
? description
: (STRPTR
) "n/a");
8836 phw
->phw_Copyright
= psdCopyStr(copyright
? copyright
: (STRPTR
) "n/a");
8837 phw
->phw_Version
= version
;
8838 phw
->phw_Revision
= revision
;
8839 phw
->phw_DriverVers
= driververs
;
8840 phw
->phw_Capabilities
= caps
;
8842 sigmask
= SIGBREAKF_CTRL_C
;
8843 if(caps
& UHCF_QUICKIO
)
8845 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Enabling QuickIO for %s.", prodname
);
8846 phw
->phw_TaskMsgPort
.mp_Flags
= PA_CALLBACK
;
8847 phw
->phw_TaskMsgPort
.mp_SigTask
= (APTR
) pQuickForwardRequest
;
8849 phw
->phw_DevMsgPort
.mp_Flags
= PA_CALLBACK
;
8850 phw
->phw_DevMsgPort
.mp_SigTask
= (APTR
) pQuickReplyRequest
;
8852 sigmask
|= (1UL<<phw
->phw_DevMsgPort
.mp_SigBit
)|(1UL<<phw
->phw_TaskMsgPort
.mp_SigBit
);
8855 KPRINTF(10, ("%s ready!\n", thistask
->tc_Node
.ln_Name
));
8856 phw
->phw_Task
= thistask
;
8858 psdLockWritePBase();
8859 AddTail(&ps
->ps_Hardware
, &phw
->phw_Node
);
8863 if(phw
->phw_ReadySigTask
)
8865 Signal(phw
->phw_ReadySigTask
, 1L<<phw
->phw_ReadySignal
);
8870 KPRINTF(1, ("Main loop wait.\n"));
8871 while((pp
= (struct PsdPipe
*) GetMsg(&phw
->phw_TaskMsgPort
)))
8873 if(pp
->pp_AbortPipe
)
8875 KPRINTF(2, ("Abort pipe %p\n", pp
->pp_AbortPipe
));
8876 AbortIO((struct IORequest
*) &pp
->pp_AbortPipe
->pp_IOReq
);
8877 ReplyMsg(&pp
->pp_Msg
);
8878 KPRINTF(2, ("Replying evil pipe %p\n", pp
));
8880 KPRINTF(1, ("Forwarding pipe %p\n", pp
));
8881 pp
->pp_IOReq
.iouh_UserData
= pp
;
8882 SendIO((struct IORequest
*) &pp
->pp_IOReq
);
8883 ++phw
->phw_MsgCount
;
8886 while((ioreq
= (struct IOUsbHWReq
*) GetMsg(&phw
->phw_DevMsgPort
)))
8888 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8889 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8890 --phw
->phw_MsgCount
;
8892 sigs
= Wait(sigmask
);
8893 } while(!(sigs
& SIGBREAKF_CTRL_C
));
8894 /* Flush all pending IO Requests */
8895 phw
->phw_RootIOReq
->iouh_Req
.io_Command
= CMD_FLUSH
;
8896 DoIO((struct IORequest
*) phw
->phw_RootIOReq
);
8898 while(phw
->phw_MsgCount
)
8900 KPRINTF(20, ("Still %ld iorequests pending!\n", phw
->phw_MsgCount
));
8904 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8905 "There are still %ld IORequests pending, before unit can go down. Driver buggy?",
8910 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8911 "Okay, I've waited long enough, sod these %ld IORequests.",
8913 phw
->phw_MsgCount
= 0;
8916 while((ioreq
= (struct IOUsbHWReq
*) GetMsg(&phw
->phw_DevMsgPort
)))
8918 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8919 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8920 --phw
->phw_MsgCount
;
8923 psdLockWritePBase();
8924 Remove(&phw
->phw_Node
);
8926 CloseDevice((struct IORequest
*) phw
->phw_RootIOReq
);
8928 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
8929 "Opening %s unit %ld failed %s (%ld).",
8930 phw
->phw_DevName
, phw
->phw_Unit
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8932 DeleteIORequest((struct IORequest
*) phw
->phw_RootIOReq
);
8933 phw
->phw_RootIOReq
= NULL
;
8935 FreeSignal((LONG
) phw
->phw_TaskMsgPort
.mp_SigBit
);
8936 FreeSignal((LONG
) phw
->phw_DevMsgPort
.mp_SigBit
);
8938 CloseLibrary((struct Library
*) ps
);
8939 phw
->phw_Task
= NULL
;
8942 if(phw
->phw_ReadySigTask
)
8944 Signal(phw
->phw_ReadySigTask
, 1L<<phw
->phw_ReadySignal
);
8950 /* /// "pEventHandlerTask()" */
8951 AROS_UFH0(void, pEventHandlerTask
)
8955 struct Task
*thistask
;
8956 struct timeval currtime
;
8959 struct PsdUsbClass
*puc
;
8960 struct PsdHandlerTask
*ph
;
8961 struct PsdEventNote
*pen
;
8965 thistask
= FindTask(NULL
);
8966 ps
= thistask
->tc_UserData
;
8967 ph
= &ps
->ps_EventHandler
;
8968 SetTaskPri(thistask
, 0);
8970 if((ph
->ph_MsgPort
= CreateMsgPort()))
8972 if((ph
->ph_TimerMsgPort
= CreateMsgPort()))
8974 if((ph
->ph_TimerIOReq
= (struct timerequest
*) CreateIORequest(ph
->ph_TimerMsgPort
, sizeof(struct timerequest
))))
8976 if(!(OpenDevice("timer.device", UNIT_VBLANK
, (struct IORequest
*) ph
->ph_TimerIOReq
, 0)))
8978 ph
->ph_TimerIOReq
->tr_node
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
8979 ph
->ph_TimerIOReq
->tr_node
.io_Message
.mn_Node
.ln_Name
= "EventHandler";
8980 ph
->ph_TimerIOReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
8982 ph
->ph_EventHandler
= psdAddEventHandler(ph
->ph_MsgPort
, EHMF_CONFIGCHG
);
8983 if(ph
->ph_EventHandler
)
8985 ph
->ph_Task
= thistask
;
8987 if(ph
->ph_ReadySigTask
)
8989 Signal(ph
->ph_ReadySigTask
, 1L<<ph
->ph_ReadySignal
);
8993 ph
->ph_TimerIOReq
->tr_time
.tv_micro
= 500*1000;
8994 SendIO(&ph
->ph_TimerIOReq
->tr_node
);
8995 sigmask
= (1UL<<ph
->ph_MsgPort
->mp_SigBit
)|(1UL<<ph
->ph_TimerMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
9000 if(ps
->ps_CheckConfigReq
)
9002 pCheckCfgChanged(ps
);
9004 while((pen
= (struct PsdEventNote
*) GetMsg(ph
->ph_MsgPort
)))
9006 switch(pen
->pen_Event
)
9008 case EHMB_CONFIGCHG
:
9011 cfgchanged
= counter
;
9016 ReplyMsg(&pen
->pen_Msg
);
9018 if(CheckIO(&ph
->ph_TimerIOReq
->tr_node
))
9021 WaitIO(&ph
->ph_TimerIOReq
->tr_node
);
9022 ph
->ph_TimerIOReq
->tr_time
.tv_micro
= 500*1000;
9023 SendIO(&ph
->ph_TimerIOReq
->tr_node
);
9025 startpopo
= !((counter
& 3) || ps
->ps_PoPo
.po_Task
);
9026 if((ps
->ps_GlobalCfg
->pgc_PopupDeviceNew
== PGCP_NEVER
) &&
9027 (!ps
->ps_GlobalCfg
->pgc_PopupDeviceDeath
) &&
9028 (!ps
->ps_GlobalCfg
->pgc_PopupDeviceGone
))
9030 startpopo
= FALSE
; // no need to start popo, no windows wanted
9034 struct PsdPoPo
*po
= &ps
->ps_PoPo
;
9036 po
->po_ReadySignal
= SIGB_SINGLE
;
9037 po
->po_ReadySigTask
= FindTask(NULL
);
9038 SetSignal(0, SIGF_SINGLE
); // clear single bit
9039 if(psdSpawnSubTask("PoPo (Poseidon Popups)", pPoPoGUITask
, ps
))
9041 Wait(1UL<<po
->po_ReadySignal
);
9043 po
->po_ReadySigTask
= NULL
;
9044 //FreeSignal(po->po_ReadySignal);
9047 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "PoPo kicks ass.");
9050 if((cfgchanged
+ 2) == counter
)
9052 KPRINTF(10, ("Sending information about config changed to all classes.\n"));
9053 /* Inform all classes */
9055 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
9056 while(puc
->puc_Node
.ln_Succ
)
9058 usbDoMethod(UCM_ConfigChangedEvent
);
9059 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
9064 // power saving stuff, check every second
9065 if((counter
& 1) && ps
->ps_GlobalCfg
->pgc_PowerSaving
)
9067 struct PsdDevice
*pd
= NULL
;
9068 struct PsdInterface
*pif
;
9069 GetSysTime((APTR
) &currtime
);
9070 while((pd
= psdGetNextDevice(pd
)))
9072 if((pd
->pd_DevClass
!= HUB_CLASSCODE
) &&
9073 ((pd
->pd_Flags
& (PDFF_CONFIGURED
|PDFF_DEAD
|PDFF_SUSPENDED
|PDFF_APPBINDING
|PDFF_DELEXPUNGE
)) == PDFF_CONFIGURED
))
9075 if(pd
->pd_LastActivity
.tv_secs
&& ((currtime
.tv_secs
- pd
->pd_LastActivity
.tv_secs
) > ps
->ps_GlobalCfg
->pgc_SuspendTimeout
))
9079 if(!((pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
) && ps
->ps_GlobalCfg
->pgc_ForceSuspend
))
9081 if(pd
->pd_DevBinding
&& ((puc
= pd
->pd_ClsBinding
)))
9084 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
9090 pif
= (struct PsdInterface
*) pd
->pd_CurrentConfig
->pc_Interfaces
.lh_Head
;
9091 while(pif
->pif_Node
.ln_Succ
)
9093 if(pif
->pif_IfBinding
&& ((puc
= pif
->pif_ClsBinding
)))
9096 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
9103 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
9108 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Suspending '%s'.", pd
->pd_ProductStr
);
9109 psdSuspendDevice(pd
);
9111 pd
->pd_LastActivity
.tv_secs
= 0;
9117 sigs
= Wait(sigmask
);
9118 } while(!(sigs
& SIGBREAKF_CTRL_C
));
9119 psdRemEventHandler(ph
->ph_EventHandler
);
9120 ph
->ph_EventHandler
= NULL
;
9121 AbortIO(&ph
->ph_TimerIOReq
->tr_node
);
9122 WaitIO(&ph
->ph_TimerIOReq
->tr_node
);
9124 CloseDevice((struct IORequest
*) ph
->ph_TimerIOReq
);
9126 DeleteIORequest((struct IORequest
*) ph
->ph_TimerIOReq
);
9128 DeleteMsgPort(ph
->ph_TimerMsgPort
);
9130 DeleteMsgPort(ph
->ph_MsgPort
);
9131 ph
->ph_MsgPort
= NULL
;
9135 if(ph
->ph_ReadySigTask
)
9137 Signal(ph
->ph_ReadySigTask
, 1L<<ph
->ph_ReadySignal
);
9143 /*****************************************************************/
9145 /* /// "Packtables for psdGetAttrs() and psdSetAttrs() " */
9146 /* Pack table for PsdBase */
9147 static const ULONG PsdBasePT
[] =
9149 PACK_STARTTABLE(PA_Dummy
),
9150 PACK_ENTRY(PA_Dummy
, PA_ConfigRead
, PsdBase
, ps_ConfigRead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9151 PACK_ENTRY(PA_Dummy
, PA_GlobalConfig
, PsdBase
, ps_GlobalCfg
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9152 PACK_ENTRY(PA_Dummy
, PA_MemPoolUsage
, PsdBase
, ps_MemAllocated
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9153 PACK_ENTRY(PA_Dummy
, PA_CurrConfigHash
, PsdBase
, ps_ConfigHash
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9154 PACK_ENTRY(PA_Dummy
, PA_SavedConfigHash
, PsdBase
, ps_SavedConfigHash
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9155 PACK_ENTRY(PA_Dummy
, PA_ReleaseVersion
, PsdBase
, ps_ReleaseVersion
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9156 PACK_ENTRY(PA_Dummy
, PA_OSVersion
, PsdBase
, ps_OSVersion
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9160 /* Pack table for PsdErrorMsg */
9161 static const ULONG PsdErrorMsgPT
[] =
9163 PACK_STARTTABLE(EMA_Dummy
),
9164 PACK_ENTRY(EMA_Dummy
, EMA_Level
, PsdErrorMsg
, pem_Level
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9165 PACK_ENTRY(EMA_Dummy
, EMA_Origin
, PsdErrorMsg
, pem_Origin
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9166 PACK_ENTRY(EMA_Dummy
, EMA_Msg
, PsdErrorMsg
, pem_Msg
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9170 /* Pack table for PsdUsbClass */
9171 static const ULONG PsdUsbClassPT
[] =
9173 PACK_STARTTABLE(UCA_Dummy
),
9174 PACK_ENTRY(UCA_Dummy
, UCA_ClassBase
, PsdUsbClass
, puc_ClassBase
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9175 PACK_ENTRY(UCA_Dummy
, UCA_ClassName
, PsdUsbClass
, puc_ClassName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9176 PACK_ENTRY(UCA_Dummy
, UCA_FullPath
, PsdUsbClass
, puc_FullPath
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9177 PACK_ENTRY(UCA_Dummy
, UCA_UseCount
, PsdUsbClass
, puc_UseCnt
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9181 /* Pack table for PsdHardware */
9182 static const ULONG PsdHardwarePT
[] =
9184 PACK_STARTTABLE(HA_Dummy
),
9185 PACK_ENTRY(HA_Dummy
, HA_DeviceName
, PsdHardware
, phw_DevName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9186 PACK_ENTRY(HA_Dummy
, HA_DeviceUnit
, PsdHardware
, phw_Unit
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9187 PACK_ENTRY(HA_Dummy
, HA_ProductName
, PsdHardware
, phw_ProductName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9188 PACK_ENTRY(HA_Dummy
, HA_Manufacturer
, PsdHardware
, phw_Manufacturer
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9189 PACK_ENTRY(HA_Dummy
, HA_Description
, PsdHardware
, phw_Description
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9190 PACK_ENTRY(HA_Dummy
, HA_Copyright
, PsdHardware
, phw_Copyright
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9191 PACK_ENTRY(HA_Dummy
, HA_Version
, PsdHardware
, phw_Version
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9192 PACK_ENTRY(HA_Dummy
, HA_Revision
, PsdHardware
, phw_Revision
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9193 PACK_ENTRY(HA_Dummy
, HA_DriverVersion
, PsdHardware
, phw_DriverVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9197 /* Pack table for PsdDevice */
9198 static const ULONG PsdDevicePT
[] =
9200 PACK_STARTTABLE(DA_Dummy
),
9201 PACK_ENTRY(DA_Dummy
, DA_Address
, PsdDevice
, pd_DevAddr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9202 PACK_ENTRY(DA_Dummy
, DA_NumConfigs
, PsdDevice
, pd_NumCfgs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9203 PACK_ENTRY(DA_Dummy
, DA_CurrConfig
, PsdDevice
, pd_CurrCfg
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9204 PACK_ENTRY(DA_Dummy
, DA_Config
, PsdDevice
, pd_CurrentConfig
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9205 PACK_ENTRY(DA_Dummy
, DA_HubDevice
, PsdDevice
, pd_Hub
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9206 PACK_ENTRY(DA_Dummy
, DA_UsbVersion
, PsdDevice
, pd_USBVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9207 PACK_ENTRY(DA_Dummy
, DA_Class
, PsdDevice
, pd_DevClass
, PKCTRL_WORD
|PKCTRL_UNPACKONLY
),
9208 PACK_ENTRY(DA_Dummy
, DA_SubClass
, PsdDevice
, pd_DevSubClass
, PKCTRL_WORD
|PKCTRL_UNPACKONLY
),
9209 PACK_ENTRY(DA_Dummy
, DA_Protocol
, PsdDevice
, pd_DevProto
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9210 PACK_ENTRY(DA_Dummy
, DA_VendorID
, PsdDevice
, pd_VendorID
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9211 PACK_ENTRY(DA_Dummy
, DA_MaxPktSize0
, PsdDevice
, pd_MaxPktSize0
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9212 PACK_ENTRY(DA_Dummy
, DA_ProductID
, PsdDevice
, pd_ProductID
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9213 PACK_ENTRY(DA_Dummy
, DA_Version
, PsdDevice
, pd_DevVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9214 PACK_ENTRY(DA_Dummy
, DA_Manufacturer
, PsdDevice
, pd_MnfctrStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9215 PACK_ENTRY(DA_Dummy
, DA_ProductName
, PsdDevice
, pd_ProductStr
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9216 PACK_ENTRY(DA_Dummy
, DA_OrigProductName
, PsdDevice
, pd_OldProductStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9217 PACK_ENTRY(DA_Dummy
, DA_SerialNumber
, PsdDevice
, pd_SerNumStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9218 PACK_ENTRY(DA_Dummy
, DA_Hardware
, PsdDevice
, pd_Hardware
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9219 PACK_ENTRY(DA_Dummy
, DA_Binding
, PsdDevice
, pd_DevBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9220 PACK_ENTRY(DA_Dummy
, DA_BindingClass
, PsdDevice
, pd_ClsBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9221 PACK_ENTRY(DA_Dummy
, DA_LangIDArray
, PsdDevice
, pd_LangIDArray
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9222 PACK_ENTRY(DA_Dummy
, DA_CurrLangID
, PsdDevice
, pd_CurrLangID
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9223 PACK_ENTRY(DA_Dummy
, DA_IDString
, PsdDevice
, pd_IDString
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9224 PACK_ENTRY(DA_Dummy
, DA_CloneCount
, PsdDevice
, pd_CloneCount
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9225 PACK_ENTRY(DA_Dummy
, DA_AtHubPortNumber
, PsdDevice
, pd_HubPort
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9226 PACK_ENTRY(DA_Dummy
, DA_PowerDrained
, PsdDevice
, pd_PowerDrain
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9227 PACK_ENTRY(DA_Dummy
, DA_PowerSupply
, PsdDevice
, pd_PowerSupply
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9228 PACK_ENTRY(DA_Dummy
, DA_IsNewToMe
, PsdDevice
, pd_IsNewToMe
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9229 PACK_ENTRY(DA_Dummy
, DA_InhibitPopup
, PsdDevice
, pd_PoPoCfg
.poc_InhibitPopup
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9230 PACK_ENTRY(DA_Dummy
, DA_InhibitClassBind
, PsdDevice
, pd_PoPoCfg
.poc_NoClassBind
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9231 PACK_ENTRY(DA_Dummy
, DA_OverridePowerInfo
, PsdDevice
, pd_PoPoCfg
.poc_OverridePowerInfo
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9232 PACK_ENTRY(DA_Dummy
, DA_HubThinkTime
, PsdDevice
, pd_HubThinkTime
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9233 PACK_WORDBIT(DA_Dummy
, DA_IsLowspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_LOWSPEED
),
9234 PACK_WORDBIT(DA_Dummy
, DA_IsHighspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HIGHSPEED
),
9235 PACK_WORDBIT(DA_Dummy
, DA_IsConnected
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_CONNECTED
),
9236 PACK_WORDBIT(DA_Dummy
, DA_HasAddress
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HASDEVADDR
),
9237 PACK_WORDBIT(DA_Dummy
, DA_HasDevDesc
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HASDEVDESC
),
9238 PACK_WORDBIT(DA_Dummy
, DA_IsConfigured
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_CONFIGURED
),
9239 PACK_WORDBIT(DA_Dummy
, DA_IsDead
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_DEAD
),
9240 PACK_WORDBIT(DA_Dummy
, DA_IsSuspended
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_SUSPENDED
),
9241 PACK_WORDBIT(DA_Dummy
, DA_HasAppBinding
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_APPBINDING
),
9242 PACK_WORDBIT(DA_Dummy
, DA_NeedsSplitTrans
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_NEEDSSPLIT
),
9243 PACK_WORDBIT(DA_Dummy
, DA_LowPower
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_LOWPOWER
),
9244 #ifdef AROS_USB30_CODE
9245 PACK_WORDBIT(DA_Dummy
, DA_IsSuperspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_SUPERSPEED
),
9250 /* Pack table for PsdConfig */
9251 static const ULONG PsdConfigPT
[] =
9253 PACK_STARTTABLE(CA_Dummy
),
9254 PACK_ENTRY(CA_Dummy
, CA_ConfigNum
, PsdConfig
, pc_CfgNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9255 PACK_ENTRY(CA_Dummy
, CA_MaxPower
, PsdConfig
, pc_MaxPower
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9256 PACK_ENTRY(CA_Dummy
, CA_ConfigName
, PsdConfig
, pc_CfgStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9257 PACK_ENTRY(CA_Dummy
, CA_NumInterfaces
, PsdConfig
, pc_NumIfs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9258 PACK_ENTRY(CA_Dummy
, CA_Attrs
, PsdConfig
, pc_Attr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9259 PACK_ENTRY(CA_Dummy
, CA_Device
, PsdConfig
, pc_Device
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9260 PACK_WORDBIT(CA_Dummy
, CA_SelfPowered
, PsdConfig
, pc_Attr
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, USCAF_SELF_POWERED
),
9261 PACK_WORDBIT(CA_Dummy
, CA_RemoteWakeup
, PsdConfig
, pc_Attr
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, USCAF_REMOTE_WAKEUP
),
9265 /* Pack table for PsdDescriptor */
9266 static const ULONG PsdDescriptorPT
[] =
9268 PACK_STARTTABLE(DDA_Dummy
),
9269 PACK_ENTRY(DDA_Dummy
, DDA_Device
, PsdDescriptor
, pdd_Device
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9270 PACK_ENTRY(DDA_Dummy
, DDA_Config
, PsdDescriptor
, pdd_Config
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9271 PACK_ENTRY(DDA_Dummy
, DDA_Interface
, PsdDescriptor
, pdd_Interface
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9272 PACK_ENTRY(DDA_Dummy
, DDA_Endpoint
, PsdDescriptor
, pdd_Endpoint
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9273 PACK_ENTRY(DDA_Dummy
, DDA_Name
, PsdDescriptor
, pdd_Name
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9274 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorType
, PsdDescriptor
, pdd_Type
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9275 PACK_ENTRY(DDA_Dummy
, DDA_CS_SubType
, PsdDescriptor
, pdd_CSSubType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9276 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorData
, PsdDescriptor
, pdd_Data
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9277 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorLength
, PsdDescriptor
, pdd_Length
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9281 /* Pack table for PsdInterface */
9282 static const ULONG PsdInterfacePT
[] =
9284 PACK_STARTTABLE(IFA_Dummy
),
9285 PACK_ENTRY(IFA_Dummy
, IFA_InterfaceNum
, PsdInterface
, pif_IfNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9286 PACK_ENTRY(IFA_Dummy
, IFA_AlternateNum
, PsdInterface
, pif_Alternate
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9287 PACK_ENTRY(IFA_Dummy
, IFA_NumEndpoints
, PsdInterface
, pif_NumEPs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9288 PACK_ENTRY(IFA_Dummy
, IFA_Class
, PsdInterface
, pif_IfClass
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9289 PACK_ENTRY(IFA_Dummy
, IFA_SubClass
, PsdInterface
, pif_IfSubClass
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9290 PACK_ENTRY(IFA_Dummy
, IFA_Protocol
, PsdInterface
, pif_IfProto
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9291 PACK_ENTRY(IFA_Dummy
, IFA_InterfaceName
, PsdInterface
, pif_IfStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9292 PACK_ENTRY(IFA_Dummy
, IFA_Config
, PsdInterface
, pif_Config
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9293 PACK_ENTRY(IFA_Dummy
, IFA_Binding
, PsdInterface
, pif_IfBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9294 PACK_ENTRY(IFA_Dummy
, IFA_BindingClass
, PsdInterface
, pif_ClsBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9295 PACK_ENTRY(IFA_Dummy
, IFA_IDString
, PsdInterface
, pif_IDString
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9299 /* Pack table for PsdEndpoint */
9300 static const ULONG PsdEndpointPT
[] =
9302 PACK_STARTTABLE(EA_Dummy
),
9303 PACK_ENTRY(EA_Dummy
, EA_EndpointNum
, PsdEndpoint
, pep_EPNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9304 PACK_ENTRY(EA_Dummy
, EA_TransferType
, PsdEndpoint
, pep_TransType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9305 PACK_ENTRY(EA_Dummy
, EA_MaxPktSize
, PsdEndpoint
, pep_MaxPktSize
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9306 PACK_ENTRY(EA_Dummy
, EA_Interval
, PsdEndpoint
, pep_Interval
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9307 PACK_ENTRY(EA_Dummy
, EA_NumTransMuFrame
, PsdEndpoint
, pep_NumTransMuFr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9308 PACK_ENTRY(EA_Dummy
, EA_SyncType
, PsdEndpoint
, pep_SyncType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9309 PACK_ENTRY(EA_Dummy
, EA_UsageType
, PsdEndpoint
, pep_UsageType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9310 PACK_ENTRY(EA_Dummy
, EA_Interface
, PsdEndpoint
, pep_Interface
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9311 PACK_WORDBIT(EA_Dummy
, EA_IsIn
, PsdEndpoint
, pep_Direction
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, 1),
9315 /* Pack table for PsdPipe */
9316 static const ULONG PsdPipePT
[] =
9318 PACK_STARTTABLE(PPA_Dummy
),
9319 PACK_ENTRY(PPA_Dummy
, PPA_Endpoint
, PsdPipe
, pp_Endpoint
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9320 PACK_ENTRY(PPA_Dummy
, PPA_Error
, PsdPipe
, pp_IOReq
.iouh_Req
.io_Error
, PKCTRL_BYTE
|PKCTRL_UNPACKONLY
),
9321 PACK_ENTRY(PPA_Dummy
, PPA_Actual
, PsdPipe
, pp_IOReq
.iouh_Actual
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9322 PACK_ENTRY(PPA_Dummy
, PPA_EndpointNum
, PsdPipe
, pp_IOReq
.iouh_Endpoint
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9323 PACK_ENTRY(PPA_Dummy
, PPA_DeviceAddress
, PsdPipe
, pp_IOReq
.iouh_DevAddr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9324 PACK_ENTRY(PPA_Dummy
, PPA_MaxPktSize
, PsdPipe
, pp_IOReq
.iouh_MaxPktSize
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9325 PACK_ENTRY(PPA_Dummy
, PPA_NakTimeoutTime
, PsdPipe
, pp_IOReq
.iouh_NakTimeout
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9326 PACK_ENTRY(PPA_Dummy
, PPA_Interval
, PsdPipe
, pp_IOReq
.iouh_Interval
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9327 PACK_WORDBIT(PPA_Dummy
, PPA_NoShortPackets
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_NOSHORTPKT
),
9328 PACK_WORDBIT(PPA_Dummy
, PPA_NakTimeout
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_NAKTIMEOUT
),
9329 PACK_WORDBIT(PPA_Dummy
, PPA_AllowRuntPackets
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_ALLOWRUNTPKTS
),
9333 /* Pack table for PsdAppBinding */
9334 static const ULONG PsdAppBindingPT
[] =
9336 PACK_STARTTABLE(ABA_Dummy
),
9337 PACK_ENTRY(ABA_Dummy
, ABA_ReleaseHook
, PsdAppBinding
, pab_ReleaseHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9338 PACK_ENTRY(ABA_Dummy
, ABA_Device
, PsdAppBinding
, pab_Device
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9339 PACK_ENTRY(ABA_Dummy
, ABA_UserData
, PsdAppBinding
, pab_UserData
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9340 PACK_ENTRY(ABA_Dummy
, ABA_Task
, PsdAppBinding
, pab_Task
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9341 PACK_ENTRY(ABA_Dummy
, ABA_ForceRelease
, PsdAppBinding
, pab_ForceRelease
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9345 /* Pack table for PsdAppBinding */
9346 static const ULONG PsdEventNotePT
[] =
9348 PACK_STARTTABLE(ENA_Dummy
),
9349 PACK_ENTRY(ENA_Dummy
, ENA_EventID
, PsdEventNote
, pen_Event
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9350 PACK_ENTRY(ENA_Dummy
, ENA_Param1
, PsdEventNote
, pen_Param1
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9351 PACK_ENTRY(ENA_Dummy
, ENA_Param2
, PsdEventNote
, pen_Param2
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9355 /* Pack table for PsdGlobalCfg */
9356 static const ULONG PsdGlobalCfgPT
[] =
9358 PACK_STARTTABLE(GCA_Dummy
),
9359 PACK_ENTRY(GCA_Dummy
, GCA_LogInfo
, PsdGlobalCfg
, pgc_LogInfo
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9360 PACK_ENTRY(GCA_Dummy
, GCA_LogWarning
, PsdGlobalCfg
, pgc_LogWarning
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9361 PACK_ENTRY(GCA_Dummy
, GCA_LogError
, PsdGlobalCfg
, pgc_LogError
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9362 PACK_ENTRY(GCA_Dummy
, GCA_LogFailure
, PsdGlobalCfg
, pgc_LogFailure
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9363 PACK_ENTRY(GCA_Dummy
, GCA_BootDelay
, PsdGlobalCfg
, pgc_BootDelay
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9364 PACK_ENTRY(GCA_Dummy
, GCA_SubTaskPri
, PsdGlobalCfg
, pgc_SubTaskPri
, PKCTRL_WORD
|PKCTRL_PACKUNPACK
),
9365 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceNew
, PsdGlobalCfg
, pgc_PopupDeviceNew
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9366 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceGone
, PsdGlobalCfg
, pgc_PopupDeviceGone
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9367 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceDeath
, PsdGlobalCfg
, pgc_PopupDeviceDeath
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9368 PACK_ENTRY(GCA_Dummy
, GCA_PopupCloseDelay
, PsdGlobalCfg
, pgc_PopupCloseDelay
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9369 PACK_ENTRY(GCA_Dummy
, GCA_PopupActivateWin
, PsdGlobalCfg
, pgc_PopupActivateWin
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9370 PACK_ENTRY(GCA_Dummy
, GCA_PopupWinToFront
, PsdGlobalCfg
, pgc_PopupWinToFront
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9371 PACK_ENTRY(GCA_Dummy
, GCA_AutoDisableLP
, PsdGlobalCfg
, pgc_AutoDisableLP
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9372 PACK_ENTRY(GCA_Dummy
, GCA_AutoDisableDead
, PsdGlobalCfg
, pgc_AutoDisableDead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9373 PACK_ENTRY(GCA_Dummy
, GCA_AutoRestartDead
, PsdGlobalCfg
, pgc_AutoRestartDead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9374 PACK_ENTRY(GCA_Dummy
, GCA_PowerSaving
, PsdGlobalCfg
, pgc_PowerSaving
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9375 PACK_ENTRY(GCA_Dummy
, GCA_ForceSuspend
, PsdGlobalCfg
, pgc_ForceSuspend
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9376 PACK_ENTRY(GCA_Dummy
, GCA_SuspendTimeout
, PsdGlobalCfg
, pgc_SuspendTimeout
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9377 PACK_ENTRY(GCA_Dummy
, GCA_PrefsVersion
, PsdGlobalCfg
, pgc_PrefsVersion
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9381 /* Pack table for PsdPipeStream */
9382 static const ULONG PsdPipeStreamPT
[] =
9384 PACK_STARTTABLE(PSA_Dummy
),
9385 PACK_ENTRY(PSA_Dummy
, PSA_MessagePort
, PsdPipeStream
, pps_MsgPort
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9386 PACK_ENTRY(PSA_Dummy
, PSA_NumPipes
, PsdPipeStream
, pps_NumPipes
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9387 PACK_ENTRY(PSA_Dummy
, PSA_BufferSize
, PsdPipeStream
, pps_BufferSize
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9388 PACK_ENTRY(PSA_Dummy
, PSA_NakTimeoutTime
, PsdPipeStream
, pps_NakTimeoutTime
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9389 PACK_ENTRY(PSA_Dummy
, PSA_BytesPending
, PsdPipeStream
, pps_BytesPending
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9390 PACK_ENTRY(PSA_Dummy
, PSA_Error
, PsdPipeStream
, pps_Error
, PKCTRL_LONG
|PKCTRL_PACKUNPACK
),
9391 PACK_ENTRY(PSA_Dummy
, PSA_TermArray
, PsdPipeStream
, pps_TermArray
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9392 PACK_ENTRY(PSA_Dummy
, PSA_AbortSigMask
, PsdPipeStream
, pps_AbortSigMask
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9393 PACK_ENTRY(PSA_Dummy
, PSA_ActivePipe
, PsdPipeStream
, pps_ActivePipe
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9394 PACK_WORDBIT(PSA_Dummy
, PSA_AsyncIO
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_ASYNCIO
),
9395 PACK_WORDBIT(PSA_Dummy
, PSA_ShortPktTerm
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_SHORTTERM
),
9396 PACK_WORDBIT(PSA_Dummy
, PSA_ReadAhead
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_READAHEAD
),
9397 PACK_WORDBIT(PSA_Dummy
, PSA_BufferedRead
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_BUFFERREAD
),
9398 PACK_WORDBIT(PSA_Dummy
, PSA_BufferedWrite
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_BUFFERWRITE
),
9399 PACK_WORDBIT(PSA_Dummy
, PSA_NoZeroPktTerm
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_NOSHORTPKT
),
9400 PACK_WORDBIT(PSA_Dummy
, PSA_NakTimeout
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_NAKTIMEOUT
),
9401 PACK_WORDBIT(PSA_Dummy
, PSA_AllowRuntPackets
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_ALLOWRUNT
),
9402 PACK_WORDBIT(PSA_Dummy
, PSA_DoNotWait
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_DONOTWAIT
),
9406 /* Pack table for PsdRTIsoHandler */
9407 static const ULONG PsdRTIsoHandlerPT
[] =
9409 PACK_STARTTABLE(RTA_Dummy
),
9410 PACK_ENTRY(RTA_Dummy
, RTA_InRequestHook
, PsdRTIsoHandler
, prt_RTIso
.urti_InReqHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9411 PACK_ENTRY(RTA_Dummy
, RTA_OutRequestHook
, PsdRTIsoHandler
, prt_RTIso
.urti_OutReqHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9412 PACK_ENTRY(RTA_Dummy
, RTA_InDoneHook
, PsdRTIsoHandler
, prt_RTIso
.urti_InDoneHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9413 PACK_ENTRY(RTA_Dummy
, RTA_OutDoneHook
, PsdRTIsoHandler
, prt_RTIso
.urti_OutDoneHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9414 PACK_ENTRY(RTA_Dummy
, RTA_ReleaseHook
, PsdRTIsoHandler
, prt_ReleaseHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9415 PACK_ENTRY(RTA_Dummy
, RTA_OutPrefetchSize
, PsdRTIsoHandler
, prt_RTIso
.urti_OutPrefetch
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9419 /* PGA assignment table */
9420 static const ULONG
*PsdPTArray
[] =